diff options
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r-- | drivers/s390/scsi/Makefile | 5 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 213 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ccw.c | 37 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_cfdc.c | 189 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_dbf.c | 1179 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_dbf.h | 503 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 93 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 741 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 116 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.c | 355 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.h | 126 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 758 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_qdio.c | 49 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_qdio.h | 9 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 272 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_sysfs.c | 224 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_unit.c | 244 |
17 files changed, 2379 insertions, 2734 deletions
diff --git a/drivers/s390/scsi/Makefile b/drivers/s390/scsi/Makefile index cb301cc6178c..c454ffebb63e 100644 --- a/drivers/s390/scsi/Makefile +++ b/drivers/s390/scsi/Makefile | |||
@@ -2,7 +2,8 @@ | |||
2 | # Makefile for the S/390 specific device drivers | 2 | # Makefile for the S/390 specific device drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \ | 5 | zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_cfdc.o zfcp_dbf.o zfcp_erp.o \ |
6 | zfcp_fsf.o zfcp_dbf.o zfcp_sysfs.o zfcp_fc.o zfcp_cfdc.o | 6 | zfcp_fc.o zfcp_fsf.o zfcp_qdio.o zfcp_scsi.o zfcp_sysfs.o \ |
7 | zfcp_unit.o | ||
7 | 8 | ||
8 | obj-$(CONFIG_ZFCP) += zfcp.o | 9 | obj-$(CONFIG_ZFCP) += zfcp.o |
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 96fa1f536394..645b0fcbb370 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -45,8 +45,8 @@ static char *init_device; | |||
45 | module_param_named(device, init_device, charp, 0400); | 45 | module_param_named(device, init_device, charp, 0400); |
46 | MODULE_PARM_DESC(device, "specify initial device"); | 46 | MODULE_PARM_DESC(device, "specify initial device"); |
47 | 47 | ||
48 | static struct kmem_cache *zfcp_cache_hw_align(const char *name, | 48 | static struct kmem_cache * __init zfcp_cache_hw_align(const char *name, |
49 | unsigned long size) | 49 | unsigned long size) |
50 | { | 50 | { |
51 | return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL); | 51 | return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL); |
52 | } | 52 | } |
@@ -56,7 +56,6 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) | |||
56 | struct ccw_device *cdev; | 56 | struct ccw_device *cdev; |
57 | struct zfcp_adapter *adapter; | 57 | struct zfcp_adapter *adapter; |
58 | struct zfcp_port *port; | 58 | struct zfcp_port *port; |
59 | struct zfcp_unit *unit; | ||
60 | 59 | ||
61 | cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); | 60 | cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); |
62 | if (!cdev) | 61 | if (!cdev) |
@@ -72,17 +71,11 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) | |||
72 | port = zfcp_get_port_by_wwpn(adapter, wwpn); | 71 | port = zfcp_get_port_by_wwpn(adapter, wwpn); |
73 | if (!port) | 72 | if (!port) |
74 | goto out_port; | 73 | goto out_port; |
74 | flush_work(&port->rport_work); | ||
75 | 75 | ||
76 | unit = zfcp_unit_enqueue(port, lun); | 76 | zfcp_unit_add(port, lun); |
77 | if (IS_ERR(unit)) | ||
78 | goto out_unit; | ||
79 | |||
80 | zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL); | ||
81 | zfcp_erp_wait(adapter); | ||
82 | flush_work(&unit->scsi_work); | ||
83 | |||
84 | out_unit: | ||
85 | put_device(&port->dev); | 77 | put_device(&port->dev); |
78 | |||
86 | out_port: | 79 | out_port: |
87 | zfcp_ccw_adapter_put(adapter); | 80 | zfcp_ccw_adapter_put(adapter); |
88 | out_ccw_device: | 81 | out_ccw_device: |
@@ -129,35 +122,23 @@ static int __init zfcp_module_init(void) | |||
129 | { | 122 | { |
130 | int retval = -ENOMEM; | 123 | int retval = -ENOMEM; |
131 | 124 | ||
132 | zfcp_data.gpn_ft_cache = zfcp_cache_hw_align("zfcp_gpn", | 125 | zfcp_fsf_qtcb_cache = zfcp_cache_hw_align("zfcp_fsf_qtcb", |
133 | sizeof(struct zfcp_fc_gpn_ft_req)); | 126 | sizeof(struct fsf_qtcb)); |
134 | if (!zfcp_data.gpn_ft_cache) | 127 | if (!zfcp_fsf_qtcb_cache) |
135 | goto out; | ||
136 | |||
137 | zfcp_data.qtcb_cache = zfcp_cache_hw_align("zfcp_qtcb", | ||
138 | sizeof(struct fsf_qtcb)); | ||
139 | if (!zfcp_data.qtcb_cache) | ||
140 | goto out_qtcb_cache; | 128 | goto out_qtcb_cache; |
141 | 129 | ||
142 | zfcp_data.sr_buffer_cache = zfcp_cache_hw_align("zfcp_sr", | 130 | zfcp_fc_req_cache = zfcp_cache_hw_align("zfcp_fc_req", |
143 | sizeof(struct fsf_status_read_buffer)); | 131 | sizeof(struct zfcp_fc_req)); |
144 | if (!zfcp_data.sr_buffer_cache) | 132 | if (!zfcp_fc_req_cache) |
145 | goto out_sr_cache; | 133 | goto out_fc_cache; |
146 | 134 | ||
147 | zfcp_data.gid_pn_cache = zfcp_cache_hw_align("zfcp_gid", | 135 | zfcp_scsi_transport_template = |
148 | sizeof(struct zfcp_fc_gid_pn)); | ||
149 | if (!zfcp_data.gid_pn_cache) | ||
150 | goto out_gid_cache; | ||
151 | |||
152 | zfcp_data.adisc_cache = zfcp_cache_hw_align("zfcp_adisc", | ||
153 | sizeof(struct zfcp_fc_els_adisc)); | ||
154 | if (!zfcp_data.adisc_cache) | ||
155 | goto out_adisc_cache; | ||
156 | |||
157 | zfcp_data.scsi_transport_template = | ||
158 | fc_attach_transport(&zfcp_transport_functions); | 136 | fc_attach_transport(&zfcp_transport_functions); |
159 | if (!zfcp_data.scsi_transport_template) | 137 | if (!zfcp_scsi_transport_template) |
160 | goto out_transport; | 138 | goto out_transport; |
139 | scsi_transport_reserve_device(zfcp_scsi_transport_template, | ||
140 | sizeof(struct zfcp_scsi_dev)); | ||
141 | |||
161 | 142 | ||
162 | retval = misc_register(&zfcp_cfdc_misc); | 143 | retval = misc_register(&zfcp_cfdc_misc); |
163 | if (retval) { | 144 | if (retval) { |
@@ -179,18 +160,12 @@ static int __init zfcp_module_init(void) | |||
179 | out_ccw_register: | 160 | out_ccw_register: |
180 | misc_deregister(&zfcp_cfdc_misc); | 161 | misc_deregister(&zfcp_cfdc_misc); |
181 | out_misc: | 162 | out_misc: |
182 | fc_release_transport(zfcp_data.scsi_transport_template); | 163 | fc_release_transport(zfcp_scsi_transport_template); |
183 | out_transport: | 164 | out_transport: |
184 | kmem_cache_destroy(zfcp_data.adisc_cache); | 165 | kmem_cache_destroy(zfcp_fc_req_cache); |
185 | out_adisc_cache: | 166 | out_fc_cache: |
186 | kmem_cache_destroy(zfcp_data.gid_pn_cache); | 167 | kmem_cache_destroy(zfcp_fsf_qtcb_cache); |
187 | out_gid_cache: | ||
188 | kmem_cache_destroy(zfcp_data.sr_buffer_cache); | ||
189 | out_sr_cache: | ||
190 | kmem_cache_destroy(zfcp_data.qtcb_cache); | ||
191 | out_qtcb_cache: | 168 | out_qtcb_cache: |
192 | kmem_cache_destroy(zfcp_data.gpn_ft_cache); | ||
193 | out: | ||
194 | return retval; | 169 | return retval; |
195 | } | 170 | } |
196 | 171 | ||
@@ -200,41 +175,14 @@ static void __exit zfcp_module_exit(void) | |||
200 | { | 175 | { |
201 | ccw_driver_unregister(&zfcp_ccw_driver); | 176 | ccw_driver_unregister(&zfcp_ccw_driver); |
202 | misc_deregister(&zfcp_cfdc_misc); | 177 | misc_deregister(&zfcp_cfdc_misc); |
203 | fc_release_transport(zfcp_data.scsi_transport_template); | 178 | fc_release_transport(zfcp_scsi_transport_template); |
204 | kmem_cache_destroy(zfcp_data.adisc_cache); | 179 | kmem_cache_destroy(zfcp_fc_req_cache); |
205 | kmem_cache_destroy(zfcp_data.gid_pn_cache); | 180 | kmem_cache_destroy(zfcp_fsf_qtcb_cache); |
206 | kmem_cache_destroy(zfcp_data.sr_buffer_cache); | ||
207 | kmem_cache_destroy(zfcp_data.qtcb_cache); | ||
208 | kmem_cache_destroy(zfcp_data.gpn_ft_cache); | ||
209 | } | 181 | } |
210 | 182 | ||
211 | module_exit(zfcp_module_exit); | 183 | module_exit(zfcp_module_exit); |
212 | 184 | ||
213 | /** | 185 | /** |
214 | * zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN | ||
215 | * @port: pointer to port to search for unit | ||
216 | * @fcp_lun: FCP LUN to search for | ||
217 | * | ||
218 | * Returns: pointer to zfcp_unit or NULL | ||
219 | */ | ||
220 | struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun) | ||
221 | { | ||
222 | unsigned long flags; | ||
223 | struct zfcp_unit *unit; | ||
224 | |||
225 | read_lock_irqsave(&port->unit_list_lock, flags); | ||
226 | list_for_each_entry(unit, &port->unit_list, list) | ||
227 | if (unit->fcp_lun == fcp_lun) { | ||
228 | if (!get_device(&unit->dev)) | ||
229 | unit = NULL; | ||
230 | read_unlock_irqrestore(&port->unit_list_lock, flags); | ||
231 | return unit; | ||
232 | } | ||
233 | read_unlock_irqrestore(&port->unit_list_lock, flags); | ||
234 | return NULL; | ||
235 | } | ||
236 | |||
237 | /** | ||
238 | * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn | 186 | * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn |
239 | * @adapter: pointer to adapter to search for port | 187 | * @adapter: pointer to adapter to search for port |
240 | * @wwpn: wwpn to search for | 188 | * @wwpn: wwpn to search for |
@@ -259,92 +207,6 @@ struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, | |||
259 | return NULL; | 207 | return NULL; |
260 | } | 208 | } |
261 | 209 | ||
262 | /** | ||
263 | * zfcp_unit_release - dequeue unit | ||
264 | * @dev: pointer to device | ||
265 | * | ||
266 | * waits until all work is done on unit and removes it then from the unit->list | ||
267 | * of the associated port. | ||
268 | */ | ||
269 | static void zfcp_unit_release(struct device *dev) | ||
270 | { | ||
271 | struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); | ||
272 | |||
273 | put_device(&unit->port->dev); | ||
274 | kfree(unit); | ||
275 | } | ||
276 | |||
277 | /** | ||
278 | * zfcp_unit_enqueue - enqueue unit to unit list of a port. | ||
279 | * @port: pointer to port where unit is added | ||
280 | * @fcp_lun: FCP LUN of unit to be enqueued | ||
281 | * Returns: pointer to enqueued unit on success, ERR_PTR on error | ||
282 | * | ||
283 | * Sets up some unit internal structures and creates sysfs entry. | ||
284 | */ | ||
285 | struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | ||
286 | { | ||
287 | struct zfcp_unit *unit; | ||
288 | int retval = -ENOMEM; | ||
289 | |||
290 | get_device(&port->dev); | ||
291 | |||
292 | unit = zfcp_get_unit_by_lun(port, fcp_lun); | ||
293 | if (unit) { | ||
294 | put_device(&unit->dev); | ||
295 | retval = -EEXIST; | ||
296 | goto err_out; | ||
297 | } | ||
298 | |||
299 | unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); | ||
300 | if (!unit) | ||
301 | goto err_out; | ||
302 | |||
303 | unit->port = port; | ||
304 | unit->fcp_lun = fcp_lun; | ||
305 | unit->dev.parent = &port->dev; | ||
306 | unit->dev.release = zfcp_unit_release; | ||
307 | |||
308 | if (dev_set_name(&unit->dev, "0x%016llx", | ||
309 | (unsigned long long) fcp_lun)) { | ||
310 | kfree(unit); | ||
311 | goto err_out; | ||
312 | } | ||
313 | retval = -EINVAL; | ||
314 | |||
315 | INIT_WORK(&unit->scsi_work, zfcp_scsi_scan_work); | ||
316 | |||
317 | spin_lock_init(&unit->latencies.lock); | ||
318 | unit->latencies.write.channel.min = 0xFFFFFFFF; | ||
319 | unit->latencies.write.fabric.min = 0xFFFFFFFF; | ||
320 | unit->latencies.read.channel.min = 0xFFFFFFFF; | ||
321 | unit->latencies.read.fabric.min = 0xFFFFFFFF; | ||
322 | unit->latencies.cmd.channel.min = 0xFFFFFFFF; | ||
323 | unit->latencies.cmd.fabric.min = 0xFFFFFFFF; | ||
324 | |||
325 | if (device_register(&unit->dev)) { | ||
326 | put_device(&unit->dev); | ||
327 | goto err_out; | ||
328 | } | ||
329 | |||
330 | if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) | ||
331 | goto err_out_put; | ||
332 | |||
333 | write_lock_irq(&port->unit_list_lock); | ||
334 | list_add_tail(&unit->list, &port->unit_list); | ||
335 | write_unlock_irq(&port->unit_list_lock); | ||
336 | |||
337 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status); | ||
338 | |||
339 | return unit; | ||
340 | |||
341 | err_out_put: | ||
342 | device_unregister(&unit->dev); | ||
343 | err_out: | ||
344 | put_device(&port->dev); | ||
345 | return ERR_PTR(retval); | ||
346 | } | ||
347 | |||
348 | static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter) | 210 | static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter) |
349 | { | 211 | { |
350 | adapter->pool.erp_req = | 212 | adapter->pool.erp_req = |
@@ -374,18 +236,18 @@ static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter) | |||
374 | return -ENOMEM; | 236 | return -ENOMEM; |
375 | 237 | ||
376 | adapter->pool.qtcb_pool = | 238 | adapter->pool.qtcb_pool = |
377 | mempool_create_slab_pool(4, zfcp_data.qtcb_cache); | 239 | mempool_create_slab_pool(4, zfcp_fsf_qtcb_cache); |
378 | if (!adapter->pool.qtcb_pool) | 240 | if (!adapter->pool.qtcb_pool) |
379 | return -ENOMEM; | 241 | return -ENOMEM; |
380 | 242 | ||
381 | adapter->pool.status_read_data = | 243 | BUILD_BUG_ON(sizeof(struct fsf_status_read_buffer) > PAGE_SIZE); |
382 | mempool_create_slab_pool(FSF_STATUS_READS_RECOM, | 244 | adapter->pool.sr_data = |
383 | zfcp_data.sr_buffer_cache); | 245 | mempool_create_page_pool(FSF_STATUS_READS_RECOM, 0); |
384 | if (!adapter->pool.status_read_data) | 246 | if (!adapter->pool.sr_data) |
385 | return -ENOMEM; | 247 | return -ENOMEM; |
386 | 248 | ||
387 | adapter->pool.gid_pn = | 249 | adapter->pool.gid_pn = |
388 | mempool_create_slab_pool(1, zfcp_data.gid_pn_cache); | 250 | mempool_create_slab_pool(1, zfcp_fc_req_cache); |
389 | if (!adapter->pool.gid_pn) | 251 | if (!adapter->pool.gid_pn) |
390 | return -ENOMEM; | 252 | return -ENOMEM; |
391 | 253 | ||
@@ -404,8 +266,8 @@ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) | |||
404 | mempool_destroy(adapter->pool.qtcb_pool); | 266 | mempool_destroy(adapter->pool.qtcb_pool); |
405 | if (adapter->pool.status_read_req) | 267 | if (adapter->pool.status_read_req) |
406 | mempool_destroy(adapter->pool.status_read_req); | 268 | mempool_destroy(adapter->pool.status_read_req); |
407 | if (adapter->pool.status_read_data) | 269 | if (adapter->pool.sr_data) |
408 | mempool_destroy(adapter->pool.status_read_data); | 270 | mempool_destroy(adapter->pool.sr_data); |
409 | if (adapter->pool.gid_pn) | 271 | if (adapter->pool.gid_pn) |
410 | mempool_destroy(adapter->pool.gid_pn); | 272 | mempool_destroy(adapter->pool.gid_pn); |
411 | } | 273 | } |
@@ -425,8 +287,7 @@ int zfcp_status_read_refill(struct zfcp_adapter *adapter) | |||
425 | if (zfcp_fsf_status_read(adapter->qdio)) { | 287 | if (zfcp_fsf_status_read(adapter->qdio)) { |
426 | if (atomic_read(&adapter->stat_miss) >= | 288 | if (atomic_read(&adapter->stat_miss) >= |
427 | adapter->stat_read_buf_num) { | 289 | adapter->stat_read_buf_num) { |
428 | zfcp_erp_adapter_reopen(adapter, 0, "axsref1", | 290 | zfcp_erp_adapter_reopen(adapter, 0, "axsref1"); |
429 | NULL); | ||
430 | return 1; | 291 | return 1; |
431 | } | 292 | } |
432 | break; | 293 | break; |
@@ -501,6 +362,7 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
501 | 362 | ||
502 | INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler); | 363 | INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler); |
503 | INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports); | 364 | INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports); |
365 | INIT_WORK(&adapter->ns_up_work, zfcp_fc_sym_name_update); | ||
504 | 366 | ||
505 | if (zfcp_qdio_setup(adapter)) | 367 | if (zfcp_qdio_setup(adapter)) |
506 | goto failed; | 368 | goto failed; |
@@ -552,7 +414,7 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
552 | adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN; | 414 | adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN; |
553 | adapter->ccw_device->dev.dma_parms = &adapter->dma_parms; | 415 | adapter->ccw_device->dev.dma_parms = &adapter->dma_parms; |
554 | 416 | ||
555 | if (!zfcp_adapter_scsi_register(adapter)) | 417 | if (!zfcp_scsi_adapter_register(adapter)) |
556 | return adapter; | 418 | return adapter; |
557 | 419 | ||
558 | failed: | 420 | failed: |
@@ -566,14 +428,15 @@ void zfcp_adapter_unregister(struct zfcp_adapter *adapter) | |||
566 | 428 | ||
567 | cancel_work_sync(&adapter->scan_work); | 429 | cancel_work_sync(&adapter->scan_work); |
568 | cancel_work_sync(&adapter->stat_work); | 430 | cancel_work_sync(&adapter->stat_work); |
431 | cancel_work_sync(&adapter->ns_up_work); | ||
569 | zfcp_destroy_adapter_work_queue(adapter); | 432 | zfcp_destroy_adapter_work_queue(adapter); |
570 | 433 | ||
571 | zfcp_fc_wka_ports_force_offline(adapter->gs); | 434 | zfcp_fc_wka_ports_force_offline(adapter->gs); |
572 | zfcp_adapter_scsi_unregister(adapter); | 435 | zfcp_scsi_adapter_unregister(adapter); |
573 | sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs); | 436 | sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs); |
574 | 437 | ||
575 | zfcp_erp_thread_kill(adapter); | 438 | zfcp_erp_thread_kill(adapter); |
576 | zfcp_dbf_adapter_unregister(adapter->dbf); | 439 | zfcp_dbf_adapter_unregister(adapter); |
577 | zfcp_qdio_destroy(adapter->qdio); | 440 | zfcp_qdio_destroy(adapter->qdio); |
578 | 441 | ||
579 | zfcp_ccw_adapter_put(adapter); /* final put to release */ | 442 | zfcp_ccw_adapter_put(adapter); /* final put to release */ |
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index ce1cc7a11fb4..e8b7cee62046 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -46,10 +46,9 @@ static int zfcp_ccw_activate(struct ccw_device *cdev) | |||
46 | if (!adapter) | 46 | if (!adapter) |
47 | return 0; | 47 | return 0; |
48 | 48 | ||
49 | zfcp_erp_modify_adapter_status(adapter, "ccresu1", NULL, | 49 | zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); |
50 | ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); | ||
51 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | 50 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
52 | "ccresu2", NULL); | 51 | "ccresu2"); |
53 | zfcp_erp_wait(adapter); | 52 | zfcp_erp_wait(adapter); |
54 | flush_work(&adapter->scan_work); | 53 | flush_work(&adapter->scan_work); |
55 | 54 | ||
@@ -164,14 +163,7 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev) | |||
164 | BUG_ON(!zfcp_reqlist_isempty(adapter->req_list)); | 163 | BUG_ON(!zfcp_reqlist_isempty(adapter->req_list)); |
165 | adapter->req_no = 0; | 164 | adapter->req_no = 0; |
166 | 165 | ||
167 | zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL, | 166 | zfcp_ccw_activate(cdev); |
168 | ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); | ||
169 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | ||
170 | "ccsonl2", NULL); | ||
171 | zfcp_erp_wait(adapter); | ||
172 | |||
173 | flush_work(&adapter->scan_work); | ||
174 | |||
175 | zfcp_ccw_adapter_put(adapter); | 167 | zfcp_ccw_adapter_put(adapter); |
176 | return 0; | 168 | return 0; |
177 | } | 169 | } |
@@ -190,7 +182,7 @@ static int zfcp_ccw_set_offline(struct ccw_device *cdev) | |||
190 | if (!adapter) | 182 | if (!adapter) |
191 | return 0; | 183 | return 0; |
192 | 184 | ||
193 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL); | 185 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1"); |
194 | zfcp_erp_wait(adapter); | 186 | zfcp_erp_wait(adapter); |
195 | 187 | ||
196 | zfcp_ccw_adapter_put(adapter); | 188 | zfcp_ccw_adapter_put(adapter); |
@@ -215,25 +207,24 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event) | |||
215 | switch (event) { | 207 | switch (event) { |
216 | case CIO_GONE: | 208 | case CIO_GONE: |
217 | dev_warn(&cdev->dev, "The FCP device has been detached\n"); | 209 | dev_warn(&cdev->dev, "The FCP device has been detached\n"); |
218 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1", NULL); | 210 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1"); |
219 | break; | 211 | break; |
220 | case CIO_NO_PATH: | 212 | case CIO_NO_PATH: |
221 | dev_warn(&cdev->dev, | 213 | dev_warn(&cdev->dev, |
222 | "The CHPID for the FCP device is offline\n"); | 214 | "The CHPID for the FCP device is offline\n"); |
223 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2", NULL); | 215 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2"); |
224 | break; | 216 | break; |
225 | case CIO_OPER: | 217 | case CIO_OPER: |
226 | dev_info(&cdev->dev, "The FCP device is operational again\n"); | 218 | dev_info(&cdev->dev, "The FCP device is operational again\n"); |
227 | zfcp_erp_modify_adapter_status(adapter, "ccnoti3", NULL, | 219 | zfcp_erp_set_adapter_status(adapter, |
228 | ZFCP_STATUS_COMMON_RUNNING, | 220 | ZFCP_STATUS_COMMON_RUNNING); |
229 | ZFCP_SET); | ||
230 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | 221 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
231 | "ccnoti4", NULL); | 222 | "ccnoti4"); |
232 | break; | 223 | break; |
233 | case CIO_BOXED: | 224 | case CIO_BOXED: |
234 | dev_warn(&cdev->dev, "The FCP device did not respond within " | 225 | dev_warn(&cdev->dev, "The FCP device did not respond within " |
235 | "the specified time\n"); | 226 | "the specified time\n"); |
236 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5", NULL); | 227 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5"); |
237 | break; | 228 | break; |
238 | } | 229 | } |
239 | 230 | ||
@@ -252,7 +243,7 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev) | |||
252 | if (!adapter) | 243 | if (!adapter) |
253 | return; | 244 | return; |
254 | 245 | ||
255 | zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL); | 246 | zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1"); |
256 | zfcp_erp_wait(adapter); | 247 | zfcp_erp_wait(adapter); |
257 | zfcp_erp_thread_kill(adapter); | 248 | zfcp_erp_thread_kill(adapter); |
258 | 249 | ||
@@ -260,8 +251,10 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev) | |||
260 | } | 251 | } |
261 | 252 | ||
262 | struct ccw_driver zfcp_ccw_driver = { | 253 | struct ccw_driver zfcp_ccw_driver = { |
263 | .owner = THIS_MODULE, | 254 | .driver = { |
264 | .name = "zfcp", | 255 | .owner = THIS_MODULE, |
256 | .name = "zfcp", | ||
257 | }, | ||
265 | .ids = zfcp_ccw_device_id, | 258 | .ids = zfcp_ccw_device_id, |
266 | .probe = zfcp_ccw_probe, | 259 | .probe = zfcp_ccw_probe, |
267 | .remove = zfcp_ccw_remove, | 260 | .remove = zfcp_ccw_remove, |
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index fcbd2b756da4..303dde09d294 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c | |||
@@ -2,9 +2,10 @@ | |||
2 | * zfcp device driver | 2 | * zfcp device driver |
3 | * | 3 | * |
4 | * Userspace interface for accessing the | 4 | * Userspace interface for accessing the |
5 | * Access Control Lists / Control File Data Channel | 5 | * Access Control Lists / Control File Data Channel; |
6 | * handling of response code and states for ports and LUNs. | ||
6 | * | 7 | * |
7 | * Copyright IBM Corporation 2008, 2009 | 8 | * Copyright IBM Corporation 2008, 2010 |
8 | */ | 9 | */ |
9 | 10 | ||
10 | #define KMSG_COMPONENT "zfcp" | 11 | #define KMSG_COMPONENT "zfcp" |
@@ -251,8 +252,9 @@ static const struct file_operations zfcp_cfdc_fops = { | |||
251 | .open = nonseekable_open, | 252 | .open = nonseekable_open, |
252 | .unlocked_ioctl = zfcp_cfdc_dev_ioctl, | 253 | .unlocked_ioctl = zfcp_cfdc_dev_ioctl, |
253 | #ifdef CONFIG_COMPAT | 254 | #ifdef CONFIG_COMPAT |
254 | .compat_ioctl = zfcp_cfdc_dev_ioctl | 255 | .compat_ioctl = zfcp_cfdc_dev_ioctl, |
255 | #endif | 256 | #endif |
257 | .llseek = no_llseek, | ||
256 | }; | 258 | }; |
257 | 259 | ||
258 | struct miscdevice zfcp_cfdc_misc = { | 260 | struct miscdevice zfcp_cfdc_misc = { |
@@ -260,3 +262,184 @@ struct miscdevice zfcp_cfdc_misc = { | |||
260 | .name = "zfcp_cfdc", | 262 | .name = "zfcp_cfdc", |
261 | .fops = &zfcp_cfdc_fops, | 263 | .fops = &zfcp_cfdc_fops, |
262 | }; | 264 | }; |
265 | |||
266 | /** | ||
267 | * zfcp_cfdc_adapter_access_changed - Process change in adapter ACT | ||
268 | * @adapter: Adapter where the Access Control Table (ACT) changed | ||
269 | * | ||
270 | * After a change in the adapter ACT, check if access to any | ||
271 | * previously denied resources is now possible. | ||
272 | */ | ||
273 | void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter) | ||
274 | { | ||
275 | unsigned long flags; | ||
276 | struct zfcp_port *port; | ||
277 | struct scsi_device *sdev; | ||
278 | struct zfcp_scsi_dev *zfcp_sdev; | ||
279 | int status; | ||
280 | |||
281 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) | ||
282 | return; | ||
283 | |||
284 | read_lock_irqsave(&adapter->port_list_lock, flags); | ||
285 | list_for_each_entry(port, &adapter->port_list, list) { | ||
286 | status = atomic_read(&port->status); | ||
287 | if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) || | ||
288 | (status & ZFCP_STATUS_COMMON_ACCESS_BOXED)) | ||
289 | zfcp_erp_port_reopen(port, | ||
290 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
291 | "cfaac_1"); | ||
292 | } | ||
293 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | ||
294 | |||
295 | shost_for_each_device(sdev, port->adapter->scsi_host) { | ||
296 | zfcp_sdev = sdev_to_zfcp(sdev); | ||
297 | status = atomic_read(&zfcp_sdev->status); | ||
298 | if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) || | ||
299 | (status & ZFCP_STATUS_COMMON_ACCESS_BOXED)) | ||
300 | zfcp_erp_lun_reopen(sdev, | ||
301 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
302 | "cfaac_2"); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table) | ||
307 | { | ||
308 | u16 subtable = table >> 16; | ||
309 | u16 rule = table & 0xffff; | ||
310 | const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" }; | ||
311 | |||
312 | if (subtable && subtable < ARRAY_SIZE(act_type)) | ||
313 | dev_warn(&adapter->ccw_device->dev, | ||
314 | "Access denied according to ACT rule type %s, " | ||
315 | "rule %d\n", act_type[subtable], rule); | ||
316 | } | ||
317 | |||
318 | /** | ||
319 | * zfcp_cfdc_port_denied - Process "access denied" for port | ||
320 | * @port: The port where the access has been denied | ||
321 | * @qual: The FSF status qualifier for the access denied FSF status | ||
322 | */ | ||
323 | void zfcp_cfdc_port_denied(struct zfcp_port *port, | ||
324 | union fsf_status_qual *qual) | ||
325 | { | ||
326 | dev_warn(&port->adapter->ccw_device->dev, | ||
327 | "Access denied to port 0x%016Lx\n", | ||
328 | (unsigned long long)port->wwpn); | ||
329 | |||
330 | zfcp_act_eval_err(port->adapter, qual->halfword[0]); | ||
331 | zfcp_act_eval_err(port->adapter, qual->halfword[1]); | ||
332 | zfcp_erp_set_port_status(port, | ||
333 | ZFCP_STATUS_COMMON_ERP_FAILED | | ||
334 | ZFCP_STATUS_COMMON_ACCESS_DENIED); | ||
335 | } | ||
336 | |||
337 | /** | ||
338 | * zfcp_cfdc_lun_denied - Process "access denied" for LUN | ||
339 | * @sdev: The SCSI device / LUN where the access has been denied | ||
340 | * @qual: The FSF status qualifier for the access denied FSF status | ||
341 | */ | ||
342 | void zfcp_cfdc_lun_denied(struct scsi_device *sdev, | ||
343 | union fsf_status_qual *qual) | ||
344 | { | ||
345 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
346 | |||
347 | dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev, | ||
348 | "Access denied to LUN 0x%016Lx on port 0x%016Lx\n", | ||
349 | zfcp_scsi_dev_lun(sdev), | ||
350 | (unsigned long long)zfcp_sdev->port->wwpn); | ||
351 | zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->halfword[0]); | ||
352 | zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->halfword[1]); | ||
353 | zfcp_erp_set_lun_status(sdev, | ||
354 | ZFCP_STATUS_COMMON_ERP_FAILED | | ||
355 | ZFCP_STATUS_COMMON_ACCESS_DENIED); | ||
356 | |||
357 | atomic_clear_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status); | ||
358 | atomic_clear_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status); | ||
359 | } | ||
360 | |||
361 | /** | ||
362 | * zfcp_cfdc_lun_shrng_vltn - Evaluate LUN sharing violation status | ||
363 | * @sdev: The LUN / SCSI device where sharing violation occurred | ||
364 | * @qual: The FSF status qualifier from the LUN sharing violation | ||
365 | */ | ||
366 | void zfcp_cfdc_lun_shrng_vltn(struct scsi_device *sdev, | ||
367 | union fsf_status_qual *qual) | ||
368 | { | ||
369 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
370 | |||
371 | if (qual->word[0]) | ||
372 | dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev, | ||
373 | "LUN 0x%Lx on port 0x%Lx is already in " | ||
374 | "use by CSS%d, MIF Image ID %x\n", | ||
375 | zfcp_scsi_dev_lun(sdev), | ||
376 | (unsigned long long)zfcp_sdev->port->wwpn, | ||
377 | qual->fsf_queue_designator.cssid, | ||
378 | qual->fsf_queue_designator.hla); | ||
379 | else | ||
380 | zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->word[2]); | ||
381 | |||
382 | zfcp_erp_set_lun_status(sdev, | ||
383 | ZFCP_STATUS_COMMON_ERP_FAILED | | ||
384 | ZFCP_STATUS_COMMON_ACCESS_DENIED); | ||
385 | atomic_clear_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status); | ||
386 | atomic_clear_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status); | ||
387 | } | ||
388 | |||
389 | /** | ||
390 | * zfcp_cfdc_open_lun_eval - Eval access ctrl. status for successful "open lun" | ||
391 | * @sdev: The SCSI device / LUN where to evaluate the status | ||
392 | * @bottom: The qtcb bottom with the status from the "open lun" | ||
393 | * | ||
394 | * Returns: 0 if LUN is usable, -EACCES if the access control table | ||
395 | * reports an unsupported configuration. | ||
396 | */ | ||
397 | int zfcp_cfdc_open_lun_eval(struct scsi_device *sdev, | ||
398 | struct fsf_qtcb_bottom_support *bottom) | ||
399 | { | ||
400 | int shared, rw; | ||
401 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
402 | struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; | ||
403 | |||
404 | if ((adapter->connection_features & FSF_FEATURE_NPIV_MODE) || | ||
405 | !(adapter->adapter_features & FSF_FEATURE_LUN_SHARING) || | ||
406 | zfcp_ccw_priv_sch(adapter)) | ||
407 | return 0; | ||
408 | |||
409 | shared = !(bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE); | ||
410 | rw = (bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER); | ||
411 | |||
412 | if (shared) | ||
413 | atomic_set_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status); | ||
414 | |||
415 | if (!rw) { | ||
416 | atomic_set_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status); | ||
417 | dev_info(&adapter->ccw_device->dev, "SCSI device at LUN " | ||
418 | "0x%016Lx on port 0x%016Lx opened read-only\n", | ||
419 | zfcp_scsi_dev_lun(sdev), | ||
420 | (unsigned long long)zfcp_sdev->port->wwpn); | ||
421 | } | ||
422 | |||
423 | if (!shared && !rw) { | ||
424 | dev_err(&adapter->ccw_device->dev, "Exclusive read-only access " | ||
425 | "not supported (LUN 0x%016Lx, port 0x%016Lx)\n", | ||
426 | zfcp_scsi_dev_lun(sdev), | ||
427 | (unsigned long long)zfcp_sdev->port->wwpn); | ||
428 | zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED); | ||
429 | zfcp_erp_lun_shutdown(sdev, 0, "fsouh_6"); | ||
430 | return -EACCES; | ||
431 | } | ||
432 | |||
433 | if (shared && rw) { | ||
434 | dev_err(&adapter->ccw_device->dev, | ||
435 | "Shared read-write access not supported " | ||
436 | "(LUN 0x%016Lx, port 0x%016Lx)\n", | ||
437 | zfcp_scsi_dev_lun(sdev), | ||
438 | (unsigned long long)zfcp_sdev->port->wwpn); | ||
439 | zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED); | ||
440 | zfcp_erp_lun_shutdown(sdev, 0, "fsosh_8"); | ||
441 | return -EACCES; | ||
442 | } | ||
443 | |||
444 | return 0; | ||
445 | } | ||
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index a86117b0d6e1..96d1462e0bf5 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Debug traces for zfcp. | 4 | * Debug traces for zfcp. |
5 | * | 5 | * |
6 | * Copyright IBM Corporation 2002, 2009 | 6 | * Copyright IBM Corporation 2002, 2010 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
@@ -22,982 +22,392 @@ module_param(dbfsize, uint, 0400); | |||
22 | MODULE_PARM_DESC(dbfsize, | 22 | MODULE_PARM_DESC(dbfsize, |
23 | "number of pages for each debug feature area (default 4)"); | 23 | "number of pages for each debug feature area (default 4)"); |
24 | 24 | ||
25 | static void zfcp_dbf_hexdump(debug_info_t *dbf, void *to, int to_len, | 25 | static inline unsigned int zfcp_dbf_plen(unsigned int offset) |
26 | int level, char *from, int from_len) | ||
27 | { | 26 | { |
28 | int offset; | 27 | return sizeof(struct zfcp_dbf_pay) + offset - ZFCP_DBF_PAY_MAX_REC; |
29 | struct zfcp_dbf_dump *dump = to; | ||
30 | int room = to_len - sizeof(*dump); | ||
31 | |||
32 | for (offset = 0; offset < from_len; offset += dump->size) { | ||
33 | memset(to, 0, to_len); | ||
34 | strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE); | ||
35 | dump->total_size = from_len; | ||
36 | dump->offset = offset; | ||
37 | dump->size = min(from_len - offset, room); | ||
38 | memcpy(dump->data, from + offset, dump->size); | ||
39 | debug_event(dbf, level, dump, dump->size + sizeof(*dump)); | ||
40 | } | ||
41 | } | 28 | } |
42 | 29 | ||
43 | static void zfcp_dbf_tag(char **p, const char *label, const char *tag) | 30 | static inline |
31 | void zfcp_dbf_pl_write(struct zfcp_dbf *dbf, void *data, u16 length, char *area, | ||
32 | u64 req_id) | ||
44 | { | 33 | { |
45 | int i; | 34 | struct zfcp_dbf_pay *pl = &dbf->pay_buf; |
46 | 35 | u16 offset = 0, rec_length; | |
47 | *p += sprintf(*p, "%-24s", label); | ||
48 | for (i = 0; i < ZFCP_DBF_TAG_SIZE; i++) | ||
49 | *p += sprintf(*p, "%c", tag[i]); | ||
50 | *p += sprintf(*p, "\n"); | ||
51 | } | ||
52 | 36 | ||
53 | static void zfcp_dbf_outs(char **buf, const char *s1, const char *s2) | 37 | spin_lock(&dbf->pay_lock); |
54 | { | 38 | memset(pl, 0, sizeof(*pl)); |
55 | *buf += sprintf(*buf, "%-24s%s\n", s1, s2); | 39 | pl->fsf_req_id = req_id; |
56 | } | 40 | memcpy(pl->area, area, ZFCP_DBF_TAG_LEN); |
57 | 41 | ||
58 | static void zfcp_dbf_out(char **buf, const char *s, const char *format, ...) | 42 | while (offset < length) { |
59 | { | 43 | rec_length = min((u16) ZFCP_DBF_PAY_MAX_REC, |
60 | va_list arg; | 44 | (u16) (length - offset)); |
45 | memcpy(pl->data, data + offset, rec_length); | ||
46 | debug_event(dbf->pay, 1, pl, zfcp_dbf_plen(rec_length)); | ||
61 | 47 | ||
62 | *buf += sprintf(*buf, "%-24s", s); | 48 | offset += rec_length; |
63 | va_start(arg, format); | 49 | pl->counter++; |
64 | *buf += vsprintf(*buf, format, arg); | ||
65 | va_end(arg); | ||
66 | *buf += sprintf(*buf, "\n"); | ||
67 | } | ||
68 | |||
69 | static void zfcp_dbf_outd(char **p, const char *label, char *buffer, | ||
70 | int buflen, int offset, int total_size) | ||
71 | { | ||
72 | if (!offset) | ||
73 | *p += sprintf(*p, "%-24s ", label); | ||
74 | while (buflen--) { | ||
75 | if (offset > 0) { | ||
76 | if ((offset % 32) == 0) | ||
77 | *p += sprintf(*p, "\n%-24c ", ' '); | ||
78 | else if ((offset % 4) == 0) | ||
79 | *p += sprintf(*p, " "); | ||
80 | } | ||
81 | *p += sprintf(*p, "%02x", *buffer++); | ||
82 | if (++offset == total_size) { | ||
83 | *p += sprintf(*p, "\n"); | ||
84 | break; | ||
85 | } | ||
86 | } | 50 | } |
87 | if (!total_size) | ||
88 | *p += sprintf(*p, "\n"); | ||
89 | } | ||
90 | 51 | ||
91 | static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view, | 52 | spin_unlock(&dbf->pay_lock); |
92 | int area, debug_entry_t *entry, char *out_buf) | ||
93 | { | ||
94 | struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry); | ||
95 | struct timespec t; | ||
96 | char *p = out_buf; | ||
97 | |||
98 | if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) { | ||
99 | stck_to_timespec(entry->id.stck, &t); | ||
100 | zfcp_dbf_out(&p, "timestamp", "%011lu:%06lu", | ||
101 | t.tv_sec, t.tv_nsec); | ||
102 | zfcp_dbf_out(&p, "cpu", "%02i", entry->id.fields.cpuid); | ||
103 | } else { | ||
104 | zfcp_dbf_outd(&p, "", dump->data, dump->size, dump->offset, | ||
105 | dump->total_size); | ||
106 | if ((dump->offset + dump->size) == dump->total_size) | ||
107 | p += sprintf(p, "\n"); | ||
108 | } | ||
109 | return p - out_buf; | ||
110 | } | 53 | } |
111 | 54 | ||
112 | void _zfcp_dbf_hba_fsf_response(const char *tag2, int level, | 55 | /** |
113 | struct zfcp_fsf_req *fsf_req, | 56 | * zfcp_dbf_hba_fsf_res - trace event for fsf responses |
114 | struct zfcp_dbf *dbf) | 57 | * @tag: tag indicating which kind of unsolicited status has been received |
58 | * @req: request for which a response was received | ||
59 | */ | ||
60 | void zfcp_dbf_hba_fsf_res(char *tag, struct zfcp_fsf_req *req) | ||
115 | { | 61 | { |
116 | struct fsf_qtcb *qtcb = fsf_req->qtcb; | 62 | struct zfcp_dbf *dbf = req->adapter->dbf; |
117 | union fsf_prot_status_qual *prot_status_qual = | 63 | struct fsf_qtcb_prefix *q_pref = &req->qtcb->prefix; |
118 | &qtcb->prefix.prot_status_qual; | 64 | struct fsf_qtcb_header *q_head = &req->qtcb->header; |
119 | union fsf_status_qual *fsf_status_qual = &qtcb->header.fsf_status_qual; | 65 | struct zfcp_dbf_hba *rec = &dbf->hba_buf; |
120 | struct scsi_cmnd *scsi_cmnd; | ||
121 | struct zfcp_port *port; | ||
122 | struct zfcp_unit *unit; | ||
123 | struct zfcp_send_els *send_els; | ||
124 | struct zfcp_dbf_hba_record *rec = &dbf->hba_buf; | ||
125 | struct zfcp_dbf_hba_record_response *response = &rec->u.response; | ||
126 | unsigned long flags; | 66 | unsigned long flags; |
127 | 67 | ||
128 | spin_lock_irqsave(&dbf->hba_lock, flags); | 68 | spin_lock_irqsave(&dbf->hba_lock, flags); |
129 | memset(rec, 0, sizeof(*rec)); | 69 | memset(rec, 0, sizeof(*rec)); |
130 | strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE); | ||
131 | strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE); | ||
132 | |||
133 | response->fsf_command = fsf_req->fsf_command; | ||
134 | response->fsf_reqid = fsf_req->req_id; | ||
135 | response->fsf_seqno = fsf_req->seq_no; | ||
136 | response->fsf_issued = fsf_req->issued; | ||
137 | response->fsf_prot_status = qtcb->prefix.prot_status; | ||
138 | response->fsf_status = qtcb->header.fsf_status; | ||
139 | memcpy(response->fsf_prot_status_qual, | ||
140 | prot_status_qual, FSF_PROT_STATUS_QUAL_SIZE); | ||
141 | memcpy(response->fsf_status_qual, | ||
142 | fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE); | ||
143 | response->fsf_req_status = fsf_req->status; | ||
144 | response->sbal_first = fsf_req->qdio_req.sbal_first; | ||
145 | response->sbal_last = fsf_req->qdio_req.sbal_last; | ||
146 | response->sbal_response = fsf_req->qdio_req.sbal_response; | ||
147 | response->pool = fsf_req->pool != NULL; | ||
148 | response->erp_action = (unsigned long)fsf_req->erp_action; | ||
149 | |||
150 | switch (fsf_req->fsf_command) { | ||
151 | case FSF_QTCB_FCP_CMND: | ||
152 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) | ||
153 | break; | ||
154 | scsi_cmnd = (struct scsi_cmnd *)fsf_req->data; | ||
155 | if (scsi_cmnd) { | ||
156 | response->u.fcp.cmnd = (unsigned long)scsi_cmnd; | ||
157 | response->u.fcp.serial = scsi_cmnd->serial_number; | ||
158 | response->u.fcp.data_dir = | ||
159 | qtcb->bottom.io.data_direction; | ||
160 | } | ||
161 | break; | ||
162 | |||
163 | case FSF_QTCB_OPEN_PORT_WITH_DID: | ||
164 | case FSF_QTCB_CLOSE_PORT: | ||
165 | case FSF_QTCB_CLOSE_PHYSICAL_PORT: | ||
166 | port = (struct zfcp_port *)fsf_req->data; | ||
167 | response->u.port.wwpn = port->wwpn; | ||
168 | response->u.port.d_id = port->d_id; | ||
169 | response->u.port.port_handle = qtcb->header.port_handle; | ||
170 | break; | ||
171 | |||
172 | case FSF_QTCB_OPEN_LUN: | ||
173 | case FSF_QTCB_CLOSE_LUN: | ||
174 | unit = (struct zfcp_unit *)fsf_req->data; | ||
175 | port = unit->port; | ||
176 | response->u.unit.wwpn = port->wwpn; | ||
177 | response->u.unit.fcp_lun = unit->fcp_lun; | ||
178 | response->u.unit.port_handle = qtcb->header.port_handle; | ||
179 | response->u.unit.lun_handle = qtcb->header.lun_handle; | ||
180 | break; | ||
181 | |||
182 | case FSF_QTCB_SEND_ELS: | ||
183 | send_els = (struct zfcp_send_els *)fsf_req->data; | ||
184 | response->u.els.d_id = ntoh24(qtcb->bottom.support.d_id); | ||
185 | break; | ||
186 | |||
187 | case FSF_QTCB_ABORT_FCP_CMND: | ||
188 | case FSF_QTCB_SEND_GENERIC: | ||
189 | case FSF_QTCB_EXCHANGE_CONFIG_DATA: | ||
190 | case FSF_QTCB_EXCHANGE_PORT_DATA: | ||
191 | case FSF_QTCB_DOWNLOAD_CONTROL_FILE: | ||
192 | case FSF_QTCB_UPLOAD_CONTROL_FILE: | ||
193 | break; | ||
194 | } | ||
195 | |||
196 | debug_event(dbf->hba, level, rec, sizeof(*rec)); | ||
197 | 70 | ||
198 | /* have fcp channel microcode fixed to use as little as possible */ | 71 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); |
199 | if (fsf_req->fsf_command != FSF_QTCB_FCP_CMND) { | 72 | rec->id = ZFCP_DBF_HBA_RES; |
200 | /* adjust length skipping trailing zeros */ | 73 | rec->fsf_req_id = req->req_id; |
201 | char *buf = (char *)qtcb + qtcb->header.log_start; | 74 | rec->fsf_req_status = req->status; |
202 | int len = qtcb->header.log_length; | 75 | rec->fsf_cmd = req->fsf_command; |
203 | for (; len && !buf[len - 1]; len--); | 76 | rec->fsf_seq_no = req->seq_no; |
204 | zfcp_dbf_hexdump(dbf->hba, rec, sizeof(*rec), level, buf, | 77 | rec->u.res.req_issued = req->issued; |
205 | len); | 78 | rec->u.res.prot_status = q_pref->prot_status; |
79 | rec->u.res.fsf_status = q_head->fsf_status; | ||
80 | |||
81 | memcpy(rec->u.res.prot_status_qual, &q_pref->prot_status_qual, | ||
82 | FSF_PROT_STATUS_QUAL_SIZE); | ||
83 | memcpy(rec->u.res.fsf_status_qual, &q_head->fsf_status_qual, | ||
84 | FSF_STATUS_QUALIFIER_SIZE); | ||
85 | |||
86 | if (req->fsf_command != FSF_QTCB_FCP_CMND) { | ||
87 | rec->pl_len = q_head->log_length; | ||
88 | zfcp_dbf_pl_write(dbf, (char *)q_pref + q_head->log_start, | ||
89 | rec->pl_len, "fsf_res", req->req_id); | ||
206 | } | 90 | } |
207 | 91 | ||
208 | spin_unlock_irqrestore(&dbf->hba_lock, flags); | 92 | debug_event(dbf->hba, 1, rec, sizeof(*rec)); |
209 | } | ||
210 | |||
211 | void _zfcp_dbf_hba_fsf_unsol(const char *tag, int level, struct zfcp_dbf *dbf, | ||
212 | struct fsf_status_read_buffer *status_buffer) | ||
213 | { | ||
214 | struct zfcp_dbf_hba_record *rec = &dbf->hba_buf; | ||
215 | unsigned long flags; | ||
216 | |||
217 | spin_lock_irqsave(&dbf->hba_lock, flags); | ||
218 | memset(rec, 0, sizeof(*rec)); | ||
219 | strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE); | ||
220 | strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE); | ||
221 | |||
222 | rec->u.status.failed = atomic_read(&dbf->adapter->stat_miss); | ||
223 | if (status_buffer != NULL) { | ||
224 | rec->u.status.status_type = status_buffer->status_type; | ||
225 | rec->u.status.status_subtype = status_buffer->status_subtype; | ||
226 | memcpy(&rec->u.status.queue_designator, | ||
227 | &status_buffer->queue_designator, | ||
228 | sizeof(struct fsf_queue_designator)); | ||
229 | |||
230 | switch (status_buffer->status_type) { | ||
231 | case FSF_STATUS_READ_SENSE_DATA_AVAIL: | ||
232 | rec->u.status.payload_size = | ||
233 | ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL; | ||
234 | break; | ||
235 | |||
236 | case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: | ||
237 | rec->u.status.payload_size = | ||
238 | ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD; | ||
239 | break; | ||
240 | |||
241 | case FSF_STATUS_READ_LINK_DOWN: | ||
242 | switch (status_buffer->status_subtype) { | ||
243 | case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: | ||
244 | case FSF_STATUS_READ_SUB_FDISC_FAILED: | ||
245 | rec->u.status.payload_size = | ||
246 | sizeof(struct fsf_link_down_info); | ||
247 | } | ||
248 | break; | ||
249 | |||
250 | case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: | ||
251 | rec->u.status.payload_size = | ||
252 | ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT; | ||
253 | break; | ||
254 | } | ||
255 | memcpy(&rec->u.status.payload, | ||
256 | &status_buffer->payload, rec->u.status.payload_size); | ||
257 | } | ||
258 | |||
259 | debug_event(dbf->hba, level, rec, sizeof(*rec)); | ||
260 | spin_unlock_irqrestore(&dbf->hba_lock, flags); | 93 | spin_unlock_irqrestore(&dbf->hba_lock, flags); |
261 | } | 94 | } |
262 | 95 | ||
263 | /** | 96 | /** |
264 | * zfcp_dbf_hba_qdio - trace event for QDIO related failure | 97 | * zfcp_dbf_hba_fsf_uss - trace event for an unsolicited status buffer |
265 | * @qdio: qdio structure affected by this QDIO related event | 98 | * @tag: tag indicating which kind of unsolicited status has been received |
266 | * @qdio_error: as passed by qdio module | 99 | * @req: request providing the unsolicited status |
267 | * @sbal_index: first buffer with error condition, as passed by qdio module | ||
268 | * @sbal_count: number of buffers affected, as passed by qdio module | ||
269 | */ | 100 | */ |
270 | void zfcp_dbf_hba_qdio(struct zfcp_dbf *dbf, unsigned int qdio_error, | 101 | void zfcp_dbf_hba_fsf_uss(char *tag, struct zfcp_fsf_req *req) |
271 | int sbal_index, int sbal_count) | ||
272 | { | 102 | { |
273 | struct zfcp_dbf_hba_record *r = &dbf->hba_buf; | 103 | struct zfcp_dbf *dbf = req->adapter->dbf; |
104 | struct fsf_status_read_buffer *srb = req->data; | ||
105 | struct zfcp_dbf_hba *rec = &dbf->hba_buf; | ||
274 | unsigned long flags; | 106 | unsigned long flags; |
275 | 107 | ||
276 | spin_lock_irqsave(&dbf->hba_lock, flags); | 108 | spin_lock_irqsave(&dbf->hba_lock, flags); |
277 | memset(r, 0, sizeof(*r)); | 109 | memset(rec, 0, sizeof(*rec)); |
278 | strncpy(r->tag, "qdio", ZFCP_DBF_TAG_SIZE); | 110 | |
279 | r->u.qdio.qdio_error = qdio_error; | 111 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); |
280 | r->u.qdio.sbal_index = sbal_index; | 112 | rec->id = ZFCP_DBF_HBA_USS; |
281 | r->u.qdio.sbal_count = sbal_count; | 113 | rec->fsf_req_id = req->req_id; |
282 | debug_event(dbf->hba, 0, r, sizeof(*r)); | 114 | rec->fsf_req_status = req->status; |
115 | rec->fsf_cmd = req->fsf_command; | ||
116 | |||
117 | if (!srb) | ||
118 | goto log; | ||
119 | |||
120 | rec->u.uss.status_type = srb->status_type; | ||
121 | rec->u.uss.status_subtype = srb->status_subtype; | ||
122 | rec->u.uss.d_id = ntoh24(srb->d_id); | ||
123 | rec->u.uss.lun = srb->fcp_lun; | ||
124 | memcpy(&rec->u.uss.queue_designator, &srb->queue_designator, | ||
125 | sizeof(rec->u.uss.queue_designator)); | ||
126 | |||
127 | /* status read buffer payload length */ | ||
128 | rec->pl_len = (!srb->length) ? 0 : srb->length - | ||
129 | offsetof(struct fsf_status_read_buffer, payload); | ||
130 | |||
131 | if (rec->pl_len) | ||
132 | zfcp_dbf_pl_write(dbf, srb->payload.data, rec->pl_len, | ||
133 | "fsf_uss", req->req_id); | ||
134 | log: | ||
135 | debug_event(dbf->hba, 2, rec, sizeof(*rec)); | ||
283 | spin_unlock_irqrestore(&dbf->hba_lock, flags); | 136 | spin_unlock_irqrestore(&dbf->hba_lock, flags); |
284 | } | 137 | } |
285 | 138 | ||
286 | /** | 139 | /** |
287 | * zfcp_dbf_hba_berr - trace event for bit error threshold | 140 | * zfcp_dbf_hba_bit_err - trace event for bit error conditions |
288 | * @dbf: dbf structure affected by this QDIO related event | 141 | * @tag: tag indicating which kind of unsolicited status has been received |
289 | * @req: fsf request | 142 | * @req: request which caused the bit_error condition |
290 | */ | 143 | */ |
291 | void zfcp_dbf_hba_berr(struct zfcp_dbf *dbf, struct zfcp_fsf_req *req) | 144 | void zfcp_dbf_hba_bit_err(char *tag, struct zfcp_fsf_req *req) |
292 | { | 145 | { |
293 | struct zfcp_dbf_hba_record *r = &dbf->hba_buf; | 146 | struct zfcp_dbf *dbf = req->adapter->dbf; |
147 | struct zfcp_dbf_hba *rec = &dbf->hba_buf; | ||
294 | struct fsf_status_read_buffer *sr_buf = req->data; | 148 | struct fsf_status_read_buffer *sr_buf = req->data; |
295 | struct fsf_bit_error_payload *err = &sr_buf->payload.bit_error; | ||
296 | unsigned long flags; | 149 | unsigned long flags; |
297 | 150 | ||
298 | spin_lock_irqsave(&dbf->hba_lock, flags); | 151 | spin_lock_irqsave(&dbf->hba_lock, flags); |
299 | memset(r, 0, sizeof(*r)); | 152 | memset(rec, 0, sizeof(*rec)); |
300 | strncpy(r->tag, "berr", ZFCP_DBF_TAG_SIZE); | ||
301 | memcpy(&r->u.berr, err, sizeof(struct fsf_bit_error_payload)); | ||
302 | debug_event(dbf->hba, 0, r, sizeof(*r)); | ||
303 | spin_unlock_irqrestore(&dbf->hba_lock, flags); | ||
304 | } | ||
305 | static void zfcp_dbf_hba_view_response(char **p, | ||
306 | struct zfcp_dbf_hba_record_response *r) | ||
307 | { | ||
308 | struct timespec t; | ||
309 | |||
310 | zfcp_dbf_out(p, "fsf_command", "0x%08x", r->fsf_command); | ||
311 | zfcp_dbf_out(p, "fsf_reqid", "0x%0Lx", r->fsf_reqid); | ||
312 | zfcp_dbf_out(p, "fsf_seqno", "0x%08x", r->fsf_seqno); | ||
313 | stck_to_timespec(r->fsf_issued, &t); | ||
314 | zfcp_dbf_out(p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec); | ||
315 | zfcp_dbf_out(p, "fsf_prot_status", "0x%08x", r->fsf_prot_status); | ||
316 | zfcp_dbf_out(p, "fsf_status", "0x%08x", r->fsf_status); | ||
317 | zfcp_dbf_outd(p, "fsf_prot_status_qual", r->fsf_prot_status_qual, | ||
318 | FSF_PROT_STATUS_QUAL_SIZE, 0, FSF_PROT_STATUS_QUAL_SIZE); | ||
319 | zfcp_dbf_outd(p, "fsf_status_qual", r->fsf_status_qual, | ||
320 | FSF_STATUS_QUALIFIER_SIZE, 0, FSF_STATUS_QUALIFIER_SIZE); | ||
321 | zfcp_dbf_out(p, "fsf_req_status", "0x%08x", r->fsf_req_status); | ||
322 | zfcp_dbf_out(p, "sbal_first", "0x%02x", r->sbal_first); | ||
323 | zfcp_dbf_out(p, "sbal_last", "0x%02x", r->sbal_last); | ||
324 | zfcp_dbf_out(p, "sbal_response", "0x%02x", r->sbal_response); | ||
325 | zfcp_dbf_out(p, "pool", "0x%02x", r->pool); | ||
326 | |||
327 | switch (r->fsf_command) { | ||
328 | case FSF_QTCB_FCP_CMND: | ||
329 | if (r->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) | ||
330 | break; | ||
331 | zfcp_dbf_out(p, "data_direction", "0x%04x", r->u.fcp.data_dir); | ||
332 | zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd); | ||
333 | zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial); | ||
334 | *p += sprintf(*p, "\n"); | ||
335 | break; | ||
336 | |||
337 | case FSF_QTCB_OPEN_PORT_WITH_DID: | ||
338 | case FSF_QTCB_CLOSE_PORT: | ||
339 | case FSF_QTCB_CLOSE_PHYSICAL_PORT: | ||
340 | zfcp_dbf_out(p, "wwpn", "0x%016Lx", r->u.port.wwpn); | ||
341 | zfcp_dbf_out(p, "d_id", "0x%06x", r->u.port.d_id); | ||
342 | zfcp_dbf_out(p, "port_handle", "0x%08x", r->u.port.port_handle); | ||
343 | break; | ||
344 | |||
345 | case FSF_QTCB_OPEN_LUN: | ||
346 | case FSF_QTCB_CLOSE_LUN: | ||
347 | zfcp_dbf_out(p, "wwpn", "0x%016Lx", r->u.unit.wwpn); | ||
348 | zfcp_dbf_out(p, "fcp_lun", "0x%016Lx", r->u.unit.fcp_lun); | ||
349 | zfcp_dbf_out(p, "port_handle", "0x%08x", r->u.unit.port_handle); | ||
350 | zfcp_dbf_out(p, "lun_handle", "0x%08x", r->u.unit.lun_handle); | ||
351 | break; | ||
352 | |||
353 | case FSF_QTCB_SEND_ELS: | ||
354 | zfcp_dbf_out(p, "d_id", "0x%06x", r->u.els.d_id); | ||
355 | break; | ||
356 | |||
357 | case FSF_QTCB_ABORT_FCP_CMND: | ||
358 | case FSF_QTCB_SEND_GENERIC: | ||
359 | case FSF_QTCB_EXCHANGE_CONFIG_DATA: | ||
360 | case FSF_QTCB_EXCHANGE_PORT_DATA: | ||
361 | case FSF_QTCB_DOWNLOAD_CONTROL_FILE: | ||
362 | case FSF_QTCB_UPLOAD_CONTROL_FILE: | ||
363 | break; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | static void zfcp_dbf_hba_view_status(char **p, | ||
368 | struct zfcp_dbf_hba_record_status *r) | ||
369 | { | ||
370 | zfcp_dbf_out(p, "failed", "0x%02x", r->failed); | ||
371 | zfcp_dbf_out(p, "status_type", "0x%08x", r->status_type); | ||
372 | zfcp_dbf_out(p, "status_subtype", "0x%08x", r->status_subtype); | ||
373 | zfcp_dbf_outd(p, "queue_designator", (char *)&r->queue_designator, | ||
374 | sizeof(struct fsf_queue_designator), 0, | ||
375 | sizeof(struct fsf_queue_designator)); | ||
376 | zfcp_dbf_outd(p, "payload", (char *)&r->payload, r->payload_size, 0, | ||
377 | r->payload_size); | ||
378 | } | ||
379 | |||
380 | static void zfcp_dbf_hba_view_qdio(char **p, struct zfcp_dbf_hba_record_qdio *r) | ||
381 | { | ||
382 | zfcp_dbf_out(p, "qdio_error", "0x%08x", r->qdio_error); | ||
383 | zfcp_dbf_out(p, "sbal_index", "0x%02x", r->sbal_index); | ||
384 | zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count); | ||
385 | } | ||
386 | 153 | ||
387 | static void zfcp_dbf_hba_view_berr(char **p, struct fsf_bit_error_payload *r) | 154 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); |
388 | { | 155 | rec->id = ZFCP_DBF_HBA_BIT; |
389 | zfcp_dbf_out(p, "link_failures", "%d", r->link_failure_error_count); | 156 | rec->fsf_req_id = req->req_id; |
390 | zfcp_dbf_out(p, "loss_of_sync_err", "%d", r->loss_of_sync_error_count); | 157 | rec->fsf_req_status = req->status; |
391 | zfcp_dbf_out(p, "loss_of_sig_err", "%d", r->loss_of_signal_error_count); | 158 | rec->fsf_cmd = req->fsf_command; |
392 | zfcp_dbf_out(p, "prim_seq_err", "%d", | 159 | memcpy(&rec->u.be, &sr_buf->payload.bit_error, |
393 | r->primitive_sequence_error_count); | 160 | sizeof(struct fsf_bit_error_payload)); |
394 | zfcp_dbf_out(p, "inval_trans_word_err", "%d", | ||
395 | r->invalid_transmission_word_error_count); | ||
396 | zfcp_dbf_out(p, "CRC_errors", "%d", r->crc_error_count); | ||
397 | zfcp_dbf_out(p, "prim_seq_event_to", "%d", | ||
398 | r->primitive_sequence_event_timeout_count); | ||
399 | zfcp_dbf_out(p, "elast_buf_overrun_err", "%d", | ||
400 | r->elastic_buffer_overrun_error_count); | ||
401 | zfcp_dbf_out(p, "adv_rec_buf2buf_cred", "%d", | ||
402 | r->advertised_receive_b2b_credit); | ||
403 | zfcp_dbf_out(p, "curr_rec_buf2buf_cred", "%d", | ||
404 | r->current_receive_b2b_credit); | ||
405 | zfcp_dbf_out(p, "adv_trans_buf2buf_cred", "%d", | ||
406 | r->advertised_transmit_b2b_credit); | ||
407 | zfcp_dbf_out(p, "curr_trans_buf2buf_cred", "%d", | ||
408 | r->current_transmit_b2b_credit); | ||
409 | } | ||
410 | 161 | ||
411 | static int zfcp_dbf_hba_view_format(debug_info_t *id, struct debug_view *view, | 162 | debug_event(dbf->hba, 1, rec, sizeof(*rec)); |
412 | char *out_buf, const char *in_buf) | 163 | spin_unlock_irqrestore(&dbf->hba_lock, flags); |
413 | { | ||
414 | struct zfcp_dbf_hba_record *r = (struct zfcp_dbf_hba_record *)in_buf; | ||
415 | char *p = out_buf; | ||
416 | |||
417 | if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) | ||
418 | return 0; | ||
419 | |||
420 | zfcp_dbf_tag(&p, "tag", r->tag); | ||
421 | if (isalpha(r->tag2[0])) | ||
422 | zfcp_dbf_tag(&p, "tag2", r->tag2); | ||
423 | |||
424 | if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0) | ||
425 | zfcp_dbf_hba_view_response(&p, &r->u.response); | ||
426 | else if (strncmp(r->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0) | ||
427 | zfcp_dbf_hba_view_status(&p, &r->u.status); | ||
428 | else if (strncmp(r->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0) | ||
429 | zfcp_dbf_hba_view_qdio(&p, &r->u.qdio); | ||
430 | else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0) | ||
431 | zfcp_dbf_hba_view_berr(&p, &r->u.berr); | ||
432 | |||
433 | if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) != 0) | ||
434 | p += sprintf(p, "\n"); | ||
435 | return p - out_buf; | ||
436 | } | 164 | } |
437 | 165 | ||
438 | static struct debug_view zfcp_dbf_hba_view = { | 166 | static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, |
439 | .name = "structured", | 167 | struct zfcp_adapter *adapter, |
440 | .header_proc = zfcp_dbf_view_header, | 168 | struct zfcp_port *port, |
441 | .format_proc = zfcp_dbf_hba_view_format, | 169 | struct scsi_device *sdev) |
442 | }; | ||
443 | |||
444 | static const char *zfcp_dbf_rec_tags[] = { | ||
445 | [ZFCP_REC_DBF_ID_THREAD] = "thread", | ||
446 | [ZFCP_REC_DBF_ID_TARGET] = "target", | ||
447 | [ZFCP_REC_DBF_ID_TRIGGER] = "trigger", | ||
448 | [ZFCP_REC_DBF_ID_ACTION] = "action", | ||
449 | }; | ||
450 | |||
451 | static int zfcp_dbf_rec_view_format(debug_info_t *id, struct debug_view *view, | ||
452 | char *buf, const char *_rec) | ||
453 | { | 170 | { |
454 | struct zfcp_dbf_rec_record *r = (struct zfcp_dbf_rec_record *)_rec; | 171 | rec->adapter_status = atomic_read(&adapter->status); |
455 | char *p = buf; | 172 | if (port) { |
456 | char hint[ZFCP_DBF_ID_SIZE + 1]; | 173 | rec->port_status = atomic_read(&port->status); |
457 | 174 | rec->wwpn = port->wwpn; | |
458 | memcpy(hint, r->id2, ZFCP_DBF_ID_SIZE); | 175 | rec->d_id = port->d_id; |
459 | hint[ZFCP_DBF_ID_SIZE] = 0; | 176 | } |
460 | zfcp_dbf_outs(&p, "tag", zfcp_dbf_rec_tags[r->id]); | 177 | if (sdev) { |
461 | zfcp_dbf_outs(&p, "hint", hint); | 178 | rec->lun_status = atomic_read(&sdev_to_zfcp(sdev)->status); |
462 | switch (r->id) { | 179 | rec->lun = zfcp_scsi_dev_lun(sdev); |
463 | case ZFCP_REC_DBF_ID_THREAD: | ||
464 | zfcp_dbf_out(&p, "total", "%d", r->u.thread.total); | ||
465 | zfcp_dbf_out(&p, "ready", "%d", r->u.thread.ready); | ||
466 | zfcp_dbf_out(&p, "running", "%d", r->u.thread.running); | ||
467 | break; | ||
468 | case ZFCP_REC_DBF_ID_TARGET: | ||
469 | zfcp_dbf_out(&p, "reference", "0x%016Lx", r->u.target.ref); | ||
470 | zfcp_dbf_out(&p, "status", "0x%08x", r->u.target.status); | ||
471 | zfcp_dbf_out(&p, "erp_count", "%d", r->u.target.erp_count); | ||
472 | zfcp_dbf_out(&p, "d_id", "0x%06x", r->u.target.d_id); | ||
473 | zfcp_dbf_out(&p, "wwpn", "0x%016Lx", r->u.target.wwpn); | ||
474 | zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.target.fcp_lun); | ||
475 | break; | ||
476 | case ZFCP_REC_DBF_ID_TRIGGER: | ||
477 | zfcp_dbf_out(&p, "reference", "0x%016Lx", r->u.trigger.ref); | ||
478 | zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.trigger.action); | ||
479 | zfcp_dbf_out(&p, "requested", "%d", r->u.trigger.want); | ||
480 | zfcp_dbf_out(&p, "executed", "%d", r->u.trigger.need); | ||
481 | zfcp_dbf_out(&p, "wwpn", "0x%016Lx", r->u.trigger.wwpn); | ||
482 | zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.trigger.fcp_lun); | ||
483 | zfcp_dbf_out(&p, "adapter_status", "0x%08x", r->u.trigger.as); | ||
484 | zfcp_dbf_out(&p, "port_status", "0x%08x", r->u.trigger.ps); | ||
485 | zfcp_dbf_out(&p, "unit_status", "0x%08x", r->u.trigger.us); | ||
486 | break; | ||
487 | case ZFCP_REC_DBF_ID_ACTION: | ||
488 | zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.action.action); | ||
489 | zfcp_dbf_out(&p, "fsf_req", "0x%016Lx", r->u.action.fsf_req); | ||
490 | zfcp_dbf_out(&p, "status", "0x%08Lx", r->u.action.status); | ||
491 | zfcp_dbf_out(&p, "step", "0x%08Lx", r->u.action.step); | ||
492 | break; | ||
493 | } | 180 | } |
494 | p += sprintf(p, "\n"); | ||
495 | return p - buf; | ||
496 | } | 181 | } |
497 | 182 | ||
498 | static struct debug_view zfcp_dbf_rec_view = { | ||
499 | .name = "structured", | ||
500 | .header_proc = zfcp_dbf_view_header, | ||
501 | .format_proc = zfcp_dbf_rec_view_format, | ||
502 | }; | ||
503 | |||
504 | /** | 183 | /** |
505 | * zfcp_dbf_rec_thread - trace event related to recovery thread operation | 184 | * zfcp_dbf_rec_trig - trace event related to triggered recovery |
506 | * @id2: identifier for event | 185 | * @tag: identifier for event |
507 | * @dbf: reference to dbf structure | 186 | * @adapter: adapter on which the erp_action should run |
508 | * This function assumes that the caller is holding erp_lock. | 187 | * @port: remote port involved in the erp_action |
188 | * @sdev: scsi device involved in the erp_action | ||
189 | * @want: wanted erp_action | ||
190 | * @need: required erp_action | ||
191 | * | ||
192 | * The adapter->erp_lock has to be held. | ||
509 | */ | 193 | */ |
510 | void zfcp_dbf_rec_thread(char *id2, struct zfcp_dbf *dbf) | 194 | void zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter, |
195 | struct zfcp_port *port, struct scsi_device *sdev, | ||
196 | u8 want, u8 need) | ||
511 | { | 197 | { |
512 | struct zfcp_adapter *adapter = dbf->adapter; | 198 | struct zfcp_dbf *dbf = adapter->dbf; |
513 | struct zfcp_dbf_rec_record *r = &dbf->rec_buf; | 199 | struct zfcp_dbf_rec *rec = &dbf->rec_buf; |
514 | unsigned long flags = 0; | ||
515 | struct list_head *entry; | 200 | struct list_head *entry; |
516 | unsigned ready = 0, running = 0, total; | ||
517 | |||
518 | list_for_each(entry, &adapter->erp_ready_head) | ||
519 | ready++; | ||
520 | list_for_each(entry, &adapter->erp_running_head) | ||
521 | running++; | ||
522 | total = adapter->erp_total_count; | ||
523 | |||
524 | spin_lock_irqsave(&dbf->rec_lock, flags); | ||
525 | memset(r, 0, sizeof(*r)); | ||
526 | r->id = ZFCP_REC_DBF_ID_THREAD; | ||
527 | memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE); | ||
528 | r->u.thread.total = total; | ||
529 | r->u.thread.ready = ready; | ||
530 | r->u.thread.running = running; | ||
531 | debug_event(dbf->rec, 6, r, sizeof(*r)); | ||
532 | spin_unlock_irqrestore(&dbf->rec_lock, flags); | ||
533 | } | ||
534 | |||
535 | /** | ||
536 | * zfcp_dbf_rec_thread - trace event related to recovery thread operation | ||
537 | * @id2: identifier for event | ||
538 | * @adapter: adapter | ||
539 | * This function assumes that the caller does not hold erp_lock. | ||
540 | */ | ||
541 | void zfcp_dbf_rec_thread_lock(char *id2, struct zfcp_dbf *dbf) | ||
542 | { | ||
543 | struct zfcp_adapter *adapter = dbf->adapter; | ||
544 | unsigned long flags; | ||
545 | |||
546 | read_lock_irqsave(&adapter->erp_lock, flags); | ||
547 | zfcp_dbf_rec_thread(id2, dbf); | ||
548 | read_unlock_irqrestore(&adapter->erp_lock, flags); | ||
549 | } | ||
550 | |||
551 | static void zfcp_dbf_rec_target(char *id2, void *ref, struct zfcp_dbf *dbf, | ||
552 | atomic_t *status, atomic_t *erp_count, u64 wwpn, | ||
553 | u32 d_id, u64 fcp_lun) | ||
554 | { | ||
555 | struct zfcp_dbf_rec_record *r = &dbf->rec_buf; | ||
556 | unsigned long flags; | 201 | unsigned long flags; |
557 | 202 | ||
558 | spin_lock_irqsave(&dbf->rec_lock, flags); | 203 | spin_lock_irqsave(&dbf->rec_lock, flags); |
559 | memset(r, 0, sizeof(*r)); | 204 | memset(rec, 0, sizeof(*rec)); |
560 | r->id = ZFCP_REC_DBF_ID_TARGET; | ||
561 | memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE); | ||
562 | r->u.target.ref = (unsigned long)ref; | ||
563 | r->u.target.status = atomic_read(status); | ||
564 | r->u.target.wwpn = wwpn; | ||
565 | r->u.target.d_id = d_id; | ||
566 | r->u.target.fcp_lun = fcp_lun; | ||
567 | r->u.target.erp_count = atomic_read(erp_count); | ||
568 | debug_event(dbf->rec, 3, r, sizeof(*r)); | ||
569 | spin_unlock_irqrestore(&dbf->rec_lock, flags); | ||
570 | } | ||
571 | |||
572 | /** | ||
573 | * zfcp_dbf_rec_adapter - trace event for adapter state change | ||
574 | * @id: identifier for trigger of state change | ||
575 | * @ref: additional reference (e.g. request) | ||
576 | * @dbf: reference to dbf structure | ||
577 | */ | ||
578 | void zfcp_dbf_rec_adapter(char *id, void *ref, struct zfcp_dbf *dbf) | ||
579 | { | ||
580 | struct zfcp_adapter *adapter = dbf->adapter; | ||
581 | |||
582 | zfcp_dbf_rec_target(id, ref, dbf, &adapter->status, | ||
583 | &adapter->erp_counter, 0, 0, | ||
584 | ZFCP_DBF_INVALID_LUN); | ||
585 | } | ||
586 | |||
587 | /** | ||
588 | * zfcp_dbf_rec_port - trace event for port state change | ||
589 | * @id: identifier for trigger of state change | ||
590 | * @ref: additional reference (e.g. request) | ||
591 | * @port: port | ||
592 | */ | ||
593 | void zfcp_dbf_rec_port(char *id, void *ref, struct zfcp_port *port) | ||
594 | { | ||
595 | struct zfcp_dbf *dbf = port->adapter->dbf; | ||
596 | 205 | ||
597 | zfcp_dbf_rec_target(id, ref, dbf, &port->status, | 206 | rec->id = ZFCP_DBF_REC_TRIG; |
598 | &port->erp_counter, port->wwpn, port->d_id, | 207 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); |
599 | ZFCP_DBF_INVALID_LUN); | 208 | zfcp_dbf_set_common(rec, adapter, port, sdev); |
600 | } | ||
601 | 209 | ||
602 | /** | 210 | list_for_each(entry, &adapter->erp_ready_head) |
603 | * zfcp_dbf_rec_unit - trace event for unit state change | 211 | rec->u.trig.ready++; |
604 | * @id: identifier for trigger of state change | ||
605 | * @ref: additional reference (e.g. request) | ||
606 | * @unit: unit | ||
607 | */ | ||
608 | void zfcp_dbf_rec_unit(char *id, void *ref, struct zfcp_unit *unit) | ||
609 | { | ||
610 | struct zfcp_port *port = unit->port; | ||
611 | struct zfcp_dbf *dbf = port->adapter->dbf; | ||
612 | 212 | ||
613 | zfcp_dbf_rec_target(id, ref, dbf, &unit->status, | 213 | list_for_each(entry, &adapter->erp_running_head) |
614 | &unit->erp_counter, port->wwpn, port->d_id, | 214 | rec->u.trig.running++; |
615 | unit->fcp_lun); | ||
616 | } | ||
617 | 215 | ||
618 | /** | 216 | rec->u.trig.want = want; |
619 | * zfcp_dbf_rec_trigger - trace event for triggered error recovery | 217 | rec->u.trig.need = need; |
620 | * @id2: identifier for error recovery trigger | ||
621 | * @ref: additional reference (e.g. request) | ||
622 | * @want: originally requested error recovery action | ||
623 | * @need: error recovery action actually initiated | ||
624 | * @action: address of error recovery action struct | ||
625 | * @adapter: adapter | ||
626 | * @port: port | ||
627 | * @unit: unit | ||
628 | */ | ||
629 | void zfcp_dbf_rec_trigger(char *id2, void *ref, u8 want, u8 need, void *action, | ||
630 | struct zfcp_adapter *adapter, struct zfcp_port *port, | ||
631 | struct zfcp_unit *unit) | ||
632 | { | ||
633 | struct zfcp_dbf *dbf = adapter->dbf; | ||
634 | struct zfcp_dbf_rec_record *r = &dbf->rec_buf; | ||
635 | unsigned long flags; | ||
636 | 218 | ||
637 | spin_lock_irqsave(&dbf->rec_lock, flags); | 219 | debug_event(dbf->rec, 1, rec, sizeof(*rec)); |
638 | memset(r, 0, sizeof(*r)); | ||
639 | r->id = ZFCP_REC_DBF_ID_TRIGGER; | ||
640 | memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE); | ||
641 | r->u.trigger.ref = (unsigned long)ref; | ||
642 | r->u.trigger.want = want; | ||
643 | r->u.trigger.need = need; | ||
644 | r->u.trigger.action = (unsigned long)action; | ||
645 | r->u.trigger.as = atomic_read(&adapter->status); | ||
646 | if (port) { | ||
647 | r->u.trigger.ps = atomic_read(&port->status); | ||
648 | r->u.trigger.wwpn = port->wwpn; | ||
649 | } | ||
650 | if (unit) | ||
651 | r->u.trigger.us = atomic_read(&unit->status); | ||
652 | r->u.trigger.fcp_lun = unit ? unit->fcp_lun : ZFCP_DBF_INVALID_LUN; | ||
653 | debug_event(dbf->rec, action ? 1 : 4, r, sizeof(*r)); | ||
654 | spin_unlock_irqrestore(&dbf->rec_lock, flags); | 220 | spin_unlock_irqrestore(&dbf->rec_lock, flags); |
655 | } | 221 | } |
656 | 222 | ||
223 | |||
657 | /** | 224 | /** |
658 | * zfcp_dbf_rec_action - trace event showing progress of recovery action | 225 | * zfcp_dbf_rec_run - trace event related to running recovery |
659 | * @id2: identifier | 226 | * @tag: identifier for event |
660 | * @erp_action: error recovery action struct pointer | 227 | * @erp: erp_action running |
661 | */ | 228 | */ |
662 | void zfcp_dbf_rec_action(char *id2, struct zfcp_erp_action *erp_action) | 229 | void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp) |
663 | { | 230 | { |
664 | struct zfcp_dbf *dbf = erp_action->adapter->dbf; | 231 | struct zfcp_dbf *dbf = erp->adapter->dbf; |
665 | struct zfcp_dbf_rec_record *r = &dbf->rec_buf; | 232 | struct zfcp_dbf_rec *rec = &dbf->rec_buf; |
666 | unsigned long flags; | 233 | unsigned long flags; |
667 | 234 | ||
668 | spin_lock_irqsave(&dbf->rec_lock, flags); | 235 | spin_lock_irqsave(&dbf->rec_lock, flags); |
669 | memset(r, 0, sizeof(*r)); | 236 | memset(rec, 0, sizeof(*rec)); |
670 | r->id = ZFCP_REC_DBF_ID_ACTION; | ||
671 | memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE); | ||
672 | r->u.action.action = (unsigned long)erp_action; | ||
673 | r->u.action.status = erp_action->status; | ||
674 | r->u.action.step = erp_action->step; | ||
675 | r->u.action.fsf_req = erp_action->fsf_req_id; | ||
676 | debug_event(dbf->rec, 5, r, sizeof(*r)); | ||
677 | spin_unlock_irqrestore(&dbf->rec_lock, flags); | ||
678 | } | ||
679 | 237 | ||
680 | /** | 238 | rec->id = ZFCP_DBF_REC_RUN; |
681 | * zfcp_dbf_san_ct_request - trace event for issued CT request | 239 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); |
682 | * @fsf_req: request containing issued CT data | 240 | zfcp_dbf_set_common(rec, erp->adapter, erp->port, erp->sdev); |
683 | * @d_id: destination id where ct request is sent to | ||
684 | */ | ||
685 | void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *fsf_req, u32 d_id) | ||
686 | { | ||
687 | struct zfcp_fsf_ct_els *ct = (struct zfcp_fsf_ct_els *)fsf_req->data; | ||
688 | struct zfcp_adapter *adapter = fsf_req->adapter; | ||
689 | struct zfcp_dbf *dbf = adapter->dbf; | ||
690 | struct fc_ct_hdr *hdr = sg_virt(ct->req); | ||
691 | struct zfcp_dbf_san_record *r = &dbf->san_buf; | ||
692 | struct zfcp_dbf_san_record_ct_request *oct = &r->u.ct_req; | ||
693 | int level = 3; | ||
694 | unsigned long flags; | ||
695 | 241 | ||
696 | spin_lock_irqsave(&dbf->san_lock, flags); | 242 | rec->u.run.fsf_req_id = erp->fsf_req_id; |
697 | memset(r, 0, sizeof(*r)); | 243 | rec->u.run.rec_status = erp->status; |
698 | strncpy(r->tag, "octc", ZFCP_DBF_TAG_SIZE); | 244 | rec->u.run.rec_step = erp->step; |
699 | r->fsf_reqid = fsf_req->req_id; | 245 | rec->u.run.rec_action = erp->action; |
700 | r->fsf_seqno = fsf_req->seq_no; | ||
701 | oct->d_id = d_id; | ||
702 | oct->cmd_req_code = hdr->ct_cmd; | ||
703 | oct->revision = hdr->ct_rev; | ||
704 | oct->gs_type = hdr->ct_fs_type; | ||
705 | oct->gs_subtype = hdr->ct_fs_subtype; | ||
706 | oct->options = hdr->ct_options; | ||
707 | oct->max_res_size = hdr->ct_mr_size; | ||
708 | oct->len = min((int)ct->req->length - (int)sizeof(struct fc_ct_hdr), | ||
709 | ZFCP_DBF_SAN_MAX_PAYLOAD); | ||
710 | debug_event(dbf->san, level, r, sizeof(*r)); | ||
711 | zfcp_dbf_hexdump(dbf->san, r, sizeof(*r), level, | ||
712 | (void *)hdr + sizeof(struct fc_ct_hdr), oct->len); | ||
713 | spin_unlock_irqrestore(&dbf->san_lock, flags); | ||
714 | } | ||
715 | 246 | ||
716 | /** | 247 | if (erp->sdev) |
717 | * zfcp_dbf_san_ct_response - trace event for completion of CT request | 248 | rec->u.run.rec_count = |
718 | * @fsf_req: request containing CT response | 249 | atomic_read(&sdev_to_zfcp(erp->sdev)->erp_counter); |
719 | */ | 250 | else if (erp->port) |
720 | void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *fsf_req) | 251 | rec->u.run.rec_count = atomic_read(&erp->port->erp_counter); |
721 | { | 252 | else |
722 | struct zfcp_fsf_ct_els *ct = (struct zfcp_fsf_ct_els *)fsf_req->data; | 253 | rec->u.run.rec_count = atomic_read(&erp->adapter->erp_counter); |
723 | struct zfcp_adapter *adapter = fsf_req->adapter; | ||
724 | struct fc_ct_hdr *hdr = sg_virt(ct->resp); | ||
725 | struct zfcp_dbf *dbf = adapter->dbf; | ||
726 | struct zfcp_dbf_san_record *r = &dbf->san_buf; | ||
727 | struct zfcp_dbf_san_record_ct_response *rct = &r->u.ct_resp; | ||
728 | int level = 3; | ||
729 | unsigned long flags; | ||
730 | 254 | ||
731 | spin_lock_irqsave(&dbf->san_lock, flags); | 255 | debug_event(dbf->rec, 1, rec, sizeof(*rec)); |
732 | memset(r, 0, sizeof(*r)); | 256 | spin_unlock_irqrestore(&dbf->rec_lock, flags); |
733 | strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE); | ||
734 | r->fsf_reqid = fsf_req->req_id; | ||
735 | r->fsf_seqno = fsf_req->seq_no; | ||
736 | rct->cmd_rsp_code = hdr->ct_cmd; | ||
737 | rct->revision = hdr->ct_rev; | ||
738 | rct->reason_code = hdr->ct_reason; | ||
739 | rct->expl = hdr->ct_explan; | ||
740 | rct->vendor_unique = hdr->ct_vendor; | ||
741 | rct->max_res_size = hdr->ct_mr_size; | ||
742 | rct->len = min((int)ct->resp->length - (int)sizeof(struct fc_ct_hdr), | ||
743 | ZFCP_DBF_SAN_MAX_PAYLOAD); | ||
744 | debug_event(dbf->san, level, r, sizeof(*r)); | ||
745 | zfcp_dbf_hexdump(dbf->san, r, sizeof(*r), level, | ||
746 | (void *)hdr + sizeof(struct fc_ct_hdr), rct->len); | ||
747 | spin_unlock_irqrestore(&dbf->san_lock, flags); | ||
748 | } | 257 | } |
749 | 258 | ||
750 | static void zfcp_dbf_san_els(const char *tag, int level, | 259 | static inline |
751 | struct zfcp_fsf_req *fsf_req, u32 d_id, | 260 | void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf, void *data, u8 id, u16 len, |
752 | void *buffer, int buflen) | 261 | u64 req_id, u32 d_id) |
753 | { | 262 | { |
754 | struct zfcp_adapter *adapter = fsf_req->adapter; | 263 | struct zfcp_dbf_san *rec = &dbf->san_buf; |
755 | struct zfcp_dbf *dbf = adapter->dbf; | 264 | u16 rec_len; |
756 | struct zfcp_dbf_san_record *rec = &dbf->san_buf; | ||
757 | unsigned long flags; | 265 | unsigned long flags; |
758 | 266 | ||
759 | spin_lock_irqsave(&dbf->san_lock, flags); | 267 | spin_lock_irqsave(&dbf->san_lock, flags); |
760 | memset(rec, 0, sizeof(*rec)); | 268 | memset(rec, 0, sizeof(*rec)); |
761 | strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); | 269 | |
762 | rec->fsf_reqid = fsf_req->req_id; | 270 | rec->id = id; |
763 | rec->fsf_seqno = fsf_req->seq_no; | 271 | rec->fsf_req_id = req_id; |
764 | rec->u.els.d_id = d_id; | 272 | rec->d_id = d_id; |
765 | debug_event(dbf->san, level, rec, sizeof(*rec)); | 273 | rec_len = min(len, (u16)ZFCP_DBF_SAN_MAX_PAYLOAD); |
766 | zfcp_dbf_hexdump(dbf->san, rec, sizeof(*rec), level, | 274 | memcpy(rec->payload, data, rec_len); |
767 | buffer, min(buflen, ZFCP_DBF_SAN_MAX_PAYLOAD)); | 275 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); |
276 | |||
277 | debug_event(dbf->san, 1, rec, sizeof(*rec)); | ||
768 | spin_unlock_irqrestore(&dbf->san_lock, flags); | 278 | spin_unlock_irqrestore(&dbf->san_lock, flags); |
769 | } | 279 | } |
770 | 280 | ||
771 | /** | 281 | /** |
772 | * zfcp_dbf_san_els_request - trace event for issued ELS | 282 | * zfcp_dbf_san_req - trace event for issued SAN request |
773 | * @fsf_req: request containing issued ELS | 283 | * @tag: indentifier for event |
284 | * @fsf_req: request containing issued CT data | ||
285 | * d_id: destination ID | ||
774 | */ | 286 | */ |
775 | void zfcp_dbf_san_els_request(struct zfcp_fsf_req *fsf_req) | 287 | void zfcp_dbf_san_req(char *tag, struct zfcp_fsf_req *fsf, u32 d_id) |
776 | { | 288 | { |
777 | struct zfcp_fsf_ct_els *els = (struct zfcp_fsf_ct_els *)fsf_req->data; | 289 | struct zfcp_dbf *dbf = fsf->adapter->dbf; |
778 | u32 d_id = ntoh24(fsf_req->qtcb->bottom.support.d_id); | 290 | struct zfcp_fsf_ct_els *ct_els = fsf->data; |
291 | u16 length; | ||
779 | 292 | ||
780 | zfcp_dbf_san_els("oels", 2, fsf_req, d_id, | 293 | length = (u16)(ct_els->req->length + FC_CT_HDR_LEN); |
781 | sg_virt(els->req), els->req->length); | 294 | zfcp_dbf_san(tag, dbf, sg_virt(ct_els->req), ZFCP_DBF_SAN_REQ, length, |
295 | fsf->req_id, d_id); | ||
782 | } | 296 | } |
783 | 297 | ||
784 | /** | 298 | /** |
785 | * zfcp_dbf_san_els_response - trace event for completed ELS | 299 | * zfcp_dbf_san_res - trace event for received SAN request |
786 | * @fsf_req: request containing ELS response | 300 | * @tag: indentifier for event |
301 | * @fsf_req: request containing issued CT data | ||
787 | */ | 302 | */ |
788 | void zfcp_dbf_san_els_response(struct zfcp_fsf_req *fsf_req) | 303 | void zfcp_dbf_san_res(char *tag, struct zfcp_fsf_req *fsf) |
789 | { | 304 | { |
790 | struct zfcp_fsf_ct_els *els = (struct zfcp_fsf_ct_els *)fsf_req->data; | 305 | struct zfcp_dbf *dbf = fsf->adapter->dbf; |
791 | u32 d_id = ntoh24(fsf_req->qtcb->bottom.support.d_id); | 306 | struct zfcp_fsf_ct_els *ct_els = fsf->data; |
307 | u16 length; | ||
792 | 308 | ||
793 | zfcp_dbf_san_els("rels", 2, fsf_req, d_id, | 309 | length = (u16)(ct_els->resp->length + FC_CT_HDR_LEN); |
794 | sg_virt(els->resp), els->resp->length); | 310 | zfcp_dbf_san(tag, dbf, sg_virt(ct_els->resp), ZFCP_DBF_SAN_RES, length, |
311 | fsf->req_id, 0); | ||
795 | } | 312 | } |
796 | 313 | ||
797 | /** | 314 | /** |
798 | * zfcp_dbf_san_incoming_els - trace event for incomig ELS | 315 | * zfcp_dbf_san_in_els - trace event for incoming ELS |
799 | * @fsf_req: request containing unsolicited status buffer with incoming ELS | 316 | * @tag: indentifier for event |
317 | * @fsf_req: request containing issued CT data | ||
800 | */ | 318 | */ |
801 | void zfcp_dbf_san_incoming_els(struct zfcp_fsf_req *fsf_req) | 319 | void zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf) |
802 | { | 320 | { |
803 | struct fsf_status_read_buffer *buf = | 321 | struct zfcp_dbf *dbf = fsf->adapter->dbf; |
804 | (struct fsf_status_read_buffer *)fsf_req->data; | 322 | struct fsf_status_read_buffer *srb = |
805 | int length = (int)buf->length - | 323 | (struct fsf_status_read_buffer *) fsf->data; |
806 | (int)((void *)&buf->payload - (void *)buf); | 324 | u16 length; |
807 | 325 | ||
808 | zfcp_dbf_san_els("iels", 1, fsf_req, ntoh24(buf->d_id), | 326 | length = (u16)(srb->length - |
809 | (void *)buf->payload.data, length); | 327 | offsetof(struct fsf_status_read_buffer, payload)); |
810 | } | 328 | zfcp_dbf_san(tag, dbf, srb->payload.data, ZFCP_DBF_SAN_ELS, length, |
811 | 329 | fsf->req_id, ntoh24(srb->d_id)); | |
812 | static int zfcp_dbf_san_view_format(debug_info_t *id, struct debug_view *view, | ||
813 | char *out_buf, const char *in_buf) | ||
814 | { | ||
815 | struct zfcp_dbf_san_record *r = (struct zfcp_dbf_san_record *)in_buf; | ||
816 | char *p = out_buf; | ||
817 | |||
818 | if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) | ||
819 | return 0; | ||
820 | |||
821 | zfcp_dbf_tag(&p, "tag", r->tag); | ||
822 | zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid); | ||
823 | zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno); | ||
824 | |||
825 | if (strncmp(r->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) { | ||
826 | struct zfcp_dbf_san_record_ct_request *ct = &r->u.ct_req; | ||
827 | zfcp_dbf_out(&p, "d_id", "0x%06x", ct->d_id); | ||
828 | zfcp_dbf_out(&p, "cmd_req_code", "0x%04x", ct->cmd_req_code); | ||
829 | zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision); | ||
830 | zfcp_dbf_out(&p, "gs_type", "0x%02x", ct->gs_type); | ||
831 | zfcp_dbf_out(&p, "gs_subtype", "0x%02x", ct->gs_subtype); | ||
832 | zfcp_dbf_out(&p, "options", "0x%02x", ct->options); | ||
833 | zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size); | ||
834 | } else if (strncmp(r->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) { | ||
835 | struct zfcp_dbf_san_record_ct_response *ct = &r->u.ct_resp; | ||
836 | zfcp_dbf_out(&p, "cmd_rsp_code", "0x%04x", ct->cmd_rsp_code); | ||
837 | zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision); | ||
838 | zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code); | ||
839 | zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl); | ||
840 | zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique); | ||
841 | zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size); | ||
842 | } else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 || | ||
843 | strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 || | ||
844 | strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) { | ||
845 | struct zfcp_dbf_san_record_els *els = &r->u.els; | ||
846 | zfcp_dbf_out(&p, "d_id", "0x%06x", els->d_id); | ||
847 | } | ||
848 | return p - out_buf; | ||
849 | } | 330 | } |
850 | 331 | ||
851 | static struct debug_view zfcp_dbf_san_view = { | 332 | /** |
852 | .name = "structured", | 333 | * zfcp_dbf_scsi - trace event for scsi commands |
853 | .header_proc = zfcp_dbf_view_header, | 334 | * @tag: identifier for event |
854 | .format_proc = zfcp_dbf_san_view_format, | 335 | * @sc: pointer to struct scsi_cmnd |
855 | }; | 336 | * @fsf: pointer to struct zfcp_fsf_req |
856 | 337 | */ | |
857 | void _zfcp_dbf_scsi(const char *tag, const char *tag2, int level, | 338 | void zfcp_dbf_scsi(char *tag, struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf) |
858 | struct zfcp_dbf *dbf, struct scsi_cmnd *scsi_cmnd, | ||
859 | struct zfcp_fsf_req *fsf_req, unsigned long old_req_id) | ||
860 | { | 339 | { |
861 | struct zfcp_dbf_scsi_record *rec = &dbf->scsi_buf; | 340 | struct zfcp_adapter *adapter = |
862 | struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec; | 341 | (struct zfcp_adapter *) sc->device->host->hostdata[0]; |
863 | unsigned long flags; | 342 | struct zfcp_dbf *dbf = adapter->dbf; |
343 | struct zfcp_dbf_scsi *rec = &dbf->scsi_buf; | ||
864 | struct fcp_resp_with_ext *fcp_rsp; | 344 | struct fcp_resp_with_ext *fcp_rsp; |
865 | struct fcp_resp_rsp_info *fcp_rsp_info = NULL; | 345 | struct fcp_resp_rsp_info *fcp_rsp_info; |
866 | char *fcp_sns_info = NULL; | 346 | unsigned long flags; |
867 | int offset = 0, buflen = 0; | ||
868 | 347 | ||
869 | spin_lock_irqsave(&dbf->scsi_lock, flags); | 348 | spin_lock_irqsave(&dbf->scsi_lock, flags); |
870 | do { | 349 | memset(rec, 0, sizeof(*rec)); |
871 | memset(rec, 0, sizeof(*rec)); | ||
872 | if (offset == 0) { | ||
873 | strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); | ||
874 | strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE); | ||
875 | if (scsi_cmnd != NULL) { | ||
876 | if (scsi_cmnd->device) { | ||
877 | rec->scsi_id = scsi_cmnd->device->id; | ||
878 | rec->scsi_lun = scsi_cmnd->device->lun; | ||
879 | } | ||
880 | rec->scsi_result = scsi_cmnd->result; | ||
881 | rec->scsi_cmnd = (unsigned long)scsi_cmnd; | ||
882 | rec->scsi_serial = scsi_cmnd->serial_number; | ||
883 | memcpy(rec->scsi_opcode, scsi_cmnd->cmnd, | ||
884 | min((int)scsi_cmnd->cmd_len, | ||
885 | ZFCP_DBF_SCSI_OPCODE)); | ||
886 | rec->scsi_retries = scsi_cmnd->retries; | ||
887 | rec->scsi_allowed = scsi_cmnd->allowed; | ||
888 | } | ||
889 | if (fsf_req != NULL) { | ||
890 | fcp_rsp = (struct fcp_resp_with_ext *) | ||
891 | &(fsf_req->qtcb->bottom.io.fcp_rsp); | ||
892 | fcp_rsp_info = (struct fcp_resp_rsp_info *) | ||
893 | &fcp_rsp[1]; | ||
894 | fcp_sns_info = (char *) &fcp_rsp[1]; | ||
895 | if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) | ||
896 | fcp_sns_info += fcp_rsp->ext.fr_sns_len; | ||
897 | |||
898 | rec->rsp_validity = fcp_rsp->resp.fr_flags; | ||
899 | rec->rsp_scsi_status = fcp_rsp->resp.fr_status; | ||
900 | rec->rsp_resid = fcp_rsp->ext.fr_resid; | ||
901 | if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) | ||
902 | rec->rsp_code = fcp_rsp_info->rsp_code; | ||
903 | if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) { | ||
904 | buflen = min(fcp_rsp->ext.fr_sns_len, | ||
905 | (u32)ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO); | ||
906 | rec->sns_info_len = buflen; | ||
907 | memcpy(rec->sns_info, fcp_sns_info, | ||
908 | min(buflen, | ||
909 | ZFCP_DBF_SCSI_FCP_SNS_INFO)); | ||
910 | offset += min(buflen, | ||
911 | ZFCP_DBF_SCSI_FCP_SNS_INFO); | ||
912 | } | ||
913 | |||
914 | rec->fsf_reqid = fsf_req->req_id; | ||
915 | rec->fsf_seqno = fsf_req->seq_no; | ||
916 | rec->fsf_issued = fsf_req->issued; | ||
917 | } | ||
918 | rec->old_fsf_reqid = old_req_id; | ||
919 | } else { | ||
920 | strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE); | ||
921 | dump->total_size = buflen; | ||
922 | dump->offset = offset; | ||
923 | dump->size = min(buflen - offset, | ||
924 | (int)sizeof(struct | ||
925 | zfcp_dbf_scsi_record) - | ||
926 | (int)sizeof(struct zfcp_dbf_dump)); | ||
927 | memcpy(dump->data, fcp_sns_info + offset, dump->size); | ||
928 | offset += dump->size; | ||
929 | } | ||
930 | debug_event(dbf->scsi, level, rec, sizeof(*rec)); | ||
931 | } while (offset < buflen); | ||
932 | spin_unlock_irqrestore(&dbf->scsi_lock, flags); | ||
933 | } | ||
934 | 350 | ||
935 | static int zfcp_dbf_scsi_view_format(debug_info_t *id, struct debug_view *view, | 351 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); |
936 | char *out_buf, const char *in_buf) | 352 | rec->id = ZFCP_DBF_SCSI_CMND; |
937 | { | 353 | rec->scsi_result = sc->result; |
938 | struct zfcp_dbf_scsi_record *r = (struct zfcp_dbf_scsi_record *)in_buf; | 354 | rec->scsi_retries = sc->retries; |
939 | struct timespec t; | 355 | rec->scsi_allowed = sc->allowed; |
940 | char *p = out_buf; | 356 | rec->scsi_id = sc->device->id; |
941 | 357 | rec->scsi_lun = sc->device->lun; | |
942 | if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) | 358 | rec->host_scribble = (unsigned long)sc->host_scribble; |
943 | return 0; | 359 | |
944 | 360 | memcpy(rec->scsi_opcode, sc->cmnd, | |
945 | zfcp_dbf_tag(&p, "tag", r->tag); | 361 | min((int)sc->cmd_len, ZFCP_DBF_SCSI_OPCODE)); |
946 | zfcp_dbf_tag(&p, "tag2", r->tag2); | 362 | |
947 | zfcp_dbf_out(&p, "scsi_id", "0x%08x", r->scsi_id); | 363 | if (fsf) { |
948 | zfcp_dbf_out(&p, "scsi_lun", "0x%08x", r->scsi_lun); | 364 | rec->fsf_req_id = fsf->req_id; |
949 | zfcp_dbf_out(&p, "scsi_result", "0x%08x", r->scsi_result); | 365 | fcp_rsp = (struct fcp_resp_with_ext *) |
950 | zfcp_dbf_out(&p, "scsi_cmnd", "0x%0Lx", r->scsi_cmnd); | 366 | &(fsf->qtcb->bottom.io.fcp_rsp); |
951 | zfcp_dbf_out(&p, "scsi_serial", "0x%016Lx", r->scsi_serial); | 367 | memcpy(&rec->fcp_rsp, fcp_rsp, FCP_RESP_WITH_EXT); |
952 | zfcp_dbf_outd(&p, "scsi_opcode", r->scsi_opcode, ZFCP_DBF_SCSI_OPCODE, | 368 | if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) { |
953 | 0, ZFCP_DBF_SCSI_OPCODE); | 369 | fcp_rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1]; |
954 | zfcp_dbf_out(&p, "scsi_retries", "0x%02x", r->scsi_retries); | 370 | rec->fcp_rsp_info = fcp_rsp_info->rsp_code; |
955 | zfcp_dbf_out(&p, "scsi_allowed", "0x%02x", r->scsi_allowed); | 371 | } |
956 | if (strncmp(r->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) | 372 | if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) { |
957 | zfcp_dbf_out(&p, "old_fsf_reqid", "0x%0Lx", r->old_fsf_reqid); | 373 | rec->pl_len = min((u16)SCSI_SENSE_BUFFERSIZE, |
958 | zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid); | 374 | (u16)ZFCP_DBF_PAY_MAX_REC); |
959 | zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno); | 375 | zfcp_dbf_pl_write(dbf, sc->sense_buffer, rec->pl_len, |
960 | stck_to_timespec(r->fsf_issued, &t); | 376 | "fcp_sns", fsf->req_id); |
961 | zfcp_dbf_out(&p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec); | 377 | } |
962 | |||
963 | if (strncmp(r->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) { | ||
964 | zfcp_dbf_out(&p, "fcp_rsp_validity", "0x%02x", r->rsp_validity); | ||
965 | zfcp_dbf_out(&p, "fcp_rsp_scsi_status", "0x%02x", | ||
966 | r->rsp_scsi_status); | ||
967 | zfcp_dbf_out(&p, "fcp_rsp_resid", "0x%08x", r->rsp_resid); | ||
968 | zfcp_dbf_out(&p, "fcp_rsp_code", "0x%08x", r->rsp_code); | ||
969 | zfcp_dbf_out(&p, "fcp_sns_info_len", "0x%08x", r->sns_info_len); | ||
970 | zfcp_dbf_outd(&p, "fcp_sns_info", r->sns_info, | ||
971 | min((int)r->sns_info_len, | ||
972 | ZFCP_DBF_SCSI_FCP_SNS_INFO), 0, | ||
973 | r->sns_info_len); | ||
974 | } | 378 | } |
975 | p += sprintf(p, "\n"); | ||
976 | return p - out_buf; | ||
977 | } | ||
978 | 379 | ||
979 | static struct debug_view zfcp_dbf_scsi_view = { | 380 | debug_event(dbf->scsi, 1, rec, sizeof(*rec)); |
980 | .name = "structured", | 381 | spin_unlock_irqrestore(&dbf->scsi_lock, flags); |
981 | .header_proc = zfcp_dbf_view_header, | 382 | } |
982 | .format_proc = zfcp_dbf_scsi_view_format, | ||
983 | }; | ||
984 | 383 | ||
985 | static debug_info_t *zfcp_dbf_reg(const char *name, int level, | 384 | static debug_info_t *zfcp_dbf_reg(const char *name, int size, int rec_size) |
986 | struct debug_view *view, int size) | ||
987 | { | 385 | { |
988 | struct debug_info *d; | 386 | struct debug_info *d; |
989 | 387 | ||
990 | d = debug_register(name, dbfsize, level, size); | 388 | d = debug_register(name, size, 1, rec_size); |
991 | if (!d) | 389 | if (!d) |
992 | return NULL; | 390 | return NULL; |
993 | 391 | ||
994 | debug_register_view(d, &debug_hex_ascii_view); | 392 | debug_register_view(d, &debug_hex_ascii_view); |
995 | debug_register_view(d, view); | 393 | debug_set_level(d, 3); |
996 | debug_set_level(d, level); | ||
997 | 394 | ||
998 | return d; | 395 | return d; |
999 | } | 396 | } |
1000 | 397 | ||
398 | static void zfcp_dbf_unregister(struct zfcp_dbf *dbf) | ||
399 | { | ||
400 | if (!dbf) | ||
401 | return; | ||
402 | |||
403 | debug_unregister(dbf->scsi); | ||
404 | debug_unregister(dbf->san); | ||
405 | debug_unregister(dbf->hba); | ||
406 | debug_unregister(dbf->pay); | ||
407 | debug_unregister(dbf->rec); | ||
408 | kfree(dbf); | ||
409 | } | ||
410 | |||
1001 | /** | 411 | /** |
1002 | * zfcp_adapter_debug_register - registers debug feature for an adapter | 412 | * zfcp_adapter_debug_register - registers debug feature for an adapter |
1003 | * @adapter: pointer to adapter for which debug features should be registered | 413 | * @adapter: pointer to adapter for which debug features should be registered |
@@ -1005,69 +415,66 @@ static debug_info_t *zfcp_dbf_reg(const char *name, int level, | |||
1005 | */ | 415 | */ |
1006 | int zfcp_dbf_adapter_register(struct zfcp_adapter *adapter) | 416 | int zfcp_dbf_adapter_register(struct zfcp_adapter *adapter) |
1007 | { | 417 | { |
1008 | char dbf_name[DEBUG_MAX_NAME_LEN]; | 418 | char name[DEBUG_MAX_NAME_LEN]; |
1009 | struct zfcp_dbf *dbf; | 419 | struct zfcp_dbf *dbf; |
1010 | 420 | ||
1011 | dbf = kzalloc(sizeof(struct zfcp_dbf), GFP_KERNEL); | 421 | dbf = kzalloc(sizeof(struct zfcp_dbf), GFP_KERNEL); |
1012 | if (!dbf) | 422 | if (!dbf) |
1013 | return -ENOMEM; | 423 | return -ENOMEM; |
1014 | 424 | ||
1015 | dbf->adapter = adapter; | 425 | spin_lock_init(&dbf->pay_lock); |
1016 | |||
1017 | spin_lock_init(&dbf->hba_lock); | 426 | spin_lock_init(&dbf->hba_lock); |
1018 | spin_lock_init(&dbf->san_lock); | 427 | spin_lock_init(&dbf->san_lock); |
1019 | spin_lock_init(&dbf->scsi_lock); | 428 | spin_lock_init(&dbf->scsi_lock); |
1020 | spin_lock_init(&dbf->rec_lock); | 429 | spin_lock_init(&dbf->rec_lock); |
1021 | 430 | ||
1022 | /* debug feature area which records recovery activity */ | 431 | /* debug feature area which records recovery activity */ |
1023 | sprintf(dbf_name, "zfcp_%s_rec", dev_name(&adapter->ccw_device->dev)); | 432 | sprintf(name, "zfcp_%s_rec", dev_name(&adapter->ccw_device->dev)); |
1024 | dbf->rec = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_rec_view, | 433 | dbf->rec = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_rec)); |
1025 | sizeof(struct zfcp_dbf_rec_record)); | ||
1026 | if (!dbf->rec) | 434 | if (!dbf->rec) |
1027 | goto err_out; | 435 | goto err_out; |
1028 | 436 | ||
1029 | /* debug feature area which records HBA (FSF and QDIO) conditions */ | 437 | /* debug feature area which records HBA (FSF and QDIO) conditions */ |
1030 | sprintf(dbf_name, "zfcp_%s_hba", dev_name(&adapter->ccw_device->dev)); | 438 | sprintf(name, "zfcp_%s_hba", dev_name(&adapter->ccw_device->dev)); |
1031 | dbf->hba = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_hba_view, | 439 | dbf->hba = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_hba)); |
1032 | sizeof(struct zfcp_dbf_hba_record)); | ||
1033 | if (!dbf->hba) | 440 | if (!dbf->hba) |
1034 | goto err_out; | 441 | goto err_out; |
1035 | 442 | ||
443 | /* debug feature area which records payload info */ | ||
444 | sprintf(name, "zfcp_%s_pay", dev_name(&adapter->ccw_device->dev)); | ||
445 | dbf->pay = zfcp_dbf_reg(name, dbfsize * 2, sizeof(struct zfcp_dbf_pay)); | ||
446 | if (!dbf->pay) | ||
447 | goto err_out; | ||
448 | |||
1036 | /* debug feature area which records SAN command failures and recovery */ | 449 | /* debug feature area which records SAN command failures and recovery */ |
1037 | sprintf(dbf_name, "zfcp_%s_san", dev_name(&adapter->ccw_device->dev)); | 450 | sprintf(name, "zfcp_%s_san", dev_name(&adapter->ccw_device->dev)); |
1038 | dbf->san = zfcp_dbf_reg(dbf_name, 6, &zfcp_dbf_san_view, | 451 | dbf->san = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_san)); |
1039 | sizeof(struct zfcp_dbf_san_record)); | ||
1040 | if (!dbf->san) | 452 | if (!dbf->san) |
1041 | goto err_out; | 453 | goto err_out; |
1042 | 454 | ||
1043 | /* debug feature area which records SCSI command failures and recovery */ | 455 | /* debug feature area which records SCSI command failures and recovery */ |
1044 | sprintf(dbf_name, "zfcp_%s_scsi", dev_name(&adapter->ccw_device->dev)); | 456 | sprintf(name, "zfcp_%s_scsi", dev_name(&adapter->ccw_device->dev)); |
1045 | dbf->scsi = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_scsi_view, | 457 | dbf->scsi = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_scsi)); |
1046 | sizeof(struct zfcp_dbf_scsi_record)); | ||
1047 | if (!dbf->scsi) | 458 | if (!dbf->scsi) |
1048 | goto err_out; | 459 | goto err_out; |
1049 | 460 | ||
1050 | adapter->dbf = dbf; | 461 | adapter->dbf = dbf; |
1051 | return 0; | ||
1052 | 462 | ||
463 | return 0; | ||
1053 | err_out: | 464 | err_out: |
1054 | zfcp_dbf_adapter_unregister(dbf); | 465 | zfcp_dbf_unregister(dbf); |
1055 | return -ENOMEM; | 466 | return -ENOMEM; |
1056 | } | 467 | } |
1057 | 468 | ||
1058 | /** | 469 | /** |
1059 | * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter | 470 | * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter |
1060 | * @dbf: pointer to dbf for which debug features should be unregistered | 471 | * @adapter: pointer to adapter for which debug features should be unregistered |
1061 | */ | 472 | */ |
1062 | void zfcp_dbf_adapter_unregister(struct zfcp_dbf *dbf) | 473 | void zfcp_dbf_adapter_unregister(struct zfcp_adapter *adapter) |
1063 | { | 474 | { |
1064 | if (!dbf) | 475 | struct zfcp_dbf *dbf = adapter->dbf; |
1065 | return; | 476 | |
1066 | debug_unregister(dbf->scsi); | 477 | adapter->dbf = NULL; |
1067 | debug_unregister(dbf->san); | 478 | zfcp_dbf_unregister(dbf); |
1068 | debug_unregister(dbf->hba); | ||
1069 | debug_unregister(dbf->rec); | ||
1070 | dbf->adapter->dbf = NULL; | ||
1071 | kfree(dbf); | ||
1072 | } | 479 | } |
1073 | 480 | ||
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 2bcc3403126a..714f087eb7a9 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h | |||
@@ -1,22 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of the zfcp device driver for | 2 | * zfcp device driver |
3 | * FCP adapters for IBM System z9 and zSeries. | 3 | * debug feature declarations |
4 | * | 4 | * |
5 | * Copyright IBM Corp. 2008, 2009 | 5 | * Copyright IBM Corp. 2008, 2010 |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | 6 | */ |
21 | 7 | ||
22 | #ifndef ZFCP_DBF_H | 8 | #ifndef ZFCP_DBF_H |
@@ -27,339 +13,370 @@ | |||
27 | #include "zfcp_fsf.h" | 13 | #include "zfcp_fsf.h" |
28 | #include "zfcp_def.h" | 14 | #include "zfcp_def.h" |
29 | 15 | ||
30 | #define ZFCP_DBF_TAG_SIZE 4 | 16 | #define ZFCP_DBF_TAG_LEN 7 |
31 | #define ZFCP_DBF_ID_SIZE 7 | ||
32 | 17 | ||
33 | #define ZFCP_DBF_INVALID_LUN 0xFFFFFFFFFFFFFFFFull | 18 | #define ZFCP_DBF_INVALID_LUN 0xFFFFFFFFFFFFFFFFull |
34 | 19 | ||
35 | struct zfcp_dbf_dump { | 20 | /** |
36 | u8 tag[ZFCP_DBF_TAG_SIZE]; | 21 | * struct zfcp_dbf_rec_trigger - trace record for triggered recovery action |
37 | u32 total_size; /* size of total dump data */ | 22 | * @ready: number of ready recovery actions |
38 | u32 offset; /* how much data has being already dumped */ | 23 | * @running: number of running recovery actions |
39 | u32 size; /* how much data comes with this record */ | 24 | * @want: wanted recovery action |
40 | u8 data[]; /* dump data */ | 25 | * @need: needed recovery action |
41 | } __attribute__ ((packed)); | 26 | */ |
42 | 27 | struct zfcp_dbf_rec_trigger { | |
43 | struct zfcp_dbf_rec_record_thread { | ||
44 | u32 total; | ||
45 | u32 ready; | 28 | u32 ready; |
46 | u32 running; | 29 | u32 running; |
47 | }; | ||
48 | |||
49 | struct zfcp_dbf_rec_record_target { | ||
50 | u64 ref; | ||
51 | u32 status; | ||
52 | u32 d_id; | ||
53 | u64 wwpn; | ||
54 | u64 fcp_lun; | ||
55 | u32 erp_count; | ||
56 | }; | ||
57 | |||
58 | struct zfcp_dbf_rec_record_trigger { | ||
59 | u8 want; | 30 | u8 want; |
60 | u8 need; | 31 | u8 need; |
61 | u32 as; | 32 | } __packed; |
62 | u32 ps; | ||
63 | u32 us; | ||
64 | u64 ref; | ||
65 | u64 action; | ||
66 | u64 wwpn; | ||
67 | u64 fcp_lun; | ||
68 | }; | ||
69 | 33 | ||
70 | struct zfcp_dbf_rec_record_action { | 34 | /** |
71 | u32 status; | 35 | * struct zfcp_dbf_rec_running - trace record for running recovery |
72 | u32 step; | 36 | * @fsf_req_id: request id for fsf requests |
73 | u64 action; | 37 | * @rec_status: status of the fsf request |
74 | u64 fsf_req; | 38 | * @rec_step: current step of the recovery action |
39 | * rec_count: recovery counter | ||
40 | */ | ||
41 | struct zfcp_dbf_rec_running { | ||
42 | u64 fsf_req_id; | ||
43 | u32 rec_status; | ||
44 | u16 rec_step; | ||
45 | u8 rec_action; | ||
46 | u8 rec_count; | ||
47 | } __packed; | ||
48 | |||
49 | /** | ||
50 | * enum zfcp_dbf_rec_id - recovery trace record id | ||
51 | * @ZFCP_DBF_REC_TRIG: triggered recovery identifier | ||
52 | * @ZFCP_DBF_REC_RUN: running recovery identifier | ||
53 | */ | ||
54 | enum zfcp_dbf_rec_id { | ||
55 | ZFCP_DBF_REC_TRIG = 1, | ||
56 | ZFCP_DBF_REC_RUN = 2, | ||
75 | }; | 57 | }; |
76 | 58 | ||
77 | struct zfcp_dbf_rec_record { | 59 | /** |
60 | * struct zfcp_dbf_rec - trace record for error recovery actions | ||
61 | * @id: unique number of recovery record type | ||
62 | * @tag: identifier string specifying the location of initiation | ||
63 | * @lun: logical unit number | ||
64 | * @wwpn: word wide port number | ||
65 | * @d_id: destination ID | ||
66 | * @adapter_status: current status of the adapter | ||
67 | * @port_status: current status of the port | ||
68 | * @lun_status: current status of the lun | ||
69 | * @u.trig: structure zfcp_dbf_rec_trigger | ||
70 | * @u.run: structure zfcp_dbf_rec_running | ||
71 | */ | ||
72 | struct zfcp_dbf_rec { | ||
78 | u8 id; | 73 | u8 id; |
79 | char id2[7]; | 74 | char tag[ZFCP_DBF_TAG_LEN]; |
75 | u64 lun; | ||
76 | u64 wwpn; | ||
77 | u32 d_id; | ||
78 | u32 adapter_status; | ||
79 | u32 port_status; | ||
80 | u32 lun_status; | ||
80 | union { | 81 | union { |
81 | struct zfcp_dbf_rec_record_action action; | 82 | struct zfcp_dbf_rec_trigger trig; |
82 | struct zfcp_dbf_rec_record_thread thread; | 83 | struct zfcp_dbf_rec_running run; |
83 | struct zfcp_dbf_rec_record_target target; | ||
84 | struct zfcp_dbf_rec_record_trigger trigger; | ||
85 | } u; | 84 | } u; |
86 | }; | 85 | } __packed; |
87 | 86 | ||
88 | enum { | 87 | /** |
89 | ZFCP_REC_DBF_ID_ACTION, | 88 | * enum zfcp_dbf_san_id - SAN trace record identifier |
90 | ZFCP_REC_DBF_ID_THREAD, | 89 | * @ZFCP_DBF_SAN_REQ: request trace record id |
91 | ZFCP_REC_DBF_ID_TARGET, | 90 | * @ZFCP_DBF_SAN_RES: response trace record id |
92 | ZFCP_REC_DBF_ID_TRIGGER, | 91 | * @ZFCP_DBF_SAN_ELS: extended link service record id |
92 | */ | ||
93 | enum zfcp_dbf_san_id { | ||
94 | ZFCP_DBF_SAN_REQ = 1, | ||
95 | ZFCP_DBF_SAN_RES = 2, | ||
96 | ZFCP_DBF_SAN_ELS = 3, | ||
93 | }; | 97 | }; |
94 | 98 | ||
95 | struct zfcp_dbf_hba_record_response { | 99 | /** struct zfcp_dbf_san - trace record for SAN requests and responses |
96 | u32 fsf_command; | 100 | * @id: unique number of recovery record type |
97 | u64 fsf_reqid; | 101 | * @tag: identifier string specifying the location of initiation |
98 | u32 fsf_seqno; | 102 | * @fsf_req_id: request id for fsf requests |
99 | u64 fsf_issued; | 103 | * @payload: unformatted information related to request/response |
100 | u32 fsf_prot_status; | 104 | * @d_id: destination id |
105 | */ | ||
106 | struct zfcp_dbf_san { | ||
107 | u8 id; | ||
108 | char tag[ZFCP_DBF_TAG_LEN]; | ||
109 | u64 fsf_req_id; | ||
110 | u32 d_id; | ||
111 | #define ZFCP_DBF_SAN_MAX_PAYLOAD (FC_CT_HDR_LEN + 32) | ||
112 | char payload[ZFCP_DBF_SAN_MAX_PAYLOAD]; | ||
113 | } __packed; | ||
114 | |||
115 | /** | ||
116 | * struct zfcp_dbf_hba_res - trace record for hba responses | ||
117 | * @req_issued: timestamp when request was issued | ||
118 | * @prot_status: protocol status | ||
119 | * @prot_status_qual: protocol status qualifier | ||
120 | * @fsf_status: fsf status | ||
121 | * @fsf_status_qual: fsf status qualifier | ||
122 | */ | ||
123 | struct zfcp_dbf_hba_res { | ||
124 | u64 req_issued; | ||
125 | u32 prot_status; | ||
126 | u8 prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE]; | ||
101 | u32 fsf_status; | 127 | u32 fsf_status; |
102 | u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE]; | 128 | u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE]; |
103 | u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE]; | 129 | } __packed; |
104 | u32 fsf_req_status; | ||
105 | u8 sbal_first; | ||
106 | u8 sbal_last; | ||
107 | u8 sbal_response; | ||
108 | u8 pool; | ||
109 | u64 erp_action; | ||
110 | union { | ||
111 | struct { | ||
112 | u64 cmnd; | ||
113 | u64 serial; | ||
114 | u32 data_dir; | ||
115 | } fcp; | ||
116 | struct { | ||
117 | u64 wwpn; | ||
118 | u32 d_id; | ||
119 | u32 port_handle; | ||
120 | } port; | ||
121 | struct { | ||
122 | u64 wwpn; | ||
123 | u64 fcp_lun; | ||
124 | u32 port_handle; | ||
125 | u32 lun_handle; | ||
126 | } unit; | ||
127 | struct { | ||
128 | u32 d_id; | ||
129 | } els; | ||
130 | } u; | ||
131 | } __attribute__ ((packed)); | ||
132 | 130 | ||
133 | struct zfcp_dbf_hba_record_status { | 131 | /** |
134 | u8 failed; | 132 | * struct zfcp_dbf_hba_uss - trace record for unsolicited status |
133 | * @status_type: type of unsolicited status | ||
134 | * @status_subtype: subtype of unsolicited status | ||
135 | * @d_id: destination ID | ||
136 | * @lun: logical unit number | ||
137 | * @queue_designator: queue designator | ||
138 | */ | ||
139 | struct zfcp_dbf_hba_uss { | ||
135 | u32 status_type; | 140 | u32 status_type; |
136 | u32 status_subtype; | 141 | u32 status_subtype; |
137 | struct fsf_queue_designator | ||
138 | queue_designator; | ||
139 | u32 payload_size; | ||
140 | #define ZFCP_DBF_UNSOL_PAYLOAD 80 | ||
141 | #define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL 32 | ||
142 | #define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD 56 | ||
143 | #define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT 2 * sizeof(u32) | ||
144 | u8 payload[ZFCP_DBF_UNSOL_PAYLOAD]; | ||
145 | } __attribute__ ((packed)); | ||
146 | |||
147 | struct zfcp_dbf_hba_record_qdio { | ||
148 | u32 qdio_error; | ||
149 | u8 sbal_index; | ||
150 | u8 sbal_count; | ||
151 | } __attribute__ ((packed)); | ||
152 | |||
153 | struct zfcp_dbf_hba_record { | ||
154 | u8 tag[ZFCP_DBF_TAG_SIZE]; | ||
155 | u8 tag2[ZFCP_DBF_TAG_SIZE]; | ||
156 | union { | ||
157 | struct zfcp_dbf_hba_record_response response; | ||
158 | struct zfcp_dbf_hba_record_status status; | ||
159 | struct zfcp_dbf_hba_record_qdio qdio; | ||
160 | struct fsf_bit_error_payload berr; | ||
161 | } u; | ||
162 | } __attribute__ ((packed)); | ||
163 | |||
164 | struct zfcp_dbf_san_record_ct_request { | ||
165 | u16 cmd_req_code; | ||
166 | u8 revision; | ||
167 | u8 gs_type; | ||
168 | u8 gs_subtype; | ||
169 | u8 options; | ||
170 | u16 max_res_size; | ||
171 | u32 len; | ||
172 | u32 d_id; | ||
173 | } __attribute__ ((packed)); | ||
174 | |||
175 | struct zfcp_dbf_san_record_ct_response { | ||
176 | u16 cmd_rsp_code; | ||
177 | u8 revision; | ||
178 | u8 reason_code; | ||
179 | u8 expl; | ||
180 | u8 vendor_unique; | ||
181 | u16 max_res_size; | ||
182 | u32 len; | ||
183 | } __attribute__ ((packed)); | ||
184 | |||
185 | struct zfcp_dbf_san_record_els { | ||
186 | u32 d_id; | 142 | u32 d_id; |
187 | } __attribute__ ((packed)); | 143 | u64 lun; |
144 | u64 queue_designator; | ||
145 | } __packed; | ||
146 | |||
147 | /** | ||
148 | * enum zfcp_dbf_hba_id - HBA trace record identifier | ||
149 | * @ZFCP_DBF_HBA_RES: response trace record | ||
150 | * @ZFCP_DBF_HBA_USS: unsolicited status trace record | ||
151 | * @ZFCP_DBF_HBA_BIT: bit error trace record | ||
152 | */ | ||
153 | enum zfcp_dbf_hba_id { | ||
154 | ZFCP_DBF_HBA_RES = 1, | ||
155 | ZFCP_DBF_HBA_USS = 2, | ||
156 | ZFCP_DBF_HBA_BIT = 3, | ||
157 | }; | ||
188 | 158 | ||
189 | struct zfcp_dbf_san_record { | 159 | /** |
190 | u8 tag[ZFCP_DBF_TAG_SIZE]; | 160 | * struct zfcp_dbf_hba - common trace record for HBA records |
191 | u64 fsf_reqid; | 161 | * @id: unique number of recovery record type |
192 | u32 fsf_seqno; | 162 | * @tag: identifier string specifying the location of initiation |
163 | * @fsf_req_id: request id for fsf requests | ||
164 | * @fsf_req_status: status of fsf request | ||
165 | * @fsf_cmd: fsf command | ||
166 | * @fsf_seq_no: fsf sequence number | ||
167 | * @pl_len: length of payload stored as zfcp_dbf_pay | ||
168 | * @u: record type specific data | ||
169 | */ | ||
170 | struct zfcp_dbf_hba { | ||
171 | u8 id; | ||
172 | char tag[ZFCP_DBF_TAG_LEN]; | ||
173 | u64 fsf_req_id; | ||
174 | u32 fsf_req_status; | ||
175 | u32 fsf_cmd; | ||
176 | u32 fsf_seq_no; | ||
177 | u16 pl_len; | ||
193 | union { | 178 | union { |
194 | struct zfcp_dbf_san_record_ct_request ct_req; | 179 | struct zfcp_dbf_hba_res res; |
195 | struct zfcp_dbf_san_record_ct_response ct_resp; | 180 | struct zfcp_dbf_hba_uss uss; |
196 | struct zfcp_dbf_san_record_els els; | 181 | struct fsf_bit_error_payload be; |
197 | } u; | 182 | } u; |
198 | } __attribute__ ((packed)); | 183 | } __packed; |
199 | 184 | ||
200 | #define ZFCP_DBF_SAN_MAX_PAYLOAD 1024 | 185 | /** |
186 | * enum zfcp_dbf_scsi_id - scsi trace record identifier | ||
187 | * @ZFCP_DBF_SCSI_CMND: scsi command trace record | ||
188 | */ | ||
189 | enum zfcp_dbf_scsi_id { | ||
190 | ZFCP_DBF_SCSI_CMND = 1, | ||
191 | }; | ||
201 | 192 | ||
202 | struct zfcp_dbf_scsi_record { | 193 | /** |
203 | u8 tag[ZFCP_DBF_TAG_SIZE]; | 194 | * struct zfcp_dbf_scsi - common trace record for SCSI records |
204 | u8 tag2[ZFCP_DBF_TAG_SIZE]; | 195 | * @id: unique number of recovery record type |
196 | * @tag: identifier string specifying the location of initiation | ||
197 | * @scsi_id: scsi device id | ||
198 | * @scsi_lun: scsi device logical unit number | ||
199 | * @scsi_result: scsi result | ||
200 | * @scsi_retries: current retry number of scsi request | ||
201 | * @scsi_allowed: allowed retries | ||
202 | * @fcp_rsp_info: FCP response info | ||
203 | * @scsi_opcode: scsi opcode | ||
204 | * @fsf_req_id: request id of fsf request | ||
205 | * @host_scribble: LLD specific data attached to SCSI request | ||
206 | * @pl_len: length of paload stored as zfcp_dbf_pay | ||
207 | * @fsf_rsp: response for fsf request | ||
208 | */ | ||
209 | struct zfcp_dbf_scsi { | ||
210 | u8 id; | ||
211 | char tag[ZFCP_DBF_TAG_LEN]; | ||
205 | u32 scsi_id; | 212 | u32 scsi_id; |
206 | u32 scsi_lun; | 213 | u32 scsi_lun; |
207 | u32 scsi_result; | 214 | u32 scsi_result; |
208 | u64 scsi_cmnd; | ||
209 | u64 scsi_serial; | ||
210 | #define ZFCP_DBF_SCSI_OPCODE 16 | ||
211 | u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE]; | ||
212 | u8 scsi_retries; | 215 | u8 scsi_retries; |
213 | u8 scsi_allowed; | 216 | u8 scsi_allowed; |
214 | u64 fsf_reqid; | 217 | u8 fcp_rsp_info; |
215 | u32 fsf_seqno; | 218 | #define ZFCP_DBF_SCSI_OPCODE 16 |
216 | u64 fsf_issued; | 219 | u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE]; |
217 | u64 old_fsf_reqid; | 220 | u64 fsf_req_id; |
218 | u8 rsp_validity; | 221 | u64 host_scribble; |
219 | u8 rsp_scsi_status; | 222 | u16 pl_len; |
220 | u32 rsp_resid; | 223 | struct fcp_resp_with_ext fcp_rsp; |
221 | u8 rsp_code; | 224 | } __packed; |
222 | #define ZFCP_DBF_SCSI_FCP_SNS_INFO 16 | 225 | |
223 | #define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO 256 | 226 | /** |
224 | u32 sns_info_len; | 227 | * struct zfcp_dbf_pay - trace record for unformatted payload information |
225 | u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO]; | 228 | * @area: area this record is originated from |
226 | } __attribute__ ((packed)); | 229 | * @counter: ascending record number |
230 | * @fsf_req_id: request id of fsf request | ||
231 | * @data: unformatted data | ||
232 | */ | ||
233 | struct zfcp_dbf_pay { | ||
234 | u8 counter; | ||
235 | char area[ZFCP_DBF_TAG_LEN]; | ||
236 | u64 fsf_req_id; | ||
237 | #define ZFCP_DBF_PAY_MAX_REC 0x100 | ||
238 | char data[ZFCP_DBF_PAY_MAX_REC]; | ||
239 | } __packed; | ||
227 | 240 | ||
241 | /** | ||
242 | * struct zfcp_dbf - main dbf trace structure | ||
243 | * @pay: reference to payload trace area | ||
244 | * @rec: reference to recovery trace area | ||
245 | * @hba: reference to hba trace area | ||
246 | * @san: reference to san trace area | ||
247 | * @scsi: reference to scsi trace area | ||
248 | * @pay_lock: lock protecting payload trace buffer | ||
249 | * @rec_lock: lock protecting recovery trace buffer | ||
250 | * @hba_lock: lock protecting hba trace buffer | ||
251 | * @san_lock: lock protecting san trace buffer | ||
252 | * @scsi_lock: lock protecting scsi trace buffer | ||
253 | * @pay_buf: pre-allocated buffer for payload | ||
254 | * @rec_buf: pre-allocated buffer for recovery | ||
255 | * @hba_buf: pre-allocated buffer for hba | ||
256 | * @san_buf: pre-allocated buffer for san | ||
257 | * @scsi_buf: pre-allocated buffer for scsi | ||
258 | */ | ||
228 | struct zfcp_dbf { | 259 | struct zfcp_dbf { |
260 | debug_info_t *pay; | ||
229 | debug_info_t *rec; | 261 | debug_info_t *rec; |
230 | debug_info_t *hba; | 262 | debug_info_t *hba; |
231 | debug_info_t *san; | 263 | debug_info_t *san; |
232 | debug_info_t *scsi; | 264 | debug_info_t *scsi; |
265 | spinlock_t pay_lock; | ||
233 | spinlock_t rec_lock; | 266 | spinlock_t rec_lock; |
234 | spinlock_t hba_lock; | 267 | spinlock_t hba_lock; |
235 | spinlock_t san_lock; | 268 | spinlock_t san_lock; |
236 | spinlock_t scsi_lock; | 269 | spinlock_t scsi_lock; |
237 | struct zfcp_dbf_rec_record rec_buf; | 270 | struct zfcp_dbf_pay pay_buf; |
238 | struct zfcp_dbf_hba_record hba_buf; | 271 | struct zfcp_dbf_rec rec_buf; |
239 | struct zfcp_dbf_san_record san_buf; | 272 | struct zfcp_dbf_hba hba_buf; |
240 | struct zfcp_dbf_scsi_record scsi_buf; | 273 | struct zfcp_dbf_san san_buf; |
241 | struct zfcp_adapter *adapter; | 274 | struct zfcp_dbf_scsi scsi_buf; |
242 | }; | 275 | }; |
243 | 276 | ||
244 | static inline | 277 | static inline |
245 | void zfcp_dbf_hba_fsf_resp(const char *tag2, int level, | 278 | void zfcp_dbf_hba_fsf_resp(char *tag, int level, struct zfcp_fsf_req *req) |
246 | struct zfcp_fsf_req *req, struct zfcp_dbf *dbf) | ||
247 | { | 279 | { |
248 | if (level <= dbf->hba->level) | 280 | if (level <= req->adapter->dbf->hba->level) |
249 | _zfcp_dbf_hba_fsf_response(tag2, level, req, dbf); | 281 | zfcp_dbf_hba_fsf_res(tag, req); |
250 | } | 282 | } |
251 | 283 | ||
252 | /** | 284 | /** |
253 | * zfcp_dbf_hba_fsf_response - trace event for request completion | 285 | * zfcp_dbf_hba_fsf_response - trace event for request completion |
254 | * @fsf_req: request that has been completed | 286 | * @req: request that has been completed |
255 | */ | 287 | */ |
256 | static inline void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req) | 288 | static inline |
289 | void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req) | ||
257 | { | 290 | { |
258 | struct zfcp_dbf *dbf = req->adapter->dbf; | ||
259 | struct fsf_qtcb *qtcb = req->qtcb; | 291 | struct fsf_qtcb *qtcb = req->qtcb; |
260 | 292 | ||
261 | if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) && | 293 | if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) && |
262 | (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) { | 294 | (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) { |
263 | zfcp_dbf_hba_fsf_resp("perr", 1, req, dbf); | 295 | zfcp_dbf_hba_fsf_resp("fs_perr", 1, req); |
264 | 296 | ||
265 | } else if (qtcb->header.fsf_status != FSF_GOOD) { | 297 | } else if (qtcb->header.fsf_status != FSF_GOOD) { |
266 | zfcp_dbf_hba_fsf_resp("ferr", 1, req, dbf); | 298 | zfcp_dbf_hba_fsf_resp("fs_ferr", 1, req); |
267 | 299 | ||
268 | } else if ((req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) || | 300 | } else if ((req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) || |
269 | (req->fsf_command == FSF_QTCB_OPEN_LUN)) { | 301 | (req->fsf_command == FSF_QTCB_OPEN_LUN)) { |
270 | zfcp_dbf_hba_fsf_resp("open", 4, req, dbf); | 302 | zfcp_dbf_hba_fsf_resp("fs_open", 4, req); |
271 | 303 | ||
272 | } else if (qtcb->header.log_length) { | 304 | } else if (qtcb->header.log_length) { |
273 | zfcp_dbf_hba_fsf_resp("qtcb", 5, req, dbf); | 305 | zfcp_dbf_hba_fsf_resp("fs_qtcb", 5, req); |
274 | 306 | ||
275 | } else { | 307 | } else { |
276 | zfcp_dbf_hba_fsf_resp("norm", 6, req, dbf); | 308 | zfcp_dbf_hba_fsf_resp("fs_norm", 6, req); |
277 | } | 309 | } |
278 | } | ||
279 | |||
280 | /** | ||
281 | * zfcp_dbf_hba_fsf_unsol - trace event for an unsolicited status buffer | ||
282 | * @tag: tag indicating which kind of unsolicited status has been received | ||
283 | * @dbf: reference to dbf structure | ||
284 | * @status_buffer: buffer containing payload of unsolicited status | ||
285 | */ | ||
286 | static inline | ||
287 | void zfcp_dbf_hba_fsf_unsol(const char *tag, struct zfcp_dbf *dbf, | ||
288 | struct fsf_status_read_buffer *buf) | ||
289 | { | ||
290 | int level = 2; | ||
291 | |||
292 | if (level <= dbf->hba->level) | ||
293 | _zfcp_dbf_hba_fsf_unsol(tag, level, dbf, buf); | ||
294 | } | 310 | } |
295 | 311 | ||
296 | static inline | 312 | static inline |
297 | void zfcp_dbf_scsi(const char *tag, const char *tag2, int level, | 313 | void _zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *scmd, |
298 | struct zfcp_dbf *dbf, struct scsi_cmnd *scmd, | 314 | struct zfcp_fsf_req *req) |
299 | struct zfcp_fsf_req *req, unsigned long old_id) | ||
300 | { | 315 | { |
301 | if (level <= dbf->scsi->level) | 316 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) |
302 | _zfcp_dbf_scsi(tag, tag2, level, dbf, scmd, req, old_id); | 317 | scmd->device->host->hostdata[0]; |
318 | |||
319 | if (level <= adapter->dbf->scsi->level) | ||
320 | zfcp_dbf_scsi(tag, scmd, req); | ||
303 | } | 321 | } |
304 | 322 | ||
305 | /** | 323 | /** |
306 | * zfcp_dbf_scsi_result - trace event for SCSI command completion | 324 | * zfcp_dbf_scsi_result - trace event for SCSI command completion |
307 | * @dbf: adapter dbf trace | ||
308 | * @scmd: SCSI command pointer | 325 | * @scmd: SCSI command pointer |
309 | * @req: FSF request used to issue SCSI command | 326 | * @req: FSF request used to issue SCSI command |
310 | */ | 327 | */ |
311 | static inline | 328 | static inline |
312 | void zfcp_dbf_scsi_result(struct zfcp_dbf *dbf, struct scsi_cmnd *scmd, | 329 | void zfcp_dbf_scsi_result(struct scsi_cmnd *scmd, struct zfcp_fsf_req *req) |
313 | struct zfcp_fsf_req *req) | ||
314 | { | 330 | { |
315 | if (scmd->result != 0) | 331 | if (scmd->result != 0) |
316 | zfcp_dbf_scsi("rslt", "erro", 3, dbf, scmd, req, 0); | 332 | _zfcp_dbf_scsi("rsl_err", 3, scmd, req); |
317 | else if (scmd->retries > 0) | 333 | else if (scmd->retries > 0) |
318 | zfcp_dbf_scsi("rslt", "retr", 4, dbf, scmd, req, 0); | 334 | _zfcp_dbf_scsi("rsl_ret", 4, scmd, req); |
319 | else | 335 | else |
320 | zfcp_dbf_scsi("rslt", "norm", 6, dbf, scmd, req, 0); | 336 | _zfcp_dbf_scsi("rsl_nor", 6, scmd, req); |
321 | } | 337 | } |
322 | 338 | ||
323 | /** | 339 | /** |
324 | * zfcp_dbf_scsi_fail_send - trace event for failure to send SCSI command | 340 | * zfcp_dbf_scsi_fail_send - trace event for failure to send SCSI command |
325 | * @dbf: adapter dbf trace | ||
326 | * @scmd: SCSI command pointer | 341 | * @scmd: SCSI command pointer |
327 | */ | 342 | */ |
328 | static inline | 343 | static inline |
329 | void zfcp_dbf_scsi_fail_send(struct zfcp_dbf *dbf, struct scsi_cmnd *scmd) | 344 | void zfcp_dbf_scsi_fail_send(struct scsi_cmnd *scmd) |
330 | { | 345 | { |
331 | zfcp_dbf_scsi("rslt", "fail", 4, dbf, scmd, NULL, 0); | 346 | _zfcp_dbf_scsi("rsl_fai", 4, scmd, NULL); |
332 | } | 347 | } |
333 | 348 | ||
334 | /** | 349 | /** |
335 | * zfcp_dbf_scsi_abort - trace event for SCSI command abort | 350 | * zfcp_dbf_scsi_abort - trace event for SCSI command abort |
336 | * @tag: tag indicating success or failure of abort operation | 351 | * @tag: tag indicating success or failure of abort operation |
337 | * @adapter: adapter thas has been used to issue SCSI command to be aborted | ||
338 | * @scmd: SCSI command to be aborted | 352 | * @scmd: SCSI command to be aborted |
339 | * @new_req: request containing abort (might be NULL) | 353 | * @fsf_req: request containing abort (might be NULL) |
340 | * @old_id: identifier of request containg SCSI command to be aborted | ||
341 | */ | 354 | */ |
342 | static inline | 355 | static inline |
343 | void zfcp_dbf_scsi_abort(const char *tag, struct zfcp_dbf *dbf, | 356 | void zfcp_dbf_scsi_abort(char *tag, struct scsi_cmnd *scmd, |
344 | struct scsi_cmnd *scmd, struct zfcp_fsf_req *new_req, | 357 | struct zfcp_fsf_req *fsf_req) |
345 | unsigned long old_id) | ||
346 | { | 358 | { |
347 | zfcp_dbf_scsi("abrt", tag, 1, dbf, scmd, new_req, old_id); | 359 | _zfcp_dbf_scsi(tag, 1, scmd, fsf_req); |
348 | } | 360 | } |
349 | 361 | ||
350 | /** | 362 | /** |
351 | * zfcp_dbf_scsi_devreset - trace event for Logical Unit or Target Reset | 363 | * zfcp_dbf_scsi_devreset - trace event for Logical Unit or Target Reset |
352 | * @tag: tag indicating success or failure of reset operation | 364 | * @tag: tag indicating success or failure of reset operation |
365 | * @scmnd: SCSI command which caused this error recovery | ||
353 | * @flag: indicates type of reset (Target Reset, Logical Unit Reset) | 366 | * @flag: indicates type of reset (Target Reset, Logical Unit Reset) |
354 | * @unit: unit that needs reset | ||
355 | * @scsi_cmnd: SCSI command which caused this error recovery | ||
356 | */ | 367 | */ |
357 | static inline | 368 | static inline |
358 | void zfcp_dbf_scsi_devreset(const char *tag, u8 flag, struct zfcp_unit *unit, | 369 | void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag) |
359 | struct scsi_cmnd *scsi_cmnd) | ||
360 | { | 370 | { |
361 | zfcp_dbf_scsi(flag == FCP_TMF_TGT_RESET ? "trst" : "lrst", tag, 1, | 371 | char tmp_tag[ZFCP_DBF_TAG_LEN]; |
362 | unit->port->adapter->dbf, scsi_cmnd, NULL, 0); | 372 | |
373 | if (flag == FCP_TMF_TGT_RESET) | ||
374 | memcpy(tmp_tag, "tr_", 3); | ||
375 | else | ||
376 | memcpy(tmp_tag, "lr_", 3); | ||
377 | |||
378 | memcpy(&tmp_tag[3], tag, 4); | ||
379 | _zfcp_dbf_scsi(tmp_tag, 1, scmnd, NULL); | ||
363 | } | 380 | } |
364 | 381 | ||
365 | #endif /* ZFCP_DBF_H */ | 382 | #endif /* ZFCP_DBF_H */ |
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index e1c6b6e05a75..527ba48eea57 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -85,11 +85,10 @@ struct zfcp_reqlist; | |||
85 | #define ZFCP_STATUS_PORT_LINK_TEST 0x00000002 | 85 | #define ZFCP_STATUS_PORT_LINK_TEST 0x00000002 |
86 | 86 | ||
87 | /* logical unit status */ | 87 | /* logical unit status */ |
88 | #define ZFCP_STATUS_UNIT_SHARED 0x00000004 | 88 | #define ZFCP_STATUS_LUN_SHARED 0x00000004 |
89 | #define ZFCP_STATUS_UNIT_READONLY 0x00000008 | 89 | #define ZFCP_STATUS_LUN_READONLY 0x00000008 |
90 | 90 | ||
91 | /* FSF request status (this does not have a common part) */ | 91 | /* FSF request status (this does not have a common part) */ |
92 | #define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002 | ||
93 | #define ZFCP_STATUS_FSFREQ_ERROR 0x00000008 | 92 | #define ZFCP_STATUS_FSFREQ_ERROR 0x00000008 |
94 | #define ZFCP_STATUS_FSFREQ_CLEANUP 0x00000010 | 93 | #define ZFCP_STATUS_FSFREQ_CLEANUP 0x00000010 |
95 | #define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED 0x00000040 | 94 | #define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED 0x00000040 |
@@ -108,7 +107,7 @@ struct zfcp_adapter_mempool { | |||
108 | mempool_t *scsi_req; | 107 | mempool_t *scsi_req; |
109 | mempool_t *scsi_abort; | 108 | mempool_t *scsi_abort; |
110 | mempool_t *status_read_req; | 109 | mempool_t *status_read_req; |
111 | mempool_t *status_read_data; | 110 | mempool_t *sr_data; |
112 | mempool_t *gid_pn; | 111 | mempool_t *gid_pn; |
113 | mempool_t *qtcb_pool; | 112 | mempool_t *qtcb_pool; |
114 | }; | 113 | }; |
@@ -118,7 +117,7 @@ struct zfcp_erp_action { | |||
118 | int action; /* requested action code */ | 117 | int action; /* requested action code */ |
119 | struct zfcp_adapter *adapter; /* device which should be recovered */ | 118 | struct zfcp_adapter *adapter; /* device which should be recovered */ |
120 | struct zfcp_port *port; | 119 | struct zfcp_port *port; |
121 | struct zfcp_unit *unit; | 120 | struct scsi_device *sdev; |
122 | u32 status; /* recovery status */ | 121 | u32 status; /* recovery status */ |
123 | u32 step; /* active step of this erp action */ | 122 | u32 step; /* active step of this erp action */ |
124 | unsigned long fsf_req_id; | 123 | unsigned long fsf_req_id; |
@@ -190,6 +189,7 @@ struct zfcp_adapter { | |||
190 | struct fsf_qtcb_bottom_port *stats_reset_data; | 189 | struct fsf_qtcb_bottom_port *stats_reset_data; |
191 | unsigned long stats_reset; | 190 | unsigned long stats_reset; |
192 | struct work_struct scan_work; | 191 | struct work_struct scan_work; |
192 | struct work_struct ns_up_work; | ||
193 | struct service_level service_level; | 193 | struct service_level service_level; |
194 | struct workqueue_struct *work_queue; | 194 | struct workqueue_struct *work_queue; |
195 | struct device_dma_parameters dma_parms; | 195 | struct device_dma_parameters dma_parms; |
@@ -219,21 +219,66 @@ struct zfcp_port { | |||
219 | unsigned int starget_id; | 219 | unsigned int starget_id; |
220 | }; | 220 | }; |
221 | 221 | ||
222 | /** | ||
223 | * struct zfcp_unit - LUN configured via zfcp sysfs | ||
224 | * @dev: struct device for sysfs representation and reference counting | ||
225 | * @list: entry in LUN/unit list per zfcp_port | ||
226 | * @port: reference to zfcp_port where this LUN is configured | ||
227 | * @fcp_lun: 64 bit LUN value | ||
228 | * @scsi_work: for running scsi_scan_target | ||
229 | * | ||
230 | * This is the representation of a LUN that has been configured for | ||
231 | * usage. The main data here is the 64 bit LUN value, data for | ||
232 | * running I/O and recovery is in struct zfcp_scsi_dev. | ||
233 | */ | ||
222 | struct zfcp_unit { | 234 | struct zfcp_unit { |
223 | struct device dev; | 235 | struct device dev; |
224 | struct list_head list; /* list of logical units */ | 236 | struct list_head list; |
225 | struct zfcp_port *port; /* remote port of unit */ | 237 | struct zfcp_port *port; |
226 | atomic_t status; /* status of this logical unit */ | 238 | u64 fcp_lun; |
227 | u64 fcp_lun; /* own FCP_LUN */ | ||
228 | u32 handle; /* handle assigned by FSF */ | ||
229 | struct scsi_device *device; /* scsi device struct pointer */ | ||
230 | struct zfcp_erp_action erp_action; /* pending error recovery */ | ||
231 | atomic_t erp_counter; | ||
232 | struct zfcp_latencies latencies; | ||
233 | struct work_struct scsi_work; | 239 | struct work_struct scsi_work; |
234 | }; | 240 | }; |
235 | 241 | ||
236 | /** | 242 | /** |
243 | * struct zfcp_scsi_dev - zfcp data per SCSI device | ||
244 | * @status: zfcp internal status flags | ||
245 | * @lun_handle: handle from "open lun" for issuing FSF requests | ||
246 | * @erp_action: zfcp erp data for opening and recovering this LUN | ||
247 | * @erp_counter: zfcp erp counter for this LUN | ||
248 | * @latencies: FSF channel and fabric latencies | ||
249 | * @port: zfcp_port where this LUN belongs to | ||
250 | */ | ||
251 | struct zfcp_scsi_dev { | ||
252 | atomic_t status; | ||
253 | u32 lun_handle; | ||
254 | struct zfcp_erp_action erp_action; | ||
255 | atomic_t erp_counter; | ||
256 | struct zfcp_latencies latencies; | ||
257 | struct zfcp_port *port; | ||
258 | }; | ||
259 | |||
260 | /** | ||
261 | * sdev_to_zfcp - Access zfcp LUN data for SCSI device | ||
262 | * @sdev: scsi_device where to get the zfcp_scsi_dev pointer | ||
263 | */ | ||
264 | static inline struct zfcp_scsi_dev *sdev_to_zfcp(struct scsi_device *sdev) | ||
265 | { | ||
266 | return scsi_transport_device_data(sdev); | ||
267 | } | ||
268 | |||
269 | /** | ||
270 | * zfcp_scsi_dev_lun - Return SCSI device LUN as 64 bit FCP LUN | ||
271 | * @sdev: SCSI device where to get the LUN from | ||
272 | */ | ||
273 | static inline u64 zfcp_scsi_dev_lun(struct scsi_device *sdev) | ||
274 | { | ||
275 | u64 fcp_lun; | ||
276 | |||
277 | int_to_scsilun(sdev->lun, (struct scsi_lun *)&fcp_lun); | ||
278 | return fcp_lun; | ||
279 | } | ||
280 | |||
281 | /** | ||
237 | * struct zfcp_fsf_req - basic FSF request structure | 282 | * struct zfcp_fsf_req - basic FSF request structure |
238 | * @list: list of FSF requests | 283 | * @list: list of FSF requests |
239 | * @req_id: unique request ID | 284 | * @req_id: unique request ID |
@@ -249,7 +294,6 @@ struct zfcp_unit { | |||
249 | * @erp_action: reference to erp action if request issued on behalf of ERP | 294 | * @erp_action: reference to erp action if request issued on behalf of ERP |
250 | * @pool: reference to memory pool if used for this request | 295 | * @pool: reference to memory pool if used for this request |
251 | * @issued: time when request was send (STCK) | 296 | * @issued: time when request was send (STCK) |
252 | * @unit: reference to unit if this request is a SCSI request | ||
253 | * @handler: handler which should be called to process response | 297 | * @handler: handler which should be called to process response |
254 | */ | 298 | */ |
255 | struct zfcp_fsf_req { | 299 | struct zfcp_fsf_req { |
@@ -267,24 +311,7 @@ struct zfcp_fsf_req { | |||
267 | struct zfcp_erp_action *erp_action; | 311 | struct zfcp_erp_action *erp_action; |
268 | mempool_t *pool; | 312 | mempool_t *pool; |
269 | unsigned long long issued; | 313 | unsigned long long issued; |
270 | struct zfcp_unit *unit; | ||
271 | void (*handler)(struct zfcp_fsf_req *); | 314 | void (*handler)(struct zfcp_fsf_req *); |
272 | }; | 315 | }; |
273 | 316 | ||
274 | /* driver data */ | ||
275 | struct zfcp_data { | ||
276 | struct scsi_host_template scsi_host_template; | ||
277 | struct scsi_transport_template *scsi_transport_template; | ||
278 | struct kmem_cache *gpn_ft_cache; | ||
279 | struct kmem_cache *qtcb_cache; | ||
280 | struct kmem_cache *sr_buffer_cache; | ||
281 | struct kmem_cache *gid_pn_cache; | ||
282 | struct kmem_cache *adisc_cache; | ||
283 | }; | ||
284 | |||
285 | /********************** ZFCP SPECIFIC DEFINES ********************************/ | ||
286 | |||
287 | #define ZFCP_SET 0x00000100 | ||
288 | #define ZFCP_CLEAR 0x00000200 | ||
289 | |||
290 | #endif /* ZFCP_DEF_H */ | 317 | #endif /* ZFCP_DEF_H */ |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 160b432c907f..e1b4f800e226 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -21,6 +21,7 @@ enum zfcp_erp_act_flags { | |||
21 | ZFCP_STATUS_ERP_DISMISSING = 0x00100000, | 21 | ZFCP_STATUS_ERP_DISMISSING = 0x00100000, |
22 | ZFCP_STATUS_ERP_DISMISSED = 0x00200000, | 22 | ZFCP_STATUS_ERP_DISMISSED = 0x00200000, |
23 | ZFCP_STATUS_ERP_LOWMEM = 0x00400000, | 23 | ZFCP_STATUS_ERP_LOWMEM = 0x00400000, |
24 | ZFCP_STATUS_ERP_NO_REF = 0x00800000, | ||
24 | }; | 25 | }; |
25 | 26 | ||
26 | enum zfcp_erp_steps { | 27 | enum zfcp_erp_steps { |
@@ -29,12 +30,12 @@ enum zfcp_erp_steps { | |||
29 | ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, | 30 | ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, |
30 | ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, | 31 | ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, |
31 | ZFCP_ERP_STEP_PORT_OPENING = 0x0800, | 32 | ZFCP_ERP_STEP_PORT_OPENING = 0x0800, |
32 | ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000, | 33 | ZFCP_ERP_STEP_LUN_CLOSING = 0x1000, |
33 | ZFCP_ERP_STEP_UNIT_OPENING = 0x2000, | 34 | ZFCP_ERP_STEP_LUN_OPENING = 0x2000, |
34 | }; | 35 | }; |
35 | 36 | ||
36 | enum zfcp_erp_act_type { | 37 | enum zfcp_erp_act_type { |
37 | ZFCP_ERP_ACTION_REOPEN_UNIT = 1, | 38 | ZFCP_ERP_ACTION_REOPEN_LUN = 1, |
38 | ZFCP_ERP_ACTION_REOPEN_PORT = 2, | 39 | ZFCP_ERP_ACTION_REOPEN_PORT = 2, |
39 | ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3, | 40 | ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3, |
40 | ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4, | 41 | ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4, |
@@ -56,9 +57,8 @@ enum zfcp_erp_act_result { | |||
56 | 57 | ||
57 | static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask) | 58 | static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask) |
58 | { | 59 | { |
59 | zfcp_erp_modify_adapter_status(adapter, "erablk1", NULL, | 60 | zfcp_erp_clear_adapter_status(adapter, |
60 | ZFCP_STATUS_COMMON_UNBLOCKED | mask, | 61 | ZFCP_STATUS_COMMON_UNBLOCKED | mask); |
61 | ZFCP_CLEAR); | ||
62 | } | 62 | } |
63 | 63 | ||
64 | static int zfcp_erp_action_exists(struct zfcp_erp_action *act) | 64 | static int zfcp_erp_action_exists(struct zfcp_erp_action *act) |
@@ -76,9 +76,9 @@ static void zfcp_erp_action_ready(struct zfcp_erp_action *act) | |||
76 | struct zfcp_adapter *adapter = act->adapter; | 76 | struct zfcp_adapter *adapter = act->adapter; |
77 | 77 | ||
78 | list_move(&act->list, &act->adapter->erp_ready_head); | 78 | list_move(&act->list, &act->adapter->erp_ready_head); |
79 | zfcp_dbf_rec_action("erardy1", act); | 79 | zfcp_dbf_rec_run("erardy1", act); |
80 | wake_up(&adapter->erp_ready_wq); | 80 | wake_up(&adapter->erp_ready_wq); |
81 | zfcp_dbf_rec_thread("erardy2", adapter->dbf); | 81 | zfcp_dbf_rec_run("erardy2", act); |
82 | } | 82 | } |
83 | 83 | ||
84 | static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act) | 84 | static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act) |
@@ -88,24 +88,24 @@ static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act) | |||
88 | zfcp_erp_action_ready(act); | 88 | zfcp_erp_action_ready(act); |
89 | } | 89 | } |
90 | 90 | ||
91 | static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) | 91 | static void zfcp_erp_action_dismiss_lun(struct scsi_device *sdev) |
92 | { | 92 | { |
93 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_INUSE) | 93 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
94 | zfcp_erp_action_dismiss(&unit->erp_action); | 94 | |
95 | if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_INUSE) | ||
96 | zfcp_erp_action_dismiss(&zfcp_sdev->erp_action); | ||
95 | } | 97 | } |
96 | 98 | ||
97 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) | 99 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) |
98 | { | 100 | { |
99 | struct zfcp_unit *unit; | 101 | struct scsi_device *sdev; |
100 | 102 | ||
101 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE) | 103 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE) |
102 | zfcp_erp_action_dismiss(&port->erp_action); | 104 | zfcp_erp_action_dismiss(&port->erp_action); |
103 | else { | 105 | else |
104 | read_lock(&port->unit_list_lock); | 106 | shost_for_each_device(sdev, port->adapter->scsi_host) |
105 | list_for_each_entry(unit, &port->unit_list, list) | 107 | if (sdev_to_zfcp(sdev)->port == port) |
106 | zfcp_erp_action_dismiss_unit(unit); | 108 | zfcp_erp_action_dismiss_lun(sdev); |
107 | read_unlock(&port->unit_list_lock); | ||
108 | } | ||
109 | } | 109 | } |
110 | 110 | ||
111 | static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) | 111 | static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) |
@@ -124,15 +124,17 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) | |||
124 | 124 | ||
125 | static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, | 125 | static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, |
126 | struct zfcp_port *port, | 126 | struct zfcp_port *port, |
127 | struct zfcp_unit *unit) | 127 | struct scsi_device *sdev) |
128 | { | 128 | { |
129 | int need = want; | 129 | int need = want; |
130 | int u_status, p_status, a_status; | 130 | int l_status, p_status, a_status; |
131 | struct zfcp_scsi_dev *zfcp_sdev; | ||
131 | 132 | ||
132 | switch (want) { | 133 | switch (want) { |
133 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 134 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
134 | u_status = atomic_read(&unit->status); | 135 | zfcp_sdev = sdev_to_zfcp(sdev); |
135 | if (u_status & ZFCP_STATUS_COMMON_ERP_INUSE) | 136 | l_status = atomic_read(&zfcp_sdev->status); |
137 | if (l_status & ZFCP_STATUS_COMMON_ERP_INUSE) | ||
136 | return 0; | 138 | return 0; |
137 | p_status = atomic_read(&port->status); | 139 | p_status = atomic_read(&port->status); |
138 | if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) || | 140 | if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) || |
@@ -154,6 +156,8 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, | |||
154 | if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) || | 156 | if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) || |
155 | a_status & ZFCP_STATUS_COMMON_ERP_FAILED) | 157 | a_status & ZFCP_STATUS_COMMON_ERP_FAILED) |
156 | return 0; | 158 | return 0; |
159 | if (p_status & ZFCP_STATUS_COMMON_NOESC) | ||
160 | return need; | ||
157 | if (!(a_status & ZFCP_STATUS_COMMON_UNBLOCKED)) | 161 | if (!(a_status & ZFCP_STATUS_COMMON_UNBLOCKED)) |
158 | need = ZFCP_ERP_ACTION_REOPEN_ADAPTER; | 162 | need = ZFCP_ERP_ACTION_REOPEN_ADAPTER; |
159 | /* fall through */ | 163 | /* fall through */ |
@@ -169,22 +173,29 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, | |||
169 | return need; | 173 | return need; |
170 | } | 174 | } |
171 | 175 | ||
172 | static struct zfcp_erp_action *zfcp_erp_setup_act(int need, | 176 | static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, |
173 | struct zfcp_adapter *adapter, | 177 | struct zfcp_adapter *adapter, |
174 | struct zfcp_port *port, | 178 | struct zfcp_port *port, |
175 | struct zfcp_unit *unit) | 179 | struct scsi_device *sdev) |
176 | { | 180 | { |
177 | struct zfcp_erp_action *erp_action; | 181 | struct zfcp_erp_action *erp_action; |
178 | u32 status = 0; | 182 | struct zfcp_scsi_dev *zfcp_sdev; |
179 | 183 | ||
180 | switch (need) { | 184 | switch (need) { |
181 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 185 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
182 | if (!get_device(&unit->dev)) | 186 | zfcp_sdev = sdev_to_zfcp(sdev); |
183 | return NULL; | 187 | if (!(act_status & ZFCP_STATUS_ERP_NO_REF)) |
184 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); | 188 | if (scsi_device_get(sdev)) |
185 | erp_action = &unit->erp_action; | 189 | return NULL; |
186 | if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING)) | 190 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, |
187 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | 191 | &zfcp_sdev->status); |
192 | erp_action = &zfcp_sdev->erp_action; | ||
193 | memset(erp_action, 0, sizeof(struct zfcp_erp_action)); | ||
194 | erp_action->port = port; | ||
195 | erp_action->sdev = sdev; | ||
196 | if (!(atomic_read(&zfcp_sdev->status) & | ||
197 | ZFCP_STATUS_COMMON_RUNNING)) | ||
198 | act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; | ||
188 | break; | 199 | break; |
189 | 200 | ||
190 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 201 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
@@ -194,8 +205,10 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, | |||
194 | zfcp_erp_action_dismiss_port(port); | 205 | zfcp_erp_action_dismiss_port(port); |
195 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); | 206 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); |
196 | erp_action = &port->erp_action; | 207 | erp_action = &port->erp_action; |
208 | memset(erp_action, 0, sizeof(struct zfcp_erp_action)); | ||
209 | erp_action->port = port; | ||
197 | if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING)) | 210 | if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING)) |
198 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | 211 | act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; |
199 | break; | 212 | break; |
200 | 213 | ||
201 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 214 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
@@ -203,66 +216,65 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, | |||
203 | zfcp_erp_action_dismiss_adapter(adapter); | 216 | zfcp_erp_action_dismiss_adapter(adapter); |
204 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); | 217 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); |
205 | erp_action = &adapter->erp_action; | 218 | erp_action = &adapter->erp_action; |
219 | memset(erp_action, 0, sizeof(struct zfcp_erp_action)); | ||
206 | if (!(atomic_read(&adapter->status) & | 220 | if (!(atomic_read(&adapter->status) & |
207 | ZFCP_STATUS_COMMON_RUNNING)) | 221 | ZFCP_STATUS_COMMON_RUNNING)) |
208 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | 222 | act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; |
209 | break; | 223 | break; |
210 | 224 | ||
211 | default: | 225 | default: |
212 | return NULL; | 226 | return NULL; |
213 | } | 227 | } |
214 | 228 | ||
215 | memset(erp_action, 0, sizeof(struct zfcp_erp_action)); | ||
216 | erp_action->adapter = adapter; | 229 | erp_action->adapter = adapter; |
217 | erp_action->port = port; | ||
218 | erp_action->unit = unit; | ||
219 | erp_action->action = need; | 230 | erp_action->action = need; |
220 | erp_action->status = status; | 231 | erp_action->status = act_status; |
221 | 232 | ||
222 | return erp_action; | 233 | return erp_action; |
223 | } | 234 | } |
224 | 235 | ||
225 | static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, | 236 | static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, |
226 | struct zfcp_port *port, | 237 | struct zfcp_port *port, |
227 | struct zfcp_unit *unit, char *id, void *ref) | 238 | struct scsi_device *sdev, |
239 | char *id, u32 act_status) | ||
228 | { | 240 | { |
229 | int retval = 1, need; | 241 | int retval = 1, need; |
230 | struct zfcp_erp_action *act = NULL; | 242 | struct zfcp_erp_action *act; |
231 | 243 | ||
232 | if (!adapter->erp_thread) | 244 | if (!adapter->erp_thread) |
233 | return -EIO; | 245 | return -EIO; |
234 | 246 | ||
235 | need = zfcp_erp_required_act(want, adapter, port, unit); | 247 | need = zfcp_erp_required_act(want, adapter, port, sdev); |
236 | if (!need) | 248 | if (!need) |
237 | goto out; | 249 | goto out; |
238 | 250 | ||
239 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); | 251 | act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev); |
240 | act = zfcp_erp_setup_act(need, adapter, port, unit); | ||
241 | if (!act) | 252 | if (!act) |
242 | goto out; | 253 | goto out; |
254 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); | ||
243 | ++adapter->erp_total_count; | 255 | ++adapter->erp_total_count; |
244 | list_add_tail(&act->list, &adapter->erp_ready_head); | 256 | list_add_tail(&act->list, &adapter->erp_ready_head); |
245 | wake_up(&adapter->erp_ready_wq); | 257 | wake_up(&adapter->erp_ready_wq); |
246 | zfcp_dbf_rec_thread("eracte1", adapter->dbf); | ||
247 | retval = 0; | 258 | retval = 0; |
248 | out: | 259 | out: |
249 | zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, unit); | 260 | zfcp_dbf_rec_trig(id, adapter, port, sdev, want, need); |
250 | return retval; | 261 | return retval; |
251 | } | 262 | } |
252 | 263 | ||
253 | static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, | 264 | static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, |
254 | int clear_mask, char *id, void *ref) | 265 | int clear_mask, char *id) |
255 | { | 266 | { |
256 | zfcp_erp_adapter_block(adapter, clear_mask); | 267 | zfcp_erp_adapter_block(adapter, clear_mask); |
257 | zfcp_scsi_schedule_rports_block(adapter); | 268 | zfcp_scsi_schedule_rports_block(adapter); |
258 | 269 | ||
259 | /* ensure propagation of failed status to new devices */ | 270 | /* ensure propagation of failed status to new devices */ |
260 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { | 271 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
261 | zfcp_erp_adapter_failed(adapter, "erareo1", NULL); | 272 | zfcp_erp_set_adapter_status(adapter, |
273 | ZFCP_STATUS_COMMON_ERP_FAILED); | ||
262 | return -EIO; | 274 | return -EIO; |
263 | } | 275 | } |
264 | return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, | 276 | return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, |
265 | adapter, NULL, NULL, id, ref); | 277 | adapter, NULL, NULL, id, 0); |
266 | } | 278 | } |
267 | 279 | ||
268 | /** | 280 | /** |
@@ -270,10 +282,8 @@ static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, | |||
270 | * @adapter: Adapter to reopen. | 282 | * @adapter: Adapter to reopen. |
271 | * @clear: Status flags to clear. | 283 | * @clear: Status flags to clear. |
272 | * @id: Id for debug trace event. | 284 | * @id: Id for debug trace event. |
273 | * @ref: Reference for debug trace event. | ||
274 | */ | 285 | */ |
275 | void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, | 286 | void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, char *id) |
276 | char *id, void *ref) | ||
277 | { | 287 | { |
278 | unsigned long flags; | 288 | unsigned long flags; |
279 | 289 | ||
@@ -282,10 +292,11 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, | |||
282 | 292 | ||
283 | write_lock_irqsave(&adapter->erp_lock, flags); | 293 | write_lock_irqsave(&adapter->erp_lock, flags); |
284 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) | 294 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) |
285 | zfcp_erp_adapter_failed(adapter, "erareo1", NULL); | 295 | zfcp_erp_set_adapter_status(adapter, |
296 | ZFCP_STATUS_COMMON_ERP_FAILED); | ||
286 | else | 297 | else |
287 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, | 298 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, |
288 | NULL, NULL, id, ref); | 299 | NULL, NULL, id, 0); |
289 | write_unlock_irqrestore(&adapter->erp_lock, flags); | 300 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
290 | } | 301 | } |
291 | 302 | ||
@@ -294,13 +305,12 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, | |||
294 | * @adapter: Adapter to shut down. | 305 | * @adapter: Adapter to shut down. |
295 | * @clear: Status flags to clear. | 306 | * @clear: Status flags to clear. |
296 | * @id: Id for debug trace event. | 307 | * @id: Id for debug trace event. |
297 | * @ref: Reference for debug trace event. | ||
298 | */ | 308 | */ |
299 | void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear, | 309 | void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear, |
300 | char *id, void *ref) | 310 | char *id) |
301 | { | 311 | { |
302 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; | 312 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; |
303 | zfcp_erp_adapter_reopen(adapter, clear | flags, id, ref); | 313 | zfcp_erp_adapter_reopen(adapter, clear | flags, id); |
304 | } | 314 | } |
305 | 315 | ||
306 | /** | 316 | /** |
@@ -308,38 +318,21 @@ void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear, | |||
308 | * @port: Port to shut down. | 318 | * @port: Port to shut down. |
309 | * @clear: Status flags to clear. | 319 | * @clear: Status flags to clear. |
310 | * @id: Id for debug trace event. | 320 | * @id: Id for debug trace event. |
311 | * @ref: Reference for debug trace event. | ||
312 | */ | ||
313 | void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id, | ||
314 | void *ref) | ||
315 | { | ||
316 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; | ||
317 | zfcp_erp_port_reopen(port, clear | flags, id, ref); | ||
318 | } | ||
319 | |||
320 | /** | ||
321 | * zfcp_erp_unit_shutdown - Shutdown unit | ||
322 | * @unit: Unit to shut down. | ||
323 | * @clear: Status flags to clear. | ||
324 | * @id: Id for debug trace event. | ||
325 | * @ref: Reference for debug trace event. | ||
326 | */ | 321 | */ |
327 | void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, char *id, | 322 | void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id) |
328 | void *ref) | ||
329 | { | 323 | { |
330 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; | 324 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; |
331 | zfcp_erp_unit_reopen(unit, clear | flags, id, ref); | 325 | zfcp_erp_port_reopen(port, clear | flags, id); |
332 | } | 326 | } |
333 | 327 | ||
334 | static void zfcp_erp_port_block(struct zfcp_port *port, int clear) | 328 | static void zfcp_erp_port_block(struct zfcp_port *port, int clear) |
335 | { | 329 | { |
336 | zfcp_erp_modify_port_status(port, "erpblk1", NULL, | 330 | zfcp_erp_clear_port_status(port, |
337 | ZFCP_STATUS_COMMON_UNBLOCKED | clear, | 331 | ZFCP_STATUS_COMMON_UNBLOCKED | clear); |
338 | ZFCP_CLEAR); | ||
339 | } | 332 | } |
340 | 333 | ||
341 | static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, | 334 | static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, |
342 | int clear, char *id, void *ref) | 335 | char *id) |
343 | { | 336 | { |
344 | zfcp_erp_port_block(port, clear); | 337 | zfcp_erp_port_block(port, clear); |
345 | zfcp_scsi_schedule_rport_block(port); | 338 | zfcp_scsi_schedule_rport_block(port); |
@@ -348,136 +341,171 @@ static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, | |||
348 | return; | 341 | return; |
349 | 342 | ||
350 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, | 343 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, |
351 | port->adapter, port, NULL, id, ref); | 344 | port->adapter, port, NULL, id, 0); |
352 | } | 345 | } |
353 | 346 | ||
354 | /** | 347 | /** |
355 | * zfcp_erp_port_forced_reopen - Forced close of port and open again | 348 | * zfcp_erp_port_forced_reopen - Forced close of port and open again |
356 | * @port: Port to force close and to reopen. | 349 | * @port: Port to force close and to reopen. |
350 | * @clear: Status flags to clear. | ||
357 | * @id: Id for debug trace event. | 351 | * @id: Id for debug trace event. |
358 | * @ref: Reference for debug trace event. | ||
359 | */ | 352 | */ |
360 | void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id, | 353 | void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id) |
361 | void *ref) | ||
362 | { | 354 | { |
363 | unsigned long flags; | 355 | unsigned long flags; |
364 | struct zfcp_adapter *adapter = port->adapter; | 356 | struct zfcp_adapter *adapter = port->adapter; |
365 | 357 | ||
366 | write_lock_irqsave(&adapter->erp_lock, flags); | 358 | write_lock_irqsave(&adapter->erp_lock, flags); |
367 | _zfcp_erp_port_forced_reopen(port, clear, id, ref); | 359 | _zfcp_erp_port_forced_reopen(port, clear, id); |
368 | write_unlock_irqrestore(&adapter->erp_lock, flags); | 360 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
369 | } | 361 | } |
370 | 362 | ||
371 | static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, | 363 | static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) |
372 | void *ref) | ||
373 | { | 364 | { |
374 | zfcp_erp_port_block(port, clear); | 365 | zfcp_erp_port_block(port, clear); |
375 | zfcp_scsi_schedule_rport_block(port); | 366 | zfcp_scsi_schedule_rport_block(port); |
376 | 367 | ||
377 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { | 368 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
378 | /* ensure propagation of failed status to new devices */ | 369 | /* ensure propagation of failed status to new devices */ |
379 | zfcp_erp_port_failed(port, "erpreo1", NULL); | 370 | zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED); |
380 | return -EIO; | 371 | return -EIO; |
381 | } | 372 | } |
382 | 373 | ||
383 | return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, | 374 | return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, |
384 | port->adapter, port, NULL, id, ref); | 375 | port->adapter, port, NULL, id, 0); |
385 | } | 376 | } |
386 | 377 | ||
387 | /** | 378 | /** |
388 | * zfcp_erp_port_reopen - trigger remote port recovery | 379 | * zfcp_erp_port_reopen - trigger remote port recovery |
389 | * @port: port to recover | 380 | * @port: port to recover |
390 | * @clear_mask: flags in port status to be cleared | 381 | * @clear_mask: flags in port status to be cleared |
382 | * @id: Id for debug trace event. | ||
391 | * | 383 | * |
392 | * Returns 0 if recovery has been triggered, < 0 if not. | 384 | * Returns 0 if recovery has been triggered, < 0 if not. |
393 | */ | 385 | */ |
394 | int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref) | 386 | int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) |
395 | { | 387 | { |
396 | int retval; | 388 | int retval; |
397 | unsigned long flags; | 389 | unsigned long flags; |
398 | struct zfcp_adapter *adapter = port->adapter; | 390 | struct zfcp_adapter *adapter = port->adapter; |
399 | 391 | ||
400 | write_lock_irqsave(&adapter->erp_lock, flags); | 392 | write_lock_irqsave(&adapter->erp_lock, flags); |
401 | retval = _zfcp_erp_port_reopen(port, clear, id, ref); | 393 | retval = _zfcp_erp_port_reopen(port, clear, id); |
402 | write_unlock_irqrestore(&adapter->erp_lock, flags); | 394 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
403 | 395 | ||
404 | return retval; | 396 | return retval; |
405 | } | 397 | } |
406 | 398 | ||
407 | static void zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask) | 399 | static void zfcp_erp_lun_block(struct scsi_device *sdev, int clear_mask) |
408 | { | 400 | { |
409 | zfcp_erp_modify_unit_status(unit, "erublk1", NULL, | 401 | zfcp_erp_clear_lun_status(sdev, |
410 | ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, | 402 | ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask); |
411 | ZFCP_CLEAR); | ||
412 | } | 403 | } |
413 | 404 | ||
414 | static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id, | 405 | static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id, |
415 | void *ref) | 406 | u32 act_status) |
416 | { | 407 | { |
417 | struct zfcp_adapter *adapter = unit->port->adapter; | 408 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
409 | struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; | ||
418 | 410 | ||
419 | zfcp_erp_unit_block(unit, clear); | 411 | zfcp_erp_lun_block(sdev, clear); |
420 | 412 | ||
421 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) | 413 | if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) |
422 | return; | 414 | return; |
423 | 415 | ||
424 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT, | 416 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter, |
425 | adapter, unit->port, unit, id, ref); | 417 | zfcp_sdev->port, sdev, id, act_status); |
426 | } | 418 | } |
427 | 419 | ||
428 | /** | 420 | /** |
429 | * zfcp_erp_unit_reopen - initiate reopen of a unit | 421 | * zfcp_erp_lun_reopen - initiate reopen of a LUN |
430 | * @unit: unit to be reopened | 422 | * @sdev: SCSI device / LUN to be reopened |
431 | * @clear_mask: specifies flags in unit status to be cleared | 423 | * @clear_mask: specifies flags in LUN status to be cleared |
424 | * @id: Id for debug trace event. | ||
425 | * | ||
432 | * Return: 0 on success, < 0 on error | 426 | * Return: 0 on success, < 0 on error |
433 | */ | 427 | */ |
434 | void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id, | 428 | void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id) |
435 | void *ref) | ||
436 | { | 429 | { |
437 | unsigned long flags; | 430 | unsigned long flags; |
438 | struct zfcp_port *port = unit->port; | 431 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
432 | struct zfcp_port *port = zfcp_sdev->port; | ||
439 | struct zfcp_adapter *adapter = port->adapter; | 433 | struct zfcp_adapter *adapter = port->adapter; |
440 | 434 | ||
441 | write_lock_irqsave(&adapter->erp_lock, flags); | 435 | write_lock_irqsave(&adapter->erp_lock, flags); |
442 | _zfcp_erp_unit_reopen(unit, clear, id, ref); | 436 | _zfcp_erp_lun_reopen(sdev, clear, id, 0); |
443 | write_unlock_irqrestore(&adapter->erp_lock, flags); | 437 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
444 | } | 438 | } |
445 | 439 | ||
446 | static int status_change_set(unsigned long mask, atomic_t *status) | 440 | /** |
441 | * zfcp_erp_lun_shutdown - Shutdown LUN | ||
442 | * @sdev: SCSI device / LUN to shut down. | ||
443 | * @clear: Status flags to clear. | ||
444 | * @id: Id for debug trace event. | ||
445 | */ | ||
446 | void zfcp_erp_lun_shutdown(struct scsi_device *sdev, int clear, char *id) | ||
447 | { | 447 | { |
448 | return (atomic_read(status) ^ mask) & mask; | 448 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; |
449 | zfcp_erp_lun_reopen(sdev, clear | flags, id); | ||
449 | } | 450 | } |
450 | 451 | ||
451 | static int status_change_clear(unsigned long mask, atomic_t *status) | 452 | /** |
453 | * zfcp_erp_lun_shutdown_wait - Shutdown LUN and wait for erp completion | ||
454 | * @sdev: SCSI device / LUN to shut down. | ||
455 | * @id: Id for debug trace event. | ||
456 | * | ||
457 | * Do not acquire a reference for the LUN when creating the ERP | ||
458 | * action. It is safe, because this function waits for the ERP to | ||
459 | * complete first. This allows to shutdown the LUN, even when the SCSI | ||
460 | * device is in the state SDEV_DEL when scsi_device_get will fail. | ||
461 | */ | ||
462 | void zfcp_erp_lun_shutdown_wait(struct scsi_device *sdev, char *id) | ||
452 | { | 463 | { |
453 | return atomic_read(status) & mask; | 464 | unsigned long flags; |
465 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
466 | struct zfcp_port *port = zfcp_sdev->port; | ||
467 | struct zfcp_adapter *adapter = port->adapter; | ||
468 | int clear = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; | ||
469 | |||
470 | write_lock_irqsave(&adapter->erp_lock, flags); | ||
471 | _zfcp_erp_lun_reopen(sdev, clear, id, ZFCP_STATUS_ERP_NO_REF); | ||
472 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
473 | |||
474 | zfcp_erp_wait(adapter); | ||
475 | } | ||
476 | |||
477 | static int status_change_set(unsigned long mask, atomic_t *status) | ||
478 | { | ||
479 | return (atomic_read(status) ^ mask) & mask; | ||
454 | } | 480 | } |
455 | 481 | ||
456 | static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) | 482 | static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) |
457 | { | 483 | { |
458 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) | 484 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) |
459 | zfcp_dbf_rec_adapter("eraubl1", NULL, adapter->dbf); | 485 | zfcp_dbf_rec_run("eraubl1", &adapter->erp_action); |
460 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status); | 486 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status); |
461 | } | 487 | } |
462 | 488 | ||
463 | static void zfcp_erp_port_unblock(struct zfcp_port *port) | 489 | static void zfcp_erp_port_unblock(struct zfcp_port *port) |
464 | { | 490 | { |
465 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status)) | 491 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status)) |
466 | zfcp_dbf_rec_port("erpubl1", NULL, port); | 492 | zfcp_dbf_rec_run("erpubl1", &port->erp_action); |
467 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status); | 493 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status); |
468 | } | 494 | } |
469 | 495 | ||
470 | static void zfcp_erp_unit_unblock(struct zfcp_unit *unit) | 496 | static void zfcp_erp_lun_unblock(struct scsi_device *sdev) |
471 | { | 497 | { |
472 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status)) | 498 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
473 | zfcp_dbf_rec_unit("eruubl1", NULL, unit); | 499 | |
474 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status); | 500 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status)) |
501 | zfcp_dbf_rec_run("erlubl1", &sdev_to_zfcp(sdev)->erp_action); | ||
502 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status); | ||
475 | } | 503 | } |
476 | 504 | ||
477 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) | 505 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) |
478 | { | 506 | { |
479 | list_move(&erp_action->list, &erp_action->adapter->erp_running_head); | 507 | list_move(&erp_action->list, &erp_action->adapter->erp_running_head); |
480 | zfcp_dbf_rec_action("erator1", erp_action); | 508 | zfcp_dbf_rec_run("erator1", erp_action); |
481 | } | 509 | } |
482 | 510 | ||
483 | static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) | 511 | static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) |
@@ -494,11 +522,11 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) | |||
494 | if (act->status & (ZFCP_STATUS_ERP_DISMISSED | | 522 | if (act->status & (ZFCP_STATUS_ERP_DISMISSED | |
495 | ZFCP_STATUS_ERP_TIMEDOUT)) { | 523 | ZFCP_STATUS_ERP_TIMEDOUT)) { |
496 | req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; | 524 | req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; |
497 | zfcp_dbf_rec_action("erscf_1", act); | 525 | zfcp_dbf_rec_run("erscf_1", act); |
498 | req->erp_action = NULL; | 526 | req->erp_action = NULL; |
499 | } | 527 | } |
500 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) | 528 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) |
501 | zfcp_dbf_rec_action("erscf_2", act); | 529 | zfcp_dbf_rec_run("erscf_2", act); |
502 | if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) | 530 | if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) |
503 | act->fsf_req_id = 0; | 531 | act->fsf_req_id = 0; |
504 | } else | 532 | } else |
@@ -549,41 +577,40 @@ static void zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action) | |||
549 | } | 577 | } |
550 | 578 | ||
551 | static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, | 579 | static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, |
552 | int clear, char *id, void *ref) | 580 | int clear, char *id) |
553 | { | 581 | { |
554 | struct zfcp_port *port; | 582 | struct zfcp_port *port; |
555 | 583 | ||
556 | read_lock(&adapter->port_list_lock); | 584 | read_lock(&adapter->port_list_lock); |
557 | list_for_each_entry(port, &adapter->port_list, list) | 585 | list_for_each_entry(port, &adapter->port_list, list) |
558 | _zfcp_erp_port_reopen(port, clear, id, ref); | 586 | _zfcp_erp_port_reopen(port, clear, id); |
559 | read_unlock(&adapter->port_list_lock); | 587 | read_unlock(&adapter->port_list_lock); |
560 | } | 588 | } |
561 | 589 | ||
562 | static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, | 590 | static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear, |
563 | char *id, void *ref) | 591 | char *id) |
564 | { | 592 | { |
565 | struct zfcp_unit *unit; | 593 | struct scsi_device *sdev; |
566 | 594 | ||
567 | read_lock(&port->unit_list_lock); | 595 | shost_for_each_device(sdev, port->adapter->scsi_host) |
568 | list_for_each_entry(unit, &port->unit_list, list) | 596 | if (sdev_to_zfcp(sdev)->port == port) |
569 | _zfcp_erp_unit_reopen(unit, clear, id, ref); | 597 | _zfcp_erp_lun_reopen(sdev, clear, id, 0); |
570 | read_unlock(&port->unit_list_lock); | ||
571 | } | 598 | } |
572 | 599 | ||
573 | static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) | 600 | static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) |
574 | { | 601 | { |
575 | switch (act->action) { | 602 | switch (act->action) { |
576 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 603 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
577 | _zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1", NULL); | 604 | _zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1"); |
578 | break; | 605 | break; |
579 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 606 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
580 | _zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2", NULL); | 607 | _zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2"); |
581 | break; | 608 | break; |
582 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 609 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
583 | _zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL); | 610 | _zfcp_erp_port_reopen(act->port, 0, "ersff_3"); |
584 | break; | 611 | break; |
585 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 612 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
586 | _zfcp_erp_unit_reopen(act->unit, 0, "ersff_4", NULL); | 613 | _zfcp_erp_lun_reopen(act->sdev, 0, "ersff_4", 0); |
587 | break; | 614 | break; |
588 | } | 615 | } |
589 | } | 616 | } |
@@ -592,13 +619,13 @@ static void zfcp_erp_strategy_followup_success(struct zfcp_erp_action *act) | |||
592 | { | 619 | { |
593 | switch (act->action) { | 620 | switch (act->action) { |
594 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 621 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
595 | _zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1", NULL); | 622 | _zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1"); |
596 | break; | 623 | break; |
597 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 624 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
598 | _zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL); | 625 | _zfcp_erp_port_reopen(act->port, 0, "ersfs_2"); |
599 | break; | 626 | break; |
600 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 627 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
601 | _zfcp_erp_unit_reopen_all(act->port, 0, "ersfs_3", NULL); | 628 | _zfcp_erp_lun_reopen_all(act->port, 0, "ersfs_3"); |
602 | break; | 629 | break; |
603 | } | 630 | } |
604 | } | 631 | } |
@@ -617,17 +644,6 @@ static void zfcp_erp_wakeup(struct zfcp_adapter *adapter) | |||
617 | read_unlock_irqrestore(&adapter->erp_lock, flags); | 644 | read_unlock_irqrestore(&adapter->erp_lock, flags); |
618 | } | 645 | } |
619 | 646 | ||
620 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act) | ||
621 | { | ||
622 | struct zfcp_qdio *qdio = act->adapter->qdio; | ||
623 | |||
624 | if (zfcp_qdio_open(qdio)) | ||
625 | return ZFCP_ERP_FAILED; | ||
626 | init_waitqueue_head(&qdio->req_q_wq); | ||
627 | atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &act->adapter->status); | ||
628 | return ZFCP_ERP_SUCCEEDED; | ||
629 | } | ||
630 | |||
631 | static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter) | 647 | static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter) |
632 | { | 648 | { |
633 | struct zfcp_port *port; | 649 | struct zfcp_port *port; |
@@ -635,7 +651,7 @@ static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter) | |||
635 | adapter->peer_d_id); | 651 | adapter->peer_d_id); |
636 | if (IS_ERR(port)) /* error or port already attached */ | 652 | if (IS_ERR(port)) /* error or port already attached */ |
637 | return; | 653 | return; |
638 | _zfcp_erp_port_reopen(port, 0, "ereptp1", NULL); | 654 | _zfcp_erp_port_reopen(port, 0, "ereptp1"); |
639 | } | 655 | } |
640 | 656 | ||
641 | static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) | 657 | static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) |
@@ -658,10 +674,8 @@ static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) | |||
658 | return ZFCP_ERP_FAILED; | 674 | return ZFCP_ERP_FAILED; |
659 | } | 675 | } |
660 | 676 | ||
661 | zfcp_dbf_rec_thread_lock("erasfx1", adapter->dbf); | ||
662 | wait_event(adapter->erp_ready_wq, | 677 | wait_event(adapter->erp_ready_wq, |
663 | !list_empty(&adapter->erp_ready_head)); | 678 | !list_empty(&adapter->erp_ready_head)); |
664 | zfcp_dbf_rec_thread_lock("erasfx2", adapter->dbf); | ||
665 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) | 679 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) |
666 | break; | 680 | break; |
667 | 681 | ||
@@ -700,10 +714,10 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act) | |||
700 | if (ret) | 714 | if (ret) |
701 | return ZFCP_ERP_FAILED; | 715 | return ZFCP_ERP_FAILED; |
702 | 716 | ||
703 | zfcp_dbf_rec_thread_lock("erasox1", adapter->dbf); | 717 | zfcp_dbf_rec_run("erasox1", act); |
704 | wait_event(adapter->erp_ready_wq, | 718 | wait_event(adapter->erp_ready_wq, |
705 | !list_empty(&adapter->erp_ready_head)); | 719 | !list_empty(&adapter->erp_ready_head)); |
706 | zfcp_dbf_rec_thread_lock("erasox2", adapter->dbf); | 720 | zfcp_dbf_rec_run("erasox2", act); |
707 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) | 721 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) |
708 | return ZFCP_ERP_FAILED; | 722 | return ZFCP_ERP_FAILED; |
709 | 723 | ||
@@ -718,7 +732,7 @@ static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act) | |||
718 | if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED) | 732 | if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED) |
719 | return ZFCP_ERP_FAILED; | 733 | return ZFCP_ERP_FAILED; |
720 | 734 | ||
721 | if (mempool_resize(act->adapter->pool.status_read_data, | 735 | if (mempool_resize(act->adapter->pool.sr_data, |
722 | act->adapter->stat_read_buf_num, GFP_KERNEL)) | 736 | act->adapter->stat_read_buf_num, GFP_KERNEL)) |
723 | return ZFCP_ERP_FAILED; | 737 | return ZFCP_ERP_FAILED; |
724 | 738 | ||
@@ -742,9 +756,8 @@ static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act) | |||
742 | zfcp_fsf_req_dismiss_all(adapter); | 756 | zfcp_fsf_req_dismiss_all(adapter); |
743 | adapter->fsf_req_seq_no = 0; | 757 | adapter->fsf_req_seq_no = 0; |
744 | zfcp_fc_wka_ports_force_offline(adapter->gs); | 758 | zfcp_fc_wka_ports_force_offline(adapter->gs); |
745 | /* all ports and units are closed */ | 759 | /* all ports and LUNs are closed */ |
746 | zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL, | 760 | zfcp_erp_clear_adapter_status(adapter, ZFCP_STATUS_COMMON_OPEN); |
747 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); | ||
748 | 761 | ||
749 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | | 762 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | |
750 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); | 763 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); |
@@ -754,7 +767,7 @@ static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *act) | |||
754 | { | 767 | { |
755 | struct zfcp_adapter *adapter = act->adapter; | 768 | struct zfcp_adapter *adapter = act->adapter; |
756 | 769 | ||
757 | if (zfcp_erp_adapter_strategy_open_qdio(act)) { | 770 | if (zfcp_qdio_open(adapter->qdio)) { |
758 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | | 771 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | |
759 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 772 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, |
760 | &adapter->status); | 773 | &adapter->status); |
@@ -861,7 +874,7 @@ static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) | |||
861 | struct zfcp_port *port = act->port; | 874 | struct zfcp_port *port = act->port; |
862 | 875 | ||
863 | if (port->wwpn != adapter->peer_wwpn) { | 876 | if (port->wwpn != adapter->peer_wwpn) { |
864 | zfcp_erp_port_failed(port, "eroptp1", NULL); | 877 | zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED); |
865 | return ZFCP_ERP_FAILED; | 878 | return ZFCP_ERP_FAILED; |
866 | } | 879 | } |
867 | port->d_id = adapter->peer_d_id; | 880 | port->d_id = adapter->peer_d_id; |
@@ -933,82 +946,87 @@ close_init_done: | |||
933 | return zfcp_erp_port_strategy_open_common(erp_action); | 946 | return zfcp_erp_port_strategy_open_common(erp_action); |
934 | } | 947 | } |
935 | 948 | ||
936 | static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) | 949 | static void zfcp_erp_lun_strategy_clearstati(struct scsi_device *sdev) |
937 | { | 950 | { |
951 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
952 | |||
938 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | | 953 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | |
939 | ZFCP_STATUS_UNIT_SHARED | | 954 | ZFCP_STATUS_LUN_SHARED | ZFCP_STATUS_LUN_READONLY, |
940 | ZFCP_STATUS_UNIT_READONLY, | 955 | &zfcp_sdev->status); |
941 | &unit->status); | ||
942 | } | 956 | } |
943 | 957 | ||
944 | static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action) | 958 | static int zfcp_erp_lun_strategy_close(struct zfcp_erp_action *erp_action) |
945 | { | 959 | { |
946 | int retval = zfcp_fsf_close_unit(erp_action); | 960 | int retval = zfcp_fsf_close_lun(erp_action); |
947 | if (retval == -ENOMEM) | 961 | if (retval == -ENOMEM) |
948 | return ZFCP_ERP_NOMEM; | 962 | return ZFCP_ERP_NOMEM; |
949 | erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING; | 963 | erp_action->step = ZFCP_ERP_STEP_LUN_CLOSING; |
950 | if (retval) | 964 | if (retval) |
951 | return ZFCP_ERP_FAILED; | 965 | return ZFCP_ERP_FAILED; |
952 | return ZFCP_ERP_CONTINUES; | 966 | return ZFCP_ERP_CONTINUES; |
953 | } | 967 | } |
954 | 968 | ||
955 | static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action) | 969 | static int zfcp_erp_lun_strategy_open(struct zfcp_erp_action *erp_action) |
956 | { | 970 | { |
957 | int retval = zfcp_fsf_open_unit(erp_action); | 971 | int retval = zfcp_fsf_open_lun(erp_action); |
958 | if (retval == -ENOMEM) | 972 | if (retval == -ENOMEM) |
959 | return ZFCP_ERP_NOMEM; | 973 | return ZFCP_ERP_NOMEM; |
960 | erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING; | 974 | erp_action->step = ZFCP_ERP_STEP_LUN_OPENING; |
961 | if (retval) | 975 | if (retval) |
962 | return ZFCP_ERP_FAILED; | 976 | return ZFCP_ERP_FAILED; |
963 | return ZFCP_ERP_CONTINUES; | 977 | return ZFCP_ERP_CONTINUES; |
964 | } | 978 | } |
965 | 979 | ||
966 | static int zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action) | 980 | static int zfcp_erp_lun_strategy(struct zfcp_erp_action *erp_action) |
967 | { | 981 | { |
968 | struct zfcp_unit *unit = erp_action->unit; | 982 | struct scsi_device *sdev = erp_action->sdev; |
983 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
969 | 984 | ||
970 | switch (erp_action->step) { | 985 | switch (erp_action->step) { |
971 | case ZFCP_ERP_STEP_UNINITIALIZED: | 986 | case ZFCP_ERP_STEP_UNINITIALIZED: |
972 | zfcp_erp_unit_strategy_clearstati(unit); | 987 | zfcp_erp_lun_strategy_clearstati(sdev); |
973 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) | 988 | if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN) |
974 | return zfcp_erp_unit_strategy_close(erp_action); | 989 | return zfcp_erp_lun_strategy_close(erp_action); |
975 | /* already closed, fall through */ | 990 | /* already closed, fall through */ |
976 | case ZFCP_ERP_STEP_UNIT_CLOSING: | 991 | case ZFCP_ERP_STEP_LUN_CLOSING: |
977 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) | 992 | if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN) |
978 | return ZFCP_ERP_FAILED; | 993 | return ZFCP_ERP_FAILED; |
979 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | 994 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) |
980 | return ZFCP_ERP_EXIT; | 995 | return ZFCP_ERP_EXIT; |
981 | return zfcp_erp_unit_strategy_open(erp_action); | 996 | return zfcp_erp_lun_strategy_open(erp_action); |
982 | 997 | ||
983 | case ZFCP_ERP_STEP_UNIT_OPENING: | 998 | case ZFCP_ERP_STEP_LUN_OPENING: |
984 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) | 999 | if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN) |
985 | return ZFCP_ERP_SUCCEEDED; | 1000 | return ZFCP_ERP_SUCCEEDED; |
986 | } | 1001 | } |
987 | return ZFCP_ERP_FAILED; | 1002 | return ZFCP_ERP_FAILED; |
988 | } | 1003 | } |
989 | 1004 | ||
990 | static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) | 1005 | static int zfcp_erp_strategy_check_lun(struct scsi_device *sdev, int result) |
991 | { | 1006 | { |
1007 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
1008 | |||
992 | switch (result) { | 1009 | switch (result) { |
993 | case ZFCP_ERP_SUCCEEDED : | 1010 | case ZFCP_ERP_SUCCEEDED : |
994 | atomic_set(&unit->erp_counter, 0); | 1011 | atomic_set(&zfcp_sdev->erp_counter, 0); |
995 | zfcp_erp_unit_unblock(unit); | 1012 | zfcp_erp_lun_unblock(sdev); |
996 | break; | 1013 | break; |
997 | case ZFCP_ERP_FAILED : | 1014 | case ZFCP_ERP_FAILED : |
998 | atomic_inc(&unit->erp_counter); | 1015 | atomic_inc(&zfcp_sdev->erp_counter); |
999 | if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) { | 1016 | if (atomic_read(&zfcp_sdev->erp_counter) > ZFCP_MAX_ERPS) { |
1000 | dev_err(&unit->port->adapter->ccw_device->dev, | 1017 | dev_err(&zfcp_sdev->port->adapter->ccw_device->dev, |
1001 | "ERP failed for unit 0x%016Lx on " | 1018 | "ERP failed for LUN 0x%016Lx on " |
1002 | "port 0x%016Lx\n", | 1019 | "port 0x%016Lx\n", |
1003 | (unsigned long long)unit->fcp_lun, | 1020 | (unsigned long long)zfcp_scsi_dev_lun(sdev), |
1004 | (unsigned long long)unit->port->wwpn); | 1021 | (unsigned long long)zfcp_sdev->port->wwpn); |
1005 | zfcp_erp_unit_failed(unit, "erusck1", NULL); | 1022 | zfcp_erp_set_lun_status(sdev, |
1023 | ZFCP_STATUS_COMMON_ERP_FAILED); | ||
1006 | } | 1024 | } |
1007 | break; | 1025 | break; |
1008 | } | 1026 | } |
1009 | 1027 | ||
1010 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { | 1028 | if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
1011 | zfcp_erp_unit_block(unit, 0); | 1029 | zfcp_erp_lun_block(sdev, 0); |
1012 | result = ZFCP_ERP_EXIT; | 1030 | result = ZFCP_ERP_EXIT; |
1013 | } | 1031 | } |
1014 | return result; | 1032 | return result; |
@@ -1032,7 +1050,8 @@ static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) | |||
1032 | dev_err(&port->adapter->ccw_device->dev, | 1050 | dev_err(&port->adapter->ccw_device->dev, |
1033 | "ERP failed for remote port 0x%016Lx\n", | 1051 | "ERP failed for remote port 0x%016Lx\n", |
1034 | (unsigned long long)port->wwpn); | 1052 | (unsigned long long)port->wwpn); |
1035 | zfcp_erp_port_failed(port, "erpsck1", NULL); | 1053 | zfcp_erp_set_port_status(port, |
1054 | ZFCP_STATUS_COMMON_ERP_FAILED); | ||
1036 | } | 1055 | } |
1037 | break; | 1056 | break; |
1038 | } | 1057 | } |
@@ -1059,7 +1078,8 @@ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, | |||
1059 | dev_err(&adapter->ccw_device->dev, | 1078 | dev_err(&adapter->ccw_device->dev, |
1060 | "ERP cannot recover an error " | 1079 | "ERP cannot recover an error " |
1061 | "on the FCP device\n"); | 1080 | "on the FCP device\n"); |
1062 | zfcp_erp_adapter_failed(adapter, "erasck1", NULL); | 1081 | zfcp_erp_set_adapter_status(adapter, |
1082 | ZFCP_STATUS_COMMON_ERP_FAILED); | ||
1063 | } | 1083 | } |
1064 | break; | 1084 | break; |
1065 | } | 1085 | } |
@@ -1076,12 +1096,12 @@ static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, | |||
1076 | { | 1096 | { |
1077 | struct zfcp_adapter *adapter = erp_action->adapter; | 1097 | struct zfcp_adapter *adapter = erp_action->adapter; |
1078 | struct zfcp_port *port = erp_action->port; | 1098 | struct zfcp_port *port = erp_action->port; |
1079 | struct zfcp_unit *unit = erp_action->unit; | 1099 | struct scsi_device *sdev = erp_action->sdev; |
1080 | 1100 | ||
1081 | switch (erp_action->action) { | 1101 | switch (erp_action->action) { |
1082 | 1102 | ||
1083 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1103 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
1084 | result = zfcp_erp_strategy_check_unit(unit, result); | 1104 | result = zfcp_erp_strategy_check_lun(sdev, result); |
1085 | break; | 1105 | break; |
1086 | 1106 | ||
1087 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1107 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
@@ -1116,7 +1136,8 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) | |||
1116 | int action = act->action; | 1136 | int action = act->action; |
1117 | struct zfcp_adapter *adapter = act->adapter; | 1137 | struct zfcp_adapter *adapter = act->adapter; |
1118 | struct zfcp_port *port = act->port; | 1138 | struct zfcp_port *port = act->port; |
1119 | struct zfcp_unit *unit = act->unit; | 1139 | struct scsi_device *sdev = act->sdev; |
1140 | struct zfcp_scsi_dev *zfcp_sdev; | ||
1120 | u32 erp_status = act->status; | 1141 | u32 erp_status = act->status; |
1121 | 1142 | ||
1122 | switch (action) { | 1143 | switch (action) { |
@@ -1124,7 +1145,7 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) | |||
1124 | if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) { | 1145 | if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) { |
1125 | _zfcp_erp_adapter_reopen(adapter, | 1146 | _zfcp_erp_adapter_reopen(adapter, |
1126 | ZFCP_STATUS_COMMON_ERP_FAILED, | 1147 | ZFCP_STATUS_COMMON_ERP_FAILED, |
1127 | "ersscg1", NULL); | 1148 | "ersscg1"); |
1128 | return ZFCP_ERP_EXIT; | 1149 | return ZFCP_ERP_EXIT; |
1129 | } | 1150 | } |
1130 | break; | 1151 | break; |
@@ -1134,16 +1155,17 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) | |||
1134 | if (zfcp_erp_strat_change_det(&port->status, erp_status)) { | 1155 | if (zfcp_erp_strat_change_det(&port->status, erp_status)) { |
1135 | _zfcp_erp_port_reopen(port, | 1156 | _zfcp_erp_port_reopen(port, |
1136 | ZFCP_STATUS_COMMON_ERP_FAILED, | 1157 | ZFCP_STATUS_COMMON_ERP_FAILED, |
1137 | "ersscg2", NULL); | 1158 | "ersscg2"); |
1138 | return ZFCP_ERP_EXIT; | 1159 | return ZFCP_ERP_EXIT; |
1139 | } | 1160 | } |
1140 | break; | 1161 | break; |
1141 | 1162 | ||
1142 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1163 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
1143 | if (zfcp_erp_strat_change_det(&unit->status, erp_status)) { | 1164 | zfcp_sdev = sdev_to_zfcp(sdev); |
1144 | _zfcp_erp_unit_reopen(unit, | 1165 | if (zfcp_erp_strat_change_det(&zfcp_sdev->status, erp_status)) { |
1145 | ZFCP_STATUS_COMMON_ERP_FAILED, | 1166 | _zfcp_erp_lun_reopen(sdev, |
1146 | "ersscg3", NULL); | 1167 | ZFCP_STATUS_COMMON_ERP_FAILED, |
1168 | "ersscg3", 0); | ||
1147 | return ZFCP_ERP_EXIT; | 1169 | return ZFCP_ERP_EXIT; |
1148 | } | 1170 | } |
1149 | break; | 1171 | break; |
@@ -1154,6 +1176,7 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) | |||
1154 | static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) | 1176 | static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) |
1155 | { | 1177 | { |
1156 | struct zfcp_adapter *adapter = erp_action->adapter; | 1178 | struct zfcp_adapter *adapter = erp_action->adapter; |
1179 | struct zfcp_scsi_dev *zfcp_sdev; | ||
1157 | 1180 | ||
1158 | adapter->erp_total_count--; | 1181 | adapter->erp_total_count--; |
1159 | if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { | 1182 | if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { |
@@ -1162,12 +1185,13 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) | |||
1162 | } | 1185 | } |
1163 | 1186 | ||
1164 | list_del(&erp_action->list); | 1187 | list_del(&erp_action->list); |
1165 | zfcp_dbf_rec_action("eractd1", erp_action); | 1188 | zfcp_dbf_rec_run("eractd1", erp_action); |
1166 | 1189 | ||
1167 | switch (erp_action->action) { | 1190 | switch (erp_action->action) { |
1168 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1191 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
1192 | zfcp_sdev = sdev_to_zfcp(erp_action->sdev); | ||
1169 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, | 1193 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, |
1170 | &erp_action->unit->status); | 1194 | &zfcp_sdev->status); |
1171 | break; | 1195 | break; |
1172 | 1196 | ||
1173 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1197 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
@@ -1187,11 +1211,12 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) | |||
1187 | { | 1211 | { |
1188 | struct zfcp_adapter *adapter = act->adapter; | 1212 | struct zfcp_adapter *adapter = act->adapter; |
1189 | struct zfcp_port *port = act->port; | 1213 | struct zfcp_port *port = act->port; |
1190 | struct zfcp_unit *unit = act->unit; | 1214 | struct scsi_device *sdev = act->sdev; |
1191 | 1215 | ||
1192 | switch (act->action) { | 1216 | switch (act->action) { |
1193 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1217 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
1194 | put_device(&unit->dev); | 1218 | if (!(act->status & ZFCP_STATUS_ERP_NO_REF)) |
1219 | scsi_device_put(sdev); | ||
1195 | break; | 1220 | break; |
1196 | 1221 | ||
1197 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 1222 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
@@ -1206,8 +1231,10 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) | |||
1206 | if (result == ZFCP_ERP_SUCCEEDED) { | 1231 | if (result == ZFCP_ERP_SUCCEEDED) { |
1207 | register_service_level(&adapter->service_level); | 1232 | register_service_level(&adapter->service_level); |
1208 | queue_work(adapter->work_queue, &adapter->scan_work); | 1233 | queue_work(adapter->work_queue, &adapter->scan_work); |
1234 | queue_work(adapter->work_queue, &adapter->ns_up_work); | ||
1209 | } else | 1235 | } else |
1210 | unregister_service_level(&adapter->service_level); | 1236 | unregister_service_level(&adapter->service_level); |
1237 | |||
1211 | kref_put(&adapter->ref, zfcp_adapter_release); | 1238 | kref_put(&adapter->ref, zfcp_adapter_release); |
1212 | break; | 1239 | break; |
1213 | } | 1240 | } |
@@ -1222,8 +1249,8 @@ static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action) | |||
1222 | return zfcp_erp_port_forced_strategy(erp_action); | 1249 | return zfcp_erp_port_forced_strategy(erp_action); |
1223 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 1250 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
1224 | return zfcp_erp_port_strategy(erp_action); | 1251 | return zfcp_erp_port_strategy(erp_action); |
1225 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1252 | case ZFCP_ERP_ACTION_REOPEN_LUN: |
1226 | return zfcp_erp_unit_strategy(erp_action); | 1253 | return zfcp_erp_lun_strategy(erp_action); |
1227 | } | 1254 | } |
1228 | return ZFCP_ERP_FAILED; | 1255 | return ZFCP_ERP_FAILED; |
1229 | } | 1256 | } |
@@ -1267,7 +1294,7 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) | |||
1267 | erp_action->status |= ZFCP_STATUS_ERP_LOWMEM; | 1294 | erp_action->status |= ZFCP_STATUS_ERP_LOWMEM; |
1268 | } | 1295 | } |
1269 | if (adapter->erp_total_count == adapter->erp_low_mem_count) | 1296 | if (adapter->erp_total_count == adapter->erp_low_mem_count) |
1270 | _zfcp_erp_adapter_reopen(adapter, 0, "erstgy1", NULL); | 1297 | _zfcp_erp_adapter_reopen(adapter, 0, "erstgy1"); |
1271 | else { | 1298 | else { |
1272 | zfcp_erp_strategy_memwait(erp_action); | 1299 | zfcp_erp_strategy_memwait(erp_action); |
1273 | retval = ZFCP_ERP_CONTINUES; | 1300 | retval = ZFCP_ERP_CONTINUES; |
@@ -1311,11 +1338,9 @@ static int zfcp_erp_thread(void *data) | |||
1311 | unsigned long flags; | 1338 | unsigned long flags; |
1312 | 1339 | ||
1313 | for (;;) { | 1340 | for (;;) { |
1314 | zfcp_dbf_rec_thread_lock("erthrd1", adapter->dbf); | ||
1315 | wait_event_interruptible(adapter->erp_ready_wq, | 1341 | wait_event_interruptible(adapter->erp_ready_wq, |
1316 | !list_empty(&adapter->erp_ready_head) || | 1342 | !list_empty(&adapter->erp_ready_head) || |
1317 | kthread_should_stop()); | 1343 | kthread_should_stop()); |
1318 | zfcp_dbf_rec_thread_lock("erthrd2", adapter->dbf); | ||
1319 | 1344 | ||
1320 | if (kthread_should_stop()) | 1345 | if (kthread_should_stop()) |
1321 | break; | 1346 | break; |
@@ -1376,42 +1401,6 @@ void zfcp_erp_thread_kill(struct zfcp_adapter *adapter) | |||
1376 | } | 1401 | } |
1377 | 1402 | ||
1378 | /** | 1403 | /** |
1379 | * zfcp_erp_adapter_failed - Set adapter status to failed. | ||
1380 | * @adapter: Failed adapter. | ||
1381 | * @id: Event id for debug trace. | ||
1382 | * @ref: Reference for debug trace. | ||
1383 | */ | ||
1384 | void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, char *id, void *ref) | ||
1385 | { | ||
1386 | zfcp_erp_modify_adapter_status(adapter, id, ref, | ||
1387 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | ||
1388 | } | ||
1389 | |||
1390 | /** | ||
1391 | * zfcp_erp_port_failed - Set port status to failed. | ||
1392 | * @port: Failed port. | ||
1393 | * @id: Event id for debug trace. | ||
1394 | * @ref: Reference for debug trace. | ||
1395 | */ | ||
1396 | void zfcp_erp_port_failed(struct zfcp_port *port, char *id, void *ref) | ||
1397 | { | ||
1398 | zfcp_erp_modify_port_status(port, id, ref, | ||
1399 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | ||
1400 | } | ||
1401 | |||
1402 | /** | ||
1403 | * zfcp_erp_unit_failed - Set unit status to failed. | ||
1404 | * @unit: Failed unit. | ||
1405 | * @id: Event id for debug trace. | ||
1406 | * @ref: Reference for debug trace. | ||
1407 | */ | ||
1408 | void zfcp_erp_unit_failed(struct zfcp_unit *unit, char *id, void *ref) | ||
1409 | { | ||
1410 | zfcp_erp_modify_unit_status(unit, id, ref, | ||
1411 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | ||
1412 | } | ||
1413 | |||
1414 | /** | ||
1415 | * zfcp_erp_wait - wait for completion of error recovery on an adapter | 1404 | * zfcp_erp_wait - wait for completion of error recovery on an adapter |
1416 | * @adapter: adapter for which to wait for completion of its error recovery | 1405 | * @adapter: adapter for which to wait for completion of its error recovery |
1417 | */ | 1406 | */ |
@@ -1423,210 +1412,148 @@ void zfcp_erp_wait(struct zfcp_adapter *adapter) | |||
1423 | } | 1412 | } |
1424 | 1413 | ||
1425 | /** | 1414 | /** |
1426 | * zfcp_erp_modify_adapter_status - change adapter status bits | 1415 | * zfcp_erp_set_adapter_status - set adapter status bits |
1427 | * @adapter: adapter to change the status | 1416 | * @adapter: adapter to change the status |
1428 | * @id: id for the debug trace | ||
1429 | * @ref: reference for the debug trace | ||
1430 | * @mask: status bits to change | 1417 | * @mask: status bits to change |
1431 | * @set_or_clear: ZFCP_SET or ZFCP_CLEAR | ||
1432 | * | 1418 | * |
1433 | * Changes in common status bits are propagated to attached ports and units. | 1419 | * Changes in common status bits are propagated to attached ports and LUNs. |
1434 | */ | 1420 | */ |
1435 | void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id, | 1421 | void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask) |
1436 | void *ref, u32 mask, int set_or_clear) | ||
1437 | { | 1422 | { |
1438 | struct zfcp_port *port; | 1423 | struct zfcp_port *port; |
1424 | struct scsi_device *sdev; | ||
1439 | unsigned long flags; | 1425 | unsigned long flags; |
1440 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; | 1426 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; |
1441 | 1427 | ||
1442 | if (set_or_clear == ZFCP_SET) { | 1428 | atomic_set_mask(mask, &adapter->status); |
1443 | if (status_change_set(mask, &adapter->status)) | ||
1444 | zfcp_dbf_rec_adapter(id, ref, adapter->dbf); | ||
1445 | atomic_set_mask(mask, &adapter->status); | ||
1446 | } else { | ||
1447 | if (status_change_clear(mask, &adapter->status)) | ||
1448 | zfcp_dbf_rec_adapter(id, ref, adapter->dbf); | ||
1449 | atomic_clear_mask(mask, &adapter->status); | ||
1450 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
1451 | atomic_set(&adapter->erp_counter, 0); | ||
1452 | } | ||
1453 | 1429 | ||
1454 | if (common_mask) { | 1430 | if (!common_mask) |
1455 | read_lock_irqsave(&adapter->port_list_lock, flags); | 1431 | return; |
1456 | list_for_each_entry(port, &adapter->port_list, list) | 1432 | |
1457 | zfcp_erp_modify_port_status(port, id, ref, common_mask, | 1433 | read_lock_irqsave(&adapter->port_list_lock, flags); |
1458 | set_or_clear); | 1434 | list_for_each_entry(port, &adapter->port_list, list) |
1459 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | 1435 | atomic_set_mask(common_mask, &port->status); |
1460 | } | 1436 | read_unlock_irqrestore(&adapter->port_list_lock, flags); |
1437 | |||
1438 | shost_for_each_device(sdev, adapter->scsi_host) | ||
1439 | atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status); | ||
1461 | } | 1440 | } |
1462 | 1441 | ||
1463 | /** | 1442 | /** |
1464 | * zfcp_erp_modify_port_status - change port status bits | 1443 | * zfcp_erp_clear_adapter_status - clear adapter status bits |
1465 | * @port: port to change the status bits | 1444 | * @adapter: adapter to change the status |
1466 | * @id: id for the debug trace | ||
1467 | * @ref: reference for the debug trace | ||
1468 | * @mask: status bits to change | 1445 | * @mask: status bits to change |
1469 | * @set_or_clear: ZFCP_SET or ZFCP_CLEAR | ||
1470 | * | 1446 | * |
1471 | * Changes in common status bits are propagated to attached units. | 1447 | * Changes in common status bits are propagated to attached ports and LUNs. |
1472 | */ | 1448 | */ |
1473 | void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref, | 1449 | void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask) |
1474 | u32 mask, int set_or_clear) | ||
1475 | { | 1450 | { |
1476 | struct zfcp_unit *unit; | 1451 | struct zfcp_port *port; |
1452 | struct scsi_device *sdev; | ||
1477 | unsigned long flags; | 1453 | unsigned long flags; |
1478 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; | 1454 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; |
1455 | u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED; | ||
1479 | 1456 | ||
1480 | if (set_or_clear == ZFCP_SET) { | 1457 | atomic_clear_mask(mask, &adapter->status); |
1481 | if (status_change_set(mask, &port->status)) | 1458 | |
1482 | zfcp_dbf_rec_port(id, ref, port); | 1459 | if (!common_mask) |
1483 | atomic_set_mask(mask, &port->status); | 1460 | return; |
1484 | } else { | 1461 | |
1485 | if (status_change_clear(mask, &port->status)) | 1462 | if (clear_counter) |
1486 | zfcp_dbf_rec_port(id, ref, port); | 1463 | atomic_set(&adapter->erp_counter, 0); |
1487 | atomic_clear_mask(mask, &port->status); | 1464 | |
1488 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) | 1465 | read_lock_irqsave(&adapter->port_list_lock, flags); |
1466 | list_for_each_entry(port, &adapter->port_list, list) { | ||
1467 | atomic_clear_mask(common_mask, &port->status); | ||
1468 | if (clear_counter) | ||
1489 | atomic_set(&port->erp_counter, 0); | 1469 | atomic_set(&port->erp_counter, 0); |
1490 | } | 1470 | } |
1471 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | ||
1491 | 1472 | ||
1492 | if (common_mask) { | 1473 | shost_for_each_device(sdev, adapter->scsi_host) { |
1493 | read_lock_irqsave(&port->unit_list_lock, flags); | 1474 | atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status); |
1494 | list_for_each_entry(unit, &port->unit_list, list) | 1475 | if (clear_counter) |
1495 | zfcp_erp_modify_unit_status(unit, id, ref, common_mask, | 1476 | atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0); |
1496 | set_or_clear); | ||
1497 | read_unlock_irqrestore(&port->unit_list_lock, flags); | ||
1498 | } | 1477 | } |
1499 | } | 1478 | } |
1500 | 1479 | ||
1501 | /** | 1480 | /** |
1502 | * zfcp_erp_modify_unit_status - change unit status bits | 1481 | * zfcp_erp_set_port_status - set port status bits |
1503 | * @unit: unit to change the status bits | 1482 | * @port: port to change the status |
1504 | * @id: id for the debug trace | ||
1505 | * @ref: reference for the debug trace | ||
1506 | * @mask: status bits to change | 1483 | * @mask: status bits to change |
1507 | * @set_or_clear: ZFCP_SET or ZFCP_CLEAR | 1484 | * |
1508 | */ | 1485 | * Changes in common status bits are propagated to attached LUNs. |
1509 | void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref, | ||
1510 | u32 mask, int set_or_clear) | ||
1511 | { | ||
1512 | if (set_or_clear == ZFCP_SET) { | ||
1513 | if (status_change_set(mask, &unit->status)) | ||
1514 | zfcp_dbf_rec_unit(id, ref, unit); | ||
1515 | atomic_set_mask(mask, &unit->status); | ||
1516 | } else { | ||
1517 | if (status_change_clear(mask, &unit->status)) | ||
1518 | zfcp_dbf_rec_unit(id, ref, unit); | ||
1519 | atomic_clear_mask(mask, &unit->status); | ||
1520 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) { | ||
1521 | atomic_set(&unit->erp_counter, 0); | ||
1522 | } | ||
1523 | } | ||
1524 | } | ||
1525 | |||
1526 | /** | ||
1527 | * zfcp_erp_port_boxed - Mark port as "boxed" and start ERP | ||
1528 | * @port: The "boxed" port. | ||
1529 | * @id: The debug trace id. | ||
1530 | * @id: Reference for the debug trace. | ||
1531 | */ | 1486 | */ |
1532 | void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref) | 1487 | void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask) |
1533 | { | 1488 | { |
1534 | zfcp_erp_modify_port_status(port, id, ref, | 1489 | struct scsi_device *sdev; |
1535 | ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET); | 1490 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; |
1536 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | ||
1537 | } | ||
1538 | 1491 | ||
1539 | /** | 1492 | atomic_set_mask(mask, &port->status); |
1540 | * zfcp_erp_unit_boxed - Mark unit as "boxed" and start ERP | ||
1541 | * @port: The "boxed" unit. | ||
1542 | * @id: The debug trace id. | ||
1543 | * @id: Reference for the debug trace. | ||
1544 | */ | ||
1545 | void zfcp_erp_unit_boxed(struct zfcp_unit *unit, char *id, void *ref) | ||
1546 | { | ||
1547 | zfcp_erp_modify_unit_status(unit, id, ref, | ||
1548 | ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET); | ||
1549 | zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | ||
1550 | } | ||
1551 | 1493 | ||
1552 | /** | 1494 | if (!common_mask) |
1553 | * zfcp_erp_port_access_denied - Adapter denied access to port. | 1495 | return; |
1554 | * @port: port where access has been denied | 1496 | |
1555 | * @id: id for debug trace | 1497 | shost_for_each_device(sdev, port->adapter->scsi_host) |
1556 | * @ref: reference for debug trace | 1498 | if (sdev_to_zfcp(sdev)->port == port) |
1557 | * | 1499 | atomic_set_mask(common_mask, |
1558 | * Since the adapter has denied access, stop using the port and the | 1500 | &sdev_to_zfcp(sdev)->status); |
1559 | * attached units. | ||
1560 | */ | ||
1561 | void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref) | ||
1562 | { | ||
1563 | zfcp_erp_modify_port_status(port, id, ref, | ||
1564 | ZFCP_STATUS_COMMON_ERP_FAILED | | ||
1565 | ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); | ||
1566 | } | 1501 | } |
1567 | 1502 | ||
1568 | /** | 1503 | /** |
1569 | * zfcp_erp_unit_access_denied - Adapter denied access to unit. | 1504 | * zfcp_erp_clear_port_status - clear port status bits |
1570 | * @unit: unit where access has been denied | 1505 | * @port: adapter to change the status |
1571 | * @id: id for debug trace | 1506 | * @mask: status bits to change |
1572 | * @ref: reference for debug trace | ||
1573 | * | 1507 | * |
1574 | * Since the adapter has denied access, stop using the unit. | 1508 | * Changes in common status bits are propagated to attached LUNs. |
1575 | */ | 1509 | */ |
1576 | void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, char *id, void *ref) | 1510 | void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask) |
1577 | { | 1511 | { |
1578 | zfcp_erp_modify_unit_status(unit, id, ref, | 1512 | struct scsi_device *sdev; |
1579 | ZFCP_STATUS_COMMON_ERP_FAILED | | 1513 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; |
1580 | ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); | 1514 | u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED; |
1581 | } | ||
1582 | 1515 | ||
1583 | static void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, char *id, | 1516 | atomic_clear_mask(mask, &port->status); |
1584 | void *ref) | 1517 | |
1585 | { | 1518 | if (!common_mask) |
1586 | int status = atomic_read(&unit->status); | ||
1587 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | | ||
1588 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) | ||
1589 | return; | 1519 | return; |
1590 | 1520 | ||
1591 | zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | 1521 | if (clear_counter) |
1522 | atomic_set(&port->erp_counter, 0); | ||
1523 | |||
1524 | shost_for_each_device(sdev, port->adapter->scsi_host) | ||
1525 | if (sdev_to_zfcp(sdev)->port == port) { | ||
1526 | atomic_clear_mask(common_mask, | ||
1527 | &sdev_to_zfcp(sdev)->status); | ||
1528 | if (clear_counter) | ||
1529 | atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0); | ||
1530 | } | ||
1592 | } | 1531 | } |
1593 | 1532 | ||
1594 | static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id, | 1533 | /** |
1595 | void *ref) | 1534 | * zfcp_erp_set_lun_status - set lun status bits |
1535 | * @sdev: SCSI device / lun to set the status bits | ||
1536 | * @mask: status bits to change | ||
1537 | */ | ||
1538 | void zfcp_erp_set_lun_status(struct scsi_device *sdev, u32 mask) | ||
1596 | { | 1539 | { |
1597 | struct zfcp_unit *unit; | 1540 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
1598 | unsigned long flags; | ||
1599 | int status = atomic_read(&port->status); | ||
1600 | |||
1601 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | | ||
1602 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) { | ||
1603 | read_lock_irqsave(&port->unit_list_lock, flags); | ||
1604 | list_for_each_entry(unit, &port->unit_list, list) | ||
1605 | zfcp_erp_unit_access_changed(unit, id, ref); | ||
1606 | read_unlock_irqrestore(&port->unit_list_lock, flags); | ||
1607 | return; | ||
1608 | } | ||
1609 | 1541 | ||
1610 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | 1542 | atomic_set_mask(mask, &zfcp_sdev->status); |
1611 | } | 1543 | } |
1612 | 1544 | ||
1613 | /** | 1545 | /** |
1614 | * zfcp_erp_adapter_access_changed - Process change in adapter ACT | 1546 | * zfcp_erp_clear_lun_status - clear lun status bits |
1615 | * @adapter: Adapter where the Access Control Table (ACT) changed | 1547 | * @sdev: SCSi device / lun to clear the status bits |
1616 | * @id: Id for debug trace | 1548 | * @mask: status bits to change |
1617 | * @ref: Reference for debug trace | ||
1618 | */ | 1549 | */ |
1619 | void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id, | 1550 | void zfcp_erp_clear_lun_status(struct scsi_device *sdev, u32 mask) |
1620 | void *ref) | ||
1621 | { | 1551 | { |
1622 | unsigned long flags; | 1552 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
1623 | struct zfcp_port *port; | ||
1624 | 1553 | ||
1625 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) | 1554 | atomic_clear_mask(mask, &zfcp_sdev->status); |
1626 | return; | ||
1627 | 1555 | ||
1628 | read_lock_irqsave(&adapter->port_list_lock, flags); | 1556 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) |
1629 | list_for_each_entry(port, &adapter->port_list, list) | 1557 | atomic_set(&zfcp_sdev->erp_counter, 0); |
1630 | zfcp_erp_port_access_changed(port, id, ref); | ||
1631 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | ||
1632 | } | 1558 | } |
1559 | |||
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 3b93239c6f69..03627cfd81cd 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -15,12 +15,10 @@ | |||
15 | #include "zfcp_fc.h" | 15 | #include "zfcp_fc.h" |
16 | 16 | ||
17 | /* zfcp_aux.c */ | 17 | /* zfcp_aux.c */ |
18 | extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64); | ||
19 | extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64); | 18 | extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64); |
20 | extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *); | 19 | extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *); |
21 | extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, | 20 | extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, |
22 | u32); | 21 | u32); |
23 | extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64); | ||
24 | extern void zfcp_sg_free_table(struct scatterlist *, int); | 22 | extern void zfcp_sg_free_table(struct scatterlist *, int); |
25 | extern int zfcp_sg_setup_table(struct scatterlist *, int); | 23 | extern int zfcp_sg_setup_table(struct scatterlist *, int); |
26 | extern void zfcp_device_unregister(struct device *, | 24 | extern void zfcp_device_unregister(struct device *, |
@@ -36,66 +34,53 @@ extern void zfcp_ccw_adapter_put(struct zfcp_adapter *); | |||
36 | 34 | ||
37 | /* zfcp_cfdc.c */ | 35 | /* zfcp_cfdc.c */ |
38 | extern struct miscdevice zfcp_cfdc_misc; | 36 | extern struct miscdevice zfcp_cfdc_misc; |
37 | extern void zfcp_cfdc_port_denied(struct zfcp_port *, union fsf_status_qual *); | ||
38 | extern void zfcp_cfdc_lun_denied(struct scsi_device *, union fsf_status_qual *); | ||
39 | extern void zfcp_cfdc_lun_shrng_vltn(struct scsi_device *, | ||
40 | union fsf_status_qual *); | ||
41 | extern int zfcp_cfdc_open_lun_eval(struct scsi_device *, | ||
42 | struct fsf_qtcb_bottom_support *); | ||
43 | extern void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *); | ||
44 | |||
39 | 45 | ||
40 | /* zfcp_dbf.c */ | 46 | /* zfcp_dbf.c */ |
41 | extern int zfcp_dbf_adapter_register(struct zfcp_adapter *); | 47 | extern int zfcp_dbf_adapter_register(struct zfcp_adapter *); |
42 | extern void zfcp_dbf_adapter_unregister(struct zfcp_dbf *); | 48 | extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *); |
43 | extern void zfcp_dbf_rec_thread(char *, struct zfcp_dbf *); | 49 | extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *, |
44 | extern void zfcp_dbf_rec_thread_lock(char *, struct zfcp_dbf *); | 50 | struct zfcp_port *, struct scsi_device *, u8, u8); |
45 | extern void zfcp_dbf_rec_adapter(char *, void *, struct zfcp_dbf *); | 51 | extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *); |
46 | extern void zfcp_dbf_rec_port(char *, void *, struct zfcp_port *); | 52 | extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *); |
47 | extern void zfcp_dbf_rec_unit(char *, void *, struct zfcp_unit *); | 53 | extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *); |
48 | extern void zfcp_dbf_rec_trigger(char *, void *, u8, u8, void *, | 54 | extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); |
49 | struct zfcp_adapter *, struct zfcp_port *, | ||
50 | struct zfcp_unit *); | ||
51 | extern void zfcp_dbf_rec_action(char *, struct zfcp_erp_action *); | ||
52 | extern void _zfcp_dbf_hba_fsf_response(const char *, int, struct zfcp_fsf_req *, | ||
53 | struct zfcp_dbf *); | ||
54 | extern void _zfcp_dbf_hba_fsf_unsol(const char *, int level, struct zfcp_dbf *, | ||
55 | struct fsf_status_read_buffer *); | ||
56 | extern void zfcp_dbf_hba_qdio(struct zfcp_dbf *, unsigned int, int, int); | ||
57 | extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); | 55 | extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); |
58 | extern void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *, u32); | 56 | extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); |
59 | extern void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *); | 57 | extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); |
60 | extern void zfcp_dbf_san_els_request(struct zfcp_fsf_req *); | 58 | extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); |
61 | extern void zfcp_dbf_san_els_response(struct zfcp_fsf_req *); | 59 | extern void zfcp_dbf_scsi(char *, struct scsi_cmnd *, struct zfcp_fsf_req *); |
62 | extern void zfcp_dbf_san_incoming_els(struct zfcp_fsf_req *); | ||
63 | extern void _zfcp_dbf_scsi(const char *, const char *, int, struct zfcp_dbf *, | ||
64 | struct scsi_cmnd *, struct zfcp_fsf_req *, | ||
65 | unsigned long); | ||
66 | 60 | ||
67 | /* zfcp_erp.c */ | 61 | /* zfcp_erp.c */ |
68 | extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, char *, | 62 | extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32); |
69 | void *, u32, int); | 63 | extern void zfcp_erp_clear_adapter_status(struct zfcp_adapter *, u32); |
70 | extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *, void *); | 64 | extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *); |
71 | extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *, | 65 | extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *); |
72 | void *); | 66 | extern void zfcp_erp_set_port_status(struct zfcp_port *, u32); |
73 | extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, char *, void *); | 67 | extern void zfcp_erp_clear_port_status(struct zfcp_port *, u32); |
74 | extern void zfcp_erp_modify_port_status(struct zfcp_port *, char *, void *, u32, | 68 | extern int zfcp_erp_port_reopen(struct zfcp_port *, int, char *); |
75 | int); | 69 | extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *); |
76 | extern int zfcp_erp_port_reopen(struct zfcp_port *, int, char *, void *); | 70 | extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *); |
77 | extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *, void *); | 71 | extern void zfcp_erp_set_lun_status(struct scsi_device *, u32); |
78 | extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *, | 72 | extern void zfcp_erp_clear_lun_status(struct scsi_device *, u32); |
79 | void *); | 73 | extern void zfcp_erp_lun_reopen(struct scsi_device *, int, char *); |
80 | extern void zfcp_erp_port_failed(struct zfcp_port *, char *, void *); | 74 | extern void zfcp_erp_lun_shutdown(struct scsi_device *, int, char *); |
81 | extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, char *, void *, u32, | 75 | extern void zfcp_erp_lun_shutdown_wait(struct scsi_device *, char *); |
82 | int); | ||
83 | extern void zfcp_erp_unit_reopen(struct zfcp_unit *, int, char *, void *); | ||
84 | extern void zfcp_erp_unit_shutdown(struct zfcp_unit *, int, char *, void *); | ||
85 | extern void zfcp_erp_unit_failed(struct zfcp_unit *, char *, void *); | ||
86 | extern int zfcp_erp_thread_setup(struct zfcp_adapter *); | 76 | extern int zfcp_erp_thread_setup(struct zfcp_adapter *); |
87 | extern void zfcp_erp_thread_kill(struct zfcp_adapter *); | 77 | extern void zfcp_erp_thread_kill(struct zfcp_adapter *); |
88 | extern void zfcp_erp_wait(struct zfcp_adapter *); | 78 | extern void zfcp_erp_wait(struct zfcp_adapter *); |
89 | extern void zfcp_erp_notify(struct zfcp_erp_action *, unsigned long); | 79 | extern void zfcp_erp_notify(struct zfcp_erp_action *, unsigned long); |
90 | extern void zfcp_erp_port_boxed(struct zfcp_port *, char *, void *); | ||
91 | extern void zfcp_erp_unit_boxed(struct zfcp_unit *, char *, void *); | ||
92 | extern void zfcp_erp_port_access_denied(struct zfcp_port *, char *, void *); | ||
93 | extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, char *, void *); | ||
94 | extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, char *, | ||
95 | void *); | ||
96 | extern void zfcp_erp_timeout_handler(unsigned long); | 80 | extern void zfcp_erp_timeout_handler(unsigned long); |
97 | 81 | ||
98 | /* zfcp_fc.c */ | 82 | /* zfcp_fc.c */ |
83 | extern struct kmem_cache *zfcp_fc_req_cache; | ||
99 | extern void zfcp_fc_enqueue_event(struct zfcp_adapter *, | 84 | extern void zfcp_fc_enqueue_event(struct zfcp_adapter *, |
100 | enum fc_host_event_code event_code, u32); | 85 | enum fc_host_event_code event_code, u32); |
101 | extern void zfcp_fc_post_event(struct work_struct *); | 86 | extern void zfcp_fc_post_event(struct work_struct *); |
@@ -111,15 +96,17 @@ extern int zfcp_fc_gs_setup(struct zfcp_adapter *); | |||
111 | extern void zfcp_fc_gs_destroy(struct zfcp_adapter *); | 96 | extern void zfcp_fc_gs_destroy(struct zfcp_adapter *); |
112 | extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *); | 97 | extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *); |
113 | extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *); | 98 | extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *); |
99 | extern void zfcp_fc_sym_name_update(struct work_struct *); | ||
114 | 100 | ||
115 | /* zfcp_fsf.c */ | 101 | /* zfcp_fsf.c */ |
102 | extern struct kmem_cache *zfcp_fsf_qtcb_cache; | ||
116 | extern int zfcp_fsf_open_port(struct zfcp_erp_action *); | 103 | extern int zfcp_fsf_open_port(struct zfcp_erp_action *); |
117 | extern int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *); | 104 | extern int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *); |
118 | extern int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *); | 105 | extern int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *); |
119 | extern int zfcp_fsf_close_port(struct zfcp_erp_action *); | 106 | extern int zfcp_fsf_close_port(struct zfcp_erp_action *); |
120 | extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *); | 107 | extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *); |
121 | extern int zfcp_fsf_open_unit(struct zfcp_erp_action *); | 108 | extern int zfcp_fsf_open_lun(struct zfcp_erp_action *); |
122 | extern int zfcp_fsf_close_unit(struct zfcp_erp_action *); | 109 | extern int zfcp_fsf_close_lun(struct zfcp_erp_action *); |
123 | extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *); | 110 | extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *); |
124 | extern int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *, | 111 | extern int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *, |
125 | struct fsf_qtcb_bottom_config *); | 112 | struct fsf_qtcb_bottom_config *); |
@@ -135,12 +122,10 @@ extern int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *, struct zfcp_fsf_ct_els *, | |||
135 | mempool_t *, unsigned int); | 122 | mempool_t *, unsigned int); |
136 | extern int zfcp_fsf_send_els(struct zfcp_adapter *, u32, | 123 | extern int zfcp_fsf_send_els(struct zfcp_adapter *, u32, |
137 | struct zfcp_fsf_ct_els *, unsigned int); | 124 | struct zfcp_fsf_ct_els *, unsigned int); |
138 | extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *, | 125 | extern int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *); |
139 | struct scsi_cmnd *); | ||
140 | extern void zfcp_fsf_req_free(struct zfcp_fsf_req *); | 126 | extern void zfcp_fsf_req_free(struct zfcp_fsf_req *); |
141 | extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *, u8); | 127 | extern struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *, u8); |
142 | extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long, | 128 | extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *); |
143 | struct zfcp_unit *); | ||
144 | extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int); | 129 | extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int); |
145 | 130 | ||
146 | /* zfcp_qdio.c */ | 131 | /* zfcp_qdio.c */ |
@@ -153,18 +138,18 @@ extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *, struct zfcp_qdio_req *, | |||
153 | extern int zfcp_qdio_open(struct zfcp_qdio *); | 138 | extern int zfcp_qdio_open(struct zfcp_qdio *); |
154 | extern void zfcp_qdio_close(struct zfcp_qdio *); | 139 | extern void zfcp_qdio_close(struct zfcp_qdio *); |
155 | extern void zfcp_qdio_siosl(struct zfcp_adapter *); | 140 | extern void zfcp_qdio_siosl(struct zfcp_adapter *); |
141 | extern struct zfcp_fsf_req *zfcp_fsf_get_req(struct zfcp_qdio *, | ||
142 | struct qdio_buffer *); | ||
156 | 143 | ||
157 | /* zfcp_scsi.c */ | 144 | /* zfcp_scsi.c */ |
158 | extern struct zfcp_data zfcp_data; | 145 | extern struct scsi_transport_template *zfcp_scsi_transport_template; |
159 | extern int zfcp_adapter_scsi_register(struct zfcp_adapter *); | 146 | extern int zfcp_scsi_adapter_register(struct zfcp_adapter *); |
160 | extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *); | 147 | extern void zfcp_scsi_adapter_unregister(struct zfcp_adapter *); |
161 | extern struct fc_function_template zfcp_transport_functions; | 148 | extern struct fc_function_template zfcp_transport_functions; |
162 | extern void zfcp_scsi_rport_work(struct work_struct *); | 149 | extern void zfcp_scsi_rport_work(struct work_struct *); |
163 | extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *); | 150 | extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *); |
164 | extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *); | 151 | extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *); |
165 | extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *); | 152 | extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *); |
166 | extern void zfcp_scsi_scan(struct zfcp_unit *); | ||
167 | extern void zfcp_scsi_scan_work(struct work_struct *); | ||
168 | extern void zfcp_scsi_set_prot(struct zfcp_adapter *); | 153 | extern void zfcp_scsi_set_prot(struct zfcp_adapter *); |
169 | extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int); | 154 | extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int); |
170 | 155 | ||
@@ -175,4 +160,13 @@ extern struct attribute_group zfcp_sysfs_port_attrs; | |||
175 | extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; | 160 | extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; |
176 | extern struct device_attribute *zfcp_sysfs_shost_attrs[]; | 161 | extern struct device_attribute *zfcp_sysfs_shost_attrs[]; |
177 | 162 | ||
163 | /* zfcp_unit.c */ | ||
164 | extern int zfcp_unit_add(struct zfcp_port *, u64); | ||
165 | extern int zfcp_unit_remove(struct zfcp_port *, u64); | ||
166 | extern struct zfcp_unit *zfcp_unit_find(struct zfcp_port *, u64); | ||
167 | extern struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit); | ||
168 | extern void zfcp_unit_scsi_scan(struct zfcp_unit *); | ||
169 | extern void zfcp_unit_queue_scsi_scan(struct zfcp_port *); | ||
170 | extern unsigned int zfcp_unit_sdev_status(struct zfcp_unit *); | ||
171 | |||
178 | #endif /* ZFCP_EXT_H */ | 172 | #endif /* ZFCP_EXT_H */ |
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 6f3ed2b9a349..297e6b71ce9c 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c | |||
@@ -11,11 +11,14 @@ | |||
11 | 11 | ||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/utsname.h> | ||
14 | #include <scsi/fc/fc_els.h> | 15 | #include <scsi/fc/fc_els.h> |
15 | #include <scsi/libfc.h> | 16 | #include <scsi/libfc.h> |
16 | #include "zfcp_ext.h" | 17 | #include "zfcp_ext.h" |
17 | #include "zfcp_fc.h" | 18 | #include "zfcp_fc.h" |
18 | 19 | ||
20 | struct kmem_cache *zfcp_fc_req_cache; | ||
21 | |||
19 | static u32 zfcp_fc_rscn_range_mask[] = { | 22 | static u32 zfcp_fc_rscn_range_mask[] = { |
20 | [ELS_ADDR_FMT_PORT] = 0xFFFFFF, | 23 | [ELS_ADDR_FMT_PORT] = 0xFFFFFF, |
21 | [ELS_ADDR_FMT_AREA] = 0xFFFF00, | 24 | [ELS_ADDR_FMT_AREA] = 0xFFFF00, |
@@ -174,7 +177,7 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, | |||
174 | if (!port->d_id) | 177 | if (!port->d_id) |
175 | zfcp_erp_port_reopen(port, | 178 | zfcp_erp_port_reopen(port, |
176 | ZFCP_STATUS_COMMON_ERP_FAILED, | 179 | ZFCP_STATUS_COMMON_ERP_FAILED, |
177 | "fcrscn1", NULL); | 180 | "fcrscn1"); |
178 | } | 181 | } |
179 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | 182 | read_unlock_irqrestore(&adapter->port_list_lock, flags); |
180 | } | 183 | } |
@@ -215,7 +218,7 @@ static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn) | |||
215 | read_lock_irqsave(&adapter->port_list_lock, flags); | 218 | read_lock_irqsave(&adapter->port_list_lock, flags); |
216 | list_for_each_entry(port, &adapter->port_list, list) | 219 | list_for_each_entry(port, &adapter->port_list, list) |
217 | if (port->wwpn == wwpn) { | 220 | if (port->wwpn == wwpn) { |
218 | zfcp_erp_port_forced_reopen(port, 0, "fciwwp1", req); | 221 | zfcp_erp_port_forced_reopen(port, 0, "fciwwp1"); |
219 | break; | 222 | break; |
220 | } | 223 | } |
221 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | 224 | read_unlock_irqrestore(&adapter->port_list_lock, flags); |
@@ -251,7 +254,7 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req) | |||
251 | (struct fsf_status_read_buffer *) fsf_req->data; | 254 | (struct fsf_status_read_buffer *) fsf_req->data; |
252 | unsigned int els_type = status_buffer->payload.data[0]; | 255 | unsigned int els_type = status_buffer->payload.data[0]; |
253 | 256 | ||
254 | zfcp_dbf_san_incoming_els(fsf_req); | 257 | zfcp_dbf_san_in_els("fciels1", fsf_req); |
255 | if (els_type == ELS_PLOGI) | 258 | if (els_type == ELS_PLOGI) |
256 | zfcp_fc_incoming_plogi(fsf_req); | 259 | zfcp_fc_incoming_plogi(fsf_req); |
257 | else if (els_type == ELS_LOGO) | 260 | else if (els_type == ELS_LOGO) |
@@ -260,24 +263,18 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req) | |||
260 | zfcp_fc_incoming_rscn(fsf_req); | 263 | zfcp_fc_incoming_rscn(fsf_req); |
261 | } | 264 | } |
262 | 265 | ||
263 | static void zfcp_fc_ns_gid_pn_eval(void *data) | 266 | static void zfcp_fc_ns_gid_pn_eval(struct zfcp_fc_req *fc_req) |
264 | { | 267 | { |
265 | struct zfcp_fc_gid_pn *gid_pn = data; | 268 | struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els; |
266 | struct zfcp_fsf_ct_els *ct = &gid_pn->ct; | 269 | struct zfcp_fc_gid_pn_rsp *gid_pn_rsp = &fc_req->u.gid_pn.rsp; |
267 | struct zfcp_fc_gid_pn_req *gid_pn_req = sg_virt(ct->req); | ||
268 | struct zfcp_fc_gid_pn_resp *gid_pn_resp = sg_virt(ct->resp); | ||
269 | struct zfcp_port *port = gid_pn->port; | ||
270 | 270 | ||
271 | if (ct->status) | 271 | if (ct_els->status) |
272 | return; | 272 | return; |
273 | if (gid_pn_resp->ct_hdr.ct_cmd != FC_FS_ACC) | 273 | if (gid_pn_rsp->ct_hdr.ct_cmd != FC_FS_ACC) |
274 | return; | 274 | return; |
275 | 275 | ||
276 | /* paranoia */ | ||
277 | if (gid_pn_req->gid_pn.fn_wwpn != port->wwpn) | ||
278 | return; | ||
279 | /* looks like a valid d_id */ | 276 | /* looks like a valid d_id */ |
280 | port->d_id = ntoh24(gid_pn_resp->gid_pn.fp_fid); | 277 | ct_els->port->d_id = ntoh24(gid_pn_rsp->gid_pn.fp_fid); |
281 | } | 278 | } |
282 | 279 | ||
283 | static void zfcp_fc_complete(void *data) | 280 | static void zfcp_fc_complete(void *data) |
@@ -285,69 +282,73 @@ static void zfcp_fc_complete(void *data) | |||
285 | complete(data); | 282 | complete(data); |
286 | } | 283 | } |
287 | 284 | ||
285 | static void zfcp_fc_ct_ns_init(struct fc_ct_hdr *ct_hdr, u16 cmd, u16 mr_size) | ||
286 | { | ||
287 | ct_hdr->ct_rev = FC_CT_REV; | ||
288 | ct_hdr->ct_fs_type = FC_FST_DIR; | ||
289 | ct_hdr->ct_fs_subtype = FC_NS_SUBTYPE; | ||
290 | ct_hdr->ct_cmd = cmd; | ||
291 | ct_hdr->ct_mr_size = mr_size / 4; | ||
292 | } | ||
293 | |||
288 | static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port, | 294 | static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port, |
289 | struct zfcp_fc_gid_pn *gid_pn) | 295 | struct zfcp_fc_req *fc_req) |
290 | { | 296 | { |
291 | struct zfcp_adapter *adapter = port->adapter; | 297 | struct zfcp_adapter *adapter = port->adapter; |
292 | DECLARE_COMPLETION_ONSTACK(completion); | 298 | DECLARE_COMPLETION_ONSTACK(completion); |
299 | struct zfcp_fc_gid_pn_req *gid_pn_req = &fc_req->u.gid_pn.req; | ||
300 | struct zfcp_fc_gid_pn_rsp *gid_pn_rsp = &fc_req->u.gid_pn.rsp; | ||
293 | int ret; | 301 | int ret; |
294 | 302 | ||
295 | /* setup parameters for send generic command */ | 303 | /* setup parameters for send generic command */ |
296 | gid_pn->port = port; | 304 | fc_req->ct_els.port = port; |
297 | gid_pn->ct.handler = zfcp_fc_complete; | 305 | fc_req->ct_els.handler = zfcp_fc_complete; |
298 | gid_pn->ct.handler_data = &completion; | 306 | fc_req->ct_els.handler_data = &completion; |
299 | gid_pn->ct.req = &gid_pn->sg_req; | 307 | fc_req->ct_els.req = &fc_req->sg_req; |
300 | gid_pn->ct.resp = &gid_pn->sg_resp; | 308 | fc_req->ct_els.resp = &fc_req->sg_rsp; |
301 | sg_init_one(&gid_pn->sg_req, &gid_pn->gid_pn_req, | 309 | sg_init_one(&fc_req->sg_req, gid_pn_req, sizeof(*gid_pn_req)); |
302 | sizeof(struct zfcp_fc_gid_pn_req)); | 310 | sg_init_one(&fc_req->sg_rsp, gid_pn_rsp, sizeof(*gid_pn_rsp)); |
303 | sg_init_one(&gid_pn->sg_resp, &gid_pn->gid_pn_resp, | 311 | |
304 | sizeof(struct zfcp_fc_gid_pn_resp)); | 312 | zfcp_fc_ct_ns_init(&gid_pn_req->ct_hdr, |
305 | 313 | FC_NS_GID_PN, ZFCP_FC_CT_SIZE_PAGE); | |
306 | /* setup nameserver request */ | 314 | gid_pn_req->gid_pn.fn_wwpn = port->wwpn; |
307 | gid_pn->gid_pn_req.ct_hdr.ct_rev = FC_CT_REV; | 315 | |
308 | gid_pn->gid_pn_req.ct_hdr.ct_fs_type = FC_FST_DIR; | 316 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, &fc_req->ct_els, |
309 | gid_pn->gid_pn_req.ct_hdr.ct_fs_subtype = FC_NS_SUBTYPE; | ||
310 | gid_pn->gid_pn_req.ct_hdr.ct_options = 0; | ||
311 | gid_pn->gid_pn_req.ct_hdr.ct_cmd = FC_NS_GID_PN; | ||
312 | gid_pn->gid_pn_req.ct_hdr.ct_mr_size = ZFCP_FC_CT_SIZE_PAGE / 4; | ||
313 | gid_pn->gid_pn_req.gid_pn.fn_wwpn = port->wwpn; | ||
314 | |||
315 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, &gid_pn->ct, | ||
316 | adapter->pool.gid_pn_req, | 317 | adapter->pool.gid_pn_req, |
317 | ZFCP_FC_CTELS_TMO); | 318 | ZFCP_FC_CTELS_TMO); |
318 | if (!ret) { | 319 | if (!ret) { |
319 | wait_for_completion(&completion); | 320 | wait_for_completion(&completion); |
320 | zfcp_fc_ns_gid_pn_eval(gid_pn); | 321 | zfcp_fc_ns_gid_pn_eval(fc_req); |
321 | } | 322 | } |
322 | return ret; | 323 | return ret; |
323 | } | 324 | } |
324 | 325 | ||
325 | /** | 326 | /** |
326 | * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request | 327 | * zfcp_fc_ns_gid_pn - initiate GID_PN nameserver request |
327 | * @port: port where GID_PN request is needed | 328 | * @port: port where GID_PN request is needed |
328 | * return: -ENOMEM on error, 0 otherwise | 329 | * return: -ENOMEM on error, 0 otherwise |
329 | */ | 330 | */ |
330 | static int zfcp_fc_ns_gid_pn(struct zfcp_port *port) | 331 | static int zfcp_fc_ns_gid_pn(struct zfcp_port *port) |
331 | { | 332 | { |
332 | int ret; | 333 | int ret; |
333 | struct zfcp_fc_gid_pn *gid_pn; | 334 | struct zfcp_fc_req *fc_req; |
334 | struct zfcp_adapter *adapter = port->adapter; | 335 | struct zfcp_adapter *adapter = port->adapter; |
335 | 336 | ||
336 | gid_pn = mempool_alloc(adapter->pool.gid_pn, GFP_ATOMIC); | 337 | fc_req = mempool_alloc(adapter->pool.gid_pn, GFP_ATOMIC); |
337 | if (!gid_pn) | 338 | if (!fc_req) |
338 | return -ENOMEM; | 339 | return -ENOMEM; |
339 | 340 | ||
340 | memset(gid_pn, 0, sizeof(*gid_pn)); | 341 | memset(fc_req, 0, sizeof(*fc_req)); |
341 | 342 | ||
342 | ret = zfcp_fc_wka_port_get(&adapter->gs->ds); | 343 | ret = zfcp_fc_wka_port_get(&adapter->gs->ds); |
343 | if (ret) | 344 | if (ret) |
344 | goto out; | 345 | goto out; |
345 | 346 | ||
346 | ret = zfcp_fc_ns_gid_pn_request(port, gid_pn); | 347 | ret = zfcp_fc_ns_gid_pn_request(port, fc_req); |
347 | 348 | ||
348 | zfcp_fc_wka_port_put(&adapter->gs->ds); | 349 | zfcp_fc_wka_port_put(&adapter->gs->ds); |
349 | out: | 350 | out: |
350 | mempool_free(gid_pn, adapter->pool.gid_pn); | 351 | mempool_free(fc_req, adapter->pool.gid_pn); |
351 | return ret; | 352 | return ret; |
352 | } | 353 | } |
353 | 354 | ||
@@ -360,16 +361,16 @@ void zfcp_fc_port_did_lookup(struct work_struct *work) | |||
360 | ret = zfcp_fc_ns_gid_pn(port); | 361 | ret = zfcp_fc_ns_gid_pn(port); |
361 | if (ret) { | 362 | if (ret) { |
362 | /* could not issue gid_pn for some reason */ | 363 | /* could not issue gid_pn for some reason */ |
363 | zfcp_erp_adapter_reopen(port->adapter, 0, "fcgpn_1", NULL); | 364 | zfcp_erp_adapter_reopen(port->adapter, 0, "fcgpn_1"); |
364 | goto out; | 365 | goto out; |
365 | } | 366 | } |
366 | 367 | ||
367 | if (!port->d_id) { | 368 | if (!port->d_id) { |
368 | zfcp_erp_port_failed(port, "fcgpn_2", NULL); | 369 | zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED); |
369 | goto out; | 370 | goto out; |
370 | } | 371 | } |
371 | 372 | ||
372 | zfcp_erp_port_reopen(port, 0, "fcgpn_3", NULL); | 373 | zfcp_erp_port_reopen(port, 0, "fcgpn_3"); |
373 | out: | 374 | out: |
374 | put_device(&port->dev); | 375 | put_device(&port->dev); |
375 | } | 376 | } |
@@ -419,14 +420,14 @@ void zfcp_fc_plogi_evaluate(struct zfcp_port *port, struct fc_els_flogi *plogi) | |||
419 | 420 | ||
420 | static void zfcp_fc_adisc_handler(void *data) | 421 | static void zfcp_fc_adisc_handler(void *data) |
421 | { | 422 | { |
422 | struct zfcp_fc_els_adisc *adisc = data; | 423 | struct zfcp_fc_req *fc_req = data; |
423 | struct zfcp_port *port = adisc->els.port; | 424 | struct zfcp_port *port = fc_req->ct_els.port; |
424 | struct fc_els_adisc *adisc_resp = &adisc->adisc_resp; | 425 | struct fc_els_adisc *adisc_resp = &fc_req->u.adisc.rsp; |
425 | 426 | ||
426 | if (adisc->els.status) { | 427 | if (fc_req->ct_els.status) { |
427 | /* request rejected or timed out */ | 428 | /* request rejected or timed out */ |
428 | zfcp_erp_port_forced_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, | 429 | zfcp_erp_port_forced_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, |
429 | "fcadh_1", NULL); | 430 | "fcadh_1"); |
430 | goto out; | 431 | goto out; |
431 | } | 432 | } |
432 | 433 | ||
@@ -436,7 +437,7 @@ static void zfcp_fc_adisc_handler(void *data) | |||
436 | if ((port->wwpn != adisc_resp->adisc_wwpn) || | 437 | if ((port->wwpn != adisc_resp->adisc_wwpn) || |
437 | !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) { | 438 | !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) { |
438 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, | 439 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, |
439 | "fcadh_2", NULL); | 440 | "fcadh_2"); |
440 | goto out; | 441 | goto out; |
441 | } | 442 | } |
442 | 443 | ||
@@ -445,42 +446,42 @@ static void zfcp_fc_adisc_handler(void *data) | |||
445 | out: | 446 | out: |
446 | atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status); | 447 | atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status); |
447 | put_device(&port->dev); | 448 | put_device(&port->dev); |
448 | kmem_cache_free(zfcp_data.adisc_cache, adisc); | 449 | kmem_cache_free(zfcp_fc_req_cache, fc_req); |
449 | } | 450 | } |
450 | 451 | ||
451 | static int zfcp_fc_adisc(struct zfcp_port *port) | 452 | static int zfcp_fc_adisc(struct zfcp_port *port) |
452 | { | 453 | { |
453 | struct zfcp_fc_els_adisc *adisc; | 454 | struct zfcp_fc_req *fc_req; |
454 | struct zfcp_adapter *adapter = port->adapter; | 455 | struct zfcp_adapter *adapter = port->adapter; |
456 | struct Scsi_Host *shost = adapter->scsi_host; | ||
455 | int ret; | 457 | int ret; |
456 | 458 | ||
457 | adisc = kmem_cache_zalloc(zfcp_data.adisc_cache, GFP_ATOMIC); | 459 | fc_req = kmem_cache_zalloc(zfcp_fc_req_cache, GFP_ATOMIC); |
458 | if (!adisc) | 460 | if (!fc_req) |
459 | return -ENOMEM; | 461 | return -ENOMEM; |
460 | 462 | ||
461 | adisc->els.port = port; | 463 | fc_req->ct_els.port = port; |
462 | adisc->els.req = &adisc->req; | 464 | fc_req->ct_els.req = &fc_req->sg_req; |
463 | adisc->els.resp = &adisc->resp; | 465 | fc_req->ct_els.resp = &fc_req->sg_rsp; |
464 | sg_init_one(adisc->els.req, &adisc->adisc_req, | 466 | sg_init_one(&fc_req->sg_req, &fc_req->u.adisc.req, |
465 | sizeof(struct fc_els_adisc)); | 467 | sizeof(struct fc_els_adisc)); |
466 | sg_init_one(adisc->els.resp, &adisc->adisc_resp, | 468 | sg_init_one(&fc_req->sg_rsp, &fc_req->u.adisc.rsp, |
467 | sizeof(struct fc_els_adisc)); | 469 | sizeof(struct fc_els_adisc)); |
468 | 470 | ||
469 | adisc->els.handler = zfcp_fc_adisc_handler; | 471 | fc_req->ct_els.handler = zfcp_fc_adisc_handler; |
470 | adisc->els.handler_data = adisc; | 472 | fc_req->ct_els.handler_data = fc_req; |
471 | 473 | ||
472 | /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports | 474 | /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports |
473 | without FC-AL-2 capability, so we don't set it */ | 475 | without FC-AL-2 capability, so we don't set it */ |
474 | adisc->adisc_req.adisc_wwpn = fc_host_port_name(adapter->scsi_host); | 476 | fc_req->u.adisc.req.adisc_wwpn = fc_host_port_name(shost); |
475 | adisc->adisc_req.adisc_wwnn = fc_host_node_name(adapter->scsi_host); | 477 | fc_req->u.adisc.req.adisc_wwnn = fc_host_node_name(shost); |
476 | adisc->adisc_req.adisc_cmd = ELS_ADISC; | 478 | fc_req->u.adisc.req.adisc_cmd = ELS_ADISC; |
477 | hton24(adisc->adisc_req.adisc_port_id, | 479 | hton24(fc_req->u.adisc.req.adisc_port_id, fc_host_port_id(shost)); |
478 | fc_host_port_id(adapter->scsi_host)); | ||
479 | 480 | ||
480 | ret = zfcp_fsf_send_els(adapter, port->d_id, &adisc->els, | 481 | ret = zfcp_fsf_send_els(adapter, port->d_id, &fc_req->ct_els, |
481 | ZFCP_FC_CTELS_TMO); | 482 | ZFCP_FC_CTELS_TMO); |
482 | if (ret) | 483 | if (ret) |
483 | kmem_cache_free(zfcp_data.adisc_cache, adisc); | 484 | kmem_cache_free(zfcp_fc_req_cache, fc_req); |
484 | 485 | ||
485 | return ret; | 486 | return ret; |
486 | } | 487 | } |
@@ -507,7 +508,7 @@ void zfcp_fc_link_test_work(struct work_struct *work) | |||
507 | 508 | ||
508 | /* send of ADISC was not possible */ | 509 | /* send of ADISC was not possible */ |
509 | atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status); | 510 | atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status); |
510 | zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL); | 511 | zfcp_erp_port_forced_reopen(port, 0, "fcltwk1"); |
511 | 512 | ||
512 | out: | 513 | out: |
513 | put_device(&port->dev); | 514 | put_device(&port->dev); |
@@ -528,68 +529,42 @@ void zfcp_fc_test_link(struct zfcp_port *port) | |||
528 | put_device(&port->dev); | 529 | put_device(&port->dev); |
529 | } | 530 | } |
530 | 531 | ||
531 | static void zfcp_free_sg_env(struct zfcp_fc_gpn_ft *gpn_ft, int buf_num) | 532 | static struct zfcp_fc_req *zfcp_alloc_sg_env(int buf_num) |
532 | { | 533 | { |
533 | struct scatterlist *sg = &gpn_ft->sg_req; | 534 | struct zfcp_fc_req *fc_req; |
534 | |||
535 | kmem_cache_free(zfcp_data.gpn_ft_cache, sg_virt(sg)); | ||
536 | zfcp_sg_free_table(gpn_ft->sg_resp, buf_num); | ||
537 | |||
538 | kfree(gpn_ft); | ||
539 | } | ||
540 | 535 | ||
541 | static struct zfcp_fc_gpn_ft *zfcp_alloc_sg_env(int buf_num) | 536 | fc_req = kmem_cache_zalloc(zfcp_fc_req_cache, GFP_KERNEL); |
542 | { | 537 | if (!fc_req) |
543 | struct zfcp_fc_gpn_ft *gpn_ft; | ||
544 | struct zfcp_fc_gpn_ft_req *req; | ||
545 | |||
546 | gpn_ft = kzalloc(sizeof(*gpn_ft), GFP_KERNEL); | ||
547 | if (!gpn_ft) | ||
548 | return NULL; | 538 | return NULL; |
549 | 539 | ||
550 | req = kmem_cache_zalloc(zfcp_data.gpn_ft_cache, GFP_KERNEL); | 540 | if (zfcp_sg_setup_table(&fc_req->sg_rsp, buf_num)) { |
551 | if (!req) { | 541 | kmem_cache_free(zfcp_fc_req_cache, fc_req); |
552 | kfree(gpn_ft); | 542 | return NULL; |
553 | gpn_ft = NULL; | ||
554 | goto out; | ||
555 | } | 543 | } |
556 | sg_init_one(&gpn_ft->sg_req, req, sizeof(*req)); | ||
557 | 544 | ||
558 | if (zfcp_sg_setup_table(gpn_ft->sg_resp, buf_num)) { | 545 | sg_init_one(&fc_req->sg_req, &fc_req->u.gpn_ft.req, |
559 | zfcp_free_sg_env(gpn_ft, buf_num); | 546 | sizeof(struct zfcp_fc_gpn_ft_req)); |
560 | gpn_ft = NULL; | ||
561 | } | ||
562 | out: | ||
563 | return gpn_ft; | ||
564 | } | ||
565 | 547 | ||
548 | return fc_req; | ||
549 | } | ||
566 | 550 | ||
567 | static int zfcp_fc_send_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, | 551 | static int zfcp_fc_send_gpn_ft(struct zfcp_fc_req *fc_req, |
568 | struct zfcp_adapter *adapter, int max_bytes) | 552 | struct zfcp_adapter *adapter, int max_bytes) |
569 | { | 553 | { |
570 | struct zfcp_fsf_ct_els *ct = &gpn_ft->ct; | 554 | struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els; |
571 | struct zfcp_fc_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req); | 555 | struct zfcp_fc_gpn_ft_req *req = &fc_req->u.gpn_ft.req; |
572 | DECLARE_COMPLETION_ONSTACK(completion); | 556 | DECLARE_COMPLETION_ONSTACK(completion); |
573 | int ret; | 557 | int ret; |
574 | 558 | ||
575 | /* prepare CT IU for GPN_FT */ | 559 | zfcp_fc_ct_ns_init(&req->ct_hdr, FC_NS_GPN_FT, max_bytes); |
576 | req->ct_hdr.ct_rev = FC_CT_REV; | ||
577 | req->ct_hdr.ct_fs_type = FC_FST_DIR; | ||
578 | req->ct_hdr.ct_fs_subtype = FC_NS_SUBTYPE; | ||
579 | req->ct_hdr.ct_options = 0; | ||
580 | req->ct_hdr.ct_cmd = FC_NS_GPN_FT; | ||
581 | req->ct_hdr.ct_mr_size = max_bytes / 4; | ||
582 | req->gpn_ft.fn_domain_id_scope = 0; | ||
583 | req->gpn_ft.fn_area_id_scope = 0; | ||
584 | req->gpn_ft.fn_fc4_type = FC_TYPE_FCP; | 560 | req->gpn_ft.fn_fc4_type = FC_TYPE_FCP; |
585 | 561 | ||
586 | /* prepare zfcp_send_ct */ | 562 | ct_els->handler = zfcp_fc_complete; |
587 | ct->handler = zfcp_fc_complete; | 563 | ct_els->handler_data = &completion; |
588 | ct->handler_data = &completion; | 564 | ct_els->req = &fc_req->sg_req; |
589 | ct->req = &gpn_ft->sg_req; | 565 | ct_els->resp = &fc_req->sg_rsp; |
590 | ct->resp = gpn_ft->sg_resp; | ||
591 | 566 | ||
592 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct, NULL, | 567 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL, |
593 | ZFCP_FC_CTELS_TMO); | 568 | ZFCP_FC_CTELS_TMO); |
594 | if (!ret) | 569 | if (!ret) |
595 | wait_for_completion(&completion); | 570 | wait_for_completion(&completion); |
@@ -610,11 +585,11 @@ static void zfcp_fc_validate_port(struct zfcp_port *port, struct list_head *lh) | |||
610 | list_move_tail(&port->list, lh); | 585 | list_move_tail(&port->list, lh); |
611 | } | 586 | } |
612 | 587 | ||
613 | static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, | 588 | static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_req *fc_req, |
614 | struct zfcp_adapter *adapter, int max_entries) | 589 | struct zfcp_adapter *adapter, int max_entries) |
615 | { | 590 | { |
616 | struct zfcp_fsf_ct_els *ct = &gpn_ft->ct; | 591 | struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els; |
617 | struct scatterlist *sg = gpn_ft->sg_resp; | 592 | struct scatterlist *sg = &fc_req->sg_rsp; |
618 | struct fc_ct_hdr *hdr = sg_virt(sg); | 593 | struct fc_ct_hdr *hdr = sg_virt(sg); |
619 | struct fc_gpn_ft_resp *acc = sg_virt(sg); | 594 | struct fc_gpn_ft_resp *acc = sg_virt(sg); |
620 | struct zfcp_port *port, *tmp; | 595 | struct zfcp_port *port, *tmp; |
@@ -623,7 +598,7 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, | |||
623 | u32 d_id; | 598 | u32 d_id; |
624 | int ret = 0, x, last = 0; | 599 | int ret = 0, x, last = 0; |
625 | 600 | ||
626 | if (ct->status) | 601 | if (ct_els->status) |
627 | return -EIO; | 602 | return -EIO; |
628 | 603 | ||
629 | if (hdr->ct_cmd != FC_FS_ACC) { | 604 | if (hdr->ct_cmd != FC_FS_ACC) { |
@@ -659,7 +634,7 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, | |||
659 | port = zfcp_port_enqueue(adapter, acc->fp_wwpn, | 634 | port = zfcp_port_enqueue(adapter, acc->fp_wwpn, |
660 | ZFCP_STATUS_COMMON_NOESC, d_id); | 635 | ZFCP_STATUS_COMMON_NOESC, d_id); |
661 | if (!IS_ERR(port)) | 636 | if (!IS_ERR(port)) |
662 | zfcp_erp_port_reopen(port, 0, "fcegpf1", NULL); | 637 | zfcp_erp_port_reopen(port, 0, "fcegpf1"); |
663 | else if (PTR_ERR(port) != -EEXIST) | 638 | else if (PTR_ERR(port) != -EEXIST) |
664 | ret = PTR_ERR(port); | 639 | ret = PTR_ERR(port); |
665 | } | 640 | } |
@@ -671,7 +646,7 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, | |||
671 | write_unlock_irqrestore(&adapter->port_list_lock, flags); | 646 | write_unlock_irqrestore(&adapter->port_list_lock, flags); |
672 | 647 | ||
673 | list_for_each_entry_safe(port, tmp, &remove_lh, list) { | 648 | list_for_each_entry_safe(port, tmp, &remove_lh, list) { |
674 | zfcp_erp_port_shutdown(port, 0, "fcegpf2", NULL); | 649 | zfcp_erp_port_shutdown(port, 0, "fcegpf2"); |
675 | zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs); | 650 | zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs); |
676 | } | 651 | } |
677 | 652 | ||
@@ -687,7 +662,7 @@ void zfcp_fc_scan_ports(struct work_struct *work) | |||
687 | struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter, | 662 | struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter, |
688 | scan_work); | 663 | scan_work); |
689 | int ret, i; | 664 | int ret, i; |
690 | struct zfcp_fc_gpn_ft *gpn_ft; | 665 | struct zfcp_fc_req *fc_req; |
691 | int chain, max_entries, buf_num, max_bytes; | 666 | int chain, max_entries, buf_num, max_bytes; |
692 | 667 | ||
693 | chain = adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS; | 668 | chain = adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS; |
@@ -702,25 +677,145 @@ void zfcp_fc_scan_ports(struct work_struct *work) | |||
702 | if (zfcp_fc_wka_port_get(&adapter->gs->ds)) | 677 | if (zfcp_fc_wka_port_get(&adapter->gs->ds)) |
703 | return; | 678 | return; |
704 | 679 | ||
705 | gpn_ft = zfcp_alloc_sg_env(buf_num); | 680 | fc_req = zfcp_alloc_sg_env(buf_num); |
706 | if (!gpn_ft) | 681 | if (!fc_req) |
707 | goto out; | 682 | goto out; |
708 | 683 | ||
709 | for (i = 0; i < 3; i++) { | 684 | for (i = 0; i < 3; i++) { |
710 | ret = zfcp_fc_send_gpn_ft(gpn_ft, adapter, max_bytes); | 685 | ret = zfcp_fc_send_gpn_ft(fc_req, adapter, max_bytes); |
711 | if (!ret) { | 686 | if (!ret) { |
712 | ret = zfcp_fc_eval_gpn_ft(gpn_ft, adapter, max_entries); | 687 | ret = zfcp_fc_eval_gpn_ft(fc_req, adapter, max_entries); |
713 | if (ret == -EAGAIN) | 688 | if (ret == -EAGAIN) |
714 | ssleep(1); | 689 | ssleep(1); |
715 | else | 690 | else |
716 | break; | 691 | break; |
717 | } | 692 | } |
718 | } | 693 | } |
719 | zfcp_free_sg_env(gpn_ft, buf_num); | 694 | zfcp_sg_free_table(&fc_req->sg_rsp, buf_num); |
695 | kmem_cache_free(zfcp_fc_req_cache, fc_req); | ||
720 | out: | 696 | out: |
721 | zfcp_fc_wka_port_put(&adapter->gs->ds); | 697 | zfcp_fc_wka_port_put(&adapter->gs->ds); |
722 | } | 698 | } |
723 | 699 | ||
700 | static int zfcp_fc_gspn(struct zfcp_adapter *adapter, | ||
701 | struct zfcp_fc_req *fc_req) | ||
702 | { | ||
703 | DECLARE_COMPLETION_ONSTACK(completion); | ||
704 | char devno[] = "DEVNO:"; | ||
705 | struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els; | ||
706 | struct zfcp_fc_gspn_req *gspn_req = &fc_req->u.gspn.req; | ||
707 | struct zfcp_fc_gspn_rsp *gspn_rsp = &fc_req->u.gspn.rsp; | ||
708 | int ret; | ||
709 | |||
710 | zfcp_fc_ct_ns_init(&gspn_req->ct_hdr, FC_NS_GSPN_ID, | ||
711 | FC_SYMBOLIC_NAME_SIZE); | ||
712 | hton24(gspn_req->gspn.fp_fid, fc_host_port_id(adapter->scsi_host)); | ||
713 | |||
714 | sg_init_one(&fc_req->sg_req, gspn_req, sizeof(*gspn_req)); | ||
715 | sg_init_one(&fc_req->sg_rsp, gspn_rsp, sizeof(*gspn_rsp)); | ||
716 | |||
717 | ct_els->handler = zfcp_fc_complete; | ||
718 | ct_els->handler_data = &completion; | ||
719 | ct_els->req = &fc_req->sg_req; | ||
720 | ct_els->resp = &fc_req->sg_rsp; | ||
721 | |||
722 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL, | ||
723 | ZFCP_FC_CTELS_TMO); | ||
724 | if (ret) | ||
725 | return ret; | ||
726 | |||
727 | wait_for_completion(&completion); | ||
728 | if (ct_els->status) | ||
729 | return ct_els->status; | ||
730 | |||
731 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_NPIV && | ||
732 | !(strstr(gspn_rsp->gspn.fp_name, devno))) | ||
733 | snprintf(fc_host_symbolic_name(adapter->scsi_host), | ||
734 | FC_SYMBOLIC_NAME_SIZE, "%s%s %s NAME: %s", | ||
735 | gspn_rsp->gspn.fp_name, devno, | ||
736 | dev_name(&adapter->ccw_device->dev), | ||
737 | init_utsname()->nodename); | ||
738 | else | ||
739 | strlcpy(fc_host_symbolic_name(adapter->scsi_host), | ||
740 | gspn_rsp->gspn.fp_name, FC_SYMBOLIC_NAME_SIZE); | ||
741 | |||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | static void zfcp_fc_rspn(struct zfcp_adapter *adapter, | ||
746 | struct zfcp_fc_req *fc_req) | ||
747 | { | ||
748 | DECLARE_COMPLETION_ONSTACK(completion); | ||
749 | struct Scsi_Host *shost = adapter->scsi_host; | ||
750 | struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els; | ||
751 | struct zfcp_fc_rspn_req *rspn_req = &fc_req->u.rspn.req; | ||
752 | struct fc_ct_hdr *rspn_rsp = &fc_req->u.rspn.rsp; | ||
753 | int ret, len; | ||
754 | |||
755 | zfcp_fc_ct_ns_init(&rspn_req->ct_hdr, FC_NS_RSPN_ID, | ||
756 | FC_SYMBOLIC_NAME_SIZE); | ||
757 | hton24(rspn_req->rspn.fr_fid.fp_fid, fc_host_port_id(shost)); | ||
758 | len = strlcpy(rspn_req->rspn.fr_name, fc_host_symbolic_name(shost), | ||
759 | FC_SYMBOLIC_NAME_SIZE); | ||
760 | rspn_req->rspn.fr_name_len = len; | ||
761 | |||
762 | sg_init_one(&fc_req->sg_req, rspn_req, sizeof(*rspn_req)); | ||
763 | sg_init_one(&fc_req->sg_rsp, rspn_rsp, sizeof(*rspn_rsp)); | ||
764 | |||
765 | ct_els->handler = zfcp_fc_complete; | ||
766 | ct_els->handler_data = &completion; | ||
767 | ct_els->req = &fc_req->sg_req; | ||
768 | ct_els->resp = &fc_req->sg_rsp; | ||
769 | |||
770 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL, | ||
771 | ZFCP_FC_CTELS_TMO); | ||
772 | if (!ret) | ||
773 | wait_for_completion(&completion); | ||
774 | } | ||
775 | |||
776 | /** | ||
777 | * zfcp_fc_sym_name_update - Retrieve and update the symbolic port name | ||
778 | * @work: ns_up_work of the adapter where to update the symbolic port name | ||
779 | * | ||
780 | * Retrieve the current symbolic port name that may have been set by | ||
781 | * the hardware using the GSPN request and update the fc_host | ||
782 | * symbolic_name sysfs attribute. When running in NPIV mode (and hence | ||
783 | * the port name is unique for this system), update the symbolic port | ||
784 | * name to add Linux specific information and update the FC nameserver | ||
785 | * using the RSPN request. | ||
786 | */ | ||
787 | void zfcp_fc_sym_name_update(struct work_struct *work) | ||
788 | { | ||
789 | struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter, | ||
790 | ns_up_work); | ||
791 | int ret; | ||
792 | struct zfcp_fc_req *fc_req; | ||
793 | |||
794 | if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT && | ||
795 | fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV) | ||
796 | return; | ||
797 | |||
798 | fc_req = kmem_cache_zalloc(zfcp_fc_req_cache, GFP_KERNEL); | ||
799 | if (!fc_req) | ||
800 | return; | ||
801 | |||
802 | ret = zfcp_fc_wka_port_get(&adapter->gs->ds); | ||
803 | if (ret) | ||
804 | goto out_free; | ||
805 | |||
806 | ret = zfcp_fc_gspn(adapter, fc_req); | ||
807 | if (ret || fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV) | ||
808 | goto out_ds_put; | ||
809 | |||
810 | memset(fc_req, 0, sizeof(*fc_req)); | ||
811 | zfcp_fc_rspn(adapter, fc_req); | ||
812 | |||
813 | out_ds_put: | ||
814 | zfcp_fc_wka_port_put(&adapter->gs->ds); | ||
815 | out_free: | ||
816 | kmem_cache_free(zfcp_fc_req_cache, fc_req); | ||
817 | } | ||
818 | |||
724 | static void zfcp_fc_ct_els_job_handler(void *data) | 819 | static void zfcp_fc_ct_els_job_handler(void *data) |
725 | { | 820 | { |
726 | struct fc_bsg_job *job = data; | 821 | struct fc_bsg_job *job = data; |
diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h index 938d50360166..4561f3bf7300 100644 --- a/drivers/s390/scsi/zfcp_fc.h +++ b/drivers/s390/scsi/zfcp_fc.h | |||
@@ -64,33 +64,16 @@ struct zfcp_fc_gid_pn_req { | |||
64 | } __packed; | 64 | } __packed; |
65 | 65 | ||
66 | /** | 66 | /** |
67 | * struct zfcp_fc_gid_pn_resp - container for ct header plus gid_pn response | 67 | * struct zfcp_fc_gid_pn_rsp - container for ct header plus gid_pn response |
68 | * @ct_hdr: FC GS common transport header | 68 | * @ct_hdr: FC GS common transport header |
69 | * @gid_pn: GID_PN response | 69 | * @gid_pn: GID_PN response |
70 | */ | 70 | */ |
71 | struct zfcp_fc_gid_pn_resp { | 71 | struct zfcp_fc_gid_pn_rsp { |
72 | struct fc_ct_hdr ct_hdr; | 72 | struct fc_ct_hdr ct_hdr; |
73 | struct fc_gid_pn_resp gid_pn; | 73 | struct fc_gid_pn_resp gid_pn; |
74 | } __packed; | 74 | } __packed; |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * struct zfcp_fc_gid_pn - everything required in zfcp for gid_pn request | ||
78 | * @ct: data passed to zfcp_fsf for issuing fsf request | ||
79 | * @sg_req: scatterlist entry for request data | ||
80 | * @sg_resp: scatterlist entry for response data | ||
81 | * @gid_pn_req: GID_PN request data | ||
82 | * @gid_pn_resp: GID_PN response data | ||
83 | */ | ||
84 | struct zfcp_fc_gid_pn { | ||
85 | struct zfcp_fsf_ct_els ct; | ||
86 | struct scatterlist sg_req; | ||
87 | struct scatterlist sg_resp; | ||
88 | struct zfcp_fc_gid_pn_req gid_pn_req; | ||
89 | struct zfcp_fc_gid_pn_resp gid_pn_resp; | ||
90 | struct zfcp_port *port; | ||
91 | }; | ||
92 | |||
93 | /** | ||
94 | * struct zfcp_fc_gpn_ft - container for ct header plus gpn_ft request | 77 | * struct zfcp_fc_gpn_ft - container for ct header plus gpn_ft request |
95 | * @ct_hdr: FC GS common transport header | 78 | * @ct_hdr: FC GS common transport header |
96 | * @gpn_ft: GPN_FT request | 79 | * @gpn_ft: GPN_FT request |
@@ -101,41 +84,72 @@ struct zfcp_fc_gpn_ft_req { | |||
101 | } __packed; | 84 | } __packed; |
102 | 85 | ||
103 | /** | 86 | /** |
104 | * struct zfcp_fc_gpn_ft_resp - container for ct header plus gpn_ft response | 87 | * struct zfcp_fc_gspn_req - container for ct header plus GSPN_ID request |
105 | * @ct_hdr: FC GS common transport header | 88 | * @ct_hdr: FC GS common transport header |
106 | * @gpn_ft: Array of gpn_ft response data to fill one memory page | 89 | * @gspn: GSPN_ID request |
107 | */ | 90 | */ |
108 | struct zfcp_fc_gpn_ft_resp { | 91 | struct zfcp_fc_gspn_req { |
109 | struct fc_ct_hdr ct_hdr; | 92 | struct fc_ct_hdr ct_hdr; |
110 | struct fc_gpn_ft_resp gpn_ft[ZFCP_FC_GPN_FT_ENT_PAGE]; | 93 | struct fc_gid_pn_resp gspn; |
111 | } __packed; | 94 | } __packed; |
112 | 95 | ||
113 | /** | 96 | /** |
114 | * struct zfcp_fc_gpn_ft - zfcp data for gpn_ft request | 97 | * struct zfcp_fc_gspn_rsp - container for ct header plus GSPN_ID response |
115 | * @ct: data passed to zfcp_fsf for issuing fsf request | 98 | * @ct_hdr: FC GS common transport header |
116 | * @sg_req: scatter list entry for gpn_ft request | 99 | * @gspn: GSPN_ID response |
117 | * @sg_resp: scatter list entries for gpn_ft responses (per memory page) | 100 | * @name: The name string of the GSPN_ID response |
118 | */ | 101 | */ |
119 | struct zfcp_fc_gpn_ft { | 102 | struct zfcp_fc_gspn_rsp { |
120 | struct zfcp_fsf_ct_els ct; | 103 | struct fc_ct_hdr ct_hdr; |
121 | struct scatterlist sg_req; | 104 | struct fc_gspn_resp gspn; |
122 | struct scatterlist sg_resp[ZFCP_FC_GPN_FT_NUM_BUFS]; | 105 | char name[FC_SYMBOLIC_NAME_SIZE]; |
123 | }; | 106 | } __packed; |
124 | 107 | ||
125 | /** | 108 | /** |
126 | * struct zfcp_fc_els_adisc - everything required in zfcp for issuing ELS ADISC | 109 | * struct zfcp_fc_rspn_req - container for ct header plus RSPN_ID request |
127 | * @els: data required for issuing els fsf command | 110 | * @ct_hdr: FC GS common transport header |
128 | * @req: scatterlist entry for ELS ADISC request | 111 | * @rspn: RSPN_ID request |
129 | * @resp: scatterlist entry for ELS ADISC response | 112 | * @name: The name string of the RSPN_ID request |
130 | * @adisc_req: ELS ADISC request data | ||
131 | * @adisc_resp: ELS ADISC response data | ||
132 | */ | 113 | */ |
133 | struct zfcp_fc_els_adisc { | 114 | struct zfcp_fc_rspn_req { |
134 | struct zfcp_fsf_ct_els els; | 115 | struct fc_ct_hdr ct_hdr; |
135 | struct scatterlist req; | 116 | struct fc_ns_rspn rspn; |
136 | struct scatterlist resp; | 117 | char name[FC_SYMBOLIC_NAME_SIZE]; |
137 | struct fc_els_adisc adisc_req; | 118 | } __packed; |
138 | struct fc_els_adisc adisc_resp; | 119 | |
120 | /** | ||
121 | * struct zfcp_fc_req - Container for FC ELS and CT requests sent from zfcp | ||
122 | * @ct_els: data required for issuing fsf command | ||
123 | * @sg_req: scatterlist entry for request data | ||
124 | * @sg_rsp: scatterlist entry for response data | ||
125 | * @u: request specific data | ||
126 | */ | ||
127 | struct zfcp_fc_req { | ||
128 | struct zfcp_fsf_ct_els ct_els; | ||
129 | struct scatterlist sg_req; | ||
130 | struct scatterlist sg_rsp; | ||
131 | union { | ||
132 | struct { | ||
133 | struct fc_els_adisc req; | ||
134 | struct fc_els_adisc rsp; | ||
135 | } adisc; | ||
136 | struct { | ||
137 | struct zfcp_fc_gid_pn_req req; | ||
138 | struct zfcp_fc_gid_pn_rsp rsp; | ||
139 | } gid_pn; | ||
140 | struct { | ||
141 | struct scatterlist sg_rsp2[ZFCP_FC_GPN_FT_NUM_BUFS - 1]; | ||
142 | struct zfcp_fc_gpn_ft_req req; | ||
143 | } gpn_ft; | ||
144 | struct { | ||
145 | struct zfcp_fc_gspn_req req; | ||
146 | struct zfcp_fc_gspn_rsp rsp; | ||
147 | } gspn; | ||
148 | struct { | ||
149 | struct zfcp_fc_rspn_req req; | ||
150 | struct fc_ct_hdr rsp; | ||
151 | } rspn; | ||
152 | } u; | ||
139 | }; | 153 | }; |
140 | 154 | ||
141 | /** | 155 | /** |
@@ -192,14 +206,21 @@ struct zfcp_fc_wka_ports { | |||
192 | * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd | 206 | * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd |
193 | * @fcp: fcp_cmnd to setup | 207 | * @fcp: fcp_cmnd to setup |
194 | * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB | 208 | * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB |
209 | * @tm: task management flags to setup task management command | ||
195 | */ | 210 | */ |
196 | static inline | 211 | static inline |
197 | void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi) | 212 | void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi, |
213 | u8 tm_flags) | ||
198 | { | 214 | { |
199 | char tag[2]; | 215 | char tag[2]; |
200 | 216 | ||
201 | int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun); | 217 | int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun); |
202 | 218 | ||
219 | if (unlikely(tm_flags)) { | ||
220 | fcp->fc_tm_flags = tm_flags; | ||
221 | return; | ||
222 | } | ||
223 | |||
203 | if (scsi_populate_tag_msg(scsi, tag)) { | 224 | if (scsi_populate_tag_msg(scsi, tag)) { |
204 | switch (tag[0]) { | 225 | switch (tag[0]) { |
205 | case MSG_ORDERED_TAG: | 226 | case MSG_ORDERED_TAG: |
@@ -226,19 +247,6 @@ void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi) | |||
226 | } | 247 | } |
227 | 248 | ||
228 | /** | 249 | /** |
229 | * zfcp_fc_fcp_tm - setup FCP command as task management command | ||
230 | * @fcp: fcp_cmnd to setup | ||
231 | * @dev: scsi_device where to send the task management command | ||
232 | * @tm: task management flags to setup tm command | ||
233 | */ | ||
234 | static inline | ||
235 | void zfcp_fc_fcp_tm(struct fcp_cmnd *fcp, struct scsi_device *dev, u8 tm_flags) | ||
236 | { | ||
237 | int_to_scsilun(dev->lun, (struct scsi_lun *) &fcp->fc_lun); | ||
238 | fcp->fc_tm_flags |= tm_flags; | ||
239 | } | ||
240 | |||
241 | /** | ||
242 | * zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly | 250 | * zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly |
243 | * @fcp_rsp: FCP RSP IU to evaluate | 251 | * @fcp_rsp: FCP RSP IU to evaluate |
244 | * @scsi: SCSI command where to update status and sense buffer | 252 | * @scsi: SCSI command where to update status and sense buffer |
@@ -270,7 +278,7 @@ void zfcp_fc_eval_fcp_rsp(struct fcp_resp_with_ext *fcp_rsp, | |||
270 | if (unlikely(rsp_flags & FCP_SNS_LEN_VAL)) { | 278 | if (unlikely(rsp_flags & FCP_SNS_LEN_VAL)) { |
271 | sense = (char *) &fcp_rsp[1]; | 279 | sense = (char *) &fcp_rsp[1]; |
272 | if (rsp_flags & FCP_RSP_LEN_VAL) | 280 | if (rsp_flags & FCP_RSP_LEN_VAL) |
273 | sense += fcp_rsp->ext.fr_sns_len; | 281 | sense += fcp_rsp->ext.fr_rsp_len; |
274 | sense_len = min(fcp_rsp->ext.fr_sns_len, | 282 | sense_len = min(fcp_rsp->ext.fr_sns_len, |
275 | (u32) SCSI_SENSE_BUFFERSIZE); | 283 | (u32) SCSI_SENSE_BUFFERSIZE); |
276 | memcpy(scsi->sense_buffer, sense, sense_len); | 284 | memcpy(scsi->sense_buffer, sense, sense_len); |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 9d1d7d1842ce..022fb6a8cb83 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -18,12 +18,14 @@ | |||
18 | #include "zfcp_qdio.h" | 18 | #include "zfcp_qdio.h" |
19 | #include "zfcp_reqlist.h" | 19 | #include "zfcp_reqlist.h" |
20 | 20 | ||
21 | struct kmem_cache *zfcp_fsf_qtcb_cache; | ||
22 | |||
21 | static void zfcp_fsf_request_timeout_handler(unsigned long data) | 23 | static void zfcp_fsf_request_timeout_handler(unsigned long data) |
22 | { | 24 | { |
23 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; | 25 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; |
24 | zfcp_qdio_siosl(adapter); | 26 | zfcp_qdio_siosl(adapter); |
25 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | 27 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
26 | "fsrth_1", NULL); | 28 | "fsrth_1"); |
27 | } | 29 | } |
28 | 30 | ||
29 | static void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, | 31 | static void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, |
@@ -61,50 +63,11 @@ static u32 fsf_qtcb_type[] = { | |||
61 | [FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND | 63 | [FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND |
62 | }; | 64 | }; |
63 | 65 | ||
64 | static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table) | ||
65 | { | ||
66 | u16 subtable = table >> 16; | ||
67 | u16 rule = table & 0xffff; | ||
68 | const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" }; | ||
69 | |||
70 | if (subtable && subtable < ARRAY_SIZE(act_type)) | ||
71 | dev_warn(&adapter->ccw_device->dev, | ||
72 | "Access denied according to ACT rule type %s, " | ||
73 | "rule %d\n", act_type[subtable], rule); | ||
74 | } | ||
75 | |||
76 | static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req, | ||
77 | struct zfcp_port *port) | ||
78 | { | ||
79 | struct fsf_qtcb_header *header = &req->qtcb->header; | ||
80 | dev_warn(&req->adapter->ccw_device->dev, | ||
81 | "Access denied to port 0x%016Lx\n", | ||
82 | (unsigned long long)port->wwpn); | ||
83 | zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]); | ||
84 | zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]); | ||
85 | zfcp_erp_port_access_denied(port, "fspad_1", req); | ||
86 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
87 | } | ||
88 | |||
89 | static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req, | ||
90 | struct zfcp_unit *unit) | ||
91 | { | ||
92 | struct fsf_qtcb_header *header = &req->qtcb->header; | ||
93 | dev_warn(&req->adapter->ccw_device->dev, | ||
94 | "Access denied to unit 0x%016Lx on port 0x%016Lx\n", | ||
95 | (unsigned long long)unit->fcp_lun, | ||
96 | (unsigned long long)unit->port->wwpn); | ||
97 | zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]); | ||
98 | zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]); | ||
99 | zfcp_erp_unit_access_denied(unit, "fsuad_1", req); | ||
100 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
101 | } | ||
102 | |||
103 | static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req) | 66 | static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req) |
104 | { | 67 | { |
105 | dev_err(&req->adapter->ccw_device->dev, "FCP device not " | 68 | dev_err(&req->adapter->ccw_device->dev, "FCP device not " |
106 | "operational because of an unsupported FC class\n"); | 69 | "operational because of an unsupported FC class\n"); |
107 | zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1", req); | 70 | zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1"); |
108 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 71 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
109 | } | 72 | } |
110 | 73 | ||
@@ -122,7 +85,7 @@ void zfcp_fsf_req_free(struct zfcp_fsf_req *req) | |||
122 | } | 85 | } |
123 | 86 | ||
124 | if (likely(req->qtcb)) | 87 | if (likely(req->qtcb)) |
125 | kmem_cache_free(zfcp_data.qtcb_cache, req->qtcb); | 88 | kmem_cache_free(zfcp_fsf_qtcb_cache, req->qtcb); |
126 | kfree(req); | 89 | kfree(req); |
127 | } | 90 | } |
128 | 91 | ||
@@ -137,13 +100,13 @@ static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req) | |||
137 | read_lock_irqsave(&adapter->port_list_lock, flags); | 100 | read_lock_irqsave(&adapter->port_list_lock, flags); |
138 | list_for_each_entry(port, &adapter->port_list, list) | 101 | list_for_each_entry(port, &adapter->port_list, list) |
139 | if (port->d_id == d_id) { | 102 | if (port->d_id == d_id) { |
140 | zfcp_erp_port_reopen(port, 0, "fssrpc1", req); | 103 | zfcp_erp_port_reopen(port, 0, "fssrpc1"); |
141 | break; | 104 | break; |
142 | } | 105 | } |
143 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | 106 | read_unlock_irqrestore(&adapter->port_list_lock, flags); |
144 | } | 107 | } |
145 | 108 | ||
146 | static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id, | 109 | static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, |
147 | struct fsf_link_down_info *link_down) | 110 | struct fsf_link_down_info *link_down) |
148 | { | 111 | { |
149 | struct zfcp_adapter *adapter = req->adapter; | 112 | struct zfcp_adapter *adapter = req->adapter; |
@@ -223,7 +186,7 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id, | |||
223 | "the FC fabric is down\n"); | 186 | "the FC fabric is down\n"); |
224 | } | 187 | } |
225 | out: | 188 | out: |
226 | zfcp_erp_adapter_failed(adapter, id, req); | 189 | zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_ERP_FAILED); |
227 | } | 190 | } |
228 | 191 | ||
229 | static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req) | 192 | static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req) |
@@ -234,13 +197,13 @@ static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req) | |||
234 | 197 | ||
235 | switch (sr_buf->status_subtype) { | 198 | switch (sr_buf->status_subtype) { |
236 | case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: | 199 | case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: |
237 | zfcp_fsf_link_down_info_eval(req, "fssrld1", ldi); | 200 | zfcp_fsf_link_down_info_eval(req, ldi); |
238 | break; | 201 | break; |
239 | case FSF_STATUS_READ_SUB_FDISC_FAILED: | 202 | case FSF_STATUS_READ_SUB_FDISC_FAILED: |
240 | zfcp_fsf_link_down_info_eval(req, "fssrld2", ldi); | 203 | zfcp_fsf_link_down_info_eval(req, ldi); |
241 | break; | 204 | break; |
242 | case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: | 205 | case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: |
243 | zfcp_fsf_link_down_info_eval(req, "fssrld3", NULL); | 206 | zfcp_fsf_link_down_info_eval(req, NULL); |
244 | }; | 207 | }; |
245 | } | 208 | } |
246 | 209 | ||
@@ -250,13 +213,13 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) | |||
250 | struct fsf_status_read_buffer *sr_buf = req->data; | 213 | struct fsf_status_read_buffer *sr_buf = req->data; |
251 | 214 | ||
252 | if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { | 215 | if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { |
253 | zfcp_dbf_hba_fsf_unsol("dism", adapter->dbf, sr_buf); | 216 | zfcp_dbf_hba_fsf_uss("fssrh_1", req); |
254 | mempool_free(sr_buf, adapter->pool.status_read_data); | 217 | mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data); |
255 | zfcp_fsf_req_free(req); | 218 | zfcp_fsf_req_free(req); |
256 | return; | 219 | return; |
257 | } | 220 | } |
258 | 221 | ||
259 | zfcp_dbf_hba_fsf_unsol("read", adapter->dbf, sr_buf); | 222 | zfcp_dbf_hba_fsf_uss("fssrh_2", req); |
260 | 223 | ||
261 | switch (sr_buf->status_type) { | 224 | switch (sr_buf->status_type) { |
262 | case FSF_STATUS_READ_PORT_CLOSED: | 225 | case FSF_STATUS_READ_PORT_CLOSED: |
@@ -271,7 +234,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) | |||
271 | dev_warn(&adapter->ccw_device->dev, | 234 | dev_warn(&adapter->ccw_device->dev, |
272 | "The error threshold for checksum statistics " | 235 | "The error threshold for checksum statistics " |
273 | "has been exceeded\n"); | 236 | "has been exceeded\n"); |
274 | zfcp_dbf_hba_berr(adapter->dbf, req); | 237 | zfcp_dbf_hba_bit_err("fssrh_3", req); |
275 | break; | 238 | break; |
276 | case FSF_STATUS_READ_LINK_DOWN: | 239 | case FSF_STATUS_READ_LINK_DOWN: |
277 | zfcp_fsf_status_read_link_down(req); | 240 | zfcp_fsf_status_read_link_down(req); |
@@ -281,32 +244,30 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) | |||
281 | dev_info(&adapter->ccw_device->dev, | 244 | dev_info(&adapter->ccw_device->dev, |
282 | "The local link has been restored\n"); | 245 | "The local link has been restored\n"); |
283 | /* All ports should be marked as ready to run again */ | 246 | /* All ports should be marked as ready to run again */ |
284 | zfcp_erp_modify_adapter_status(adapter, "fssrh_1", NULL, | 247 | zfcp_erp_set_adapter_status(adapter, |
285 | ZFCP_STATUS_COMMON_RUNNING, | 248 | ZFCP_STATUS_COMMON_RUNNING); |
286 | ZFCP_SET); | ||
287 | zfcp_erp_adapter_reopen(adapter, | 249 | zfcp_erp_adapter_reopen(adapter, |
288 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | | 250 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | |
289 | ZFCP_STATUS_COMMON_ERP_FAILED, | 251 | ZFCP_STATUS_COMMON_ERP_FAILED, |
290 | "fssrh_2", req); | 252 | "fssrh_2"); |
291 | zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKUP, 0); | 253 | zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKUP, 0); |
292 | 254 | ||
293 | break; | 255 | break; |
294 | case FSF_STATUS_READ_NOTIFICATION_LOST: | 256 | case FSF_STATUS_READ_NOTIFICATION_LOST: |
295 | if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED) | 257 | if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED) |
296 | zfcp_erp_adapter_access_changed(adapter, "fssrh_3", | 258 | zfcp_cfdc_adapter_access_changed(adapter); |
297 | req); | ||
298 | if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS) | 259 | if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS) |
299 | queue_work(adapter->work_queue, &adapter->scan_work); | 260 | queue_work(adapter->work_queue, &adapter->scan_work); |
300 | break; | 261 | break; |
301 | case FSF_STATUS_READ_CFDC_UPDATED: | 262 | case FSF_STATUS_READ_CFDC_UPDATED: |
302 | zfcp_erp_adapter_access_changed(adapter, "fssrh_4", req); | 263 | zfcp_cfdc_adapter_access_changed(adapter); |
303 | break; | 264 | break; |
304 | case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: | 265 | case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: |
305 | adapter->adapter_features = sr_buf->payload.word[0]; | 266 | adapter->adapter_features = sr_buf->payload.word[0]; |
306 | break; | 267 | break; |
307 | } | 268 | } |
308 | 269 | ||
309 | mempool_free(sr_buf, adapter->pool.status_read_data); | 270 | mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data); |
310 | zfcp_fsf_req_free(req); | 271 | zfcp_fsf_req_free(req); |
311 | 272 | ||
312 | atomic_inc(&adapter->stat_miss); | 273 | atomic_inc(&adapter->stat_miss); |
@@ -328,7 +289,7 @@ static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req) | |||
328 | "The FCP adapter reported a problem " | 289 | "The FCP adapter reported a problem " |
329 | "that cannot be recovered\n"); | 290 | "that cannot be recovered\n"); |
330 | zfcp_qdio_siosl(req->adapter); | 291 | zfcp_qdio_siosl(req->adapter); |
331 | zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1", req); | 292 | zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1"); |
332 | break; | 293 | break; |
333 | } | 294 | } |
334 | /* all non-return stats set FSFREQ_ERROR*/ | 295 | /* all non-return stats set FSFREQ_ERROR*/ |
@@ -345,7 +306,7 @@ static void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req) | |||
345 | dev_err(&req->adapter->ccw_device->dev, | 306 | dev_err(&req->adapter->ccw_device->dev, |
346 | "The FCP adapter does not recognize the command 0x%x\n", | 307 | "The FCP adapter does not recognize the command 0x%x\n", |
347 | req->qtcb->header.fsf_command); | 308 | req->qtcb->header.fsf_command); |
348 | zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1", req); | 309 | zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1"); |
349 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 310 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
350 | break; | 311 | break; |
351 | case FSF_ADAPTER_STATUS_AVAILABLE: | 312 | case FSF_ADAPTER_STATUS_AVAILABLE: |
@@ -376,17 +337,17 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) | |||
376 | "QTCB version 0x%x not supported by FCP adapter " | 337 | "QTCB version 0x%x not supported by FCP adapter " |
377 | "(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION, | 338 | "(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION, |
378 | psq->word[0], psq->word[1]); | 339 | psq->word[0], psq->word[1]); |
379 | zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1", req); | 340 | zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1"); |
380 | break; | 341 | break; |
381 | case FSF_PROT_ERROR_STATE: | 342 | case FSF_PROT_ERROR_STATE: |
382 | case FSF_PROT_SEQ_NUMB_ERROR: | 343 | case FSF_PROT_SEQ_NUMB_ERROR: |
383 | zfcp_erp_adapter_reopen(adapter, 0, "fspse_2", req); | 344 | zfcp_erp_adapter_reopen(adapter, 0, "fspse_2"); |
384 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 345 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
385 | break; | 346 | break; |
386 | case FSF_PROT_UNSUPP_QTCB_TYPE: | 347 | case FSF_PROT_UNSUPP_QTCB_TYPE: |
387 | dev_err(&adapter->ccw_device->dev, | 348 | dev_err(&adapter->ccw_device->dev, |
388 | "The QTCB type is not supported by the FCP adapter\n"); | 349 | "The QTCB type is not supported by the FCP adapter\n"); |
389 | zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3", req); | 350 | zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3"); |
390 | break; | 351 | break; |
391 | case FSF_PROT_HOST_CONNECTION_INITIALIZING: | 352 | case FSF_PROT_HOST_CONNECTION_INITIALIZING: |
392 | atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | 353 | atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, |
@@ -396,30 +357,28 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) | |||
396 | dev_err(&adapter->ccw_device->dev, | 357 | dev_err(&adapter->ccw_device->dev, |
397 | "0x%Lx is an ambiguous request identifier\n", | 358 | "0x%Lx is an ambiguous request identifier\n", |
398 | (unsigned long long)qtcb->bottom.support.req_handle); | 359 | (unsigned long long)qtcb->bottom.support.req_handle); |
399 | zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4", req); | 360 | zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4"); |
400 | break; | 361 | break; |
401 | case FSF_PROT_LINK_DOWN: | 362 | case FSF_PROT_LINK_DOWN: |
402 | zfcp_fsf_link_down_info_eval(req, "fspse_5", | 363 | zfcp_fsf_link_down_info_eval(req, &psq->link_down_info); |
403 | &psq->link_down_info); | ||
404 | /* go through reopen to flush pending requests */ | 364 | /* go through reopen to flush pending requests */ |
405 | zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req); | 365 | zfcp_erp_adapter_reopen(adapter, 0, "fspse_6"); |
406 | break; | 366 | break; |
407 | case FSF_PROT_REEST_QUEUE: | 367 | case FSF_PROT_REEST_QUEUE: |
408 | /* All ports should be marked as ready to run again */ | 368 | /* All ports should be marked as ready to run again */ |
409 | zfcp_erp_modify_adapter_status(adapter, "fspse_7", NULL, | 369 | zfcp_erp_set_adapter_status(adapter, |
410 | ZFCP_STATUS_COMMON_RUNNING, | 370 | ZFCP_STATUS_COMMON_RUNNING); |
411 | ZFCP_SET); | ||
412 | zfcp_erp_adapter_reopen(adapter, | 371 | zfcp_erp_adapter_reopen(adapter, |
413 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | | 372 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | |
414 | ZFCP_STATUS_COMMON_ERP_FAILED, | 373 | ZFCP_STATUS_COMMON_ERP_FAILED, |
415 | "fspse_8", req); | 374 | "fspse_8"); |
416 | break; | 375 | break; |
417 | default: | 376 | default: |
418 | dev_err(&adapter->ccw_device->dev, | 377 | dev_err(&adapter->ccw_device->dev, |
419 | "0x%x is not a valid transfer protocol status\n", | 378 | "0x%x is not a valid transfer protocol status\n", |
420 | qtcb->prefix.prot_status); | 379 | qtcb->prefix.prot_status); |
421 | zfcp_qdio_siosl(adapter); | 380 | zfcp_qdio_siosl(adapter); |
422 | zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9", req); | 381 | zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9"); |
423 | } | 382 | } |
424 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 383 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
425 | } | 384 | } |
@@ -525,7 +484,7 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) | |||
525 | dev_err(&adapter->ccw_device->dev, | 484 | dev_err(&adapter->ccw_device->dev, |
526 | "Unknown or unsupported arbitrated loop " | 485 | "Unknown or unsupported arbitrated loop " |
527 | "fibre channel topology detected\n"); | 486 | "fibre channel topology detected\n"); |
528 | zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1", req); | 487 | zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1"); |
529 | return -EIO; | 488 | return -EIO; |
530 | } | 489 | } |
531 | 490 | ||
@@ -561,7 +520,7 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) | |||
561 | "FCP adapter maximum QTCB size (%d bytes) " | 520 | "FCP adapter maximum QTCB size (%d bytes) " |
562 | "is too small\n", | 521 | "is too small\n", |
563 | bottom->max_qtcb_size); | 522 | bottom->max_qtcb_size); |
564 | zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1", req); | 523 | zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1"); |
565 | return; | 524 | return; |
566 | } | 525 | } |
567 | atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, | 526 | atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, |
@@ -575,14 +534,11 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) | |||
575 | fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; | 534 | fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; |
576 | adapter->hydra_version = 0; | 535 | adapter->hydra_version = 0; |
577 | 536 | ||
578 | atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, | 537 | zfcp_fsf_link_down_info_eval(req, |
579 | &adapter->status); | ||
580 | |||
581 | zfcp_fsf_link_down_info_eval(req, "fsecdh2", | ||
582 | &qtcb->header.fsf_status_qual.link_down_info); | 538 | &qtcb->header.fsf_status_qual.link_down_info); |
583 | break; | 539 | break; |
584 | default: | 540 | default: |
585 | zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3", req); | 541 | zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3"); |
586 | return; | 542 | return; |
587 | } | 543 | } |
588 | 544 | ||
@@ -598,14 +554,14 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) | |||
598 | dev_err(&adapter->ccw_device->dev, | 554 | dev_err(&adapter->ccw_device->dev, |
599 | "The FCP adapter only supports newer " | 555 | "The FCP adapter only supports newer " |
600 | "control block versions\n"); | 556 | "control block versions\n"); |
601 | zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4", req); | 557 | zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4"); |
602 | return; | 558 | return; |
603 | } | 559 | } |
604 | if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) { | 560 | if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) { |
605 | dev_err(&adapter->ccw_device->dev, | 561 | dev_err(&adapter->ccw_device->dev, |
606 | "The FCP adapter only supports older " | 562 | "The FCP adapter only supports older " |
607 | "control block versions\n"); | 563 | "control block versions\n"); |
608 | zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5", req); | 564 | zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5"); |
609 | } | 565 | } |
610 | } | 566 | } |
611 | 567 | ||
@@ -644,7 +600,7 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) | |||
644 | break; | 600 | break; |
645 | case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: | 601 | case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: |
646 | zfcp_fsf_exchange_port_evaluate(req); | 602 | zfcp_fsf_exchange_port_evaluate(req); |
647 | zfcp_fsf_link_down_info_eval(req, "fsepdh1", | 603 | zfcp_fsf_link_down_info_eval(req, |
648 | &qtcb->header.fsf_status_qual.link_down_info); | 604 | &qtcb->header.fsf_status_qual.link_down_info); |
649 | break; | 605 | break; |
650 | } | 606 | } |
@@ -674,7 +630,7 @@ static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool) | |||
674 | if (likely(pool)) | 630 | if (likely(pool)) |
675 | qtcb = mempool_alloc(pool, GFP_ATOMIC); | 631 | qtcb = mempool_alloc(pool, GFP_ATOMIC); |
676 | else | 632 | else |
677 | qtcb = kmem_cache_alloc(zfcp_data.qtcb_cache, GFP_ATOMIC); | 633 | qtcb = kmem_cache_alloc(zfcp_fsf_qtcb_cache, GFP_ATOMIC); |
678 | 634 | ||
679 | if (unlikely(!qtcb)) | 635 | if (unlikely(!qtcb)) |
680 | return NULL; | 636 | return NULL; |
@@ -684,7 +640,7 @@ static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool) | |||
684 | } | 640 | } |
685 | 641 | ||
686 | static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio, | 642 | static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio, |
687 | u32 fsf_cmd, u32 sbtype, | 643 | u32 fsf_cmd, u8 sbtype, |
688 | mempool_t *pool) | 644 | mempool_t *pool) |
689 | { | 645 | { |
690 | struct zfcp_adapter *adapter = qdio->adapter; | 646 | struct zfcp_adapter *adapter = qdio->adapter; |
@@ -746,7 +702,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) | |||
746 | del_timer(&req->timer); | 702 | del_timer(&req->timer); |
747 | /* lookup request again, list might have changed */ | 703 | /* lookup request again, list might have changed */ |
748 | zfcp_reqlist_find_rm(adapter->req_list, req_id); | 704 | zfcp_reqlist_find_rm(adapter->req_list, req_id); |
749 | zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req); | 705 | zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1"); |
750 | return -EIO; | 706 | return -EIO; |
751 | } | 707 | } |
752 | 708 | ||
@@ -769,9 +725,10 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio) | |||
769 | struct zfcp_adapter *adapter = qdio->adapter; | 725 | struct zfcp_adapter *adapter = qdio->adapter; |
770 | struct zfcp_fsf_req *req; | 726 | struct zfcp_fsf_req *req; |
771 | struct fsf_status_read_buffer *sr_buf; | 727 | struct fsf_status_read_buffer *sr_buf; |
728 | struct page *page; | ||
772 | int retval = -EIO; | 729 | int retval = -EIO; |
773 | 730 | ||
774 | spin_lock_bh(&qdio->req_q_lock); | 731 | spin_lock_irq(&qdio->req_q_lock); |
775 | if (zfcp_qdio_sbal_get(qdio)) | 732 | if (zfcp_qdio_sbal_get(qdio)) |
776 | goto out; | 733 | goto out; |
777 | 734 | ||
@@ -782,11 +739,12 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio) | |||
782 | goto out; | 739 | goto out; |
783 | } | 740 | } |
784 | 741 | ||
785 | sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC); | 742 | page = mempool_alloc(adapter->pool.sr_data, GFP_ATOMIC); |
786 | if (!sr_buf) { | 743 | if (!page) { |
787 | retval = -ENOMEM; | 744 | retval = -ENOMEM; |
788 | goto failed_buf; | 745 | goto failed_buf; |
789 | } | 746 | } |
747 | sr_buf = page_address(page); | ||
790 | memset(sr_buf, 0, sizeof(*sr_buf)); | 748 | memset(sr_buf, 0, sizeof(*sr_buf)); |
791 | req->data = sr_buf; | 749 | req->data = sr_buf; |
792 | 750 | ||
@@ -800,18 +758,20 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio) | |||
800 | goto out; | 758 | goto out; |
801 | 759 | ||
802 | failed_req_send: | 760 | failed_req_send: |
803 | mempool_free(sr_buf, adapter->pool.status_read_data); | 761 | req->data = NULL; |
762 | mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data); | ||
804 | failed_buf: | 763 | failed_buf: |
764 | zfcp_dbf_hba_fsf_uss("fssr__1", req); | ||
805 | zfcp_fsf_req_free(req); | 765 | zfcp_fsf_req_free(req); |
806 | zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL); | ||
807 | out: | 766 | out: |
808 | spin_unlock_bh(&qdio->req_q_lock); | 767 | spin_unlock_irq(&qdio->req_q_lock); |
809 | return retval; | 768 | return retval; |
810 | } | 769 | } |
811 | 770 | ||
812 | static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) | 771 | static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) |
813 | { | 772 | { |
814 | struct zfcp_unit *unit = req->data; | 773 | struct scsi_device *sdev = req->data; |
774 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
815 | union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual; | 775 | union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual; |
816 | 776 | ||
817 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) | 777 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
@@ -820,14 +780,14 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) | |||
820 | switch (req->qtcb->header.fsf_status) { | 780 | switch (req->qtcb->header.fsf_status) { |
821 | case FSF_PORT_HANDLE_NOT_VALID: | 781 | case FSF_PORT_HANDLE_NOT_VALID: |
822 | if (fsq->word[0] == fsq->word[1]) { | 782 | if (fsq->word[0] == fsq->word[1]) { |
823 | zfcp_erp_adapter_reopen(unit->port->adapter, 0, | 783 | zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, |
824 | "fsafch1", req); | 784 | "fsafch1"); |
825 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 785 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
826 | } | 786 | } |
827 | break; | 787 | break; |
828 | case FSF_LUN_HANDLE_NOT_VALID: | 788 | case FSF_LUN_HANDLE_NOT_VALID: |
829 | if (fsq->word[0] == fsq->word[1]) { | 789 | if (fsq->word[0] == fsq->word[1]) { |
830 | zfcp_erp_port_reopen(unit->port, 0, "fsafch2", req); | 790 | zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2"); |
831 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 791 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
832 | } | 792 | } |
833 | break; | 793 | break; |
@@ -835,17 +795,22 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) | |||
835 | req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED; | 795 | req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED; |
836 | break; | 796 | break; |
837 | case FSF_PORT_BOXED: | 797 | case FSF_PORT_BOXED: |
838 | zfcp_erp_port_boxed(unit->port, "fsafch3", req); | 798 | zfcp_erp_set_port_status(zfcp_sdev->port, |
799 | ZFCP_STATUS_COMMON_ACCESS_BOXED); | ||
800 | zfcp_erp_port_reopen(zfcp_sdev->port, | ||
801 | ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3"); | ||
839 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 802 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
840 | break; | 803 | break; |
841 | case FSF_LUN_BOXED: | 804 | case FSF_LUN_BOXED: |
842 | zfcp_erp_unit_boxed(unit, "fsafch4", req); | 805 | zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED); |
806 | zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED, | ||
807 | "fsafch4"); | ||
843 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 808 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
844 | break; | 809 | break; |
845 | case FSF_ADAPTER_STATUS_AVAILABLE: | 810 | case FSF_ADAPTER_STATUS_AVAILABLE: |
846 | switch (fsq->word[0]) { | 811 | switch (fsq->word[0]) { |
847 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: | 812 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
848 | zfcp_fc_test_link(unit->port); | 813 | zfcp_fc_test_link(zfcp_sdev->port); |
849 | /* fall through */ | 814 | /* fall through */ |
850 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: | 815 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: |
851 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 816 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
@@ -859,39 +824,40 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) | |||
859 | } | 824 | } |
860 | 825 | ||
861 | /** | 826 | /** |
862 | * zfcp_fsf_abort_fcp_command - abort running SCSI command | 827 | * zfcp_fsf_abort_fcp_cmnd - abort running SCSI command |
863 | * @old_req_id: unsigned long | 828 | * @scmnd: The SCSI command to abort |
864 | * @unit: pointer to struct zfcp_unit | ||
865 | * Returns: pointer to struct zfcp_fsf_req | 829 | * Returns: pointer to struct zfcp_fsf_req |
866 | */ | 830 | */ |
867 | 831 | ||
868 | struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id, | 832 | struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd) |
869 | struct zfcp_unit *unit) | ||
870 | { | 833 | { |
871 | struct zfcp_fsf_req *req = NULL; | 834 | struct zfcp_fsf_req *req = NULL; |
872 | struct zfcp_qdio *qdio = unit->port->adapter->qdio; | 835 | struct scsi_device *sdev = scmnd->device; |
836 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
837 | struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio; | ||
838 | unsigned long old_req_id = (unsigned long) scmnd->host_scribble; | ||
873 | 839 | ||
874 | spin_lock_bh(&qdio->req_q_lock); | 840 | spin_lock_irq(&qdio->req_q_lock); |
875 | if (zfcp_qdio_sbal_get(qdio)) | 841 | if (zfcp_qdio_sbal_get(qdio)) |
876 | goto out; | 842 | goto out; |
877 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND, | 843 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND, |
878 | SBAL_FLAGS0_TYPE_READ, | 844 | SBAL_SFLAGS0_TYPE_READ, |
879 | qdio->adapter->pool.scsi_abort); | 845 | qdio->adapter->pool.scsi_abort); |
880 | if (IS_ERR(req)) { | 846 | if (IS_ERR(req)) { |
881 | req = NULL; | 847 | req = NULL; |
882 | goto out; | 848 | goto out; |
883 | } | 849 | } |
884 | 850 | ||
885 | if (unlikely(!(atomic_read(&unit->status) & | 851 | if (unlikely(!(atomic_read(&zfcp_sdev->status) & |
886 | ZFCP_STATUS_COMMON_UNBLOCKED))) | 852 | ZFCP_STATUS_COMMON_UNBLOCKED))) |
887 | goto out_error_free; | 853 | goto out_error_free; |
888 | 854 | ||
889 | zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); | 855 | zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); |
890 | 856 | ||
891 | req->data = unit; | 857 | req->data = sdev; |
892 | req->handler = zfcp_fsf_abort_fcp_command_handler; | 858 | req->handler = zfcp_fsf_abort_fcp_command_handler; |
893 | req->qtcb->header.lun_handle = unit->handle; | 859 | req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; |
894 | req->qtcb->header.port_handle = unit->port->handle; | 860 | req->qtcb->header.port_handle = zfcp_sdev->port->handle; |
895 | req->qtcb->bottom.support.req_handle = (u64) old_req_id; | 861 | req->qtcb->bottom.support.req_handle = (u64) old_req_id; |
896 | 862 | ||
897 | zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT); | 863 | zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT); |
@@ -902,7 +868,7 @@ out_error_free: | |||
902 | zfcp_fsf_req_free(req); | 868 | zfcp_fsf_req_free(req); |
903 | req = NULL; | 869 | req = NULL; |
904 | out: | 870 | out: |
905 | spin_unlock_bh(&qdio->req_q_lock); | 871 | spin_unlock_irq(&qdio->req_q_lock); |
906 | return req; | 872 | return req; |
907 | } | 873 | } |
908 | 874 | ||
@@ -919,7 +885,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) | |||
919 | 885 | ||
920 | switch (header->fsf_status) { | 886 | switch (header->fsf_status) { |
921 | case FSF_GOOD: | 887 | case FSF_GOOD: |
922 | zfcp_dbf_san_ct_response(req); | 888 | zfcp_dbf_san_res("fsscth1", req); |
923 | ct->status = 0; | 889 | ct->status = 0; |
924 | break; | 890 | break; |
925 | case FSF_SERVICE_CLASS_NOT_SUPPORTED: | 891 | case FSF_SERVICE_CLASS_NOT_SUPPORTED: |
@@ -939,7 +905,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) | |||
939 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 905 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
940 | break; | 906 | break; |
941 | case FSF_PORT_HANDLE_NOT_VALID: | 907 | case FSF_PORT_HANDLE_NOT_VALID: |
942 | zfcp_erp_adapter_reopen(adapter, 0, "fsscth1", req); | 908 | zfcp_erp_adapter_reopen(adapter, 0, "fsscth1"); |
943 | /* fall through */ | 909 | /* fall through */ |
944 | case FSF_GENERIC_COMMAND_REJECTED: | 910 | case FSF_GENERIC_COMMAND_REJECTED: |
945 | case FSF_PAYLOAD_SIZE_MISMATCH: | 911 | case FSF_PAYLOAD_SIZE_MISMATCH: |
@@ -1041,12 +1007,12 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port, | |||
1041 | struct zfcp_fsf_req *req; | 1007 | struct zfcp_fsf_req *req; |
1042 | int ret = -EIO; | 1008 | int ret = -EIO; |
1043 | 1009 | ||
1044 | spin_lock_bh(&qdio->req_q_lock); | 1010 | spin_lock_irq(&qdio->req_q_lock); |
1045 | if (zfcp_qdio_sbal_get(qdio)) | 1011 | if (zfcp_qdio_sbal_get(qdio)) |
1046 | goto out; | 1012 | goto out; |
1047 | 1013 | ||
1048 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC, | 1014 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC, |
1049 | SBAL_FLAGS0_TYPE_WRITE_READ, pool); | 1015 | SBAL_SFLAGS0_TYPE_WRITE_READ, pool); |
1050 | 1016 | ||
1051 | if (IS_ERR(req)) { | 1017 | if (IS_ERR(req)) { |
1052 | ret = PTR_ERR(req); | 1018 | ret = PTR_ERR(req); |
@@ -1062,7 +1028,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port, | |||
1062 | req->qtcb->header.port_handle = wka_port->handle; | 1028 | req->qtcb->header.port_handle = wka_port->handle; |
1063 | req->data = ct; | 1029 | req->data = ct; |
1064 | 1030 | ||
1065 | zfcp_dbf_san_ct_request(req, wka_port->d_id); | 1031 | zfcp_dbf_san_req("fssct_1", req, wka_port->d_id); |
1066 | 1032 | ||
1067 | ret = zfcp_fsf_req_send(req); | 1033 | ret = zfcp_fsf_req_send(req); |
1068 | if (ret) | 1034 | if (ret) |
@@ -1073,7 +1039,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port, | |||
1073 | failed_send: | 1039 | failed_send: |
1074 | zfcp_fsf_req_free(req); | 1040 | zfcp_fsf_req_free(req); |
1075 | out: | 1041 | out: |
1076 | spin_unlock_bh(&qdio->req_q_lock); | 1042 | spin_unlock_irq(&qdio->req_q_lock); |
1077 | return ret; | 1043 | return ret; |
1078 | } | 1044 | } |
1079 | 1045 | ||
@@ -1090,7 +1056,7 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req) | |||
1090 | 1056 | ||
1091 | switch (header->fsf_status) { | 1057 | switch (header->fsf_status) { |
1092 | case FSF_GOOD: | 1058 | case FSF_GOOD: |
1093 | zfcp_dbf_san_els_response(req); | 1059 | zfcp_dbf_san_res("fsselh1", req); |
1094 | send_els->status = 0; | 1060 | send_els->status = 0; |
1095 | break; | 1061 | break; |
1096 | case FSF_SERVICE_CLASS_NOT_SUPPORTED: | 1062 | case FSF_SERVICE_CLASS_NOT_SUPPORTED: |
@@ -1111,11 +1077,13 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req) | |||
1111 | case FSF_RESPONSE_SIZE_TOO_LARGE: | 1077 | case FSF_RESPONSE_SIZE_TOO_LARGE: |
1112 | break; | 1078 | break; |
1113 | case FSF_ACCESS_DENIED: | 1079 | case FSF_ACCESS_DENIED: |
1114 | if (port) | 1080 | if (port) { |
1115 | zfcp_fsf_access_denied_port(req, port); | 1081 | zfcp_cfdc_port_denied(port, &header->fsf_status_qual); |
1082 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
1083 | } | ||
1116 | break; | 1084 | break; |
1117 | case FSF_SBAL_MISMATCH: | 1085 | case FSF_SBAL_MISMATCH: |
1118 | /* should never occure, avoided in zfcp_fsf_send_els */ | 1086 | /* should never occur, avoided in zfcp_fsf_send_els */ |
1119 | /* fall through */ | 1087 | /* fall through */ |
1120 | default: | 1088 | default: |
1121 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1089 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
@@ -1137,12 +1105,12 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id, | |||
1137 | struct zfcp_qdio *qdio = adapter->qdio; | 1105 | struct zfcp_qdio *qdio = adapter->qdio; |
1138 | int ret = -EIO; | 1106 | int ret = -EIO; |
1139 | 1107 | ||
1140 | spin_lock_bh(&qdio->req_q_lock); | 1108 | spin_lock_irq(&qdio->req_q_lock); |
1141 | if (zfcp_qdio_sbal_get(qdio)) | 1109 | if (zfcp_qdio_sbal_get(qdio)) |
1142 | goto out; | 1110 | goto out; |
1143 | 1111 | ||
1144 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS, | 1112 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS, |
1145 | SBAL_FLAGS0_TYPE_WRITE_READ, NULL); | 1113 | SBAL_SFLAGS0_TYPE_WRITE_READ, NULL); |
1146 | 1114 | ||
1147 | if (IS_ERR(req)) { | 1115 | if (IS_ERR(req)) { |
1148 | ret = PTR_ERR(req); | 1116 | ret = PTR_ERR(req); |
@@ -1162,7 +1130,7 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id, | |||
1162 | req->handler = zfcp_fsf_send_els_handler; | 1130 | req->handler = zfcp_fsf_send_els_handler; |
1163 | req->data = els; | 1131 | req->data = els; |
1164 | 1132 | ||
1165 | zfcp_dbf_san_els_request(req); | 1133 | zfcp_dbf_san_req("fssels1", req, d_id); |
1166 | 1134 | ||
1167 | ret = zfcp_fsf_req_send(req); | 1135 | ret = zfcp_fsf_req_send(req); |
1168 | if (ret) | 1136 | if (ret) |
@@ -1173,7 +1141,7 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id, | |||
1173 | failed_send: | 1141 | failed_send: |
1174 | zfcp_fsf_req_free(req); | 1142 | zfcp_fsf_req_free(req); |
1175 | out: | 1143 | out: |
1176 | spin_unlock_bh(&qdio->req_q_lock); | 1144 | spin_unlock_irq(&qdio->req_q_lock); |
1177 | return ret; | 1145 | return ret; |
1178 | } | 1146 | } |
1179 | 1147 | ||
@@ -1183,12 +1151,12 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) | |||
1183 | struct zfcp_qdio *qdio = erp_action->adapter->qdio; | 1151 | struct zfcp_qdio *qdio = erp_action->adapter->qdio; |
1184 | int retval = -EIO; | 1152 | int retval = -EIO; |
1185 | 1153 | ||
1186 | spin_lock_bh(&qdio->req_q_lock); | 1154 | spin_lock_irq(&qdio->req_q_lock); |
1187 | if (zfcp_qdio_sbal_get(qdio)) | 1155 | if (zfcp_qdio_sbal_get(qdio)) |
1188 | goto out; | 1156 | goto out; |
1189 | 1157 | ||
1190 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, | 1158 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, |
1191 | SBAL_FLAGS0_TYPE_READ, | 1159 | SBAL_SFLAGS0_TYPE_READ, |
1192 | qdio->adapter->pool.erp_req); | 1160 | qdio->adapter->pool.erp_req); |
1193 | 1161 | ||
1194 | if (IS_ERR(req)) { | 1162 | if (IS_ERR(req)) { |
@@ -1215,7 +1183,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) | |||
1215 | erp_action->fsf_req_id = 0; | 1183 | erp_action->fsf_req_id = 0; |
1216 | } | 1184 | } |
1217 | out: | 1185 | out: |
1218 | spin_unlock_bh(&qdio->req_q_lock); | 1186 | spin_unlock_irq(&qdio->req_q_lock); |
1219 | return retval; | 1187 | return retval; |
1220 | } | 1188 | } |
1221 | 1189 | ||
@@ -1225,12 +1193,12 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio, | |||
1225 | struct zfcp_fsf_req *req = NULL; | 1193 | struct zfcp_fsf_req *req = NULL; |
1226 | int retval = -EIO; | 1194 | int retval = -EIO; |
1227 | 1195 | ||
1228 | spin_lock_bh(&qdio->req_q_lock); | 1196 | spin_lock_irq(&qdio->req_q_lock); |
1229 | if (zfcp_qdio_sbal_get(qdio)) | 1197 | if (zfcp_qdio_sbal_get(qdio)) |
1230 | goto out_unlock; | 1198 | goto out_unlock; |
1231 | 1199 | ||
1232 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, | 1200 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, |
1233 | SBAL_FLAGS0_TYPE_READ, NULL); | 1201 | SBAL_SFLAGS0_TYPE_READ, NULL); |
1234 | 1202 | ||
1235 | if (IS_ERR(req)) { | 1203 | if (IS_ERR(req)) { |
1236 | retval = PTR_ERR(req); | 1204 | retval = PTR_ERR(req); |
@@ -1251,7 +1219,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio, | |||
1251 | 1219 | ||
1252 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | 1220 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); |
1253 | retval = zfcp_fsf_req_send(req); | 1221 | retval = zfcp_fsf_req_send(req); |
1254 | spin_unlock_bh(&qdio->req_q_lock); | 1222 | spin_unlock_irq(&qdio->req_q_lock); |
1255 | if (!retval) | 1223 | if (!retval) |
1256 | wait_for_completion(&req->completion); | 1224 | wait_for_completion(&req->completion); |
1257 | 1225 | ||
@@ -1259,7 +1227,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio, | |||
1259 | return retval; | 1227 | return retval; |
1260 | 1228 | ||
1261 | out_unlock: | 1229 | out_unlock: |
1262 | spin_unlock_bh(&qdio->req_q_lock); | 1230 | spin_unlock_irq(&qdio->req_q_lock); |
1263 | return retval; | 1231 | return retval; |
1264 | } | 1232 | } |
1265 | 1233 | ||
@@ -1277,12 +1245,12 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) | |||
1277 | if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) | 1245 | if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) |
1278 | return -EOPNOTSUPP; | 1246 | return -EOPNOTSUPP; |
1279 | 1247 | ||
1280 | spin_lock_bh(&qdio->req_q_lock); | 1248 | spin_lock_irq(&qdio->req_q_lock); |
1281 | if (zfcp_qdio_sbal_get(qdio)) | 1249 | if (zfcp_qdio_sbal_get(qdio)) |
1282 | goto out; | 1250 | goto out; |
1283 | 1251 | ||
1284 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, | 1252 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, |
1285 | SBAL_FLAGS0_TYPE_READ, | 1253 | SBAL_SFLAGS0_TYPE_READ, |
1286 | qdio->adapter->pool.erp_req); | 1254 | qdio->adapter->pool.erp_req); |
1287 | 1255 | ||
1288 | if (IS_ERR(req)) { | 1256 | if (IS_ERR(req)) { |
@@ -1304,7 +1272,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) | |||
1304 | erp_action->fsf_req_id = 0; | 1272 | erp_action->fsf_req_id = 0; |
1305 | } | 1273 | } |
1306 | out: | 1274 | out: |
1307 | spin_unlock_bh(&qdio->req_q_lock); | 1275 | spin_unlock_irq(&qdio->req_q_lock); |
1308 | return retval; | 1276 | return retval; |
1309 | } | 1277 | } |
1310 | 1278 | ||
@@ -1323,12 +1291,12 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio, | |||
1323 | if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) | 1291 | if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) |
1324 | return -EOPNOTSUPP; | 1292 | return -EOPNOTSUPP; |
1325 | 1293 | ||
1326 | spin_lock_bh(&qdio->req_q_lock); | 1294 | spin_lock_irq(&qdio->req_q_lock); |
1327 | if (zfcp_qdio_sbal_get(qdio)) | 1295 | if (zfcp_qdio_sbal_get(qdio)) |
1328 | goto out_unlock; | 1296 | goto out_unlock; |
1329 | 1297 | ||
1330 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, | 1298 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, |
1331 | SBAL_FLAGS0_TYPE_READ, NULL); | 1299 | SBAL_SFLAGS0_TYPE_READ, NULL); |
1332 | 1300 | ||
1333 | if (IS_ERR(req)) { | 1301 | if (IS_ERR(req)) { |
1334 | retval = PTR_ERR(req); | 1302 | retval = PTR_ERR(req); |
@@ -1343,7 +1311,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio, | |||
1343 | req->handler = zfcp_fsf_exchange_port_data_handler; | 1311 | req->handler = zfcp_fsf_exchange_port_data_handler; |
1344 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | 1312 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); |
1345 | retval = zfcp_fsf_req_send(req); | 1313 | retval = zfcp_fsf_req_send(req); |
1346 | spin_unlock_bh(&qdio->req_q_lock); | 1314 | spin_unlock_irq(&qdio->req_q_lock); |
1347 | 1315 | ||
1348 | if (!retval) | 1316 | if (!retval) |
1349 | wait_for_completion(&req->completion); | 1317 | wait_for_completion(&req->completion); |
@@ -1353,7 +1321,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio, | |||
1353 | return retval; | 1321 | return retval; |
1354 | 1322 | ||
1355 | out_unlock: | 1323 | out_unlock: |
1356 | spin_unlock_bh(&qdio->req_q_lock); | 1324 | spin_unlock_irq(&qdio->req_q_lock); |
1357 | return retval; | 1325 | return retval; |
1358 | } | 1326 | } |
1359 | 1327 | ||
@@ -1370,14 +1338,16 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1370 | case FSF_PORT_ALREADY_OPEN: | 1338 | case FSF_PORT_ALREADY_OPEN: |
1371 | break; | 1339 | break; |
1372 | case FSF_ACCESS_DENIED: | 1340 | case FSF_ACCESS_DENIED: |
1373 | zfcp_fsf_access_denied_port(req, port); | 1341 | zfcp_cfdc_port_denied(port, &header->fsf_status_qual); |
1342 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
1374 | break; | 1343 | break; |
1375 | case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: | 1344 | case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: |
1376 | dev_warn(&req->adapter->ccw_device->dev, | 1345 | dev_warn(&req->adapter->ccw_device->dev, |
1377 | "Not enough FCP adapter resources to open " | 1346 | "Not enough FCP adapter resources to open " |
1378 | "remote port 0x%016Lx\n", | 1347 | "remote port 0x%016Lx\n", |
1379 | (unsigned long long)port->wwpn); | 1348 | (unsigned long long)port->wwpn); |
1380 | zfcp_erp_port_failed(port, "fsoph_1", req); | 1349 | zfcp_erp_set_port_status(port, |
1350 | ZFCP_STATUS_COMMON_ERP_FAILED); | ||
1381 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1351 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1382 | break; | 1352 | break; |
1383 | case FSF_ADAPTER_STATUS_AVAILABLE: | 1353 | case FSF_ADAPTER_STATUS_AVAILABLE: |
@@ -1437,12 +1407,12 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) | |||
1437 | struct zfcp_fsf_req *req; | 1407 | struct zfcp_fsf_req *req; |
1438 | int retval = -EIO; | 1408 | int retval = -EIO; |
1439 | 1409 | ||
1440 | spin_lock_bh(&qdio->req_q_lock); | 1410 | spin_lock_irq(&qdio->req_q_lock); |
1441 | if (zfcp_qdio_sbal_get(qdio)) | 1411 | if (zfcp_qdio_sbal_get(qdio)) |
1442 | goto out; | 1412 | goto out; |
1443 | 1413 | ||
1444 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID, | 1414 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID, |
1445 | SBAL_FLAGS0_TYPE_READ, | 1415 | SBAL_SFLAGS0_TYPE_READ, |
1446 | qdio->adapter->pool.erp_req); | 1416 | qdio->adapter->pool.erp_req); |
1447 | 1417 | ||
1448 | if (IS_ERR(req)) { | 1418 | if (IS_ERR(req)) { |
@@ -1468,7 +1438,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) | |||
1468 | put_device(&port->dev); | 1438 | put_device(&port->dev); |
1469 | } | 1439 | } |
1470 | out: | 1440 | out: |
1471 | spin_unlock_bh(&qdio->req_q_lock); | 1441 | spin_unlock_irq(&qdio->req_q_lock); |
1472 | return retval; | 1442 | return retval; |
1473 | } | 1443 | } |
1474 | 1444 | ||
@@ -1481,15 +1451,13 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req) | |||
1481 | 1451 | ||
1482 | switch (req->qtcb->header.fsf_status) { | 1452 | switch (req->qtcb->header.fsf_status) { |
1483 | case FSF_PORT_HANDLE_NOT_VALID: | 1453 | case FSF_PORT_HANDLE_NOT_VALID: |
1484 | zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1", req); | 1454 | zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1"); |
1485 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1455 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1486 | break; | 1456 | break; |
1487 | case FSF_ADAPTER_STATUS_AVAILABLE: | 1457 | case FSF_ADAPTER_STATUS_AVAILABLE: |
1488 | break; | 1458 | break; |
1489 | case FSF_GOOD: | 1459 | case FSF_GOOD: |
1490 | zfcp_erp_modify_port_status(port, "fscph_2", req, | 1460 | zfcp_erp_clear_port_status(port, ZFCP_STATUS_COMMON_OPEN); |
1491 | ZFCP_STATUS_COMMON_OPEN, | ||
1492 | ZFCP_CLEAR); | ||
1493 | break; | 1461 | break; |
1494 | } | 1462 | } |
1495 | } | 1463 | } |
@@ -1505,12 +1473,12 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) | |||
1505 | struct zfcp_fsf_req *req; | 1473 | struct zfcp_fsf_req *req; |
1506 | int retval = -EIO; | 1474 | int retval = -EIO; |
1507 | 1475 | ||
1508 | spin_lock_bh(&qdio->req_q_lock); | 1476 | spin_lock_irq(&qdio->req_q_lock); |
1509 | if (zfcp_qdio_sbal_get(qdio)) | 1477 | if (zfcp_qdio_sbal_get(qdio)) |
1510 | goto out; | 1478 | goto out; |
1511 | 1479 | ||
1512 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT, | 1480 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT, |
1513 | SBAL_FLAGS0_TYPE_READ, | 1481 | SBAL_SFLAGS0_TYPE_READ, |
1514 | qdio->adapter->pool.erp_req); | 1482 | qdio->adapter->pool.erp_req); |
1515 | 1483 | ||
1516 | if (IS_ERR(req)) { | 1484 | if (IS_ERR(req)) { |
@@ -1534,7 +1502,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) | |||
1534 | erp_action->fsf_req_id = 0; | 1502 | erp_action->fsf_req_id = 0; |
1535 | } | 1503 | } |
1536 | out: | 1504 | out: |
1537 | spin_unlock_bh(&qdio->req_q_lock); | 1505 | spin_unlock_irq(&qdio->req_q_lock); |
1538 | return retval; | 1506 | return retval; |
1539 | } | 1507 | } |
1540 | 1508 | ||
@@ -1580,15 +1548,15 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port) | |||
1580 | struct zfcp_fsf_req *req; | 1548 | struct zfcp_fsf_req *req; |
1581 | int retval = -EIO; | 1549 | int retval = -EIO; |
1582 | 1550 | ||
1583 | spin_lock_bh(&qdio->req_q_lock); | 1551 | spin_lock_irq(&qdio->req_q_lock); |
1584 | if (zfcp_qdio_sbal_get(qdio)) | 1552 | if (zfcp_qdio_sbal_get(qdio)) |
1585 | goto out; | 1553 | goto out; |
1586 | 1554 | ||
1587 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID, | 1555 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID, |
1588 | SBAL_FLAGS0_TYPE_READ, | 1556 | SBAL_SFLAGS0_TYPE_READ, |
1589 | qdio->adapter->pool.erp_req); | 1557 | qdio->adapter->pool.erp_req); |
1590 | 1558 | ||
1591 | if (unlikely(IS_ERR(req))) { | 1559 | if (IS_ERR(req)) { |
1592 | retval = PTR_ERR(req); | 1560 | retval = PTR_ERR(req); |
1593 | goto out; | 1561 | goto out; |
1594 | } | 1562 | } |
@@ -1605,7 +1573,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port) | |||
1605 | if (retval) | 1573 | if (retval) |
1606 | zfcp_fsf_req_free(req); | 1574 | zfcp_fsf_req_free(req); |
1607 | out: | 1575 | out: |
1608 | spin_unlock_bh(&qdio->req_q_lock); | 1576 | spin_unlock_irq(&qdio->req_q_lock); |
1609 | return retval; | 1577 | return retval; |
1610 | } | 1578 | } |
1611 | 1579 | ||
@@ -1615,7 +1583,7 @@ static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req) | |||
1615 | 1583 | ||
1616 | if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) { | 1584 | if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) { |
1617 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1585 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1618 | zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1", req); | 1586 | zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1"); |
1619 | } | 1587 | } |
1620 | 1588 | ||
1621 | wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; | 1589 | wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; |
@@ -1633,15 +1601,15 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port) | |||
1633 | struct zfcp_fsf_req *req; | 1601 | struct zfcp_fsf_req *req; |
1634 | int retval = -EIO; | 1602 | int retval = -EIO; |
1635 | 1603 | ||
1636 | spin_lock_bh(&qdio->req_q_lock); | 1604 | spin_lock_irq(&qdio->req_q_lock); |
1637 | if (zfcp_qdio_sbal_get(qdio)) | 1605 | if (zfcp_qdio_sbal_get(qdio)) |
1638 | goto out; | 1606 | goto out; |
1639 | 1607 | ||
1640 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT, | 1608 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT, |
1641 | SBAL_FLAGS0_TYPE_READ, | 1609 | SBAL_SFLAGS0_TYPE_READ, |
1642 | qdio->adapter->pool.erp_req); | 1610 | qdio->adapter->pool.erp_req); |
1643 | 1611 | ||
1644 | if (unlikely(IS_ERR(req))) { | 1612 | if (IS_ERR(req)) { |
1645 | retval = PTR_ERR(req); | 1613 | retval = PTR_ERR(req); |
1646 | goto out; | 1614 | goto out; |
1647 | } | 1615 | } |
@@ -1658,7 +1626,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port) | |||
1658 | if (retval) | 1626 | if (retval) |
1659 | zfcp_fsf_req_free(req); | 1627 | zfcp_fsf_req_free(req); |
1660 | out: | 1628 | out: |
1661 | spin_unlock_bh(&qdio->req_q_lock); | 1629 | spin_unlock_irq(&qdio->req_q_lock); |
1662 | return retval; | 1630 | return retval; |
1663 | } | 1631 | } |
1664 | 1632 | ||
@@ -1666,29 +1634,30 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) | |||
1666 | { | 1634 | { |
1667 | struct zfcp_port *port = req->data; | 1635 | struct zfcp_port *port = req->data; |
1668 | struct fsf_qtcb_header *header = &req->qtcb->header; | 1636 | struct fsf_qtcb_header *header = &req->qtcb->header; |
1669 | struct zfcp_unit *unit; | 1637 | struct scsi_device *sdev; |
1670 | 1638 | ||
1671 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) | 1639 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
1672 | return; | 1640 | return; |
1673 | 1641 | ||
1674 | switch (header->fsf_status) { | 1642 | switch (header->fsf_status) { |
1675 | case FSF_PORT_HANDLE_NOT_VALID: | 1643 | case FSF_PORT_HANDLE_NOT_VALID: |
1676 | zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1", req); | 1644 | zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1"); |
1677 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1645 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1678 | break; | 1646 | break; |
1679 | case FSF_ACCESS_DENIED: | 1647 | case FSF_ACCESS_DENIED: |
1680 | zfcp_fsf_access_denied_port(req, port); | 1648 | zfcp_cfdc_port_denied(port, &header->fsf_status_qual); |
1681 | break; | 1649 | break; |
1682 | case FSF_PORT_BOXED: | 1650 | case FSF_PORT_BOXED: |
1683 | /* can't use generic zfcp_erp_modify_port_status because | 1651 | /* can't use generic zfcp_erp_modify_port_status because |
1684 | * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */ | 1652 | * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */ |
1685 | atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); | 1653 | atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); |
1686 | read_lock(&port->unit_list_lock); | 1654 | shost_for_each_device(sdev, port->adapter->scsi_host) |
1687 | list_for_each_entry(unit, &port->unit_list, list) | 1655 | if (sdev_to_zfcp(sdev)->port == port) |
1688 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, | 1656 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, |
1689 | &unit->status); | 1657 | &sdev_to_zfcp(sdev)->status); |
1690 | read_unlock(&port->unit_list_lock); | 1658 | zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ACCESS_BOXED); |
1691 | zfcp_erp_port_boxed(port, "fscpph2", req); | 1659 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, |
1660 | "fscpph2"); | ||
1692 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1661 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1693 | break; | 1662 | break; |
1694 | case FSF_ADAPTER_STATUS_AVAILABLE: | 1663 | case FSF_ADAPTER_STATUS_AVAILABLE: |
@@ -1705,11 +1674,10 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) | |||
1705 | * ZFCP_STATUS_COMMON_OPEN must not be reset for the port | 1674 | * ZFCP_STATUS_COMMON_OPEN must not be reset for the port |
1706 | */ | 1675 | */ |
1707 | atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); | 1676 | atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); |
1708 | read_lock(&port->unit_list_lock); | 1677 | shost_for_each_device(sdev, port->adapter->scsi_host) |
1709 | list_for_each_entry(unit, &port->unit_list, list) | 1678 | if (sdev_to_zfcp(sdev)->port == port) |
1710 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, | 1679 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, |
1711 | &unit->status); | 1680 | &sdev_to_zfcp(sdev)->status); |
1712 | read_unlock(&port->unit_list_lock); | ||
1713 | break; | 1681 | break; |
1714 | } | 1682 | } |
1715 | } | 1683 | } |
@@ -1725,12 +1693,12 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) | |||
1725 | struct zfcp_fsf_req *req; | 1693 | struct zfcp_fsf_req *req; |
1726 | int retval = -EIO; | 1694 | int retval = -EIO; |
1727 | 1695 | ||
1728 | spin_lock_bh(&qdio->req_q_lock); | 1696 | spin_lock_irq(&qdio->req_q_lock); |
1729 | if (zfcp_qdio_sbal_get(qdio)) | 1697 | if (zfcp_qdio_sbal_get(qdio)) |
1730 | goto out; | 1698 | goto out; |
1731 | 1699 | ||
1732 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT, | 1700 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT, |
1733 | SBAL_FLAGS0_TYPE_READ, | 1701 | SBAL_SFLAGS0_TYPE_READ, |
1734 | qdio->adapter->pool.erp_req); | 1702 | qdio->adapter->pool.erp_req); |
1735 | 1703 | ||
1736 | if (IS_ERR(req)) { | 1704 | if (IS_ERR(req)) { |
@@ -1754,69 +1722,56 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) | |||
1754 | erp_action->fsf_req_id = 0; | 1722 | erp_action->fsf_req_id = 0; |
1755 | } | 1723 | } |
1756 | out: | 1724 | out: |
1757 | spin_unlock_bh(&qdio->req_q_lock); | 1725 | spin_unlock_irq(&qdio->req_q_lock); |
1758 | return retval; | 1726 | return retval; |
1759 | } | 1727 | } |
1760 | 1728 | ||
1761 | static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) | 1729 | static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req) |
1762 | { | 1730 | { |
1763 | struct zfcp_adapter *adapter = req->adapter; | 1731 | struct zfcp_adapter *adapter = req->adapter; |
1764 | struct zfcp_unit *unit = req->data; | 1732 | struct scsi_device *sdev = req->data; |
1733 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
1765 | struct fsf_qtcb_header *header = &req->qtcb->header; | 1734 | struct fsf_qtcb_header *header = &req->qtcb->header; |
1766 | struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support; | 1735 | struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support; |
1767 | struct fsf_queue_designator *queue_designator = | ||
1768 | &header->fsf_status_qual.fsf_queue_designator; | ||
1769 | int exclusive, readwrite; | ||
1770 | 1736 | ||
1771 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) | 1737 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
1772 | return; | 1738 | return; |
1773 | 1739 | ||
1774 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | | 1740 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | |
1775 | ZFCP_STATUS_COMMON_ACCESS_BOXED | | 1741 | ZFCP_STATUS_COMMON_ACCESS_BOXED | |
1776 | ZFCP_STATUS_UNIT_SHARED | | 1742 | ZFCP_STATUS_LUN_SHARED | |
1777 | ZFCP_STATUS_UNIT_READONLY, | 1743 | ZFCP_STATUS_LUN_READONLY, |
1778 | &unit->status); | 1744 | &zfcp_sdev->status); |
1779 | 1745 | ||
1780 | switch (header->fsf_status) { | 1746 | switch (header->fsf_status) { |
1781 | 1747 | ||
1782 | case FSF_PORT_HANDLE_NOT_VALID: | 1748 | case FSF_PORT_HANDLE_NOT_VALID: |
1783 | zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fsouh_1", req); | 1749 | zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1"); |
1784 | /* fall through */ | 1750 | /* fall through */ |
1785 | case FSF_LUN_ALREADY_OPEN: | 1751 | case FSF_LUN_ALREADY_OPEN: |
1786 | break; | 1752 | break; |
1787 | case FSF_ACCESS_DENIED: | 1753 | case FSF_ACCESS_DENIED: |
1788 | zfcp_fsf_access_denied_unit(req, unit); | 1754 | zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual); |
1789 | atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status); | 1755 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1790 | atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); | ||
1791 | break; | 1756 | break; |
1792 | case FSF_PORT_BOXED: | 1757 | case FSF_PORT_BOXED: |
1793 | zfcp_erp_port_boxed(unit->port, "fsouh_2", req); | 1758 | zfcp_erp_set_port_status(zfcp_sdev->port, |
1759 | ZFCP_STATUS_COMMON_ACCESS_BOXED); | ||
1760 | zfcp_erp_port_reopen(zfcp_sdev->port, | ||
1761 | ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2"); | ||
1794 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1762 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1795 | break; | 1763 | break; |
1796 | case FSF_LUN_SHARING_VIOLATION: | 1764 | case FSF_LUN_SHARING_VIOLATION: |
1797 | if (header->fsf_status_qual.word[0]) | 1765 | zfcp_cfdc_lun_shrng_vltn(sdev, &header->fsf_status_qual); |
1798 | dev_warn(&adapter->ccw_device->dev, | ||
1799 | "LUN 0x%Lx on port 0x%Lx is already in " | ||
1800 | "use by CSS%d, MIF Image ID %x\n", | ||
1801 | (unsigned long long)unit->fcp_lun, | ||
1802 | (unsigned long long)unit->port->wwpn, | ||
1803 | queue_designator->cssid, | ||
1804 | queue_designator->hla); | ||
1805 | else | ||
1806 | zfcp_act_eval_err(adapter, | ||
1807 | header->fsf_status_qual.word[2]); | ||
1808 | zfcp_erp_unit_access_denied(unit, "fsouh_3", req); | ||
1809 | atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status); | ||
1810 | atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); | ||
1811 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1766 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1812 | break; | 1767 | break; |
1813 | case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED: | 1768 | case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED: |
1814 | dev_warn(&adapter->ccw_device->dev, | 1769 | dev_warn(&adapter->ccw_device->dev, |
1815 | "No handle is available for LUN " | 1770 | "No handle is available for LUN " |
1816 | "0x%016Lx on port 0x%016Lx\n", | 1771 | "0x%016Lx on port 0x%016Lx\n", |
1817 | (unsigned long long)unit->fcp_lun, | 1772 | (unsigned long long)zfcp_scsi_dev_lun(sdev), |
1818 | (unsigned long long)unit->port->wwpn); | 1773 | (unsigned long long)zfcp_sdev->port->wwpn); |
1819 | zfcp_erp_unit_failed(unit, "fsouh_4", req); | 1774 | zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED); |
1820 | /* fall through */ | 1775 | /* fall through */ |
1821 | case FSF_INVALID_COMMAND_OPTION: | 1776 | case FSF_INVALID_COMMAND_OPTION: |
1822 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1777 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
@@ -1824,7 +1779,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) | |||
1824 | case FSF_ADAPTER_STATUS_AVAILABLE: | 1779 | case FSF_ADAPTER_STATUS_AVAILABLE: |
1825 | switch (header->fsf_status_qual.word[0]) { | 1780 | switch (header->fsf_status_qual.word[0]) { |
1826 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: | 1781 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
1827 | zfcp_fc_test_link(unit->port); | 1782 | zfcp_fc_test_link(zfcp_sdev->port); |
1828 | /* fall through */ | 1783 | /* fall through */ |
1829 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: | 1784 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: |
1830 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1785 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
@@ -1833,75 +1788,31 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) | |||
1833 | break; | 1788 | break; |
1834 | 1789 | ||
1835 | case FSF_GOOD: | 1790 | case FSF_GOOD: |
1836 | unit->handle = header->lun_handle; | 1791 | zfcp_sdev->lun_handle = header->lun_handle; |
1837 | atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); | 1792 | atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status); |
1838 | 1793 | zfcp_cfdc_open_lun_eval(sdev, bottom); | |
1839 | if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) && | ||
1840 | (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) && | ||
1841 | !zfcp_ccw_priv_sch(adapter)) { | ||
1842 | exclusive = (bottom->lun_access_info & | ||
1843 | FSF_UNIT_ACCESS_EXCLUSIVE); | ||
1844 | readwrite = (bottom->lun_access_info & | ||
1845 | FSF_UNIT_ACCESS_OUTBOUND_TRANSFER); | ||
1846 | |||
1847 | if (!exclusive) | ||
1848 | atomic_set_mask(ZFCP_STATUS_UNIT_SHARED, | ||
1849 | &unit->status); | ||
1850 | |||
1851 | if (!readwrite) { | ||
1852 | atomic_set_mask(ZFCP_STATUS_UNIT_READONLY, | ||
1853 | &unit->status); | ||
1854 | dev_info(&adapter->ccw_device->dev, | ||
1855 | "SCSI device at LUN 0x%016Lx on port " | ||
1856 | "0x%016Lx opened read-only\n", | ||
1857 | (unsigned long long)unit->fcp_lun, | ||
1858 | (unsigned long long)unit->port->wwpn); | ||
1859 | } | ||
1860 | |||
1861 | if (exclusive && !readwrite) { | ||
1862 | dev_err(&adapter->ccw_device->dev, | ||
1863 | "Exclusive read-only access not " | ||
1864 | "supported (unit 0x%016Lx, " | ||
1865 | "port 0x%016Lx)\n", | ||
1866 | (unsigned long long)unit->fcp_lun, | ||
1867 | (unsigned long long)unit->port->wwpn); | ||
1868 | zfcp_erp_unit_failed(unit, "fsouh_5", req); | ||
1869 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
1870 | zfcp_erp_unit_shutdown(unit, 0, "fsouh_6", req); | ||
1871 | } else if (!exclusive && readwrite) { | ||
1872 | dev_err(&adapter->ccw_device->dev, | ||
1873 | "Shared read-write access not " | ||
1874 | "supported (unit 0x%016Lx, port " | ||
1875 | "0x%016Lx)\n", | ||
1876 | (unsigned long long)unit->fcp_lun, | ||
1877 | (unsigned long long)unit->port->wwpn); | ||
1878 | zfcp_erp_unit_failed(unit, "fsouh_7", req); | ||
1879 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
1880 | zfcp_erp_unit_shutdown(unit, 0, "fsouh_8", req); | ||
1881 | } | ||
1882 | } | ||
1883 | break; | 1794 | break; |
1884 | } | 1795 | } |
1885 | } | 1796 | } |
1886 | 1797 | ||
1887 | /** | 1798 | /** |
1888 | * zfcp_fsf_open_unit - open unit | 1799 | * zfcp_fsf_open_lun - open LUN |
1889 | * @erp_action: pointer to struct zfcp_erp_action | 1800 | * @erp_action: pointer to struct zfcp_erp_action |
1890 | * Returns: 0 on success, error otherwise | 1801 | * Returns: 0 on success, error otherwise |
1891 | */ | 1802 | */ |
1892 | int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | 1803 | int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action) |
1893 | { | 1804 | { |
1894 | struct zfcp_adapter *adapter = erp_action->adapter; | 1805 | struct zfcp_adapter *adapter = erp_action->adapter; |
1895 | struct zfcp_qdio *qdio = adapter->qdio; | 1806 | struct zfcp_qdio *qdio = adapter->qdio; |
1896 | struct zfcp_fsf_req *req; | 1807 | struct zfcp_fsf_req *req; |
1897 | int retval = -EIO; | 1808 | int retval = -EIO; |
1898 | 1809 | ||
1899 | spin_lock_bh(&qdio->req_q_lock); | 1810 | spin_lock_irq(&qdio->req_q_lock); |
1900 | if (zfcp_qdio_sbal_get(qdio)) | 1811 | if (zfcp_qdio_sbal_get(qdio)) |
1901 | goto out; | 1812 | goto out; |
1902 | 1813 | ||
1903 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN, | 1814 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN, |
1904 | SBAL_FLAGS0_TYPE_READ, | 1815 | SBAL_SFLAGS0_TYPE_READ, |
1905 | adapter->pool.erp_req); | 1816 | adapter->pool.erp_req); |
1906 | 1817 | ||
1907 | if (IS_ERR(req)) { | 1818 | if (IS_ERR(req)) { |
@@ -1913,9 +1824,9 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | |||
1913 | zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); | 1824 | zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); |
1914 | 1825 | ||
1915 | req->qtcb->header.port_handle = erp_action->port->handle; | 1826 | req->qtcb->header.port_handle = erp_action->port->handle; |
1916 | req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun; | 1827 | req->qtcb->bottom.support.fcp_lun = zfcp_scsi_dev_lun(erp_action->sdev); |
1917 | req->handler = zfcp_fsf_open_unit_handler; | 1828 | req->handler = zfcp_fsf_open_lun_handler; |
1918 | req->data = erp_action->unit; | 1829 | req->data = erp_action->sdev; |
1919 | req->erp_action = erp_action; | 1830 | req->erp_action = erp_action; |
1920 | erp_action->fsf_req_id = req->req_id; | 1831 | erp_action->fsf_req_id = req->req_id; |
1921 | 1832 | ||
@@ -1929,34 +1840,38 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | |||
1929 | erp_action->fsf_req_id = 0; | 1840 | erp_action->fsf_req_id = 0; |
1930 | } | 1841 | } |
1931 | out: | 1842 | out: |
1932 | spin_unlock_bh(&qdio->req_q_lock); | 1843 | spin_unlock_irq(&qdio->req_q_lock); |
1933 | return retval; | 1844 | return retval; |
1934 | } | 1845 | } |
1935 | 1846 | ||
1936 | static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req) | 1847 | static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req) |
1937 | { | 1848 | { |
1938 | struct zfcp_unit *unit = req->data; | 1849 | struct scsi_device *sdev = req->data; |
1850 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
1939 | 1851 | ||
1940 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) | 1852 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
1941 | return; | 1853 | return; |
1942 | 1854 | ||
1943 | switch (req->qtcb->header.fsf_status) { | 1855 | switch (req->qtcb->header.fsf_status) { |
1944 | case FSF_PORT_HANDLE_NOT_VALID: | 1856 | case FSF_PORT_HANDLE_NOT_VALID: |
1945 | zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fscuh_1", req); | 1857 | zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1"); |
1946 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1858 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1947 | break; | 1859 | break; |
1948 | case FSF_LUN_HANDLE_NOT_VALID: | 1860 | case FSF_LUN_HANDLE_NOT_VALID: |
1949 | zfcp_erp_port_reopen(unit->port, 0, "fscuh_2", req); | 1861 | zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2"); |
1950 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1862 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1951 | break; | 1863 | break; |
1952 | case FSF_PORT_BOXED: | 1864 | case FSF_PORT_BOXED: |
1953 | zfcp_erp_port_boxed(unit->port, "fscuh_3", req); | 1865 | zfcp_erp_set_port_status(zfcp_sdev->port, |
1866 | ZFCP_STATUS_COMMON_ACCESS_BOXED); | ||
1867 | zfcp_erp_port_reopen(zfcp_sdev->port, | ||
1868 | ZFCP_STATUS_COMMON_ERP_FAILED, "fscuh_3"); | ||
1954 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1869 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1955 | break; | 1870 | break; |
1956 | case FSF_ADAPTER_STATUS_AVAILABLE: | 1871 | case FSF_ADAPTER_STATUS_AVAILABLE: |
1957 | switch (req->qtcb->header.fsf_status_qual.word[0]) { | 1872 | switch (req->qtcb->header.fsf_status_qual.word[0]) { |
1958 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: | 1873 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
1959 | zfcp_fc_test_link(unit->port); | 1874 | zfcp_fc_test_link(zfcp_sdev->port); |
1960 | /* fall through */ | 1875 | /* fall through */ |
1961 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: | 1876 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: |
1962 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1877 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
@@ -1964,28 +1879,29 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req) | |||
1964 | } | 1879 | } |
1965 | break; | 1880 | break; |
1966 | case FSF_GOOD: | 1881 | case FSF_GOOD: |
1967 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); | 1882 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status); |
1968 | break; | 1883 | break; |
1969 | } | 1884 | } |
1970 | } | 1885 | } |
1971 | 1886 | ||
1972 | /** | 1887 | /** |
1973 | * zfcp_fsf_close_unit - close zfcp unit | 1888 | * zfcp_fsf_close_LUN - close LUN |
1974 | * @erp_action: pointer to struct zfcp_unit | 1889 | * @erp_action: pointer to erp_action triggering the "close LUN" |
1975 | * Returns: 0 on success, error otherwise | 1890 | * Returns: 0 on success, error otherwise |
1976 | */ | 1891 | */ |
1977 | int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) | 1892 | int zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action) |
1978 | { | 1893 | { |
1979 | struct zfcp_qdio *qdio = erp_action->adapter->qdio; | 1894 | struct zfcp_qdio *qdio = erp_action->adapter->qdio; |
1895 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(erp_action->sdev); | ||
1980 | struct zfcp_fsf_req *req; | 1896 | struct zfcp_fsf_req *req; |
1981 | int retval = -EIO; | 1897 | int retval = -EIO; |
1982 | 1898 | ||
1983 | spin_lock_bh(&qdio->req_q_lock); | 1899 | spin_lock_irq(&qdio->req_q_lock); |
1984 | if (zfcp_qdio_sbal_get(qdio)) | 1900 | if (zfcp_qdio_sbal_get(qdio)) |
1985 | goto out; | 1901 | goto out; |
1986 | 1902 | ||
1987 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN, | 1903 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN, |
1988 | SBAL_FLAGS0_TYPE_READ, | 1904 | SBAL_SFLAGS0_TYPE_READ, |
1989 | qdio->adapter->pool.erp_req); | 1905 | qdio->adapter->pool.erp_req); |
1990 | 1906 | ||
1991 | if (IS_ERR(req)) { | 1907 | if (IS_ERR(req)) { |
@@ -1997,9 +1913,9 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) | |||
1997 | zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); | 1913 | zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); |
1998 | 1914 | ||
1999 | req->qtcb->header.port_handle = erp_action->port->handle; | 1915 | req->qtcb->header.port_handle = erp_action->port->handle; |
2000 | req->qtcb->header.lun_handle = erp_action->unit->handle; | 1916 | req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; |
2001 | req->handler = zfcp_fsf_close_unit_handler; | 1917 | req->handler = zfcp_fsf_close_lun_handler; |
2002 | req->data = erp_action->unit; | 1918 | req->data = erp_action->sdev; |
2003 | req->erp_action = erp_action; | 1919 | req->erp_action = erp_action; |
2004 | erp_action->fsf_req_id = req->req_id; | 1920 | erp_action->fsf_req_id = req->req_id; |
2005 | 1921 | ||
@@ -2010,7 +1926,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) | |||
2010 | erp_action->fsf_req_id = 0; | 1926 | erp_action->fsf_req_id = 0; |
2011 | } | 1927 | } |
2012 | out: | 1928 | out: |
2013 | spin_unlock_bh(&qdio->req_q_lock); | 1929 | spin_unlock_irq(&qdio->req_q_lock); |
2014 | return retval; | 1930 | return retval; |
2015 | } | 1931 | } |
2016 | 1932 | ||
@@ -2025,7 +1941,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) | |||
2025 | { | 1941 | { |
2026 | struct fsf_qual_latency_info *lat_in; | 1942 | struct fsf_qual_latency_info *lat_in; |
2027 | struct latency_cont *lat = NULL; | 1943 | struct latency_cont *lat = NULL; |
2028 | struct zfcp_unit *unit = req->unit; | 1944 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device); |
2029 | struct zfcp_blk_drv_data blktrc; | 1945 | struct zfcp_blk_drv_data blktrc; |
2030 | int ticks = req->adapter->timer_ticks; | 1946 | int ticks = req->adapter->timer_ticks; |
2031 | 1947 | ||
@@ -2048,24 +1964,24 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) | |||
2048 | case FSF_DATADIR_DIF_READ_STRIP: | 1964 | case FSF_DATADIR_DIF_READ_STRIP: |
2049 | case FSF_DATADIR_DIF_READ_CONVERT: | 1965 | case FSF_DATADIR_DIF_READ_CONVERT: |
2050 | case FSF_DATADIR_READ: | 1966 | case FSF_DATADIR_READ: |
2051 | lat = &unit->latencies.read; | 1967 | lat = &zfcp_sdev->latencies.read; |
2052 | break; | 1968 | break; |
2053 | case FSF_DATADIR_DIF_WRITE_INSERT: | 1969 | case FSF_DATADIR_DIF_WRITE_INSERT: |
2054 | case FSF_DATADIR_DIF_WRITE_CONVERT: | 1970 | case FSF_DATADIR_DIF_WRITE_CONVERT: |
2055 | case FSF_DATADIR_WRITE: | 1971 | case FSF_DATADIR_WRITE: |
2056 | lat = &unit->latencies.write; | 1972 | lat = &zfcp_sdev->latencies.write; |
2057 | break; | 1973 | break; |
2058 | case FSF_DATADIR_CMND: | 1974 | case FSF_DATADIR_CMND: |
2059 | lat = &unit->latencies.cmd; | 1975 | lat = &zfcp_sdev->latencies.cmd; |
2060 | break; | 1976 | break; |
2061 | } | 1977 | } |
2062 | 1978 | ||
2063 | if (lat) { | 1979 | if (lat) { |
2064 | spin_lock(&unit->latencies.lock); | 1980 | spin_lock(&zfcp_sdev->latencies.lock); |
2065 | zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat); | 1981 | zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat); |
2066 | zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat); | 1982 | zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat); |
2067 | lat->counter++; | 1983 | lat->counter++; |
2068 | spin_unlock(&unit->latencies.lock); | 1984 | spin_unlock(&zfcp_sdev->latencies.lock); |
2069 | } | 1985 | } |
2070 | } | 1986 | } |
2071 | 1987 | ||
@@ -2073,7 +1989,79 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) | |||
2073 | sizeof(blktrc)); | 1989 | sizeof(blktrc)); |
2074 | } | 1990 | } |
2075 | 1991 | ||
2076 | static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req) | 1992 | static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) |
1993 | { | ||
1994 | struct scsi_cmnd *scmnd = req->data; | ||
1995 | struct scsi_device *sdev = scmnd->device; | ||
1996 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
1997 | struct fsf_qtcb_header *header = &req->qtcb->header; | ||
1998 | |||
1999 | if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) | ||
2000 | return; | ||
2001 | |||
2002 | switch (header->fsf_status) { | ||
2003 | case FSF_HANDLE_MISMATCH: | ||
2004 | case FSF_PORT_HANDLE_NOT_VALID: | ||
2005 | zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1"); | ||
2006 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2007 | break; | ||
2008 | case FSF_FCPLUN_NOT_VALID: | ||
2009 | case FSF_LUN_HANDLE_NOT_VALID: | ||
2010 | zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2"); | ||
2011 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2012 | break; | ||
2013 | case FSF_SERVICE_CLASS_NOT_SUPPORTED: | ||
2014 | zfcp_fsf_class_not_supp(req); | ||
2015 | break; | ||
2016 | case FSF_ACCESS_DENIED: | ||
2017 | zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual); | ||
2018 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2019 | break; | ||
2020 | case FSF_DIRECTION_INDICATOR_NOT_VALID: | ||
2021 | dev_err(&req->adapter->ccw_device->dev, | ||
2022 | "Incorrect direction %d, LUN 0x%016Lx on port " | ||
2023 | "0x%016Lx closed\n", | ||
2024 | req->qtcb->bottom.io.data_direction, | ||
2025 | (unsigned long long)zfcp_scsi_dev_lun(sdev), | ||
2026 | (unsigned long long)zfcp_sdev->port->wwpn); | ||
2027 | zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0, | ||
2028 | "fssfch3"); | ||
2029 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2030 | break; | ||
2031 | case FSF_CMND_LENGTH_NOT_VALID: | ||
2032 | dev_err(&req->adapter->ccw_device->dev, | ||
2033 | "Incorrect CDB length %d, LUN 0x%016Lx on " | ||
2034 | "port 0x%016Lx closed\n", | ||
2035 | req->qtcb->bottom.io.fcp_cmnd_length, | ||
2036 | (unsigned long long)zfcp_scsi_dev_lun(sdev), | ||
2037 | (unsigned long long)zfcp_sdev->port->wwpn); | ||
2038 | zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0, | ||
2039 | "fssfch4"); | ||
2040 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2041 | break; | ||
2042 | case FSF_PORT_BOXED: | ||
2043 | zfcp_erp_set_port_status(zfcp_sdev->port, | ||
2044 | ZFCP_STATUS_COMMON_ACCESS_BOXED); | ||
2045 | zfcp_erp_port_reopen(zfcp_sdev->port, | ||
2046 | ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5"); | ||
2047 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2048 | break; | ||
2049 | case FSF_LUN_BOXED: | ||
2050 | zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED); | ||
2051 | zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED, | ||
2052 | "fssfch6"); | ||
2053 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2054 | break; | ||
2055 | case FSF_ADAPTER_STATUS_AVAILABLE: | ||
2056 | if (header->fsf_status_qual.word[0] == | ||
2057 | FSF_SQ_INVOKE_LINK_TEST_PROCEDURE) | ||
2058 | zfcp_fc_test_link(zfcp_sdev->port); | ||
2059 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2060 | break; | ||
2061 | } | ||
2062 | } | ||
2063 | |||
2064 | static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req) | ||
2077 | { | 2065 | { |
2078 | struct scsi_cmnd *scpnt; | 2066 | struct scsi_cmnd *scpnt; |
2079 | struct fcp_resp_with_ext *fcp_rsp; | 2067 | struct fcp_resp_with_ext *fcp_rsp; |
@@ -2087,6 +2075,8 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req) | |||
2087 | return; | 2075 | return; |
2088 | } | 2076 | } |
2089 | 2077 | ||
2078 | zfcp_fsf_fcp_handler_common(req); | ||
2079 | |||
2090 | if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { | 2080 | if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { |
2091 | set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED); | 2081 | set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED); |
2092 | goto skip_fsfstatus; | 2082 | goto skip_fsfstatus; |
@@ -2112,7 +2102,7 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req) | |||
2112 | 2102 | ||
2113 | skip_fsfstatus: | 2103 | skip_fsfstatus: |
2114 | zfcp_fsf_req_trace(req, scpnt); | 2104 | zfcp_fsf_req_trace(req, scpnt); |
2115 | zfcp_dbf_scsi_result(req->adapter->dbf, scpnt, req); | 2105 | zfcp_dbf_scsi_result(scpnt, req); |
2116 | 2106 | ||
2117 | scpnt->host_scribble = NULL; | 2107 | scpnt->host_scribble = NULL; |
2118 | (scpnt->scsi_done) (scpnt); | 2108 | (scpnt->scsi_done) (scpnt); |
@@ -2125,97 +2115,6 @@ skip_fsfstatus: | |||
2125 | read_unlock_irqrestore(&req->adapter->abort_lock, flags); | 2115 | read_unlock_irqrestore(&req->adapter->abort_lock, flags); |
2126 | } | 2116 | } |
2127 | 2117 | ||
2128 | static void zfcp_fsf_send_fcp_ctm_handler(struct zfcp_fsf_req *req) | ||
2129 | { | ||
2130 | struct fcp_resp_with_ext *fcp_rsp; | ||
2131 | struct fcp_resp_rsp_info *rsp_info; | ||
2132 | |||
2133 | fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp; | ||
2134 | rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1]; | ||
2135 | |||
2136 | if ((rsp_info->rsp_code != FCP_TMF_CMPL) || | ||
2137 | (req->status & ZFCP_STATUS_FSFREQ_ERROR)) | ||
2138 | req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; | ||
2139 | } | ||
2140 | |||
2141 | |||
2142 | static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req) | ||
2143 | { | ||
2144 | struct zfcp_unit *unit; | ||
2145 | struct fsf_qtcb_header *header = &req->qtcb->header; | ||
2146 | |||
2147 | if (unlikely(req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)) | ||
2148 | unit = req->data; | ||
2149 | else | ||
2150 | unit = req->unit; | ||
2151 | |||
2152 | if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) | ||
2153 | goto skip_fsfstatus; | ||
2154 | |||
2155 | switch (header->fsf_status) { | ||
2156 | case FSF_HANDLE_MISMATCH: | ||
2157 | case FSF_PORT_HANDLE_NOT_VALID: | ||
2158 | zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fssfch1", req); | ||
2159 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2160 | break; | ||
2161 | case FSF_FCPLUN_NOT_VALID: | ||
2162 | case FSF_LUN_HANDLE_NOT_VALID: | ||
2163 | zfcp_erp_port_reopen(unit->port, 0, "fssfch2", req); | ||
2164 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2165 | break; | ||
2166 | case FSF_SERVICE_CLASS_NOT_SUPPORTED: | ||
2167 | zfcp_fsf_class_not_supp(req); | ||
2168 | break; | ||
2169 | case FSF_ACCESS_DENIED: | ||
2170 | zfcp_fsf_access_denied_unit(req, unit); | ||
2171 | break; | ||
2172 | case FSF_DIRECTION_INDICATOR_NOT_VALID: | ||
2173 | dev_err(&req->adapter->ccw_device->dev, | ||
2174 | "Incorrect direction %d, unit 0x%016Lx on port " | ||
2175 | "0x%016Lx closed\n", | ||
2176 | req->qtcb->bottom.io.data_direction, | ||
2177 | (unsigned long long)unit->fcp_lun, | ||
2178 | (unsigned long long)unit->port->wwpn); | ||
2179 | zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch3", | ||
2180 | req); | ||
2181 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2182 | break; | ||
2183 | case FSF_CMND_LENGTH_NOT_VALID: | ||
2184 | dev_err(&req->adapter->ccw_device->dev, | ||
2185 | "Incorrect CDB length %d, unit 0x%016Lx on " | ||
2186 | "port 0x%016Lx closed\n", | ||
2187 | req->qtcb->bottom.io.fcp_cmnd_length, | ||
2188 | (unsigned long long)unit->fcp_lun, | ||
2189 | (unsigned long long)unit->port->wwpn); | ||
2190 | zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch4", | ||
2191 | req); | ||
2192 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2193 | break; | ||
2194 | case FSF_PORT_BOXED: | ||
2195 | zfcp_erp_port_boxed(unit->port, "fssfch5", req); | ||
2196 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2197 | break; | ||
2198 | case FSF_LUN_BOXED: | ||
2199 | zfcp_erp_unit_boxed(unit, "fssfch6", req); | ||
2200 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2201 | break; | ||
2202 | case FSF_ADAPTER_STATUS_AVAILABLE: | ||
2203 | if (header->fsf_status_qual.word[0] == | ||
2204 | FSF_SQ_INVOKE_LINK_TEST_PROCEDURE) | ||
2205 | zfcp_fc_test_link(unit->port); | ||
2206 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
2207 | break; | ||
2208 | } | ||
2209 | skip_fsfstatus: | ||
2210 | if (req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) | ||
2211 | zfcp_fsf_send_fcp_ctm_handler(req); | ||
2212 | else { | ||
2213 | zfcp_fsf_send_fcp_command_task_handler(req); | ||
2214 | req->unit = NULL; | ||
2215 | put_device(&unit->dev); | ||
2216 | } | ||
2217 | } | ||
2218 | |||
2219 | static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir) | 2118 | static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir) |
2220 | { | 2119 | { |
2221 | switch (scsi_get_prot_op(scsi_cmnd)) { | 2120 | switch (scsi_get_prot_op(scsi_cmnd)) { |
@@ -2255,33 +2154,34 @@ static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir) | |||
2255 | } | 2154 | } |
2256 | 2155 | ||
2257 | /** | 2156 | /** |
2258 | * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command) | 2157 | * zfcp_fsf_fcp_cmnd - initiate an FCP command (for a SCSI command) |
2259 | * @unit: unit where command is sent to | ||
2260 | * @scsi_cmnd: scsi command to be sent | 2158 | * @scsi_cmnd: scsi command to be sent |
2261 | */ | 2159 | */ |
2262 | int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, | 2160 | int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd) |
2263 | struct scsi_cmnd *scsi_cmnd) | ||
2264 | { | 2161 | { |
2265 | struct zfcp_fsf_req *req; | 2162 | struct zfcp_fsf_req *req; |
2266 | struct fcp_cmnd *fcp_cmnd; | 2163 | struct fcp_cmnd *fcp_cmnd; |
2267 | unsigned int sbtype = SBAL_FLAGS0_TYPE_READ; | 2164 | u8 sbtype = SBAL_SFLAGS0_TYPE_READ; |
2268 | int real_bytes, retval = -EIO, dix_bytes = 0; | 2165 | int real_bytes, retval = -EIO, dix_bytes = 0; |
2269 | struct zfcp_adapter *adapter = unit->port->adapter; | 2166 | struct scsi_device *sdev = scsi_cmnd->device; |
2167 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
2168 | struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; | ||
2270 | struct zfcp_qdio *qdio = adapter->qdio; | 2169 | struct zfcp_qdio *qdio = adapter->qdio; |
2271 | struct fsf_qtcb_bottom_io *io; | 2170 | struct fsf_qtcb_bottom_io *io; |
2171 | unsigned long flags; | ||
2272 | 2172 | ||
2273 | if (unlikely(!(atomic_read(&unit->status) & | 2173 | if (unlikely(!(atomic_read(&zfcp_sdev->status) & |
2274 | ZFCP_STATUS_COMMON_UNBLOCKED))) | 2174 | ZFCP_STATUS_COMMON_UNBLOCKED))) |
2275 | return -EBUSY; | 2175 | return -EBUSY; |
2276 | 2176 | ||
2277 | spin_lock(&qdio->req_q_lock); | 2177 | spin_lock_irqsave(&qdio->req_q_lock, flags); |
2278 | if (atomic_read(&qdio->req_q_free) <= 0) { | 2178 | if (atomic_read(&qdio->req_q_free) <= 0) { |
2279 | atomic_inc(&qdio->req_q_full); | 2179 | atomic_inc(&qdio->req_q_full); |
2280 | goto out; | 2180 | goto out; |
2281 | } | 2181 | } |
2282 | 2182 | ||
2283 | if (scsi_cmnd->sc_data_direction == DMA_TO_DEVICE) | 2183 | if (scsi_cmnd->sc_data_direction == DMA_TO_DEVICE) |
2284 | sbtype = SBAL_FLAGS0_TYPE_WRITE; | 2184 | sbtype = SBAL_SFLAGS0_TYPE_WRITE; |
2285 | 2185 | ||
2286 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND, | 2186 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND, |
2287 | sbtype, adapter->pool.scsi_req); | 2187 | sbtype, adapter->pool.scsi_req); |
@@ -2295,11 +2195,10 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, | |||
2295 | 2195 | ||
2296 | io = &req->qtcb->bottom.io; | 2196 | io = &req->qtcb->bottom.io; |
2297 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; | 2197 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; |
2298 | req->unit = unit; | ||
2299 | req->data = scsi_cmnd; | 2198 | req->data = scsi_cmnd; |
2300 | req->handler = zfcp_fsf_send_fcp_command_handler; | 2199 | req->handler = zfcp_fsf_fcp_cmnd_handler; |
2301 | req->qtcb->header.lun_handle = unit->handle; | 2200 | req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; |
2302 | req->qtcb->header.port_handle = unit->port->handle; | 2201 | req->qtcb->header.port_handle = zfcp_sdev->port->handle; |
2303 | io->service_class = FSF_CLASS_3; | 2202 | io->service_class = FSF_CLASS_3; |
2304 | io->fcp_cmnd_length = FCP_CMND_LEN; | 2203 | io->fcp_cmnd_length = FCP_CMND_LEN; |
2305 | 2204 | ||
@@ -2310,10 +2209,8 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, | |||
2310 | 2209 | ||
2311 | zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction); | 2210 | zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction); |
2312 | 2211 | ||
2313 | get_device(&unit->dev); | ||
2314 | |||
2315 | fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd; | 2212 | fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd; |
2316 | zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd); | 2213 | zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0); |
2317 | 2214 | ||
2318 | if (scsi_prot_sg_count(scsi_cmnd)) { | 2215 | if (scsi_prot_sg_count(scsi_cmnd)) { |
2319 | zfcp_qdio_set_data_div(qdio, &req->qdio_req, | 2216 | zfcp_qdio_set_data_div(qdio, &req->qdio_req, |
@@ -2338,36 +2235,52 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, | |||
2338 | goto out; | 2235 | goto out; |
2339 | 2236 | ||
2340 | failed_scsi_cmnd: | 2237 | failed_scsi_cmnd: |
2341 | put_device(&unit->dev); | ||
2342 | zfcp_fsf_req_free(req); | 2238 | zfcp_fsf_req_free(req); |
2343 | scsi_cmnd->host_scribble = NULL; | 2239 | scsi_cmnd->host_scribble = NULL; |
2344 | out: | 2240 | out: |
2345 | spin_unlock(&qdio->req_q_lock); | 2241 | spin_unlock_irqrestore(&qdio->req_q_lock, flags); |
2346 | return retval; | 2242 | return retval; |
2347 | } | 2243 | } |
2348 | 2244 | ||
2245 | static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req) | ||
2246 | { | ||
2247 | struct fcp_resp_with_ext *fcp_rsp; | ||
2248 | struct fcp_resp_rsp_info *rsp_info; | ||
2249 | |||
2250 | zfcp_fsf_fcp_handler_common(req); | ||
2251 | |||
2252 | fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp; | ||
2253 | rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1]; | ||
2254 | |||
2255 | if ((rsp_info->rsp_code != FCP_TMF_CMPL) || | ||
2256 | (req->status & ZFCP_STATUS_FSFREQ_ERROR)) | ||
2257 | req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED; | ||
2258 | } | ||
2259 | |||
2349 | /** | 2260 | /** |
2350 | * zfcp_fsf_send_fcp_ctm - send SCSI task management command | 2261 | * zfcp_fsf_fcp_task_mgmt - send SCSI task management command |
2351 | * @unit: pointer to struct zfcp_unit | 2262 | * @scmnd: SCSI command to send the task management command for |
2352 | * @tm_flags: unsigned byte for task management flags | 2263 | * @tm_flags: unsigned byte for task management flags |
2353 | * Returns: on success pointer to struct fsf_req, NULL otherwise | 2264 | * Returns: on success pointer to struct fsf_req, NULL otherwise |
2354 | */ | 2265 | */ |
2355 | struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags) | 2266 | struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd, |
2267 | u8 tm_flags) | ||
2356 | { | 2268 | { |
2357 | struct zfcp_fsf_req *req = NULL; | 2269 | struct zfcp_fsf_req *req = NULL; |
2358 | struct fcp_cmnd *fcp_cmnd; | 2270 | struct fcp_cmnd *fcp_cmnd; |
2359 | struct zfcp_qdio *qdio = unit->port->adapter->qdio; | 2271 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device); |
2272 | struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio; | ||
2360 | 2273 | ||
2361 | if (unlikely(!(atomic_read(&unit->status) & | 2274 | if (unlikely(!(atomic_read(&zfcp_sdev->status) & |
2362 | ZFCP_STATUS_COMMON_UNBLOCKED))) | 2275 | ZFCP_STATUS_COMMON_UNBLOCKED))) |
2363 | return NULL; | 2276 | return NULL; |
2364 | 2277 | ||
2365 | spin_lock_bh(&qdio->req_q_lock); | 2278 | spin_lock_irq(&qdio->req_q_lock); |
2366 | if (zfcp_qdio_sbal_get(qdio)) | 2279 | if (zfcp_qdio_sbal_get(qdio)) |
2367 | goto out; | 2280 | goto out; |
2368 | 2281 | ||
2369 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND, | 2282 | req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND, |
2370 | SBAL_FLAGS0_TYPE_WRITE, | 2283 | SBAL_SFLAGS0_TYPE_WRITE, |
2371 | qdio->adapter->pool.scsi_req); | 2284 | qdio->adapter->pool.scsi_req); |
2372 | 2285 | ||
2373 | if (IS_ERR(req)) { | 2286 | if (IS_ERR(req)) { |
@@ -2375,11 +2288,10 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags) | |||
2375 | goto out; | 2288 | goto out; |
2376 | } | 2289 | } |
2377 | 2290 | ||
2378 | req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT; | 2291 | req->data = scmnd; |
2379 | req->data = unit; | 2292 | req->handler = zfcp_fsf_fcp_task_mgmt_handler; |
2380 | req->handler = zfcp_fsf_send_fcp_command_handler; | 2293 | req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; |
2381 | req->qtcb->header.lun_handle = unit->handle; | 2294 | req->qtcb->header.port_handle = zfcp_sdev->port->handle; |
2382 | req->qtcb->header.port_handle = unit->port->handle; | ||
2383 | req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; | 2295 | req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; |
2384 | req->qtcb->bottom.io.service_class = FSF_CLASS_3; | 2296 | req->qtcb->bottom.io.service_class = FSF_CLASS_3; |
2385 | req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN; | 2297 | req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN; |
@@ -2387,7 +2299,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags) | |||
2387 | zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); | 2299 | zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); |
2388 | 2300 | ||
2389 | fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd; | 2301 | fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd; |
2390 | zfcp_fc_fcp_tm(fcp_cmnd, unit->device, tm_flags); | 2302 | zfcp_fc_scsi_to_fcp(fcp_cmnd, scmnd, tm_flags); |
2391 | 2303 | ||
2392 | zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT); | 2304 | zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT); |
2393 | if (!zfcp_fsf_req_send(req)) | 2305 | if (!zfcp_fsf_req_send(req)) |
@@ -2396,7 +2308,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags) | |||
2396 | zfcp_fsf_req_free(req); | 2308 | zfcp_fsf_req_free(req); |
2397 | req = NULL; | 2309 | req = NULL; |
2398 | out: | 2310 | out: |
2399 | spin_unlock_bh(&qdio->req_q_lock); | 2311 | spin_unlock_irq(&qdio->req_q_lock); |
2400 | return req; | 2312 | return req; |
2401 | } | 2313 | } |
2402 | 2314 | ||
@@ -2416,23 +2328,24 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, | |||
2416 | struct zfcp_qdio *qdio = adapter->qdio; | 2328 | struct zfcp_qdio *qdio = adapter->qdio; |
2417 | struct zfcp_fsf_req *req = NULL; | 2329 | struct zfcp_fsf_req *req = NULL; |
2418 | struct fsf_qtcb_bottom_support *bottom; | 2330 | struct fsf_qtcb_bottom_support *bottom; |
2419 | int direction, retval = -EIO, bytes; | 2331 | int retval = -EIO, bytes; |
2332 | u8 direction; | ||
2420 | 2333 | ||
2421 | if (!(adapter->adapter_features & FSF_FEATURE_CFDC)) | 2334 | if (!(adapter->adapter_features & FSF_FEATURE_CFDC)) |
2422 | return ERR_PTR(-EOPNOTSUPP); | 2335 | return ERR_PTR(-EOPNOTSUPP); |
2423 | 2336 | ||
2424 | switch (fsf_cfdc->command) { | 2337 | switch (fsf_cfdc->command) { |
2425 | case FSF_QTCB_DOWNLOAD_CONTROL_FILE: | 2338 | case FSF_QTCB_DOWNLOAD_CONTROL_FILE: |
2426 | direction = SBAL_FLAGS0_TYPE_WRITE; | 2339 | direction = SBAL_SFLAGS0_TYPE_WRITE; |
2427 | break; | 2340 | break; |
2428 | case FSF_QTCB_UPLOAD_CONTROL_FILE: | 2341 | case FSF_QTCB_UPLOAD_CONTROL_FILE: |
2429 | direction = SBAL_FLAGS0_TYPE_READ; | 2342 | direction = SBAL_SFLAGS0_TYPE_READ; |
2430 | break; | 2343 | break; |
2431 | default: | 2344 | default: |
2432 | return ERR_PTR(-EINVAL); | 2345 | return ERR_PTR(-EINVAL); |
2433 | } | 2346 | } |
2434 | 2347 | ||
2435 | spin_lock_bh(&qdio->req_q_lock); | 2348 | spin_lock_irq(&qdio->req_q_lock); |
2436 | if (zfcp_qdio_sbal_get(qdio)) | 2349 | if (zfcp_qdio_sbal_get(qdio)) |
2437 | goto out; | 2350 | goto out; |
2438 | 2351 | ||
@@ -2459,7 +2372,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, | |||
2459 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | 2372 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); |
2460 | retval = zfcp_fsf_req_send(req); | 2373 | retval = zfcp_fsf_req_send(req); |
2461 | out: | 2374 | out: |
2462 | spin_unlock_bh(&qdio->req_q_lock); | 2375 | spin_unlock_irq(&qdio->req_q_lock); |
2463 | 2376 | ||
2464 | if (!retval) { | 2377 | if (!retval) { |
2465 | wait_for_completion(&req->completion); | 2378 | wait_for_completion(&req->completion); |
@@ -2501,7 +2414,16 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx) | |||
2501 | fsf_req->qdio_req.sbal_response = sbal_idx; | 2414 | fsf_req->qdio_req.sbal_response = sbal_idx; |
2502 | zfcp_fsf_req_complete(fsf_req); | 2415 | zfcp_fsf_req_complete(fsf_req); |
2503 | 2416 | ||
2504 | if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY)) | 2417 | if (likely(sbale->eflags & SBAL_EFLAGS_LAST_ENTRY)) |
2505 | break; | 2418 | break; |
2506 | } | 2419 | } |
2507 | } | 2420 | } |
2421 | |||
2422 | struct zfcp_fsf_req *zfcp_fsf_get_req(struct zfcp_qdio *qdio, | ||
2423 | struct qdio_buffer *sbal) | ||
2424 | { | ||
2425 | struct qdio_buffer_element *sbale = &sbal->element[0]; | ||
2426 | u64 req_id = (unsigned long) sbale->addr; | ||
2427 | |||
2428 | return zfcp_reqlist_find(qdio->adapter->req_list, req_id); | ||
2429 | } | ||
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index b2635759721c..d9c40ea73eef 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
@@ -41,7 +41,7 @@ static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id, | |||
41 | zfcp_qdio_siosl(adapter); | 41 | zfcp_qdio_siosl(adapter); |
42 | zfcp_erp_adapter_reopen(adapter, | 42 | zfcp_erp_adapter_reopen(adapter, |
43 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | | 43 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | |
44 | ZFCP_STATUS_COMMON_ERP_FAILED, id, NULL); | 44 | ZFCP_STATUS_COMMON_ERP_FAILED, id); |
45 | } | 45 | } |
46 | 46 | ||
47 | static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt) | 47 | static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt) |
@@ -60,13 +60,11 @@ static inline void zfcp_qdio_account(struct zfcp_qdio *qdio) | |||
60 | unsigned long long now, span; | 60 | unsigned long long now, span; |
61 | int used; | 61 | int used; |
62 | 62 | ||
63 | spin_lock(&qdio->stat_lock); | ||
64 | now = get_clock_monotonic(); | 63 | now = get_clock_monotonic(); |
65 | span = (now - qdio->req_q_time) >> 12; | 64 | span = (now - qdio->req_q_time) >> 12; |
66 | used = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&qdio->req_q_free); | 65 | used = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&qdio->req_q_free); |
67 | qdio->req_q_util += used * span; | 66 | qdio->req_q_util += used * span; |
68 | qdio->req_q_time = now; | 67 | qdio->req_q_time = now; |
69 | spin_unlock(&qdio->stat_lock); | ||
70 | } | 68 | } |
71 | 69 | ||
72 | static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, | 70 | static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, |
@@ -76,7 +74,6 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, | |||
76 | struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; | 74 | struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; |
77 | 75 | ||
78 | if (unlikely(qdio_err)) { | 76 | if (unlikely(qdio_err)) { |
79 | zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count); | ||
80 | zfcp_qdio_handler_error(qdio, "qdireq1", qdio_err); | 77 | zfcp_qdio_handler_error(qdio, "qdireq1", qdio_err); |
81 | return; | 78 | return; |
82 | } | 79 | } |
@@ -84,7 +81,9 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, | |||
84 | /* cleanup all SBALs being program-owned now */ | 81 | /* cleanup all SBALs being program-owned now */ |
85 | zfcp_qdio_zero_sbals(qdio->req_q, idx, count); | 82 | zfcp_qdio_zero_sbals(qdio->req_q, idx, count); |
86 | 83 | ||
84 | spin_lock_irq(&qdio->stat_lock); | ||
87 | zfcp_qdio_account(qdio); | 85 | zfcp_qdio_account(qdio); |
86 | spin_unlock_irq(&qdio->stat_lock); | ||
88 | atomic_add(count, &qdio->req_q_free); | 87 | atomic_add(count, &qdio->req_q_free); |
89 | wake_up(&qdio->req_q_wq); | 88 | wake_up(&qdio->req_q_wq); |
90 | } | 89 | } |
@@ -97,7 +96,6 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, | |||
97 | int sbal_idx, sbal_no; | 96 | int sbal_idx, sbal_no; |
98 | 97 | ||
99 | if (unlikely(qdio_err)) { | 98 | if (unlikely(qdio_err)) { |
100 | zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count); | ||
101 | zfcp_qdio_handler_error(qdio, "qdires1", qdio_err); | 99 | zfcp_qdio_handler_error(qdio, "qdires1", qdio_err); |
102 | return; | 100 | return; |
103 | } | 101 | } |
@@ -116,7 +114,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, | |||
116 | * put SBALs back to response queue | 114 | * put SBALs back to response queue |
117 | */ | 115 | */ |
118 | if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, idx, count)) | 116 | if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, idx, count)) |
119 | zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdires2", NULL); | 117 | zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdires2"); |
120 | } | 118 | } |
121 | 119 | ||
122 | static struct qdio_buffer_element * | 120 | static struct qdio_buffer_element * |
@@ -126,7 +124,7 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) | |||
126 | 124 | ||
127 | /* set last entry flag in current SBALE of current SBAL */ | 125 | /* set last entry flag in current SBALE of current SBAL */ |
128 | sbale = zfcp_qdio_sbale_curr(qdio, q_req); | 126 | sbale = zfcp_qdio_sbale_curr(qdio, q_req); |
129 | sbale->flags |= SBAL_FLAGS_LAST_ENTRY; | 127 | sbale->eflags |= SBAL_EFLAGS_LAST_ENTRY; |
130 | 128 | ||
131 | /* don't exceed last allowed SBAL */ | 129 | /* don't exceed last allowed SBAL */ |
132 | if (q_req->sbal_last == q_req->sbal_limit) | 130 | if (q_req->sbal_last == q_req->sbal_limit) |
@@ -134,7 +132,7 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) | |||
134 | 132 | ||
135 | /* set chaining flag in first SBALE of current SBAL */ | 133 | /* set chaining flag in first SBALE of current SBAL */ |
136 | sbale = zfcp_qdio_sbale_req(qdio, q_req); | 134 | sbale = zfcp_qdio_sbale_req(qdio, q_req); |
137 | sbale->flags |= SBAL_FLAGS0_MORE_SBALS; | 135 | sbale->sflags |= SBAL_SFLAGS0_MORE_SBALS; |
138 | 136 | ||
139 | /* calculate index of next SBAL */ | 137 | /* calculate index of next SBAL */ |
140 | q_req->sbal_last++; | 138 | q_req->sbal_last++; |
@@ -149,7 +147,7 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) | |||
149 | 147 | ||
150 | /* set storage-block type for new SBAL */ | 148 | /* set storage-block type for new SBAL */ |
151 | sbale = zfcp_qdio_sbale_curr(qdio, q_req); | 149 | sbale = zfcp_qdio_sbale_curr(qdio, q_req); |
152 | sbale->flags |= q_req->sbtype; | 150 | sbale->sflags |= q_req->sbtype; |
153 | 151 | ||
154 | return sbale; | 152 | return sbale; |
155 | } | 153 | } |
@@ -179,7 +177,7 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, | |||
179 | 177 | ||
180 | /* set storage-block type for this request */ | 178 | /* set storage-block type for this request */ |
181 | sbale = zfcp_qdio_sbale_req(qdio, q_req); | 179 | sbale = zfcp_qdio_sbale_req(qdio, q_req); |
182 | sbale->flags |= q_req->sbtype; | 180 | sbale->sflags |= q_req->sbtype; |
183 | 181 | ||
184 | for (; sg; sg = sg_next(sg)) { | 182 | for (; sg; sg = sg_next(sg)) { |
185 | sbale = zfcp_qdio_sbale_next(qdio, q_req); | 183 | sbale = zfcp_qdio_sbale_next(qdio, q_req); |
@@ -201,11 +199,11 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, | |||
201 | 199 | ||
202 | static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio) | 200 | static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio) |
203 | { | 201 | { |
204 | spin_lock_bh(&qdio->req_q_lock); | 202 | spin_lock_irq(&qdio->req_q_lock); |
205 | if (atomic_read(&qdio->req_q_free) || | 203 | if (atomic_read(&qdio->req_q_free) || |
206 | !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) | 204 | !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) |
207 | return 1; | 205 | return 1; |
208 | spin_unlock_bh(&qdio->req_q_lock); | 206 | spin_unlock_irq(&qdio->req_q_lock); |
209 | return 0; | 207 | return 0; |
210 | } | 208 | } |
211 | 209 | ||
@@ -223,7 +221,7 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio) | |||
223 | { | 221 | { |
224 | long ret; | 222 | long ret; |
225 | 223 | ||
226 | spin_unlock_bh(&qdio->req_q_lock); | 224 | spin_unlock_irq(&qdio->req_q_lock); |
227 | ret = wait_event_interruptible_timeout(qdio->req_q_wq, | 225 | ret = wait_event_interruptible_timeout(qdio->req_q_wq, |
228 | zfcp_qdio_sbal_check(qdio), 5 * HZ); | 226 | zfcp_qdio_sbal_check(qdio), 5 * HZ); |
229 | 227 | ||
@@ -236,10 +234,10 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio) | |||
236 | if (!ret) { | 234 | if (!ret) { |
237 | atomic_inc(&qdio->req_q_full); | 235 | atomic_inc(&qdio->req_q_full); |
238 | /* assume hanging outbound queue, try queue recovery */ | 236 | /* assume hanging outbound queue, try queue recovery */ |
239 | zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1", NULL); | 237 | zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1"); |
240 | } | 238 | } |
241 | 239 | ||
242 | spin_lock_bh(&qdio->req_q_lock); | 240 | spin_lock_irq(&qdio->req_q_lock); |
243 | return -EIO; | 241 | return -EIO; |
244 | } | 242 | } |
245 | 243 | ||
@@ -254,7 +252,9 @@ int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) | |||
254 | int retval; | 252 | int retval; |
255 | u8 sbal_number = q_req->sbal_number; | 253 | u8 sbal_number = q_req->sbal_number; |
256 | 254 | ||
255 | spin_lock(&qdio->stat_lock); | ||
257 | zfcp_qdio_account(qdio); | 256 | zfcp_qdio_account(qdio); |
257 | spin_unlock(&qdio->stat_lock); | ||
258 | 258 | ||
259 | retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, | 259 | retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, |
260 | q_req->sbal_first, sbal_number); | 260 | q_req->sbal_first, sbal_number); |
@@ -277,16 +277,12 @@ int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) | |||
277 | static void zfcp_qdio_setup_init_data(struct qdio_initialize *id, | 277 | static void zfcp_qdio_setup_init_data(struct qdio_initialize *id, |
278 | struct zfcp_qdio *qdio) | 278 | struct zfcp_qdio *qdio) |
279 | { | 279 | { |
280 | 280 | memset(id, 0, sizeof(*id)); | |
281 | id->cdev = qdio->adapter->ccw_device; | 281 | id->cdev = qdio->adapter->ccw_device; |
282 | id->q_format = QDIO_ZFCP_QFMT; | 282 | id->q_format = QDIO_ZFCP_QFMT; |
283 | memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8); | 283 | memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8); |
284 | ASCEBC(id->adapter_name, 8); | 284 | ASCEBC(id->adapter_name, 8); |
285 | id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV; | 285 | id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV; |
286 | id->qib_param_field_format = 0; | ||
287 | id->qib_param_field = NULL; | ||
288 | id->input_slib_elements = NULL; | ||
289 | id->output_slib_elements = NULL; | ||
290 | id->no_input_qs = 1; | 286 | id->no_input_qs = 1; |
291 | id->no_output_qs = 1; | 287 | id->no_output_qs = 1; |
292 | id->input_handler = zfcp_qdio_int_resp; | 288 | id->input_handler = zfcp_qdio_int_resp; |
@@ -294,6 +290,8 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id, | |||
294 | id->int_parm = (unsigned long) qdio; | 290 | id->int_parm = (unsigned long) qdio; |
295 | id->input_sbal_addr_array = (void **) (qdio->res_q); | 291 | id->input_sbal_addr_array = (void **) (qdio->res_q); |
296 | id->output_sbal_addr_array = (void **) (qdio->req_q); | 292 | id->output_sbal_addr_array = (void **) (qdio->req_q); |
293 | id->scan_threshold = | ||
294 | QDIO_MAX_BUFFERS_PER_Q - ZFCP_QDIO_MAX_SBALS_PER_REQ * 2; | ||
297 | } | 295 | } |
298 | 296 | ||
299 | /** | 297 | /** |
@@ -311,6 +309,7 @@ static int zfcp_qdio_allocate(struct zfcp_qdio *qdio) | |||
311 | return -ENOMEM; | 309 | return -ENOMEM; |
312 | 310 | ||
313 | zfcp_qdio_setup_init_data(&init_data, qdio); | 311 | zfcp_qdio_setup_init_data(&init_data, qdio); |
312 | init_waitqueue_head(&qdio->req_q_wq); | ||
314 | 313 | ||
315 | return qdio_allocate(&init_data); | 314 | return qdio_allocate(&init_data); |
316 | } | 315 | } |
@@ -328,9 +327,9 @@ void zfcp_qdio_close(struct zfcp_qdio *qdio) | |||
328 | return; | 327 | return; |
329 | 328 | ||
330 | /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */ | 329 | /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */ |
331 | spin_lock_bh(&qdio->req_q_lock); | 330 | spin_lock_irq(&qdio->req_q_lock); |
332 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); | 331 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); |
333 | spin_unlock_bh(&qdio->req_q_lock); | 332 | spin_unlock_irq(&qdio->req_q_lock); |
334 | 333 | ||
335 | wake_up(&qdio->req_q_wq); | 334 | wake_up(&qdio->req_q_wq); |
336 | 335 | ||
@@ -385,16 +384,18 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio) | |||
385 | for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) { | 384 | for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) { |
386 | sbale = &(qdio->res_q[cc]->element[0]); | 385 | sbale = &(qdio->res_q[cc]->element[0]); |
387 | sbale->length = 0; | 386 | sbale->length = 0; |
388 | sbale->flags = SBAL_FLAGS_LAST_ENTRY; | 387 | sbale->eflags = SBAL_EFLAGS_LAST_ENTRY; |
388 | sbale->sflags = 0; | ||
389 | sbale->addr = NULL; | 389 | sbale->addr = NULL; |
390 | } | 390 | } |
391 | 391 | ||
392 | if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q)) | 392 | if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q)) |
393 | goto failed_qdio; | 393 | goto failed_qdio; |
394 | 394 | ||
395 | /* set index of first avalable SBALS / number of available SBALS */ | 395 | /* set index of first available SBALS / number of available SBALS */ |
396 | qdio->req_q_idx = 0; | 396 | qdio->req_q_idx = 0; |
397 | atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q); | 397 | atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q); |
398 | atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status); | ||
398 | 399 | ||
399 | return 0; | 400 | return 0; |
400 | 401 | ||
diff --git a/drivers/s390/scsi/zfcp_qdio.h b/drivers/s390/scsi/zfcp_qdio.h index 2297d8d3e947..54e22ace012b 100644 --- a/drivers/s390/scsi/zfcp_qdio.h +++ b/drivers/s390/scsi/zfcp_qdio.h | |||
@@ -67,7 +67,7 @@ struct zfcp_qdio { | |||
67 | * @qdio_outb_usage: usage of outbound queue | 67 | * @qdio_outb_usage: usage of outbound queue |
68 | */ | 68 | */ |
69 | struct zfcp_qdio_req { | 69 | struct zfcp_qdio_req { |
70 | u32 sbtype; | 70 | u8 sbtype; |
71 | u8 sbal_number; | 71 | u8 sbal_number; |
72 | u8 sbal_first; | 72 | u8 sbal_first; |
73 | u8 sbal_last; | 73 | u8 sbal_last; |
@@ -116,7 +116,7 @@ zfcp_qdio_sbale_curr(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) | |||
116 | */ | 116 | */ |
117 | static inline | 117 | static inline |
118 | void zfcp_qdio_req_init(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, | 118 | void zfcp_qdio_req_init(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, |
119 | unsigned long req_id, u32 sbtype, void *data, u32 len) | 119 | unsigned long req_id, u8 sbtype, void *data, u32 len) |
120 | { | 120 | { |
121 | struct qdio_buffer_element *sbale; | 121 | struct qdio_buffer_element *sbale; |
122 | int count = min(atomic_read(&qdio->req_q_free), | 122 | int count = min(atomic_read(&qdio->req_q_free), |
@@ -131,7 +131,8 @@ void zfcp_qdio_req_init(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, | |||
131 | 131 | ||
132 | sbale = zfcp_qdio_sbale_req(qdio, q_req); | 132 | sbale = zfcp_qdio_sbale_req(qdio, q_req); |
133 | sbale->addr = (void *) req_id; | 133 | sbale->addr = (void *) req_id; |
134 | sbale->flags = SBAL_FLAGS0_COMMAND | sbtype; | 134 | sbale->eflags = 0; |
135 | sbale->sflags = SBAL_SFLAGS0_COMMAND | sbtype; | ||
135 | 136 | ||
136 | if (unlikely(!data)) | 137 | if (unlikely(!data)) |
137 | return; | 138 | return; |
@@ -173,7 +174,7 @@ void zfcp_qdio_set_sbale_last(struct zfcp_qdio *qdio, | |||
173 | struct qdio_buffer_element *sbale; | 174 | struct qdio_buffer_element *sbale; |
174 | 175 | ||
175 | sbale = zfcp_qdio_sbale_curr(qdio, q_req); | 176 | sbale = zfcp_qdio_sbale_curr(qdio, q_req); |
176 | sbale->flags |= SBAL_FLAGS_LAST_ENTRY; | 177 | sbale->eflags |= SBAL_EFLAGS_LAST_ENTRY; |
177 | } | 178 | } |
178 | 179 | ||
179 | /** | 180 | /** |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index cb000c9833bb..2a4991d6d4d5 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -30,6 +30,10 @@ module_param_named(dif, enable_dif, bool, 0600); | |||
30 | MODULE_PARM_DESC(dif, "Enable DIF/DIX data integrity support"); | 30 | MODULE_PARM_DESC(dif, "Enable DIF/DIX data integrity support"); |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | static bool allow_lun_scan = 1; | ||
34 | module_param(allow_lun_scan, bool, 0600); | ||
35 | MODULE_PARM_DESC(allow_lun_scan, "For NPIV, scan and attach all storage LUNs"); | ||
36 | |||
33 | static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth, | 37 | static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth, |
34 | int reason) | 38 | int reason) |
35 | { | 39 | { |
@@ -49,11 +53,12 @@ static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth, | |||
49 | return sdev->queue_depth; | 53 | return sdev->queue_depth; |
50 | } | 54 | } |
51 | 55 | ||
52 | static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | 56 | static void zfcp_scsi_slave_destroy(struct scsi_device *sdev) |
53 | { | 57 | { |
54 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; | 58 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
55 | unit->device = NULL; | 59 | |
56 | put_device(&unit->dev); | 60 | zfcp_erp_lun_shutdown_wait(sdev, "scssd_1"); |
61 | put_device(&zfcp_sdev->port->dev); | ||
57 | } | 62 | } |
58 | 63 | ||
59 | static int zfcp_scsi_slave_configure(struct scsi_device *sdp) | 64 | static int zfcp_scsi_slave_configure(struct scsi_device *sdp) |
@@ -67,47 +72,35 @@ static int zfcp_scsi_slave_configure(struct scsi_device *sdp) | |||
67 | 72 | ||
68 | static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) | 73 | static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) |
69 | { | 74 | { |
70 | struct zfcp_adapter *adapter = | ||
71 | (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; | ||
72 | |||
73 | set_host_byte(scpnt, result); | 75 | set_host_byte(scpnt, result); |
74 | zfcp_dbf_scsi_fail_send(adapter->dbf, scpnt); | 76 | zfcp_dbf_scsi_fail_send(scpnt); |
75 | scpnt->scsi_done(scpnt); | 77 | scpnt->scsi_done(scpnt); |
76 | } | 78 | } |
77 | 79 | ||
78 | static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, | 80 | static |
79 | void (*done) (struct scsi_cmnd *)) | 81 | int zfcp_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scpnt) |
80 | { | 82 | { |
81 | struct zfcp_unit *unit; | 83 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device); |
82 | struct zfcp_adapter *adapter; | ||
83 | int status, scsi_result, ret; | ||
84 | struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device)); | 84 | struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device)); |
85 | int status, scsi_result, ret; | ||
85 | 86 | ||
86 | /* reset the status for this request */ | 87 | /* reset the status for this request */ |
87 | scpnt->result = 0; | 88 | scpnt->result = 0; |
88 | scpnt->host_scribble = NULL; | 89 | scpnt->host_scribble = NULL; |
89 | scpnt->scsi_done = done; | ||
90 | |||
91 | /* | ||
92 | * figure out adapter and target device | ||
93 | * (stored there by zfcp_scsi_slave_alloc) | ||
94 | */ | ||
95 | adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; | ||
96 | unit = scpnt->device->hostdata; | ||
97 | 90 | ||
98 | scsi_result = fc_remote_port_chkready(rport); | 91 | scsi_result = fc_remote_port_chkready(rport); |
99 | if (unlikely(scsi_result)) { | 92 | if (unlikely(scsi_result)) { |
100 | scpnt->result = scsi_result; | 93 | scpnt->result = scsi_result; |
101 | zfcp_dbf_scsi_fail_send(adapter->dbf, scpnt); | 94 | zfcp_dbf_scsi_fail_send(scpnt); |
102 | scpnt->scsi_done(scpnt); | 95 | scpnt->scsi_done(scpnt); |
103 | return 0; | 96 | return 0; |
104 | } | 97 | } |
105 | 98 | ||
106 | status = atomic_read(&unit->status); | 99 | status = atomic_read(&zfcp_sdev->status); |
107 | if (unlikely(status & ZFCP_STATUS_COMMON_ERP_FAILED) && | 100 | if (unlikely(status & ZFCP_STATUS_COMMON_ERP_FAILED) && |
108 | !(atomic_read(&unit->port->status) & | 101 | !(atomic_read(&zfcp_sdev->port->status) & |
109 | ZFCP_STATUS_COMMON_ERP_FAILED)) { | 102 | ZFCP_STATUS_COMMON_ERP_FAILED)) { |
110 | /* only unit access denied, but port is good | 103 | /* only LUN access denied, but port is good |
111 | * not covered by FC transport, have to fail here */ | 104 | * not covered by FC transport, have to fail here */ |
112 | zfcp_scsi_command_fail(scpnt, DID_ERROR); | 105 | zfcp_scsi_command_fail(scpnt, DID_ERROR); |
113 | return 0; | 106 | return 0; |
@@ -115,8 +108,8 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, | |||
115 | 108 | ||
116 | if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) { | 109 | if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) { |
117 | /* This could be either | 110 | /* This could be either |
118 | * open unit pending: this is temporary, will result in | 111 | * open LUN pending: this is temporary, will result in |
119 | * open unit or ERP_FAILED, so retry command | 112 | * open LUN or ERP_FAILED, so retry command |
120 | * call to rport_delete pending: mimic retry from | 113 | * call to rport_delete pending: mimic retry from |
121 | * fc_remote_port_chkready until rport is BLOCKED | 114 | * fc_remote_port_chkready until rport is BLOCKED |
122 | */ | 115 | */ |
@@ -124,7 +117,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, | |||
124 | return 0; | 117 | return 0; |
125 | } | 118 | } |
126 | 119 | ||
127 | ret = zfcp_fsf_send_fcp_command_task(unit, scpnt); | 120 | ret = zfcp_fsf_fcp_cmnd(scpnt); |
128 | if (unlikely(ret == -EBUSY)) | 121 | if (unlikely(ret == -EBUSY)) |
129 | return SCSI_MLQUEUE_DEVICE_BUSY; | 122 | return SCSI_MLQUEUE_DEVICE_BUSY; |
130 | else if (unlikely(ret < 0)) | 123 | else if (unlikely(ret < 0)) |
@@ -133,45 +126,43 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, | |||
133 | return ret; | 126 | return ret; |
134 | } | 127 | } |
135 | 128 | ||
136 | static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter, | 129 | static int zfcp_scsi_slave_alloc(struct scsi_device *sdev) |
137 | unsigned int id, u64 lun) | ||
138 | { | 130 | { |
139 | unsigned long flags; | 131 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); |
132 | struct zfcp_adapter *adapter = | ||
133 | (struct zfcp_adapter *) sdev->host->hostdata[0]; | ||
134 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
140 | struct zfcp_port *port; | 135 | struct zfcp_port *port; |
141 | struct zfcp_unit *unit = NULL; | 136 | struct zfcp_unit *unit; |
137 | int npiv = adapter->connection_features & FSF_FEATURE_NPIV_MODE; | ||
142 | 138 | ||
143 | read_lock_irqsave(&adapter->port_list_lock, flags); | 139 | port = zfcp_get_port_by_wwpn(adapter, rport->port_name); |
144 | list_for_each_entry(port, &adapter->port_list, list) { | 140 | if (!port) |
145 | if (!port->rport || (id != port->rport->scsi_target_id)) | 141 | return -ENXIO; |
146 | continue; | ||
147 | unit = zfcp_get_unit_by_lun(port, lun); | ||
148 | if (unit) | ||
149 | break; | ||
150 | } | ||
151 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | ||
152 | 142 | ||
153 | return unit; | 143 | unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev)); |
154 | } | 144 | if (unit) |
145 | put_device(&unit->dev); | ||
155 | 146 | ||
156 | static int zfcp_scsi_slave_alloc(struct scsi_device *sdp) | 147 | if (!unit && !(allow_lun_scan && npiv)) { |
157 | { | 148 | put_device(&port->dev); |
158 | struct zfcp_adapter *adapter; | 149 | return -ENXIO; |
159 | struct zfcp_unit *unit; | 150 | } |
160 | u64 lun; | ||
161 | 151 | ||
162 | adapter = (struct zfcp_adapter *) sdp->host->hostdata[0]; | 152 | zfcp_sdev->port = port; |
163 | if (!adapter) | 153 | zfcp_sdev->latencies.write.channel.min = 0xFFFFFFFF; |
164 | goto out; | 154 | zfcp_sdev->latencies.write.fabric.min = 0xFFFFFFFF; |
155 | zfcp_sdev->latencies.read.channel.min = 0xFFFFFFFF; | ||
156 | zfcp_sdev->latencies.read.fabric.min = 0xFFFFFFFF; | ||
157 | zfcp_sdev->latencies.cmd.channel.min = 0xFFFFFFFF; | ||
158 | zfcp_sdev->latencies.cmd.fabric.min = 0xFFFFFFFF; | ||
159 | spin_lock_init(&zfcp_sdev->latencies.lock); | ||
165 | 160 | ||
166 | int_to_scsilun(sdp->lun, (struct scsi_lun *)&lun); | 161 | zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING); |
167 | unit = zfcp_unit_lookup(adapter, sdp->id, lun); | 162 | zfcp_erp_lun_reopen(sdev, 0, "scsla_1"); |
168 | if (unit) { | 163 | zfcp_erp_wait(port->adapter); |
169 | sdp->hostdata = unit; | 164 | |
170 | unit->device = sdp; | 165 | return 0; |
171 | return 0; | ||
172 | } | ||
173 | out: | ||
174 | return -ENXIO; | ||
175 | } | 166 | } |
176 | 167 | ||
177 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | 168 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) |
@@ -179,7 +170,6 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
179 | struct Scsi_Host *scsi_host = scpnt->device->host; | 170 | struct Scsi_Host *scsi_host = scpnt->device->host; |
180 | struct zfcp_adapter *adapter = | 171 | struct zfcp_adapter *adapter = |
181 | (struct zfcp_adapter *) scsi_host->hostdata[0]; | 172 | (struct zfcp_adapter *) scsi_host->hostdata[0]; |
182 | struct zfcp_unit *unit = scpnt->device->hostdata; | ||
183 | struct zfcp_fsf_req *old_req, *abrt_req; | 173 | struct zfcp_fsf_req *old_req, *abrt_req; |
184 | unsigned long flags; | 174 | unsigned long flags; |
185 | unsigned long old_reqid = (unsigned long) scpnt->host_scribble; | 175 | unsigned long old_reqid = (unsigned long) scpnt->host_scribble; |
@@ -193,8 +183,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
193 | old_req = zfcp_reqlist_find(adapter->req_list, old_reqid); | 183 | old_req = zfcp_reqlist_find(adapter->req_list, old_reqid); |
194 | if (!old_req) { | 184 | if (!old_req) { |
195 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 185 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
196 | zfcp_dbf_scsi_abort("lte1", adapter->dbf, scpnt, NULL, | 186 | zfcp_dbf_scsi_abort("abrt_or", scpnt, NULL); |
197 | old_reqid); | ||
198 | return FAILED; /* completion could be in progress */ | 187 | return FAILED; /* completion could be in progress */ |
199 | } | 188 | } |
200 | old_req->data = NULL; | 189 | old_req->data = NULL; |
@@ -203,49 +192,52 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
203 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 192 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
204 | 193 | ||
205 | while (retry--) { | 194 | while (retry--) { |
206 | abrt_req = zfcp_fsf_abort_fcp_command(old_reqid, unit); | 195 | abrt_req = zfcp_fsf_abort_fcp_cmnd(scpnt); |
207 | if (abrt_req) | 196 | if (abrt_req) |
208 | break; | 197 | break; |
209 | 198 | ||
210 | zfcp_erp_wait(adapter); | 199 | zfcp_erp_wait(adapter); |
211 | ret = fc_block_scsi_eh(scpnt); | 200 | ret = fc_block_scsi_eh(scpnt); |
212 | if (ret) | 201 | if (ret) { |
202 | zfcp_dbf_scsi_abort("abrt_bl", scpnt, NULL); | ||
213 | return ret; | 203 | return ret; |
204 | } | ||
214 | if (!(atomic_read(&adapter->status) & | 205 | if (!(atomic_read(&adapter->status) & |
215 | ZFCP_STATUS_COMMON_RUNNING)) { | 206 | ZFCP_STATUS_COMMON_RUNNING)) { |
216 | zfcp_dbf_scsi_abort("nres", adapter->dbf, scpnt, NULL, | 207 | zfcp_dbf_scsi_abort("abrt_ru", scpnt, NULL); |
217 | old_reqid); | ||
218 | return SUCCESS; | 208 | return SUCCESS; |
219 | } | 209 | } |
220 | } | 210 | } |
221 | if (!abrt_req) | 211 | if (!abrt_req) { |
212 | zfcp_dbf_scsi_abort("abrt_ar", scpnt, NULL); | ||
222 | return FAILED; | 213 | return FAILED; |
214 | } | ||
223 | 215 | ||
224 | wait_for_completion(&abrt_req->completion); | 216 | wait_for_completion(&abrt_req->completion); |
225 | 217 | ||
226 | if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) | 218 | if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) |
227 | dbf_tag = "okay"; | 219 | dbf_tag = "abrt_ok"; |
228 | else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) | 220 | else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) |
229 | dbf_tag = "lte2"; | 221 | dbf_tag = "abrt_nn"; |
230 | else { | 222 | else { |
231 | dbf_tag = "fail"; | 223 | dbf_tag = "abrt_fa"; |
232 | retval = FAILED; | 224 | retval = FAILED; |
233 | } | 225 | } |
234 | zfcp_dbf_scsi_abort(dbf_tag, adapter->dbf, scpnt, abrt_req, old_reqid); | 226 | zfcp_dbf_scsi_abort(dbf_tag, scpnt, abrt_req); |
235 | zfcp_fsf_req_free(abrt_req); | 227 | zfcp_fsf_req_free(abrt_req); |
236 | return retval; | 228 | return retval; |
237 | } | 229 | } |
238 | 230 | ||
239 | static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) | 231 | static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) |
240 | { | 232 | { |
241 | struct zfcp_unit *unit = scpnt->device->hostdata; | 233 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device); |
242 | struct zfcp_adapter *adapter = unit->port->adapter; | 234 | struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; |
243 | struct zfcp_fsf_req *fsf_req = NULL; | 235 | struct zfcp_fsf_req *fsf_req = NULL; |
244 | int retval = SUCCESS, ret; | 236 | int retval = SUCCESS, ret; |
245 | int retry = 3; | 237 | int retry = 3; |
246 | 238 | ||
247 | while (retry--) { | 239 | while (retry--) { |
248 | fsf_req = zfcp_fsf_send_fcp_ctm(unit, tm_flags); | 240 | fsf_req = zfcp_fsf_fcp_task_mgmt(scpnt, tm_flags); |
249 | if (fsf_req) | 241 | if (fsf_req) |
250 | break; | 242 | break; |
251 | 243 | ||
@@ -256,7 +248,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) | |||
256 | 248 | ||
257 | if (!(atomic_read(&adapter->status) & | 249 | if (!(atomic_read(&adapter->status) & |
258 | ZFCP_STATUS_COMMON_RUNNING)) { | 250 | ZFCP_STATUS_COMMON_RUNNING)) { |
259 | zfcp_dbf_scsi_devreset("nres", tm_flags, unit, scpnt); | 251 | zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags); |
260 | return SUCCESS; | 252 | return SUCCESS; |
261 | } | 253 | } |
262 | } | 254 | } |
@@ -266,10 +258,10 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) | |||
266 | wait_for_completion(&fsf_req->completion); | 258 | wait_for_completion(&fsf_req->completion); |
267 | 259 | ||
268 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { | 260 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { |
269 | zfcp_dbf_scsi_devreset("fail", tm_flags, unit, scpnt); | 261 | zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags); |
270 | retval = FAILED; | 262 | retval = FAILED; |
271 | } else | 263 | } else |
272 | zfcp_dbf_scsi_devreset("okay", tm_flags, unit, scpnt); | 264 | zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags); |
273 | 265 | ||
274 | zfcp_fsf_req_free(fsf_req); | 266 | zfcp_fsf_req_free(fsf_req); |
275 | return retval; | 267 | return retval; |
@@ -287,11 +279,11 @@ static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt) | |||
287 | 279 | ||
288 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) | 280 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) |
289 | { | 281 | { |
290 | struct zfcp_unit *unit = scpnt->device->hostdata; | 282 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device); |
291 | struct zfcp_adapter *adapter = unit->port->adapter; | 283 | struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; |
292 | int ret; | 284 | int ret; |
293 | 285 | ||
294 | zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt); | 286 | zfcp_erp_adapter_reopen(adapter, 0, "schrh_1"); |
295 | zfcp_erp_wait(adapter); | 287 | zfcp_erp_wait(adapter); |
296 | ret = fc_block_scsi_eh(scpnt); | 288 | ret = fc_block_scsi_eh(scpnt); |
297 | if (ret) | 289 | if (ret) |
@@ -300,7 +292,37 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) | |||
300 | return SUCCESS; | 292 | return SUCCESS; |
301 | } | 293 | } |
302 | 294 | ||
303 | int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) | 295 | struct scsi_transport_template *zfcp_scsi_transport_template; |
296 | |||
297 | static struct scsi_host_template zfcp_scsi_host_template = { | ||
298 | .module = THIS_MODULE, | ||
299 | .name = "zfcp", | ||
300 | .queuecommand = zfcp_scsi_queuecommand, | ||
301 | .eh_abort_handler = zfcp_scsi_eh_abort_handler, | ||
302 | .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, | ||
303 | .eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler, | ||
304 | .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, | ||
305 | .slave_alloc = zfcp_scsi_slave_alloc, | ||
306 | .slave_configure = zfcp_scsi_slave_configure, | ||
307 | .slave_destroy = zfcp_scsi_slave_destroy, | ||
308 | .change_queue_depth = zfcp_scsi_change_queue_depth, | ||
309 | .proc_name = "zfcp", | ||
310 | .can_queue = 4096, | ||
311 | .this_id = -1, | ||
312 | .sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ, | ||
313 | .max_sectors = (ZFCP_QDIO_MAX_SBALES_PER_REQ * 8), | ||
314 | .dma_boundary = ZFCP_QDIO_SBALE_LEN - 1, | ||
315 | .cmd_per_lun = 1, | ||
316 | .use_clustering = 1, | ||
317 | .shost_attrs = zfcp_sysfs_shost_attrs, | ||
318 | .sdev_attrs = zfcp_sysfs_sdev_attrs, | ||
319 | }; | ||
320 | |||
321 | /** | ||
322 | * zfcp_scsi_adapter_register - Register SCSI and FC host with SCSI midlayer | ||
323 | * @adapter: The zfcp adapter to register with the SCSI midlayer | ||
324 | */ | ||
325 | int zfcp_scsi_adapter_register(struct zfcp_adapter *adapter) | ||
304 | { | 326 | { |
305 | struct ccw_dev_id dev_id; | 327 | struct ccw_dev_id dev_id; |
306 | 328 | ||
@@ -309,7 +331,7 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) | |||
309 | 331 | ||
310 | ccw_device_get_id(adapter->ccw_device, &dev_id); | 332 | ccw_device_get_id(adapter->ccw_device, &dev_id); |
311 | /* register adapter as SCSI host with mid layer of SCSI stack */ | 333 | /* register adapter as SCSI host with mid layer of SCSI stack */ |
312 | adapter->scsi_host = scsi_host_alloc(&zfcp_data.scsi_host_template, | 334 | adapter->scsi_host = scsi_host_alloc(&zfcp_scsi_host_template, |
313 | sizeof (struct zfcp_adapter *)); | 335 | sizeof (struct zfcp_adapter *)); |
314 | if (!adapter->scsi_host) { | 336 | if (!adapter->scsi_host) { |
315 | dev_err(&adapter->ccw_device->dev, | 337 | dev_err(&adapter->ccw_device->dev, |
@@ -319,12 +341,12 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) | |||
319 | } | 341 | } |
320 | 342 | ||
321 | /* tell the SCSI stack some characteristics of this adapter */ | 343 | /* tell the SCSI stack some characteristics of this adapter */ |
322 | adapter->scsi_host->max_id = 1; | 344 | adapter->scsi_host->max_id = 511; |
323 | adapter->scsi_host->max_lun = 1; | 345 | adapter->scsi_host->max_lun = 0xFFFFFFFF; |
324 | adapter->scsi_host->max_channel = 0; | 346 | adapter->scsi_host->max_channel = 0; |
325 | adapter->scsi_host->unique_id = dev_id.devno; | 347 | adapter->scsi_host->unique_id = dev_id.devno; |
326 | adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */ | 348 | adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */ |
327 | adapter->scsi_host->transportt = zfcp_data.scsi_transport_template; | 349 | adapter->scsi_host->transportt = zfcp_scsi_transport_template; |
328 | 350 | ||
329 | adapter->scsi_host->hostdata[0] = (unsigned long) adapter; | 351 | adapter->scsi_host->hostdata[0] = (unsigned long) adapter; |
330 | 352 | ||
@@ -336,7 +358,11 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) | |||
336 | return 0; | 358 | return 0; |
337 | } | 359 | } |
338 | 360 | ||
339 | void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) | 361 | /** |
362 | * zfcp_scsi_adapter_unregister - Unregister SCSI and FC host from SCSI midlayer | ||
363 | * @adapter: The zfcp adapter to unregister. | ||
364 | */ | ||
365 | void zfcp_scsi_adapter_unregister(struct zfcp_adapter *adapter) | ||
340 | { | 366 | { |
341 | struct Scsi_Host *shost; | 367 | struct Scsi_Host *shost; |
342 | struct zfcp_port *port; | 368 | struct zfcp_port *port; |
@@ -354,8 +380,6 @@ void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) | |||
354 | scsi_remove_host(shost); | 380 | scsi_remove_host(shost); |
355 | scsi_host_put(shost); | 381 | scsi_host_put(shost); |
356 | adapter->scsi_host = NULL; | 382 | adapter->scsi_host = NULL; |
357 | |||
358 | return; | ||
359 | } | 383 | } |
360 | 384 | ||
361 | static struct fc_host_statistics* | 385 | static struct fc_host_statistics* |
@@ -529,25 +553,11 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) | |||
529 | port = zfcp_get_port_by_wwpn(adapter, rport->port_name); | 553 | port = zfcp_get_port_by_wwpn(adapter, rport->port_name); |
530 | 554 | ||
531 | if (port) { | 555 | if (port) { |
532 | zfcp_erp_port_forced_reopen(port, 0, "sctrpi1", NULL); | 556 | zfcp_erp_port_forced_reopen(port, 0, "sctrpi1"); |
533 | put_device(&port->dev); | 557 | put_device(&port->dev); |
534 | } | 558 | } |
535 | } | 559 | } |
536 | 560 | ||
537 | static void zfcp_scsi_queue_unit_register(struct zfcp_port *port) | ||
538 | { | ||
539 | struct zfcp_unit *unit; | ||
540 | |||
541 | read_lock_irq(&port->unit_list_lock); | ||
542 | list_for_each_entry(unit, &port->unit_list, list) { | ||
543 | get_device(&unit->dev); | ||
544 | if (scsi_queue_work(port->adapter->scsi_host, | ||
545 | &unit->scsi_work) <= 0) | ||
546 | put_device(&unit->dev); | ||
547 | } | ||
548 | read_unlock_irq(&port->unit_list_lock); | ||
549 | } | ||
550 | |||
551 | static void zfcp_scsi_rport_register(struct zfcp_port *port) | 561 | static void zfcp_scsi_rport_register(struct zfcp_port *port) |
552 | { | 562 | { |
553 | struct fc_rport_identifiers ids; | 563 | struct fc_rport_identifiers ids; |
@@ -574,7 +584,7 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port) | |||
574 | port->rport = rport; | 584 | port->rport = rport; |
575 | port->starget_id = rport->scsi_target_id; | 585 | port->starget_id = rport->scsi_target_id; |
576 | 586 | ||
577 | zfcp_scsi_queue_unit_register(port); | 587 | zfcp_unit_queue_scsi_scan(port); |
578 | } | 588 | } |
579 | 589 | ||
580 | static void zfcp_scsi_rport_block(struct zfcp_port *port) | 590 | static void zfcp_scsi_rport_block(struct zfcp_port *port) |
@@ -638,29 +648,6 @@ void zfcp_scsi_rport_work(struct work_struct *work) | |||
638 | } | 648 | } |
639 | 649 | ||
640 | /** | 650 | /** |
641 | * zfcp_scsi_scan - Register LUN with SCSI midlayer | ||
642 | * @unit: The LUN/unit to register | ||
643 | */ | ||
644 | void zfcp_scsi_scan(struct zfcp_unit *unit) | ||
645 | { | ||
646 | struct fc_rport *rport = unit->port->rport; | ||
647 | |||
648 | if (rport && rport->port_state == FC_PORTSTATE_ONLINE) | ||
649 | scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, | ||
650 | scsilun_to_int((struct scsi_lun *) | ||
651 | &unit->fcp_lun), 0); | ||
652 | } | ||
653 | |||
654 | void zfcp_scsi_scan_work(struct work_struct *work) | ||
655 | { | ||
656 | struct zfcp_unit *unit = container_of(work, struct zfcp_unit, | ||
657 | scsi_work); | ||
658 | |||
659 | zfcp_scsi_scan(unit); | ||
660 | put_device(&unit->dev); | ||
661 | } | ||
662 | |||
663 | /** | ||
664 | * zfcp_scsi_set_prot - Configure DIF/DIX support in scsi_host | 651 | * zfcp_scsi_set_prot - Configure DIF/DIX support in scsi_host |
665 | * @adapter: The adapter where to configure DIF/DIX for the SCSI host | 652 | * @adapter: The adapter where to configure DIF/DIX for the SCSI host |
666 | */ | 653 | */ |
@@ -681,6 +668,7 @@ void zfcp_scsi_set_prot(struct zfcp_adapter *adapter) | |||
681 | adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) { | 668 | adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) { |
682 | mask |= SHOST_DIX_TYPE1_PROTECTION; | 669 | mask |= SHOST_DIX_TYPE1_PROTECTION; |
683 | scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP); | 670 | scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP); |
671 | shost->sg_prot_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2; | ||
684 | shost->sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2; | 672 | shost->sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2; |
685 | shost->max_sectors = ZFCP_QDIO_MAX_SBALES_PER_REQ * 8 / 2; | 673 | shost->max_sectors = ZFCP_QDIO_MAX_SBALES_PER_REQ * 8 / 2; |
686 | } | 674 | } |
@@ -732,34 +720,8 @@ struct fc_function_template zfcp_transport_functions = { | |||
732 | /* no functions registered for following dynamic attributes but | 720 | /* no functions registered for following dynamic attributes but |
733 | directly set by LLDD */ | 721 | directly set by LLDD */ |
734 | .show_host_port_type = 1, | 722 | .show_host_port_type = 1, |
723 | .show_host_symbolic_name = 1, | ||
735 | .show_host_speed = 1, | 724 | .show_host_speed = 1, |
736 | .show_host_port_id = 1, | 725 | .show_host_port_id = 1, |
737 | .disable_target_scan = 1, | ||
738 | .dd_bsg_size = sizeof(struct zfcp_fsf_ct_els), | 726 | .dd_bsg_size = sizeof(struct zfcp_fsf_ct_els), |
739 | }; | 727 | }; |
740 | |||
741 | struct zfcp_data zfcp_data = { | ||
742 | .scsi_host_template = { | ||
743 | .name = "zfcp", | ||
744 | .module = THIS_MODULE, | ||
745 | .proc_name = "zfcp", | ||
746 | .change_queue_depth = zfcp_scsi_change_queue_depth, | ||
747 | .slave_alloc = zfcp_scsi_slave_alloc, | ||
748 | .slave_configure = zfcp_scsi_slave_configure, | ||
749 | .slave_destroy = zfcp_scsi_slave_destroy, | ||
750 | .queuecommand = zfcp_scsi_queuecommand, | ||
751 | .eh_abort_handler = zfcp_scsi_eh_abort_handler, | ||
752 | .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, | ||
753 | .eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler, | ||
754 | .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, | ||
755 | .can_queue = 4096, | ||
756 | .this_id = -1, | ||
757 | .sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ, | ||
758 | .cmd_per_lun = 1, | ||
759 | .use_clustering = 1, | ||
760 | .sdev_attrs = zfcp_sysfs_sdev_attrs, | ||
761 | .max_sectors = (ZFCP_QDIO_MAX_SBALES_PER_REQ * 8), | ||
762 | .dma_boundary = ZFCP_QDIO_SBALE_LEN - 1, | ||
763 | .shost_attrs = zfcp_sysfs_shost_attrs, | ||
764 | }, | ||
765 | }; | ||
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index b4561c86e230..cdc4ff78a7ba 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c | |||
@@ -68,63 +68,95 @@ ZFCP_DEFINE_ATTR(zfcp_port, port, access_denied, "%d\n", | |||
68 | ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0); | 68 | ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0); |
69 | 69 | ||
70 | ZFCP_DEFINE_ATTR(zfcp_unit, unit, status, "0x%08x\n", | 70 | ZFCP_DEFINE_ATTR(zfcp_unit, unit, status, "0x%08x\n", |
71 | atomic_read(&unit->status)); | 71 | zfcp_unit_sdev_status(unit)); |
72 | ZFCP_DEFINE_ATTR(zfcp_unit, unit, in_recovery, "%d\n", | 72 | ZFCP_DEFINE_ATTR(zfcp_unit, unit, in_recovery, "%d\n", |
73 | (atomic_read(&unit->status) & | 73 | (zfcp_unit_sdev_status(unit) & |
74 | ZFCP_STATUS_COMMON_ERP_INUSE) != 0); | 74 | ZFCP_STATUS_COMMON_ERP_INUSE) != 0); |
75 | ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_denied, "%d\n", | 75 | ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_denied, "%d\n", |
76 | (atomic_read(&unit->status) & | 76 | (zfcp_unit_sdev_status(unit) & |
77 | ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0); | 77 | ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0); |
78 | ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_shared, "%d\n", | 78 | ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_shared, "%d\n", |
79 | (atomic_read(&unit->status) & | 79 | (zfcp_unit_sdev_status(unit) & |
80 | ZFCP_STATUS_UNIT_SHARED) != 0); | 80 | ZFCP_STATUS_LUN_SHARED) != 0); |
81 | ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_readonly, "%d\n", | 81 | ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_readonly, "%d\n", |
82 | (atomic_read(&unit->status) & | 82 | (zfcp_unit_sdev_status(unit) & |
83 | ZFCP_STATUS_UNIT_READONLY) != 0); | 83 | ZFCP_STATUS_LUN_READONLY) != 0); |
84 | 84 | ||
85 | #define ZFCP_SYSFS_FAILED(_feat_def, _feat, _adapter, _mod_id, _reopen_id) \ | 85 | static ssize_t zfcp_sysfs_port_failed_show(struct device *dev, |
86 | static ssize_t zfcp_sysfs_##_feat##_failed_show(struct device *dev, \ | 86 | struct device_attribute *attr, |
87 | struct device_attribute *attr, \ | 87 | char *buf) |
88 | char *buf) \ | 88 | { |
89 | { \ | 89 | struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); |
90 | struct _feat_def *_feat = container_of(dev, struct _feat_def, dev); \ | 90 | |
91 | \ | 91 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) |
92 | if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED) \ | 92 | return sprintf(buf, "1\n"); |
93 | return sprintf(buf, "1\n"); \ | 93 | |
94 | else \ | 94 | return sprintf(buf, "0\n"); |
95 | return sprintf(buf, "0\n"); \ | 95 | } |
96 | } \ | 96 | |
97 | static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \ | 97 | static ssize_t zfcp_sysfs_port_failed_store(struct device *dev, |
98 | struct device_attribute *attr,\ | 98 | struct device_attribute *attr, |
99 | const char *buf, size_t count)\ | 99 | const char *buf, size_t count) |
100 | { \ | 100 | { |
101 | struct _feat_def *_feat = container_of(dev, struct _feat_def, dev); \ | 101 | struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); |
102 | unsigned long val; \ | 102 | unsigned long val; |
103 | int retval = 0; \ | 103 | |
104 | \ | 104 | if (strict_strtoul(buf, 0, &val) || val != 0) |
105 | if (!(_feat && get_device(&_feat->dev))) \ | 105 | return -EINVAL; |
106 | return -EBUSY; \ | 106 | |
107 | \ | 107 | zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_RUNNING); |
108 | if (strict_strtoul(buf, 0, &val) || val != 0) { \ | 108 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, "sypfai2"); |
109 | retval = -EINVAL; \ | 109 | zfcp_erp_wait(port->adapter); |
110 | goto out; \ | ||
111 | } \ | ||
112 | \ | ||
113 | zfcp_erp_modify_##_feat##_status(_feat, _mod_id, NULL, \ | ||
114 | ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);\ | ||
115 | zfcp_erp_##_feat##_reopen(_feat, ZFCP_STATUS_COMMON_ERP_FAILED, \ | ||
116 | _reopen_id, NULL); \ | ||
117 | zfcp_erp_wait(_adapter); \ | ||
118 | out: \ | ||
119 | put_device(&_feat->dev); \ | ||
120 | return retval ? retval : (ssize_t) count; \ | ||
121 | } \ | ||
122 | static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \ | ||
123 | zfcp_sysfs_##_feat##_failed_show, \ | ||
124 | zfcp_sysfs_##_feat##_failed_store); | ||
125 | 110 | ||
126 | ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2"); | 111 | return count; |
127 | ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2"); | 112 | } |
113 | static ZFCP_DEV_ATTR(port, failed, S_IWUSR | S_IRUGO, | ||
114 | zfcp_sysfs_port_failed_show, | ||
115 | zfcp_sysfs_port_failed_store); | ||
116 | |||
117 | static ssize_t zfcp_sysfs_unit_failed_show(struct device *dev, | ||
118 | struct device_attribute *attr, | ||
119 | char *buf) | ||
120 | { | ||
121 | struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); | ||
122 | struct scsi_device *sdev; | ||
123 | unsigned int status, failed = 1; | ||
124 | |||
125 | sdev = zfcp_unit_sdev(unit); | ||
126 | if (sdev) { | ||
127 | status = atomic_read(&sdev_to_zfcp(sdev)->status); | ||
128 | failed = status & ZFCP_STATUS_COMMON_ERP_FAILED ? 1 : 0; | ||
129 | scsi_device_put(sdev); | ||
130 | } | ||
131 | |||
132 | return sprintf(buf, "%d\n", failed); | ||
133 | } | ||
134 | |||
135 | static ssize_t zfcp_sysfs_unit_failed_store(struct device *dev, | ||
136 | struct device_attribute *attr, | ||
137 | const char *buf, size_t count) | ||
138 | { | ||
139 | struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); | ||
140 | unsigned long val; | ||
141 | struct scsi_device *sdev; | ||
142 | |||
143 | if (strict_strtoul(buf, 0, &val) || val != 0) | ||
144 | return -EINVAL; | ||
145 | |||
146 | sdev = zfcp_unit_sdev(unit); | ||
147 | if (sdev) { | ||
148 | zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING); | ||
149 | zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED, | ||
150 | "syufai2"); | ||
151 | zfcp_erp_wait(unit->port->adapter); | ||
152 | } else | ||
153 | zfcp_unit_scsi_scan(unit); | ||
154 | |||
155 | return count; | ||
156 | } | ||
157 | static ZFCP_DEV_ATTR(unit, failed, S_IWUSR | S_IRUGO, | ||
158 | zfcp_sysfs_unit_failed_show, | ||
159 | zfcp_sysfs_unit_failed_store); | ||
128 | 160 | ||
129 | static ssize_t zfcp_sysfs_adapter_failed_show(struct device *dev, | 161 | static ssize_t zfcp_sysfs_adapter_failed_show(struct device *dev, |
130 | struct device_attribute *attr, | 162 | struct device_attribute *attr, |
@@ -163,10 +195,9 @@ static ssize_t zfcp_sysfs_adapter_failed_store(struct device *dev, | |||
163 | goto out; | 195 | goto out; |
164 | } | 196 | } |
165 | 197 | ||
166 | zfcp_erp_modify_adapter_status(adapter, "syafai1", NULL, | 198 | zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); |
167 | ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); | ||
168 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | 199 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
169 | "syafai2", NULL); | 200 | "syafai2"); |
170 | zfcp_erp_wait(adapter); | 201 | zfcp_erp_wait(adapter); |
171 | out: | 202 | out: |
172 | zfcp_ccw_adapter_put(adapter); | 203 | zfcp_ccw_adapter_put(adapter); |
@@ -224,7 +255,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, | |||
224 | 255 | ||
225 | put_device(&port->dev); | 256 | put_device(&port->dev); |
226 | 257 | ||
227 | zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL); | 258 | zfcp_erp_port_shutdown(port, 0, "syprs_1"); |
228 | zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs); | 259 | zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs); |
229 | out: | 260 | out: |
230 | zfcp_ccw_adapter_put(adapter); | 261 | zfcp_ccw_adapter_put(adapter); |
@@ -257,28 +288,15 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, | |||
257 | const char *buf, size_t count) | 288 | const char *buf, size_t count) |
258 | { | 289 | { |
259 | struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); | 290 | struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); |
260 | struct zfcp_unit *unit; | ||
261 | u64 fcp_lun; | 291 | u64 fcp_lun; |
262 | int retval = -EINVAL; | ||
263 | |||
264 | if (!(port && get_device(&port->dev))) | ||
265 | return -EBUSY; | ||
266 | 292 | ||
267 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) | 293 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) |
268 | goto out; | 294 | return -EINVAL; |
269 | 295 | ||
270 | unit = zfcp_unit_enqueue(port, fcp_lun); | 296 | if (zfcp_unit_add(port, fcp_lun)) |
271 | if (IS_ERR(unit)) | 297 | return -EINVAL; |
272 | goto out; | ||
273 | else | ||
274 | retval = 0; | ||
275 | 298 | ||
276 | zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL); | 299 | return count; |
277 | zfcp_erp_wait(unit->port->adapter); | ||
278 | zfcp_scsi_scan(unit); | ||
279 | out: | ||
280 | put_device(&port->dev); | ||
281 | return retval ? retval : (ssize_t) count; | ||
282 | } | 300 | } |
283 | static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store); | 301 | static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store); |
284 | 302 | ||
@@ -287,42 +305,15 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, | |||
287 | const char *buf, size_t count) | 305 | const char *buf, size_t count) |
288 | { | 306 | { |
289 | struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); | 307 | struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); |
290 | struct zfcp_unit *unit; | ||
291 | u64 fcp_lun; | 308 | u64 fcp_lun; |
292 | int retval = -EINVAL; | ||
293 | struct scsi_device *sdev; | ||
294 | |||
295 | if (!(port && get_device(&port->dev))) | ||
296 | return -EBUSY; | ||
297 | 309 | ||
298 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) | 310 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) |
299 | goto out; | 311 | return -EINVAL; |
300 | 312 | ||
301 | unit = zfcp_get_unit_by_lun(port, fcp_lun); | 313 | if (zfcp_unit_remove(port, fcp_lun)) |
302 | if (!unit) | 314 | return -EINVAL; |
303 | goto out; | ||
304 | else | ||
305 | retval = 0; | ||
306 | |||
307 | sdev = scsi_device_lookup(port->adapter->scsi_host, 0, | ||
308 | port->starget_id, | ||
309 | scsilun_to_int((struct scsi_lun *)&fcp_lun)); | ||
310 | if (sdev) { | ||
311 | scsi_remove_device(sdev); | ||
312 | scsi_device_put(sdev); | ||
313 | } | ||
314 | |||
315 | write_lock_irq(&port->unit_list_lock); | ||
316 | list_del(&unit->list); | ||
317 | write_unlock_irq(&port->unit_list_lock); | ||
318 | |||
319 | put_device(&unit->dev); | ||
320 | 315 | ||
321 | zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); | 316 | return count; |
322 | zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs); | ||
323 | out: | ||
324 | put_device(&port->dev); | ||
325 | return retval ? retval : (ssize_t) count; | ||
326 | } | 317 | } |
327 | static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); | 318 | static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); |
328 | 319 | ||
@@ -363,9 +354,9 @@ zfcp_sysfs_unit_##_name##_latency_show(struct device *dev, \ | |||
363 | struct device_attribute *attr, \ | 354 | struct device_attribute *attr, \ |
364 | char *buf) { \ | 355 | char *buf) { \ |
365 | struct scsi_device *sdev = to_scsi_device(dev); \ | 356 | struct scsi_device *sdev = to_scsi_device(dev); \ |
366 | struct zfcp_unit *unit = sdev->hostdata; \ | 357 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); \ |
367 | struct zfcp_latencies *lat = &unit->latencies; \ | 358 | struct zfcp_latencies *lat = &zfcp_sdev->latencies; \ |
368 | struct zfcp_adapter *adapter = unit->port->adapter; \ | 359 | struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; \ |
369 | unsigned long long fsum, fmin, fmax, csum, cmin, cmax, cc; \ | 360 | unsigned long long fsum, fmin, fmax, csum, cmin, cmax, cc; \ |
370 | \ | 361 | \ |
371 | spin_lock_bh(&lat->lock); \ | 362 | spin_lock_bh(&lat->lock); \ |
@@ -394,8 +385,8 @@ zfcp_sysfs_unit_##_name##_latency_store(struct device *dev, \ | |||
394 | const char *buf, size_t count) \ | 385 | const char *buf, size_t count) \ |
395 | { \ | 386 | { \ |
396 | struct scsi_device *sdev = to_scsi_device(dev); \ | 387 | struct scsi_device *sdev = to_scsi_device(dev); \ |
397 | struct zfcp_unit *unit = sdev->hostdata; \ | 388 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); \ |
398 | struct zfcp_latencies *lat = &unit->latencies; \ | 389 | struct zfcp_latencies *lat = &zfcp_sdev->latencies; \ |
399 | unsigned long flags; \ | 390 | unsigned long flags; \ |
400 | \ | 391 | \ |
401 | spin_lock_irqsave(&lat->lock, flags); \ | 392 | spin_lock_irqsave(&lat->lock, flags); \ |
@@ -423,19 +414,28 @@ static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \ | |||
423 | struct device_attribute *attr,\ | 414 | struct device_attribute *attr,\ |
424 | char *buf) \ | 415 | char *buf) \ |
425 | { \ | 416 | { \ |
426 | struct scsi_device *sdev = to_scsi_device(dev); \ | 417 | struct scsi_device *sdev = to_scsi_device(dev); \ |
427 | struct zfcp_unit *unit = sdev->hostdata; \ | 418 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); \ |
419 | struct zfcp_port *port = zfcp_sdev->port; \ | ||
428 | \ | 420 | \ |
429 | return sprintf(buf, _format, _value); \ | 421 | return sprintf(buf, _format, _value); \ |
430 | } \ | 422 | } \ |
431 | static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL); | 423 | static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL); |
432 | 424 | ||
433 | ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n", | 425 | ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n", |
434 | dev_name(&unit->port->adapter->ccw_device->dev)); | 426 | dev_name(&port->adapter->ccw_device->dev)); |
435 | ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", | 427 | ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", |
436 | (unsigned long long) unit->port->wwpn); | 428 | (unsigned long long) port->wwpn); |
437 | ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n", | 429 | |
438 | (unsigned long long) unit->fcp_lun); | 430 | static ssize_t zfcp_sysfs_scsi_fcp_lun_show(struct device *dev, |
431 | struct device_attribute *attr, | ||
432 | char *buf) | ||
433 | { | ||
434 | struct scsi_device *sdev = to_scsi_device(dev); | ||
435 | |||
436 | return sprintf(buf, "0x%016llx\n", zfcp_scsi_dev_lun(sdev)); | ||
437 | } | ||
438 | static DEVICE_ATTR(fcp_lun, S_IRUGO, zfcp_sysfs_scsi_fcp_lun_show, NULL); | ||
439 | 439 | ||
440 | struct device_attribute *zfcp_sysfs_sdev_attrs[] = { | 440 | struct device_attribute *zfcp_sysfs_sdev_attrs[] = { |
441 | &dev_attr_fcp_lun, | 441 | &dev_attr_fcp_lun, |
diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c new file mode 100644 index 000000000000..20796ebc33ce --- /dev/null +++ b/drivers/s390/scsi/zfcp_unit.c | |||
@@ -0,0 +1,244 @@ | |||
1 | /* | ||
2 | * zfcp device driver | ||
3 | * | ||
4 | * Tracking of manually configured LUNs and helper functions to | ||
5 | * register the LUNs with the SCSI midlayer. | ||
6 | * | ||
7 | * Copyright IBM Corporation 2010 | ||
8 | */ | ||
9 | |||
10 | #include "zfcp_def.h" | ||
11 | #include "zfcp_ext.h" | ||
12 | |||
13 | /** | ||
14 | * zfcp_unit_scsi_scan - Register LUN with SCSI midlayer | ||
15 | * @unit: The zfcp LUN/unit to register | ||
16 | * | ||
17 | * When the SCSI midlayer is not allowed to automatically scan and | ||
18 | * attach SCSI devices, zfcp has to register the single devices with | ||
19 | * the SCSI midlayer. | ||
20 | */ | ||
21 | void zfcp_unit_scsi_scan(struct zfcp_unit *unit) | ||
22 | { | ||
23 | struct fc_rport *rport = unit->port->rport; | ||
24 | unsigned int lun; | ||
25 | |||
26 | lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun); | ||
27 | |||
28 | if (rport && rport->port_state == FC_PORTSTATE_ONLINE) | ||
29 | scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, 1); | ||
30 | } | ||
31 | |||
32 | static void zfcp_unit_scsi_scan_work(struct work_struct *work) | ||
33 | { | ||
34 | struct zfcp_unit *unit = container_of(work, struct zfcp_unit, | ||
35 | scsi_work); | ||
36 | |||
37 | zfcp_unit_scsi_scan(unit); | ||
38 | put_device(&unit->dev); | ||
39 | } | ||
40 | |||
41 | /** | ||
42 | * zfcp_unit_queue_scsi_scan - Register configured units on port | ||
43 | * @port: The zfcp_port where to register units | ||
44 | * | ||
45 | * After opening a port, all units configured on this port have to be | ||
46 | * registered with the SCSI midlayer. This function should be called | ||
47 | * after calling fc_remote_port_add, so that the fc_rport is already | ||
48 | * ONLINE and the call to scsi_scan_target runs the same way as the | ||
49 | * call in the FC transport class. | ||
50 | */ | ||
51 | void zfcp_unit_queue_scsi_scan(struct zfcp_port *port) | ||
52 | { | ||
53 | struct zfcp_unit *unit; | ||
54 | |||
55 | read_lock_irq(&port->unit_list_lock); | ||
56 | list_for_each_entry(unit, &port->unit_list, list) { | ||
57 | get_device(&unit->dev); | ||
58 | if (scsi_queue_work(port->adapter->scsi_host, | ||
59 | &unit->scsi_work) <= 0) | ||
60 | put_device(&unit->dev); | ||
61 | } | ||
62 | read_unlock_irq(&port->unit_list_lock); | ||
63 | } | ||
64 | |||
65 | static struct zfcp_unit *_zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun) | ||
66 | { | ||
67 | struct zfcp_unit *unit; | ||
68 | |||
69 | list_for_each_entry(unit, &port->unit_list, list) | ||
70 | if (unit->fcp_lun == fcp_lun) { | ||
71 | get_device(&unit->dev); | ||
72 | return unit; | ||
73 | } | ||
74 | |||
75 | return NULL; | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * zfcp_unit_find - Find and return zfcp_unit with specified FCP LUN | ||
80 | * @port: zfcp_port where to look for the unit | ||
81 | * @fcp_lun: 64 Bit FCP LUN used to identify the zfcp_unit | ||
82 | * | ||
83 | * If zfcp_unit is found, a reference is acquired that has to be | ||
84 | * released later. | ||
85 | * | ||
86 | * Returns: Pointer to the zfcp_unit, or NULL if there is no zfcp_unit | ||
87 | * with the specified FCP LUN. | ||
88 | */ | ||
89 | struct zfcp_unit *zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun) | ||
90 | { | ||
91 | struct zfcp_unit *unit; | ||
92 | |||
93 | read_lock_irq(&port->unit_list_lock); | ||
94 | unit = _zfcp_unit_find(port, fcp_lun); | ||
95 | read_unlock_irq(&port->unit_list_lock); | ||
96 | return unit; | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * zfcp_unit_release - Drop reference to zfcp_port and free memory of zfcp_unit. | ||
101 | * @dev: pointer to device in zfcp_unit | ||
102 | */ | ||
103 | static void zfcp_unit_release(struct device *dev) | ||
104 | { | ||
105 | struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); | ||
106 | |||
107 | put_device(&unit->port->dev); | ||
108 | kfree(unit); | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * zfcp_unit_enqueue - enqueue unit to unit list of a port. | ||
113 | * @port: pointer to port where unit is added | ||
114 | * @fcp_lun: FCP LUN of unit to be enqueued | ||
115 | * Returns: 0 success | ||
116 | * | ||
117 | * Sets up some unit internal structures and creates sysfs entry. | ||
118 | */ | ||
119 | int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) | ||
120 | { | ||
121 | struct zfcp_unit *unit; | ||
122 | |||
123 | unit = zfcp_unit_find(port, fcp_lun); | ||
124 | if (unit) { | ||
125 | put_device(&unit->dev); | ||
126 | return -EEXIST; | ||
127 | } | ||
128 | |||
129 | unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); | ||
130 | if (!unit) | ||
131 | return -ENOMEM; | ||
132 | |||
133 | unit->port = port; | ||
134 | unit->fcp_lun = fcp_lun; | ||
135 | unit->dev.parent = &port->dev; | ||
136 | unit->dev.release = zfcp_unit_release; | ||
137 | INIT_WORK(&unit->scsi_work, zfcp_unit_scsi_scan_work); | ||
138 | |||
139 | if (dev_set_name(&unit->dev, "0x%016llx", | ||
140 | (unsigned long long) fcp_lun)) { | ||
141 | kfree(unit); | ||
142 | return -ENOMEM; | ||
143 | } | ||
144 | |||
145 | get_device(&port->dev); | ||
146 | |||
147 | if (device_register(&unit->dev)) { | ||
148 | put_device(&unit->dev); | ||
149 | return -ENOMEM; | ||
150 | } | ||
151 | |||
152 | if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) { | ||
153 | device_unregister(&unit->dev); | ||
154 | return -EINVAL; | ||
155 | } | ||
156 | |||
157 | write_lock_irq(&port->unit_list_lock); | ||
158 | list_add_tail(&unit->list, &port->unit_list); | ||
159 | write_unlock_irq(&port->unit_list_lock); | ||
160 | |||
161 | zfcp_unit_scsi_scan(unit); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * zfcp_unit_sdev - Return SCSI device for zfcp_unit | ||
168 | * @unit: The zfcp_unit where to get the SCSI device for | ||
169 | * | ||
170 | * Returns: scsi_device pointer on success, NULL if there is no SCSI | ||
171 | * device for this zfcp_unit | ||
172 | * | ||
173 | * On success, the caller also holds a reference to the SCSI device | ||
174 | * that must be released with scsi_device_put. | ||
175 | */ | ||
176 | struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit) | ||
177 | { | ||
178 | struct Scsi_Host *shost; | ||
179 | struct zfcp_port *port; | ||
180 | unsigned int lun; | ||
181 | |||
182 | lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun); | ||
183 | port = unit->port; | ||
184 | shost = port->adapter->scsi_host; | ||
185 | return scsi_device_lookup(shost, 0, port->starget_id, lun); | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * zfcp_unit_sdev_status - Return zfcp LUN status for SCSI device | ||
190 | * @unit: The unit to lookup the SCSI device for | ||
191 | * | ||
192 | * Returns the zfcp LUN status field of the SCSI device if the SCSI device | ||
193 | * for the zfcp_unit exists, 0 otherwise. | ||
194 | */ | ||
195 | unsigned int zfcp_unit_sdev_status(struct zfcp_unit *unit) | ||
196 | { | ||
197 | unsigned int status = 0; | ||
198 | struct scsi_device *sdev; | ||
199 | struct zfcp_scsi_dev *zfcp_sdev; | ||
200 | |||
201 | sdev = zfcp_unit_sdev(unit); | ||
202 | if (sdev) { | ||
203 | zfcp_sdev = sdev_to_zfcp(sdev); | ||
204 | status = atomic_read(&zfcp_sdev->status); | ||
205 | scsi_device_put(sdev); | ||
206 | } | ||
207 | |||
208 | return status; | ||
209 | } | ||
210 | |||
211 | /** | ||
212 | * zfcp_unit_remove - Remove entry from list of configured units | ||
213 | * @port: The port where to remove the unit from the configuration | ||
214 | * @fcp_lun: The 64 bit LUN of the unit to remove | ||
215 | * | ||
216 | * Returns: -EINVAL if a unit with the specified LUN does not exist, | ||
217 | * 0 on success. | ||
218 | */ | ||
219 | int zfcp_unit_remove(struct zfcp_port *port, u64 fcp_lun) | ||
220 | { | ||
221 | struct zfcp_unit *unit; | ||
222 | struct scsi_device *sdev; | ||
223 | |||
224 | write_lock_irq(&port->unit_list_lock); | ||
225 | unit = _zfcp_unit_find(port, fcp_lun); | ||
226 | if (unit) | ||
227 | list_del(&unit->list); | ||
228 | write_unlock_irq(&port->unit_list_lock); | ||
229 | |||
230 | if (!unit) | ||
231 | return -EINVAL; | ||
232 | |||
233 | sdev = zfcp_unit_sdev(unit); | ||
234 | if (sdev) { | ||
235 | scsi_remove_device(sdev); | ||
236 | scsi_device_put(sdev); | ||
237 | } | ||
238 | |||
239 | put_device(&unit->dev); | ||
240 | |||
241 | zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs); | ||
242 | |||
243 | return 0; | ||
244 | } | ||