diff options
author | Karen Higgins <karen.higgins@qlogic.com> | 2011-03-21 06:34:29 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-03-23 13:53:01 -0400 |
commit | 7eece5a084264c1bff908b0d6a1b176b39dd272f (patch) | |
tree | 953d4a0bc0ec43f5b91b53ea43e60cc32d38f4dd | |
parent | 58da51dcfc13b2222ce8565e308852aef001f5d2 (diff) |
[SCSI] qla4xxx: Prevent other port reinitialization during remove_adapter
remove ha flag AF_HBA_GOING_AWAY and added flag AF_HA_REMOVAL
to mark the other ISP-4xxx port to indicate that the driver is
being removed, so that the other port will not re-initialize
while in the process of removing the ha due to driver unload
or hba hotplug.
Signed-off-by: Karen Higgins <karen.higgins@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 5 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_mbx.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 53 |
4 files changed, 46 insertions, 16 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 7aa60ee485e1..c1f8d1b150f7 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -53,6 +53,9 @@ | |||
53 | #define PCI_DEVICE_ID_QLOGIC_ISP8022 0x8022 | 53 | #define PCI_DEVICE_ID_QLOGIC_ISP8022 0x8022 |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | #define ISP4XXX_PCI_FN_1 0x1 | ||
57 | #define ISP4XXX_PCI_FN_2 0x3 | ||
58 | |||
56 | #define QLA_SUCCESS 0 | 59 | #define QLA_SUCCESS 0 |
57 | #define QLA_ERROR 1 | 60 | #define QLA_ERROR 1 |
58 | 61 | ||
@@ -371,7 +374,7 @@ struct scsi_qla_host { | |||
371 | #define AF_LINK_UP 8 /* 0x00000100 */ | 374 | #define AF_LINK_UP 8 /* 0x00000100 */ |
372 | #define AF_IRQ_ATTACHED 10 /* 0x00000400 */ | 375 | #define AF_IRQ_ATTACHED 10 /* 0x00000400 */ |
373 | #define AF_DISABLE_ACB_COMPLETE 11 /* 0x00000800 */ | 376 | #define AF_DISABLE_ACB_COMPLETE 11 /* 0x00000800 */ |
374 | #define AF_HBA_GOING_AWAY 12 /* 0x00001000 */ | 377 | #define AF_HA_REMOVAL 12 /* 0x00001000 */ |
375 | #define AF_INTx_ENABLED 15 /* 0x00008000 */ | 378 | #define AF_INTx_ENABLED 15 /* 0x00008000 */ |
376 | #define AF_MSI_ENABLED 16 /* 0x00010000 */ | 379 | #define AF_MSI_ENABLED 16 /* 0x00010000 */ |
377 | #define AF_MSIX_ENABLED 17 /* 0x00020000 */ | 380 | #define AF_MSIX_ENABLED 17 /* 0x00020000 */ |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 2ef1a986f5c0..2f40ac761cd4 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
@@ -801,7 +801,7 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id) | |||
801 | &ha->reg->ctrl_status); | 801 | &ha->reg->ctrl_status); |
802 | readl(&ha->reg->ctrl_status); | 802 | readl(&ha->reg->ctrl_status); |
803 | 803 | ||
804 | if (!test_bit(AF_HBA_GOING_AWAY, &ha->flags)) | 804 | if (!test_bit(AF_HA_REMOVAL, &ha->flags)) |
805 | set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); | 805 | set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); |
806 | 806 | ||
807 | break; | 807 | break; |
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 379df2bde9db..199fa643cdad 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
@@ -151,7 +151,7 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
151 | if (test_bit(AF_IRQ_ATTACHED, &ha->flags) && | 151 | if (test_bit(AF_IRQ_ATTACHED, &ha->flags) && |
152 | test_bit(AF_INTERRUPTS_ON, &ha->flags) && | 152 | test_bit(AF_INTERRUPTS_ON, &ha->flags) && |
153 | test_bit(AF_ONLINE, &ha->flags) && | 153 | test_bit(AF_ONLINE, &ha->flags) && |
154 | !test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { | 154 | !test_bit(AF_HA_REMOVAL, &ha->flags)) { |
155 | /* Do not poll for completion. Use completion queue */ | 155 | /* Do not poll for completion. Use completion queue */ |
156 | set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags); | 156 | set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags); |
157 | wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ); | 157 | wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ); |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 1d5c6fbbfaae..f80b702730ad 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -749,12 +749,6 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
749 | if (!pci_channel_offline(ha->pdev)) | 749 | if (!pci_channel_offline(ha->pdev)) |
750 | pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); | 750 | pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); |
751 | 751 | ||
752 | if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { | ||
753 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s exited. HBA GOING AWAY\n", | ||
754 | __func__)); | ||
755 | return; | ||
756 | } | ||
757 | |||
758 | if (is_qla8022(ha)) { | 752 | if (is_qla8022(ha)) { |
759 | qla4_8xxx_watchdog(ha); | 753 | qla4_8xxx_watchdog(ha); |
760 | } | 754 | } |
@@ -1063,7 +1057,6 @@ void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha) | |||
1063 | 1057 | ||
1064 | /* Disable the board */ | 1058 | /* Disable the board */ |
1065 | ql4_printk(KERN_INFO, ha, "Disabling the board\n"); | 1059 | ql4_printk(KERN_INFO, ha, "Disabling the board\n"); |
1066 | set_bit(AF_HBA_GOING_AWAY, &ha->flags); | ||
1067 | 1060 | ||
1068 | qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); | 1061 | qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); |
1069 | qla4xxx_mark_all_devices_missing(ha); | 1062 | qla4xxx_mark_all_devices_missing(ha); |
@@ -1255,11 +1248,6 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1255 | goto do_dpc_exit; | 1248 | goto do_dpc_exit; |
1256 | } | 1249 | } |
1257 | 1250 | ||
1258 | /* HBA is in the process of being permanently disabled. | ||
1259 | * Don't process anything */ | ||
1260 | if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) | ||
1261 | return; | ||
1262 | |||
1263 | if (is_qla8022(ha)) { | 1251 | if (is_qla8022(ha)) { |
1264 | if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) { | 1252 | if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) { |
1265 | qla4_8xxx_idc_lock(ha); | 1253 | qla4_8xxx_idc_lock(ha); |
@@ -1824,6 +1812,44 @@ probe_disable_device: | |||
1824 | } | 1812 | } |
1825 | 1813 | ||
1826 | /** | 1814 | /** |
1815 | * qla4xxx_prevent_other_port_reinit - prevent other port from re-initialize | ||
1816 | * @ha: pointer to adapter structure | ||
1817 | * | ||
1818 | * Mark the other ISP-4xxx port to indicate that the driver is being removed, | ||
1819 | * so that the other port will not re-initialize while in the process of | ||
1820 | * removing the ha due to driver unload or hba hotplug. | ||
1821 | **/ | ||
1822 | static void qla4xxx_prevent_other_port_reinit(struct scsi_qla_host *ha) | ||
1823 | { | ||
1824 | struct scsi_qla_host *other_ha = NULL; | ||
1825 | struct pci_dev *other_pdev = NULL; | ||
1826 | int fn = ISP4XXX_PCI_FN_2; | ||
1827 | |||
1828 | /*iscsi function numbers for ISP4xxx is 1 and 3*/ | ||
1829 | if (PCI_FUNC(ha->pdev->devfn) & BIT_1) | ||
1830 | fn = ISP4XXX_PCI_FN_1; | ||
1831 | |||
1832 | other_pdev = | ||
1833 | pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus), | ||
1834 | ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn), | ||
1835 | fn)); | ||
1836 | |||
1837 | /* Get other_ha if other_pdev is valid and state is enable*/ | ||
1838 | if (other_pdev) { | ||
1839 | if (atomic_read(&other_pdev->enable_cnt)) { | ||
1840 | other_ha = pci_get_drvdata(other_pdev); | ||
1841 | if (other_ha) { | ||
1842 | set_bit(AF_HA_REMOVAL, &other_ha->flags); | ||
1843 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: " | ||
1844 | "Prevent %s reinit\n", __func__, | ||
1845 | dev_name(&other_ha->pdev->dev))); | ||
1846 | } | ||
1847 | } | ||
1848 | pci_dev_put(other_pdev); | ||
1849 | } | ||
1850 | } | ||
1851 | |||
1852 | /** | ||
1827 | * qla4xxx_remove_adapter - calback function to remove adapter. | 1853 | * qla4xxx_remove_adapter - calback function to remove adapter. |
1828 | * @pci_dev: PCI device pointer | 1854 | * @pci_dev: PCI device pointer |
1829 | **/ | 1855 | **/ |
@@ -1833,7 +1859,8 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
1833 | 1859 | ||
1834 | ha = pci_get_drvdata(pdev); | 1860 | ha = pci_get_drvdata(pdev); |
1835 | 1861 | ||
1836 | set_bit(AF_HBA_GOING_AWAY, &ha->flags); | 1862 | if (!is_qla8022(ha)) |
1863 | qla4xxx_prevent_other_port_reinit(ha); | ||
1837 | 1864 | ||
1838 | /* remove devs from iscsi_sessions to scsi_devices */ | 1865 | /* remove devs from iscsi_sessions to scsi_devices */ |
1839 | qla4xxx_free_ddb_list(ha); | 1866 | qla4xxx_free_ddb_list(ha); |