diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 6 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ccw.c | 74 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 5 |
3 files changed, 54 insertions, 31 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index e8f39f02bc3b..d1e75d36ed1a 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -541,6 +541,9 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
541 | rwlock_init(&adapter->erp_lock); | 541 | rwlock_init(&adapter->erp_lock); |
542 | rwlock_init(&adapter->abort_lock); | 542 | rwlock_init(&adapter->abort_lock); |
543 | 543 | ||
544 | if (zfcp_erp_thread_setup(adapter)) | ||
545 | goto erp_thread_failed; | ||
546 | |||
544 | INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler); | 547 | INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler); |
545 | INIT_WORK(&adapter->scan_work, _zfcp_fc_scan_ports_later); | 548 | INIT_WORK(&adapter->scan_work, _zfcp_fc_scan_ports_later); |
546 | 549 | ||
@@ -561,6 +564,8 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
561 | return 0; | 564 | return 0; |
562 | 565 | ||
563 | sysfs_failed: | 566 | sysfs_failed: |
567 | zfcp_erp_thread_kill(adapter); | ||
568 | erp_thread_failed: | ||
564 | zfcp_fc_gs_destroy(adapter); | 569 | zfcp_fc_gs_destroy(adapter); |
565 | generic_services_failed: | 570 | generic_services_failed: |
566 | zfcp_destroy_adapter_work_queue(adapter); | 571 | zfcp_destroy_adapter_work_queue(adapter); |
@@ -602,6 +607,7 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter) | |||
602 | return; | 607 | return; |
603 | 608 | ||
604 | zfcp_fc_gs_destroy(adapter); | 609 | zfcp_fc_gs_destroy(adapter); |
610 | zfcp_erp_thread_kill(adapter); | ||
605 | zfcp_destroy_adapter_work_queue(adapter); | 611 | zfcp_destroy_adapter_work_queue(adapter); |
606 | zfcp_dbf_adapter_unregister(adapter->dbf); | 612 | zfcp_dbf_adapter_unregister(adapter->dbf); |
607 | zfcp_free_low_mem_buffers(adapter); | 613 | zfcp_free_low_mem_buffers(adapter); |
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index d9da5c42ccbe..82ae6ed7ef83 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -18,6 +18,9 @@ static int zfcp_ccw_suspend(struct ccw_device *cdev) | |||
18 | { | 18 | { |
19 | struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev); | 19 | struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev); |
20 | 20 | ||
21 | if (!adapter) | ||
22 | return 0; | ||
23 | |||
21 | down(&zfcp_data.config_sema); | 24 | down(&zfcp_data.config_sema); |
22 | 25 | ||
23 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsusp1", NULL); | 26 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsusp1", NULL); |
@@ -33,6 +36,9 @@ static int zfcp_ccw_activate(struct ccw_device *cdev) | |||
33 | { | 36 | { |
34 | struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev); | 37 | struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev); |
35 | 38 | ||
39 | if (!adapter) | ||
40 | return 0; | ||
41 | |||
36 | zfcp_erp_modify_adapter_status(adapter, "ccresu1", NULL, | 42 | zfcp_erp_modify_adapter_status(adapter, "ccresu1", NULL, |
37 | ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); | 43 | ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); |
38 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | 44 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
@@ -63,25 +69,14 @@ int zfcp_ccw_priv_sch(struct zfcp_adapter *adapter) | |||
63 | * zfcp_ccw_probe - probe function of zfcp driver | 69 | * zfcp_ccw_probe - probe function of zfcp driver |
64 | * @ccw_device: pointer to belonging ccw device | 70 | * @ccw_device: pointer to belonging ccw device |
65 | * | 71 | * |
66 | * This function gets called by the common i/o layer and sets up the initial | 72 | * This function gets called by the common i/o layer for each FCP |
67 | * data structures for each fcp adapter, which was detected by the system. | 73 | * device found on the current system. This is only a stub to make cio |
68 | * Also the sysfs files for this adapter will be created by this function. | 74 | * work: To only allocate adapter resources for devices actually used, |
69 | * In addition the nameserver port will be added to the ports of the adapter | 75 | * the allocation is deferred to the first call to ccw_set_online. |
70 | * and its sysfs representation will be created too. | ||
71 | */ | 76 | */ |
72 | static int zfcp_ccw_probe(struct ccw_device *ccw_device) | 77 | static int zfcp_ccw_probe(struct ccw_device *ccw_device) |
73 | { | 78 | { |
74 | int retval = 0; | 79 | return 0; |
75 | |||
76 | down(&zfcp_data.config_sema); | ||
77 | if (zfcp_adapter_enqueue(ccw_device)) { | ||
78 | dev_err(&ccw_device->dev, | ||
79 | "Setting up data structures for the " | ||
80 | "FCP adapter failed\n"); | ||
81 | retval = -EINVAL; | ||
82 | } | ||
83 | up(&zfcp_data.config_sema); | ||
84 | return retval; | ||
85 | } | 80 | } |
86 | 81 | ||
87 | /** | 82 | /** |
@@ -102,8 +97,11 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) | |||
102 | LIST_HEAD(port_remove_lh); | 97 | LIST_HEAD(port_remove_lh); |
103 | 98 | ||
104 | ccw_device_set_offline(ccw_device); | 99 | ccw_device_set_offline(ccw_device); |
100 | |||
105 | down(&zfcp_data.config_sema); | 101 | down(&zfcp_data.config_sema); |
106 | adapter = dev_get_drvdata(&ccw_device->dev); | 102 | adapter = dev_get_drvdata(&ccw_device->dev); |
103 | if (!adapter) | ||
104 | goto out; | ||
107 | 105 | ||
108 | write_lock_irq(&zfcp_data.config_lock); | 106 | write_lock_irq(&zfcp_data.config_lock); |
109 | list_for_each_entry_safe(port, p, &adapter->port_list_head, list) { | 107 | list_for_each_entry_safe(port, p, &adapter->port_list_head, list) { |
@@ -129,6 +127,7 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) | |||
129 | wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0); | 127 | wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0); |
130 | zfcp_adapter_dequeue(adapter); | 128 | zfcp_adapter_dequeue(adapter); |
131 | 129 | ||
130 | out: | ||
132 | up(&zfcp_data.config_sema); | 131 | up(&zfcp_data.config_sema); |
133 | } | 132 | } |
134 | 133 | ||
@@ -136,22 +135,33 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) | |||
136 | * zfcp_ccw_set_online - set_online function of zfcp driver | 135 | * zfcp_ccw_set_online - set_online function of zfcp driver |
137 | * @ccw_device: pointer to belonging ccw device | 136 | * @ccw_device: pointer to belonging ccw device |
138 | * | 137 | * |
139 | * This function gets called by the common i/o layer and sets an adapter | 138 | * This function gets called by the common i/o layer and sets an |
140 | * into state online. Setting an fcp device online means that it will be | 139 | * adapter into state online. The first call will allocate all |
141 | * registered with the SCSI stack, that the QDIO queues will be set up | 140 | * adapter resources that will be retained until the device is removed |
142 | * and that the adapter will be opened (asynchronously). | 141 | * via zfcp_ccw_remove. |
142 | * | ||
143 | * Setting an fcp device online means that it will be registered with | ||
144 | * the SCSI stack, that the QDIO queues will be set up and that the | ||
145 | * adapter will be opened. | ||
143 | */ | 146 | */ |
144 | static int zfcp_ccw_set_online(struct ccw_device *ccw_device) | 147 | static int zfcp_ccw_set_online(struct ccw_device *ccw_device) |
145 | { | 148 | { |
146 | struct zfcp_adapter *adapter; | 149 | struct zfcp_adapter *adapter; |
147 | int retval; | 150 | int ret = 0; |
148 | 151 | ||
149 | down(&zfcp_data.config_sema); | 152 | down(&zfcp_data.config_sema); |
150 | adapter = dev_get_drvdata(&ccw_device->dev); | 153 | adapter = dev_get_drvdata(&ccw_device->dev); |
151 | 154 | ||
152 | retval = zfcp_erp_thread_setup(adapter); | 155 | if (!adapter) { |
153 | if (retval) | 156 | ret = zfcp_adapter_enqueue(ccw_device); |
154 | goto out; | 157 | if (ret) { |
158 | dev_err(&ccw_device->dev, | ||
159 | "Setting up data structures for the " | ||
160 | "FCP adapter failed\n"); | ||
161 | goto out; | ||
162 | } | ||
163 | adapter = dev_get_drvdata(&ccw_device->dev); | ||
164 | } | ||
155 | 165 | ||
156 | /* initialize request counter */ | 166 | /* initialize request counter */ |
157 | BUG_ON(!zfcp_reqlist_isempty(adapter)); | 167 | BUG_ON(!zfcp_reqlist_isempty(adapter)); |
@@ -162,13 +172,11 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device) | |||
162 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | 172 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
163 | "ccsonl2", NULL); | 173 | "ccsonl2", NULL); |
164 | zfcp_erp_wait(adapter); | 174 | zfcp_erp_wait(adapter); |
175 | out: | ||
165 | up(&zfcp_data.config_sema); | 176 | up(&zfcp_data.config_sema); |
166 | flush_work(&adapter->scan_work); | 177 | if (!ret) |
167 | return 0; | 178 | flush_work(&adapter->scan_work); |
168 | 179 | return ret; | |
169 | out: | ||
170 | up(&zfcp_data.config_sema); | ||
171 | return retval; | ||
172 | } | 180 | } |
173 | 181 | ||
174 | /** | 182 | /** |
@@ -184,10 +192,13 @@ static int zfcp_ccw_set_offline(struct ccw_device *ccw_device) | |||
184 | 192 | ||
185 | down(&zfcp_data.config_sema); | 193 | down(&zfcp_data.config_sema); |
186 | adapter = dev_get_drvdata(&ccw_device->dev); | 194 | adapter = dev_get_drvdata(&ccw_device->dev); |
195 | if (!adapter) | ||
196 | goto out; | ||
197 | |||
187 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL); | 198 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL); |
188 | zfcp_erp_wait(adapter); | 199 | zfcp_erp_wait(adapter); |
189 | zfcp_erp_thread_kill(adapter); | ||
190 | up(&zfcp_data.config_sema); | 200 | up(&zfcp_data.config_sema); |
201 | out: | ||
191 | return 0; | 202 | return 0; |
192 | } | 203 | } |
193 | 204 | ||
@@ -244,6 +255,7 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev) | |||
244 | adapter = dev_get_drvdata(&cdev->dev); | 255 | adapter = dev_get_drvdata(&cdev->dev); |
245 | zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL); | 256 | zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL); |
246 | zfcp_erp_wait(adapter); | 257 | zfcp_erp_wait(adapter); |
258 | zfcp_erp_thread_kill(adapter); | ||
247 | up(&zfcp_data.config_sema); | 259 | up(&zfcp_data.config_sema); |
248 | } | 260 | } |
249 | 261 | ||
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 577e15708598..73d366ba31e5 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -150,6 +150,9 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, | |||
150 | a_status = atomic_read(&adapter->status); | 150 | a_status = atomic_read(&adapter->status); |
151 | if (a_status & ZFCP_STATUS_COMMON_ERP_INUSE) | 151 | if (a_status & ZFCP_STATUS_COMMON_ERP_INUSE) |
152 | return 0; | 152 | return 0; |
153 | if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) && | ||
154 | !(a_status & ZFCP_STATUS_COMMON_OPEN)) | ||
155 | return 0; /* shutdown requested for closed adapter */ | ||
153 | } | 156 | } |
154 | 157 | ||
155 | return need; | 158 | return need; |
@@ -1349,6 +1352,8 @@ void zfcp_erp_thread_kill(struct zfcp_adapter *adapter) | |||
1349 | { | 1352 | { |
1350 | kthread_stop(adapter->erp_thread); | 1353 | kthread_stop(adapter->erp_thread); |
1351 | adapter->erp_thread = NULL; | 1354 | adapter->erp_thread = NULL; |
1355 | WARN_ON(!list_empty(&adapter->erp_ready_head)); | ||
1356 | WARN_ON(!list_empty(&adapter->erp_running_head)); | ||
1352 | } | 1357 | } |
1353 | 1358 | ||
1354 | /** | 1359 | /** |