aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2016-12-24 06:34:02 -0500
committerThomas Gleixner <tglx@linutronix.de>2016-12-25 04:47:18 -0500
commita98d1a0ca6d3fd6197f18749972d4cc21195b724 (patch)
tree507e4dda708730edcec87ac4f76c5e969288d8ec /drivers/scsi
parent6ac3bb167fed0b3d02b4fd3daa0d819841d5f6f4 (diff)
scsi: qedi: Convert to hotplug state machine
The CPU hotplug code is a trainwreck. It leaks a notifier in case of driver registration error and the per cpu loop is racy against cpu hotplug. Aside of that the driver should have been written and merged with the new state machine interfaces in the first place. Mop up the mess and Convert it to the hotplug state machine. Signed-off-by: Thomas Grumpy Gleixner <tglx@linutronix.de> Cc: Nilesh Javali <nilesh.javali@cavium.com> Cc: Adheer Chandravanshi <adheer.chandravanshi@qlogic.com> Cc: Chad Dupuis <chad.dupuis@cavium.com> Cc: Saurav Kashyap <saurav.kashyap@cavium.com> Cc: Arun Easi <arun.easi@cavium.com> Cc: Manish Rangankar <manish.rangankar@cavium.com> Cc: Johannes Thumshirn <jthumshirn@suse.de> Cc: Hannes Reinecke <hare@suse.de> Cc: Martin K. Petersen <martin.petersen@oracle.com> Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/qedi/qedi_main.c96
1 files changed, 32 insertions, 64 deletions
diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c
index 19ead8d17e55..5eda21d903e9 100644
--- a/drivers/scsi/qedi/qedi_main.c
+++ b/drivers/scsi/qedi/qedi_main.c
@@ -1612,30 +1612,29 @@ static int qedi_percpu_io_thread(void *arg)
1612 return 0; 1612 return 0;
1613} 1613}
1614 1614
1615static void qedi_percpu_thread_create(unsigned int cpu) 1615static int qedi_cpu_online(unsigned int cpu)
1616{ 1616{
1617 struct qedi_percpu_s *p; 1617 struct qedi_percpu_s *p = this_cpu_ptr(&qedi_percpu);
1618 struct task_struct *thread; 1618 struct task_struct *thread;
1619 1619
1620 p = &per_cpu(qedi_percpu, cpu);
1621
1622 thread = kthread_create_on_node(qedi_percpu_io_thread, (void *)p, 1620 thread = kthread_create_on_node(qedi_percpu_io_thread, (void *)p,
1623 cpu_to_node(cpu), 1621 cpu_to_node(cpu),
1624 "qedi_thread/%d", cpu); 1622 "qedi_thread/%d", cpu);
1625 if (likely(!IS_ERR(thread))) { 1623 if (IS_ERR(thread))
1626 kthread_bind(thread, cpu); 1624 return PTR_ERR(thread);
1627 p->iothread = thread; 1625
1628 wake_up_process(thread); 1626 kthread_bind(thread, cpu);
1629 } 1627 p->iothread = thread;
1628 wake_up_process(thread);
1629 return 0;
1630} 1630}
1631 1631
1632static void qedi_percpu_thread_destroy(unsigned int cpu) 1632static int qedi_cpu_offline(unsigned int cpu)
1633{ 1633{
1634 struct qedi_percpu_s *p; 1634 struct qedi_percpu_s *p = this_cpu_ptr(&qedi_percpu);
1635 struct task_struct *thread;
1636 struct qedi_work *work, *tmp; 1635 struct qedi_work *work, *tmp;
1636 struct task_struct *thread;
1637 1637
1638 p = &per_cpu(qedi_percpu, cpu);
1639 spin_lock_bh(&p->p_work_lock); 1638 spin_lock_bh(&p->p_work_lock);
1640 thread = p->iothread; 1639 thread = p->iothread;
1641 p->iothread = NULL; 1640 p->iothread = NULL;
@@ -1650,35 +1649,9 @@ static void qedi_percpu_thread_destroy(unsigned int cpu)
1650 spin_unlock_bh(&p->p_work_lock); 1649 spin_unlock_bh(&p->p_work_lock);
1651 if (thread) 1650 if (thread)
1652 kthread_stop(thread); 1651 kthread_stop(thread);
1652 return 0;
1653} 1653}
1654 1654
1655static int qedi_cpu_callback(struct notifier_block *nfb,
1656 unsigned long action, void *hcpu)
1657{
1658 unsigned int cpu = (unsigned long)hcpu;
1659
1660 switch (action) {
1661 case CPU_ONLINE:
1662 case CPU_ONLINE_FROZEN:
1663 QEDI_ERR(NULL, "CPU %d online.\n", cpu);
1664 qedi_percpu_thread_create(cpu);
1665 break;
1666 case CPU_DEAD:
1667 case CPU_DEAD_FROZEN:
1668 QEDI_ERR(NULL, "CPU %d offline.\n", cpu);
1669 qedi_percpu_thread_destroy(cpu);
1670 break;
1671 default:
1672 break;
1673 }
1674
1675 return NOTIFY_OK;
1676}
1677
1678static struct notifier_block qedi_cpu_notifier = {
1679 .notifier_call = qedi_cpu_callback,
1680};
1681
1682void qedi_reset_host_mtu(struct qedi_ctx *qedi, u16 mtu) 1655void qedi_reset_host_mtu(struct qedi_ctx *qedi, u16 mtu)
1683{ 1656{
1684 struct qed_ll2_params params; 1657 struct qed_ll2_params params;
@@ -2038,6 +2011,8 @@ static struct pci_device_id qedi_pci_tbl[] = {
2038}; 2011};
2039MODULE_DEVICE_TABLE(pci, qedi_pci_tbl); 2012MODULE_DEVICE_TABLE(pci, qedi_pci_tbl);
2040 2013
2014static enum cpuhp_state qedi_cpuhp_state;
2015
2041static struct pci_driver qedi_pci_driver = { 2016static struct pci_driver qedi_pci_driver = {
2042 .name = QEDI_MODULE_NAME, 2017 .name = QEDI_MODULE_NAME,
2043 .id_table = qedi_pci_tbl, 2018 .id_table = qedi_pci_tbl,
@@ -2047,16 +2022,13 @@ static struct pci_driver qedi_pci_driver = {
2047 2022
2048static int __init qedi_init(void) 2023static int __init qedi_init(void)
2049{ 2024{
2050 int rc = 0;
2051 int ret;
2052 struct qedi_percpu_s *p; 2025 struct qedi_percpu_s *p;
2053 unsigned int cpu = 0; 2026 int cpu, rc = 0;
2054 2027
2055 qedi_ops = qed_get_iscsi_ops(); 2028 qedi_ops = qed_get_iscsi_ops();
2056 if (!qedi_ops) { 2029 if (!qedi_ops) {
2057 QEDI_ERR(NULL, "Failed to get qed iSCSI operations\n"); 2030 QEDI_ERR(NULL, "Failed to get qed iSCSI operations\n");
2058 rc = -EINVAL; 2031 return -EINVAL;
2059 goto exit_qedi_init_0;
2060 } 2032 }
2061 2033
2062#ifdef CONFIG_DEBUG_FS 2034#ifdef CONFIG_DEBUG_FS
@@ -2070,15 +2042,6 @@ static int __init qedi_init(void)
2070 goto exit_qedi_init_1; 2042 goto exit_qedi_init_1;
2071 } 2043 }
2072 2044
2073 register_hotcpu_notifier(&qedi_cpu_notifier);
2074
2075 ret = pci_register_driver(&qedi_pci_driver);
2076 if (ret) {
2077 QEDI_ERR(NULL, "Failed to register driver\n");
2078 rc = -EINVAL;
2079 goto exit_qedi_init_2;
2080 }
2081
2082 for_each_possible_cpu(cpu) { 2045 for_each_possible_cpu(cpu) {
2083 p = &per_cpu(qedi_percpu, cpu); 2046 p = &per_cpu(qedi_percpu, cpu);
2084 INIT_LIST_HEAD(&p->work_list); 2047 INIT_LIST_HEAD(&p->work_list);
@@ -2086,11 +2049,22 @@ static int __init qedi_init(void)
2086 p->iothread = NULL; 2049 p->iothread = NULL;
2087 } 2050 }
2088 2051
2089 for_each_online_cpu(cpu) 2052 rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "scsi/qedi:online",
2090 qedi_percpu_thread_create(cpu); 2053 qedi_cpu_online, qedi_cpu_offline);
2054 if (rc < 0)
2055 goto exit_qedi_init_2;
2056 qedi_cpuhp_state = rc;
2091 2057
2092 return rc; 2058 rc = pci_register_driver(&qedi_pci_driver);
2059 if (rc) {
2060 QEDI_ERR(NULL, "Failed to register driver\n");
2061 goto exit_qedi_hp;
2062 }
2063
2064 return 0;
2093 2065
2066exit_qedi_hp:
2067 cpuhp_remove_state(qedi_cpuhp_state);
2094exit_qedi_init_2: 2068exit_qedi_init_2:
2095 iscsi_unregister_transport(&qedi_iscsi_transport); 2069 iscsi_unregister_transport(&qedi_iscsi_transport);
2096exit_qedi_init_1: 2070exit_qedi_init_1:
@@ -2098,19 +2072,13 @@ exit_qedi_init_1:
2098 qedi_dbg_exit(); 2072 qedi_dbg_exit();
2099#endif 2073#endif
2100 qed_put_iscsi_ops(); 2074 qed_put_iscsi_ops();
2101exit_qedi_init_0:
2102 return rc; 2075 return rc;
2103} 2076}
2104 2077
2105static void __exit qedi_cleanup(void) 2078static void __exit qedi_cleanup(void)
2106{ 2079{
2107 unsigned int cpu = 0;
2108
2109 for_each_online_cpu(cpu)
2110 qedi_percpu_thread_destroy(cpu);
2111
2112 pci_unregister_driver(&qedi_pci_driver); 2080 pci_unregister_driver(&qedi_pci_driver);
2113 unregister_hotcpu_notifier(&qedi_cpu_notifier); 2081 cpuhp_remove_state(qedi_cpuhp_state);
2114 iscsi_unregister_transport(&qedi_iscsi_transport); 2082 iscsi_unregister_transport(&qedi_iscsi_transport);
2115 2083
2116#ifdef CONFIG_DEBUG_FS 2084#ifdef CONFIG_DEBUG_FS