@@ -168,6 +168,32 @@ static int idxd_setup_interrupts(struct idxd_device *idxd)
168168 return rc ;
169169}
170170
171+ static void idxd_cleanup_interrupts (struct idxd_device * idxd )
172+ {
173+ struct pci_dev * pdev = idxd -> pdev ;
174+ struct idxd_irq_entry * irq_entry ;
175+ int i , msixcnt ;
176+
177+ msixcnt = pci_msix_vec_count (pdev );
178+ if (msixcnt <= 0 )
179+ return ;
180+
181+ irq_entry = & idxd -> irq_entries [0 ];
182+ free_irq (irq_entry -> vector , irq_entry );
183+
184+ for (i = 1 ; i < msixcnt ; i ++ ) {
185+
186+ irq_entry = & idxd -> irq_entries [i ];
187+ if (idxd -> hw .cmd_cap & BIT (IDXD_CMD_RELEASE_INT_HANDLE ))
188+ idxd_device_release_int_handle (idxd , idxd -> int_handles [i ],
189+ IDXD_IRQ_MSIX );
190+ free_irq (irq_entry -> vector , irq_entry );
191+ }
192+
193+ idxd_mask_error_interrupts (idxd );
194+ pci_free_irq_vectors (pdev );
195+ }
196+
171197static int idxd_setup_wqs (struct idxd_device * idxd )
172198{
173199 struct device * dev = & idxd -> pdev -> dev ;
@@ -304,6 +330,19 @@ static int idxd_setup_groups(struct idxd_device *idxd)
304330 return rc ;
305331}
306332
333+ static void idxd_cleanup_internals (struct idxd_device * idxd )
334+ {
335+ int i ;
336+
337+ for (i = 0 ; i < idxd -> max_groups ; i ++ )
338+ put_device (& idxd -> groups [i ]-> conf_dev );
339+ for (i = 0 ; i < idxd -> max_engines ; i ++ )
340+ put_device (& idxd -> engines [i ]-> conf_dev );
341+ for (i = 0 ; i < idxd -> max_wqs ; i ++ )
342+ put_device (& idxd -> wqs [i ]-> conf_dev );
343+ destroy_workqueue (idxd -> wq );
344+ }
345+
307346static int idxd_setup_internals (struct idxd_device * idxd )
308347{
309348 struct device * dev = & idxd -> pdev -> dev ;
@@ -532,12 +571,12 @@ static int idxd_probe(struct idxd_device *idxd)
532571 dev_dbg (dev , "Loading RO device config\n" );
533572 rc = idxd_device_load_config (idxd );
534573 if (rc < 0 )
535- goto err ;
574+ goto err_config ;
536575 }
537576
538577 rc = idxd_setup_interrupts (idxd );
539578 if (rc )
540- goto err ;
579+ goto err_config ;
541580
542581 dev_dbg (dev , "IDXD interrupt setup complete.\n" );
543582
@@ -550,13 +589,27 @@ static int idxd_probe(struct idxd_device *idxd)
550589 dev_dbg (dev , "IDXD device %d probed successfully\n" , idxd -> id );
551590 return 0 ;
552591
592+ err_config :
593+ idxd_cleanup_internals (idxd );
553594 err :
554595 if (device_pasid_enabled (idxd ))
555596 idxd_disable_system_pasid (idxd );
556597 iommu_dev_disable_feature (dev , IOMMU_DEV_FEAT_SVA );
557598 return rc ;
558599}
559600
601+ static void idxd_cleanup (struct idxd_device * idxd )
602+ {
603+ struct device * dev = & idxd -> pdev -> dev ;
604+
605+ perfmon_pmu_remove (idxd );
606+ idxd_cleanup_interrupts (idxd );
607+ idxd_cleanup_internals (idxd );
608+ if (device_pasid_enabled (idxd ))
609+ idxd_disable_system_pasid (idxd );
610+ iommu_dev_disable_feature (dev , IOMMU_DEV_FEAT_SVA );
611+ }
612+
560613static int idxd_pci_probe (struct pci_dev * pdev , const struct pci_device_id * id )
561614{
562615 struct device * dev = & pdev -> dev ;
@@ -609,7 +662,7 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
609662 rc = idxd_register_devices (idxd );
610663 if (rc ) {
611664 dev_err (dev , "IDXD sysfs setup failed\n" );
612- goto err ;
665+ goto err_dev_register ;
613666 }
614667
615668 idxd -> state = IDXD_DEV_CONF_READY ;
@@ -619,6 +672,8 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
619672
620673 return 0 ;
621674
675+ err_dev_register :
676+ idxd_cleanup (idxd );
622677 err :
623678 pci_iounmap (pdev , idxd -> reg_base );
624679 err_iomap :
0 commit comments