3434/**
3535 * struct mhi_pci_dev_info - MHI PCI device specific information
3636 * @config: MHI controller configuration
37+ * @vf_config: MHI controller configuration for Virtual function (optional)
3738 * @name: name of the PCI module
3839 * @fw: firmware path (if any)
3940 * @edl: emergency download mode firmware path (if any)
4041 * @edl_trigger: capable of triggering EDL mode in the device (if supported)
4142 * @bar_num: PCI base address register to use for MHI MMIO register space
4243 * @dma_data_width: DMA transfer word size (32 or 64 bits)
44+ * @vf_dma_data_width: DMA transfer word size for VF's (optional)
4345 * @mru_default: default MRU size for MBIM network packets
4446 * @sideband_wake: Devices using dedicated sideband GPIO for wakeup instead
4547 * of inband wake support (such as sdx24)
4648 * @no_m3: M3 not supported
49+ * @reset_on_remove: Set true for devices that require SoC during driver removal
4750 */
4851struct mhi_pci_dev_info {
4952 const struct mhi_controller_config * config ;
53+ const struct mhi_controller_config * vf_config ;
5054 const char * name ;
5155 const char * fw ;
5256 const char * edl ;
5357 bool edl_trigger ;
5458 unsigned int bar_num ;
5559 unsigned int dma_data_width ;
60+ unsigned int vf_dma_data_width ;
5661 unsigned int mru_default ;
5762 bool sideband_wake ;
5863 bool no_m3 ;
64+ bool reset_on_remove ;
5965};
6066
6167#define MHI_CHANNEL_CONFIG_UL (ch_num , ch_name , el_count , ev_ring ) \
@@ -296,8 +302,10 @@ static const struct mhi_pci_dev_info mhi_qcom_qdu100_info = {
296302 .config = & mhi_qcom_qdu100_config ,
297303 .bar_num = MHI_PCI_DEFAULT_BAR_NUM ,
298304 .dma_data_width = 32 ,
305+ .vf_dma_data_width = 40 ,
299306 .sideband_wake = false,
300307 .no_m3 = true,
308+ .reset_on_remove = true,
301309};
302310
303311static const struct mhi_channel_config mhi_qcom_sa8775p_channels [] = {
@@ -917,20 +925,8 @@ static const struct pci_device_id mhi_pci_id_table[] = {
917925 /* Telit FE990A */
918926 { PCI_DEVICE_SUB (PCI_VENDOR_ID_QCOM , 0x0308 , 0x1c5d , 0x2015 ),
919927 .driver_data = (kernel_ulong_t ) & mhi_telit_fe990a_info },
920- /* Foxconn T99W696.01, Lenovo Generic SKU */
921- { PCI_DEVICE_SUB (PCI_VENDOR_ID_QCOM , 0x0308 , PCI_VENDOR_ID_FOXCONN , 0xe142 ),
922- .driver_data = (kernel_ulong_t ) & mhi_foxconn_t99w696_info },
923- /* Foxconn T99W696.02, Lenovo X1 Carbon SKU */
924- { PCI_DEVICE_SUB (PCI_VENDOR_ID_QCOM , 0x0308 , PCI_VENDOR_ID_FOXCONN , 0xe143 ),
925- .driver_data = (kernel_ulong_t ) & mhi_foxconn_t99w696_info },
926- /* Foxconn T99W696.03, Lenovo X1 2in1 SKU */
927- { PCI_DEVICE_SUB (PCI_VENDOR_ID_QCOM , 0x0308 , PCI_VENDOR_ID_FOXCONN , 0xe144 ),
928- .driver_data = (kernel_ulong_t ) & mhi_foxconn_t99w696_info },
929- /* Foxconn T99W696.04, Lenovo PRC SKU */
930- { PCI_DEVICE_SUB (PCI_VENDOR_ID_QCOM , 0x0308 , PCI_VENDOR_ID_FOXCONN , 0xe145 ),
931- .driver_data = (kernel_ulong_t ) & mhi_foxconn_t99w696_info },
932- /* Foxconn T99W696.00, Foxconn SKU */
933- { PCI_DEVICE_SUB (PCI_VENDOR_ID_QCOM , 0x0308 , PCI_VENDOR_ID_FOXCONN , 0xe146 ),
928+ /* Foxconn T99W696, all variants */
929+ { PCI_DEVICE_SUB (PCI_VENDOR_ID_QCOM , 0x0308 , PCI_VENDOR_ID_FOXCONN , PCI_ANY_ID ),
934930 .driver_data = (kernel_ulong_t ) & mhi_foxconn_t99w696_info },
935931 { PCI_DEVICE (PCI_VENDOR_ID_QCOM , 0x0308 ),
936932 .driver_data = (kernel_ulong_t ) & mhi_qcom_sdx65_info },
@@ -1037,6 +1033,7 @@ struct mhi_pci_device {
10371033 struct work_struct recovery_work ;
10381034 struct timer_list health_check_timer ;
10391035 unsigned long status ;
1036+ bool reset_on_remove ;
10401037};
10411038
10421039static int mhi_pci_read_reg (struct mhi_controller * mhi_cntrl ,
@@ -1092,7 +1089,7 @@ static bool mhi_pci_is_alive(struct mhi_controller *mhi_cntrl)
10921089 struct pci_dev * pdev = to_pci_dev (mhi_cntrl -> cntrl_dev );
10931090 u16 vendor = 0 ;
10941091
1095- if (pci_read_config_word (pdev , PCI_VENDOR_ID , & vendor ))
1092+ if (pci_read_config_word (pci_physfn ( pdev ) , PCI_VENDOR_ID , & vendor ))
10961093 return false;
10971094
10981095 if (vendor == (u16 ) ~0 || vendor == 0 )
@@ -1203,7 +1200,9 @@ static void mhi_pci_recovery_work(struct work_struct *work)
12031200
12041201 dev_warn (& pdev -> dev , "device recovery started\n" );
12051202
1206- timer_delete (& mhi_pdev -> health_check_timer );
1203+ if (pdev -> is_physfn )
1204+ timer_delete (& mhi_pdev -> health_check_timer );
1205+
12071206 pm_runtime_forbid (& pdev -> dev );
12081207
12091208 /* Clean up MHI state */
@@ -1230,7 +1229,10 @@ static void mhi_pci_recovery_work(struct work_struct *work)
12301229 dev_dbg (& pdev -> dev , "Recovery completed\n" );
12311230
12321231 set_bit (MHI_PCI_DEV_STARTED , & mhi_pdev -> status );
1233- mod_timer (& mhi_pdev -> health_check_timer , jiffies + HEALTH_CHECK_PERIOD );
1232+
1233+ if (pdev -> is_physfn )
1234+ mod_timer (& mhi_pdev -> health_check_timer , jiffies + HEALTH_CHECK_PERIOD );
1235+
12341236 return ;
12351237
12361238err_unprepare :
@@ -1301,6 +1303,7 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
13011303 const struct mhi_controller_config * mhi_cntrl_config ;
13021304 struct mhi_pci_device * mhi_pdev ;
13031305 struct mhi_controller * mhi_cntrl ;
1306+ unsigned int dma_data_width ;
13041307 int err ;
13051308
13061309 dev_info (& pdev -> dev , "MHI PCI device found: %s\n" , info -> name );
@@ -1311,14 +1314,24 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
13111314 return - ENOMEM ;
13121315
13131316 INIT_WORK (& mhi_pdev -> recovery_work , mhi_pci_recovery_work );
1314- timer_setup (& mhi_pdev -> health_check_timer , health_check , 0 );
13151317
1316- mhi_cntrl_config = info -> config ;
1318+ if (pdev -> is_virtfn && info -> vf_config )
1319+ mhi_cntrl_config = info -> vf_config ;
1320+ else
1321+ mhi_cntrl_config = info -> config ;
1322+
1323+ /* Initialize health check monitor only for Physical functions */
1324+ if (pdev -> is_physfn )
1325+ timer_setup (& mhi_pdev -> health_check_timer , health_check , 0 );
1326+
13171327 mhi_cntrl = & mhi_pdev -> mhi_cntrl ;
13181328
1329+ dma_data_width = (pdev -> is_virtfn && info -> vf_dma_data_width ) ?
1330+ info -> vf_dma_data_width : info -> dma_data_width ;
1331+
13191332 mhi_cntrl -> cntrl_dev = & pdev -> dev ;
13201333 mhi_cntrl -> iova_start = 0 ;
1321- mhi_cntrl -> iova_stop = (dma_addr_t )DMA_BIT_MASK (info -> dma_data_width );
1334+ mhi_cntrl -> iova_stop = (dma_addr_t )DMA_BIT_MASK (dma_data_width );
13221335 mhi_cntrl -> fw_image = info -> fw ;
13231336 mhi_cntrl -> edl_image = info -> edl ;
13241337
@@ -1330,6 +1343,9 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
13301343 mhi_cntrl -> mru = info -> mru_default ;
13311344 mhi_cntrl -> name = info -> name ;
13321345
1346+ if (pdev -> is_physfn )
1347+ mhi_pdev -> reset_on_remove = info -> reset_on_remove ;
1348+
13331349 if (info -> edl_trigger )
13341350 mhi_cntrl -> edl_trigger = mhi_pci_generic_edl_trigger ;
13351351
@@ -1339,7 +1355,7 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
13391355 mhi_cntrl -> wake_toggle = mhi_pci_wake_toggle_nop ;
13401356 }
13411357
1342- err = mhi_pci_claim (mhi_cntrl , info -> bar_num , DMA_BIT_MASK (info -> dma_data_width ));
1358+ err = mhi_pci_claim (mhi_cntrl , info -> bar_num , DMA_BIT_MASK (dma_data_width ));
13431359 if (err )
13441360 return err ;
13451361
@@ -1376,7 +1392,8 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
13761392 set_bit (MHI_PCI_DEV_STARTED , & mhi_pdev -> status );
13771393
13781394 /* start health check */
1379- mod_timer (& mhi_pdev -> health_check_timer , jiffies + HEALTH_CHECK_PERIOD );
1395+ if (pdev -> is_physfn )
1396+ mod_timer (& mhi_pdev -> health_check_timer , jiffies + HEALTH_CHECK_PERIOD );
13801397
13811398 /* Allow runtime suspend only if both PME from D3Hot and M3 are supported */
13821399 if (pci_pme_capable (pdev , PCI_D3hot ) && !(info -> no_m3 )) {
@@ -1401,7 +1418,10 @@ static void mhi_pci_remove(struct pci_dev *pdev)
14011418 struct mhi_pci_device * mhi_pdev = pci_get_drvdata (pdev );
14021419 struct mhi_controller * mhi_cntrl = & mhi_pdev -> mhi_cntrl ;
14031420
1404- timer_delete_sync (& mhi_pdev -> health_check_timer );
1421+ pci_disable_sriov (pdev );
1422+
1423+ if (pdev -> is_physfn )
1424+ timer_delete_sync (& mhi_pdev -> health_check_timer );
14051425 cancel_work_sync (& mhi_pdev -> recovery_work );
14061426
14071427 if (test_and_clear_bit (MHI_PCI_DEV_STARTED , & mhi_pdev -> status )) {
@@ -1413,6 +1433,9 @@ static void mhi_pci_remove(struct pci_dev *pdev)
14131433 if (pci_pme_capable (pdev , PCI_D3hot ))
14141434 pm_runtime_get_noresume (& pdev -> dev );
14151435
1436+ if (mhi_pdev -> reset_on_remove )
1437+ mhi_soc_reset (mhi_cntrl );
1438+
14161439 mhi_unregister_controller (mhi_cntrl );
14171440}
14181441
@@ -1429,7 +1452,8 @@ static void mhi_pci_reset_prepare(struct pci_dev *pdev)
14291452
14301453 dev_info (& pdev -> dev , "reset\n" );
14311454
1432- timer_delete (& mhi_pdev -> health_check_timer );
1455+ if (pdev -> is_physfn )
1456+ timer_delete (& mhi_pdev -> health_check_timer );
14331457
14341458 /* Clean up MHI state */
14351459 if (test_and_clear_bit (MHI_PCI_DEV_STARTED , & mhi_pdev -> status )) {
@@ -1474,7 +1498,8 @@ static void mhi_pci_reset_done(struct pci_dev *pdev)
14741498 }
14751499
14761500 set_bit (MHI_PCI_DEV_STARTED , & mhi_pdev -> status );
1477- mod_timer (& mhi_pdev -> health_check_timer , jiffies + HEALTH_CHECK_PERIOD );
1501+ if (pdev -> is_physfn )
1502+ mod_timer (& mhi_pdev -> health_check_timer , jiffies + HEALTH_CHECK_PERIOD );
14781503}
14791504
14801505static pci_ers_result_t mhi_pci_error_detected (struct pci_dev * pdev ,
@@ -1539,7 +1564,9 @@ static int __maybe_unused mhi_pci_runtime_suspend(struct device *dev)
15391564 if (test_and_set_bit (MHI_PCI_DEV_SUSPENDED , & mhi_pdev -> status ))
15401565 return 0 ;
15411566
1542- timer_delete (& mhi_pdev -> health_check_timer );
1567+ if (pdev -> is_physfn )
1568+ timer_delete (& mhi_pdev -> health_check_timer );
1569+
15431570 cancel_work_sync (& mhi_pdev -> recovery_work );
15441571
15451572 if (!test_bit (MHI_PCI_DEV_STARTED , & mhi_pdev -> status ) ||
@@ -1590,7 +1617,8 @@ static int __maybe_unused mhi_pci_runtime_resume(struct device *dev)
15901617 }
15911618
15921619 /* Resume health check */
1593- mod_timer (& mhi_pdev -> health_check_timer , jiffies + HEALTH_CHECK_PERIOD );
1620+ if (pdev -> is_physfn )
1621+ mod_timer (& mhi_pdev -> health_check_timer , jiffies + HEALTH_CHECK_PERIOD );
15941622
15951623 /* It can be a remote wakeup (no mhi runtime_get), update access time */
15961624 pm_runtime_mark_last_busy (dev );
@@ -1676,7 +1704,8 @@ static struct pci_driver mhi_pci_driver = {
16761704 .remove = mhi_pci_remove ,
16771705 .shutdown = mhi_pci_shutdown ,
16781706 .err_handler = & mhi_pci_err_handler ,
1679- .driver .pm = & mhi_pci_pm_ops
1707+ .driver .pm = & mhi_pci_pm_ops ,
1708+ .sriov_configure = pci_sriov_configure_simple ,
16801709};
16811710module_pci_driver (mhi_pci_driver );
16821711
0 commit comments