diff options
50 files changed, 2107 insertions, 1112 deletions
diff --git a/Documentation/scsi/scsi_fc_transport.txt b/Documentation/scsi/scsi_fc_transport.txt index 75143f0c23b6..38d324d62b25 100644 --- a/Documentation/scsi/scsi_fc_transport.txt +++ b/Documentation/scsi/scsi_fc_transport.txt | |||
@@ -436,6 +436,42 @@ Other: | |||
436 | was updated to remove all vports for the fc_host as well. | 436 | was updated to remove all vports for the fc_host as well. |
437 | 437 | ||
438 | 438 | ||
439 | Transport supplied functions | ||
440 | ---------------------------- | ||
441 | |||
442 | The following functions are supplied by the FC-transport for use by LLDs. | ||
443 | |||
444 | fc_vport_create - create a vport | ||
445 | fc_vport_terminate - detach and remove a vport | ||
446 | |||
447 | Details: | ||
448 | |||
449 | /** | ||
450 | * fc_vport_create - Admin App or LLDD requests creation of a vport | ||
451 | * @shost: scsi host the virtual port is connected to. | ||
452 | * @ids: The world wide names, FC4 port roles, etc for | ||
453 | * the virtual port. | ||
454 | * | ||
455 | * Notes: | ||
456 | * This routine assumes no locks are held on entry. | ||
457 | */ | ||
458 | struct fc_vport * | ||
459 | fc_vport_create(struct Scsi_Host *shost, struct fc_vport_identifiers *ids) | ||
460 | |||
461 | /** | ||
462 | * fc_vport_terminate - Admin App or LLDD requests termination of a vport | ||
463 | * @vport: fc_vport to be terminated | ||
464 | * | ||
465 | * Calls the LLDD vport_delete() function, then deallocates and removes | ||
466 | * the vport from the shost and object tree. | ||
467 | * | ||
468 | * Notes: | ||
469 | * This routine assumes no locks are held on entry. | ||
470 | */ | ||
471 | int | ||
472 | fc_vport_terminate(struct fc_vport *vport) | ||
473 | |||
474 | |||
439 | Credits | 475 | Credits |
440 | ======= | 476 | ======= |
441 | The following people have contributed to this document: | 477 | The following people have contributed to this document: |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 97156b689e82..efacee0404a0 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/blkdev.h> | 29 | #include <linux/blkdev.h> |
30 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
31 | #include <linux/scatterlist.h> | 31 | #include <linux/scatterlist.h> |
32 | #include <linux/string_helpers.h> | ||
32 | 33 | ||
33 | #include <linux/mmc/card.h> | 34 | #include <linux/mmc/card.h> |
34 | #include <linux/mmc/host.h> | 35 | #include <linux/mmc/host.h> |
@@ -532,6 +533,8 @@ static int mmc_blk_probe(struct mmc_card *card) | |||
532 | struct mmc_blk_data *md; | 533 | struct mmc_blk_data *md; |
533 | int err; | 534 | int err; |
534 | 535 | ||
536 | char cap_str[10]; | ||
537 | |||
535 | /* | 538 | /* |
536 | * Check that the card supports the command class(es) we need. | 539 | * Check that the card supports the command class(es) we need. |
537 | */ | 540 | */ |
@@ -546,10 +549,11 @@ static int mmc_blk_probe(struct mmc_card *card) | |||
546 | if (err) | 549 | if (err) |
547 | goto out; | 550 | goto out; |
548 | 551 | ||
549 | printk(KERN_INFO "%s: %s %s %lluKiB %s\n", | 552 | string_get_size(get_capacity(md->disk) << 9, STRING_UNITS_2, |
553 | cap_str, sizeof(cap_str)); | ||
554 | printk(KERN_INFO "%s: %s %s %s %s\n", | ||
550 | md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), | 555 | md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), |
551 | (unsigned long long)(get_capacity(md->disk) >> 1), | 556 | cap_str, md->read_only ? "(ro)" : ""); |
552 | md->read_only ? "(ro)" : ""); | ||
553 | 557 | ||
554 | mmc_set_drvdata(card, md); | 558 | mmc_set_drvdata(card, md); |
555 | add_disk(md->disk); | 559 | add_disk(md->disk); |
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 90abfd06ed55..24255e42dc30 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -88,11 +88,13 @@ static int __init zfcp_device_setup(char *devstr) | |||
88 | strncpy(zfcp_data.init_busid, token, BUS_ID_SIZE); | 88 | strncpy(zfcp_data.init_busid, token, BUS_ID_SIZE); |
89 | 89 | ||
90 | token = strsep(&str, ","); | 90 | token = strsep(&str, ","); |
91 | if (!token || strict_strtoull(token, 0, &zfcp_data.init_wwpn)) | 91 | if (!token || strict_strtoull(token, 0, |
92 | (unsigned long long *) &zfcp_data.init_wwpn)) | ||
92 | goto err_out; | 93 | goto err_out; |
93 | 94 | ||
94 | token = strsep(&str, ","); | 95 | token = strsep(&str, ","); |
95 | if (!token || strict_strtoull(token, 0, &zfcp_data.init_fcp_lun)) | 96 | if (!token || strict_strtoull(token, 0, |
97 | (unsigned long long *) &zfcp_data.init_fcp_lun)) | ||
96 | goto err_out; | 98 | goto err_out; |
97 | 99 | ||
98 | kfree(str); | 100 | kfree(str); |
@@ -100,24 +102,10 @@ static int __init zfcp_device_setup(char *devstr) | |||
100 | 102 | ||
101 | err_out: | 103 | err_out: |
102 | kfree(str); | 104 | kfree(str); |
103 | pr_err("zfcp: Parse error for device parameter string %s, " | 105 | pr_err("zfcp: %s is not a valid SCSI device\n", devstr); |
104 | "device not attached.\n", devstr); | ||
105 | return 0; | 106 | return 0; |
106 | } | 107 | } |
107 | 108 | ||
108 | static struct zfcp_adapter *zfcp_get_adapter_by_busid(char *bus_id) | ||
109 | { | ||
110 | struct zfcp_adapter *adapter; | ||
111 | |||
112 | list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list) | ||
113 | if ((strncmp(bus_id, adapter->ccw_device->dev.bus_id, | ||
114 | BUS_ID_SIZE) == 0) && | ||
115 | !(atomic_read(&adapter->status) & | ||
116 | ZFCP_STATUS_COMMON_REMOVE)) | ||
117 | return adapter; | ||
118 | return NULL; | ||
119 | } | ||
120 | |||
121 | static void __init zfcp_init_device_configure(void) | 109 | static void __init zfcp_init_device_configure(void) |
122 | { | 110 | { |
123 | struct zfcp_adapter *adapter; | 111 | struct zfcp_adapter *adapter; |
@@ -141,7 +129,12 @@ static void __init zfcp_init_device_configure(void) | |||
141 | goto out_unit; | 129 | goto out_unit; |
142 | up(&zfcp_data.config_sema); | 130 | up(&zfcp_data.config_sema); |
143 | ccw_device_set_online(adapter->ccw_device); | 131 | ccw_device_set_online(adapter->ccw_device); |
132 | |||
144 | zfcp_erp_wait(adapter); | 133 | zfcp_erp_wait(adapter); |
134 | wait_event(adapter->erp_done_wqh, | ||
135 | !(atomic_read(&unit->status) & | ||
136 | ZFCP_STATUS_UNIT_SCSI_WORK_PENDING)); | ||
137 | |||
145 | down(&zfcp_data.config_sema); | 138 | down(&zfcp_data.config_sema); |
146 | zfcp_unit_put(unit); | 139 | zfcp_unit_put(unit); |
147 | out_unit: | 140 | out_unit: |
@@ -180,9 +173,9 @@ static int __init zfcp_module_init(void) | |||
180 | if (!zfcp_data.gid_pn_cache) | 173 | if (!zfcp_data.gid_pn_cache) |
181 | goto out_gid_cache; | 174 | goto out_gid_cache; |
182 | 175 | ||
183 | INIT_LIST_HEAD(&zfcp_data.adapter_list_head); | 176 | zfcp_data.work_queue = create_singlethread_workqueue("zfcp_wq"); |
184 | INIT_LIST_HEAD(&zfcp_data.adapter_remove_lh); | ||
185 | 177 | ||
178 | INIT_LIST_HEAD(&zfcp_data.adapter_list_head); | ||
186 | sema_init(&zfcp_data.config_sema, 1); | 179 | sema_init(&zfcp_data.config_sema, 1); |
187 | rwlock_init(&zfcp_data.config_lock); | 180 | rwlock_init(&zfcp_data.config_lock); |
188 | 181 | ||
@@ -193,13 +186,14 @@ static int __init zfcp_module_init(void) | |||
193 | 186 | ||
194 | retval = misc_register(&zfcp_cfdc_misc); | 187 | retval = misc_register(&zfcp_cfdc_misc); |
195 | if (retval) { | 188 | if (retval) { |
196 | pr_err("zfcp: registration of misc device zfcp_cfdc failed\n"); | 189 | pr_err("zfcp: Registering the misc device zfcp_cfdc failed\n"); |
197 | goto out_misc; | 190 | goto out_misc; |
198 | } | 191 | } |
199 | 192 | ||
200 | retval = zfcp_ccw_register(); | 193 | retval = zfcp_ccw_register(); |
201 | if (retval) { | 194 | if (retval) { |
202 | pr_err("zfcp: Registration with common I/O layer failed.\n"); | 195 | pr_err("zfcp: The zfcp device driver could not register with " |
196 | "the common I/O layer\n"); | ||
203 | goto out_ccw_register; | 197 | goto out_ccw_register; |
204 | } | 198 | } |
205 | 199 | ||
@@ -231,8 +225,7 @@ module_init(zfcp_module_init); | |||
231 | * | 225 | * |
232 | * Returns: pointer to zfcp_unit or NULL | 226 | * Returns: pointer to zfcp_unit or NULL |
233 | */ | 227 | */ |
234 | struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, | 228 | struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun) |
235 | fcp_lun_t fcp_lun) | ||
236 | { | 229 | { |
237 | struct zfcp_unit *unit; | 230 | struct zfcp_unit *unit; |
238 | 231 | ||
@@ -251,7 +244,7 @@ struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, | |||
251 | * Returns: pointer to zfcp_port or NULL | 244 | * Returns: pointer to zfcp_port or NULL |
252 | */ | 245 | */ |
253 | struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, | 246 | struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, |
254 | wwn_t wwpn) | 247 | u64 wwpn) |
255 | { | 248 | { |
256 | struct zfcp_port *port; | 249 | struct zfcp_port *port; |
257 | 250 | ||
@@ -276,7 +269,7 @@ static void zfcp_sysfs_unit_release(struct device *dev) | |||
276 | * | 269 | * |
277 | * Sets up some unit internal structures and creates sysfs entry. | 270 | * Sets up some unit internal structures and creates sysfs entry. |
278 | */ | 271 | */ |
279 | struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) | 272 | struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) |
280 | { | 273 | { |
281 | struct zfcp_unit *unit; | 274 | struct zfcp_unit *unit; |
282 | 275 | ||
@@ -290,7 +283,8 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) | |||
290 | unit->port = port; | 283 | unit->port = port; |
291 | unit->fcp_lun = fcp_lun; | 284 | unit->fcp_lun = fcp_lun; |
292 | 285 | ||
293 | snprintf(unit->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", fcp_lun); | 286 | snprintf(unit->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", |
287 | (unsigned long long) fcp_lun); | ||
294 | unit->sysfs_device.parent = &port->sysfs_device; | 288 | unit->sysfs_device.parent = &port->sysfs_device; |
295 | unit->sysfs_device.release = zfcp_sysfs_unit_release; | 289 | unit->sysfs_device.release = zfcp_sysfs_unit_release; |
296 | dev_set_drvdata(&unit->sysfs_device, unit); | 290 | dev_set_drvdata(&unit->sysfs_device, unit); |
@@ -323,7 +317,6 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) | |||
323 | } | 317 | } |
324 | 318 | ||
325 | zfcp_unit_get(unit); | 319 | zfcp_unit_get(unit); |
326 | unit->scsi_lun = scsilun_to_int((struct scsi_lun *)&unit->fcp_lun); | ||
327 | 320 | ||
328 | write_lock_irq(&zfcp_data.config_lock); | 321 | write_lock_irq(&zfcp_data.config_lock); |
329 | list_add_tail(&unit->list, &port->unit_list_head); | 322 | list_add_tail(&unit->list, &port->unit_list_head); |
@@ -332,7 +325,6 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) | |||
332 | 325 | ||
333 | write_unlock_irq(&zfcp_data.config_lock); | 326 | write_unlock_irq(&zfcp_data.config_lock); |
334 | 327 | ||
335 | port->units++; | ||
336 | zfcp_port_get(port); | 328 | zfcp_port_get(port); |
337 | 329 | ||
338 | return unit; | 330 | return unit; |
@@ -351,11 +343,10 @@ err_out_free: | |||
351 | */ | 343 | */ |
352 | void zfcp_unit_dequeue(struct zfcp_unit *unit) | 344 | void zfcp_unit_dequeue(struct zfcp_unit *unit) |
353 | { | 345 | { |
354 | zfcp_unit_wait(unit); | 346 | wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0); |
355 | write_lock_irq(&zfcp_data.config_lock); | 347 | write_lock_irq(&zfcp_data.config_lock); |
356 | list_del(&unit->list); | 348 | list_del(&unit->list); |
357 | write_unlock_irq(&zfcp_data.config_lock); | 349 | write_unlock_irq(&zfcp_data.config_lock); |
358 | unit->port->units--; | ||
359 | zfcp_port_put(unit->port); | 350 | zfcp_port_put(unit->port); |
360 | sysfs_remove_group(&unit->sysfs_device.kobj, &zfcp_sysfs_unit_attrs); | 351 | sysfs_remove_group(&unit->sysfs_device.kobj, &zfcp_sysfs_unit_attrs); |
361 | device_unregister(&unit->sysfs_device); | 352 | device_unregister(&unit->sysfs_device); |
@@ -416,11 +407,6 @@ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) | |||
416 | mempool_destroy(adapter->pool.data_gid_pn); | 407 | mempool_destroy(adapter->pool.data_gid_pn); |
417 | } | 408 | } |
418 | 409 | ||
419 | static void zfcp_dummy_release(struct device *dev) | ||
420 | { | ||
421 | return; | ||
422 | } | ||
423 | |||
424 | /** | 410 | /** |
425 | * zfcp_status_read_refill - refill the long running status_read_requests | 411 | * zfcp_status_read_refill - refill the long running status_read_requests |
426 | * @adapter: ptr to struct zfcp_adapter for which the buffers should be refilled | 412 | * @adapter: ptr to struct zfcp_adapter for which the buffers should be refilled |
@@ -450,19 +436,6 @@ static void _zfcp_status_read_scheduler(struct work_struct *work) | |||
450 | stat_work)); | 436 | stat_work)); |
451 | } | 437 | } |
452 | 438 | ||
453 | static int zfcp_nameserver_enqueue(struct zfcp_adapter *adapter) | ||
454 | { | ||
455 | struct zfcp_port *port; | ||
456 | |||
457 | port = zfcp_port_enqueue(adapter, 0, ZFCP_STATUS_PORT_WKA, | ||
458 | ZFCP_DID_DIRECTORY_SERVICE); | ||
459 | if (IS_ERR(port)) | ||
460 | return PTR_ERR(port); | ||
461 | zfcp_port_put(port); | ||
462 | |||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | /** | 439 | /** |
467 | * zfcp_adapter_enqueue - enqueue a new adapter to the list | 440 | * zfcp_adapter_enqueue - enqueue a new adapter to the list |
468 | * @ccw_device: pointer to the struct cc_device | 441 | * @ccw_device: pointer to the struct cc_device |
@@ -508,7 +481,6 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
508 | init_waitqueue_head(&adapter->erp_done_wqh); | 481 | init_waitqueue_head(&adapter->erp_done_wqh); |
509 | 482 | ||
510 | INIT_LIST_HEAD(&adapter->port_list_head); | 483 | INIT_LIST_HEAD(&adapter->port_list_head); |
511 | INIT_LIST_HEAD(&adapter->port_remove_lh); | ||
512 | INIT_LIST_HEAD(&adapter->erp_ready_head); | 484 | INIT_LIST_HEAD(&adapter->erp_ready_head); |
513 | INIT_LIST_HEAD(&adapter->erp_running_head); | 485 | INIT_LIST_HEAD(&adapter->erp_running_head); |
514 | 486 | ||
@@ -518,7 +490,7 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
518 | spin_lock_init(&adapter->san_dbf_lock); | 490 | spin_lock_init(&adapter->san_dbf_lock); |
519 | spin_lock_init(&adapter->scsi_dbf_lock); | 491 | spin_lock_init(&adapter->scsi_dbf_lock); |
520 | spin_lock_init(&adapter->rec_dbf_lock); | 492 | spin_lock_init(&adapter->rec_dbf_lock); |
521 | spin_lock_init(&adapter->req_q.lock); | 493 | spin_lock_init(&adapter->req_q_lock); |
522 | 494 | ||
523 | rwlock_init(&adapter->erp_lock); | 495 | rwlock_init(&adapter->erp_lock); |
524 | rwlock_init(&adapter->abort_lock); | 496 | rwlock_init(&adapter->abort_lock); |
@@ -537,28 +509,15 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
537 | &zfcp_sysfs_adapter_attrs)) | 509 | &zfcp_sysfs_adapter_attrs)) |
538 | goto sysfs_failed; | 510 | goto sysfs_failed; |
539 | 511 | ||
540 | adapter->generic_services.parent = &adapter->ccw_device->dev; | ||
541 | adapter->generic_services.release = zfcp_dummy_release; | ||
542 | snprintf(adapter->generic_services.bus_id, BUS_ID_SIZE, | ||
543 | "generic_services"); | ||
544 | |||
545 | if (device_register(&adapter->generic_services)) | ||
546 | goto generic_services_failed; | ||
547 | |||
548 | write_lock_irq(&zfcp_data.config_lock); | 512 | write_lock_irq(&zfcp_data.config_lock); |
549 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); | 513 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); |
550 | list_add_tail(&adapter->list, &zfcp_data.adapter_list_head); | 514 | list_add_tail(&adapter->list, &zfcp_data.adapter_list_head); |
551 | write_unlock_irq(&zfcp_data.config_lock); | 515 | write_unlock_irq(&zfcp_data.config_lock); |
552 | 516 | ||
553 | zfcp_data.adapters++; | 517 | zfcp_fc_nameserver_init(adapter); |
554 | |||
555 | zfcp_nameserver_enqueue(adapter); | ||
556 | 518 | ||
557 | return 0; | 519 | return 0; |
558 | 520 | ||
559 | generic_services_failed: | ||
560 | sysfs_remove_group(&ccw_device->dev.kobj, | ||
561 | &zfcp_sysfs_adapter_attrs); | ||
562 | sysfs_failed: | 521 | sysfs_failed: |
563 | zfcp_adapter_debug_unregister(adapter); | 522 | zfcp_adapter_debug_unregister(adapter); |
564 | debug_register_failed: | 523 | debug_register_failed: |
@@ -585,7 +544,6 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter) | |||
585 | cancel_work_sync(&adapter->scan_work); | 544 | cancel_work_sync(&adapter->scan_work); |
586 | cancel_work_sync(&adapter->stat_work); | 545 | cancel_work_sync(&adapter->stat_work); |
587 | zfcp_adapter_scsi_unregister(adapter); | 546 | zfcp_adapter_scsi_unregister(adapter); |
588 | device_unregister(&adapter->generic_services); | ||
589 | sysfs_remove_group(&adapter->ccw_device->dev.kobj, | 547 | sysfs_remove_group(&adapter->ccw_device->dev.kobj, |
590 | &zfcp_sysfs_adapter_attrs); | 548 | &zfcp_sysfs_adapter_attrs); |
591 | dev_set_drvdata(&adapter->ccw_device->dev, NULL); | 549 | dev_set_drvdata(&adapter->ccw_device->dev, NULL); |
@@ -603,9 +561,6 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter) | |||
603 | list_del(&adapter->list); | 561 | list_del(&adapter->list); |
604 | write_unlock_irq(&zfcp_data.config_lock); | 562 | write_unlock_irq(&zfcp_data.config_lock); |
605 | 563 | ||
606 | /* decrease number of adapters in list */ | ||
607 | zfcp_data.adapters--; | ||
608 | |||
609 | zfcp_qdio_free(adapter); | 564 | zfcp_qdio_free(adapter); |
610 | 565 | ||
611 | zfcp_free_low_mem_buffers(adapter); | 566 | zfcp_free_low_mem_buffers(adapter); |
@@ -633,21 +588,19 @@ static void zfcp_sysfs_port_release(struct device *dev) | |||
633 | * d_id is used to enqueue ports with a well known address like the Directory | 588 | * d_id is used to enqueue ports with a well known address like the Directory |
634 | * Service for nameserver lookup. | 589 | * Service for nameserver lookup. |
635 | */ | 590 | */ |
636 | struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, | 591 | struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, |
637 | u32 status, u32 d_id) | 592 | u32 status, u32 d_id) |
638 | { | 593 | { |
639 | struct zfcp_port *port; | 594 | struct zfcp_port *port; |
640 | int retval; | 595 | int retval; |
641 | char *bus_id; | ||
642 | 596 | ||
643 | port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); | 597 | port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); |
644 | if (!port) | 598 | if (!port) |
645 | return ERR_PTR(-ENOMEM); | 599 | return ERR_PTR(-ENOMEM); |
646 | 600 | ||
647 | init_waitqueue_head(&port->remove_wq); | 601 | init_waitqueue_head(&port->remove_wq); |
648 | |||
649 | INIT_LIST_HEAD(&port->unit_list_head); | 602 | INIT_LIST_HEAD(&port->unit_list_head); |
650 | INIT_LIST_HEAD(&port->unit_remove_lh); | 603 | INIT_WORK(&port->gid_pn_work, zfcp_erp_port_strategy_open_lookup); |
651 | 604 | ||
652 | port->adapter = adapter; | 605 | port->adapter = adapter; |
653 | port->d_id = d_id; | 606 | port->d_id = d_id; |
@@ -657,34 +610,9 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, | |||
657 | atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status); | 610 | atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status); |
658 | atomic_set(&port->refcount, 0); | 611 | atomic_set(&port->refcount, 0); |
659 | 612 | ||
660 | if (status & ZFCP_STATUS_PORT_WKA) { | 613 | snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", |
661 | switch (d_id) { | 614 | (unsigned long long) wwpn); |
662 | case ZFCP_DID_DIRECTORY_SERVICE: | 615 | port->sysfs_device.parent = &adapter->ccw_device->dev; |
663 | bus_id = "directory"; | ||
664 | break; | ||
665 | case ZFCP_DID_MANAGEMENT_SERVICE: | ||
666 | bus_id = "management"; | ||
667 | break; | ||
668 | case ZFCP_DID_KEY_DISTRIBUTION_SERVICE: | ||
669 | bus_id = "key_distribution"; | ||
670 | break; | ||
671 | case ZFCP_DID_ALIAS_SERVICE: | ||
672 | bus_id = "alias"; | ||
673 | break; | ||
674 | case ZFCP_DID_TIME_SERVICE: | ||
675 | bus_id = "time"; | ||
676 | break; | ||
677 | default: | ||
678 | kfree(port); | ||
679 | return ERR_PTR(-EINVAL); | ||
680 | } | ||
681 | snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "%s", bus_id); | ||
682 | port->sysfs_device.parent = &adapter->generic_services; | ||
683 | } else { | ||
684 | snprintf(port->sysfs_device.bus_id, | ||
685 | BUS_ID_SIZE, "0x%016llx", wwpn); | ||
686 | port->sysfs_device.parent = &adapter->ccw_device->dev; | ||
687 | } | ||
688 | 616 | ||
689 | port->sysfs_device.release = zfcp_sysfs_port_release; | 617 | port->sysfs_device.release = zfcp_sysfs_port_release; |
690 | dev_set_drvdata(&port->sysfs_device, port); | 618 | dev_set_drvdata(&port->sysfs_device, port); |
@@ -700,12 +628,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, | |||
700 | if (device_register(&port->sysfs_device)) | 628 | if (device_register(&port->sysfs_device)) |
701 | goto err_out_free; | 629 | goto err_out_free; |
702 | 630 | ||
703 | if (status & ZFCP_STATUS_PORT_WKA) | 631 | retval = sysfs_create_group(&port->sysfs_device.kobj, |
704 | retval = sysfs_create_group(&port->sysfs_device.kobj, | 632 | &zfcp_sysfs_port_attrs); |
705 | &zfcp_sysfs_ns_port_attrs); | ||
706 | else | ||
707 | retval = sysfs_create_group(&port->sysfs_device.kobj, | ||
708 | &zfcp_sysfs_port_attrs); | ||
709 | 633 | ||
710 | if (retval) { | 634 | if (retval) { |
711 | device_unregister(&port->sysfs_device); | 635 | device_unregister(&port->sysfs_device); |
@@ -718,10 +642,6 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, | |||
718 | list_add_tail(&port->list, &adapter->port_list_head); | 642 | list_add_tail(&port->list, &adapter->port_list_head); |
719 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); | 643 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); |
720 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); | 644 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); |
721 | if (d_id == ZFCP_DID_DIRECTORY_SERVICE) | ||
722 | if (!adapter->nameserver_port) | ||
723 | adapter->nameserver_port = port; | ||
724 | adapter->ports++; | ||
725 | 645 | ||
726 | write_unlock_irq(&zfcp_data.config_lock); | 646 | write_unlock_irq(&zfcp_data.config_lock); |
727 | 647 | ||
@@ -740,21 +660,15 @@ err_out: | |||
740 | */ | 660 | */ |
741 | void zfcp_port_dequeue(struct zfcp_port *port) | 661 | void zfcp_port_dequeue(struct zfcp_port *port) |
742 | { | 662 | { |
743 | zfcp_port_wait(port); | 663 | wait_event(port->remove_wq, atomic_read(&port->refcount) == 0); |
744 | write_lock_irq(&zfcp_data.config_lock); | 664 | write_lock_irq(&zfcp_data.config_lock); |
745 | list_del(&port->list); | 665 | list_del(&port->list); |
746 | port->adapter->ports--; | ||
747 | write_unlock_irq(&zfcp_data.config_lock); | 666 | write_unlock_irq(&zfcp_data.config_lock); |
748 | if (port->rport) | 667 | if (port->rport) |
749 | fc_remote_port_delete(port->rport); | 668 | fc_remote_port_delete(port->rport); |
750 | port->rport = NULL; | 669 | port->rport = NULL; |
751 | zfcp_adapter_put(port->adapter); | 670 | zfcp_adapter_put(port->adapter); |
752 | if (atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA) | 671 | sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs); |
753 | sysfs_remove_group(&port->sysfs_device.kobj, | ||
754 | &zfcp_sysfs_ns_port_attrs); | ||
755 | else | ||
756 | sysfs_remove_group(&port->sysfs_device.kobj, | ||
757 | &zfcp_sysfs_port_attrs); | ||
758 | device_unregister(&port->sysfs_device); | 672 | device_unregister(&port->sysfs_device); |
759 | } | 673 | } |
760 | 674 | ||
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 51b6a05f4d12..b04038c74786 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -25,7 +25,8 @@ static int zfcp_ccw_probe(struct ccw_device *ccw_device) | |||
25 | down(&zfcp_data.config_sema); | 25 | down(&zfcp_data.config_sema); |
26 | if (zfcp_adapter_enqueue(ccw_device)) { | 26 | if (zfcp_adapter_enqueue(ccw_device)) { |
27 | dev_err(&ccw_device->dev, | 27 | dev_err(&ccw_device->dev, |
28 | "Setup of data structures failed.\n"); | 28 | "Setting up data structures for the " |
29 | "FCP adapter failed\n"); | ||
29 | retval = -EINVAL; | 30 | retval = -EINVAL; |
30 | } | 31 | } |
31 | up(&zfcp_data.config_sema); | 32 | up(&zfcp_data.config_sema); |
@@ -46,6 +47,8 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) | |||
46 | struct zfcp_adapter *adapter; | 47 | struct zfcp_adapter *adapter; |
47 | struct zfcp_port *port, *p; | 48 | struct zfcp_port *port, *p; |
48 | struct zfcp_unit *unit, *u; | 49 | struct zfcp_unit *unit, *u; |
50 | LIST_HEAD(unit_remove_lh); | ||
51 | LIST_HEAD(port_remove_lh); | ||
49 | 52 | ||
50 | ccw_device_set_offline(ccw_device); | 53 | ccw_device_set_offline(ccw_device); |
51 | down(&zfcp_data.config_sema); | 54 | down(&zfcp_data.config_sema); |
@@ -54,26 +57,26 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) | |||
54 | write_lock_irq(&zfcp_data.config_lock); | 57 | write_lock_irq(&zfcp_data.config_lock); |
55 | list_for_each_entry_safe(port, p, &adapter->port_list_head, list) { | 58 | list_for_each_entry_safe(port, p, &adapter->port_list_head, list) { |
56 | list_for_each_entry_safe(unit, u, &port->unit_list_head, list) { | 59 | list_for_each_entry_safe(unit, u, &port->unit_list_head, list) { |
57 | list_move(&unit->list, &port->unit_remove_lh); | 60 | list_move(&unit->list, &unit_remove_lh); |
58 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, | 61 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, |
59 | &unit->status); | 62 | &unit->status); |
60 | } | 63 | } |
61 | list_move(&port->list, &adapter->port_remove_lh); | 64 | list_move(&port->list, &port_remove_lh); |
62 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); | 65 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); |
63 | } | 66 | } |
64 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); | 67 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); |
65 | write_unlock_irq(&zfcp_data.config_lock); | 68 | write_unlock_irq(&zfcp_data.config_lock); |
66 | 69 | ||
67 | list_for_each_entry_safe(port, p, &adapter->port_remove_lh, list) { | 70 | list_for_each_entry_safe(port, p, &port_remove_lh, list) { |
68 | list_for_each_entry_safe(unit, u, &port->unit_remove_lh, list) { | 71 | list_for_each_entry_safe(unit, u, &unit_remove_lh, list) { |
69 | if (atomic_test_mask(ZFCP_STATUS_UNIT_REGISTERED, | 72 | if (atomic_read(&unit->status) & |
70 | &unit->status)) | 73 | ZFCP_STATUS_UNIT_REGISTERED) |
71 | scsi_remove_device(unit->device); | 74 | scsi_remove_device(unit->device); |
72 | zfcp_unit_dequeue(unit); | 75 | zfcp_unit_dequeue(unit); |
73 | } | 76 | } |
74 | zfcp_port_dequeue(port); | 77 | zfcp_port_dequeue(port); |
75 | } | 78 | } |
76 | zfcp_adapter_wait(adapter); | 79 | wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0); |
77 | zfcp_adapter_dequeue(adapter); | 80 | zfcp_adapter_dequeue(adapter); |
78 | 81 | ||
79 | up(&zfcp_data.config_sema); | 82 | up(&zfcp_data.config_sema); |
@@ -156,15 +159,18 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event) | |||
156 | 159 | ||
157 | switch (event) { | 160 | switch (event) { |
158 | case CIO_GONE: | 161 | case CIO_GONE: |
159 | dev_warn(&adapter->ccw_device->dev, "device gone\n"); | 162 | dev_warn(&adapter->ccw_device->dev, |
163 | "The FCP device has been detached\n"); | ||
160 | zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL); | 164 | zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL); |
161 | break; | 165 | break; |
162 | case CIO_NO_PATH: | 166 | case CIO_NO_PATH: |
163 | dev_warn(&adapter->ccw_device->dev, "no path\n"); | 167 | dev_warn(&adapter->ccw_device->dev, |
168 | "The CHPID for the FCP device is offline\n"); | ||
164 | zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL); | 169 | zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL); |
165 | break; | 170 | break; |
166 | case CIO_OPER: | 171 | case CIO_OPER: |
167 | dev_info(&adapter->ccw_device->dev, "operational again\n"); | 172 | dev_info(&adapter->ccw_device->dev, |
173 | "The FCP device is operational again\n"); | ||
168 | zfcp_erp_modify_adapter_status(adapter, 11, NULL, | 174 | zfcp_erp_modify_adapter_status(adapter, 11, NULL, |
169 | ZFCP_STATUS_COMMON_RUNNING, | 175 | ZFCP_STATUS_COMMON_RUNNING, |
170 | ZFCP_SET); | 176 | ZFCP_SET); |
@@ -220,3 +226,20 @@ int __init zfcp_ccw_register(void) | |||
220 | { | 226 | { |
221 | return ccw_driver_register(&zfcp_ccw_driver); | 227 | return ccw_driver_register(&zfcp_ccw_driver); |
222 | } | 228 | } |
229 | |||
230 | /** | ||
231 | * zfcp_get_adapter_by_busid - find zfcp_adapter struct | ||
232 | * @busid: bus id string of zfcp adapter to find | ||
233 | */ | ||
234 | struct zfcp_adapter *zfcp_get_adapter_by_busid(char *busid) | ||
235 | { | ||
236 | struct ccw_device *ccw_device; | ||
237 | struct zfcp_adapter *adapter = NULL; | ||
238 | |||
239 | ccw_device = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); | ||
240 | if (ccw_device) { | ||
241 | adapter = dev_get_drvdata(&ccw_device->dev); | ||
242 | put_device(&ccw_device->dev); | ||
243 | } | ||
244 | return adapter; | ||
245 | } | ||
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index fca48b88fc53..060f5f2352ec 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c | |||
@@ -318,6 +318,26 @@ void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, | |||
318 | spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); | 318 | spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); |
319 | } | 319 | } |
320 | 320 | ||
321 | /** | ||
322 | * zfcp_hba_dbf_event_berr - trace event for bit error threshold | ||
323 | * @adapter: adapter affected by this QDIO related event | ||
324 | * @req: fsf request | ||
325 | */ | ||
326 | void zfcp_hba_dbf_event_berr(struct zfcp_adapter *adapter, | ||
327 | struct zfcp_fsf_req *req) | ||
328 | { | ||
329 | struct zfcp_hba_dbf_record *r = &adapter->hba_dbf_buf; | ||
330 | struct fsf_status_read_buffer *sr_buf = req->data; | ||
331 | struct fsf_bit_error_payload *err = &sr_buf->payload.bit_error; | ||
332 | unsigned long flags; | ||
333 | |||
334 | spin_lock_irqsave(&adapter->hba_dbf_lock, flags); | ||
335 | memset(r, 0, sizeof(*r)); | ||
336 | strncpy(r->tag, "berr", ZFCP_DBF_TAG_SIZE); | ||
337 | memcpy(&r->u.berr, err, sizeof(struct fsf_bit_error_payload)); | ||
338 | debug_event(adapter->hba_dbf, 0, r, sizeof(*r)); | ||
339 | spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); | ||
340 | } | ||
321 | static void zfcp_hba_dbf_view_response(char **p, | 341 | static void zfcp_hba_dbf_view_response(char **p, |
322 | struct zfcp_hba_dbf_record_response *r) | 342 | struct zfcp_hba_dbf_record_response *r) |
323 | { | 343 | { |
@@ -399,6 +419,30 @@ static void zfcp_hba_dbf_view_qdio(char **p, struct zfcp_hba_dbf_record_qdio *r) | |||
399 | zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count); | 419 | zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count); |
400 | } | 420 | } |
401 | 421 | ||
422 | static void zfcp_hba_dbf_view_berr(char **p, struct fsf_bit_error_payload *r) | ||
423 | { | ||
424 | zfcp_dbf_out(p, "link_failures", "%d", r->link_failure_error_count); | ||
425 | zfcp_dbf_out(p, "loss_of_sync_err", "%d", r->loss_of_sync_error_count); | ||
426 | zfcp_dbf_out(p, "loss_of_sig_err", "%d", r->loss_of_signal_error_count); | ||
427 | zfcp_dbf_out(p, "prim_seq_err", "%d", | ||
428 | r->primitive_sequence_error_count); | ||
429 | zfcp_dbf_out(p, "inval_trans_word_err", "%d", | ||
430 | r->invalid_transmission_word_error_count); | ||
431 | zfcp_dbf_out(p, "CRC_errors", "%d", r->crc_error_count); | ||
432 | zfcp_dbf_out(p, "prim_seq_event_to", "%d", | ||
433 | r->primitive_sequence_event_timeout_count); | ||
434 | zfcp_dbf_out(p, "elast_buf_overrun_err", "%d", | ||
435 | r->elastic_buffer_overrun_error_count); | ||
436 | zfcp_dbf_out(p, "adv_rec_buf2buf_cred", "%d", | ||
437 | r->advertised_receive_b2b_credit); | ||
438 | zfcp_dbf_out(p, "curr_rec_buf2buf_cred", "%d", | ||
439 | r->current_receive_b2b_credit); | ||
440 | zfcp_dbf_out(p, "adv_trans_buf2buf_cred", "%d", | ||
441 | r->advertised_transmit_b2b_credit); | ||
442 | zfcp_dbf_out(p, "curr_trans_buf2buf_cred", "%d", | ||
443 | r->current_transmit_b2b_credit); | ||
444 | } | ||
445 | |||
402 | static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view, | 446 | static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view, |
403 | char *out_buf, const char *in_buf) | 447 | char *out_buf, const char *in_buf) |
404 | { | 448 | { |
@@ -418,6 +462,8 @@ static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view, | |||
418 | zfcp_hba_dbf_view_status(&p, &r->u.status); | 462 | zfcp_hba_dbf_view_status(&p, &r->u.status); |
419 | else if (strncmp(r->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0) | 463 | else if (strncmp(r->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0) |
420 | zfcp_hba_dbf_view_qdio(&p, &r->u.qdio); | 464 | zfcp_hba_dbf_view_qdio(&p, &r->u.qdio); |
465 | else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0) | ||
466 | zfcp_hba_dbf_view_berr(&p, &r->u.berr); | ||
421 | 467 | ||
422 | p += sprintf(p, "\n"); | 468 | p += sprintf(p, "\n"); |
423 | return p - out_buf; | 469 | return p - out_buf; |
@@ -519,14 +565,14 @@ static const char *zfcp_rec_dbf_ids[] = { | |||
519 | [75] = "physical port recovery escalation after failed port " | 565 | [75] = "physical port recovery escalation after failed port " |
520 | "recovery", | 566 | "recovery", |
521 | [76] = "port recovery escalation after failed unit recovery", | 567 | [76] = "port recovery escalation after failed unit recovery", |
522 | [77] = "recovery opening nameserver port", | 568 | [77] = "", |
523 | [78] = "duplicate request id", | 569 | [78] = "duplicate request id", |
524 | [79] = "link down", | 570 | [79] = "link down", |
525 | [80] = "exclusive read-only unit access unsupported", | 571 | [80] = "exclusive read-only unit access unsupported", |
526 | [81] = "shared read-write unit access unsupported", | 572 | [81] = "shared read-write unit access unsupported", |
527 | [82] = "incoming rscn", | 573 | [82] = "incoming rscn", |
528 | [83] = "incoming wwpn", | 574 | [83] = "incoming wwpn", |
529 | [84] = "", | 575 | [84] = "wka port handle not valid close port", |
530 | [85] = "online", | 576 | [85] = "online", |
531 | [86] = "offline", | 577 | [86] = "offline", |
532 | [87] = "ccw device gone", | 578 | [87] = "ccw device gone", |
@@ -570,7 +616,7 @@ static const char *zfcp_rec_dbf_ids[] = { | |||
570 | [125] = "need newer zfcp", | 616 | [125] = "need newer zfcp", |
571 | [126] = "need newer microcode", | 617 | [126] = "need newer microcode", |
572 | [127] = "arbitrated loop not supported", | 618 | [127] = "arbitrated loop not supported", |
573 | [128] = "unknown topology", | 619 | [128] = "", |
574 | [129] = "qtcb size mismatch", | 620 | [129] = "qtcb size mismatch", |
575 | [130] = "unknown fsf status ecd", | 621 | [130] = "unknown fsf status ecd", |
576 | [131] = "fcp request too big", | 622 | [131] = "fcp request too big", |
@@ -829,9 +875,9 @@ void zfcp_rec_dbf_event_action(u8 id2, struct zfcp_erp_action *erp_action) | |||
829 | void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) | 875 | void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) |
830 | { | 876 | { |
831 | struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; | 877 | struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; |
832 | struct zfcp_port *port = ct->port; | 878 | struct zfcp_wka_port *wka_port = ct->wka_port; |
833 | struct zfcp_adapter *adapter = port->adapter; | 879 | struct zfcp_adapter *adapter = wka_port->adapter; |
834 | struct ct_hdr *hdr = zfcp_sg_to_address(ct->req); | 880 | struct ct_hdr *hdr = sg_virt(ct->req); |
835 | struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf; | 881 | struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf; |
836 | struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req; | 882 | struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req; |
837 | unsigned long flags; | 883 | unsigned long flags; |
@@ -842,7 +888,7 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) | |||
842 | r->fsf_reqid = (unsigned long)fsf_req; | 888 | r->fsf_reqid = (unsigned long)fsf_req; |
843 | r->fsf_seqno = fsf_req->seq_no; | 889 | r->fsf_seqno = fsf_req->seq_no; |
844 | r->s_id = fc_host_port_id(adapter->scsi_host); | 890 | r->s_id = fc_host_port_id(adapter->scsi_host); |
845 | r->d_id = port->d_id; | 891 | r->d_id = wka_port->d_id; |
846 | oct->cmd_req_code = hdr->cmd_rsp_code; | 892 | oct->cmd_req_code = hdr->cmd_rsp_code; |
847 | oct->revision = hdr->revision; | 893 | oct->revision = hdr->revision; |
848 | oct->gs_type = hdr->gs_type; | 894 | oct->gs_type = hdr->gs_type; |
@@ -863,9 +909,9 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) | |||
863 | void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) | 909 | void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) |
864 | { | 910 | { |
865 | struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; | 911 | struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; |
866 | struct zfcp_port *port = ct->port; | 912 | struct zfcp_wka_port *wka_port = ct->wka_port; |
867 | struct zfcp_adapter *adapter = port->adapter; | 913 | struct zfcp_adapter *adapter = wka_port->adapter; |
868 | struct ct_hdr *hdr = zfcp_sg_to_address(ct->resp); | 914 | struct ct_hdr *hdr = sg_virt(ct->resp); |
869 | struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf; | 915 | struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf; |
870 | struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp; | 916 | struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp; |
871 | unsigned long flags; | 917 | unsigned long flags; |
@@ -875,7 +921,7 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) | |||
875 | strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE); | 921 | strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE); |
876 | r->fsf_reqid = (unsigned long)fsf_req; | 922 | r->fsf_reqid = (unsigned long)fsf_req; |
877 | r->fsf_seqno = fsf_req->seq_no; | 923 | r->fsf_seqno = fsf_req->seq_no; |
878 | r->s_id = port->d_id; | 924 | r->s_id = wka_port->d_id; |
879 | r->d_id = fc_host_port_id(adapter->scsi_host); | 925 | r->d_id = fc_host_port_id(adapter->scsi_host); |
880 | rct->cmd_rsp_code = hdr->cmd_rsp_code; | 926 | rct->cmd_rsp_code = hdr->cmd_rsp_code; |
881 | rct->revision = hdr->revision; | 927 | rct->revision = hdr->revision; |
@@ -922,8 +968,8 @@ void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req) | |||
922 | 968 | ||
923 | zfcp_san_dbf_event_els("oels", 2, fsf_req, | 969 | zfcp_san_dbf_event_els("oels", 2, fsf_req, |
924 | fc_host_port_id(els->adapter->scsi_host), | 970 | fc_host_port_id(els->adapter->scsi_host), |
925 | els->d_id, *(u8 *) zfcp_sg_to_address(els->req), | 971 | els->d_id, *(u8 *) sg_virt(els->req), |
926 | zfcp_sg_to_address(els->req), els->req->length); | 972 | sg_virt(els->req), els->req->length); |
927 | } | 973 | } |
928 | 974 | ||
929 | /** | 975 | /** |
@@ -936,8 +982,7 @@ void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req) | |||
936 | 982 | ||
937 | zfcp_san_dbf_event_els("rels", 2, fsf_req, els->d_id, | 983 | zfcp_san_dbf_event_els("rels", 2, fsf_req, els->d_id, |
938 | fc_host_port_id(els->adapter->scsi_host), | 984 | fc_host_port_id(els->adapter->scsi_host), |
939 | *(u8 *)zfcp_sg_to_address(els->req), | 985 | *(u8 *)sg_virt(els->req), sg_virt(els->resp), |
940 | zfcp_sg_to_address(els->resp), | ||
941 | els->resp->length); | 986 | els->resp->length); |
942 | } | 987 | } |
943 | 988 | ||
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 0ddb18449d11..e8f450801fea 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h | |||
@@ -151,6 +151,7 @@ struct zfcp_hba_dbf_record { | |||
151 | struct zfcp_hba_dbf_record_response response; | 151 | struct zfcp_hba_dbf_record_response response; |
152 | struct zfcp_hba_dbf_record_status status; | 152 | struct zfcp_hba_dbf_record_status status; |
153 | struct zfcp_hba_dbf_record_qdio qdio; | 153 | struct zfcp_hba_dbf_record_qdio qdio; |
154 | struct fsf_bit_error_payload berr; | ||
154 | } u; | 155 | } u; |
155 | } __attribute__ ((packed)); | 156 | } __attribute__ ((packed)); |
156 | 157 | ||
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 67f45fc62f53..73eb41580f25 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -39,29 +39,6 @@ | |||
39 | 39 | ||
40 | /********************* GENERAL DEFINES *********************************/ | 40 | /********************* GENERAL DEFINES *********************************/ |
41 | 41 | ||
42 | /** | ||
43 | * zfcp_sg_to_address - determine kernel address from struct scatterlist | ||
44 | * @list: struct scatterlist | ||
45 | * Return: kernel address | ||
46 | */ | ||
47 | static inline void * | ||
48 | zfcp_sg_to_address(struct scatterlist *list) | ||
49 | { | ||
50 | return sg_virt(list); | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * zfcp_address_to_sg - set up struct scatterlist from kernel address | ||
55 | * @address: kernel address | ||
56 | * @list: struct scatterlist | ||
57 | * @size: buffer size | ||
58 | */ | ||
59 | static inline void | ||
60 | zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size) | ||
61 | { | ||
62 | sg_set_buf(list, address, size); | ||
63 | } | ||
64 | |||
65 | #define REQUEST_LIST_SIZE 128 | 42 | #define REQUEST_LIST_SIZE 128 |
66 | 43 | ||
67 | /********************* SCSI SPECIFIC DEFINES *********************************/ | 44 | /********************* SCSI SPECIFIC DEFINES *********************************/ |
@@ -101,11 +78,6 @@ zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size) | |||
101 | 78 | ||
102 | /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/ | 79 | /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/ |
103 | 80 | ||
104 | typedef unsigned long long wwn_t; | ||
105 | typedef unsigned long long fcp_lun_t; | ||
106 | /* data length field may be at variable position in FCP-2 FCP_CMND IU */ | ||
107 | typedef unsigned int fcp_dl_t; | ||
108 | |||
109 | /* timeout for name-server lookup (in seconds) */ | 81 | /* timeout for name-server lookup (in seconds) */ |
110 | #define ZFCP_NS_GID_PN_TIMEOUT 10 | 82 | #define ZFCP_NS_GID_PN_TIMEOUT 10 |
111 | 83 | ||
@@ -129,7 +101,7 @@ typedef unsigned int fcp_dl_t; | |||
129 | 101 | ||
130 | /* FCP(-2) FCP_CMND IU */ | 102 | /* FCP(-2) FCP_CMND IU */ |
131 | struct fcp_cmnd_iu { | 103 | struct fcp_cmnd_iu { |
132 | fcp_lun_t fcp_lun; /* FCP logical unit number */ | 104 | u64 fcp_lun; /* FCP logical unit number */ |
133 | u8 crn; /* command reference number */ | 105 | u8 crn; /* command reference number */ |
134 | u8 reserved0:5; /* reserved */ | 106 | u8 reserved0:5; /* reserved */ |
135 | u8 task_attribute:3; /* task attribute */ | 107 | u8 task_attribute:3; /* task attribute */ |
@@ -204,7 +176,7 @@ struct fcp_rscn_element { | |||
204 | struct fcp_logo { | 176 | struct fcp_logo { |
205 | u32 command; | 177 | u32 command; |
206 | u32 nport_did; | 178 | u32 nport_did; |
207 | wwn_t nport_wwpn; | 179 | u64 nport_wwpn; |
208 | } __attribute__((packed)); | 180 | } __attribute__((packed)); |
209 | 181 | ||
210 | /* | 182 | /* |
@@ -218,13 +190,6 @@ struct fcp_logo { | |||
218 | #define ZFCP_LS_RSCN 0x61 | 190 | #define ZFCP_LS_RSCN 0x61 |
219 | #define ZFCP_LS_RNID 0x78 | 191 | #define ZFCP_LS_RNID 0x78 |
220 | 192 | ||
221 | struct zfcp_ls_rjt_par { | ||
222 | u8 action; | ||
223 | u8 reason_code; | ||
224 | u8 reason_expl; | ||
225 | u8 vendor_unique; | ||
226 | } __attribute__ ((packed)); | ||
227 | |||
228 | struct zfcp_ls_adisc { | 193 | struct zfcp_ls_adisc { |
229 | u8 code; | 194 | u8 code; |
230 | u8 field[3]; | 195 | u8 field[3]; |
@@ -234,20 +199,6 @@ struct zfcp_ls_adisc { | |||
234 | u32 nport_id; | 199 | u32 nport_id; |
235 | } __attribute__ ((packed)); | 200 | } __attribute__ ((packed)); |
236 | 201 | ||
237 | struct zfcp_ls_adisc_acc { | ||
238 | u8 code; | ||
239 | u8 field[3]; | ||
240 | u32 hard_nport_id; | ||
241 | u64 wwpn; | ||
242 | u64 wwnn; | ||
243 | u32 nport_id; | ||
244 | } __attribute__ ((packed)); | ||
245 | |||
246 | struct zfcp_rc_entry { | ||
247 | u8 code; | ||
248 | const char *description; | ||
249 | }; | ||
250 | |||
251 | /* | 202 | /* |
252 | * FC-GS-2 stuff | 203 | * FC-GS-2 stuff |
253 | */ | 204 | */ |
@@ -281,9 +232,7 @@ struct zfcp_rc_entry { | |||
281 | #define ZFCP_STATUS_COMMON_RUNNING 0x40000000 | 232 | #define ZFCP_STATUS_COMMON_RUNNING 0x40000000 |
282 | #define ZFCP_STATUS_COMMON_ERP_FAILED 0x20000000 | 233 | #define ZFCP_STATUS_COMMON_ERP_FAILED 0x20000000 |
283 | #define ZFCP_STATUS_COMMON_UNBLOCKED 0x10000000 | 234 | #define ZFCP_STATUS_COMMON_UNBLOCKED 0x10000000 |
284 | #define ZFCP_STATUS_COMMON_OPENING 0x08000000 | ||
285 | #define ZFCP_STATUS_COMMON_OPEN 0x04000000 | 235 | #define ZFCP_STATUS_COMMON_OPEN 0x04000000 |
286 | #define ZFCP_STATUS_COMMON_CLOSING 0x02000000 | ||
287 | #define ZFCP_STATUS_COMMON_ERP_INUSE 0x01000000 | 236 | #define ZFCP_STATUS_COMMON_ERP_INUSE 0x01000000 |
288 | #define ZFCP_STATUS_COMMON_ACCESS_DENIED 0x00800000 | 237 | #define ZFCP_STATUS_COMMON_ACCESS_DENIED 0x00800000 |
289 | #define ZFCP_STATUS_COMMON_ACCESS_BOXED 0x00400000 | 238 | #define ZFCP_STATUS_COMMON_ACCESS_BOXED 0x00400000 |
@@ -291,16 +240,15 @@ struct zfcp_rc_entry { | |||
291 | 240 | ||
292 | /* adapter status */ | 241 | /* adapter status */ |
293 | #define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002 | 242 | #define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002 |
294 | #define ZFCP_STATUS_ADAPTER_REGISTERED 0x00000004 | ||
295 | #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 | 243 | #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 |
296 | #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 | 244 | #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 |
297 | #define ZFCP_STATUS_ADAPTER_ERP_THREAD_UP 0x00000020 | 245 | #define ZFCP_STATUS_ADAPTER_ERP_THREAD_UP 0x00000020 |
298 | #define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL 0x00000080 | 246 | #define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL 0x00000080 |
299 | #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 | 247 | #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 |
300 | #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 | 248 | #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 |
301 | #define ZFCP_STATUS_ADAPTER_XPORT_OK 0x00000800 | ||
302 | 249 | ||
303 | /* FC-PH/FC-GS well-known address identifiers for generic services */ | 250 | /* FC-PH/FC-GS well-known address identifiers for generic services */ |
251 | #define ZFCP_DID_WKA 0xFFFFF0 | ||
304 | #define ZFCP_DID_MANAGEMENT_SERVICE 0xFFFFFA | 252 | #define ZFCP_DID_MANAGEMENT_SERVICE 0xFFFFFA |
305 | #define ZFCP_DID_TIME_SERVICE 0xFFFFFB | 253 | #define ZFCP_DID_TIME_SERVICE 0xFFFFFB |
306 | #define ZFCP_DID_DIRECTORY_SERVICE 0xFFFFFC | 254 | #define ZFCP_DID_DIRECTORY_SERVICE 0xFFFFFC |
@@ -312,29 +260,27 @@ struct zfcp_rc_entry { | |||
312 | #define ZFCP_STATUS_PORT_DID_DID 0x00000002 | 260 | #define ZFCP_STATUS_PORT_DID_DID 0x00000002 |
313 | #define ZFCP_STATUS_PORT_PHYS_CLOSING 0x00000004 | 261 | #define ZFCP_STATUS_PORT_PHYS_CLOSING 0x00000004 |
314 | #define ZFCP_STATUS_PORT_NO_WWPN 0x00000008 | 262 | #define ZFCP_STATUS_PORT_NO_WWPN 0x00000008 |
315 | #define ZFCP_STATUS_PORT_NO_SCSI_ID 0x00000010 | ||
316 | #define ZFCP_STATUS_PORT_INVALID_WWPN 0x00000020 | 263 | #define ZFCP_STATUS_PORT_INVALID_WWPN 0x00000020 |
317 | 264 | ||
318 | /* for ports with well known addresses */ | 265 | /* well known address (WKA) port status*/ |
319 | #define ZFCP_STATUS_PORT_WKA \ | 266 | enum zfcp_wka_status { |
320 | (ZFCP_STATUS_PORT_NO_WWPN | \ | 267 | ZFCP_WKA_PORT_OFFLINE, |
321 | ZFCP_STATUS_PORT_NO_SCSI_ID) | 268 | ZFCP_WKA_PORT_CLOSING, |
269 | ZFCP_WKA_PORT_OPENING, | ||
270 | ZFCP_WKA_PORT_ONLINE, | ||
271 | }; | ||
322 | 272 | ||
323 | /* logical unit status */ | 273 | /* logical unit status */ |
324 | #define ZFCP_STATUS_UNIT_TEMPORARY 0x00000002 | ||
325 | #define ZFCP_STATUS_UNIT_SHARED 0x00000004 | 274 | #define ZFCP_STATUS_UNIT_SHARED 0x00000004 |
326 | #define ZFCP_STATUS_UNIT_READONLY 0x00000008 | 275 | #define ZFCP_STATUS_UNIT_READONLY 0x00000008 |
327 | #define ZFCP_STATUS_UNIT_REGISTERED 0x00000010 | 276 | #define ZFCP_STATUS_UNIT_REGISTERED 0x00000010 |
328 | #define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020 | 277 | #define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020 |
329 | 278 | ||
330 | /* FSF request status (this does not have a common part) */ | 279 | /* FSF request status (this does not have a common part) */ |
331 | #define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000 | ||
332 | #define ZFCP_STATUS_FSFREQ_POOL 0x00000001 | ||
333 | #define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002 | 280 | #define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002 |
334 | #define ZFCP_STATUS_FSFREQ_COMPLETED 0x00000004 | 281 | #define ZFCP_STATUS_FSFREQ_COMPLETED 0x00000004 |
335 | #define ZFCP_STATUS_FSFREQ_ERROR 0x00000008 | 282 | #define ZFCP_STATUS_FSFREQ_ERROR 0x00000008 |
336 | #define ZFCP_STATUS_FSFREQ_CLEANUP 0x00000010 | 283 | #define ZFCP_STATUS_FSFREQ_CLEANUP 0x00000010 |
337 | #define ZFCP_STATUS_FSFREQ_ABORTING 0x00000020 | ||
338 | #define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED 0x00000040 | 284 | #define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED 0x00000040 |
339 | #define ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED 0x00000080 | 285 | #define ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED 0x00000080 |
340 | #define ZFCP_STATUS_FSFREQ_ABORTED 0x00000100 | 286 | #define ZFCP_STATUS_FSFREQ_ABORTED 0x00000100 |
@@ -379,7 +325,7 @@ struct ct_hdr { | |||
379 | * a port name is required */ | 325 | * a port name is required */ |
380 | struct ct_iu_gid_pn_req { | 326 | struct ct_iu_gid_pn_req { |
381 | struct ct_hdr header; | 327 | struct ct_hdr header; |
382 | wwn_t wwpn; | 328 | u64 wwpn; |
383 | } __attribute__ ((packed)); | 329 | } __attribute__ ((packed)); |
384 | 330 | ||
385 | /* FS_ACC IU and data unit for GID_PN nameserver request */ | 331 | /* FS_ACC IU and data unit for GID_PN nameserver request */ |
@@ -388,11 +334,9 @@ struct ct_iu_gid_pn_resp { | |||
388 | u32 d_id; | 334 | u32 d_id; |
389 | } __attribute__ ((packed)); | 335 | } __attribute__ ((packed)); |
390 | 336 | ||
391 | typedef void (*zfcp_send_ct_handler_t)(unsigned long); | ||
392 | |||
393 | /** | 337 | /** |
394 | * struct zfcp_send_ct - used to pass parameters to function zfcp_fsf_send_ct | 338 | * struct zfcp_send_ct - used to pass parameters to function zfcp_fsf_send_ct |
395 | * @port: port where the request is sent to | 339 | * @wka_port: port where the request is sent to |
396 | * @req: scatter-gather list for request | 340 | * @req: scatter-gather list for request |
397 | * @resp: scatter-gather list for response | 341 | * @resp: scatter-gather list for response |
398 | * @req_count: number of elements in request scatter-gather list | 342 | * @req_count: number of elements in request scatter-gather list |
@@ -404,12 +348,12 @@ typedef void (*zfcp_send_ct_handler_t)(unsigned long); | |||
404 | * @status: used to pass error status to calling function | 348 | * @status: used to pass error status to calling function |
405 | */ | 349 | */ |
406 | struct zfcp_send_ct { | 350 | struct zfcp_send_ct { |
407 | struct zfcp_port *port; | 351 | struct zfcp_wka_port *wka_port; |
408 | struct scatterlist *req; | 352 | struct scatterlist *req; |
409 | struct scatterlist *resp; | 353 | struct scatterlist *resp; |
410 | unsigned int req_count; | 354 | unsigned int req_count; |
411 | unsigned int resp_count; | 355 | unsigned int resp_count; |
412 | zfcp_send_ct_handler_t handler; | 356 | void (*handler)(unsigned long); |
413 | unsigned long handler_data; | 357 | unsigned long handler_data; |
414 | int timeout; | 358 | int timeout; |
415 | struct completion *completion; | 359 | struct completion *completion; |
@@ -426,8 +370,6 @@ struct zfcp_gid_pn_data { | |||
426 | struct zfcp_port *port; | 370 | struct zfcp_port *port; |
427 | }; | 371 | }; |
428 | 372 | ||
429 | typedef void (*zfcp_send_els_handler_t)(unsigned long); | ||
430 | |||
431 | /** | 373 | /** |
432 | * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els | 374 | * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els |
433 | * @adapter: adapter where request is sent from | 375 | * @adapter: adapter where request is sent from |
@@ -451,22 +393,28 @@ struct zfcp_send_els { | |||
451 | struct scatterlist *resp; | 393 | struct scatterlist *resp; |
452 | unsigned int req_count; | 394 | unsigned int req_count; |
453 | unsigned int resp_count; | 395 | unsigned int resp_count; |
454 | zfcp_send_els_handler_t handler; | 396 | void (*handler)(unsigned long); |
455 | unsigned long handler_data; | 397 | unsigned long handler_data; |
456 | struct completion *completion; | 398 | struct completion *completion; |
457 | int ls_code; | 399 | int ls_code; |
458 | int status; | 400 | int status; |
459 | }; | 401 | }; |
460 | 402 | ||
403 | struct zfcp_wka_port { | ||
404 | struct zfcp_adapter *adapter; | ||
405 | wait_queue_head_t completion_wq; | ||
406 | enum zfcp_wka_status status; | ||
407 | atomic_t refcount; | ||
408 | u32 d_id; | ||
409 | u32 handle; | ||
410 | struct mutex mutex; | ||
411 | struct delayed_work work; | ||
412 | }; | ||
413 | |||
461 | struct zfcp_qdio_queue { | 414 | struct zfcp_qdio_queue { |
462 | struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; /* SBALs */ | 415 | struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; |
463 | u8 first; /* index of next free bfr | 416 | u8 first; /* index of next free bfr in queue */ |
464 | in queue (free_count>0) */ | 417 | atomic_t count; /* number of free buffers in queue */ |
465 | atomic_t count; /* number of free buffers | ||
466 | in queue */ | ||
467 | spinlock_t lock; /* lock for operations on queue */ | ||
468 | int pci_batch; /* SBALs since PCI indication | ||
469 | was last set */ | ||
470 | }; | 418 | }; |
471 | 419 | ||
472 | struct zfcp_erp_action { | 420 | struct zfcp_erp_action { |
@@ -475,7 +423,7 @@ struct zfcp_erp_action { | |||
475 | struct zfcp_adapter *adapter; /* device which should be recovered */ | 423 | struct zfcp_adapter *adapter; /* device which should be recovered */ |
476 | struct zfcp_port *port; | 424 | struct zfcp_port *port; |
477 | struct zfcp_unit *unit; | 425 | struct zfcp_unit *unit; |
478 | volatile u32 status; /* recovery status */ | 426 | u32 status; /* recovery status */ |
479 | u32 step; /* active step of this erp action */ | 427 | u32 step; /* active step of this erp action */ |
480 | struct zfcp_fsf_req *fsf_req; /* fsf request currently pending | 428 | struct zfcp_fsf_req *fsf_req; /* fsf request currently pending |
481 | for this action */ | 429 | for this action */ |
@@ -506,8 +454,8 @@ struct zfcp_adapter { | |||
506 | atomic_t refcount; /* reference count */ | 454 | atomic_t refcount; /* reference count */ |
507 | wait_queue_head_t remove_wq; /* can be used to wait for | 455 | wait_queue_head_t remove_wq; /* can be used to wait for |
508 | refcount drop to zero */ | 456 | refcount drop to zero */ |
509 | wwn_t peer_wwnn; /* P2P peer WWNN */ | 457 | u64 peer_wwnn; /* P2P peer WWNN */ |
510 | wwn_t peer_wwpn; /* P2P peer WWPN */ | 458 | u64 peer_wwpn; /* P2P peer WWPN */ |
511 | u32 peer_d_id; /* P2P peer D_ID */ | 459 | u32 peer_d_id; /* P2P peer D_ID */ |
512 | struct ccw_device *ccw_device; /* S/390 ccw device */ | 460 | struct ccw_device *ccw_device; /* S/390 ccw device */ |
513 | u32 hydra_version; /* Hydra version */ | 461 | u32 hydra_version; /* Hydra version */ |
@@ -518,13 +466,13 @@ struct zfcp_adapter { | |||
518 | u16 timer_ticks; /* time int for a tick */ | 466 | u16 timer_ticks; /* time int for a tick */ |
519 | struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ | 467 | struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ |
520 | struct list_head port_list_head; /* remote port list */ | 468 | struct list_head port_list_head; /* remote port list */ |
521 | struct list_head port_remove_lh; /* head of ports to be | ||
522 | removed */ | ||
523 | u32 ports; /* number of remote ports */ | ||
524 | unsigned long req_no; /* unique FSF req number */ | 469 | unsigned long req_no; /* unique FSF req number */ |
525 | struct list_head *req_list; /* list of pending reqs */ | 470 | struct list_head *req_list; /* list of pending reqs */ |
526 | spinlock_t req_list_lock; /* request list lock */ | 471 | spinlock_t req_list_lock; /* request list lock */ |
527 | struct zfcp_qdio_queue req_q; /* request queue */ | 472 | struct zfcp_qdio_queue req_q; /* request queue */ |
473 | spinlock_t req_q_lock; /* for operations on queue */ | ||
474 | int req_q_pci_batch; /* SBALs since PCI indication | ||
475 | was last set */ | ||
528 | u32 fsf_req_seq_no; /* FSF cmnd seq number */ | 476 | u32 fsf_req_seq_no; /* FSF cmnd seq number */ |
529 | wait_queue_head_t request_wq; /* can be used to wait for | 477 | wait_queue_head_t request_wq; /* can be used to wait for |
530 | more avaliable SBALs */ | 478 | more avaliable SBALs */ |
@@ -548,7 +496,7 @@ struct zfcp_adapter { | |||
548 | actions */ | 496 | actions */ |
549 | u32 erp_low_mem_count; /* nr of erp actions waiting | 497 | u32 erp_low_mem_count; /* nr of erp actions waiting |
550 | for memory */ | 498 | for memory */ |
551 | struct zfcp_port *nameserver_port; /* adapter's nameserver */ | 499 | struct zfcp_wka_port nsp; /* adapter's nameserver */ |
552 | debug_info_t *rec_dbf; | 500 | debug_info_t *rec_dbf; |
553 | debug_info_t *hba_dbf; | 501 | debug_info_t *hba_dbf; |
554 | debug_info_t *san_dbf; /* debug feature areas */ | 502 | debug_info_t *san_dbf; /* debug feature areas */ |
@@ -563,11 +511,11 @@ struct zfcp_adapter { | |||
563 | struct zfcp_scsi_dbf_record scsi_dbf_buf; | 511 | struct zfcp_scsi_dbf_record scsi_dbf_buf; |
564 | struct zfcp_adapter_mempool pool; /* Adapter memory pools */ | 512 | struct zfcp_adapter_mempool pool; /* Adapter memory pools */ |
565 | struct qdio_initialize qdio_init_data; /* for qdio_establish */ | 513 | struct qdio_initialize qdio_init_data; /* for qdio_establish */ |
566 | struct device generic_services; /* directory for WKA ports */ | ||
567 | struct fc_host_statistics *fc_stats; | 514 | struct fc_host_statistics *fc_stats; |
568 | struct fsf_qtcb_bottom_port *stats_reset_data; | 515 | struct fsf_qtcb_bottom_port *stats_reset_data; |
569 | unsigned long stats_reset; | 516 | unsigned long stats_reset; |
570 | struct work_struct scan_work; | 517 | struct work_struct scan_work; |
518 | atomic_t qdio_outb_full; /* queue full incidents */ | ||
571 | }; | 519 | }; |
572 | 520 | ||
573 | struct zfcp_port { | 521 | struct zfcp_port { |
@@ -579,18 +527,16 @@ struct zfcp_port { | |||
579 | refcount drop to zero */ | 527 | refcount drop to zero */ |
580 | struct zfcp_adapter *adapter; /* adapter used to access port */ | 528 | struct zfcp_adapter *adapter; /* adapter used to access port */ |
581 | struct list_head unit_list_head; /* head of logical unit list */ | 529 | struct list_head unit_list_head; /* head of logical unit list */ |
582 | struct list_head unit_remove_lh; /* head of luns to be removed | ||
583 | list */ | ||
584 | u32 units; /* # of logical units in list */ | ||
585 | atomic_t status; /* status of this remote port */ | 530 | atomic_t status; /* status of this remote port */ |
586 | wwn_t wwnn; /* WWNN if known */ | 531 | u64 wwnn; /* WWNN if known */ |
587 | wwn_t wwpn; /* WWPN */ | 532 | u64 wwpn; /* WWPN */ |
588 | u32 d_id; /* D_ID */ | 533 | u32 d_id; /* D_ID */ |
589 | u32 handle; /* handle assigned by FSF */ | 534 | u32 handle; /* handle assigned by FSF */ |
590 | struct zfcp_erp_action erp_action; /* pending error recovery */ | 535 | struct zfcp_erp_action erp_action; /* pending error recovery */ |
591 | atomic_t erp_counter; | 536 | atomic_t erp_counter; |
592 | u32 maxframe_size; | 537 | u32 maxframe_size; |
593 | u32 supported_classes; | 538 | u32 supported_classes; |
539 | struct work_struct gid_pn_work; | ||
594 | }; | 540 | }; |
595 | 541 | ||
596 | struct zfcp_unit { | 542 | struct zfcp_unit { |
@@ -601,8 +547,7 @@ struct zfcp_unit { | |||
601 | refcount drop to zero */ | 547 | refcount drop to zero */ |
602 | struct zfcp_port *port; /* remote port of unit */ | 548 | struct zfcp_port *port; /* remote port of unit */ |
603 | atomic_t status; /* status of this logical unit */ | 549 | atomic_t status; /* status of this logical unit */ |
604 | unsigned int scsi_lun; /* own SCSI LUN */ | 550 | u64 fcp_lun; /* own FCP_LUN */ |
605 | fcp_lun_t fcp_lun; /* own FCP_LUN */ | ||
606 | u32 handle; /* handle assigned by FSF */ | 551 | u32 handle; /* handle assigned by FSF */ |
607 | struct scsi_device *device; /* scsi device struct pointer */ | 552 | struct scsi_device *device; /* scsi device struct pointer */ |
608 | struct zfcp_erp_action erp_action; /* pending error recovery */ | 553 | struct zfcp_erp_action erp_action; /* pending error recovery */ |
@@ -625,7 +570,7 @@ struct zfcp_fsf_req { | |||
625 | u8 sbal_response; /* SBAL used in interrupt */ | 570 | u8 sbal_response; /* SBAL used in interrupt */ |
626 | wait_queue_head_t completion_wq; /* can be used by a routine | 571 | wait_queue_head_t completion_wq; /* can be used by a routine |
627 | to wait for completion */ | 572 | to wait for completion */ |
628 | volatile u32 status; /* status of this request */ | 573 | u32 status; /* status of this request */ |
629 | u32 fsf_command; /* FSF Command copy */ | 574 | u32 fsf_command; /* FSF Command copy */ |
630 | struct fsf_qtcb *qtcb; /* address of associated QTCB */ | 575 | struct fsf_qtcb *qtcb; /* address of associated QTCB */ |
631 | u32 seq_no; /* Sequence number of request */ | 576 | u32 seq_no; /* Sequence number of request */ |
@@ -644,11 +589,7 @@ struct zfcp_fsf_req { | |||
644 | struct zfcp_data { | 589 | struct zfcp_data { |
645 | struct scsi_host_template scsi_host_template; | 590 | struct scsi_host_template scsi_host_template; |
646 | struct scsi_transport_template *scsi_transport_template; | 591 | struct scsi_transport_template *scsi_transport_template; |
647 | atomic_t status; /* Module status flags */ | ||
648 | struct list_head adapter_list_head; /* head of adapter list */ | 592 | struct list_head adapter_list_head; /* head of adapter list */ |
649 | struct list_head adapter_remove_lh; /* head of adapters to be | ||
650 | removed */ | ||
651 | u32 adapters; /* # of adapters in list */ | ||
652 | rwlock_t config_lock; /* serialises changes | 593 | rwlock_t config_lock; /* serialises changes |
653 | to adapter/port/unit | 594 | to adapter/port/unit |
654 | lists */ | 595 | lists */ |
@@ -656,11 +597,12 @@ struct zfcp_data { | |||
656 | changes */ | 597 | changes */ |
657 | atomic_t loglevel; /* current loglevel */ | 598 | atomic_t loglevel; /* current loglevel */ |
658 | char init_busid[BUS_ID_SIZE]; | 599 | char init_busid[BUS_ID_SIZE]; |
659 | wwn_t init_wwpn; | 600 | u64 init_wwpn; |
660 | fcp_lun_t init_fcp_lun; | 601 | u64 init_fcp_lun; |
661 | struct kmem_cache *fsf_req_qtcb_cache; | 602 | struct kmem_cache *fsf_req_qtcb_cache; |
662 | struct kmem_cache *sr_buffer_cache; | 603 | struct kmem_cache *sr_buffer_cache; |
663 | struct kmem_cache *gid_pn_cache; | 604 | struct kmem_cache *gid_pn_cache; |
605 | struct workqueue_struct *work_queue; | ||
664 | }; | 606 | }; |
665 | 607 | ||
666 | /* struct used by memory pools for fsf_requests */ | 608 | /* struct used by memory pools for fsf_requests */ |
@@ -677,14 +619,7 @@ struct zfcp_fsf_req_qtcb { | |||
677 | #define ZFCP_SET 0x00000100 | 619 | #define ZFCP_SET 0x00000100 |
678 | #define ZFCP_CLEAR 0x00000200 | 620 | #define ZFCP_CLEAR 0x00000200 |
679 | 621 | ||
680 | #ifndef atomic_test_mask | ||
681 | #define atomic_test_mask(mask, target) \ | ||
682 | ((atomic_read(target) & mask) == mask) | ||
683 | #endif | ||
684 | |||
685 | #define zfcp_get_busid_by_adapter(adapter) (adapter->ccw_device->dev.bus_id) | 622 | #define zfcp_get_busid_by_adapter(adapter) (adapter->ccw_device->dev.bus_id) |
686 | #define zfcp_get_busid_by_port(port) (zfcp_get_busid_by_adapter(port->adapter)) | ||
687 | #define zfcp_get_busid_by_unit(unit) (zfcp_get_busid_by_port(unit->port)) | ||
688 | 623 | ||
689 | /* | 624 | /* |
690 | * Helper functions for request ID management. | 625 | * Helper functions for request ID management. |
@@ -745,12 +680,6 @@ zfcp_unit_put(struct zfcp_unit *unit) | |||
745 | } | 680 | } |
746 | 681 | ||
747 | static inline void | 682 | static inline void |
748 | zfcp_unit_wait(struct zfcp_unit *unit) | ||
749 | { | ||
750 | wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0); | ||
751 | } | ||
752 | |||
753 | static inline void | ||
754 | zfcp_port_get(struct zfcp_port *port) | 683 | zfcp_port_get(struct zfcp_port *port) |
755 | { | 684 | { |
756 | atomic_inc(&port->refcount); | 685 | atomic_inc(&port->refcount); |
@@ -764,12 +693,6 @@ zfcp_port_put(struct zfcp_port *port) | |||
764 | } | 693 | } |
765 | 694 | ||
766 | static inline void | 695 | static inline void |
767 | zfcp_port_wait(struct zfcp_port *port) | ||
768 | { | ||
769 | wait_event(port->remove_wq, atomic_read(&port->refcount) == 0); | ||
770 | } | ||
771 | |||
772 | static inline void | ||
773 | zfcp_adapter_get(struct zfcp_adapter *adapter) | 696 | zfcp_adapter_get(struct zfcp_adapter *adapter) |
774 | { | 697 | { |
775 | atomic_inc(&adapter->refcount); | 698 | atomic_inc(&adapter->refcount); |
@@ -782,10 +705,4 @@ zfcp_adapter_put(struct zfcp_adapter *adapter) | |||
782 | wake_up(&adapter->remove_wq); | 705 | wake_up(&adapter->remove_wq); |
783 | } | 706 | } |
784 | 707 | ||
785 | static inline void | ||
786 | zfcp_adapter_wait(struct zfcp_adapter *adapter) | ||
787 | { | ||
788 | wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0); | ||
789 | } | ||
790 | |||
791 | #endif /* ZFCP_DEF_H */ | 708 | #endif /* ZFCP_DEF_H */ |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 643ac4bba5b5..782313131870 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -23,7 +23,6 @@ enum zfcp_erp_steps { | |||
23 | ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001, | 23 | ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001, |
24 | ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, | 24 | ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, |
25 | ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, | 25 | ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, |
26 | ZFCP_ERP_STEP_NAMESERVER_OPEN = 0x0200, | ||
27 | ZFCP_ERP_STEP_NAMESERVER_LOOKUP = 0x0400, | 26 | ZFCP_ERP_STEP_NAMESERVER_LOOKUP = 0x0400, |
28 | ZFCP_ERP_STEP_PORT_OPENING = 0x0800, | 27 | ZFCP_ERP_STEP_PORT_OPENING = 0x0800, |
29 | ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000, | 28 | ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000, |
@@ -532,8 +531,7 @@ static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, | |||
532 | struct zfcp_port *port; | 531 | struct zfcp_port *port; |
533 | 532 | ||
534 | list_for_each_entry(port, &adapter->port_list_head, list) | 533 | list_for_each_entry(port, &adapter->port_list_head, list) |
535 | if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA)) | 534 | _zfcp_erp_port_reopen(port, clear, id, ref); |
536 | _zfcp_erp_port_reopen(port, clear, id, ref); | ||
537 | } | 535 | } |
538 | 536 | ||
539 | static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, u8 id, | 537 | static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, u8 id, |
@@ -669,8 +667,6 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act) | |||
669 | int ret; | 667 | int ret; |
670 | struct zfcp_adapter *adapter = act->adapter; | 668 | struct zfcp_adapter *adapter = act->adapter; |
671 | 669 | ||
672 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); | ||
673 | |||
674 | write_lock_irq(&adapter->erp_lock); | 670 | write_lock_irq(&adapter->erp_lock); |
675 | zfcp_erp_action_to_running(act); | 671 | zfcp_erp_action_to_running(act); |
676 | write_unlock_irq(&adapter->erp_lock); | 672 | write_unlock_irq(&adapter->erp_lock); |
@@ -741,8 +737,7 @@ static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *act, | |||
741 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); | 737 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); |
742 | failed_qdio: | 738 | failed_qdio: |
743 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | | 739 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | |
744 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | | 740 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, |
745 | ZFCP_STATUS_ADAPTER_XPORT_OK, | ||
746 | &act->adapter->status); | 741 | &act->adapter->status); |
747 | return retval; | 742 | return retval; |
748 | } | 743 | } |
@@ -751,15 +746,11 @@ static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *act) | |||
751 | { | 746 | { |
752 | int retval; | 747 | int retval; |
753 | 748 | ||
754 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &act->adapter->status); | ||
755 | zfcp_erp_adapter_strategy_generic(act, 1); /* close */ | 749 | zfcp_erp_adapter_strategy_generic(act, 1); /* close */ |
756 | atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &act->adapter->status); | ||
757 | if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | 750 | if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY) |
758 | return ZFCP_ERP_EXIT; | 751 | return ZFCP_ERP_EXIT; |
759 | 752 | ||
760 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &act->adapter->status); | ||
761 | retval = zfcp_erp_adapter_strategy_generic(act, 0); /* open */ | 753 | retval = zfcp_erp_adapter_strategy_generic(act, 0); /* open */ |
762 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &act->adapter->status); | ||
763 | 754 | ||
764 | if (retval == ZFCP_ERP_FAILED) | 755 | if (retval == ZFCP_ERP_FAILED) |
765 | ssleep(8); | 756 | ssleep(8); |
@@ -783,10 +774,7 @@ static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act) | |||
783 | 774 | ||
784 | static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) | 775 | static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) |
785 | { | 776 | { |
786 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | | 777 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | |
787 | ZFCP_STATUS_COMMON_CLOSING | | ||
788 | ZFCP_STATUS_COMMON_ACCESS_DENIED | | ||
789 | ZFCP_STATUS_PORT_DID_DID | | ||
790 | ZFCP_STATUS_PORT_PHYS_CLOSING | | 778 | ZFCP_STATUS_PORT_PHYS_CLOSING | |
791 | ZFCP_STATUS_PORT_INVALID_WWPN, | 779 | ZFCP_STATUS_PORT_INVALID_WWPN, |
792 | &port->status); | 780 | &port->status); |
@@ -839,73 +827,12 @@ static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action) | |||
839 | return ZFCP_ERP_CONTINUES; | 827 | return ZFCP_ERP_CONTINUES; |
840 | } | 828 | } |
841 | 829 | ||
842 | static void zfcp_erp_port_strategy_open_ns_wake(struct zfcp_erp_action *ns_act) | ||
843 | { | ||
844 | unsigned long flags; | ||
845 | struct zfcp_adapter *adapter = ns_act->adapter; | ||
846 | struct zfcp_erp_action *act, *tmp; | ||
847 | int status; | ||
848 | |||
849 | read_lock_irqsave(&adapter->erp_lock, flags); | ||
850 | list_for_each_entry_safe(act, tmp, &adapter->erp_running_head, list) { | ||
851 | if (act->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) { | ||
852 | status = atomic_read(&adapter->nameserver_port->status); | ||
853 | if (status & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
854 | zfcp_erp_port_failed(act->port, 27, NULL); | ||
855 | zfcp_erp_action_ready(act); | ||
856 | } | ||
857 | } | ||
858 | read_unlock_irqrestore(&adapter->erp_lock, flags); | ||
859 | } | ||
860 | |||
861 | static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *act) | ||
862 | { | ||
863 | int retval; | ||
864 | |||
865 | switch (act->step) { | ||
866 | case ZFCP_ERP_STEP_UNINITIALIZED: | ||
867 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: | ||
868 | case ZFCP_ERP_STEP_PORT_CLOSING: | ||
869 | return zfcp_erp_port_strategy_open_port(act); | ||
870 | |||
871 | case ZFCP_ERP_STEP_PORT_OPENING: | ||
872 | if (atomic_read(&act->port->status) & ZFCP_STATUS_COMMON_OPEN) | ||
873 | retval = ZFCP_ERP_SUCCEEDED; | ||
874 | else | ||
875 | retval = ZFCP_ERP_FAILED; | ||
876 | /* this is needed anyway */ | ||
877 | zfcp_erp_port_strategy_open_ns_wake(act); | ||
878 | return retval; | ||
879 | |||
880 | default: | ||
881 | return ZFCP_ERP_FAILED; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | static int zfcp_erp_port_strategy_open_lookup(struct zfcp_erp_action *act) | ||
886 | { | ||
887 | int retval; | ||
888 | |||
889 | retval = zfcp_fc_ns_gid_pn_request(act); | ||
890 | if (retval == -ENOMEM) | ||
891 | return ZFCP_ERP_NOMEM; | ||
892 | act->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; | ||
893 | if (retval) | ||
894 | return ZFCP_ERP_FAILED; | ||
895 | return ZFCP_ERP_CONTINUES; | ||
896 | } | ||
897 | |||
898 | static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) | 830 | static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) |
899 | { | 831 | { |
900 | struct zfcp_adapter *adapter = act->adapter; | 832 | struct zfcp_adapter *adapter = act->adapter; |
901 | struct zfcp_port *port = act->port; | 833 | struct zfcp_port *port = act->port; |
902 | 834 | ||
903 | if (port->wwpn != adapter->peer_wwpn) { | 835 | if (port->wwpn != adapter->peer_wwpn) { |
904 | dev_err(&adapter->ccw_device->dev, | ||
905 | "Failed to open port 0x%016Lx, " | ||
906 | "Peer WWPN 0x%016Lx does not " | ||
907 | "match.\n", port->wwpn, | ||
908 | adapter->peer_wwpn); | ||
909 | zfcp_erp_port_failed(port, 25, NULL); | 836 | zfcp_erp_port_failed(port, 25, NULL); |
910 | return ZFCP_ERP_FAILED; | 837 | return ZFCP_ERP_FAILED; |
911 | } | 838 | } |
@@ -914,11 +841,25 @@ static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) | |||
914 | return zfcp_erp_port_strategy_open_port(act); | 841 | return zfcp_erp_port_strategy_open_port(act); |
915 | } | 842 | } |
916 | 843 | ||
844 | void zfcp_erp_port_strategy_open_lookup(struct work_struct *work) | ||
845 | { | ||
846 | int retval; | ||
847 | struct zfcp_port *port = container_of(work, struct zfcp_port, | ||
848 | gid_pn_work); | ||
849 | |||
850 | retval = zfcp_fc_ns_gid_pn(&port->erp_action); | ||
851 | if (retval == -ENOMEM) | ||
852 | zfcp_erp_notify(&port->erp_action, ZFCP_ERP_NOMEM); | ||
853 | port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; | ||
854 | if (retval) | ||
855 | zfcp_erp_notify(&port->erp_action, ZFCP_ERP_FAILED); | ||
856 | |||
857 | } | ||
858 | |||
917 | static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) | 859 | static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) |
918 | { | 860 | { |
919 | struct zfcp_adapter *adapter = act->adapter; | 861 | struct zfcp_adapter *adapter = act->adapter; |
920 | struct zfcp_port *port = act->port; | 862 | struct zfcp_port *port = act->port; |
921 | struct zfcp_port *ns_port = adapter->nameserver_port; | ||
922 | int p_status = atomic_read(&port->status); | 863 | int p_status = atomic_read(&port->status); |
923 | 864 | ||
924 | switch (act->step) { | 865 | switch (act->step) { |
@@ -927,28 +868,10 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) | |||
927 | case ZFCP_ERP_STEP_PORT_CLOSING: | 868 | case ZFCP_ERP_STEP_PORT_CLOSING: |
928 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) | 869 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) |
929 | return zfcp_erp_open_ptp_port(act); | 870 | return zfcp_erp_open_ptp_port(act); |
930 | if (!ns_port) { | 871 | if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) { |
931 | dev_err(&adapter->ccw_device->dev, | 872 | queue_work(zfcp_data.work_queue, &port->gid_pn_work); |
932 | "Nameserver port unavailable.\n"); | 873 | return ZFCP_ERP_CONTINUES; |
933 | return ZFCP_ERP_FAILED; | ||
934 | } | ||
935 | if (!(atomic_read(&ns_port->status) & | ||
936 | ZFCP_STATUS_COMMON_UNBLOCKED)) { | ||
937 | /* nameserver port may live again */ | ||
938 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, | ||
939 | &ns_port->status); | ||
940 | if (zfcp_erp_port_reopen(ns_port, 0, 77, act) >= 0) { | ||
941 | act->step = ZFCP_ERP_STEP_NAMESERVER_OPEN; | ||
942 | return ZFCP_ERP_CONTINUES; | ||
943 | } | ||
944 | return ZFCP_ERP_FAILED; | ||
945 | } | 874 | } |
946 | /* else nameserver port is already open, fall through */ | ||
947 | case ZFCP_ERP_STEP_NAMESERVER_OPEN: | ||
948 | if (!(atomic_read(&ns_port->status) & ZFCP_STATUS_COMMON_OPEN)) | ||
949 | return ZFCP_ERP_FAILED; | ||
950 | return zfcp_erp_port_strategy_open_lookup(act); | ||
951 | |||
952 | case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: | 875 | case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: |
953 | if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) { | 876 | if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) { |
954 | if (p_status & (ZFCP_STATUS_PORT_INVALID_WWPN)) { | 877 | if (p_status & (ZFCP_STATUS_PORT_INVALID_WWPN)) { |
@@ -961,25 +884,26 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) | |||
961 | 884 | ||
962 | case ZFCP_ERP_STEP_PORT_OPENING: | 885 | case ZFCP_ERP_STEP_PORT_OPENING: |
963 | /* D_ID might have changed during open */ | 886 | /* D_ID might have changed during open */ |
964 | if ((p_status & ZFCP_STATUS_COMMON_OPEN) && | 887 | if (p_status & ZFCP_STATUS_COMMON_OPEN) { |
965 | (p_status & ZFCP_STATUS_PORT_DID_DID)) | 888 | if (p_status & ZFCP_STATUS_PORT_DID_DID) |
966 | return ZFCP_ERP_SUCCEEDED; | 889 | return ZFCP_ERP_SUCCEEDED; |
890 | else { | ||
891 | act->step = ZFCP_ERP_STEP_PORT_CLOSING; | ||
892 | return ZFCP_ERP_CONTINUES; | ||
893 | } | ||
967 | /* fall through otherwise */ | 894 | /* fall through otherwise */ |
895 | } | ||
968 | } | 896 | } |
969 | return ZFCP_ERP_FAILED; | 897 | return ZFCP_ERP_FAILED; |
970 | } | 898 | } |
971 | 899 | ||
972 | static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *act) | ||
973 | { | ||
974 | if (atomic_read(&act->port->status) & (ZFCP_STATUS_PORT_WKA)) | ||
975 | return zfcp_erp_port_strategy_open_nameserver(act); | ||
976 | return zfcp_erp_port_strategy_open_common(act); | ||
977 | } | ||
978 | |||
979 | static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) | 900 | static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) |
980 | { | 901 | { |
981 | struct zfcp_port *port = erp_action->port; | 902 | struct zfcp_port *port = erp_action->port; |
982 | 903 | ||
904 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) | ||
905 | goto close_init_done; | ||
906 | |||
983 | switch (erp_action->step) { | 907 | switch (erp_action->step) { |
984 | case ZFCP_ERP_STEP_UNINITIALIZED: | 908 | case ZFCP_ERP_STEP_UNINITIALIZED: |
985 | zfcp_erp_port_strategy_clearstati(port); | 909 | zfcp_erp_port_strategy_clearstati(port); |
@@ -992,19 +916,17 @@ static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) | |||
992 | return ZFCP_ERP_FAILED; | 916 | return ZFCP_ERP_FAILED; |
993 | break; | 917 | break; |
994 | } | 918 | } |
919 | |||
920 | close_init_done: | ||
995 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | 921 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) |
996 | return ZFCP_ERP_EXIT; | 922 | return ZFCP_ERP_EXIT; |
997 | else | ||
998 | return zfcp_erp_port_strategy_open(erp_action); | ||
999 | 923 | ||
1000 | return ZFCP_ERP_FAILED; | 924 | return zfcp_erp_port_strategy_open_common(erp_action); |
1001 | } | 925 | } |
1002 | 926 | ||
1003 | static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) | 927 | static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) |
1004 | { | 928 | { |
1005 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | | 929 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | |
1006 | ZFCP_STATUS_COMMON_CLOSING | | ||
1007 | ZFCP_STATUS_COMMON_ACCESS_DENIED | | ||
1008 | ZFCP_STATUS_UNIT_SHARED | | 930 | ZFCP_STATUS_UNIT_SHARED | |
1009 | ZFCP_STATUS_UNIT_READONLY, | 931 | ZFCP_STATUS_UNIT_READONLY, |
1010 | &unit->status); | 932 | &unit->status); |
@@ -1065,8 +987,14 @@ static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) | |||
1065 | break; | 987 | break; |
1066 | case ZFCP_ERP_FAILED : | 988 | case ZFCP_ERP_FAILED : |
1067 | atomic_inc(&unit->erp_counter); | 989 | atomic_inc(&unit->erp_counter); |
1068 | if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) | 990 | if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) { |
991 | dev_err(&unit->port->adapter->ccw_device->dev, | ||
992 | "ERP failed for unit 0x%016Lx on " | ||
993 | "port 0x%016Lx\n", | ||
994 | (unsigned long long)unit->fcp_lun, | ||
995 | (unsigned long long)unit->port->wwpn); | ||
1069 | zfcp_erp_unit_failed(unit, 21, NULL); | 996 | zfcp_erp_unit_failed(unit, 21, NULL); |
997 | } | ||
1070 | break; | 998 | break; |
1071 | } | 999 | } |
1072 | 1000 | ||
@@ -1091,8 +1019,12 @@ static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) | |||
1091 | result = ZFCP_ERP_EXIT; | 1019 | result = ZFCP_ERP_EXIT; |
1092 | } | 1020 | } |
1093 | atomic_inc(&port->erp_counter); | 1021 | atomic_inc(&port->erp_counter); |
1094 | if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) | 1022 | if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) { |
1023 | dev_err(&port->adapter->ccw_device->dev, | ||
1024 | "ERP failed for remote port 0x%016Lx\n", | ||
1025 | (unsigned long long)port->wwpn); | ||
1095 | zfcp_erp_port_failed(port, 22, NULL); | 1026 | zfcp_erp_port_failed(port, 22, NULL); |
1027 | } | ||
1096 | break; | 1028 | break; |
1097 | } | 1029 | } |
1098 | 1030 | ||
@@ -1114,8 +1046,12 @@ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, | |||
1114 | 1046 | ||
1115 | case ZFCP_ERP_FAILED : | 1047 | case ZFCP_ERP_FAILED : |
1116 | atomic_inc(&adapter->erp_counter); | 1048 | atomic_inc(&adapter->erp_counter); |
1117 | if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) | 1049 | if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) { |
1050 | dev_err(&adapter->ccw_device->dev, | ||
1051 | "ERP cannot recover an error " | ||
1052 | "on the FCP device\n"); | ||
1118 | zfcp_erp_adapter_failed(adapter, 23, NULL); | 1053 | zfcp_erp_adapter_failed(adapter, 23, NULL); |
1054 | } | ||
1119 | break; | 1055 | break; |
1120 | } | 1056 | } |
1121 | 1057 | ||
@@ -1250,9 +1186,10 @@ static void zfcp_erp_scsi_scan(struct work_struct *work) | |||
1250 | struct zfcp_unit *unit = p->unit; | 1186 | struct zfcp_unit *unit = p->unit; |
1251 | struct fc_rport *rport = unit->port->rport; | 1187 | struct fc_rport *rport = unit->port->rport; |
1252 | scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, | 1188 | scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, |
1253 | unit->scsi_lun, 0); | 1189 | scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0); |
1254 | atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); | 1190 | atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); |
1255 | zfcp_unit_put(unit); | 1191 | zfcp_unit_put(unit); |
1192 | wake_up(&unit->port->adapter->erp_done_wqh); | ||
1256 | kfree(p); | 1193 | kfree(p); |
1257 | } | 1194 | } |
1258 | 1195 | ||
@@ -1263,9 +1200,9 @@ static void zfcp_erp_schedule_work(struct zfcp_unit *unit) | |||
1263 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 1200 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
1264 | if (!p) { | 1201 | if (!p) { |
1265 | dev_err(&unit->port->adapter->ccw_device->dev, | 1202 | dev_err(&unit->port->adapter->ccw_device->dev, |
1266 | "Out of resources. Could not register unit " | 1203 | "Registering unit 0x%016Lx on port 0x%016Lx failed\n", |
1267 | "0x%016Lx on port 0x%016Lx with SCSI stack.\n", | 1204 | (unsigned long long)unit->fcp_lun, |
1268 | unit->fcp_lun, unit->port->wwpn); | 1205 | (unsigned long long)unit->port->wwpn); |
1269 | return; | 1206 | return; |
1270 | } | 1207 | } |
1271 | 1208 | ||
@@ -1273,7 +1210,7 @@ static void zfcp_erp_schedule_work(struct zfcp_unit *unit) | |||
1273 | atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); | 1210 | atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); |
1274 | INIT_WORK(&p->work, zfcp_erp_scsi_scan); | 1211 | INIT_WORK(&p->work, zfcp_erp_scsi_scan); |
1275 | p->unit = unit; | 1212 | p->unit = unit; |
1276 | schedule_work(&p->work); | 1213 | queue_work(zfcp_data.work_queue, &p->work); |
1277 | } | 1214 | } |
1278 | 1215 | ||
1279 | static void zfcp_erp_rport_register(struct zfcp_port *port) | 1216 | static void zfcp_erp_rport_register(struct zfcp_port *port) |
@@ -1286,8 +1223,8 @@ static void zfcp_erp_rport_register(struct zfcp_port *port) | |||
1286 | port->rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); | 1223 | port->rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); |
1287 | if (!port->rport) { | 1224 | if (!port->rport) { |
1288 | dev_err(&port->adapter->ccw_device->dev, | 1225 | dev_err(&port->adapter->ccw_device->dev, |
1289 | "Failed registration of rport " | 1226 | "Registering port 0x%016Lx failed\n", |
1290 | "0x%016Lx.\n", port->wwpn); | 1227 | (unsigned long long)port->wwpn); |
1291 | return; | 1228 | return; |
1292 | } | 1229 | } |
1293 | 1230 | ||
@@ -1299,12 +1236,12 @@ static void zfcp_erp_rport_register(struct zfcp_port *port) | |||
1299 | static void zfcp_erp_rports_del(struct zfcp_adapter *adapter) | 1236 | static void zfcp_erp_rports_del(struct zfcp_adapter *adapter) |
1300 | { | 1237 | { |
1301 | struct zfcp_port *port; | 1238 | struct zfcp_port *port; |
1302 | list_for_each_entry(port, &adapter->port_list_head, list) | 1239 | list_for_each_entry(port, &adapter->port_list_head, list) { |
1303 | if (port->rport && !(atomic_read(&port->status) & | 1240 | if (!port->rport) |
1304 | ZFCP_STATUS_PORT_WKA)) { | 1241 | continue; |
1305 | fc_remote_port_delete(port->rport); | 1242 | fc_remote_port_delete(port->rport); |
1306 | port->rport = NULL; | 1243 | port->rport = NULL; |
1307 | } | 1244 | } |
1308 | } | 1245 | } |
1309 | 1246 | ||
1310 | static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) | 1247 | static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) |
@@ -1459,9 +1396,9 @@ static int zfcp_erp_thread(void *data) | |||
1459 | zfcp_erp_wakeup(adapter); | 1396 | zfcp_erp_wakeup(adapter); |
1460 | } | 1397 | } |
1461 | 1398 | ||
1462 | zfcp_rec_dbf_event_thread(4, adapter); | 1399 | zfcp_rec_dbf_event_thread_lock(4, adapter); |
1463 | down_interruptible(&adapter->erp_ready_sem); | 1400 | down_interruptible(&adapter->erp_ready_sem); |
1464 | zfcp_rec_dbf_event_thread(5, adapter); | 1401 | zfcp_rec_dbf_event_thread_lock(5, adapter); |
1465 | } | 1402 | } |
1466 | 1403 | ||
1467 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | 1404 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); |
@@ -1484,7 +1421,7 @@ int zfcp_erp_thread_setup(struct zfcp_adapter *adapter) | |||
1484 | retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); | 1421 | retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); |
1485 | if (retval < 0) { | 1422 | if (retval < 0) { |
1486 | dev_err(&adapter->ccw_device->dev, | 1423 | dev_err(&adapter->ccw_device->dev, |
1487 | "Creation of ERP thread failed.\n"); | 1424 | "Creating an ERP thread for the FCP device failed.\n"); |
1488 | return retval; | 1425 | return retval; |
1489 | } | 1426 | } |
1490 | wait_event(adapter->erp_thread_wqh, | 1427 | wait_event(adapter->erp_thread_wqh, |
@@ -1506,7 +1443,7 @@ void zfcp_erp_thread_kill(struct zfcp_adapter *adapter) | |||
1506 | { | 1443 | { |
1507 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status); | 1444 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status); |
1508 | up(&adapter->erp_ready_sem); | 1445 | up(&adapter->erp_ready_sem); |
1509 | zfcp_rec_dbf_event_thread_lock(2, adapter); | 1446 | zfcp_rec_dbf_event_thread_lock(3, adapter); |
1510 | 1447 | ||
1511 | wait_event(adapter->erp_thread_wqh, | 1448 | wait_event(adapter->erp_thread_wqh, |
1512 | !(atomic_read(&adapter->status) & | 1449 | !(atomic_read(&adapter->status) & |
@@ -1526,7 +1463,6 @@ void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref) | |||
1526 | { | 1463 | { |
1527 | zfcp_erp_modify_adapter_status(adapter, id, ref, | 1464 | zfcp_erp_modify_adapter_status(adapter, id, ref, |
1528 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | 1465 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); |
1529 | dev_err(&adapter->ccw_device->dev, "Adapter ERP failed.\n"); | ||
1530 | } | 1466 | } |
1531 | 1467 | ||
1532 | /** | 1468 | /** |
@@ -1539,15 +1475,6 @@ void zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref) | |||
1539 | { | 1475 | { |
1540 | zfcp_erp_modify_port_status(port, id, ref, | 1476 | zfcp_erp_modify_port_status(port, id, ref, |
1541 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | 1477 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); |
1542 | |||
1543 | if (atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA) | ||
1544 | dev_err(&port->adapter->ccw_device->dev, | ||
1545 | "Port ERP failed for WKA port d_id=0x%06x.\n", | ||
1546 | port->d_id); | ||
1547 | else | ||
1548 | dev_err(&port->adapter->ccw_device->dev, | ||
1549 | "Port ERP failed for port wwpn=0x%016Lx.\n", | ||
1550 | port->wwpn); | ||
1551 | } | 1478 | } |
1552 | 1479 | ||
1553 | /** | 1480 | /** |
@@ -1560,10 +1487,6 @@ void zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, void *ref) | |||
1560 | { | 1487 | { |
1561 | zfcp_erp_modify_unit_status(unit, id, ref, | 1488 | zfcp_erp_modify_unit_status(unit, id, ref, |
1562 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | 1489 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); |
1563 | |||
1564 | dev_err(&unit->port->adapter->ccw_device->dev, | ||
1565 | "Unit ERP failed for unit 0x%016Lx on port 0x%016Lx.\n", | ||
1566 | unit->fcp_lun, unit->port->wwpn); | ||
1567 | } | 1490 | } |
1568 | 1491 | ||
1569 | /** | 1492 | /** |
@@ -1754,9 +1677,8 @@ static void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, | |||
1754 | 1677 | ||
1755 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | | 1678 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | |
1756 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) { | 1679 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) { |
1757 | if (!(status & ZFCP_STATUS_PORT_WKA)) | 1680 | list_for_each_entry(unit, &port->unit_list_head, list) |
1758 | list_for_each_entry(unit, &port->unit_list_head, list) | 1681 | zfcp_erp_unit_access_changed(unit, id, ref); |
1759 | zfcp_erp_unit_access_changed(unit, id, ref); | ||
1760 | return; | 1682 | return; |
1761 | } | 1683 | } |
1762 | 1684 | ||
@@ -1779,10 +1701,7 @@ void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id, | |||
1779 | return; | 1701 | return; |
1780 | 1702 | ||
1781 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 1703 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
1782 | if (adapter->nameserver_port) | ||
1783 | zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref); | ||
1784 | list_for_each_entry(port, &adapter->port_list_head, list) | 1704 | list_for_each_entry(port, &adapter->port_list_head, list) |
1785 | if (port != adapter->nameserver_port) | 1705 | zfcp_erp_port_access_changed(port, id, ref); |
1786 | zfcp_erp_port_access_changed(port, id, ref); | ||
1787 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 1706 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
1788 | } | 1707 | } |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index edfdb21591f3..b5adeda93e1d 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -12,16 +12,14 @@ | |||
12 | #include "zfcp_def.h" | 12 | #include "zfcp_def.h" |
13 | 13 | ||
14 | /* zfcp_aux.c */ | 14 | /* zfcp_aux.c */ |
15 | extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, | 15 | extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64); |
16 | fcp_lun_t); | 16 | extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64); |
17 | extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, | ||
18 | wwn_t); | ||
19 | extern int zfcp_adapter_enqueue(struct ccw_device *); | 17 | extern int zfcp_adapter_enqueue(struct ccw_device *); |
20 | extern void zfcp_adapter_dequeue(struct zfcp_adapter *); | 18 | extern void zfcp_adapter_dequeue(struct zfcp_adapter *); |
21 | extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, wwn_t, u32, | 19 | extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, |
22 | u32); | 20 | u32); |
23 | extern void zfcp_port_dequeue(struct zfcp_port *); | 21 | extern void zfcp_port_dequeue(struct zfcp_port *); |
24 | extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, fcp_lun_t); | 22 | extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64); |
25 | extern void zfcp_unit_dequeue(struct zfcp_unit *); | 23 | extern void zfcp_unit_dequeue(struct zfcp_unit *); |
26 | extern int zfcp_reqlist_isempty(struct zfcp_adapter *); | 24 | extern int zfcp_reqlist_isempty(struct zfcp_adapter *); |
27 | extern void zfcp_sg_free_table(struct scatterlist *, int); | 25 | extern void zfcp_sg_free_table(struct scatterlist *, int); |
@@ -29,6 +27,7 @@ extern int zfcp_sg_setup_table(struct scatterlist *, int); | |||
29 | 27 | ||
30 | /* zfcp_ccw.c */ | 28 | /* zfcp_ccw.c */ |
31 | extern int zfcp_ccw_register(void); | 29 | extern int zfcp_ccw_register(void); |
30 | extern struct zfcp_adapter *zfcp_get_adapter_by_busid(char *); | ||
32 | 31 | ||
33 | /* zfcp_cfdc.c */ | 32 | /* zfcp_cfdc.c */ |
34 | extern struct miscdevice zfcp_cfdc_misc; | 33 | extern struct miscdevice zfcp_cfdc_misc; |
@@ -50,6 +49,8 @@ extern void zfcp_hba_dbf_event_fsf_unsol(const char *, struct zfcp_adapter *, | |||
50 | struct fsf_status_read_buffer *); | 49 | struct fsf_status_read_buffer *); |
51 | extern void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *, unsigned int, int, | 50 | extern void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *, unsigned int, int, |
52 | int); | 51 | int); |
52 | extern void zfcp_hba_dbf_event_berr(struct zfcp_adapter *, | ||
53 | struct zfcp_fsf_req *); | ||
53 | extern void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *); | 54 | extern void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *); |
54 | extern void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *); | 55 | extern void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *); |
55 | extern void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *); | 56 | extern void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *); |
@@ -91,17 +92,21 @@ extern void zfcp_erp_port_access_denied(struct zfcp_port *, u8, void *); | |||
91 | extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, u8, void *); | 92 | extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, u8, void *); |
92 | extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, u8, void *); | 93 | extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, u8, void *); |
93 | extern void zfcp_erp_timeout_handler(unsigned long); | 94 | extern void zfcp_erp_timeout_handler(unsigned long); |
95 | extern void zfcp_erp_port_strategy_open_lookup(struct work_struct *); | ||
94 | 96 | ||
95 | /* zfcp_fc.c */ | 97 | /* zfcp_fc.c */ |
96 | extern int zfcp_scan_ports(struct zfcp_adapter *); | 98 | extern int zfcp_scan_ports(struct zfcp_adapter *); |
97 | extern void _zfcp_scan_ports_later(struct work_struct *); | 99 | extern void _zfcp_scan_ports_later(struct work_struct *); |
98 | extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *); | 100 | extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *); |
99 | extern int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *); | 101 | extern int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *); |
100 | extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *); | 102 | extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *); |
101 | extern void zfcp_test_link(struct zfcp_port *); | 103 | extern void zfcp_test_link(struct zfcp_port *); |
104 | extern void zfcp_fc_nameserver_init(struct zfcp_adapter *); | ||
102 | 105 | ||
103 | /* zfcp_fsf.c */ | 106 | /* zfcp_fsf.c */ |
104 | extern int zfcp_fsf_open_port(struct zfcp_erp_action *); | 107 | extern int zfcp_fsf_open_port(struct zfcp_erp_action *); |
108 | extern int zfcp_fsf_open_wka_port(struct zfcp_wka_port *); | ||
109 | extern int zfcp_fsf_close_wka_port(struct zfcp_wka_port *); | ||
105 | extern int zfcp_fsf_close_port(struct zfcp_erp_action *); | 110 | extern int zfcp_fsf_close_port(struct zfcp_erp_action *); |
106 | extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *); | 111 | extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *); |
107 | extern int zfcp_fsf_open_unit(struct zfcp_erp_action *); | 112 | extern int zfcp_fsf_open_unit(struct zfcp_erp_action *); |
@@ -135,10 +140,8 @@ extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long, | |||
135 | extern int zfcp_qdio_allocate(struct zfcp_adapter *); | 140 | extern int zfcp_qdio_allocate(struct zfcp_adapter *); |
136 | extern void zfcp_qdio_free(struct zfcp_adapter *); | 141 | extern void zfcp_qdio_free(struct zfcp_adapter *); |
137 | extern int zfcp_qdio_send(struct zfcp_fsf_req *); | 142 | extern int zfcp_qdio_send(struct zfcp_fsf_req *); |
138 | extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req( | 143 | extern struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *); |
139 | struct zfcp_fsf_req *); | 144 | extern struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_fsf_req *); |
140 | extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_curr( | ||
141 | struct zfcp_fsf_req *); | ||
142 | extern int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *, unsigned long, | 145 | extern int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *, unsigned long, |
143 | struct scatterlist *, int); | 146 | struct scatterlist *, int); |
144 | extern int zfcp_qdio_open(struct zfcp_adapter *); | 147 | extern int zfcp_qdio_open(struct zfcp_adapter *); |
@@ -148,14 +151,12 @@ extern void zfcp_qdio_close(struct zfcp_adapter *); | |||
148 | extern struct zfcp_data zfcp_data; | 151 | extern struct zfcp_data zfcp_data; |
149 | extern int zfcp_adapter_scsi_register(struct zfcp_adapter *); | 152 | extern int zfcp_adapter_scsi_register(struct zfcp_adapter *); |
150 | extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *); | 153 | extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *); |
151 | extern void zfcp_set_fcp_dl(struct fcp_cmnd_iu *, fcp_dl_t); | ||
152 | extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *); | 154 | extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *); |
153 | extern struct fc_function_template zfcp_transport_functions; | 155 | extern struct fc_function_template zfcp_transport_functions; |
154 | 156 | ||
155 | /* zfcp_sysfs.c */ | 157 | /* zfcp_sysfs.c */ |
156 | extern struct attribute_group zfcp_sysfs_unit_attrs; | 158 | extern struct attribute_group zfcp_sysfs_unit_attrs; |
157 | extern struct attribute_group zfcp_sysfs_adapter_attrs; | 159 | extern struct attribute_group zfcp_sysfs_adapter_attrs; |
158 | extern struct attribute_group zfcp_sysfs_ns_port_attrs; | ||
159 | extern struct attribute_group zfcp_sysfs_port_attrs; | 160 | extern struct attribute_group zfcp_sysfs_port_attrs; |
160 | extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; | 161 | extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; |
161 | extern struct device_attribute *zfcp_sysfs_shost_attrs[]; | 162 | extern struct device_attribute *zfcp_sysfs_shost_attrs[]; |
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 56196c98c07b..1a7c80a77ff5 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c | |||
@@ -39,6 +39,84 @@ struct zfcp_gpn_ft { | |||
39 | struct scatterlist sg_resp[ZFCP_GPN_FT_BUFFERS]; | 39 | struct scatterlist sg_resp[ZFCP_GPN_FT_BUFFERS]; |
40 | }; | 40 | }; |
41 | 41 | ||
42 | struct zfcp_fc_ns_handler_data { | ||
43 | struct completion done; | ||
44 | void (*handler)(unsigned long); | ||
45 | unsigned long handler_data; | ||
46 | }; | ||
47 | |||
48 | static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port) | ||
49 | { | ||
50 | if (mutex_lock_interruptible(&wka_port->mutex)) | ||
51 | return -ERESTARTSYS; | ||
52 | |||
53 | if (wka_port->status != ZFCP_WKA_PORT_ONLINE) { | ||
54 | wka_port->status = ZFCP_WKA_PORT_OPENING; | ||
55 | if (zfcp_fsf_open_wka_port(wka_port)) | ||
56 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | ||
57 | } | ||
58 | |||
59 | mutex_unlock(&wka_port->mutex); | ||
60 | |||
61 | wait_event_timeout( | ||
62 | wka_port->completion_wq, | ||
63 | wka_port->status == ZFCP_WKA_PORT_ONLINE || | ||
64 | wka_port->status == ZFCP_WKA_PORT_OFFLINE, | ||
65 | HZ >> 1); | ||
66 | |||
67 | if (wka_port->status == ZFCP_WKA_PORT_ONLINE) { | ||
68 | atomic_inc(&wka_port->refcount); | ||
69 | return 0; | ||
70 | } | ||
71 | return -EIO; | ||
72 | } | ||
73 | |||
74 | static void zfcp_wka_port_offline(struct work_struct *work) | ||
75 | { | ||
76 | struct delayed_work *dw = container_of(work, struct delayed_work, work); | ||
77 | struct zfcp_wka_port *wka_port = | ||
78 | container_of(dw, struct zfcp_wka_port, work); | ||
79 | |||
80 | wait_event(wka_port->completion_wq, | ||
81 | atomic_read(&wka_port->refcount) == 0); | ||
82 | |||
83 | mutex_lock(&wka_port->mutex); | ||
84 | if ((atomic_read(&wka_port->refcount) != 0) || | ||
85 | (wka_port->status != ZFCP_WKA_PORT_ONLINE)) | ||
86 | goto out; | ||
87 | |||
88 | wka_port->status = ZFCP_WKA_PORT_CLOSING; | ||
89 | if (zfcp_fsf_close_wka_port(wka_port)) { | ||
90 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | ||
91 | wake_up(&wka_port->completion_wq); | ||
92 | } | ||
93 | out: | ||
94 | mutex_unlock(&wka_port->mutex); | ||
95 | } | ||
96 | |||
97 | static void zfcp_wka_port_put(struct zfcp_wka_port *wka_port) | ||
98 | { | ||
99 | if (atomic_dec_return(&wka_port->refcount) != 0) | ||
100 | return; | ||
101 | /* wait 10 miliseconds, other reqs might pop in */ | ||
102 | schedule_delayed_work(&wka_port->work, HZ / 100); | ||
103 | } | ||
104 | |||
105 | void zfcp_fc_nameserver_init(struct zfcp_adapter *adapter) | ||
106 | { | ||
107 | struct zfcp_wka_port *wka_port = &adapter->nsp; | ||
108 | |||
109 | init_waitqueue_head(&wka_port->completion_wq); | ||
110 | |||
111 | wka_port->adapter = adapter; | ||
112 | wka_port->d_id = ZFCP_DID_DIRECTORY_SERVICE; | ||
113 | |||
114 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | ||
115 | atomic_set(&wka_port->refcount, 0); | ||
116 | mutex_init(&wka_port->mutex); | ||
117 | INIT_DELAYED_WORK(&wka_port->work, zfcp_wka_port_offline); | ||
118 | } | ||
119 | |||
42 | static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, | 120 | static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, |
43 | struct fcp_rscn_element *elem) | 121 | struct fcp_rscn_element *elem) |
44 | { | 122 | { |
@@ -47,10 +125,8 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, | |||
47 | 125 | ||
48 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 126 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
49 | list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) { | 127 | list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) { |
50 | if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) | ||
51 | continue; | ||
52 | /* FIXME: ZFCP_STATUS_PORT_DID_DID check is racy */ | 128 | /* FIXME: ZFCP_STATUS_PORT_DID_DID check is racy */ |
53 | if (!atomic_test_mask(ZFCP_STATUS_PORT_DID_DID, &port->status)) | 129 | if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_DID_DID)) |
54 | /* Try to connect to unused ports anyway. */ | 130 | /* Try to connect to unused ports anyway. */ |
55 | zfcp_erp_port_reopen(port, | 131 | zfcp_erp_port_reopen(port, |
56 | ZFCP_STATUS_COMMON_ERP_FAILED, | 132 | ZFCP_STATUS_COMMON_ERP_FAILED, |
@@ -102,7 +178,7 @@ static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req) | |||
102 | schedule_work(&fsf_req->adapter->scan_work); | 178 | schedule_work(&fsf_req->adapter->scan_work); |
103 | } | 179 | } |
104 | 180 | ||
105 | static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, wwn_t wwpn) | 181 | static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn) |
106 | { | 182 | { |
107 | struct zfcp_adapter *adapter = req->adapter; | 183 | struct zfcp_adapter *adapter = req->adapter; |
108 | struct zfcp_port *port; | 184 | struct zfcp_port *port; |
@@ -157,7 +233,18 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req) | |||
157 | zfcp_fc_incoming_rscn(fsf_req); | 233 | zfcp_fc_incoming_rscn(fsf_req); |
158 | } | 234 | } |
159 | 235 | ||
160 | static void zfcp_ns_gid_pn_handler(unsigned long data) | 236 | static void zfcp_fc_ns_handler(unsigned long data) |
237 | { | ||
238 | struct zfcp_fc_ns_handler_data *compl_rec = | ||
239 | (struct zfcp_fc_ns_handler_data *) data; | ||
240 | |||
241 | if (compl_rec->handler) | ||
242 | compl_rec->handler(compl_rec->handler_data); | ||
243 | |||
244 | complete(&compl_rec->done); | ||
245 | } | ||
246 | |||
247 | static void zfcp_fc_ns_gid_pn_eval(unsigned long data) | ||
161 | { | 248 | { |
162 | struct zfcp_gid_pn_data *gid_pn = (struct zfcp_gid_pn_data *) data; | 249 | struct zfcp_gid_pn_data *gid_pn = (struct zfcp_gid_pn_data *) data; |
163 | struct zfcp_send_ct *ct = &gid_pn->ct; | 250 | struct zfcp_send_ct *ct = &gid_pn->ct; |
@@ -166,43 +253,31 @@ static void zfcp_ns_gid_pn_handler(unsigned long data) | |||
166 | struct zfcp_port *port = gid_pn->port; | 253 | struct zfcp_port *port = gid_pn->port; |
167 | 254 | ||
168 | if (ct->status) | 255 | if (ct->status) |
169 | goto out; | 256 | return; |
170 | if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) { | 257 | if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) { |
171 | atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status); | 258 | atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status); |
172 | goto out; | 259 | return; |
173 | } | 260 | } |
174 | /* paranoia */ | 261 | /* paranoia */ |
175 | if (ct_iu_req->wwpn != port->wwpn) | 262 | if (ct_iu_req->wwpn != port->wwpn) |
176 | goto out; | 263 | return; |
177 | /* looks like a valid d_id */ | 264 | /* looks like a valid d_id */ |
178 | port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK; | 265 | port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK; |
179 | atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); | 266 | atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); |
180 | out: | ||
181 | mempool_free(gid_pn, port->adapter->pool.data_gid_pn); | ||
182 | } | 267 | } |
183 | 268 | ||
184 | /** | 269 | int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action, |
185 | * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request | 270 | struct zfcp_gid_pn_data *gid_pn) |
186 | * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed | ||
187 | * return: -ENOMEM on error, 0 otherwise | ||
188 | */ | ||
189 | int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action) | ||
190 | { | 271 | { |
191 | int ret; | ||
192 | struct zfcp_gid_pn_data *gid_pn; | ||
193 | struct zfcp_adapter *adapter = erp_action->adapter; | 272 | struct zfcp_adapter *adapter = erp_action->adapter; |
194 | 273 | struct zfcp_fc_ns_handler_data compl_rec; | |
195 | gid_pn = mempool_alloc(adapter->pool.data_gid_pn, GFP_ATOMIC); | 274 | int ret; |
196 | if (!gid_pn) | ||
197 | return -ENOMEM; | ||
198 | |||
199 | memset(gid_pn, 0, sizeof(*gid_pn)); | ||
200 | 275 | ||
201 | /* setup parameters for send generic command */ | 276 | /* setup parameters for send generic command */ |
202 | gid_pn->port = erp_action->port; | 277 | gid_pn->port = erp_action->port; |
203 | gid_pn->ct.port = adapter->nameserver_port; | 278 | gid_pn->ct.wka_port = &adapter->nsp; |
204 | gid_pn->ct.handler = zfcp_ns_gid_pn_handler; | 279 | gid_pn->ct.handler = zfcp_fc_ns_handler; |
205 | gid_pn->ct.handler_data = (unsigned long) gid_pn; | 280 | gid_pn->ct.handler_data = (unsigned long) &compl_rec; |
206 | gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT; | 281 | gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT; |
207 | gid_pn->ct.req = &gid_pn->req; | 282 | gid_pn->ct.req = &gid_pn->req; |
208 | gid_pn->ct.resp = &gid_pn->resp; | 283 | gid_pn->ct.resp = &gid_pn->resp; |
@@ -222,10 +297,42 @@ int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action) | |||
222 | gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_MAX_SIZE; | 297 | gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_MAX_SIZE; |
223 | gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn; | 298 | gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn; |
224 | 299 | ||
300 | init_completion(&compl_rec.done); | ||
301 | compl_rec.handler = zfcp_fc_ns_gid_pn_eval; | ||
302 | compl_rec.handler_data = (unsigned long) gid_pn; | ||
225 | ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp, | 303 | ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp, |
226 | erp_action); | 304 | erp_action); |
305 | if (!ret) | ||
306 | wait_for_completion(&compl_rec.done); | ||
307 | return ret; | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request | ||
312 | * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed | ||
313 | * return: -ENOMEM on error, 0 otherwise | ||
314 | */ | ||
315 | int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *erp_action) | ||
316 | { | ||
317 | int ret; | ||
318 | struct zfcp_gid_pn_data *gid_pn; | ||
319 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
320 | |||
321 | gid_pn = mempool_alloc(adapter->pool.data_gid_pn, GFP_ATOMIC); | ||
322 | if (!gid_pn) | ||
323 | return -ENOMEM; | ||
324 | |||
325 | memset(gid_pn, 0, sizeof(*gid_pn)); | ||
326 | |||
327 | ret = zfcp_wka_port_get(&adapter->nsp); | ||
227 | if (ret) | 328 | if (ret) |
228 | mempool_free(gid_pn, adapter->pool.data_gid_pn); | 329 | goto out; |
330 | |||
331 | ret = zfcp_fc_ns_gid_pn_request(erp_action, gid_pn); | ||
332 | |||
333 | zfcp_wka_port_put(&adapter->nsp); | ||
334 | out: | ||
335 | mempool_free(gid_pn, adapter->pool.data_gid_pn); | ||
229 | return ret; | 336 | return ret; |
230 | } | 337 | } |
231 | 338 | ||
@@ -255,14 +362,14 @@ struct zfcp_els_adisc { | |||
255 | struct scatterlist req; | 362 | struct scatterlist req; |
256 | struct scatterlist resp; | 363 | struct scatterlist resp; |
257 | struct zfcp_ls_adisc ls_adisc; | 364 | struct zfcp_ls_adisc ls_adisc; |
258 | struct zfcp_ls_adisc_acc ls_adisc_acc; | 365 | struct zfcp_ls_adisc ls_adisc_acc; |
259 | }; | 366 | }; |
260 | 367 | ||
261 | static void zfcp_fc_adisc_handler(unsigned long data) | 368 | static void zfcp_fc_adisc_handler(unsigned long data) |
262 | { | 369 | { |
263 | struct zfcp_els_adisc *adisc = (struct zfcp_els_adisc *) data; | 370 | struct zfcp_els_adisc *adisc = (struct zfcp_els_adisc *) data; |
264 | struct zfcp_port *port = adisc->els.port; | 371 | struct zfcp_port *port = adisc->els.port; |
265 | struct zfcp_ls_adisc_acc *ls_adisc = &adisc->ls_adisc_acc; | 372 | struct zfcp_ls_adisc *ls_adisc = &adisc->ls_adisc_acc; |
266 | 373 | ||
267 | if (adisc->els.status) { | 374 | if (adisc->els.status) { |
268 | /* request rejected or timed out */ | 375 | /* request rejected or timed out */ |
@@ -295,7 +402,7 @@ static int zfcp_fc_adisc(struct zfcp_port *port) | |||
295 | sg_init_one(adisc->els.req, &adisc->ls_adisc, | 402 | sg_init_one(adisc->els.req, &adisc->ls_adisc, |
296 | sizeof(struct zfcp_ls_adisc)); | 403 | sizeof(struct zfcp_ls_adisc)); |
297 | sg_init_one(adisc->els.resp, &adisc->ls_adisc_acc, | 404 | sg_init_one(adisc->els.resp, &adisc->ls_adisc_acc, |
298 | sizeof(struct zfcp_ls_adisc_acc)); | 405 | sizeof(struct zfcp_ls_adisc)); |
299 | 406 | ||
300 | adisc->els.req_count = 1; | 407 | adisc->els.req_count = 1; |
301 | adisc->els.resp_count = 1; | 408 | adisc->els.resp_count = 1; |
@@ -338,30 +445,6 @@ void zfcp_test_link(struct zfcp_port *port) | |||
338 | zfcp_erp_port_forced_reopen(port, 0, 65, NULL); | 445 | zfcp_erp_port_forced_reopen(port, 0, 65, NULL); |
339 | } | 446 | } |
340 | 447 | ||
341 | static int zfcp_scan_get_nameserver(struct zfcp_adapter *adapter) | ||
342 | { | ||
343 | int ret; | ||
344 | |||
345 | if (!adapter->nameserver_port) | ||
346 | return -EINTR; | ||
347 | |||
348 | if (!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, | ||
349 | &adapter->nameserver_port->status)) { | ||
350 | ret = zfcp_erp_port_reopen(adapter->nameserver_port, 0, 148, | ||
351 | NULL); | ||
352 | if (ret) | ||
353 | return ret; | ||
354 | zfcp_erp_wait(adapter); | ||
355 | } | ||
356 | return !atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, | ||
357 | &adapter->nameserver_port->status); | ||
358 | } | ||
359 | |||
360 | static void zfcp_gpn_ft_handler(unsigned long _done) | ||
361 | { | ||
362 | complete((struct completion *)_done); | ||
363 | } | ||
364 | |||
365 | static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft) | 448 | static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft) |
366 | { | 449 | { |
367 | struct scatterlist *sg = &gpn_ft->sg_req; | 450 | struct scatterlist *sg = &gpn_ft->sg_req; |
@@ -403,7 +486,7 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft, | |||
403 | { | 486 | { |
404 | struct zfcp_send_ct *ct = &gpn_ft->ct; | 487 | struct zfcp_send_ct *ct = &gpn_ft->ct; |
405 | struct ct_iu_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req); | 488 | struct ct_iu_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req); |
406 | struct completion done; | 489 | struct zfcp_fc_ns_handler_data compl_rec; |
407 | int ret; | 490 | int ret; |
408 | 491 | ||
409 | /* prepare CT IU for GPN_FT */ | 492 | /* prepare CT IU for GPN_FT */ |
@@ -420,19 +503,20 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft, | |||
420 | req->fc4_type = ZFCP_CT_SCSI_FCP; | 503 | req->fc4_type = ZFCP_CT_SCSI_FCP; |
421 | 504 | ||
422 | /* prepare zfcp_send_ct */ | 505 | /* prepare zfcp_send_ct */ |
423 | ct->port = adapter->nameserver_port; | 506 | ct->wka_port = &adapter->nsp; |
424 | ct->handler = zfcp_gpn_ft_handler; | 507 | ct->handler = zfcp_fc_ns_handler; |
425 | ct->handler_data = (unsigned long)&done; | 508 | ct->handler_data = (unsigned long)&compl_rec; |
426 | ct->timeout = 10; | 509 | ct->timeout = 10; |
427 | ct->req = &gpn_ft->sg_req; | 510 | ct->req = &gpn_ft->sg_req; |
428 | ct->resp = gpn_ft->sg_resp; | 511 | ct->resp = gpn_ft->sg_resp; |
429 | ct->req_count = 1; | 512 | ct->req_count = 1; |
430 | ct->resp_count = ZFCP_GPN_FT_BUFFERS; | 513 | ct->resp_count = ZFCP_GPN_FT_BUFFERS; |
431 | 514 | ||
432 | init_completion(&done); | 515 | init_completion(&compl_rec.done); |
516 | compl_rec.handler = NULL; | ||
433 | ret = zfcp_fsf_send_ct(ct, NULL, NULL); | 517 | ret = zfcp_fsf_send_ct(ct, NULL, NULL); |
434 | if (!ret) | 518 | if (!ret) |
435 | wait_for_completion(&done); | 519 | wait_for_completion(&compl_rec.done); |
436 | return ret; | 520 | return ret; |
437 | } | 521 | } |
438 | 522 | ||
@@ -442,9 +526,8 @@ static void zfcp_validate_port(struct zfcp_port *port) | |||
442 | 526 | ||
443 | atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status); | 527 | atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status); |
444 | 528 | ||
445 | if (port == adapter->nameserver_port) | 529 | if ((port->supported_classes != 0) || |
446 | return; | 530 | !list_empty(&port->unit_list_head)) { |
447 | if ((port->supported_classes != 0) || (port->units != 0)) { | ||
448 | zfcp_port_put(port); | 531 | zfcp_port_put(port); |
449 | return; | 532 | return; |
450 | } | 533 | } |
@@ -460,7 +543,7 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft) | |||
460 | struct scatterlist *sg = gpn_ft->sg_resp; | 543 | struct scatterlist *sg = gpn_ft->sg_resp; |
461 | struct ct_hdr *hdr = sg_virt(sg); | 544 | struct ct_hdr *hdr = sg_virt(sg); |
462 | struct gpn_ft_resp_acc *acc = sg_virt(sg); | 545 | struct gpn_ft_resp_acc *acc = sg_virt(sg); |
463 | struct zfcp_adapter *adapter = ct->port->adapter; | 546 | struct zfcp_adapter *adapter = ct->wka_port->adapter; |
464 | struct zfcp_port *port, *tmp; | 547 | struct zfcp_port *port, *tmp; |
465 | u32 d_id; | 548 | u32 d_id; |
466 | int ret = 0, x, last = 0; | 549 | int ret = 0, x, last = 0; |
@@ -490,6 +573,9 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft) | |||
490 | d_id = acc->port_id[0] << 16 | acc->port_id[1] << 8 | | 573 | d_id = acc->port_id[0] << 16 | acc->port_id[1] << 8 | |
491 | acc->port_id[2]; | 574 | acc->port_id[2]; |
492 | 575 | ||
576 | /* don't attach ports with a well known address */ | ||
577 | if ((d_id & ZFCP_DID_WKA) == ZFCP_DID_WKA) | ||
578 | continue; | ||
493 | /* skip the adapter's port and known remote ports */ | 579 | /* skip the adapter's port and known remote ports */ |
494 | if (acc->wwpn == fc_host_port_name(adapter->scsi_host)) | 580 | if (acc->wwpn == fc_host_port_name(adapter->scsi_host)) |
495 | continue; | 581 | continue; |
@@ -528,13 +614,15 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter) | |||
528 | if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT) | 614 | if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT) |
529 | return 0; | 615 | return 0; |
530 | 616 | ||
531 | ret = zfcp_scan_get_nameserver(adapter); | 617 | ret = zfcp_wka_port_get(&adapter->nsp); |
532 | if (ret) | 618 | if (ret) |
533 | return ret; | 619 | return ret; |
534 | 620 | ||
535 | gpn_ft = zfcp_alloc_sg_env(); | 621 | gpn_ft = zfcp_alloc_sg_env(); |
536 | if (!gpn_ft) | 622 | if (!gpn_ft) { |
537 | return -ENOMEM; | 623 | ret = -ENOMEM; |
624 | goto out; | ||
625 | } | ||
538 | 626 | ||
539 | for (i = 0; i < 3; i++) { | 627 | for (i = 0; i < 3; i++) { |
540 | ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter); | 628 | ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter); |
@@ -547,7 +635,8 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter) | |||
547 | } | 635 | } |
548 | } | 636 | } |
549 | zfcp_free_sg_env(gpn_ft); | 637 | zfcp_free_sg_env(gpn_ft); |
550 | 638 | out: | |
639 | zfcp_wka_port_put(&adapter->nsp); | ||
551 | return ret; | 640 | return ret; |
552 | } | 641 | } |
553 | 642 | ||
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 49dbeb754e5f..739356a5c123 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -50,19 +50,16 @@ static u32 fsf_qtcb_type[] = { | |||
50 | [FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND | 50 | [FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND |
51 | }; | 51 | }; |
52 | 52 | ||
53 | static const char *zfcp_act_subtable_type[] = { | ||
54 | "unknown", "OS", "WWPN", "DID", "LUN" | ||
55 | }; | ||
56 | |||
57 | static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table) | 53 | static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table) |
58 | { | 54 | { |
59 | u16 subtable = table >> 16; | 55 | u16 subtable = table >> 16; |
60 | u16 rule = table & 0xffff; | 56 | u16 rule = table & 0xffff; |
57 | const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" }; | ||
61 | 58 | ||
62 | if (subtable && subtable < ARRAY_SIZE(zfcp_act_subtable_type)) | 59 | if (subtable && subtable < ARRAY_SIZE(act_type)) |
63 | dev_warn(&adapter->ccw_device->dev, | 60 | dev_warn(&adapter->ccw_device->dev, |
64 | "Access denied in subtable %s, rule %d.\n", | 61 | "Access denied according to ACT rule type %s, " |
65 | zfcp_act_subtable_type[subtable], rule); | 62 | "rule %d\n", act_type[subtable], rule); |
66 | } | 63 | } |
67 | 64 | ||
68 | static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req, | 65 | static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req, |
@@ -70,8 +67,8 @@ static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req, | |||
70 | { | 67 | { |
71 | struct fsf_qtcb_header *header = &req->qtcb->header; | 68 | struct fsf_qtcb_header *header = &req->qtcb->header; |
72 | dev_warn(&req->adapter->ccw_device->dev, | 69 | dev_warn(&req->adapter->ccw_device->dev, |
73 | "Access denied, cannot send command to port 0x%016Lx.\n", | 70 | "Access denied to port 0x%016Lx\n", |
74 | port->wwpn); | 71 | (unsigned long long)port->wwpn); |
75 | zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]); | 72 | zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]); |
76 | zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]); | 73 | zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]); |
77 | zfcp_erp_port_access_denied(port, 55, req); | 74 | zfcp_erp_port_access_denied(port, 55, req); |
@@ -83,8 +80,9 @@ static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req, | |||
83 | { | 80 | { |
84 | struct fsf_qtcb_header *header = &req->qtcb->header; | 81 | struct fsf_qtcb_header *header = &req->qtcb->header; |
85 | dev_warn(&req->adapter->ccw_device->dev, | 82 | dev_warn(&req->adapter->ccw_device->dev, |
86 | "Access denied for unit 0x%016Lx on port 0x%016Lx.\n", | 83 | "Access denied to unit 0x%016Lx on port 0x%016Lx\n", |
87 | unit->fcp_lun, unit->port->wwpn); | 84 | (unsigned long long)unit->fcp_lun, |
85 | (unsigned long long)unit->port->wwpn); | ||
88 | zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]); | 86 | zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]); |
89 | zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]); | 87 | zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]); |
90 | zfcp_erp_unit_access_denied(unit, 59, req); | 88 | zfcp_erp_unit_access_denied(unit, 59, req); |
@@ -93,9 +91,8 @@ static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req, | |||
93 | 91 | ||
94 | static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req) | 92 | static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req) |
95 | { | 93 | { |
96 | dev_err(&req->adapter->ccw_device->dev, | 94 | dev_err(&req->adapter->ccw_device->dev, "FCP device not " |
97 | "Required FC class not supported by adapter, " | 95 | "operational because of an unsupported FC class\n"); |
98 | "shutting down adapter.\n"); | ||
99 | zfcp_erp_adapter_shutdown(req->adapter, 0, 123, req); | 96 | zfcp_erp_adapter_shutdown(req->adapter, 0, 123, req); |
100 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 97 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
101 | } | 98 | } |
@@ -171,42 +168,6 @@ static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req) | |||
171 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 168 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
172 | } | 169 | } |
173 | 170 | ||
174 | static void zfcp_fsf_bit_error_threshold(struct zfcp_fsf_req *req) | ||
175 | { | ||
176 | struct zfcp_adapter *adapter = req->adapter; | ||
177 | struct fsf_status_read_buffer *sr_buf = req->data; | ||
178 | struct fsf_bit_error_payload *err = &sr_buf->payload.bit_error; | ||
179 | |||
180 | dev_warn(&adapter->ccw_device->dev, | ||
181 | "Warning: bit error threshold data " | ||
182 | "received for the adapter: " | ||
183 | "link failures = %i, loss of sync errors = %i, " | ||
184 | "loss of signal errors = %i, " | ||
185 | "primitive sequence errors = %i, " | ||
186 | "invalid transmission word errors = %i, " | ||
187 | "CRC errors = %i).\n", | ||
188 | err->link_failure_error_count, | ||
189 | err->loss_of_sync_error_count, | ||
190 | err->loss_of_signal_error_count, | ||
191 | err->primitive_sequence_error_count, | ||
192 | err->invalid_transmission_word_error_count, | ||
193 | err->crc_error_count); | ||
194 | dev_warn(&adapter->ccw_device->dev, | ||
195 | "Additional bit error threshold data of the adapter: " | ||
196 | "primitive sequence event time-outs = %i, " | ||
197 | "elastic buffer overrun errors = %i, " | ||
198 | "advertised receive buffer-to-buffer credit = %i, " | ||
199 | "current receice buffer-to-buffer credit = %i, " | ||
200 | "advertised transmit buffer-to-buffer credit = %i, " | ||
201 | "current transmit buffer-to-buffer credit = %i).\n", | ||
202 | err->primitive_sequence_event_timeout_count, | ||
203 | err->elastic_buffer_overrun_error_count, | ||
204 | err->advertised_receive_b2b_credit, | ||
205 | err->current_receive_b2b_credit, | ||
206 | err->advertised_transmit_b2b_credit, | ||
207 | err->current_transmit_b2b_credit); | ||
208 | } | ||
209 | |||
210 | static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, u8 id, | 171 | static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, u8 id, |
211 | struct fsf_link_down_info *link_down) | 172 | struct fsf_link_down_info *link_down) |
212 | { | 173 | { |
@@ -223,62 +184,66 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, u8 id, | |||
223 | switch (link_down->error_code) { | 184 | switch (link_down->error_code) { |
224 | case FSF_PSQ_LINK_NO_LIGHT: | 185 | case FSF_PSQ_LINK_NO_LIGHT: |
225 | dev_warn(&req->adapter->ccw_device->dev, | 186 | dev_warn(&req->adapter->ccw_device->dev, |
226 | "The local link is down: no light detected.\n"); | 187 | "There is no light signal from the local " |
188 | "fibre channel cable\n"); | ||
227 | break; | 189 | break; |
228 | case FSF_PSQ_LINK_WRAP_PLUG: | 190 | case FSF_PSQ_LINK_WRAP_PLUG: |
229 | dev_warn(&req->adapter->ccw_device->dev, | 191 | dev_warn(&req->adapter->ccw_device->dev, |
230 | "The local link is down: wrap plug detected.\n"); | 192 | "There is a wrap plug instead of a fibre " |
193 | "channel cable\n"); | ||
231 | break; | 194 | break; |
232 | case FSF_PSQ_LINK_NO_FCP: | 195 | case FSF_PSQ_LINK_NO_FCP: |
233 | dev_warn(&req->adapter->ccw_device->dev, | 196 | dev_warn(&req->adapter->ccw_device->dev, |
234 | "The local link is down: " | 197 | "The adjacent fibre channel node does not " |
235 | "adjacent node on link does not support FCP.\n"); | 198 | "support FCP\n"); |
236 | break; | 199 | break; |
237 | case FSF_PSQ_LINK_FIRMWARE_UPDATE: | 200 | case FSF_PSQ_LINK_FIRMWARE_UPDATE: |
238 | dev_warn(&req->adapter->ccw_device->dev, | 201 | dev_warn(&req->adapter->ccw_device->dev, |
239 | "The local link is down: " | 202 | "The FCP device is suspended because of a " |
240 | "firmware update in progress.\n"); | 203 | "firmware update\n"); |
241 | break; | 204 | break; |
242 | case FSF_PSQ_LINK_INVALID_WWPN: | 205 | case FSF_PSQ_LINK_INVALID_WWPN: |
243 | dev_warn(&req->adapter->ccw_device->dev, | 206 | dev_warn(&req->adapter->ccw_device->dev, |
244 | "The local link is down: " | 207 | "The FCP device detected a WWPN that is " |
245 | "duplicate or invalid WWPN detected.\n"); | 208 | "duplicate or not valid\n"); |
246 | break; | 209 | break; |
247 | case FSF_PSQ_LINK_NO_NPIV_SUPPORT: | 210 | case FSF_PSQ_LINK_NO_NPIV_SUPPORT: |
248 | dev_warn(&req->adapter->ccw_device->dev, | 211 | dev_warn(&req->adapter->ccw_device->dev, |
249 | "The local link is down: " | 212 | "The fibre channel fabric does not support NPIV\n"); |
250 | "no support for NPIV by Fabric.\n"); | ||
251 | break; | 213 | break; |
252 | case FSF_PSQ_LINK_NO_FCP_RESOURCES: | 214 | case FSF_PSQ_LINK_NO_FCP_RESOURCES: |
253 | dev_warn(&req->adapter->ccw_device->dev, | 215 | dev_warn(&req->adapter->ccw_device->dev, |
254 | "The local link is down: " | 216 | "The FCP adapter cannot support more NPIV ports\n"); |
255 | "out of resource in FCP daughtercard.\n"); | ||
256 | break; | 217 | break; |
257 | case FSF_PSQ_LINK_NO_FABRIC_RESOURCES: | 218 | case FSF_PSQ_LINK_NO_FABRIC_RESOURCES: |
258 | dev_warn(&req->adapter->ccw_device->dev, | 219 | dev_warn(&req->adapter->ccw_device->dev, |
259 | "The local link is down: " | 220 | "The adjacent switch cannot support " |
260 | "out of resource in Fabric.\n"); | 221 | "more NPIV ports\n"); |
261 | break; | 222 | break; |
262 | case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE: | 223 | case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE: |
263 | dev_warn(&req->adapter->ccw_device->dev, | 224 | dev_warn(&req->adapter->ccw_device->dev, |
264 | "The local link is down: " | 225 | "The FCP adapter could not log in to the " |
265 | "unable to login to Fabric.\n"); | 226 | "fibre channel fabric\n"); |
266 | break; | 227 | break; |
267 | case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED: | 228 | case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED: |
268 | dev_warn(&req->adapter->ccw_device->dev, | 229 | dev_warn(&req->adapter->ccw_device->dev, |
269 | "WWPN assignment file corrupted on adapter.\n"); | 230 | "The WWPN assignment file on the FCP adapter " |
231 | "has been damaged\n"); | ||
270 | break; | 232 | break; |
271 | case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED: | 233 | case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED: |
272 | dev_warn(&req->adapter->ccw_device->dev, | 234 | dev_warn(&req->adapter->ccw_device->dev, |
273 | "Mode table corrupted on adapter.\n"); | 235 | "The mode table on the FCP adapter " |
236 | "has been damaged\n"); | ||
274 | break; | 237 | break; |
275 | case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT: | 238 | case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT: |
276 | dev_warn(&req->adapter->ccw_device->dev, | 239 | dev_warn(&req->adapter->ccw_device->dev, |
277 | "No WWPN for assignment table on adapter.\n"); | 240 | "All NPIV ports on the FCP adapter have " |
241 | "been assigned\n"); | ||
278 | break; | 242 | break; |
279 | default: | 243 | default: |
280 | dev_warn(&req->adapter->ccw_device->dev, | 244 | dev_warn(&req->adapter->ccw_device->dev, |
281 | "The local link to adapter is down.\n"); | 245 | "The link between the FCP adapter and " |
246 | "the FC fabric is down\n"); | ||
282 | } | 247 | } |
283 | out: | 248 | out: |
284 | zfcp_erp_adapter_failed(adapter, id, req); | 249 | zfcp_erp_adapter_failed(adapter, id, req); |
@@ -286,27 +251,18 @@ out: | |||
286 | 251 | ||
287 | static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req) | 252 | static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req) |
288 | { | 253 | { |
289 | struct zfcp_adapter *adapter = req->adapter; | ||
290 | struct fsf_status_read_buffer *sr_buf = req->data; | 254 | struct fsf_status_read_buffer *sr_buf = req->data; |
291 | struct fsf_link_down_info *ldi = | 255 | struct fsf_link_down_info *ldi = |
292 | (struct fsf_link_down_info *) &sr_buf->payload; | 256 | (struct fsf_link_down_info *) &sr_buf->payload; |
293 | 257 | ||
294 | switch (sr_buf->status_subtype) { | 258 | switch (sr_buf->status_subtype) { |
295 | case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: | 259 | case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: |
296 | dev_warn(&adapter->ccw_device->dev, | ||
297 | "Physical link is down.\n"); | ||
298 | zfcp_fsf_link_down_info_eval(req, 38, ldi); | 260 | zfcp_fsf_link_down_info_eval(req, 38, ldi); |
299 | break; | 261 | break; |
300 | case FSF_STATUS_READ_SUB_FDISC_FAILED: | 262 | case FSF_STATUS_READ_SUB_FDISC_FAILED: |
301 | dev_warn(&adapter->ccw_device->dev, | ||
302 | "Local link is down " | ||
303 | "due to failed FDISC login.\n"); | ||
304 | zfcp_fsf_link_down_info_eval(req, 39, ldi); | 263 | zfcp_fsf_link_down_info_eval(req, 39, ldi); |
305 | break; | 264 | break; |
306 | case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: | 265 | case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: |
307 | dev_warn(&adapter->ccw_device->dev, | ||
308 | "Local link is down " | ||
309 | "due to firmware update on adapter.\n"); | ||
310 | zfcp_fsf_link_down_info_eval(req, 40, NULL); | 266 | zfcp_fsf_link_down_info_eval(req, 40, NULL); |
311 | }; | 267 | }; |
312 | } | 268 | } |
@@ -335,14 +291,17 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) | |||
335 | case FSF_STATUS_READ_SENSE_DATA_AVAIL: | 291 | case FSF_STATUS_READ_SENSE_DATA_AVAIL: |
336 | break; | 292 | break; |
337 | case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: | 293 | case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: |
338 | zfcp_fsf_bit_error_threshold(req); | 294 | dev_warn(&adapter->ccw_device->dev, |
295 | "The error threshold for checksum statistics " | ||
296 | "has been exceeded\n"); | ||
297 | zfcp_hba_dbf_event_berr(adapter, req); | ||
339 | break; | 298 | break; |
340 | case FSF_STATUS_READ_LINK_DOWN: | 299 | case FSF_STATUS_READ_LINK_DOWN: |
341 | zfcp_fsf_status_read_link_down(req); | 300 | zfcp_fsf_status_read_link_down(req); |
342 | break; | 301 | break; |
343 | case FSF_STATUS_READ_LINK_UP: | 302 | case FSF_STATUS_READ_LINK_UP: |
344 | dev_info(&adapter->ccw_device->dev, | 303 | dev_info(&adapter->ccw_device->dev, |
345 | "Local link was replugged.\n"); | 304 | "The local link has been restored\n"); |
346 | /* All ports should be marked as ready to run again */ | 305 | /* All ports should be marked as ready to run again */ |
347 | zfcp_erp_modify_adapter_status(adapter, 30, NULL, | 306 | zfcp_erp_modify_adapter_status(adapter, 30, NULL, |
348 | ZFCP_STATUS_COMMON_RUNNING, | 307 | ZFCP_STATUS_COMMON_RUNNING, |
@@ -370,7 +329,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) | |||
370 | zfcp_fsf_req_free(req); | 329 | zfcp_fsf_req_free(req); |
371 | 330 | ||
372 | atomic_inc(&adapter->stat_miss); | 331 | atomic_inc(&adapter->stat_miss); |
373 | schedule_work(&adapter->stat_work); | 332 | queue_work(zfcp_data.work_queue, &adapter->stat_work); |
374 | } | 333 | } |
375 | 334 | ||
376 | static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req) | 335 | static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req) |
@@ -386,8 +345,8 @@ static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req) | |||
386 | break; | 345 | break; |
387 | case FSF_SQ_NO_RECOM: | 346 | case FSF_SQ_NO_RECOM: |
388 | dev_err(&req->adapter->ccw_device->dev, | 347 | dev_err(&req->adapter->ccw_device->dev, |
389 | "No recommendation could be given for a " | 348 | "The FCP adapter reported a problem " |
390 | "problem on the adapter.\n"); | 349 | "that cannot be recovered\n"); |
391 | zfcp_erp_adapter_shutdown(req->adapter, 0, 121, req); | 350 | zfcp_erp_adapter_shutdown(req->adapter, 0, 121, req); |
392 | break; | 351 | break; |
393 | } | 352 | } |
@@ -403,8 +362,7 @@ static void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req) | |||
403 | switch (req->qtcb->header.fsf_status) { | 362 | switch (req->qtcb->header.fsf_status) { |
404 | case FSF_UNKNOWN_COMMAND: | 363 | case FSF_UNKNOWN_COMMAND: |
405 | dev_err(&req->adapter->ccw_device->dev, | 364 | dev_err(&req->adapter->ccw_device->dev, |
406 | "Command issued by the device driver (0x%x) is " | 365 | "The FCP adapter does not recognize the command 0x%x\n", |
407 | "not known by the adapter.\n", | ||
408 | req->qtcb->header.fsf_command); | 366 | req->qtcb->header.fsf_command); |
409 | zfcp_erp_adapter_shutdown(req->adapter, 0, 120, req); | 367 | zfcp_erp_adapter_shutdown(req->adapter, 0, 120, req); |
410 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 368 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
@@ -435,11 +393,9 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) | |||
435 | return; | 393 | return; |
436 | case FSF_PROT_QTCB_VERSION_ERROR: | 394 | case FSF_PROT_QTCB_VERSION_ERROR: |
437 | dev_err(&adapter->ccw_device->dev, | 395 | dev_err(&adapter->ccw_device->dev, |
438 | "The QTCB version requested by zfcp (0x%x) is not " | 396 | "QTCB version 0x%x not supported by FCP adapter " |
439 | "supported by the FCP adapter (lowest supported " | 397 | "(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION, |
440 | "0x%x, highest supported 0x%x).\n", | 398 | psq->word[0], psq->word[1]); |
441 | FSF_QTCB_CURRENT_VERSION, psq->word[0], | ||
442 | psq->word[1]); | ||
443 | zfcp_erp_adapter_shutdown(adapter, 0, 117, req); | 399 | zfcp_erp_adapter_shutdown(adapter, 0, 117, req); |
444 | break; | 400 | break; |
445 | case FSF_PROT_ERROR_STATE: | 401 | case FSF_PROT_ERROR_STATE: |
@@ -449,8 +405,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) | |||
449 | break; | 405 | break; |
450 | case FSF_PROT_UNSUPP_QTCB_TYPE: | 406 | case FSF_PROT_UNSUPP_QTCB_TYPE: |
451 | dev_err(&adapter->ccw_device->dev, | 407 | dev_err(&adapter->ccw_device->dev, |
452 | "Packet header type used by the device driver is " | 408 | "The QTCB type is not supported by the FCP adapter\n"); |
453 | "incompatible with that used on the adapter.\n"); | ||
454 | zfcp_erp_adapter_shutdown(adapter, 0, 118, req); | 409 | zfcp_erp_adapter_shutdown(adapter, 0, 118, req); |
455 | break; | 410 | break; |
456 | case FSF_PROT_HOST_CONNECTION_INITIALIZING: | 411 | case FSF_PROT_HOST_CONNECTION_INITIALIZING: |
@@ -459,7 +414,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) | |||
459 | break; | 414 | break; |
460 | case FSF_PROT_DUPLICATE_REQUEST_ID: | 415 | case FSF_PROT_DUPLICATE_REQUEST_ID: |
461 | dev_err(&adapter->ccw_device->dev, | 416 | dev_err(&adapter->ccw_device->dev, |
462 | "The request identifier 0x%Lx is ambiguous.\n", | 417 | "0x%Lx is an ambiguous request identifier\n", |
463 | (unsigned long long)qtcb->bottom.support.req_handle); | 418 | (unsigned long long)qtcb->bottom.support.req_handle); |
464 | zfcp_erp_adapter_shutdown(adapter, 0, 78, req); | 419 | zfcp_erp_adapter_shutdown(adapter, 0, 78, req); |
465 | break; | 420 | break; |
@@ -479,9 +434,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) | |||
479 | break; | 434 | break; |
480 | default: | 435 | default: |
481 | dev_err(&adapter->ccw_device->dev, | 436 | dev_err(&adapter->ccw_device->dev, |
482 | "Transfer protocol status information" | 437 | "0x%x is not a valid transfer protocol status\n", |
483 | "provided by the adapter (0x%x) " | ||
484 | "is not compatible with the device driver.\n", | ||
485 | qtcb->prefix.prot_status); | 438 | qtcb->prefix.prot_status); |
486 | zfcp_erp_adapter_shutdown(adapter, 0, 119, req); | 439 | zfcp_erp_adapter_shutdown(adapter, 0, 119, req); |
487 | } | 440 | } |
@@ -559,33 +512,17 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) | |||
559 | adapter->peer_wwpn = bottom->plogi_payload.wwpn; | 512 | adapter->peer_wwpn = bottom->plogi_payload.wwpn; |
560 | adapter->peer_wwnn = bottom->plogi_payload.wwnn; | 513 | adapter->peer_wwnn = bottom->plogi_payload.wwnn; |
561 | fc_host_port_type(shost) = FC_PORTTYPE_PTP; | 514 | fc_host_port_type(shost) = FC_PORTTYPE_PTP; |
562 | if (req->erp_action) | ||
563 | dev_info(&adapter->ccw_device->dev, | ||
564 | "Point-to-Point fibrechannel " | ||
565 | "configuration detected.\n"); | ||
566 | break; | 515 | break; |
567 | case FSF_TOPO_FABRIC: | 516 | case FSF_TOPO_FABRIC: |
568 | fc_host_port_type(shost) = FC_PORTTYPE_NPORT; | 517 | fc_host_port_type(shost) = FC_PORTTYPE_NPORT; |
569 | if (req->erp_action) | ||
570 | dev_info(&adapter->ccw_device->dev, | ||
571 | "Switched fabric fibrechannel " | ||
572 | "network detected.\n"); | ||
573 | break; | 518 | break; |
574 | case FSF_TOPO_AL: | 519 | case FSF_TOPO_AL: |
575 | fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; | 520 | fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; |
576 | dev_err(&adapter->ccw_device->dev, | ||
577 | "Unsupported arbitrated loop fibrechannel " | ||
578 | "topology detected, shutting down " | ||
579 | "adapter.\n"); | ||
580 | zfcp_erp_adapter_shutdown(adapter, 0, 127, req); | ||
581 | return -EIO; | ||
582 | default: | 521 | default: |
583 | fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; | ||
584 | dev_err(&adapter->ccw_device->dev, | 522 | dev_err(&adapter->ccw_device->dev, |
585 | "The fibrechannel topology reported by the" | 523 | "Unknown or unsupported arbitrated loop " |
586 | " adapter is not known by the zfcp driver," | 524 | "fibre channel topology detected\n"); |
587 | " shutting down adapter.\n"); | 525 | zfcp_erp_adapter_shutdown(adapter, 0, 127, req); |
588 | zfcp_erp_adapter_shutdown(adapter, 0, 128, req); | ||
589 | return -EIO; | 526 | return -EIO; |
590 | } | 527 | } |
591 | 528 | ||
@@ -616,11 +553,9 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) | |||
616 | 553 | ||
617 | if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { | 554 | if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { |
618 | dev_err(&adapter->ccw_device->dev, | 555 | dev_err(&adapter->ccw_device->dev, |
619 | "Maximum QTCB size (%d bytes) allowed by " | 556 | "FCP adapter maximum QTCB size (%d bytes) " |
620 | "the adapter is lower than the minimum " | 557 | "is too small\n", |
621 | "required by the driver (%ld bytes).\n", | 558 | bottom->max_qtcb_size); |
622 | bottom->max_qtcb_size, | ||
623 | sizeof(struct fsf_qtcb)); | ||
624 | zfcp_erp_adapter_shutdown(adapter, 0, 129, req); | 559 | zfcp_erp_adapter_shutdown(adapter, 0, 129, req); |
625 | return; | 560 | return; |
626 | } | 561 | } |
@@ -656,15 +591,15 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) | |||
656 | 591 | ||
657 | if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) { | 592 | if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) { |
658 | dev_err(&adapter->ccw_device->dev, | 593 | dev_err(&adapter->ccw_device->dev, |
659 | "The adapter only supports newer control block " | 594 | "The FCP adapter only supports newer " |
660 | "versions, try updated device driver.\n"); | 595 | "control block versions\n"); |
661 | zfcp_erp_adapter_shutdown(adapter, 0, 125, req); | 596 | zfcp_erp_adapter_shutdown(adapter, 0, 125, req); |
662 | return; | 597 | return; |
663 | } | 598 | } |
664 | if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) { | 599 | if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) { |
665 | dev_err(&adapter->ccw_device->dev, | 600 | dev_err(&adapter->ccw_device->dev, |
666 | "The adapter only supports older control block " | 601 | "The FCP adapter only supports older " |
667 | "versions, consider a microcode upgrade.\n"); | 602 | "control block versions\n"); |
668 | zfcp_erp_adapter_shutdown(adapter, 0, 126, req); | 603 | zfcp_erp_adapter_shutdown(adapter, 0, 126, req); |
669 | } | 604 | } |
670 | } | 605 | } |
@@ -688,7 +623,6 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) | |||
688 | 623 | ||
689 | static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) | 624 | static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) |
690 | { | 625 | { |
691 | struct zfcp_adapter *adapter = req->adapter; | ||
692 | struct fsf_qtcb *qtcb = req->qtcb; | 626 | struct fsf_qtcb *qtcb = req->qtcb; |
693 | 627 | ||
694 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) | 628 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
@@ -697,38 +631,47 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) | |||
697 | switch (qtcb->header.fsf_status) { | 631 | switch (qtcb->header.fsf_status) { |
698 | case FSF_GOOD: | 632 | case FSF_GOOD: |
699 | zfcp_fsf_exchange_port_evaluate(req); | 633 | zfcp_fsf_exchange_port_evaluate(req); |
700 | atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); | ||
701 | break; | 634 | break; |
702 | case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: | 635 | case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: |
703 | zfcp_fsf_exchange_port_evaluate(req); | 636 | zfcp_fsf_exchange_port_evaluate(req); |
704 | atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); | ||
705 | zfcp_fsf_link_down_info_eval(req, 43, | 637 | zfcp_fsf_link_down_info_eval(req, 43, |
706 | &qtcb->header.fsf_status_qual.link_down_info); | 638 | &qtcb->header.fsf_status_qual.link_down_info); |
707 | break; | 639 | break; |
708 | } | 640 | } |
709 | } | 641 | } |
710 | 642 | ||
711 | static int zfcp_fsf_sbal_check(struct zfcp_qdio_queue *queue) | 643 | static int zfcp_fsf_sbal_check(struct zfcp_adapter *adapter) |
712 | { | 644 | { |
713 | spin_lock_bh(&queue->lock); | 645 | struct zfcp_qdio_queue *req_q = &adapter->req_q; |
714 | if (atomic_read(&queue->count)) | 646 | |
647 | spin_lock_bh(&adapter->req_q_lock); | ||
648 | if (atomic_read(&req_q->count)) | ||
715 | return 1; | 649 | return 1; |
716 | spin_unlock_bh(&queue->lock); | 650 | spin_unlock_bh(&adapter->req_q_lock); |
717 | return 0; | 651 | return 0; |
718 | } | 652 | } |
719 | 653 | ||
654 | static int zfcp_fsf_sbal_available(struct zfcp_adapter *adapter) | ||
655 | { | ||
656 | unsigned int count = atomic_read(&adapter->req_q.count); | ||
657 | if (!count) | ||
658 | atomic_inc(&adapter->qdio_outb_full); | ||
659 | return count > 0; | ||
660 | } | ||
661 | |||
720 | static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) | 662 | static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) |
721 | { | 663 | { |
722 | long ret; | 664 | long ret; |
723 | struct zfcp_qdio_queue *req_q = &adapter->req_q; | ||
724 | 665 | ||
725 | spin_unlock_bh(&req_q->lock); | 666 | spin_unlock_bh(&adapter->req_q_lock); |
726 | ret = wait_event_interruptible_timeout(adapter->request_wq, | 667 | ret = wait_event_interruptible_timeout(adapter->request_wq, |
727 | zfcp_fsf_sbal_check(req_q), 5 * HZ); | 668 | zfcp_fsf_sbal_check(adapter), 5 * HZ); |
728 | if (ret > 0) | 669 | if (ret > 0) |
729 | return 0; | 670 | return 0; |
671 | if (!ret) | ||
672 | atomic_inc(&adapter->qdio_outb_full); | ||
730 | 673 | ||
731 | spin_lock_bh(&req_q->lock); | 674 | spin_lock_bh(&adapter->req_q_lock); |
732 | return -EIO; | 675 | return -EIO; |
733 | } | 676 | } |
734 | 677 | ||
@@ -765,7 +708,7 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter, | |||
765 | u32 fsf_cmd, int req_flags, | 708 | u32 fsf_cmd, int req_flags, |
766 | mempool_t *pool) | 709 | mempool_t *pool) |
767 | { | 710 | { |
768 | volatile struct qdio_buffer_element *sbale; | 711 | struct qdio_buffer_element *sbale; |
769 | 712 | ||
770 | struct zfcp_fsf_req *req; | 713 | struct zfcp_fsf_req *req; |
771 | struct zfcp_qdio_queue *req_q = &adapter->req_q; | 714 | struct zfcp_qdio_queue *req_q = &adapter->req_q; |
@@ -867,10 +810,10 @@ int zfcp_fsf_status_read(struct zfcp_adapter *adapter) | |||
867 | { | 810 | { |
868 | struct zfcp_fsf_req *req; | 811 | struct zfcp_fsf_req *req; |
869 | struct fsf_status_read_buffer *sr_buf; | 812 | struct fsf_status_read_buffer *sr_buf; |
870 | volatile struct qdio_buffer_element *sbale; | 813 | struct qdio_buffer_element *sbale; |
871 | int retval = -EIO; | 814 | int retval = -EIO; |
872 | 815 | ||
873 | spin_lock_bh(&adapter->req_q.lock); | 816 | spin_lock_bh(&adapter->req_q_lock); |
874 | if (zfcp_fsf_req_sbal_get(adapter)) | 817 | if (zfcp_fsf_req_sbal_get(adapter)) |
875 | goto out; | 818 | goto out; |
876 | 819 | ||
@@ -910,7 +853,7 @@ failed_buf: | |||
910 | zfcp_fsf_req_free(req); | 853 | zfcp_fsf_req_free(req); |
911 | zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL); | 854 | zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL); |
912 | out: | 855 | out: |
913 | spin_unlock_bh(&adapter->req_q.lock); | 856 | spin_unlock_bh(&adapter->req_q_lock); |
914 | return retval; | 857 | return retval; |
915 | } | 858 | } |
916 | 859 | ||
@@ -980,11 +923,11 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id, | |||
980 | struct zfcp_unit *unit, | 923 | struct zfcp_unit *unit, |
981 | int req_flags) | 924 | int req_flags) |
982 | { | 925 | { |
983 | volatile struct qdio_buffer_element *sbale; | 926 | struct qdio_buffer_element *sbale; |
984 | struct zfcp_fsf_req *req = NULL; | 927 | struct zfcp_fsf_req *req = NULL; |
985 | 928 | ||
986 | spin_lock(&adapter->req_q.lock); | 929 | spin_lock(&adapter->req_q_lock); |
987 | if (!atomic_read(&adapter->req_q.count)) | 930 | if (!zfcp_fsf_sbal_available(adapter)) |
988 | goto out; | 931 | goto out; |
989 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND, | 932 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND, |
990 | req_flags, adapter->pool.fsf_req_abort); | 933 | req_flags, adapter->pool.fsf_req_abort); |
@@ -1013,7 +956,7 @@ out_error_free: | |||
1013 | zfcp_fsf_req_free(req); | 956 | zfcp_fsf_req_free(req); |
1014 | req = NULL; | 957 | req = NULL; |
1015 | out: | 958 | out: |
1016 | spin_unlock(&adapter->req_q.lock); | 959 | spin_unlock(&adapter->req_q_lock); |
1017 | return req; | 960 | return req; |
1018 | } | 961 | } |
1019 | 962 | ||
@@ -1021,7 +964,6 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) | |||
1021 | { | 964 | { |
1022 | struct zfcp_adapter *adapter = req->adapter; | 965 | struct zfcp_adapter *adapter = req->adapter; |
1023 | struct zfcp_send_ct *send_ct = req->data; | 966 | struct zfcp_send_ct *send_ct = req->data; |
1024 | struct zfcp_port *port = send_ct->port; | ||
1025 | struct fsf_qtcb_header *header = &req->qtcb->header; | 967 | struct fsf_qtcb_header *header = &req->qtcb->header; |
1026 | 968 | ||
1027 | send_ct->status = -EINVAL; | 969 | send_ct->status = -EINVAL; |
@@ -1040,17 +982,14 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) | |||
1040 | case FSF_ADAPTER_STATUS_AVAILABLE: | 982 | case FSF_ADAPTER_STATUS_AVAILABLE: |
1041 | switch (header->fsf_status_qual.word[0]){ | 983 | switch (header->fsf_status_qual.word[0]){ |
1042 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: | 984 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
1043 | zfcp_test_link(port); | ||
1044 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: | 985 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: |
1045 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 986 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1046 | break; | 987 | break; |
1047 | } | 988 | } |
1048 | break; | 989 | break; |
1049 | case FSF_ACCESS_DENIED: | 990 | case FSF_ACCESS_DENIED: |
1050 | zfcp_fsf_access_denied_port(req, port); | ||
1051 | break; | 991 | break; |
1052 | case FSF_PORT_BOXED: | 992 | case FSF_PORT_BOXED: |
1053 | zfcp_erp_port_boxed(port, 49, req); | ||
1054 | req->status |= ZFCP_STATUS_FSFREQ_ERROR | | 993 | req->status |= ZFCP_STATUS_FSFREQ_ERROR | |
1055 | ZFCP_STATUS_FSFREQ_RETRY; | 994 | ZFCP_STATUS_FSFREQ_RETRY; |
1056 | break; | 995 | break; |
@@ -1101,12 +1040,12 @@ static int zfcp_fsf_setup_sbals(struct zfcp_fsf_req *req, | |||
1101 | int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, | 1040 | int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, |
1102 | struct zfcp_erp_action *erp_action) | 1041 | struct zfcp_erp_action *erp_action) |
1103 | { | 1042 | { |
1104 | struct zfcp_port *port = ct->port; | 1043 | struct zfcp_wka_port *wka_port = ct->wka_port; |
1105 | struct zfcp_adapter *adapter = port->adapter; | 1044 | struct zfcp_adapter *adapter = wka_port->adapter; |
1106 | struct zfcp_fsf_req *req; | 1045 | struct zfcp_fsf_req *req; |
1107 | int ret = -EIO; | 1046 | int ret = -EIO; |
1108 | 1047 | ||
1109 | spin_lock_bh(&adapter->req_q.lock); | 1048 | spin_lock_bh(&adapter->req_q_lock); |
1110 | if (zfcp_fsf_req_sbal_get(adapter)) | 1049 | if (zfcp_fsf_req_sbal_get(adapter)) |
1111 | goto out; | 1050 | goto out; |
1112 | 1051 | ||
@@ -1123,7 +1062,7 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, | |||
1123 | goto failed_send; | 1062 | goto failed_send; |
1124 | 1063 | ||
1125 | req->handler = zfcp_fsf_send_ct_handler; | 1064 | req->handler = zfcp_fsf_send_ct_handler; |
1126 | req->qtcb->header.port_handle = port->handle; | 1065 | req->qtcb->header.port_handle = wka_port->handle; |
1127 | req->qtcb->bottom.support.service_class = FSF_CLASS_3; | 1066 | req->qtcb->bottom.support.service_class = FSF_CLASS_3; |
1128 | req->qtcb->bottom.support.timeout = ct->timeout; | 1067 | req->qtcb->bottom.support.timeout = ct->timeout; |
1129 | req->data = ct; | 1068 | req->data = ct; |
@@ -1148,7 +1087,7 @@ failed_send: | |||
1148 | if (erp_action) | 1087 | if (erp_action) |
1149 | erp_action->fsf_req = NULL; | 1088 | erp_action->fsf_req = NULL; |
1150 | out: | 1089 | out: |
1151 | spin_unlock_bh(&adapter->req_q.lock); | 1090 | spin_unlock_bh(&adapter->req_q_lock); |
1152 | return ret; | 1091 | return ret; |
1153 | } | 1092 | } |
1154 | 1093 | ||
@@ -1218,8 +1157,8 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els) | |||
1218 | ZFCP_STATUS_COMMON_UNBLOCKED))) | 1157 | ZFCP_STATUS_COMMON_UNBLOCKED))) |
1219 | return -EBUSY; | 1158 | return -EBUSY; |
1220 | 1159 | ||
1221 | spin_lock(&adapter->req_q.lock); | 1160 | spin_lock(&adapter->req_q_lock); |
1222 | if (!atomic_read(&adapter->req_q.count)) | 1161 | if (!zfcp_fsf_sbal_available(adapter)) |
1223 | goto out; | 1162 | goto out; |
1224 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS, | 1163 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS, |
1225 | ZFCP_REQ_AUTO_CLEANUP, NULL); | 1164 | ZFCP_REQ_AUTO_CLEANUP, NULL); |
@@ -1228,8 +1167,8 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els) | |||
1228 | goto out; | 1167 | goto out; |
1229 | } | 1168 | } |
1230 | 1169 | ||
1231 | ret = zfcp_fsf_setup_sbals(req, els->req, els->resp, | 1170 | ret = zfcp_fsf_setup_sbals(req, els->req, els->resp, 2); |
1232 | FSF_MAX_SBALS_PER_ELS_REQ); | 1171 | |
1233 | if (ret) | 1172 | if (ret) |
1234 | goto failed_send; | 1173 | goto failed_send; |
1235 | 1174 | ||
@@ -1252,19 +1191,19 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els) | |||
1252 | failed_send: | 1191 | failed_send: |
1253 | zfcp_fsf_req_free(req); | 1192 | zfcp_fsf_req_free(req); |
1254 | out: | 1193 | out: |
1255 | spin_unlock(&adapter->req_q.lock); | 1194 | spin_unlock(&adapter->req_q_lock); |
1256 | return ret; | 1195 | return ret; |
1257 | } | 1196 | } |
1258 | 1197 | ||
1259 | int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) | 1198 | int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) |
1260 | { | 1199 | { |
1261 | volatile struct qdio_buffer_element *sbale; | 1200 | struct qdio_buffer_element *sbale; |
1262 | struct zfcp_fsf_req *req; | 1201 | struct zfcp_fsf_req *req; |
1263 | struct zfcp_adapter *adapter = erp_action->adapter; | 1202 | struct zfcp_adapter *adapter = erp_action->adapter; |
1264 | int retval = -EIO; | 1203 | int retval = -EIO; |
1265 | 1204 | ||
1266 | spin_lock_bh(&adapter->req_q.lock); | 1205 | spin_lock_bh(&adapter->req_q_lock); |
1267 | if (!atomic_read(&adapter->req_q.count)) | 1206 | if (!zfcp_fsf_sbal_available(adapter)) |
1268 | goto out; | 1207 | goto out; |
1269 | req = zfcp_fsf_req_create(adapter, | 1208 | req = zfcp_fsf_req_create(adapter, |
1270 | FSF_QTCB_EXCHANGE_CONFIG_DATA, | 1209 | FSF_QTCB_EXCHANGE_CONFIG_DATA, |
@@ -1295,18 +1234,18 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) | |||
1295 | erp_action->fsf_req = NULL; | 1234 | erp_action->fsf_req = NULL; |
1296 | } | 1235 | } |
1297 | out: | 1236 | out: |
1298 | spin_unlock_bh(&adapter->req_q.lock); | 1237 | spin_unlock_bh(&adapter->req_q_lock); |
1299 | return retval; | 1238 | return retval; |
1300 | } | 1239 | } |
1301 | 1240 | ||
1302 | int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, | 1241 | int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, |
1303 | struct fsf_qtcb_bottom_config *data) | 1242 | struct fsf_qtcb_bottom_config *data) |
1304 | { | 1243 | { |
1305 | volatile struct qdio_buffer_element *sbale; | 1244 | struct qdio_buffer_element *sbale; |
1306 | struct zfcp_fsf_req *req = NULL; | 1245 | struct zfcp_fsf_req *req = NULL; |
1307 | int retval = -EIO; | 1246 | int retval = -EIO; |
1308 | 1247 | ||
1309 | spin_lock_bh(&adapter->req_q.lock); | 1248 | spin_lock_bh(&adapter->req_q_lock); |
1310 | if (zfcp_fsf_req_sbal_get(adapter)) | 1249 | if (zfcp_fsf_req_sbal_get(adapter)) |
1311 | goto out; | 1250 | goto out; |
1312 | 1251 | ||
@@ -1334,7 +1273,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, | |||
1334 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | 1273 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); |
1335 | retval = zfcp_fsf_req_send(req); | 1274 | retval = zfcp_fsf_req_send(req); |
1336 | out: | 1275 | out: |
1337 | spin_unlock_bh(&adapter->req_q.lock); | 1276 | spin_unlock_bh(&adapter->req_q_lock); |
1338 | if (!retval) | 1277 | if (!retval) |
1339 | wait_event(req->completion_wq, | 1278 | wait_event(req->completion_wq, |
1340 | req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | 1279 | req->status & ZFCP_STATUS_FSFREQ_COMPLETED); |
@@ -1351,7 +1290,7 @@ out: | |||
1351 | */ | 1290 | */ |
1352 | int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) | 1291 | int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) |
1353 | { | 1292 | { |
1354 | volatile struct qdio_buffer_element *sbale; | 1293 | struct qdio_buffer_element *sbale; |
1355 | struct zfcp_fsf_req *req; | 1294 | struct zfcp_fsf_req *req; |
1356 | struct zfcp_adapter *adapter = erp_action->adapter; | 1295 | struct zfcp_adapter *adapter = erp_action->adapter; |
1357 | int retval = -EIO; | 1296 | int retval = -EIO; |
@@ -1359,8 +1298,8 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) | |||
1359 | if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) | 1298 | if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) |
1360 | return -EOPNOTSUPP; | 1299 | return -EOPNOTSUPP; |
1361 | 1300 | ||
1362 | spin_lock_bh(&adapter->req_q.lock); | 1301 | spin_lock_bh(&adapter->req_q_lock); |
1363 | if (!atomic_read(&adapter->req_q.count)) | 1302 | if (!zfcp_fsf_sbal_available(adapter)) |
1364 | goto out; | 1303 | goto out; |
1365 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, | 1304 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, |
1366 | ZFCP_REQ_AUTO_CLEANUP, | 1305 | ZFCP_REQ_AUTO_CLEANUP, |
@@ -1385,7 +1324,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) | |||
1385 | erp_action->fsf_req = NULL; | 1324 | erp_action->fsf_req = NULL; |
1386 | } | 1325 | } |
1387 | out: | 1326 | out: |
1388 | spin_unlock_bh(&adapter->req_q.lock); | 1327 | spin_unlock_bh(&adapter->req_q_lock); |
1389 | return retval; | 1328 | return retval; |
1390 | } | 1329 | } |
1391 | 1330 | ||
@@ -1398,15 +1337,15 @@ out: | |||
1398 | int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, | 1337 | int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, |
1399 | struct fsf_qtcb_bottom_port *data) | 1338 | struct fsf_qtcb_bottom_port *data) |
1400 | { | 1339 | { |
1401 | volatile struct qdio_buffer_element *sbale; | 1340 | struct qdio_buffer_element *sbale; |
1402 | struct zfcp_fsf_req *req = NULL; | 1341 | struct zfcp_fsf_req *req = NULL; |
1403 | int retval = -EIO; | 1342 | int retval = -EIO; |
1404 | 1343 | ||
1405 | if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) | 1344 | if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) |
1406 | return -EOPNOTSUPP; | 1345 | return -EOPNOTSUPP; |
1407 | 1346 | ||
1408 | spin_lock_bh(&adapter->req_q.lock); | 1347 | spin_lock_bh(&adapter->req_q_lock); |
1409 | if (!atomic_read(&adapter->req_q.count)) | 1348 | if (!zfcp_fsf_sbal_available(adapter)) |
1410 | goto out; | 1349 | goto out; |
1411 | 1350 | ||
1412 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0, | 1351 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0, |
@@ -1427,7 +1366,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, | |||
1427 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | 1366 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); |
1428 | retval = zfcp_fsf_req_send(req); | 1367 | retval = zfcp_fsf_req_send(req); |
1429 | out: | 1368 | out: |
1430 | spin_unlock_bh(&adapter->req_q.lock); | 1369 | spin_unlock_bh(&adapter->req_q_lock); |
1431 | if (!retval) | 1370 | if (!retval) |
1432 | wait_event(req->completion_wq, | 1371 | wait_event(req->completion_wq, |
1433 | req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | 1372 | req->status & ZFCP_STATUS_FSFREQ_COMPLETED); |
@@ -1443,7 +1382,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1443 | struct fsf_plogi *plogi; | 1382 | struct fsf_plogi *plogi; |
1444 | 1383 | ||
1445 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) | 1384 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
1446 | goto skip_fsfstatus; | 1385 | return; |
1447 | 1386 | ||
1448 | switch (header->fsf_status) { | 1387 | switch (header->fsf_status) { |
1449 | case FSF_PORT_ALREADY_OPEN: | 1388 | case FSF_PORT_ALREADY_OPEN: |
@@ -1453,9 +1392,9 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1453 | break; | 1392 | break; |
1454 | case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: | 1393 | case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: |
1455 | dev_warn(&req->adapter->ccw_device->dev, | 1394 | dev_warn(&req->adapter->ccw_device->dev, |
1456 | "The adapter is out of resources. The remote port " | 1395 | "Not enough FCP adapter resources to open " |
1457 | "0x%016Lx could not be opened, disabling it.\n", | 1396 | "remote port 0x%016Lx\n", |
1458 | port->wwpn); | 1397 | (unsigned long long)port->wwpn); |
1459 | zfcp_erp_port_failed(port, 31, req); | 1398 | zfcp_erp_port_failed(port, 31, req); |
1460 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1399 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1461 | break; | 1400 | break; |
@@ -1467,8 +1406,8 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1467 | break; | 1406 | break; |
1468 | case FSF_SQ_NO_RETRY_POSSIBLE: | 1407 | case FSF_SQ_NO_RETRY_POSSIBLE: |
1469 | dev_warn(&req->adapter->ccw_device->dev, | 1408 | dev_warn(&req->adapter->ccw_device->dev, |
1470 | "The remote port 0x%016Lx could not be " | 1409 | "Remote port 0x%016Lx could not be opened\n", |
1471 | "opened. Disabling it.\n", port->wwpn); | 1410 | (unsigned long long)port->wwpn); |
1472 | zfcp_erp_port_failed(port, 32, req); | 1411 | zfcp_erp_port_failed(port, 32, req); |
1473 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1412 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1474 | break; | 1413 | break; |
@@ -1496,9 +1435,6 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1496 | * another GID_PN straight after a port has been opened. | 1435 | * another GID_PN straight after a port has been opened. |
1497 | * Alternately, an ADISC/PDISC ELS should suffice, as well. | 1436 | * Alternately, an ADISC/PDISC ELS should suffice, as well. |
1498 | */ | 1437 | */ |
1499 | if (atomic_read(&port->status) & ZFCP_STATUS_PORT_NO_WWPN) | ||
1500 | break; | ||
1501 | |||
1502 | plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els; | 1438 | plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els; |
1503 | if (req->qtcb->bottom.support.els1_length >= sizeof(*plogi)) { | 1439 | if (req->qtcb->bottom.support.els1_length >= sizeof(*plogi)) { |
1504 | if (plogi->serv_param.wwpn != port->wwpn) | 1440 | if (plogi->serv_param.wwpn != port->wwpn) |
@@ -1514,9 +1450,6 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1514 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1450 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1515 | break; | 1451 | break; |
1516 | } | 1452 | } |
1517 | |||
1518 | skip_fsfstatus: | ||
1519 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &port->status); | ||
1520 | } | 1453 | } |
1521 | 1454 | ||
1522 | /** | 1455 | /** |
@@ -1526,12 +1459,12 @@ skip_fsfstatus: | |||
1526 | */ | 1459 | */ |
1527 | int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) | 1460 | int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) |
1528 | { | 1461 | { |
1529 | volatile struct qdio_buffer_element *sbale; | 1462 | struct qdio_buffer_element *sbale; |
1530 | struct zfcp_adapter *adapter = erp_action->adapter; | 1463 | struct zfcp_adapter *adapter = erp_action->adapter; |
1531 | struct zfcp_fsf_req *req; | 1464 | struct zfcp_fsf_req *req; |
1532 | int retval = -EIO; | 1465 | int retval = -EIO; |
1533 | 1466 | ||
1534 | spin_lock_bh(&adapter->req_q.lock); | 1467 | spin_lock_bh(&adapter->req_q_lock); |
1535 | if (zfcp_fsf_req_sbal_get(adapter)) | 1468 | if (zfcp_fsf_req_sbal_get(adapter)) |
1536 | goto out; | 1469 | goto out; |
1537 | 1470 | ||
@@ -1553,7 +1486,6 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) | |||
1553 | req->data = erp_action->port; | 1486 | req->data = erp_action->port; |
1554 | req->erp_action = erp_action; | 1487 | req->erp_action = erp_action; |
1555 | erp_action->fsf_req = req; | 1488 | erp_action->fsf_req = req; |
1556 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); | ||
1557 | 1489 | ||
1558 | zfcp_fsf_start_erp_timer(req); | 1490 | zfcp_fsf_start_erp_timer(req); |
1559 | retval = zfcp_fsf_req_send(req); | 1491 | retval = zfcp_fsf_req_send(req); |
@@ -1562,7 +1494,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) | |||
1562 | erp_action->fsf_req = NULL; | 1494 | erp_action->fsf_req = NULL; |
1563 | } | 1495 | } |
1564 | out: | 1496 | out: |
1565 | spin_unlock_bh(&adapter->req_q.lock); | 1497 | spin_unlock_bh(&adapter->req_q_lock); |
1566 | return retval; | 1498 | return retval; |
1567 | } | 1499 | } |
1568 | 1500 | ||
@@ -1571,7 +1503,7 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req) | |||
1571 | struct zfcp_port *port = req->data; | 1503 | struct zfcp_port *port = req->data; |
1572 | 1504 | ||
1573 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) | 1505 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
1574 | goto skip_fsfstatus; | 1506 | return; |
1575 | 1507 | ||
1576 | switch (req->qtcb->header.fsf_status) { | 1508 | switch (req->qtcb->header.fsf_status) { |
1577 | case FSF_PORT_HANDLE_NOT_VALID: | 1509 | case FSF_PORT_HANDLE_NOT_VALID: |
@@ -1586,9 +1518,6 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req) | |||
1586 | ZFCP_CLEAR); | 1518 | ZFCP_CLEAR); |
1587 | break; | 1519 | break; |
1588 | } | 1520 | } |
1589 | |||
1590 | skip_fsfstatus: | ||
1591 | atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &port->status); | ||
1592 | } | 1521 | } |
1593 | 1522 | ||
1594 | /** | 1523 | /** |
@@ -1598,12 +1527,12 @@ skip_fsfstatus: | |||
1598 | */ | 1527 | */ |
1599 | int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) | 1528 | int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) |
1600 | { | 1529 | { |
1601 | volatile struct qdio_buffer_element *sbale; | 1530 | struct qdio_buffer_element *sbale; |
1602 | struct zfcp_adapter *adapter = erp_action->adapter; | 1531 | struct zfcp_adapter *adapter = erp_action->adapter; |
1603 | struct zfcp_fsf_req *req; | 1532 | struct zfcp_fsf_req *req; |
1604 | int retval = -EIO; | 1533 | int retval = -EIO; |
1605 | 1534 | ||
1606 | spin_lock_bh(&adapter->req_q.lock); | 1535 | spin_lock_bh(&adapter->req_q_lock); |
1607 | if (zfcp_fsf_req_sbal_get(adapter)) | 1536 | if (zfcp_fsf_req_sbal_get(adapter)) |
1608 | goto out; | 1537 | goto out; |
1609 | 1538 | ||
@@ -1624,7 +1553,6 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) | |||
1624 | req->erp_action = erp_action; | 1553 | req->erp_action = erp_action; |
1625 | req->qtcb->header.port_handle = erp_action->port->handle; | 1554 | req->qtcb->header.port_handle = erp_action->port->handle; |
1626 | erp_action->fsf_req = req; | 1555 | erp_action->fsf_req = req; |
1627 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); | ||
1628 | 1556 | ||
1629 | zfcp_fsf_start_erp_timer(req); | 1557 | zfcp_fsf_start_erp_timer(req); |
1630 | retval = zfcp_fsf_req_send(req); | 1558 | retval = zfcp_fsf_req_send(req); |
@@ -1633,7 +1561,131 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) | |||
1633 | erp_action->fsf_req = NULL; | 1561 | erp_action->fsf_req = NULL; |
1634 | } | 1562 | } |
1635 | out: | 1563 | out: |
1636 | spin_unlock_bh(&adapter->req_q.lock); | 1564 | spin_unlock_bh(&adapter->req_q_lock); |
1565 | return retval; | ||
1566 | } | ||
1567 | |||
1568 | static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req) | ||
1569 | { | ||
1570 | struct zfcp_wka_port *wka_port = req->data; | ||
1571 | struct fsf_qtcb_header *header = &req->qtcb->header; | ||
1572 | |||
1573 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) { | ||
1574 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | ||
1575 | goto out; | ||
1576 | } | ||
1577 | |||
1578 | switch (header->fsf_status) { | ||
1579 | case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: | ||
1580 | dev_warn(&req->adapter->ccw_device->dev, | ||
1581 | "Opening WKA port 0x%x failed\n", wka_port->d_id); | ||
1582 | case FSF_ADAPTER_STATUS_AVAILABLE: | ||
1583 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
1584 | case FSF_ACCESS_DENIED: | ||
1585 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | ||
1586 | break; | ||
1587 | case FSF_PORT_ALREADY_OPEN: | ||
1588 | case FSF_GOOD: | ||
1589 | wka_port->handle = header->port_handle; | ||
1590 | wka_port->status = ZFCP_WKA_PORT_ONLINE; | ||
1591 | } | ||
1592 | out: | ||
1593 | wake_up(&wka_port->completion_wq); | ||
1594 | } | ||
1595 | |||
1596 | /** | ||
1597 | * zfcp_fsf_open_wka_port - create and send open wka-port request | ||
1598 | * @wka_port: pointer to struct zfcp_wka_port | ||
1599 | * Returns: 0 on success, error otherwise | ||
1600 | */ | ||
1601 | int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port) | ||
1602 | { | ||
1603 | struct qdio_buffer_element *sbale; | ||
1604 | struct zfcp_adapter *adapter = wka_port->adapter; | ||
1605 | struct zfcp_fsf_req *req; | ||
1606 | int retval = -EIO; | ||
1607 | |||
1608 | spin_lock_bh(&adapter->req_q_lock); | ||
1609 | if (zfcp_fsf_req_sbal_get(adapter)) | ||
1610 | goto out; | ||
1611 | |||
1612 | req = zfcp_fsf_req_create(adapter, | ||
1613 | FSF_QTCB_OPEN_PORT_WITH_DID, | ||
1614 | ZFCP_REQ_AUTO_CLEANUP, | ||
1615 | adapter->pool.fsf_req_erp); | ||
1616 | if (unlikely(IS_ERR(req))) { | ||
1617 | retval = PTR_ERR(req); | ||
1618 | goto out; | ||
1619 | } | ||
1620 | |||
1621 | sbale = zfcp_qdio_sbale_req(req); | ||
1622 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | ||
1623 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | ||
1624 | |||
1625 | req->handler = zfcp_fsf_open_wka_port_handler; | ||
1626 | req->qtcb->bottom.support.d_id = wka_port->d_id; | ||
1627 | req->data = wka_port; | ||
1628 | |||
1629 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | ||
1630 | retval = zfcp_fsf_req_send(req); | ||
1631 | if (retval) | ||
1632 | zfcp_fsf_req_free(req); | ||
1633 | out: | ||
1634 | spin_unlock_bh(&adapter->req_q_lock); | ||
1635 | return retval; | ||
1636 | } | ||
1637 | |||
1638 | static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req) | ||
1639 | { | ||
1640 | struct zfcp_wka_port *wka_port = req->data; | ||
1641 | |||
1642 | if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) { | ||
1643 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | ||
1644 | zfcp_erp_adapter_reopen(wka_port->adapter, 0, 84, req); | ||
1645 | } | ||
1646 | |||
1647 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | ||
1648 | wake_up(&wka_port->completion_wq); | ||
1649 | } | ||
1650 | |||
1651 | /** | ||
1652 | * zfcp_fsf_close_wka_port - create and send close wka port request | ||
1653 | * @erp_action: pointer to struct zfcp_erp_action | ||
1654 | * Returns: 0 on success, error otherwise | ||
1655 | */ | ||
1656 | int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port) | ||
1657 | { | ||
1658 | struct qdio_buffer_element *sbale; | ||
1659 | struct zfcp_adapter *adapter = wka_port->adapter; | ||
1660 | struct zfcp_fsf_req *req; | ||
1661 | int retval = -EIO; | ||
1662 | |||
1663 | spin_lock_bh(&adapter->req_q_lock); | ||
1664 | if (zfcp_fsf_req_sbal_get(adapter)) | ||
1665 | goto out; | ||
1666 | |||
1667 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT, | ||
1668 | ZFCP_REQ_AUTO_CLEANUP, | ||
1669 | adapter->pool.fsf_req_erp); | ||
1670 | if (unlikely(IS_ERR(req))) { | ||
1671 | retval = PTR_ERR(req); | ||
1672 | goto out; | ||
1673 | } | ||
1674 | |||
1675 | sbale = zfcp_qdio_sbale_req(req); | ||
1676 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | ||
1677 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | ||
1678 | |||
1679 | req->handler = zfcp_fsf_close_wka_port_handler; | ||
1680 | req->data = wka_port; | ||
1681 | req->qtcb->header.port_handle = wka_port->handle; | ||
1682 | |||
1683 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | ||
1684 | retval = zfcp_fsf_req_send(req); | ||
1685 | if (retval) | ||
1686 | zfcp_fsf_req_free(req); | ||
1687 | out: | ||
1688 | spin_unlock_bh(&adapter->req_q_lock); | ||
1637 | return retval; | 1689 | return retval; |
1638 | } | 1690 | } |
1639 | 1691 | ||
@@ -1695,12 +1747,12 @@ skip_fsfstatus: | |||
1695 | */ | 1747 | */ |
1696 | int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) | 1748 | int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) |
1697 | { | 1749 | { |
1698 | volatile struct qdio_buffer_element *sbale; | 1750 | struct qdio_buffer_element *sbale; |
1699 | struct zfcp_adapter *adapter = erp_action->adapter; | 1751 | struct zfcp_adapter *adapter = erp_action->adapter; |
1700 | struct zfcp_fsf_req *req; | 1752 | struct zfcp_fsf_req *req; |
1701 | int retval = -EIO; | 1753 | int retval = -EIO; |
1702 | 1754 | ||
1703 | spin_lock_bh(&adapter->req_q.lock); | 1755 | spin_lock_bh(&adapter->req_q_lock); |
1704 | if (zfcp_fsf_req_sbal_get(adapter)) | 1756 | if (zfcp_fsf_req_sbal_get(adapter)) |
1705 | goto out; | 1757 | goto out; |
1706 | 1758 | ||
@@ -1731,7 +1783,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) | |||
1731 | erp_action->fsf_req = NULL; | 1783 | erp_action->fsf_req = NULL; |
1732 | } | 1784 | } |
1733 | out: | 1785 | out: |
1734 | spin_unlock_bh(&adapter->req_q.lock); | 1786 | spin_unlock_bh(&adapter->req_q_lock); |
1735 | return retval; | 1787 | return retval; |
1736 | } | 1788 | } |
1737 | 1789 | ||
@@ -1746,7 +1798,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) | |||
1746 | int exclusive, readwrite; | 1798 | int exclusive, readwrite; |
1747 | 1799 | ||
1748 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) | 1800 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
1749 | goto skip_fsfstatus; | 1801 | return; |
1750 | 1802 | ||
1751 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | | 1803 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | |
1752 | ZFCP_STATUS_COMMON_ACCESS_BOXED | | 1804 | ZFCP_STATUS_COMMON_ACCESS_BOXED | |
@@ -1774,14 +1826,12 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) | |||
1774 | case FSF_LUN_SHARING_VIOLATION: | 1826 | case FSF_LUN_SHARING_VIOLATION: |
1775 | if (header->fsf_status_qual.word[0]) | 1827 | if (header->fsf_status_qual.word[0]) |
1776 | dev_warn(&adapter->ccw_device->dev, | 1828 | dev_warn(&adapter->ccw_device->dev, |
1777 | "FCP-LUN 0x%Lx at the remote port " | 1829 | "LUN 0x%Lx on port 0x%Lx is already in " |
1778 | "with WWPN 0x%Lx " | 1830 | "use by CSS%d, MIF Image ID %x\n", |
1779 | "connected to the adapter " | 1831 | (unsigned long long)unit->fcp_lun, |
1780 | "is already in use in LPAR%d, CSS%d.\n", | 1832 | (unsigned long long)unit->port->wwpn, |
1781 | unit->fcp_lun, | 1833 | queue_designator->cssid, |
1782 | unit->port->wwpn, | 1834 | queue_designator->hla); |
1783 | queue_designator->hla, | ||
1784 | queue_designator->cssid); | ||
1785 | else | 1835 | else |
1786 | zfcp_act_eval_err(adapter, | 1836 | zfcp_act_eval_err(adapter, |
1787 | header->fsf_status_qual.word[2]); | 1837 | header->fsf_status_qual.word[2]); |
@@ -1792,9 +1842,10 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) | |||
1792 | break; | 1842 | break; |
1793 | case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED: | 1843 | case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED: |
1794 | dev_warn(&adapter->ccw_device->dev, | 1844 | dev_warn(&adapter->ccw_device->dev, |
1795 | "The adapter ran out of resources. There is no " | 1845 | "No handle is available for LUN " |
1796 | "handle available for unit 0x%016Lx on port 0x%016Lx.", | 1846 | "0x%016Lx on port 0x%016Lx\n", |
1797 | unit->fcp_lun, unit->port->wwpn); | 1847 | (unsigned long long)unit->fcp_lun, |
1848 | (unsigned long long)unit->port->wwpn); | ||
1798 | zfcp_erp_unit_failed(unit, 34, req); | 1849 | zfcp_erp_unit_failed(unit, 34, req); |
1799 | /* fall through */ | 1850 | /* fall through */ |
1800 | case FSF_INVALID_COMMAND_OPTION: | 1851 | case FSF_INVALID_COMMAND_OPTION: |
@@ -1831,26 +1882,29 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) | |||
1831 | atomic_set_mask(ZFCP_STATUS_UNIT_READONLY, | 1882 | atomic_set_mask(ZFCP_STATUS_UNIT_READONLY, |
1832 | &unit->status); | 1883 | &unit->status); |
1833 | dev_info(&adapter->ccw_device->dev, | 1884 | dev_info(&adapter->ccw_device->dev, |
1834 | "Read-only access for unit 0x%016Lx " | 1885 | "SCSI device at LUN 0x%016Lx on port " |
1835 | "on port 0x%016Lx.\n", | 1886 | "0x%016Lx opened read-only\n", |
1836 | unit->fcp_lun, unit->port->wwpn); | 1887 | (unsigned long long)unit->fcp_lun, |
1888 | (unsigned long long)unit->port->wwpn); | ||
1837 | } | 1889 | } |
1838 | 1890 | ||
1839 | if (exclusive && !readwrite) { | 1891 | if (exclusive && !readwrite) { |
1840 | dev_err(&adapter->ccw_device->dev, | 1892 | dev_err(&adapter->ccw_device->dev, |
1841 | "Exclusive access of read-only unit " | 1893 | "Exclusive read-only access not " |
1842 | "0x%016Lx on port 0x%016Lx not " | 1894 | "supported (unit 0x%016Lx, " |
1843 | "supported, disabling unit.\n", | 1895 | "port 0x%016Lx)\n", |
1844 | unit->fcp_lun, unit->port->wwpn); | 1896 | (unsigned long long)unit->fcp_lun, |
1897 | (unsigned long long)unit->port->wwpn); | ||
1845 | zfcp_erp_unit_failed(unit, 35, req); | 1898 | zfcp_erp_unit_failed(unit, 35, req); |
1846 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1899 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1847 | zfcp_erp_unit_shutdown(unit, 0, 80, req); | 1900 | zfcp_erp_unit_shutdown(unit, 0, 80, req); |
1848 | } else if (!exclusive && readwrite) { | 1901 | } else if (!exclusive && readwrite) { |
1849 | dev_err(&adapter->ccw_device->dev, | 1902 | dev_err(&adapter->ccw_device->dev, |
1850 | "Shared access of read-write unit " | 1903 | "Shared read-write access not " |
1851 | "0x%016Lx on port 0x%016Lx not " | 1904 | "supported (unit 0x%016Lx, port " |
1852 | "supported, disabling unit.\n", | 1905 | "0x%016Lx\n)", |
1853 | unit->fcp_lun, unit->port->wwpn); | 1906 | (unsigned long long)unit->fcp_lun, |
1907 | (unsigned long long)unit->port->wwpn); | ||
1854 | zfcp_erp_unit_failed(unit, 36, req); | 1908 | zfcp_erp_unit_failed(unit, 36, req); |
1855 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1909 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1856 | zfcp_erp_unit_shutdown(unit, 0, 81, req); | 1910 | zfcp_erp_unit_shutdown(unit, 0, 81, req); |
@@ -1858,9 +1912,6 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) | |||
1858 | } | 1912 | } |
1859 | break; | 1913 | break; |
1860 | } | 1914 | } |
1861 | |||
1862 | skip_fsfstatus: | ||
1863 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &unit->status); | ||
1864 | } | 1915 | } |
1865 | 1916 | ||
1866 | /** | 1917 | /** |
@@ -1870,12 +1921,12 @@ skip_fsfstatus: | |||
1870 | */ | 1921 | */ |
1871 | int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | 1922 | int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) |
1872 | { | 1923 | { |
1873 | volatile struct qdio_buffer_element *sbale; | 1924 | struct qdio_buffer_element *sbale; |
1874 | struct zfcp_adapter *adapter = erp_action->adapter; | 1925 | struct zfcp_adapter *adapter = erp_action->adapter; |
1875 | struct zfcp_fsf_req *req; | 1926 | struct zfcp_fsf_req *req; |
1876 | int retval = -EIO; | 1927 | int retval = -EIO; |
1877 | 1928 | ||
1878 | spin_lock_bh(&adapter->req_q.lock); | 1929 | spin_lock_bh(&adapter->req_q_lock); |
1879 | if (zfcp_fsf_req_sbal_get(adapter)) | 1930 | if (zfcp_fsf_req_sbal_get(adapter)) |
1880 | goto out; | 1931 | goto out; |
1881 | 1932 | ||
@@ -1901,8 +1952,6 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | |||
1901 | if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) | 1952 | if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) |
1902 | req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING; | 1953 | req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING; |
1903 | 1954 | ||
1904 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); | ||
1905 | |||
1906 | zfcp_fsf_start_erp_timer(req); | 1955 | zfcp_fsf_start_erp_timer(req); |
1907 | retval = zfcp_fsf_req_send(req); | 1956 | retval = zfcp_fsf_req_send(req); |
1908 | if (retval) { | 1957 | if (retval) { |
@@ -1910,7 +1959,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | |||
1910 | erp_action->fsf_req = NULL; | 1959 | erp_action->fsf_req = NULL; |
1911 | } | 1960 | } |
1912 | out: | 1961 | out: |
1913 | spin_unlock_bh(&adapter->req_q.lock); | 1962 | spin_unlock_bh(&adapter->req_q_lock); |
1914 | return retval; | 1963 | return retval; |
1915 | } | 1964 | } |
1916 | 1965 | ||
@@ -1919,7 +1968,7 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req) | |||
1919 | struct zfcp_unit *unit = req->data; | 1968 | struct zfcp_unit *unit = req->data; |
1920 | 1969 | ||
1921 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) | 1970 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
1922 | goto skip_fsfstatus; | 1971 | return; |
1923 | 1972 | ||
1924 | switch (req->qtcb->header.fsf_status) { | 1973 | switch (req->qtcb->header.fsf_status) { |
1925 | case FSF_PORT_HANDLE_NOT_VALID: | 1974 | case FSF_PORT_HANDLE_NOT_VALID: |
@@ -1949,8 +1998,6 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req) | |||
1949 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); | 1998 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); |
1950 | break; | 1999 | break; |
1951 | } | 2000 | } |
1952 | skip_fsfstatus: | ||
1953 | atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &unit->status); | ||
1954 | } | 2001 | } |
1955 | 2002 | ||
1956 | /** | 2003 | /** |
@@ -1960,12 +2007,12 @@ skip_fsfstatus: | |||
1960 | */ | 2007 | */ |
1961 | int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) | 2008 | int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) |
1962 | { | 2009 | { |
1963 | volatile struct qdio_buffer_element *sbale; | 2010 | struct qdio_buffer_element *sbale; |
1964 | struct zfcp_adapter *adapter = erp_action->adapter; | 2011 | struct zfcp_adapter *adapter = erp_action->adapter; |
1965 | struct zfcp_fsf_req *req; | 2012 | struct zfcp_fsf_req *req; |
1966 | int retval = -EIO; | 2013 | int retval = -EIO; |
1967 | 2014 | ||
1968 | spin_lock_bh(&adapter->req_q.lock); | 2015 | spin_lock_bh(&adapter->req_q_lock); |
1969 | if (zfcp_fsf_req_sbal_get(adapter)) | 2016 | if (zfcp_fsf_req_sbal_get(adapter)) |
1970 | goto out; | 2017 | goto out; |
1971 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_LUN, | 2018 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_LUN, |
@@ -1986,7 +2033,6 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) | |||
1986 | req->data = erp_action->unit; | 2033 | req->data = erp_action->unit; |
1987 | req->erp_action = erp_action; | 2034 | req->erp_action = erp_action; |
1988 | erp_action->fsf_req = req; | 2035 | erp_action->fsf_req = req; |
1989 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); | ||
1990 | 2036 | ||
1991 | zfcp_fsf_start_erp_timer(req); | 2037 | zfcp_fsf_start_erp_timer(req); |
1992 | retval = zfcp_fsf_req_send(req); | 2038 | retval = zfcp_fsf_req_send(req); |
@@ -1995,7 +2041,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) | |||
1995 | erp_action->fsf_req = NULL; | 2041 | erp_action->fsf_req = NULL; |
1996 | } | 2042 | } |
1997 | out: | 2043 | out: |
1998 | spin_unlock_bh(&adapter->req_q.lock); | 2044 | spin_unlock_bh(&adapter->req_q_lock); |
1999 | return retval; | 2045 | return retval; |
2000 | } | 2046 | } |
2001 | 2047 | ||
@@ -2156,21 +2202,21 @@ static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req) | |||
2156 | break; | 2202 | break; |
2157 | case FSF_DIRECTION_INDICATOR_NOT_VALID: | 2203 | case FSF_DIRECTION_INDICATOR_NOT_VALID: |
2158 | dev_err(&req->adapter->ccw_device->dev, | 2204 | dev_err(&req->adapter->ccw_device->dev, |
2159 | "Invalid data direction (%d) given for unit " | 2205 | "Incorrect direction %d, unit 0x%016Lx on port " |
2160 | "0x%016Lx on port 0x%016Lx, shutting down " | 2206 | "0x%016Lx closed\n", |
2161 | "adapter.\n", | ||
2162 | req->qtcb->bottom.io.data_direction, | 2207 | req->qtcb->bottom.io.data_direction, |
2163 | unit->fcp_lun, unit->port->wwpn); | 2208 | (unsigned long long)unit->fcp_lun, |
2209 | (unsigned long long)unit->port->wwpn); | ||
2164 | zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 133, req); | 2210 | zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 133, req); |
2165 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 2211 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
2166 | break; | 2212 | break; |
2167 | case FSF_CMND_LENGTH_NOT_VALID: | 2213 | case FSF_CMND_LENGTH_NOT_VALID: |
2168 | dev_err(&req->adapter->ccw_device->dev, | 2214 | dev_err(&req->adapter->ccw_device->dev, |
2169 | "An invalid control-data-block length field (%d) " | 2215 | "Incorrect CDB length %d, unit 0x%016Lx on " |
2170 | "was found in a command for unit 0x%016Lx on port " | 2216 | "port 0x%016Lx closed\n", |
2171 | "0x%016Lx. Shutting down adapter.\n", | ||
2172 | req->qtcb->bottom.io.fcp_cmnd_length, | 2217 | req->qtcb->bottom.io.fcp_cmnd_length, |
2173 | unit->fcp_lun, unit->port->wwpn); | 2218 | (unsigned long long)unit->fcp_lun, |
2219 | (unsigned long long)unit->port->wwpn); | ||
2174 | zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 134, req); | 2220 | zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 134, req); |
2175 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 2221 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
2176 | break; | 2222 | break; |
@@ -2201,6 +2247,20 @@ skip_fsfstatus: | |||
2201 | } | 2247 | } |
2202 | } | 2248 | } |
2203 | 2249 | ||
2250 | static void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, u32 fcp_dl) | ||
2251 | { | ||
2252 | u32 *fcp_dl_ptr; | ||
2253 | |||
2254 | /* | ||
2255 | * fcp_dl_addr = start address of fcp_cmnd structure + | ||
2256 | * size of fixed part + size of dynamically sized add_dcp_cdb field | ||
2257 | * SEE FCP-2 documentation | ||
2258 | */ | ||
2259 | fcp_dl_ptr = (u32 *) ((unsigned char *) &fcp_cmd[1] + | ||
2260 | (fcp_cmd->add_fcp_cdb_length << 2)); | ||
2261 | *fcp_dl_ptr = fcp_dl; | ||
2262 | } | ||
2263 | |||
2204 | /** | 2264 | /** |
2205 | * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command) | 2265 | * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command) |
2206 | * @adapter: adapter where scsi command is issued | 2266 | * @adapter: adapter where scsi command is issued |
@@ -2223,8 +2283,8 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, | |||
2223 | ZFCP_STATUS_COMMON_UNBLOCKED))) | 2283 | ZFCP_STATUS_COMMON_UNBLOCKED))) |
2224 | return -EBUSY; | 2284 | return -EBUSY; |
2225 | 2285 | ||
2226 | spin_lock(&adapter->req_q.lock); | 2286 | spin_lock(&adapter->req_q_lock); |
2227 | if (!atomic_read(&adapter->req_q.count)) | 2287 | if (!zfcp_fsf_sbal_available(adapter)) |
2228 | goto out; | 2288 | goto out; |
2229 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, | 2289 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, |
2230 | adapter->pool.fsf_req_scsi); | 2290 | adapter->pool.fsf_req_scsi); |
@@ -2286,7 +2346,7 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, | |||
2286 | memcpy(fcp_cmnd_iu->fcp_cdb, scsi_cmnd->cmnd, scsi_cmnd->cmd_len); | 2346 | memcpy(fcp_cmnd_iu->fcp_cdb, scsi_cmnd->cmnd, scsi_cmnd->cmd_len); |
2287 | 2347 | ||
2288 | req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) + | 2348 | req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) + |
2289 | fcp_cmnd_iu->add_fcp_cdb_length + sizeof(fcp_dl_t); | 2349 | fcp_cmnd_iu->add_fcp_cdb_length + sizeof(u32); |
2290 | 2350 | ||
2291 | real_bytes = zfcp_qdio_sbals_from_sg(req, sbtype, | 2351 | real_bytes = zfcp_qdio_sbals_from_sg(req, sbtype, |
2292 | scsi_sglist(scsi_cmnd), | 2352 | scsi_sglist(scsi_cmnd), |
@@ -2296,10 +2356,10 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, | |||
2296 | retval = -EIO; | 2356 | retval = -EIO; |
2297 | else { | 2357 | else { |
2298 | dev_err(&adapter->ccw_device->dev, | 2358 | dev_err(&adapter->ccw_device->dev, |
2299 | "SCSI request too large. " | 2359 | "Oversize data package, unit 0x%016Lx " |
2300 | "Shutting down unit 0x%016Lx on port " | 2360 | "on port 0x%016Lx closed\n", |
2301 | "0x%016Lx.\n", unit->fcp_lun, | 2361 | (unsigned long long)unit->fcp_lun, |
2302 | unit->port->wwpn); | 2362 | (unsigned long long)unit->port->wwpn); |
2303 | zfcp_erp_unit_shutdown(unit, 0, 131, req); | 2363 | zfcp_erp_unit_shutdown(unit, 0, 131, req); |
2304 | retval = -EINVAL; | 2364 | retval = -EINVAL; |
2305 | } | 2365 | } |
@@ -2322,7 +2382,7 @@ failed_scsi_cmnd: | |||
2322 | zfcp_fsf_req_free(req); | 2382 | zfcp_fsf_req_free(req); |
2323 | scsi_cmnd->host_scribble = NULL; | 2383 | scsi_cmnd->host_scribble = NULL; |
2324 | out: | 2384 | out: |
2325 | spin_unlock(&adapter->req_q.lock); | 2385 | spin_unlock(&adapter->req_q_lock); |
2326 | return retval; | 2386 | return retval; |
2327 | } | 2387 | } |
2328 | 2388 | ||
@@ -2338,7 +2398,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, | |||
2338 | struct zfcp_unit *unit, | 2398 | struct zfcp_unit *unit, |
2339 | u8 tm_flags, int req_flags) | 2399 | u8 tm_flags, int req_flags) |
2340 | { | 2400 | { |
2341 | volatile struct qdio_buffer_element *sbale; | 2401 | struct qdio_buffer_element *sbale; |
2342 | struct zfcp_fsf_req *req = NULL; | 2402 | struct zfcp_fsf_req *req = NULL; |
2343 | struct fcp_cmnd_iu *fcp_cmnd_iu; | 2403 | struct fcp_cmnd_iu *fcp_cmnd_iu; |
2344 | 2404 | ||
@@ -2346,8 +2406,8 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, | |||
2346 | ZFCP_STATUS_COMMON_UNBLOCKED))) | 2406 | ZFCP_STATUS_COMMON_UNBLOCKED))) |
2347 | return NULL; | 2407 | return NULL; |
2348 | 2408 | ||
2349 | spin_lock(&adapter->req_q.lock); | 2409 | spin_lock(&adapter->req_q_lock); |
2350 | if (!atomic_read(&adapter->req_q.count)) | 2410 | if (!zfcp_fsf_sbal_available(adapter)) |
2351 | goto out; | 2411 | goto out; |
2352 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, | 2412 | req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, |
2353 | adapter->pool.fsf_req_scsi); | 2413 | adapter->pool.fsf_req_scsi); |
@@ -2362,7 +2422,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, | |||
2362 | req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; | 2422 | req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; |
2363 | req->qtcb->bottom.io.service_class = FSF_CLASS_3; | 2423 | req->qtcb->bottom.io.service_class = FSF_CLASS_3; |
2364 | req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) + | 2424 | req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) + |
2365 | sizeof(fcp_dl_t); | 2425 | sizeof(u32); |
2366 | 2426 | ||
2367 | sbale = zfcp_qdio_sbale_req(req); | 2427 | sbale = zfcp_qdio_sbale_req(req); |
2368 | sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE; | 2428 | sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE; |
@@ -2379,7 +2439,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, | |||
2379 | zfcp_fsf_req_free(req); | 2439 | zfcp_fsf_req_free(req); |
2380 | req = NULL; | 2440 | req = NULL; |
2381 | out: | 2441 | out: |
2382 | spin_unlock(&adapter->req_q.lock); | 2442 | spin_unlock(&adapter->req_q_lock); |
2383 | return req; | 2443 | return req; |
2384 | } | 2444 | } |
2385 | 2445 | ||
@@ -2398,7 +2458,7 @@ static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req) | |||
2398 | struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, | 2458 | struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, |
2399 | struct zfcp_fsf_cfdc *fsf_cfdc) | 2459 | struct zfcp_fsf_cfdc *fsf_cfdc) |
2400 | { | 2460 | { |
2401 | volatile struct qdio_buffer_element *sbale; | 2461 | struct qdio_buffer_element *sbale; |
2402 | struct zfcp_fsf_req *req = NULL; | 2462 | struct zfcp_fsf_req *req = NULL; |
2403 | struct fsf_qtcb_bottom_support *bottom; | 2463 | struct fsf_qtcb_bottom_support *bottom; |
2404 | int direction, retval = -EIO, bytes; | 2464 | int direction, retval = -EIO, bytes; |
@@ -2417,7 +2477,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, | |||
2417 | return ERR_PTR(-EINVAL); | 2477 | return ERR_PTR(-EINVAL); |
2418 | } | 2478 | } |
2419 | 2479 | ||
2420 | spin_lock_bh(&adapter->req_q.lock); | 2480 | spin_lock_bh(&adapter->req_q_lock); |
2421 | if (zfcp_fsf_req_sbal_get(adapter)) | 2481 | if (zfcp_fsf_req_sbal_get(adapter)) |
2422 | goto out; | 2482 | goto out; |
2423 | 2483 | ||
@@ -2447,7 +2507,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, | |||
2447 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | 2507 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); |
2448 | retval = zfcp_fsf_req_send(req); | 2508 | retval = zfcp_fsf_req_send(req); |
2449 | out: | 2509 | out: |
2450 | spin_unlock_bh(&adapter->req_q.lock); | 2510 | spin_unlock_bh(&adapter->req_q_lock); |
2451 | 2511 | ||
2452 | if (!retval) { | 2512 | if (!retval) { |
2453 | wait_event(req->completion_wq, | 2513 | wait_event(req->completion_wq, |
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index bf94b4da0763..fd3a88777ac8 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h | |||
@@ -71,13 +71,6 @@ | |||
71 | #define FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED 0x00000041 | 71 | #define FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED 0x00000041 |
72 | #define FSF_ELS_COMMAND_REJECTED 0x00000050 | 72 | #define FSF_ELS_COMMAND_REJECTED 0x00000050 |
73 | #define FSF_GENERIC_COMMAND_REJECTED 0x00000051 | 73 | #define FSF_GENERIC_COMMAND_REJECTED 0x00000051 |
74 | #define FSF_OPERATION_PARTIALLY_SUCCESSFUL 0x00000052 | ||
75 | #define FSF_AUTHORIZATION_FAILURE 0x00000053 | ||
76 | #define FSF_CFDC_ERROR_DETECTED 0x00000054 | ||
77 | #define FSF_CONTROL_FILE_UPDATE_ERROR 0x00000055 | ||
78 | #define FSF_CONTROL_FILE_TOO_LARGE 0x00000056 | ||
79 | #define FSF_ACCESS_CONFLICT_DETECTED 0x00000057 | ||
80 | #define FSF_CONFLICTS_OVERRULED 0x00000058 | ||
81 | #define FSF_PORT_BOXED 0x00000059 | 74 | #define FSF_PORT_BOXED 0x00000059 |
82 | #define FSF_LUN_BOXED 0x0000005A | 75 | #define FSF_LUN_BOXED 0x0000005A |
83 | #define FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE 0x0000005B | 76 | #define FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE 0x0000005B |
@@ -85,9 +78,7 @@ | |||
85 | #define FSF_REQUEST_SIZE_TOO_LARGE 0x00000061 | 78 | #define FSF_REQUEST_SIZE_TOO_LARGE 0x00000061 |
86 | #define FSF_RESPONSE_SIZE_TOO_LARGE 0x00000062 | 79 | #define FSF_RESPONSE_SIZE_TOO_LARGE 0x00000062 |
87 | #define FSF_SBAL_MISMATCH 0x00000063 | 80 | #define FSF_SBAL_MISMATCH 0x00000063 |
88 | #define FSF_OPEN_PORT_WITHOUT_PRLI 0x00000064 | ||
89 | #define FSF_ADAPTER_STATUS_AVAILABLE 0x000000AD | 81 | #define FSF_ADAPTER_STATUS_AVAILABLE 0x000000AD |
90 | #define FSF_FCP_RSP_AVAILABLE 0x000000AF | ||
91 | #define FSF_UNKNOWN_COMMAND 0x000000E2 | 82 | #define FSF_UNKNOWN_COMMAND 0x000000E2 |
92 | #define FSF_UNKNOWN_OP_SUBTYPE 0x000000E3 | 83 | #define FSF_UNKNOWN_OP_SUBTYPE 0x000000E3 |
93 | #define FSF_INVALID_COMMAND_OPTION 0x000000E5 | 84 | #define FSF_INVALID_COMMAND_OPTION 0x000000E5 |
@@ -102,20 +93,9 @@ | |||
102 | #define FSF_SQ_RETRY_IF_POSSIBLE 0x02 | 93 | #define FSF_SQ_RETRY_IF_POSSIBLE 0x02 |
103 | #define FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED 0x03 | 94 | #define FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED 0x03 |
104 | #define FSF_SQ_INVOKE_LINK_TEST_PROCEDURE 0x04 | 95 | #define FSF_SQ_INVOKE_LINK_TEST_PROCEDURE 0x04 |
105 | #define FSF_SQ_ULP_PROGRAMMING_ERROR 0x05 | ||
106 | #define FSF_SQ_COMMAND_ABORTED 0x06 | 96 | #define FSF_SQ_COMMAND_ABORTED 0x06 |
107 | #define FSF_SQ_NO_RETRY_POSSIBLE 0x07 | 97 | #define FSF_SQ_NO_RETRY_POSSIBLE 0x07 |
108 | 98 | ||
109 | /* FSF status qualifier for CFDC commands */ | ||
110 | #define FSF_SQ_CFDC_HARDENED_ON_SE 0x00000000 | ||
111 | #define FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE 0x00000001 | ||
112 | #define FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE2 0x00000002 | ||
113 | /* CFDC subtable codes */ | ||
114 | #define FSF_SQ_CFDC_SUBTABLE_OS 0x0001 | ||
115 | #define FSF_SQ_CFDC_SUBTABLE_PORT_WWPN 0x0002 | ||
116 | #define FSF_SQ_CFDC_SUBTABLE_PORT_DID 0x0003 | ||
117 | #define FSF_SQ_CFDC_SUBTABLE_LUN 0x0004 | ||
118 | |||
119 | /* FSF status qualifier (most significant 4 bytes), local link down */ | 99 | /* FSF status qualifier (most significant 4 bytes), local link down */ |
120 | #define FSF_PSQ_LINK_NO_LIGHT 0x00000004 | 100 | #define FSF_PSQ_LINK_NO_LIGHT 0x00000004 |
121 | #define FSF_PSQ_LINK_WRAP_PLUG 0x00000008 | 101 | #define FSF_PSQ_LINK_WRAP_PLUG 0x00000008 |
@@ -145,7 +125,6 @@ | |||
145 | #define FSF_STATUS_READ_LINK_UP 0x00000006 | 125 | #define FSF_STATUS_READ_LINK_UP 0x00000006 |
146 | #define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009 | 126 | #define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009 |
147 | #define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A | 127 | #define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A |
148 | #define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B | ||
149 | #define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C | 128 | #define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C |
150 | 129 | ||
151 | /* status subtypes in status read buffer */ | 130 | /* status subtypes in status read buffer */ |
@@ -159,20 +138,9 @@ | |||
159 | 138 | ||
160 | /* status subtypes for unsolicited status notification lost */ | 139 | /* status subtypes for unsolicited status notification lost */ |
161 | #define FSF_STATUS_READ_SUB_INCOMING_ELS 0x00000001 | 140 | #define FSF_STATUS_READ_SUB_INCOMING_ELS 0x00000001 |
162 | #define FSF_STATUS_READ_SUB_SENSE_DATA 0x00000002 | ||
163 | #define FSF_STATUS_READ_SUB_LINK_STATUS 0x00000004 | ||
164 | #define FSF_STATUS_READ_SUB_PORT_CLOSED 0x00000008 | ||
165 | #define FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD 0x00000010 | ||
166 | #define FSF_STATUS_READ_SUB_ACT_UPDATED 0x00000020 | 141 | #define FSF_STATUS_READ_SUB_ACT_UPDATED 0x00000020 |
167 | #define FSF_STATUS_READ_SUB_ACT_HARDENED 0x00000040 | ||
168 | #define FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT 0x00000080 | ||
169 | |||
170 | /* status subtypes for CFDC */ | ||
171 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002 | ||
172 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F | ||
173 | 142 | ||
174 | /* topologie that is detected by the adapter */ | 143 | /* topologie that is detected by the adapter */ |
175 | #define FSF_TOPO_ERROR 0x00000000 | ||
176 | #define FSF_TOPO_P2P 0x00000001 | 144 | #define FSF_TOPO_P2P 0x00000001 |
177 | #define FSF_TOPO_FABRIC 0x00000002 | 145 | #define FSF_TOPO_FABRIC 0x00000002 |
178 | #define FSF_TOPO_AL 0x00000003 | 146 | #define FSF_TOPO_AL 0x00000003 |
@@ -180,17 +148,13 @@ | |||
180 | /* data direction for FCP commands */ | 148 | /* data direction for FCP commands */ |
181 | #define FSF_DATADIR_WRITE 0x00000001 | 149 | #define FSF_DATADIR_WRITE 0x00000001 |
182 | #define FSF_DATADIR_READ 0x00000002 | 150 | #define FSF_DATADIR_READ 0x00000002 |
183 | #define FSF_DATADIR_READ_WRITE 0x00000003 | ||
184 | #define FSF_DATADIR_CMND 0x00000004 | 151 | #define FSF_DATADIR_CMND 0x00000004 |
185 | 152 | ||
186 | /* fc service class */ | 153 | /* fc service class */ |
187 | #define FSF_CLASS_1 0x00000001 | ||
188 | #define FSF_CLASS_2 0x00000002 | ||
189 | #define FSF_CLASS_3 0x00000003 | 154 | #define FSF_CLASS_3 0x00000003 |
190 | 155 | ||
191 | /* SBAL chaining */ | 156 | /* SBAL chaining */ |
192 | #define FSF_MAX_SBALS_PER_REQ 36 | 157 | #define FSF_MAX_SBALS_PER_REQ 36 |
193 | #define FSF_MAX_SBALS_PER_ELS_REQ 2 | ||
194 | 158 | ||
195 | /* logging space behind QTCB */ | 159 | /* logging space behind QTCB */ |
196 | #define FSF_QTCB_LOG_SIZE 1024 | 160 | #define FSF_QTCB_LOG_SIZE 1024 |
@@ -200,50 +164,16 @@ | |||
200 | #define FSF_FEATURE_LUN_SHARING 0x00000004 | 164 | #define FSF_FEATURE_LUN_SHARING 0x00000004 |
201 | #define FSF_FEATURE_NOTIFICATION_LOST 0x00000008 | 165 | #define FSF_FEATURE_NOTIFICATION_LOST 0x00000008 |
202 | #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 | 166 | #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 |
203 | #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 | ||
204 | #define FSF_FEATURE_UPDATE_ALERT 0x00000100 | 167 | #define FSF_FEATURE_UPDATE_ALERT 0x00000100 |
205 | #define FSF_FEATURE_MEASUREMENT_DATA 0x00000200 | 168 | #define FSF_FEATURE_MEASUREMENT_DATA 0x00000200 |
206 | 169 | ||
207 | /* host connection features */ | 170 | /* host connection features */ |
208 | #define FSF_FEATURE_NPIV_MODE 0x00000001 | 171 | #define FSF_FEATURE_NPIV_MODE 0x00000001 |
209 | #define FSF_FEATURE_VM_ASSIGNED_WWPN 0x00000002 | ||
210 | 172 | ||
211 | /* option */ | 173 | /* option */ |
212 | #define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001 | 174 | #define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001 |
213 | #define FSF_OPEN_LUN_REPLICATE_SENSE 0x00000002 | ||
214 | |||
215 | /* adapter types */ | ||
216 | #define FSF_ADAPTER_TYPE_FICON 0x00000001 | ||
217 | #define FSF_ADAPTER_TYPE_FICON_EXPRESS 0x00000002 | ||
218 | |||
219 | /* port types */ | ||
220 | #define FSF_HBA_PORTTYPE_UNKNOWN 0x00000001 | ||
221 | #define FSF_HBA_PORTTYPE_NOTPRESENT 0x00000003 | ||
222 | #define FSF_HBA_PORTTYPE_NPORT 0x00000005 | ||
223 | #define FSF_HBA_PORTTYPE_PTP 0x00000021 | ||
224 | /* following are not defined and used by FSF Spec | ||
225 | but are additionally defined by FC-HBA */ | ||
226 | #define FSF_HBA_PORTTYPE_OTHER 0x00000002 | ||
227 | #define FSF_HBA_PORTTYPE_NOTPRESENT 0x00000003 | ||
228 | #define FSF_HBA_PORTTYPE_NLPORT 0x00000006 | ||
229 | #define FSF_HBA_PORTTYPE_FLPORT 0x00000007 | ||
230 | #define FSF_HBA_PORTTYPE_FPORT 0x00000008 | ||
231 | #define FSF_HBA_PORTTYPE_LPORT 0x00000020 | ||
232 | |||
233 | /* port states */ | ||
234 | #define FSF_HBA_PORTSTATE_UNKNOWN 0x00000001 | ||
235 | #define FSF_HBA_PORTSTATE_ONLINE 0x00000002 | ||
236 | #define FSF_HBA_PORTSTATE_OFFLINE 0x00000003 | ||
237 | #define FSF_HBA_PORTSTATE_LINKDOWN 0x00000006 | ||
238 | #define FSF_HBA_PORTSTATE_ERROR 0x00000007 | ||
239 | |||
240 | /* IO states of adapter */ | ||
241 | #define FSF_IOSTAT_NPORT_RJT 0x00000004 | ||
242 | #define FSF_IOSTAT_FABRIC_RJT 0x00000005 | ||
243 | #define FSF_IOSTAT_LS_RJT 0x00000009 | ||
244 | 175 | ||
245 | /* open LUN access flags*/ | 176 | /* open LUN access flags*/ |
246 | #define FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED 0x01000000 | ||
247 | #define FSF_UNIT_ACCESS_EXCLUSIVE 0x02000000 | 177 | #define FSF_UNIT_ACCESS_EXCLUSIVE 0x02000000 |
248 | #define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER 0x10000000 | 178 | #define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER 0x10000000 |
249 | 179 | ||
@@ -265,11 +195,6 @@ struct fsf_queue_designator { | |||
265 | u32 res1; | 195 | u32 res1; |
266 | } __attribute__ ((packed)); | 196 | } __attribute__ ((packed)); |
267 | 197 | ||
268 | struct fsf_port_closed_payload { | ||
269 | struct fsf_queue_designator queue_designator; | ||
270 | u32 port_handle; | ||
271 | } __attribute__ ((packed)); | ||
272 | |||
273 | struct fsf_bit_error_payload { | 198 | struct fsf_bit_error_payload { |
274 | u32 res1; | 199 | u32 res1; |
275 | u32 link_failure_error_count; | 200 | u32 link_failure_error_count; |
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 69d632d851d9..3e05080e62d4 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
@@ -28,7 +28,7 @@ static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal) | |||
28 | return 0; | 28 | return 0; |
29 | } | 29 | } |
30 | 30 | ||
31 | static volatile struct qdio_buffer_element * | 31 | static struct qdio_buffer_element * |
32 | zfcp_qdio_sbale(struct zfcp_qdio_queue *q, int sbal_idx, int sbale_idx) | 32 | zfcp_qdio_sbale(struct zfcp_qdio_queue *q, int sbal_idx, int sbale_idx) |
33 | { | 33 | { |
34 | return &q->sbal[sbal_idx]->element[sbale_idx]; | 34 | return &q->sbal[sbal_idx]->element[sbale_idx]; |
@@ -57,7 +57,7 @@ void zfcp_qdio_free(struct zfcp_adapter *adapter) | |||
57 | 57 | ||
58 | static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, u8 id) | 58 | static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, u8 id) |
59 | { | 59 | { |
60 | dev_warn(&adapter->ccw_device->dev, "QDIO problem occurred.\n"); | 60 | dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n"); |
61 | 61 | ||
62 | zfcp_erp_adapter_reopen(adapter, | 62 | zfcp_erp_adapter_reopen(adapter, |
63 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | | 63 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | |
@@ -145,7 +145,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, | |||
145 | { | 145 | { |
146 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm; | 146 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm; |
147 | struct zfcp_qdio_queue *queue = &adapter->resp_q; | 147 | struct zfcp_qdio_queue *queue = &adapter->resp_q; |
148 | volatile struct qdio_buffer_element *sbale; | 148 | struct qdio_buffer_element *sbale; |
149 | int sbal_idx, sbale_idx, sbal_no; | 149 | int sbal_idx, sbale_idx, sbal_no; |
150 | 150 | ||
151 | if (unlikely(qdio_err)) { | 151 | if (unlikely(qdio_err)) { |
@@ -174,8 +174,8 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, | |||
174 | 174 | ||
175 | if (unlikely(!(sbale->flags & SBAL_FLAGS_LAST_ENTRY))) | 175 | if (unlikely(!(sbale->flags & SBAL_FLAGS_LAST_ENTRY))) |
176 | dev_warn(&adapter->ccw_device->dev, | 176 | dev_warn(&adapter->ccw_device->dev, |
177 | "Protocol violation by adapter. " | 177 | "A QDIO protocol error occurred, " |
178 | "Continuing operations.\n"); | 178 | "operations continue\n"); |
179 | } | 179 | } |
180 | 180 | ||
181 | /* | 181 | /* |
@@ -190,8 +190,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, | |||
190 | * @fsf_req: pointer to struct fsf_req | 190 | * @fsf_req: pointer to struct fsf_req |
191 | * Returns: pointer to qdio_buffer_element (SBALE) structure | 191 | * Returns: pointer to qdio_buffer_element (SBALE) structure |
192 | */ | 192 | */ |
193 | volatile struct qdio_buffer_element * | 193 | struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *req) |
194 | zfcp_qdio_sbale_req(struct zfcp_fsf_req *req) | ||
195 | { | 194 | { |
196 | return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last, 0); | 195 | return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last, 0); |
197 | } | 196 | } |
@@ -201,8 +200,7 @@ zfcp_qdio_sbale_req(struct zfcp_fsf_req *req) | |||
201 | * @fsf_req: pointer to struct fsf_req | 200 | * @fsf_req: pointer to struct fsf_req |
202 | * Returns: pointer to qdio_buffer_element (SBALE) structure | 201 | * Returns: pointer to qdio_buffer_element (SBALE) structure |
203 | */ | 202 | */ |
204 | volatile struct qdio_buffer_element * | 203 | struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_fsf_req *req) |
205 | zfcp_qdio_sbale_curr(struct zfcp_fsf_req *req) | ||
206 | { | 204 | { |
207 | return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last, | 205 | return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last, |
208 | req->sbale_curr); | 206 | req->sbale_curr); |
@@ -216,10 +214,10 @@ static void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals) | |||
216 | % QDIO_MAX_BUFFERS_PER_Q; | 214 | % QDIO_MAX_BUFFERS_PER_Q; |
217 | } | 215 | } |
218 | 216 | ||
219 | static volatile struct qdio_buffer_element * | 217 | static struct qdio_buffer_element * |
220 | zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) | 218 | zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) |
221 | { | 219 | { |
222 | volatile struct qdio_buffer_element *sbale; | 220 | struct qdio_buffer_element *sbale; |
223 | 221 | ||
224 | /* set last entry flag in current SBALE of current SBAL */ | 222 | /* set last entry flag in current SBALE of current SBAL */ |
225 | sbale = zfcp_qdio_sbale_curr(fsf_req); | 223 | sbale = zfcp_qdio_sbale_curr(fsf_req); |
@@ -250,7 +248,7 @@ zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) | |||
250 | return sbale; | 248 | return sbale; |
251 | } | 249 | } |
252 | 250 | ||
253 | static volatile struct qdio_buffer_element * | 251 | static struct qdio_buffer_element * |
254 | zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) | 252 | zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) |
255 | { | 253 | { |
256 | if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL) | 254 | if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL) |
@@ -273,7 +271,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req, | |||
273 | unsigned int sbtype, void *start_addr, | 271 | unsigned int sbtype, void *start_addr, |
274 | unsigned int total_length) | 272 | unsigned int total_length) |
275 | { | 273 | { |
276 | volatile struct qdio_buffer_element *sbale; | 274 | struct qdio_buffer_element *sbale; |
277 | unsigned long remaining, length; | 275 | unsigned long remaining, length; |
278 | void *addr; | 276 | void *addr; |
279 | 277 | ||
@@ -282,6 +280,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req, | |||
282 | addr += length, remaining -= length) { | 280 | addr += length, remaining -= length) { |
283 | sbale = zfcp_qdio_sbale_next(fsf_req, sbtype); | 281 | sbale = zfcp_qdio_sbale_next(fsf_req, sbtype); |
284 | if (!sbale) { | 282 | if (!sbale) { |
283 | atomic_inc(&fsf_req->adapter->qdio_outb_full); | ||
285 | zfcp_qdio_undo_sbals(fsf_req); | 284 | zfcp_qdio_undo_sbals(fsf_req); |
286 | return -EINVAL; | 285 | return -EINVAL; |
287 | } | 286 | } |
@@ -307,7 +306,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req, | |||
307 | int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, | 306 | int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, |
308 | struct scatterlist *sg, int max_sbals) | 307 | struct scatterlist *sg, int max_sbals) |
309 | { | 308 | { |
310 | volatile struct qdio_buffer_element *sbale; | 309 | struct qdio_buffer_element *sbale; |
311 | int retval, bytes = 0; | 310 | int retval, bytes = 0; |
312 | 311 | ||
313 | /* figure out last allowed SBAL */ | 312 | /* figure out last allowed SBAL */ |
@@ -344,10 +343,10 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req) | |||
344 | int first = fsf_req->sbal_first; | 343 | int first = fsf_req->sbal_first; |
345 | int count = fsf_req->sbal_number; | 344 | int count = fsf_req->sbal_number; |
346 | int retval, pci, pci_batch; | 345 | int retval, pci, pci_batch; |
347 | volatile struct qdio_buffer_element *sbale; | 346 | struct qdio_buffer_element *sbale; |
348 | 347 | ||
349 | /* acknowledgements for transferred buffers */ | 348 | /* acknowledgements for transferred buffers */ |
350 | pci_batch = req_q->pci_batch + count; | 349 | pci_batch = adapter->req_q_pci_batch + count; |
351 | if (unlikely(pci_batch >= ZFCP_QDIO_PCI_INTERVAL)) { | 350 | if (unlikely(pci_batch >= ZFCP_QDIO_PCI_INTERVAL)) { |
352 | pci_batch %= ZFCP_QDIO_PCI_INTERVAL; | 351 | pci_batch %= ZFCP_QDIO_PCI_INTERVAL; |
353 | pci = first + count - (pci_batch + 1); | 352 | pci = first + count - (pci_batch + 1); |
@@ -367,7 +366,7 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req) | |||
367 | atomic_sub(count, &req_q->count); | 366 | atomic_sub(count, &req_q->count); |
368 | req_q->first += count; | 367 | req_q->first += count; |
369 | req_q->first %= QDIO_MAX_BUFFERS_PER_Q; | 368 | req_q->first %= QDIO_MAX_BUFFERS_PER_Q; |
370 | req_q->pci_batch = pci_batch; | 369 | adapter->req_q_pci_batch = pci_batch; |
371 | return 0; | 370 | return 0; |
372 | } | 371 | } |
373 | 372 | ||
@@ -418,14 +417,14 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter) | |||
418 | struct zfcp_qdio_queue *req_q; | 417 | struct zfcp_qdio_queue *req_q; |
419 | int first, count; | 418 | int first, count; |
420 | 419 | ||
421 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) | 420 | if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) |
422 | return; | 421 | return; |
423 | 422 | ||
424 | /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */ | 423 | /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */ |
425 | req_q = &adapter->req_q; | 424 | req_q = &adapter->req_q; |
426 | spin_lock_bh(&req_q->lock); | 425 | spin_lock_bh(&adapter->req_q_lock); |
427 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); | 426 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); |
428 | spin_unlock_bh(&req_q->lock); | 427 | spin_unlock_bh(&adapter->req_q_lock); |
429 | 428 | ||
430 | qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR); | 429 | qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR); |
431 | 430 | ||
@@ -438,7 +437,7 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter) | |||
438 | } | 437 | } |
439 | req_q->first = 0; | 438 | req_q->first = 0; |
440 | atomic_set(&req_q->count, 0); | 439 | atomic_set(&req_q->count, 0); |
441 | req_q->pci_batch = 0; | 440 | adapter->req_q_pci_batch = 0; |
442 | adapter->resp_q.first = 0; | 441 | adapter->resp_q.first = 0; |
443 | atomic_set(&adapter->resp_q.count, 0); | 442 | atomic_set(&adapter->resp_q.count, 0); |
444 | } | 443 | } |
@@ -450,23 +449,17 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter) | |||
450 | */ | 449 | */ |
451 | int zfcp_qdio_open(struct zfcp_adapter *adapter) | 450 | int zfcp_qdio_open(struct zfcp_adapter *adapter) |
452 | { | 451 | { |
453 | volatile struct qdio_buffer_element *sbale; | 452 | struct qdio_buffer_element *sbale; |
454 | int cc; | 453 | int cc; |
455 | 454 | ||
456 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) | 455 | if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP) |
457 | return -EIO; | 456 | return -EIO; |
458 | 457 | ||
459 | if (qdio_establish(&adapter->qdio_init_data)) { | 458 | if (qdio_establish(&adapter->qdio_init_data)) |
460 | dev_err(&adapter->ccw_device->dev, | 459 | goto failed_establish; |
461 | "Establish of QDIO queues failed.\n"); | ||
462 | return -EIO; | ||
463 | } | ||
464 | 460 | ||
465 | if (qdio_activate(adapter->ccw_device)) { | 461 | if (qdio_activate(adapter->ccw_device)) |
466 | dev_err(&adapter->ccw_device->dev, | ||
467 | "Activate of QDIO queues failed.\n"); | ||
468 | goto failed_qdio; | 462 | goto failed_qdio; |
469 | } | ||
470 | 463 | ||
471 | for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) { | 464 | for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) { |
472 | sbale = &(adapter->resp_q.sbal[cc]->element[0]); | 465 | sbale = &(adapter->resp_q.sbal[cc]->element[0]); |
@@ -476,20 +469,20 @@ int zfcp_qdio_open(struct zfcp_adapter *adapter) | |||
476 | } | 469 | } |
477 | 470 | ||
478 | if (do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_INPUT, 0, 0, | 471 | if (do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_INPUT, 0, 0, |
479 | QDIO_MAX_BUFFERS_PER_Q)) { | 472 | QDIO_MAX_BUFFERS_PER_Q)) |
480 | dev_err(&adapter->ccw_device->dev, | ||
481 | "Init of QDIO response queue failed.\n"); | ||
482 | goto failed_qdio; | 473 | goto failed_qdio; |
483 | } | ||
484 | 474 | ||
485 | /* set index of first avalable SBALS / number of available SBALS */ | 475 | /* set index of first avalable SBALS / number of available SBALS */ |
486 | adapter->req_q.first = 0; | 476 | adapter->req_q.first = 0; |
487 | atomic_set(&adapter->req_q.count, QDIO_MAX_BUFFERS_PER_Q); | 477 | atomic_set(&adapter->req_q.count, QDIO_MAX_BUFFERS_PER_Q); |
488 | adapter->req_q.pci_batch = 0; | 478 | adapter->req_q_pci_batch = 0; |
489 | 479 | ||
490 | return 0; | 480 | return 0; |
491 | 481 | ||
492 | failed_qdio: | 482 | failed_qdio: |
493 | qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR); | 483 | qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR); |
484 | failed_establish: | ||
485 | dev_err(&adapter->ccw_device->dev, | ||
486 | "Setting up the QDIO connection to the FCP adapter failed\n"); | ||
494 | return -EIO; | 487 | return -EIO; |
495 | } | 488 | } |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index aeae56b00b45..ca8f85f3dad4 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -21,20 +21,6 @@ char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu) | |||
21 | return fcp_sns_info_ptr; | 21 | return fcp_sns_info_ptr; |
22 | } | 22 | } |
23 | 23 | ||
24 | void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, fcp_dl_t fcp_dl) | ||
25 | { | ||
26 | fcp_dl_t *fcp_dl_ptr; | ||
27 | |||
28 | /* | ||
29 | * fcp_dl_addr = start address of fcp_cmnd structure + | ||
30 | * size of fixed part + size of dynamically sized add_dcp_cdb field | ||
31 | * SEE FCP-2 documentation | ||
32 | */ | ||
33 | fcp_dl_ptr = (fcp_dl_t *) ((unsigned char *) &fcp_cmd[1] + | ||
34 | (fcp_cmd->add_fcp_cdb_length << 2)); | ||
35 | *fcp_dl_ptr = fcp_dl; | ||
36 | } | ||
37 | |||
38 | static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | 24 | static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) |
39 | { | 25 | { |
40 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; | 26 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; |
@@ -119,13 +105,17 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter, | |||
119 | { | 105 | { |
120 | struct zfcp_port *port; | 106 | struct zfcp_port *port; |
121 | struct zfcp_unit *unit; | 107 | struct zfcp_unit *unit; |
108 | int scsi_lun; | ||
122 | 109 | ||
123 | list_for_each_entry(port, &adapter->port_list_head, list) { | 110 | list_for_each_entry(port, &adapter->port_list_head, list) { |
124 | if (!port->rport || (id != port->rport->scsi_target_id)) | 111 | if (!port->rport || (id != port->rport->scsi_target_id)) |
125 | continue; | 112 | continue; |
126 | list_for_each_entry(unit, &port->unit_list_head, list) | 113 | list_for_each_entry(unit, &port->unit_list_head, list) { |
127 | if (lun == unit->scsi_lun) | 114 | scsi_lun = scsilun_to_int( |
115 | (struct scsi_lun *)&unit->fcp_lun); | ||
116 | if (lun == scsi_lun) | ||
128 | return unit; | 117 | return unit; |
118 | } | ||
129 | } | 119 | } |
130 | 120 | ||
131 | return NULL; | 121 | return NULL; |
@@ -183,7 +173,6 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
183 | return retval; | 173 | return retval; |
184 | } | 174 | } |
185 | fsf_req->data = NULL; | 175 | fsf_req->data = NULL; |
186 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING; | ||
187 | 176 | ||
188 | /* don't access old fsf_req after releasing the abort_lock */ | 177 | /* don't access old fsf_req after releasing the abort_lock */ |
189 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 178 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
@@ -294,7 +283,8 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) | |||
294 | sizeof (struct zfcp_adapter *)); | 283 | sizeof (struct zfcp_adapter *)); |
295 | if (!adapter->scsi_host) { | 284 | if (!adapter->scsi_host) { |
296 | dev_err(&adapter->ccw_device->dev, | 285 | dev_err(&adapter->ccw_device->dev, |
297 | "registration with SCSI stack failed."); | 286 | "Registering the FCP device with the " |
287 | "SCSI stack failed\n"); | ||
298 | return -EIO; | 288 | return -EIO; |
299 | } | 289 | } |
300 | 290 | ||
@@ -312,7 +302,6 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) | |||
312 | scsi_host_put(adapter->scsi_host); | 302 | scsi_host_put(adapter->scsi_host); |
313 | return -EIO; | 303 | return -EIO; |
314 | } | 304 | } |
315 | atomic_set_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status); | ||
316 | 305 | ||
317 | return 0; | 306 | return 0; |
318 | } | 307 | } |
@@ -336,7 +325,6 @@ void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) | |||
336 | scsi_remove_host(shost); | 325 | scsi_remove_host(shost); |
337 | scsi_host_put(shost); | 326 | scsi_host_put(shost); |
338 | adapter->scsi_host = NULL; | 327 | adapter->scsi_host = NULL; |
339 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status); | ||
340 | 328 | ||
341 | return; | 329 | return; |
342 | } | 330 | } |
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 2e85c6c49e7d..2809d789b55c 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c | |||
@@ -26,9 +26,9 @@ static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \ | |||
26 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, status, "0x%08x\n", | 26 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, status, "0x%08x\n", |
27 | atomic_read(&adapter->status)); | 27 | atomic_read(&adapter->status)); |
28 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwnn, "0x%016llx\n", | 28 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwnn, "0x%016llx\n", |
29 | adapter->peer_wwnn); | 29 | (unsigned long long) adapter->peer_wwnn); |
30 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwpn, "0x%016llx\n", | 30 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwpn, "0x%016llx\n", |
31 | adapter->peer_wwpn); | 31 | (unsigned long long) adapter->peer_wwpn); |
32 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_d_id, "0x%06x\n", | 32 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_d_id, "0x%06x\n", |
33 | adapter->peer_d_id); | 33 | adapter->peer_d_id); |
34 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, card_version, "0x%04x\n", | 34 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, card_version, "0x%04x\n", |
@@ -135,8 +135,9 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, | |||
135 | { | 135 | { |
136 | struct zfcp_adapter *adapter = dev_get_drvdata(dev); | 136 | struct zfcp_adapter *adapter = dev_get_drvdata(dev); |
137 | struct zfcp_port *port; | 137 | struct zfcp_port *port; |
138 | wwn_t wwpn; | 138 | u64 wwpn; |
139 | int retval = 0; | 139 | int retval = 0; |
140 | LIST_HEAD(port_remove_lh); | ||
140 | 141 | ||
141 | down(&zfcp_data.config_sema); | 142 | down(&zfcp_data.config_sema); |
142 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) { | 143 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) { |
@@ -144,7 +145,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, | |||
144 | goto out; | 145 | goto out; |
145 | } | 146 | } |
146 | 147 | ||
147 | if (strict_strtoull(buf, 0, &wwpn)) { | 148 | if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn)) { |
148 | retval = -EINVAL; | 149 | retval = -EINVAL; |
149 | goto out; | 150 | goto out; |
150 | } | 151 | } |
@@ -154,7 +155,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, | |||
154 | if (port && (atomic_read(&port->refcount) == 0)) { | 155 | if (port && (atomic_read(&port->refcount) == 0)) { |
155 | zfcp_port_get(port); | 156 | zfcp_port_get(port); |
156 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); | 157 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); |
157 | list_move(&port->list, &adapter->port_remove_lh); | 158 | list_move(&port->list, &port_remove_lh); |
158 | } else | 159 | } else |
159 | port = NULL; | 160 | port = NULL; |
160 | write_unlock_irq(&zfcp_data.config_lock); | 161 | write_unlock_irq(&zfcp_data.config_lock); |
@@ -200,7 +201,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, | |||
200 | { | 201 | { |
201 | struct zfcp_port *port = dev_get_drvdata(dev); | 202 | struct zfcp_port *port = dev_get_drvdata(dev); |
202 | struct zfcp_unit *unit; | 203 | struct zfcp_unit *unit; |
203 | fcp_lun_t fcp_lun; | 204 | u64 fcp_lun; |
204 | int retval = -EINVAL; | 205 | int retval = -EINVAL; |
205 | 206 | ||
206 | down(&zfcp_data.config_sema); | 207 | down(&zfcp_data.config_sema); |
@@ -209,7 +210,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, | |||
209 | goto out; | 210 | goto out; |
210 | } | 211 | } |
211 | 212 | ||
212 | if (strict_strtoull(buf, 0, &fcp_lun)) | 213 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) |
213 | goto out; | 214 | goto out; |
214 | 215 | ||
215 | unit = zfcp_unit_enqueue(port, fcp_lun); | 216 | unit = zfcp_unit_enqueue(port, fcp_lun); |
@@ -233,8 +234,9 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, | |||
233 | { | 234 | { |
234 | struct zfcp_port *port = dev_get_drvdata(dev); | 235 | struct zfcp_port *port = dev_get_drvdata(dev); |
235 | struct zfcp_unit *unit; | 236 | struct zfcp_unit *unit; |
236 | fcp_lun_t fcp_lun; | 237 | u64 fcp_lun; |
237 | int retval = 0; | 238 | int retval = 0; |
239 | LIST_HEAD(unit_remove_lh); | ||
238 | 240 | ||
239 | down(&zfcp_data.config_sema); | 241 | down(&zfcp_data.config_sema); |
240 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) { | 242 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) { |
@@ -242,7 +244,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, | |||
242 | goto out; | 244 | goto out; |
243 | } | 245 | } |
244 | 246 | ||
245 | if (strict_strtoull(buf, 0, &fcp_lun)) { | 247 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) { |
246 | retval = -EINVAL; | 248 | retval = -EINVAL; |
247 | goto out; | 249 | goto out; |
248 | } | 250 | } |
@@ -252,7 +254,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, | |||
252 | if (unit && (atomic_read(&unit->refcount) == 0)) { | 254 | if (unit && (atomic_read(&unit->refcount) == 0)) { |
253 | zfcp_unit_get(unit); | 255 | zfcp_unit_get(unit); |
254 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); | 256 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); |
255 | list_move(&unit->list, &port->unit_remove_lh); | 257 | list_move(&unit->list, &unit_remove_lh); |
256 | } else | 258 | } else |
257 | unit = NULL; | 259 | unit = NULL; |
258 | 260 | ||
@@ -273,22 +275,7 @@ out: | |||
273 | } | 275 | } |
274 | static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); | 276 | static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); |
275 | 277 | ||
276 | static struct attribute *zfcp_port_ns_attrs[] = { | 278 | static struct attribute *zfcp_port_attrs[] = { |
277 | &dev_attr_port_failed.attr, | ||
278 | &dev_attr_port_in_recovery.attr, | ||
279 | &dev_attr_port_status.attr, | ||
280 | &dev_attr_port_access_denied.attr, | ||
281 | NULL | ||
282 | }; | ||
283 | |||
284 | /** | ||
285 | * zfcp_sysfs_ns_port_attrs - sysfs attributes for nameserver | ||
286 | */ | ||
287 | struct attribute_group zfcp_sysfs_ns_port_attrs = { | ||
288 | .attrs = zfcp_port_ns_attrs, | ||
289 | }; | ||
290 | |||
291 | static struct attribute *zfcp_port_no_ns_attrs[] = { | ||
292 | &dev_attr_unit_add.attr, | 279 | &dev_attr_unit_add.attr, |
293 | &dev_attr_unit_remove.attr, | 280 | &dev_attr_unit_remove.attr, |
294 | &dev_attr_port_failed.attr, | 281 | &dev_attr_port_failed.attr, |
@@ -302,7 +289,7 @@ static struct attribute *zfcp_port_no_ns_attrs[] = { | |||
302 | * zfcp_sysfs_port_attrs - sysfs attributes for all other ports | 289 | * zfcp_sysfs_port_attrs - sysfs attributes for all other ports |
303 | */ | 290 | */ |
304 | struct attribute_group zfcp_sysfs_port_attrs = { | 291 | struct attribute_group zfcp_sysfs_port_attrs = { |
305 | .attrs = zfcp_port_no_ns_attrs, | 292 | .attrs = zfcp_port_attrs, |
306 | }; | 293 | }; |
307 | 294 | ||
308 | static struct attribute *zfcp_unit_attrs[] = { | 295 | static struct attribute *zfcp_unit_attrs[] = { |
@@ -395,8 +382,10 @@ static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL); | |||
395 | 382 | ||
396 | ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n", | 383 | ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n", |
397 | unit->port->adapter->ccw_device->dev.bus_id); | 384 | unit->port->adapter->ccw_device->dev.bus_id); |
398 | ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", unit->port->wwpn); | 385 | ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", |
399 | ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n", unit->fcp_lun); | 386 | (unsigned long long) unit->port->wwpn); |
387 | ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n", | ||
388 | (unsigned long long) unit->fcp_lun); | ||
400 | 389 | ||
401 | struct device_attribute *zfcp_sysfs_sdev_attrs[] = { | 390 | struct device_attribute *zfcp_sysfs_sdev_attrs[] = { |
402 | &dev_attr_fcp_lun, | 391 | &dev_attr_fcp_lun, |
@@ -487,10 +476,23 @@ ZFCP_SHOST_ATTR(megabytes, "%llu %llu\n", | |||
487 | ZFCP_SHOST_ATTR(seconds_active, "%llu\n", | 476 | ZFCP_SHOST_ATTR(seconds_active, "%llu\n", |
488 | (unsigned long long) stat_info.seconds_act); | 477 | (unsigned long long) stat_info.seconds_act); |
489 | 478 | ||
479 | static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev, | ||
480 | struct device_attribute *attr, | ||
481 | char *buf) | ||
482 | { | ||
483 | struct Scsi_Host *scsi_host = class_to_shost(dev); | ||
484 | struct zfcp_adapter *adapter = | ||
485 | (struct zfcp_adapter *) scsi_host->hostdata[0]; | ||
486 | |||
487 | return sprintf(buf, "%d\n", atomic_read(&adapter->qdio_outb_full)); | ||
488 | } | ||
489 | static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL); | ||
490 | |||
490 | struct device_attribute *zfcp_sysfs_shost_attrs[] = { | 491 | struct device_attribute *zfcp_sysfs_shost_attrs[] = { |
491 | &dev_attr_utilization, | 492 | &dev_attr_utilization, |
492 | &dev_attr_requests, | 493 | &dev_attr_requests, |
493 | &dev_attr_megabytes, | 494 | &dev_attr_megabytes, |
494 | &dev_attr_seconds_active, | 495 | &dev_attr_seconds_active, |
496 | &dev_attr_queue_full, | ||
495 | NULL | 497 | NULL |
496 | }; | 498 | }; |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 4e0322b1c1ea..d3b211af4e1c 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -1325,14 +1325,6 @@ config SCSI_QLOGIC_FAS | |||
1325 | To compile this driver as a module, choose M here: the | 1325 | To compile this driver as a module, choose M here: the |
1326 | module will be called qlogicfas. | 1326 | module will be called qlogicfas. |
1327 | 1327 | ||
1328 | config SCSI_QLOGIC_FC_FIRMWARE | ||
1329 | bool "Include loadable firmware in driver" | ||
1330 | depends on SCSI_QLOGIC_FC | ||
1331 | help | ||
1332 | Say Y to include ISP2X00 Fabric Initiator/Target Firmware, with | ||
1333 | expanded LUN addressing and FcTape (FCP-2) support, in the | ||
1334 | qlogicfc driver. This is required on some platforms. | ||
1335 | |||
1336 | config SCSI_QLOGIC_1280 | 1328 | config SCSI_QLOGIC_1280 |
1337 | tristate "Qlogic QLA 1240/1x80/1x160 SCSI support" | 1329 | tristate "Qlogic QLA 1240/1x80/1x160 SCSI support" |
1338 | depends on PCI && SCSI | 1330 | depends on PCI && SCSI |
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index ef693e8412e9..8f45570a8a01 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c | |||
@@ -84,7 +84,7 @@ struct clariion_dh_data { | |||
84 | /* | 84 | /* |
85 | * I/O buffer for both MODE_SELECT and INQUIRY commands. | 85 | * I/O buffer for both MODE_SELECT and INQUIRY commands. |
86 | */ | 86 | */ |
87 | char buffer[CLARIION_BUFFER_SIZE]; | 87 | unsigned char buffer[CLARIION_BUFFER_SIZE]; |
88 | /* | 88 | /* |
89 | * SCSI sense buffer for commands -- assumes serial issuance | 89 | * SCSI sense buffer for commands -- assumes serial issuance |
90 | * and completion sequence of all commands for same multipath. | 90 | * and completion sequence of all commands for same multipath. |
@@ -176,7 +176,7 @@ static int parse_sp_info_reply(struct scsi_device *sdev, | |||
176 | err = SCSI_DH_DEV_TEMP_BUSY; | 176 | err = SCSI_DH_DEV_TEMP_BUSY; |
177 | goto out; | 177 | goto out; |
178 | } | 178 | } |
179 | if (csdev->buffer[4] < 0 || csdev->buffer[4] > 2) { | 179 | if (csdev->buffer[4] > 2) { |
180 | /* Invalid buffer format */ | 180 | /* Invalid buffer format */ |
181 | sdev_printk(KERN_NOTICE, sdev, | 181 | sdev_printk(KERN_NOTICE, sdev, |
182 | "%s: invalid VPD page 0xC0 format\n", | 182 | "%s: invalid VPD page 0xC0 format\n", |
@@ -278,7 +278,6 @@ static struct request *get_req(struct scsi_device *sdev, int cmd, | |||
278 | return NULL; | 278 | return NULL; |
279 | } | 279 | } |
280 | 280 | ||
281 | memset(rq->cmd, 0, BLK_MAX_CDB); | ||
282 | rq->cmd_len = COMMAND_SIZE(cmd); | 281 | rq->cmd_len = COMMAND_SIZE(cmd); |
283 | rq->cmd[0] = cmd; | 282 | rq->cmd[0] = cmd; |
284 | 283 | ||
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index a6a4ef3ad51c..5e93c88ad66b 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c | |||
@@ -114,7 +114,6 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h) | |||
114 | req->cmd_type = REQ_TYPE_BLOCK_PC; | 114 | req->cmd_type = REQ_TYPE_BLOCK_PC; |
115 | req->cmd_flags |= REQ_FAILFAST; | 115 | req->cmd_flags |= REQ_FAILFAST; |
116 | req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY); | 116 | req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY); |
117 | memset(req->cmd, 0, MAX_COMMAND_SIZE); | ||
118 | req->cmd[0] = TEST_UNIT_READY; | 117 | req->cmd[0] = TEST_UNIT_READY; |
119 | req->timeout = HP_SW_TIMEOUT; | 118 | req->timeout = HP_SW_TIMEOUT; |
120 | req->sense = h->sense; | 119 | req->sense = h->sense; |
@@ -207,7 +206,6 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h) | |||
207 | req->cmd_type = REQ_TYPE_BLOCK_PC; | 206 | req->cmd_type = REQ_TYPE_BLOCK_PC; |
208 | req->cmd_flags |= REQ_FAILFAST; | 207 | req->cmd_flags |= REQ_FAILFAST; |
209 | req->cmd_len = COMMAND_SIZE(START_STOP); | 208 | req->cmd_len = COMMAND_SIZE(START_STOP); |
210 | memset(req->cmd, 0, MAX_COMMAND_SIZE); | ||
211 | req->cmd[0] = START_STOP; | 209 | req->cmd[0] = START_STOP; |
212 | req->cmd[4] = 1; /* Start spin cycle */ | 210 | req->cmd[4] = 1; /* Start spin cycle */ |
213 | req->timeout = HP_SW_TIMEOUT; | 211 | req->timeout = HP_SW_TIMEOUT; |
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 6e2f130d56de..50bf95f3b5c4 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c | |||
@@ -225,8 +225,6 @@ static struct request *get_rdac_req(struct scsi_device *sdev, | |||
225 | return NULL; | 225 | return NULL; |
226 | } | 226 | } |
227 | 227 | ||
228 | memset(rq->cmd, 0, BLK_MAX_CDB); | ||
229 | |||
230 | rq->cmd_type = REQ_TYPE_BLOCK_PC; | 228 | rq->cmd_type = REQ_TYPE_BLOCK_PC; |
231 | rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE; | 229 | rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE; |
232 | rq->retries = RDAC_RETRIES; | 230 | rq->retries = RDAC_RETRIES; |
@@ -590,6 +588,8 @@ static const struct scsi_dh_devlist rdac_dev_list[] = { | |||
590 | {"STK", "OPENstorage D280"}, | 588 | {"STK", "OPENstorage D280"}, |
591 | {"SUN", "CSM200_R"}, | 589 | {"SUN", "CSM200_R"}, |
592 | {"SUN", "LCSM100_F"}, | 590 | {"SUN", "LCSM100_F"}, |
591 | {"DELL", "MD3000"}, | ||
592 | {"DELL", "MD3000i"}, | ||
593 | {NULL, NULL}, | 593 | {NULL, NULL}, |
594 | }; | 594 | }; |
595 | 595 | ||
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index fed0b02ebc1d..3fdbb13e80a8 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
@@ -464,7 +464,7 @@ static int __scsi_host_match(struct device *dev, void *data) | |||
464 | struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) | 464 | struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) |
465 | { | 465 | { |
466 | struct device *cdev; | 466 | struct device *cdev; |
467 | struct Scsi_Host *shost = ERR_PTR(-ENXIO); | 467 | struct Scsi_Host *shost = NULL; |
468 | 468 | ||
469 | cdev = class_find_device(&shost_class, NULL, &hostnum, | 469 | cdev = class_find_device(&shost_class, NULL, &hostnum, |
470 | __scsi_host_match); | 470 | __scsi_host_match); |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 1eca82420aab..da7b67d30d9a 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -1456,7 +1456,7 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, | |||
1456 | if (lun == task->sc->device->lun || lun == -1) { | 1456 | if (lun == task->sc->device->lun || lun == -1) { |
1457 | debug_scsi("failing in progress sc %p itt 0x%x\n", | 1457 | debug_scsi("failing in progress sc %p itt 0x%x\n", |
1458 | task->sc, task->itt); | 1458 | task->sc, task->itt); |
1459 | fail_command(conn, task, DID_BUS_BUSY << 16); | 1459 | fail_command(conn, task, error << 16); |
1460 | } | 1460 | } |
1461 | } | 1461 | } |
1462 | } | 1462 | } |
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 45e7dcb4b34d..0ddfe7106b3b 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -292,10 +292,11 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, | |||
292 | valid = 0; | 292 | valid = 0; |
293 | if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) | 293 | if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) |
294 | valid = 1; | 294 | valid = 1; |
295 | else if (start == (FA_BOOT_CODE_ADDR*4) || | 295 | else if (start == (ha->flt_region_boot * 4) || |
296 | start == (FA_RISC_CODE_ADDR*4)) | 296 | start == (ha->flt_region_fw * 4)) |
297 | valid = 1; | 297 | valid = 1; |
298 | else if (IS_QLA25XX(ha) && start == (FA_VPD_NVRAM_ADDR*4)) | 298 | else if (IS_QLA25XX(ha) && |
299 | start == (ha->flt_region_vpd_nvram * 4)) | ||
299 | valid = 1; | 300 | valid = 1; |
300 | if (!valid) { | 301 | if (!valid) { |
301 | qla_printk(KERN_WARNING, ha, | 302 | qla_printk(KERN_WARNING, ha, |
@@ -1065,6 +1066,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) | |||
1065 | pfc_host_stat->dumped_frames = stats->dumped_frames; | 1066 | pfc_host_stat->dumped_frames = stats->dumped_frames; |
1066 | pfc_host_stat->nos_count = stats->nos_rcvd; | 1067 | pfc_host_stat->nos_count = stats->nos_rcvd; |
1067 | } | 1068 | } |
1069 | pfc_host_stat->fcp_input_megabytes = ha->qla_stats.input_bytes >> 20; | ||
1070 | pfc_host_stat->fcp_output_megabytes = ha->qla_stats.output_bytes >> 20; | ||
1068 | 1071 | ||
1069 | done_free: | 1072 | done_free: |
1070 | dma_pool_free(ha->s_dma_pool, stats, stats_dma); | 1073 | dma_pool_free(ha->s_dma_pool, stats, stats_dma); |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 94a720eabfd8..83c819216771 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/firmware.h> | 25 | #include <linux/firmware.h> |
26 | #include <linux/aer.h> | 26 | #include <linux/aer.h> |
27 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
28 | #include <linux/semaphore.h> | ||
29 | 28 | ||
30 | #include <scsi/scsi.h> | 29 | #include <scsi/scsi.h> |
31 | #include <scsi/scsi_host.h> | 30 | #include <scsi/scsi_host.h> |
@@ -2157,6 +2156,8 @@ struct qla_chip_state_84xx { | |||
2157 | 2156 | ||
2158 | struct qla_statistics { | 2157 | struct qla_statistics { |
2159 | uint32_t total_isp_aborts; | 2158 | uint32_t total_isp_aborts; |
2159 | uint64_t input_bytes; | ||
2160 | uint64_t output_bytes; | ||
2160 | }; | 2161 | }; |
2161 | 2162 | ||
2162 | /* | 2163 | /* |
@@ -2238,6 +2239,7 @@ typedef struct scsi_qla_host { | |||
2238 | #define FCPORT_UPDATE_NEEDED 27 | 2239 | #define FCPORT_UPDATE_NEEDED 27 |
2239 | #define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */ | 2240 | #define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */ |
2240 | #define UNLOADING 29 | 2241 | #define UNLOADING 29 |
2242 | #define NPIV_CONFIG_NEEDED 30 | ||
2241 | 2243 | ||
2242 | uint32_t device_flags; | 2244 | uint32_t device_flags; |
2243 | #define DFLG_LOCAL_DEVICES BIT_0 | 2245 | #define DFLG_LOCAL_DEVICES BIT_0 |
@@ -2507,7 +2509,6 @@ typedef struct scsi_qla_host { | |||
2507 | uint64_t fce_wr, fce_rd; | 2509 | uint64_t fce_wr, fce_rd; |
2508 | struct mutex fce_mutex; | 2510 | struct mutex fce_mutex; |
2509 | 2511 | ||
2510 | uint32_t hw_event_start; | ||
2511 | uint32_t hw_event_ptr; | 2512 | uint32_t hw_event_ptr; |
2512 | uint32_t hw_event_pause_errors; | 2513 | uint32_t hw_event_pause_errors; |
2513 | 2514 | ||
@@ -2553,6 +2554,14 @@ typedef struct scsi_qla_host { | |||
2553 | uint32_t fdt_unprotect_sec_cmd; | 2554 | uint32_t fdt_unprotect_sec_cmd; |
2554 | uint32_t fdt_protect_sec_cmd; | 2555 | uint32_t fdt_protect_sec_cmd; |
2555 | 2556 | ||
2557 | uint32_t flt_region_flt; | ||
2558 | uint32_t flt_region_fdt; | ||
2559 | uint32_t flt_region_boot; | ||
2560 | uint32_t flt_region_fw; | ||
2561 | uint32_t flt_region_vpd_nvram; | ||
2562 | uint32_t flt_region_hw_event; | ||
2563 | uint32_t flt_region_npiv_conf; | ||
2564 | |||
2556 | /* Needed for BEACON */ | 2565 | /* Needed for BEACON */ |
2557 | uint16_t beacon_blink_led; | 2566 | uint16_t beacon_blink_led; |
2558 | uint8_t beacon_color_state; | 2567 | uint8_t beacon_color_state; |
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index cf194517400d..d1d14202575a 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h | |||
@@ -789,14 +789,23 @@ struct device_reg_24xx { | |||
789 | #define FA_RISC_CODE_ADDR 0x20000 | 789 | #define FA_RISC_CODE_ADDR 0x20000 |
790 | #define FA_RISC_CODE_SEGMENTS 2 | 790 | #define FA_RISC_CODE_SEGMENTS 2 |
791 | 791 | ||
792 | #define FA_FLASH_DESCR_ADDR_24 0x11000 | ||
793 | #define FA_FLASH_LAYOUT_ADDR_24 0x11400 | ||
794 | #define FA_NPIV_CONF0_ADDR_24 0x16000 | ||
795 | #define FA_NPIV_CONF1_ADDR_24 0x17000 | ||
796 | |||
792 | #define FA_FW_AREA_ADDR 0x40000 | 797 | #define FA_FW_AREA_ADDR 0x40000 |
793 | #define FA_VPD_NVRAM_ADDR 0x48000 | 798 | #define FA_VPD_NVRAM_ADDR 0x48000 |
794 | #define FA_FEATURE_ADDR 0x4C000 | 799 | #define FA_FEATURE_ADDR 0x4C000 |
795 | #define FA_FLASH_DESCR_ADDR 0x50000 | 800 | #define FA_FLASH_DESCR_ADDR 0x50000 |
801 | #define FA_FLASH_LAYOUT_ADDR 0x50400 | ||
796 | #define FA_HW_EVENT0_ADDR 0x54000 | 802 | #define FA_HW_EVENT0_ADDR 0x54000 |
797 | #define FA_HW_EVENT1_ADDR 0x54200 | 803 | #define FA_HW_EVENT1_ADDR 0x54400 |
798 | #define FA_HW_EVENT_SIZE 0x200 | 804 | #define FA_HW_EVENT_SIZE 0x200 |
799 | #define FA_HW_EVENT_ENTRY_SIZE 4 | 805 | #define FA_HW_EVENT_ENTRY_SIZE 4 |
806 | #define FA_NPIV_CONF0_ADDR 0x5C000 | ||
807 | #define FA_NPIV_CONF1_ADDR 0x5D000 | ||
808 | |||
800 | /* | 809 | /* |
801 | * Flash Error Log Event Codes. | 810 | * Flash Error Log Event Codes. |
802 | */ | 811 | */ |
@@ -806,10 +815,6 @@ struct device_reg_24xx { | |||
806 | #define HW_EVENT_NVRAM_CHKSUM_ERR 0xF023 | 815 | #define HW_EVENT_NVRAM_CHKSUM_ERR 0xF023 |
807 | #define HW_EVENT_FLASH_FW_ERR 0xF024 | 816 | #define HW_EVENT_FLASH_FW_ERR 0xF024 |
808 | 817 | ||
809 | #define FA_BOOT_LOG_ADDR 0x58000 | ||
810 | #define FA_FW_DUMP0_ADDR 0x60000 | ||
811 | #define FA_FW_DUMP1_ADDR 0x70000 | ||
812 | |||
813 | uint32_t flash_data; /* Flash/NVRAM BIOS data. */ | 818 | uint32_t flash_data; /* Flash/NVRAM BIOS data. */ |
814 | 819 | ||
815 | uint32_t ctrl_status; /* Control/Status. */ | 820 | uint32_t ctrl_status; /* Control/Status. */ |
@@ -1203,6 +1208,62 @@ struct qla_fdt_layout { | |||
1203 | uint8_t unused2[65]; | 1208 | uint8_t unused2[65]; |
1204 | }; | 1209 | }; |
1205 | 1210 | ||
1211 | /* Flash Layout Table ********************************************************/ | ||
1212 | |||
1213 | struct qla_flt_location { | ||
1214 | uint8_t sig[4]; | ||
1215 | uint32_t start_lo; | ||
1216 | uint32_t start_hi; | ||
1217 | uint16_t unused; | ||
1218 | uint16_t checksum; | ||
1219 | }; | ||
1220 | |||
1221 | struct qla_flt_header { | ||
1222 | uint16_t version; | ||
1223 | uint16_t length; | ||
1224 | uint16_t checksum; | ||
1225 | uint16_t unused; | ||
1226 | }; | ||
1227 | |||
1228 | #define FLT_REG_FW 0x01 | ||
1229 | #define FLT_REG_BOOT_CODE 0x07 | ||
1230 | #define FLT_REG_VPD_0 0x14 | ||
1231 | #define FLT_REG_NVRAM_0 0x15 | ||
1232 | #define FLT_REG_VPD_1 0x16 | ||
1233 | #define FLT_REG_NVRAM_1 0x17 | ||
1234 | #define FLT_REG_FDT 0x1a | ||
1235 | #define FLT_REG_FLT 0x1c | ||
1236 | #define FLT_REG_HW_EVENT_0 0x1d | ||
1237 | #define FLT_REG_HW_EVENT_1 0x1f | ||
1238 | #define FLT_REG_NPIV_CONF_0 0x29 | ||
1239 | #define FLT_REG_NPIV_CONF_1 0x2a | ||
1240 | |||
1241 | struct qla_flt_region { | ||
1242 | uint32_t code; | ||
1243 | uint32_t size; | ||
1244 | uint32_t start; | ||
1245 | uint32_t end; | ||
1246 | }; | ||
1247 | |||
1248 | /* Flash NPIV Configuration Table ********************************************/ | ||
1249 | |||
1250 | struct qla_npiv_header { | ||
1251 | uint8_t sig[2]; | ||
1252 | uint16_t version; | ||
1253 | uint16_t entries; | ||
1254 | uint16_t unused[4]; | ||
1255 | uint16_t checksum; | ||
1256 | }; | ||
1257 | |||
1258 | struct qla_npiv_entry { | ||
1259 | uint16_t flags; | ||
1260 | uint16_t vf_id; | ||
1261 | uint16_t qos; | ||
1262 | uint16_t unused1; | ||
1263 | uint8_t port_name[WWN_SIZE]; | ||
1264 | uint8_t node_name[WWN_SIZE]; | ||
1265 | }; | ||
1266 | |||
1206 | /* 84XX Support **************************************************************/ | 1267 | /* 84XX Support **************************************************************/ |
1207 | 1268 | ||
1208 | #define MBA_ISP84XX_ALERT 0x800f /* Alert Notification. */ | 1269 | #define MBA_ISP84XX_ALERT 0x800f /* Alert Notification. */ |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 0b156735e9a6..753dbe6cce6e 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -313,9 +313,11 @@ extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); | |||
313 | extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t, | 313 | extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t, |
314 | uint16_t, uint16_t); | 314 | uint16_t, uint16_t); |
315 | 315 | ||
316 | extern void qla2xxx_get_flash_info(scsi_qla_host_t *); | 316 | extern int qla2xxx_get_flash_info(scsi_qla_host_t *); |
317 | extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); | 317 | extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); |
318 | 318 | ||
319 | extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *); | ||
320 | |||
319 | /* | 321 | /* |
320 | * Global Function Prototypes in qla_dbg.c source file. | 322 | * Global Function Prototypes in qla_dbg.c source file. |
321 | */ | 323 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ee89ddd64aae..a470f2d3270d 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -83,6 +83,13 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
83 | 83 | ||
84 | ha->isp_ops->reset_chip(ha); | 84 | ha->isp_ops->reset_chip(ha); |
85 | 85 | ||
86 | rval = qla2xxx_get_flash_info(ha); | ||
87 | if (rval) { | ||
88 | DEBUG2(printk("scsi(%ld): Unable to validate FLASH data.\n", | ||
89 | ha->host_no)); | ||
90 | return (rval); | ||
91 | } | ||
92 | |||
86 | ha->isp_ops->get_flash_version(ha, ha->request_ring); | 93 | ha->isp_ops->get_flash_version(ha, ha->request_ring); |
87 | 94 | ||
88 | qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); | 95 | qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); |
@@ -109,7 +116,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
109 | rval = qla2x00_setup_chip(ha); | 116 | rval = qla2x00_setup_chip(ha); |
110 | if (rval) | 117 | if (rval) |
111 | return (rval); | 118 | return (rval); |
112 | qla2xxx_get_flash_info(ha); | ||
113 | } | 119 | } |
114 | if (IS_QLA84XX(ha)) { | 120 | if (IS_QLA84XX(ha)) { |
115 | ha->cs84xx = qla84xx_get_chip(ha); | 121 | ha->cs84xx = qla84xx_get_chip(ha); |
@@ -2016,7 +2022,7 @@ qla2x00_configure_loop(scsi_qla_host_t *ha) | |||
2016 | DEBUG3(printk("%s: exiting normally\n", __func__)); | 2022 | DEBUG3(printk("%s: exiting normally\n", __func__)); |
2017 | } | 2023 | } |
2018 | 2024 | ||
2019 | /* Restore state if a resync event occured during processing */ | 2025 | /* Restore state if a resync event occurred during processing */ |
2020 | if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { | 2026 | if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { |
2021 | if (test_bit(LOCAL_LOOP_UPDATE, &save_flags)) | 2027 | if (test_bit(LOCAL_LOOP_UPDATE, &save_flags)) |
2022 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); | 2028 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); |
@@ -2561,7 +2567,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) | |||
2561 | rval = QLA_SUCCESS; | 2567 | rval = QLA_SUCCESS; |
2562 | 2568 | ||
2563 | /* Try GID_PT to get device list, else GAN. */ | 2569 | /* Try GID_PT to get device list, else GAN. */ |
2564 | swl = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_ATOMIC); | 2570 | swl = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_KERNEL); |
2565 | if (!swl) { | 2571 | if (!swl) { |
2566 | /*EMPTY*/ | 2572 | /*EMPTY*/ |
2567 | DEBUG2(printk("scsi(%ld): GID_PT allocations failed, fallback " | 2573 | DEBUG2(printk("scsi(%ld): GID_PT allocations failed, fallback " |
@@ -3751,7 +3757,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3751 | rval = QLA_SUCCESS; | 3757 | rval = QLA_SUCCESS; |
3752 | 3758 | ||
3753 | segments = FA_RISC_CODE_SEGMENTS; | 3759 | segments = FA_RISC_CODE_SEGMENTS; |
3754 | faddr = FA_RISC_CODE_ADDR; | 3760 | faddr = ha->flt_region_fw; |
3755 | dcode = (uint32_t *)ha->request_ring; | 3761 | dcode = (uint32_t *)ha->request_ring; |
3756 | *srisc_addr = 0; | 3762 | *srisc_addr = 0; |
3757 | 3763 | ||
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 92fafbdbbaab..e90afad120ee 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h | |||
@@ -52,7 +52,7 @@ to_qla_parent(scsi_qla_host_t *ha) | |||
52 | * @ha: HA context | 52 | * @ha: HA context |
53 | * @ha_locked: is function called with the hardware lock | 53 | * @ha_locked: is function called with the hardware lock |
54 | * | 54 | * |
55 | * Returns non-zero if a failure occured, else zero. | 55 | * Returns non-zero if a failure occurred, else zero. |
56 | */ | 56 | */ |
57 | static inline int | 57 | static inline int |
58 | qla2x00_issue_marker(scsi_qla_host_t *ha, int ha_locked) | 58 | qla2x00_issue_marker(scsi_qla_host_t *ha, int ha_locked) |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index d57669aa4615..85bc0a48598b 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -21,17 +21,22 @@ static void qla2x00_isp_cmd(scsi_qla_host_t *ha); | |||
21 | * Returns the proper CF_* direction based on CDB. | 21 | * Returns the proper CF_* direction based on CDB. |
22 | */ | 22 | */ |
23 | static inline uint16_t | 23 | static inline uint16_t |
24 | qla2x00_get_cmd_direction(struct scsi_cmnd *cmd) | 24 | qla2x00_get_cmd_direction(srb_t *sp) |
25 | { | 25 | { |
26 | uint16_t cflags; | 26 | uint16_t cflags; |
27 | 27 | ||
28 | cflags = 0; | 28 | cflags = 0; |
29 | 29 | ||
30 | /* Set transfer direction */ | 30 | /* Set transfer direction */ |
31 | if (cmd->sc_data_direction == DMA_TO_DEVICE) | 31 | if (sp->cmd->sc_data_direction == DMA_TO_DEVICE) { |
32 | cflags = CF_WRITE; | 32 | cflags = CF_WRITE; |
33 | else if (cmd->sc_data_direction == DMA_FROM_DEVICE) | 33 | sp->fcport->ha->qla_stats.output_bytes += |
34 | scsi_bufflen(sp->cmd); | ||
35 | } else if (sp->cmd->sc_data_direction == DMA_FROM_DEVICE) { | ||
34 | cflags = CF_READ; | 36 | cflags = CF_READ; |
37 | sp->fcport->ha->qla_stats.input_bytes += | ||
38 | scsi_bufflen(sp->cmd); | ||
39 | } | ||
35 | return (cflags); | 40 | return (cflags); |
36 | } | 41 | } |
37 | 42 | ||
@@ -169,7 +174,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, | |||
169 | 174 | ||
170 | ha = sp->ha; | 175 | ha = sp->ha; |
171 | 176 | ||
172 | cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(cmd)); | 177 | cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp)); |
173 | 178 | ||
174 | /* Three DSDs are available in the Command Type 2 IOCB */ | 179 | /* Three DSDs are available in the Command Type 2 IOCB */ |
175 | avail_dsds = 3; | 180 | avail_dsds = 3; |
@@ -228,7 +233,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, | |||
228 | 233 | ||
229 | ha = sp->ha; | 234 | ha = sp->ha; |
230 | 235 | ||
231 | cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(cmd)); | 236 | cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp)); |
232 | 237 | ||
233 | /* Two DSDs are available in the Command Type 3 IOCB */ | 238 | /* Two DSDs are available in the Command Type 3 IOCB */ |
234 | avail_dsds = 2; | 239 | avail_dsds = 2; |
@@ -262,7 +267,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, | |||
262 | * qla2x00_start_scsi() - Send a SCSI command to the ISP | 267 | * qla2x00_start_scsi() - Send a SCSI command to the ISP |
263 | * @sp: command to send to the ISP | 268 | * @sp: command to send to the ISP |
264 | * | 269 | * |
265 | * Returns non-zero if a failure occured, else zero. | 270 | * Returns non-zero if a failure occurred, else zero. |
266 | */ | 271 | */ |
267 | int | 272 | int |
268 | qla2x00_start_scsi(srb_t *sp) | 273 | qla2x00_start_scsi(srb_t *sp) |
@@ -407,7 +412,7 @@ queuing_error: | |||
407 | * | 412 | * |
408 | * Can be called from both normal and interrupt context. | 413 | * Can be called from both normal and interrupt context. |
409 | * | 414 | * |
410 | * Returns non-zero if a failure occured, else zero. | 415 | * Returns non-zero if a failure occurred, else zero. |
411 | */ | 416 | */ |
412 | int | 417 | int |
413 | __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, | 418 | __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, |
@@ -625,12 +630,17 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, | |||
625 | ha = sp->ha; | 630 | ha = sp->ha; |
626 | 631 | ||
627 | /* Set transfer direction */ | 632 | /* Set transfer direction */ |
628 | if (cmd->sc_data_direction == DMA_TO_DEVICE) | 633 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { |
629 | cmd_pkt->task_mgmt_flags = | 634 | cmd_pkt->task_mgmt_flags = |
630 | __constant_cpu_to_le16(TMF_WRITE_DATA); | 635 | __constant_cpu_to_le16(TMF_WRITE_DATA); |
631 | else if (cmd->sc_data_direction == DMA_FROM_DEVICE) | 636 | sp->fcport->ha->qla_stats.output_bytes += |
637 | scsi_bufflen(sp->cmd); | ||
638 | } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { | ||
632 | cmd_pkt->task_mgmt_flags = | 639 | cmd_pkt->task_mgmt_flags = |
633 | __constant_cpu_to_le16(TMF_READ_DATA); | 640 | __constant_cpu_to_le16(TMF_READ_DATA); |
641 | sp->fcport->ha->qla_stats.input_bytes += | ||
642 | scsi_bufflen(sp->cmd); | ||
643 | } | ||
634 | 644 | ||
635 | /* One DSD is available in the Command Type 3 IOCB */ | 645 | /* One DSD is available in the Command Type 3 IOCB */ |
636 | avail_dsds = 1; | 646 | avail_dsds = 1; |
@@ -666,7 +676,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, | |||
666 | * qla24xx_start_scsi() - Send a SCSI command to the ISP | 676 | * qla24xx_start_scsi() - Send a SCSI command to the ISP |
667 | * @sp: command to send to the ISP | 677 | * @sp: command to send to the ISP |
668 | * | 678 | * |
669 | * Returns non-zero if a failure occured, else zero. | 679 | * Returns non-zero if a failure occurred, else zero. |
670 | */ | 680 | */ |
671 | int | 681 | int |
672 | qla24xx_start_scsi(srb_t *sp) | 682 | qla24xx_start_scsi(srb_t *sp) |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index bf41887cdd65..fc4bfa7f839c 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -391,9 +391,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
391 | break; | 391 | break; |
392 | 392 | ||
393 | case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ | 393 | case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ |
394 | DEBUG2(printk("scsi(%ld): LIP occured (%x).\n", ha->host_no, | 394 | DEBUG2(printk("scsi(%ld): LIP occurred (%x).\n", ha->host_no, |
395 | mb[1])); | 395 | mb[1])); |
396 | qla_printk(KERN_INFO, ha, "LIP occured (%x).\n", mb[1]); | 396 | qla_printk(KERN_INFO, ha, "LIP occurred (%x).\n", mb[1]); |
397 | 397 | ||
398 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { | 398 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { |
399 | atomic_set(&ha->loop_state, LOOP_DOWN); | 399 | atomic_set(&ha->loop_state, LOOP_DOWN); |
@@ -460,7 +460,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
460 | DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n", | 460 | DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n", |
461 | ha->host_no, mb[1])); | 461 | ha->host_no, mb[1])); |
462 | qla_printk(KERN_INFO, ha, | 462 | qla_printk(KERN_INFO, ha, |
463 | "LIP reset occured (%x).\n", mb[1]); | 463 | "LIP reset occurred (%x).\n", mb[1]); |
464 | 464 | ||
465 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { | 465 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { |
466 | atomic_set(&ha->loop_state, LOOP_DOWN); | 466 | atomic_set(&ha->loop_state, LOOP_DOWN); |
@@ -543,7 +543,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
543 | 543 | ||
544 | case MBA_PORT_UPDATE: /* Port database update */ | 544 | case MBA_PORT_UPDATE: /* Port database update */ |
545 | /* | 545 | /* |
546 | * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET | 546 | * If PORT UPDATE is global (received LIP_OCCURRED/LIP_RESET |
547 | * event etc. earlier indicating loop is down) then process | 547 | * event etc. earlier indicating loop is down) then process |
548 | * it. Otherwise ignore it and Wait for RSCN to come in. | 548 | * it. Otherwise ignore it and Wait for RSCN to come in. |
549 | */ | 549 | */ |
@@ -589,7 +589,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
589 | "scsi(%ld): RSCN database changed -- %04x %04x %04x.\n", | 589 | "scsi(%ld): RSCN database changed -- %04x %04x %04x.\n", |
590 | ha->host_no, mb[1], mb[2], mb[3])); | 590 | ha->host_no, mb[1], mb[2], mb[3])); |
591 | 591 | ||
592 | rscn_entry = (mb[1] << 16) | mb[2]; | 592 | rscn_entry = ((mb[1] & 0xff) << 16) | mb[2]; |
593 | host_pid = (ha->d_id.b.domain << 16) | (ha->d_id.b.area << 8) | | 593 | host_pid = (ha->d_id.b.domain << 16) | (ha->d_id.b.area << 8) | |
594 | ha->d_id.b.al_pa; | 594 | ha->d_id.b.al_pa; |
595 | if (rscn_entry == host_pid) { | 595 | if (rscn_entry == host_pid) { |
@@ -600,6 +600,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
600 | break; | 600 | break; |
601 | } | 601 | } |
602 | 602 | ||
603 | /* Ignore reserved bits from RSCN-payload. */ | ||
604 | rscn_entry = ((mb[1] & 0x3ff) << 16) | mb[2]; | ||
603 | rscn_queue_index = ha->rscn_in_ptr + 1; | 605 | rscn_queue_index = ha->rscn_in_ptr + 1; |
604 | if (rscn_queue_index == MAX_RSCN_COUNT) | 606 | if (rscn_queue_index == MAX_RSCN_COUNT) |
605 | rscn_queue_index = 0; | 607 | rscn_queue_index = 0; |
@@ -1060,8 +1062,9 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
1060 | resid = resid_len; | 1062 | resid = resid_len; |
1061 | /* Use F/W calculated residual length. */ | 1063 | /* Use F/W calculated residual length. */ |
1062 | if (IS_FWI2_CAPABLE(ha)) { | 1064 | if (IS_FWI2_CAPABLE(ha)) { |
1063 | if (scsi_status & SS_RESIDUAL_UNDER && | 1065 | if (!(scsi_status & SS_RESIDUAL_UNDER)) { |
1064 | resid != fw_resid_len) { | 1066 | lscsi_status = 0; |
1067 | } else if (resid != fw_resid_len) { | ||
1065 | scsi_status &= ~SS_RESIDUAL_UNDER; | 1068 | scsi_status &= ~SS_RESIDUAL_UNDER; |
1066 | lscsi_status = 0; | 1069 | lscsi_status = 0; |
1067 | } | 1070 | } |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 813bc7784c0a..36bc6851e23d 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -233,7 +233,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) | |||
233 | DEBUG2_3_11(printk("%s(%ld): timeout schedule " | 233 | DEBUG2_3_11(printk("%s(%ld): timeout schedule " |
234 | "isp_abort_needed.\n", __func__, ha->host_no)); | 234 | "isp_abort_needed.\n", __func__, ha->host_no)); |
235 | qla_printk(KERN_WARNING, ha, | 235 | qla_printk(KERN_WARNING, ha, |
236 | "Mailbox command timeout occured. Scheduling ISP " | 236 | "Mailbox command timeout occurred. Scheduling ISP " |
237 | "abort.\n"); | 237 | "abort.\n"); |
238 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 238 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); |
239 | qla2xxx_wake_dpc(ha); | 239 | qla2xxx_wake_dpc(ha); |
@@ -244,7 +244,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) | |||
244 | DEBUG2_3_11(printk("%s(%ld): timeout calling " | 244 | DEBUG2_3_11(printk("%s(%ld): timeout calling " |
245 | "abort_isp\n", __func__, ha->host_no)); | 245 | "abort_isp\n", __func__, ha->host_no)); |
246 | qla_printk(KERN_WARNING, ha, | 246 | qla_printk(KERN_WARNING, ha, |
247 | "Mailbox command timeout occured. Issuing ISP " | 247 | "Mailbox command timeout occurred. Issuing ISP " |
248 | "abort.\n"); | 248 | "abort.\n"); |
249 | 249 | ||
250 | set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | 250 | set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); |
@@ -1995,7 +1995,7 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map) | |||
1995 | char *pmap; | 1995 | char *pmap; |
1996 | dma_addr_t pmap_dma; | 1996 | dma_addr_t pmap_dma; |
1997 | 1997 | ||
1998 | pmap = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &pmap_dma); | 1998 | pmap = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma); |
1999 | if (pmap == NULL) { | 1999 | if (pmap == NULL) { |
2000 | DEBUG2_3_11(printk("%s(%ld): **** Mem Alloc Failed ****", | 2000 | DEBUG2_3_11(printk("%s(%ld): **** Mem Alloc Failed ****", |
2001 | __func__, ha->host_no)); | 2001 | __func__, ha->host_no)); |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 6d0f0e5f2827..3433441b956a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -1517,6 +1517,7 @@ qla2xxx_scan_start(struct Scsi_Host *shost) | |||
1517 | set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); | 1517 | set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); |
1518 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); | 1518 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); |
1519 | set_bit(RSCN_UPDATE, &ha->dpc_flags); | 1519 | set_bit(RSCN_UPDATE, &ha->dpc_flags); |
1520 | set_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags); | ||
1520 | } | 1521 | } |
1521 | 1522 | ||
1522 | static int | 1523 | static int |
@@ -1663,8 +1664,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1663 | ha->gid_list_info_size = 8; | 1664 | ha->gid_list_info_size = 8; |
1664 | ha->optrom_size = OPTROM_SIZE_25XX; | 1665 | ha->optrom_size = OPTROM_SIZE_25XX; |
1665 | ha->isp_ops = &qla25xx_isp_ops; | 1666 | ha->isp_ops = &qla25xx_isp_ops; |
1666 | ha->hw_event_start = PCI_FUNC(pdev->devfn) ? | ||
1667 | FA_HW_EVENT1_ADDR: FA_HW_EVENT0_ADDR; | ||
1668 | } | 1667 | } |
1669 | host->can_queue = ha->request_q_length + 128; | 1668 | host->can_queue = ha->request_q_length + 128; |
1670 | 1669 | ||
@@ -2433,6 +2432,12 @@ qla2x00_do_dpc(void *data) | |||
2433 | ha->host_no)); | 2432 | ha->host_no)); |
2434 | } | 2433 | } |
2435 | 2434 | ||
2435 | if (test_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags) && | ||
2436 | atomic_read(&ha->loop_state) == LOOP_READY) { | ||
2437 | clear_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags); | ||
2438 | qla2xxx_flash_npiv_conf(ha); | ||
2439 | } | ||
2440 | |||
2436 | if (!ha->interrupts_on) | 2441 | if (!ha->interrupts_on) |
2437 | ha->isp_ops->enable_intrs(ha); | 2442 | ha->isp_ops->enable_intrs(ha); |
2438 | 2443 | ||
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 1bca74474935..90a13211717f 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -543,23 +543,198 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, | |||
543 | } | 543 | } |
544 | } | 544 | } |
545 | 545 | ||
546 | void | 546 | static int |
547 | qla2xxx_get_flash_info(scsi_qla_host_t *ha) | 547 | qla2xxx_find_flt_start(scsi_qla_host_t *ha, uint32_t *start) |
548 | { | ||
549 | const char *loc, *locations[] = { "DEF", "PCI" }; | ||
550 | uint32_t pcihdr, pcids; | ||
551 | uint32_t *dcode; | ||
552 | uint8_t *buf, *bcode, last_image; | ||
553 | uint16_t cnt, chksum, *wptr; | ||
554 | struct qla_flt_location *fltl; | ||
555 | |||
556 | /* | ||
557 | * FLT-location structure resides after the last PCI region. | ||
558 | */ | ||
559 | |||
560 | /* Begin with sane defaults. */ | ||
561 | loc = locations[0]; | ||
562 | *start = IS_QLA24XX_TYPE(ha) ? FA_FLASH_LAYOUT_ADDR_24: | ||
563 | FA_FLASH_LAYOUT_ADDR; | ||
564 | |||
565 | /* Begin with first PCI expansion ROM header. */ | ||
566 | buf = (uint8_t *)ha->request_ring; | ||
567 | dcode = (uint32_t *)ha->request_ring; | ||
568 | pcihdr = 0; | ||
569 | last_image = 1; | ||
570 | do { | ||
571 | /* Verify PCI expansion ROM header. */ | ||
572 | qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, 0x20); | ||
573 | bcode = buf + (pcihdr % 4); | ||
574 | if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) | ||
575 | goto end; | ||
576 | |||
577 | /* Locate PCI data structure. */ | ||
578 | pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]); | ||
579 | qla24xx_read_flash_data(ha, dcode, pcids >> 2, 0x20); | ||
580 | bcode = buf + (pcihdr % 4); | ||
581 | |||
582 | /* Validate signature of PCI data structure. */ | ||
583 | if (bcode[0x0] != 'P' || bcode[0x1] != 'C' || | ||
584 | bcode[0x2] != 'I' || bcode[0x3] != 'R') | ||
585 | goto end; | ||
586 | |||
587 | last_image = bcode[0x15] & BIT_7; | ||
588 | |||
589 | /* Locate next PCI expansion ROM. */ | ||
590 | pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512; | ||
591 | } while (!last_image); | ||
592 | |||
593 | /* Now verify FLT-location structure. */ | ||
594 | fltl = (struct qla_flt_location *)ha->request_ring; | ||
595 | qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, | ||
596 | sizeof(struct qla_flt_location) >> 2); | ||
597 | if (fltl->sig[0] != 'Q' || fltl->sig[1] != 'F' || | ||
598 | fltl->sig[2] != 'L' || fltl->sig[3] != 'T') | ||
599 | goto end; | ||
600 | |||
601 | wptr = (uint16_t *)ha->request_ring; | ||
602 | cnt = sizeof(struct qla_flt_location) >> 1; | ||
603 | for (chksum = 0; cnt; cnt--) | ||
604 | chksum += le16_to_cpu(*wptr++); | ||
605 | if (chksum) { | ||
606 | qla_printk(KERN_ERR, ha, | ||
607 | "Inconsistent FLTL detected: checksum=0x%x.\n", chksum); | ||
608 | qla2x00_dump_buffer(buf, sizeof(struct qla_flt_location)); | ||
609 | return QLA_FUNCTION_FAILED; | ||
610 | } | ||
611 | |||
612 | /* Good data. Use specified location. */ | ||
613 | loc = locations[1]; | ||
614 | *start = le16_to_cpu(fltl->start_hi) << 16 | | ||
615 | le16_to_cpu(fltl->start_lo); | ||
616 | end: | ||
617 | DEBUG2(qla_printk(KERN_DEBUG, ha, "FLTL[%s] = 0x%x.\n", loc, *start)); | ||
618 | return QLA_SUCCESS; | ||
619 | } | ||
620 | |||
621 | static void | ||
622 | qla2xxx_get_flt_info(scsi_qla_host_t *ha, uint32_t flt_addr) | ||
623 | { | ||
624 | const char *loc, *locations[] = { "DEF", "FLT" }; | ||
625 | uint16_t *wptr; | ||
626 | uint16_t cnt, chksum; | ||
627 | uint32_t start; | ||
628 | struct qla_flt_header *flt; | ||
629 | struct qla_flt_region *region; | ||
630 | |||
631 | ha->flt_region_flt = flt_addr; | ||
632 | wptr = (uint16_t *)ha->request_ring; | ||
633 | flt = (struct qla_flt_header *)ha->request_ring; | ||
634 | region = (struct qla_flt_region *)&flt[1]; | ||
635 | ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring, | ||
636 | flt_addr << 2, OPTROM_BURST_SIZE); | ||
637 | if (*wptr == __constant_cpu_to_le16(0xffff)) | ||
638 | goto no_flash_data; | ||
639 | if (flt->version != __constant_cpu_to_le16(1)) { | ||
640 | DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported FLT detected: " | ||
641 | "version=0x%x length=0x%x checksum=0x%x.\n", | ||
642 | le16_to_cpu(flt->version), le16_to_cpu(flt->length), | ||
643 | le16_to_cpu(flt->checksum))); | ||
644 | goto no_flash_data; | ||
645 | } | ||
646 | |||
647 | cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1; | ||
648 | for (chksum = 0; cnt; cnt--) | ||
649 | chksum += le16_to_cpu(*wptr++); | ||
650 | if (chksum) { | ||
651 | DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent FLT detected: " | ||
652 | "version=0x%x length=0x%x checksum=0x%x.\n", | ||
653 | le16_to_cpu(flt->version), le16_to_cpu(flt->length), | ||
654 | chksum)); | ||
655 | goto no_flash_data; | ||
656 | } | ||
657 | |||
658 | loc = locations[1]; | ||
659 | cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region); | ||
660 | for ( ; cnt; cnt--, region++) { | ||
661 | /* Store addresses as DWORD offsets. */ | ||
662 | start = le32_to_cpu(region->start) >> 2; | ||
663 | |||
664 | DEBUG3(qla_printk(KERN_DEBUG, ha, "FLT[%02x]: start=0x%x " | ||
665 | "end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start, | ||
666 | le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size))); | ||
667 | |||
668 | switch (le32_to_cpu(region->code)) { | ||
669 | case FLT_REG_FW: | ||
670 | ha->flt_region_fw = start; | ||
671 | break; | ||
672 | case FLT_REG_BOOT_CODE: | ||
673 | ha->flt_region_boot = start; | ||
674 | break; | ||
675 | case FLT_REG_VPD_0: | ||
676 | ha->flt_region_vpd_nvram = start; | ||
677 | break; | ||
678 | case FLT_REG_FDT: | ||
679 | ha->flt_region_fdt = start; | ||
680 | break; | ||
681 | case FLT_REG_HW_EVENT_0: | ||
682 | if (!PCI_FUNC(ha->pdev->devfn)) | ||
683 | ha->flt_region_hw_event = start; | ||
684 | break; | ||
685 | case FLT_REG_HW_EVENT_1: | ||
686 | if (PCI_FUNC(ha->pdev->devfn)) | ||
687 | ha->flt_region_hw_event = start; | ||
688 | break; | ||
689 | case FLT_REG_NPIV_CONF_0: | ||
690 | if (!PCI_FUNC(ha->pdev->devfn)) | ||
691 | ha->flt_region_npiv_conf = start; | ||
692 | break; | ||
693 | case FLT_REG_NPIV_CONF_1: | ||
694 | if (PCI_FUNC(ha->pdev->devfn)) | ||
695 | ha->flt_region_npiv_conf = start; | ||
696 | break; | ||
697 | } | ||
698 | } | ||
699 | goto done; | ||
700 | |||
701 | no_flash_data: | ||
702 | /* Use hardcoded defaults. */ | ||
703 | loc = locations[0]; | ||
704 | ha->flt_region_fw = FA_RISC_CODE_ADDR; | ||
705 | ha->flt_region_boot = FA_BOOT_CODE_ADDR; | ||
706 | ha->flt_region_vpd_nvram = FA_VPD_NVRAM_ADDR; | ||
707 | ha->flt_region_fdt = IS_QLA24XX_TYPE(ha) ? FA_FLASH_DESCR_ADDR_24: | ||
708 | FA_FLASH_DESCR_ADDR; | ||
709 | ha->flt_region_hw_event = !PCI_FUNC(ha->pdev->devfn) ? | ||
710 | FA_HW_EVENT0_ADDR: FA_HW_EVENT1_ADDR; | ||
711 | ha->flt_region_npiv_conf = !PCI_FUNC(ha->pdev->devfn) ? | ||
712 | (IS_QLA24XX_TYPE(ha) ? FA_NPIV_CONF0_ADDR_24: FA_NPIV_CONF0_ADDR): | ||
713 | (IS_QLA24XX_TYPE(ha) ? FA_NPIV_CONF1_ADDR_24: FA_NPIV_CONF1_ADDR); | ||
714 | done: | ||
715 | DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x " | ||
716 | "vpd_nvram=0x%x fdt=0x%x flt=0x%x hwe=0x%x npiv=0x%x.\n", loc, | ||
717 | ha->flt_region_boot, ha->flt_region_fw, ha->flt_region_vpd_nvram, | ||
718 | ha->flt_region_fdt, ha->flt_region_flt, ha->flt_region_hw_event, | ||
719 | ha->flt_region_npiv_conf)); | ||
720 | } | ||
721 | |||
722 | static void | ||
723 | qla2xxx_get_fdt_info(scsi_qla_host_t *ha) | ||
548 | { | 724 | { |
549 | #define FLASH_BLK_SIZE_32K 0x8000 | 725 | #define FLASH_BLK_SIZE_32K 0x8000 |
550 | #define FLASH_BLK_SIZE_64K 0x10000 | 726 | #define FLASH_BLK_SIZE_64K 0x10000 |
727 | const char *loc, *locations[] = { "MID", "FDT" }; | ||
551 | uint16_t cnt, chksum; | 728 | uint16_t cnt, chksum; |
552 | uint16_t *wptr; | 729 | uint16_t *wptr; |
553 | struct qla_fdt_layout *fdt; | 730 | struct qla_fdt_layout *fdt; |
554 | uint8_t man_id, flash_id; | 731 | uint8_t man_id, flash_id; |
555 | 732 | uint16_t mid, fid; | |
556 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) | ||
557 | return; | ||
558 | 733 | ||
559 | wptr = (uint16_t *)ha->request_ring; | 734 | wptr = (uint16_t *)ha->request_ring; |
560 | fdt = (struct qla_fdt_layout *)ha->request_ring; | 735 | fdt = (struct qla_fdt_layout *)ha->request_ring; |
561 | ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring, | 736 | ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring, |
562 | FA_FLASH_DESCR_ADDR << 2, OPTROM_BURST_SIZE); | 737 | ha->flt_region_fdt << 2, OPTROM_BURST_SIZE); |
563 | if (*wptr == __constant_cpu_to_le16(0xffff)) | 738 | if (*wptr == __constant_cpu_to_le16(0xffff)) |
564 | goto no_flash_data; | 739 | goto no_flash_data; |
565 | if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' || | 740 | if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' || |
@@ -577,7 +752,10 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha) | |||
577 | goto no_flash_data; | 752 | goto no_flash_data; |
578 | } | 753 | } |
579 | 754 | ||
580 | ha->fdt_odd_index = le16_to_cpu(fdt->man_id) == 0x1f; | 755 | loc = locations[1]; |
756 | mid = le16_to_cpu(fdt->man_id); | ||
757 | fid = le16_to_cpu(fdt->id); | ||
758 | ha->fdt_odd_index = mid == 0x1f; | ||
581 | ha->fdt_wrt_disable = fdt->wrt_disable_bits; | 759 | ha->fdt_wrt_disable = fdt->wrt_disable_bits; |
582 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd); | 760 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd); |
583 | ha->fdt_block_size = le32_to_cpu(fdt->block_size); | 761 | ha->fdt_block_size = le32_to_cpu(fdt->block_size); |
@@ -588,16 +766,12 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha) | |||
588 | flash_conf_to_access_addr(0x0300 | fdt->protect_sec_cmd): | 766 | flash_conf_to_access_addr(0x0300 | fdt->protect_sec_cmd): |
589 | flash_conf_to_access_addr(0x0336); | 767 | flash_conf_to_access_addr(0x0336); |
590 | } | 768 | } |
591 | 769 | goto done; | |
592 | DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[FDT]: (0x%x/0x%x) erase=0x%x " | ||
593 | "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", | ||
594 | le16_to_cpu(fdt->man_id), le16_to_cpu(fdt->id), ha->fdt_erase_cmd, | ||
595 | ha->fdt_protect_sec_cmd, ha->fdt_unprotect_sec_cmd, | ||
596 | ha->fdt_odd_index, ha->fdt_wrt_disable, ha->fdt_block_size)); | ||
597 | return; | ||
598 | |||
599 | no_flash_data: | 770 | no_flash_data: |
771 | loc = locations[0]; | ||
600 | qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); | 772 | qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); |
773 | mid = man_id; | ||
774 | fid = flash_id; | ||
601 | ha->fdt_wrt_disable = 0x9c; | 775 | ha->fdt_wrt_disable = 0x9c; |
602 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x03d8); | 776 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x03d8); |
603 | switch (man_id) { | 777 | switch (man_id) { |
@@ -625,14 +799,117 @@ no_flash_data: | |||
625 | ha->fdt_block_size = FLASH_BLK_SIZE_64K; | 799 | ha->fdt_block_size = FLASH_BLK_SIZE_64K; |
626 | break; | 800 | break; |
627 | } | 801 | } |
628 | 802 | done: | |
629 | DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[MID]: (0x%x/0x%x) erase=0x%x " | 803 | DEBUG2(qla_printk(KERN_DEBUG, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x " |
630 | "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", man_id, flash_id, | 804 | "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", loc, mid, fid, |
631 | ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd, | 805 | ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd, |
632 | ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable, | 806 | ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable, |
633 | ha->fdt_block_size)); | 807 | ha->fdt_block_size)); |
634 | } | 808 | } |
635 | 809 | ||
810 | int | ||
811 | qla2xxx_get_flash_info(scsi_qla_host_t *ha) | ||
812 | { | ||
813 | int ret; | ||
814 | uint32_t flt_addr; | ||
815 | |||
816 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) | ||
817 | return QLA_SUCCESS; | ||
818 | |||
819 | ret = qla2xxx_find_flt_start(ha, &flt_addr); | ||
820 | if (ret != QLA_SUCCESS) | ||
821 | return ret; | ||
822 | |||
823 | qla2xxx_get_flt_info(ha, flt_addr); | ||
824 | qla2xxx_get_fdt_info(ha); | ||
825 | |||
826 | return QLA_SUCCESS; | ||
827 | } | ||
828 | |||
829 | void | ||
830 | qla2xxx_flash_npiv_conf(scsi_qla_host_t *ha) | ||
831 | { | ||
832 | #define NPIV_CONFIG_SIZE (16*1024) | ||
833 | void *data; | ||
834 | uint16_t *wptr; | ||
835 | uint16_t cnt, chksum; | ||
836 | struct qla_npiv_header hdr; | ||
837 | struct qla_npiv_entry *entry; | ||
838 | |||
839 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) | ||
840 | return; | ||
841 | |||
842 | ha->isp_ops->read_optrom(ha, (uint8_t *)&hdr, | ||
843 | ha->flt_region_npiv_conf << 2, sizeof(struct qla_npiv_header)); | ||
844 | if (hdr.version == __constant_cpu_to_le16(0xffff)) | ||
845 | return; | ||
846 | if (hdr.version != __constant_cpu_to_le16(1)) { | ||
847 | DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported NPIV-Config " | ||
848 | "detected: version=0x%x entries=0x%x checksum=0x%x.\n", | ||
849 | le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries), | ||
850 | le16_to_cpu(hdr.checksum))); | ||
851 | return; | ||
852 | } | ||
853 | |||
854 | data = kmalloc(NPIV_CONFIG_SIZE, GFP_KERNEL); | ||
855 | if (!data) { | ||
856 | DEBUG2(qla_printk(KERN_INFO, ha, "NPIV-Config: Unable to " | ||
857 | "allocate memory.\n")); | ||
858 | return; | ||
859 | } | ||
860 | |||
861 | ha->isp_ops->read_optrom(ha, (uint8_t *)data, | ||
862 | ha->flt_region_npiv_conf << 2, NPIV_CONFIG_SIZE); | ||
863 | |||
864 | cnt = (sizeof(struct qla_npiv_header) + le16_to_cpu(hdr.entries) * | ||
865 | sizeof(struct qla_npiv_entry)) >> 1; | ||
866 | for (wptr = data, chksum = 0; cnt; cnt--) | ||
867 | chksum += le16_to_cpu(*wptr++); | ||
868 | if (chksum) { | ||
869 | DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent NPIV-Config " | ||
870 | "detected: version=0x%x entries=0x%x checksum=0x%x.\n", | ||
871 | le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries), | ||
872 | chksum)); | ||
873 | goto done; | ||
874 | } | ||
875 | |||
876 | entry = data + sizeof(struct qla_npiv_header); | ||
877 | cnt = le16_to_cpu(hdr.entries); | ||
878 | for ( ; cnt; cnt--, entry++) { | ||
879 | uint16_t flags; | ||
880 | struct fc_vport_identifiers vid; | ||
881 | struct fc_vport *vport; | ||
882 | |||
883 | flags = le16_to_cpu(entry->flags); | ||
884 | if (flags == 0xffff) | ||
885 | continue; | ||
886 | if ((flags & BIT_0) == 0) | ||
887 | continue; | ||
888 | |||
889 | memset(&vid, 0, sizeof(vid)); | ||
890 | vid.roles = FC_PORT_ROLE_FCP_INITIATOR; | ||
891 | vid.vport_type = FC_PORTTYPE_NPIV; | ||
892 | vid.disable = false; | ||
893 | vid.port_name = wwn_to_u64(entry->port_name); | ||
894 | vid.node_name = wwn_to_u64(entry->node_name); | ||
895 | |||
896 | DEBUG2(qla_printk(KERN_DEBUG, ha, "NPIV[%02x]: wwpn=%llx " | ||
897 | "wwnn=%llx vf_id=0x%x qos=0x%x.\n", cnt, | ||
898 | (unsigned long long)vid.port_name, | ||
899 | (unsigned long long)vid.node_name, | ||
900 | le16_to_cpu(entry->vf_id), le16_to_cpu(entry->qos))); | ||
901 | |||
902 | vport = fc_vport_create(ha->host, 0, &vid); | ||
903 | if (!vport) | ||
904 | qla_printk(KERN_INFO, ha, "NPIV-Config: Failed to " | ||
905 | "create vport [%02x]: wwpn=%llx wwnn=%llx.\n", cnt, | ||
906 | (unsigned long long)vid.port_name, | ||
907 | (unsigned long long)vid.node_name); | ||
908 | } | ||
909 | done: | ||
910 | kfree(data); | ||
911 | } | ||
912 | |||
636 | static void | 913 | static void |
637 | qla24xx_unprotect_flash(scsi_qla_host_t *ha) | 914 | qla24xx_unprotect_flash(scsi_qla_host_t *ha) |
638 | { | 915 | { |
@@ -920,7 +1197,8 @@ qla25xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
920 | dwptr = (uint32_t *)buf; | 1197 | dwptr = (uint32_t *)buf; |
921 | for (i = 0; i < bytes >> 2; i++, naddr++) | 1198 | for (i = 0; i < bytes >> 2; i++, naddr++) |
922 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, | 1199 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, |
923 | flash_data_to_access_addr(FA_VPD_NVRAM_ADDR | naddr))); | 1200 | flash_data_to_access_addr(ha->flt_region_vpd_nvram | |
1201 | naddr))); | ||
924 | 1202 | ||
925 | return buf; | 1203 | return buf; |
926 | } | 1204 | } |
@@ -935,10 +1213,10 @@ qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
935 | dbuf = vmalloc(RMW_BUFFER_SIZE); | 1213 | dbuf = vmalloc(RMW_BUFFER_SIZE); |
936 | if (!dbuf) | 1214 | if (!dbuf) |
937 | return QLA_MEMORY_ALLOC_FAILED; | 1215 | return QLA_MEMORY_ALLOC_FAILED; |
938 | ha->isp_ops->read_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, | 1216 | ha->isp_ops->read_optrom(ha, dbuf, ha->flt_region_vpd_nvram << 2, |
939 | RMW_BUFFER_SIZE); | 1217 | RMW_BUFFER_SIZE); |
940 | memcpy(dbuf + (naddr << 2), buf, bytes); | 1218 | memcpy(dbuf + (naddr << 2), buf, bytes); |
941 | ha->isp_ops->write_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, | 1219 | ha->isp_ops->write_optrom(ha, dbuf, ha->flt_region_vpd_nvram << 2, |
942 | RMW_BUFFER_SIZE); | 1220 | RMW_BUFFER_SIZE); |
943 | vfree(dbuf); | 1221 | vfree(dbuf); |
944 | 1222 | ||
@@ -2166,7 +2444,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2166 | memset(dbyte, 0, 8); | 2444 | memset(dbyte, 0, 8); |
2167 | dcode = (uint16_t *)dbyte; | 2445 | dcode = (uint16_t *)dbyte; |
2168 | 2446 | ||
2169 | qla2x00_read_flash_data(ha, dbyte, FA_RISC_CODE_ADDR * 4 + 10, | 2447 | qla2x00_read_flash_data(ha, dbyte, ha->flt_region_fw * 4 + 10, |
2170 | 8); | 2448 | 8); |
2171 | DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n", | 2449 | DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n", |
2172 | __func__, ha->host_no)); | 2450 | __func__, ha->host_no)); |
@@ -2177,7 +2455,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2177 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | 2455 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && |
2178 | dcode[3] == 0)) { | 2456 | dcode[3] == 0)) { |
2179 | DEBUG2(printk("%s(): Unrecognized fw revision at " | 2457 | DEBUG2(printk("%s(): Unrecognized fw revision at " |
2180 | "%x.\n", __func__, FA_RISC_CODE_ADDR * 4)); | 2458 | "%x.\n", __func__, ha->flt_region_fw * 4)); |
2181 | } else { | 2459 | } else { |
2182 | /* values are in big endian */ | 2460 | /* values are in big endian */ |
2183 | ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1]; | 2461 | ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1]; |
@@ -2212,7 +2490,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2212 | dcode = mbuf; | 2490 | dcode = mbuf; |
2213 | 2491 | ||
2214 | /* Begin with first PCI expansion ROM header. */ | 2492 | /* Begin with first PCI expansion ROM header. */ |
2215 | pcihdr = 0; | 2493 | pcihdr = ha->flt_region_boot; |
2216 | last_image = 1; | 2494 | last_image = 1; |
2217 | do { | 2495 | do { |
2218 | /* Verify PCI expansion ROM header. */ | 2496 | /* Verify PCI expansion ROM header. */ |
@@ -2282,7 +2560,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2282 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); | 2560 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); |
2283 | dcode = mbuf; | 2561 | dcode = mbuf; |
2284 | 2562 | ||
2285 | qla24xx_read_flash_data(ha, dcode, FA_RISC_CODE_ADDR + 4, 4); | 2563 | qla24xx_read_flash_data(ha, dcode, ha->flt_region_fw + 4, 4); |
2286 | for (i = 0; i < 4; i++) | 2564 | for (i = 0; i < 4; i++) |
2287 | dcode[i] = be32_to_cpu(dcode[i]); | 2565 | dcode[i] = be32_to_cpu(dcode[i]); |
2288 | 2566 | ||
@@ -2291,7 +2569,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2291 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | 2569 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && |
2292 | dcode[3] == 0)) { | 2570 | dcode[3] == 0)) { |
2293 | DEBUG2(printk("%s(): Unrecognized fw version at %x.\n", | 2571 | DEBUG2(printk("%s(): Unrecognized fw version at %x.\n", |
2294 | __func__, FA_RISC_CODE_ADDR)); | 2572 | __func__, ha->flt_region_fw)); |
2295 | } else { | 2573 | } else { |
2296 | ha->fw_revision[0] = dcode[0]; | 2574 | ha->fw_revision[0] = dcode[0]; |
2297 | ha->fw_revision[1] = dcode[1]; | 2575 | ha->fw_revision[1] = dcode[1]; |
@@ -2355,7 +2633,7 @@ qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata) | |||
2355 | /* Locate first empty entry. */ | 2633 | /* Locate first empty entry. */ |
2356 | for (;;) { | 2634 | for (;;) { |
2357 | if (ha->hw_event_ptr >= | 2635 | if (ha->hw_event_ptr >= |
2358 | ha->hw_event_start + FA_HW_EVENT_SIZE) { | 2636 | ha->flt_region_hw_event + FA_HW_EVENT_SIZE) { |
2359 | DEBUG2(qla_printk(KERN_WARNING, ha, | 2637 | DEBUG2(qla_printk(KERN_WARNING, ha, |
2360 | "HW event -- Log Full!\n")); | 2638 | "HW event -- Log Full!\n")); |
2361 | return QLA_MEMORY_ALLOC_FAILED; | 2639 | return QLA_MEMORY_ALLOC_FAILED; |
@@ -2391,7 +2669,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1, | |||
2391 | int rval; | 2669 | int rval; |
2392 | uint32_t marker[2], fdata[4]; | 2670 | uint32_t marker[2], fdata[4]; |
2393 | 2671 | ||
2394 | if (ha->hw_event_start == 0) | 2672 | if (ha->flt_region_hw_event == 0) |
2395 | return QLA_FUNCTION_FAILED; | 2673 | return QLA_FUNCTION_FAILED; |
2396 | 2674 | ||
2397 | DEBUG2(qla_printk(KERN_WARNING, ha, | 2675 | DEBUG2(qla_printk(KERN_WARNING, ha, |
@@ -2406,7 +2684,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1, | |||
2406 | QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER); | 2684 | QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER); |
2407 | 2685 | ||
2408 | /* Locate marker. */ | 2686 | /* Locate marker. */ |
2409 | ha->hw_event_ptr = ha->hw_event_start; | 2687 | ha->hw_event_ptr = ha->flt_region_hw_event; |
2410 | for (;;) { | 2688 | for (;;) { |
2411 | qla24xx_read_flash_data(ha, fdata, ha->hw_event_ptr, | 2689 | qla24xx_read_flash_data(ha, fdata, ha->hw_event_ptr, |
2412 | 4); | 2690 | 4); |
@@ -2415,7 +2693,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1, | |||
2415 | break; | 2693 | break; |
2416 | ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE; | 2694 | ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE; |
2417 | if (ha->hw_event_ptr >= | 2695 | if (ha->hw_event_ptr >= |
2418 | ha->hw_event_start + FA_HW_EVENT_SIZE) { | 2696 | ha->flt_region_hw_event + FA_HW_EVENT_SIZE) { |
2419 | DEBUG2(qla_printk(KERN_WARNING, ha, | 2697 | DEBUG2(qla_printk(KERN_WARNING, ha, |
2420 | "HW event -- Log Full!\n")); | 2698 | "HW event -- Log Full!\n")); |
2421 | return QLA_MEMORY_ALLOC_FAILED; | 2699 | return QLA_MEMORY_ALLOC_FAILED; |
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 4160e4caa7b9..be5e299df528 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
@@ -7,7 +7,7 @@ | |||
7 | /* | 7 | /* |
8 | * Driver version | 8 | * Driver version |
9 | */ | 9 | */ |
10 | #define QLA2XXX_VERSION "8.02.01-k7" | 10 | #define QLA2XXX_VERSION "8.02.01-k8" |
11 | 11 | ||
12 | #define QLA_DRIVER_MAJOR_VER 8 | 12 | #define QLA_DRIVER_MAJOR_VER 8 |
13 | #define QLA_DRIVER_MINOR_VER 2 | 13 | #define QLA_DRIVER_MINOR_VER 2 |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index dbeb86cafc0d..2ac3cb2b9081 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -668,13 +668,14 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) | |||
668 | goto out; | 668 | goto out; |
669 | } | 669 | } |
670 | 670 | ||
671 | /* Check to see if the scsi lld put this device into state SDEV_BLOCK. */ | 671 | /* Check to see if the scsi lld made this device blocked. */ |
672 | if (unlikely(cmd->device->sdev_state == SDEV_BLOCK)) { | 672 | if (unlikely(scsi_device_blocked(cmd->device))) { |
673 | /* | 673 | /* |
674 | * in SDEV_BLOCK, the command is just put back on the device | 674 | * in blocked state, the command is just put back on |
675 | * queue. The suspend state has already blocked the queue so | 675 | * the device queue. The suspend state has already |
676 | * future requests should not occur until the device | 676 | * blocked the queue so future requests should not |
677 | * transitions out of the suspend state. | 677 | * occur until the device transitions out of the |
678 | * suspend state. | ||
678 | */ | 679 | */ |
679 | 680 | ||
680 | scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); | 681 | scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index e7686500e9dd..98ee55ced592 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -1250,6 +1250,7 @@ int scsi_prep_state_check(struct scsi_device *sdev, struct request *req) | |||
1250 | break; | 1250 | break; |
1251 | case SDEV_QUIESCE: | 1251 | case SDEV_QUIESCE: |
1252 | case SDEV_BLOCK: | 1252 | case SDEV_BLOCK: |
1253 | case SDEV_CREATED_BLOCK: | ||
1253 | /* | 1254 | /* |
1254 | * If the devices is blocked we defer normal commands. | 1255 | * If the devices is blocked we defer normal commands. |
1255 | */ | 1256 | */ |
@@ -2073,10 +2074,13 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) | |||
2073 | 2074 | ||
2074 | switch (state) { | 2075 | switch (state) { |
2075 | case SDEV_CREATED: | 2076 | case SDEV_CREATED: |
2076 | /* There are no legal states that come back to | 2077 | switch (oldstate) { |
2077 | * created. This is the manually initialised start | 2078 | case SDEV_CREATED_BLOCK: |
2078 | * state */ | 2079 | break; |
2079 | goto illegal; | 2080 | default: |
2081 | goto illegal; | ||
2082 | } | ||
2083 | break; | ||
2080 | 2084 | ||
2081 | case SDEV_RUNNING: | 2085 | case SDEV_RUNNING: |
2082 | switch (oldstate) { | 2086 | switch (oldstate) { |
@@ -2114,8 +2118,17 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) | |||
2114 | 2118 | ||
2115 | case SDEV_BLOCK: | 2119 | case SDEV_BLOCK: |
2116 | switch (oldstate) { | 2120 | switch (oldstate) { |
2117 | case SDEV_CREATED: | ||
2118 | case SDEV_RUNNING: | 2121 | case SDEV_RUNNING: |
2122 | case SDEV_CREATED_BLOCK: | ||
2123 | break; | ||
2124 | default: | ||
2125 | goto illegal; | ||
2126 | } | ||
2127 | break; | ||
2128 | |||
2129 | case SDEV_CREATED_BLOCK: | ||
2130 | switch (oldstate) { | ||
2131 | case SDEV_CREATED: | ||
2119 | break; | 2132 | break; |
2120 | default: | 2133 | default: |
2121 | goto illegal; | 2134 | goto illegal; |
@@ -2403,8 +2416,12 @@ scsi_internal_device_block(struct scsi_device *sdev) | |||
2403 | int err = 0; | 2416 | int err = 0; |
2404 | 2417 | ||
2405 | err = scsi_device_set_state(sdev, SDEV_BLOCK); | 2418 | err = scsi_device_set_state(sdev, SDEV_BLOCK); |
2406 | if (err) | 2419 | if (err) { |
2407 | return err; | 2420 | err = scsi_device_set_state(sdev, SDEV_CREATED_BLOCK); |
2421 | |||
2422 | if (err) | ||
2423 | return err; | ||
2424 | } | ||
2408 | 2425 | ||
2409 | /* | 2426 | /* |
2410 | * The device has transitioned to SDEV_BLOCK. Stop the | 2427 | * The device has transitioned to SDEV_BLOCK. Stop the |
@@ -2447,8 +2464,12 @@ scsi_internal_device_unblock(struct scsi_device *sdev) | |||
2447 | * and goose the device queue if successful. | 2464 | * and goose the device queue if successful. |
2448 | */ | 2465 | */ |
2449 | err = scsi_device_set_state(sdev, SDEV_RUNNING); | 2466 | err = scsi_device_set_state(sdev, SDEV_RUNNING); |
2450 | if (err) | 2467 | if (err) { |
2451 | return err; | 2468 | err = scsi_device_set_state(sdev, SDEV_CREATED); |
2469 | |||
2470 | if (err) | ||
2471 | return err; | ||
2472 | } | ||
2452 | 2473 | ||
2453 | spin_lock_irqsave(q->queue_lock, flags); | 2474 | spin_lock_irqsave(q->queue_lock, flags); |
2454 | blk_start_queue(q); | 2475 | blk_start_queue(q); |
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c index ae7ed9a22662..b37e133de805 100644 --- a/drivers/scsi/scsi_netlink.c +++ b/drivers/scsi/scsi_netlink.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/time.h> | 21 | #include <linux/time.h> |
22 | #include <linux/jiffies.h> | 22 | #include <linux/jiffies.h> |
23 | #include <linux/security.h> | 23 | #include <linux/security.h> |
24 | #include <linux/delay.h> | ||
24 | #include <net/sock.h> | 25 | #include <net/sock.h> |
25 | #include <net/netlink.h> | 26 | #include <net/netlink.h> |
26 | 27 | ||
@@ -30,6 +31,39 @@ | |||
30 | struct sock *scsi_nl_sock = NULL; | 31 | struct sock *scsi_nl_sock = NULL; |
31 | EXPORT_SYMBOL_GPL(scsi_nl_sock); | 32 | EXPORT_SYMBOL_GPL(scsi_nl_sock); |
32 | 33 | ||
34 | static DEFINE_SPINLOCK(scsi_nl_lock); | ||
35 | static struct list_head scsi_nl_drivers; | ||
36 | |||
37 | static u32 scsi_nl_state; | ||
38 | #define STATE_EHANDLER_BSY 0x00000001 | ||
39 | |||
40 | struct scsi_nl_transport { | ||
41 | int (*msg_handler)(struct sk_buff *); | ||
42 | void (*event_handler)(struct notifier_block *, unsigned long, void *); | ||
43 | unsigned int refcnt; | ||
44 | int flags; | ||
45 | }; | ||
46 | |||
47 | /* flags values (bit flags) */ | ||
48 | #define HANDLER_DELETING 0x1 | ||
49 | |||
50 | static struct scsi_nl_transport transports[SCSI_NL_MAX_TRANSPORTS] = | ||
51 | { {NULL, }, }; | ||
52 | |||
53 | |||
54 | struct scsi_nl_drvr { | ||
55 | struct list_head next; | ||
56 | int (*dmsg_handler)(struct Scsi_Host *shost, void *payload, | ||
57 | u32 len, u32 pid); | ||
58 | void (*devt_handler)(struct notifier_block *nb, | ||
59 | unsigned long event, void *notify_ptr); | ||
60 | struct scsi_host_template *hostt; | ||
61 | u64 vendor_id; | ||
62 | unsigned int refcnt; | ||
63 | int flags; | ||
64 | }; | ||
65 | |||
66 | |||
33 | 67 | ||
34 | /** | 68 | /** |
35 | * scsi_nl_rcv_msg - Receive message handler. | 69 | * scsi_nl_rcv_msg - Receive message handler. |
@@ -45,8 +79,9 @@ scsi_nl_rcv_msg(struct sk_buff *skb) | |||
45 | { | 79 | { |
46 | struct nlmsghdr *nlh; | 80 | struct nlmsghdr *nlh; |
47 | struct scsi_nl_hdr *hdr; | 81 | struct scsi_nl_hdr *hdr; |
48 | uint32_t rlen; | 82 | unsigned long flags; |
49 | int err; | 83 | u32 rlen; |
84 | int err, tport; | ||
50 | 85 | ||
51 | while (skb->len >= NLMSG_SPACE(0)) { | 86 | while (skb->len >= NLMSG_SPACE(0)) { |
52 | err = 0; | 87 | err = 0; |
@@ -65,7 +100,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb) | |||
65 | 100 | ||
66 | if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) { | 101 | if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) { |
67 | err = -EBADMSG; | 102 | err = -EBADMSG; |
68 | return; | 103 | goto next_msg; |
69 | } | 104 | } |
70 | 105 | ||
71 | hdr = NLMSG_DATA(nlh); | 106 | hdr = NLMSG_DATA(nlh); |
@@ -83,12 +118,27 @@ scsi_nl_rcv_msg(struct sk_buff *skb) | |||
83 | if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) { | 118 | if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) { |
84 | printk(KERN_WARNING "%s: discarding partial message\n", | 119 | printk(KERN_WARNING "%s: discarding partial message\n", |
85 | __func__); | 120 | __func__); |
86 | return; | 121 | goto next_msg; |
87 | } | 122 | } |
88 | 123 | ||
89 | /* | 124 | /* |
90 | * We currently don't support anyone sending us a message | 125 | * Deliver message to the appropriate transport |
91 | */ | 126 | */ |
127 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
128 | |||
129 | tport = hdr->transport; | ||
130 | if ((tport < SCSI_NL_MAX_TRANSPORTS) && | ||
131 | !(transports[tport].flags & HANDLER_DELETING) && | ||
132 | (transports[tport].msg_handler)) { | ||
133 | transports[tport].refcnt++; | ||
134 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
135 | err = transports[tport].msg_handler(skb); | ||
136 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
137 | transports[tport].refcnt--; | ||
138 | } else | ||
139 | err = -ENOENT; | ||
140 | |||
141 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
92 | 142 | ||
93 | next_msg: | 143 | next_msg: |
94 | if ((err) || (nlh->nlmsg_flags & NLM_F_ACK)) | 144 | if ((err) || (nlh->nlmsg_flags & NLM_F_ACK)) |
@@ -110,14 +160,42 @@ static int | |||
110 | scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr) | 160 | scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr) |
111 | { | 161 | { |
112 | struct netlink_notify *n = ptr; | 162 | struct netlink_notify *n = ptr; |
163 | struct scsi_nl_drvr *driver; | ||
164 | unsigned long flags; | ||
165 | int tport; | ||
113 | 166 | ||
114 | if (n->protocol != NETLINK_SCSITRANSPORT) | 167 | if (n->protocol != NETLINK_SCSITRANSPORT) |
115 | return NOTIFY_DONE; | 168 | return NOTIFY_DONE; |
116 | 169 | ||
170 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
171 | scsi_nl_state |= STATE_EHANDLER_BSY; | ||
172 | |||
117 | /* | 173 | /* |
118 | * Currently, we are not tracking PID's, etc. There is nothing | 174 | * Pass event on to any transports that may be listening |
119 | * to handle. | ||
120 | */ | 175 | */ |
176 | for (tport = 0; tport < SCSI_NL_MAX_TRANSPORTS; tport++) { | ||
177 | if (!(transports[tport].flags & HANDLER_DELETING) && | ||
178 | (transports[tport].event_handler)) { | ||
179 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
180 | transports[tport].event_handler(this, event, ptr); | ||
181 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * Pass event on to any drivers that may be listening | ||
187 | */ | ||
188 | list_for_each_entry(driver, &scsi_nl_drivers, next) { | ||
189 | if (!(driver->flags & HANDLER_DELETING) && | ||
190 | (driver->devt_handler)) { | ||
191 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
192 | driver->devt_handler(this, event, ptr); | ||
193 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | scsi_nl_state &= ~STATE_EHANDLER_BSY; | ||
198 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
121 | 199 | ||
122 | return NOTIFY_DONE; | 200 | return NOTIFY_DONE; |
123 | } | 201 | } |
@@ -128,7 +206,281 @@ static struct notifier_block scsi_netlink_notifier = { | |||
128 | 206 | ||
129 | 207 | ||
130 | /** | 208 | /** |
131 | * scsi_netlink_init - Called by SCSI subsystem to intialize the SCSI transport netlink interface | 209 | * GENERIC SCSI transport receive and event handlers |
210 | **/ | ||
211 | |||
212 | /** | ||
213 | * scsi_generic_msg_handler - receive message handler for GENERIC transport | ||
214 | * messages | ||
215 | * | ||
216 | * @skb: socket receive buffer | ||
217 | * | ||
218 | **/ | ||
219 | static int | ||
220 | scsi_generic_msg_handler(struct sk_buff *skb) | ||
221 | { | ||
222 | struct nlmsghdr *nlh = nlmsg_hdr(skb); | ||
223 | struct scsi_nl_hdr *snlh = NLMSG_DATA(nlh); | ||
224 | struct scsi_nl_drvr *driver; | ||
225 | struct Scsi_Host *shost; | ||
226 | unsigned long flags; | ||
227 | int err = 0, match, pid; | ||
228 | |||
229 | pid = NETLINK_CREDS(skb)->pid; | ||
230 | |||
231 | switch (snlh->msgtype) { | ||
232 | case SCSI_NL_SHOST_VENDOR: | ||
233 | { | ||
234 | struct scsi_nl_host_vendor_msg *msg = NLMSG_DATA(nlh); | ||
235 | |||
236 | /* Locate the driver that corresponds to the message */ | ||
237 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
238 | match = 0; | ||
239 | list_for_each_entry(driver, &scsi_nl_drivers, next) { | ||
240 | if (driver->vendor_id == msg->vendor_id) { | ||
241 | match = 1; | ||
242 | break; | ||
243 | } | ||
244 | } | ||
245 | |||
246 | if ((!match) || (!driver->dmsg_handler)) { | ||
247 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
248 | err = -ESRCH; | ||
249 | goto rcv_exit; | ||
250 | } | ||
251 | |||
252 | if (driver->flags & HANDLER_DELETING) { | ||
253 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
254 | err = -ESHUTDOWN; | ||
255 | goto rcv_exit; | ||
256 | } | ||
257 | |||
258 | driver->refcnt++; | ||
259 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
260 | |||
261 | |||
262 | /* if successful, scsi_host_lookup takes a shost reference */ | ||
263 | shost = scsi_host_lookup(msg->host_no); | ||
264 | if (!shost) { | ||
265 | err = -ENODEV; | ||
266 | goto driver_exit; | ||
267 | } | ||
268 | |||
269 | /* is this host owned by the vendor ? */ | ||
270 | if (shost->hostt != driver->hostt) { | ||
271 | err = -EINVAL; | ||
272 | goto vendormsg_put; | ||
273 | } | ||
274 | |||
275 | /* pass message on to the driver */ | ||
276 | err = driver->dmsg_handler(shost, (void *)&msg[1], | ||
277 | msg->vmsg_datalen, pid); | ||
278 | |||
279 | vendormsg_put: | ||
280 | /* release reference by scsi_host_lookup */ | ||
281 | scsi_host_put(shost); | ||
282 | |||
283 | driver_exit: | ||
284 | /* release our own reference on the registration object */ | ||
285 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
286 | driver->refcnt--; | ||
287 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
288 | break; | ||
289 | } | ||
290 | |||
291 | default: | ||
292 | err = -EBADR; | ||
293 | break; | ||
294 | } | ||
295 | |||
296 | rcv_exit: | ||
297 | if (err) | ||
298 | printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n", | ||
299 | __func__, snlh->msgtype, err); | ||
300 | return err; | ||
301 | } | ||
302 | |||
303 | |||
304 | /** | ||
305 | * scsi_nl_add_transport - | ||
306 | * Registers message and event handlers for a transport. Enables | ||
307 | * receipt of netlink messages and events to a transport. | ||
308 | * | ||
309 | * @tport: transport registering handlers | ||
310 | * @msg_handler: receive message handler callback | ||
311 | * @event_handler: receive event handler callback | ||
312 | **/ | ||
313 | int | ||
314 | scsi_nl_add_transport(u8 tport, | ||
315 | int (*msg_handler)(struct sk_buff *), | ||
316 | void (*event_handler)(struct notifier_block *, unsigned long, void *)) | ||
317 | { | ||
318 | unsigned long flags; | ||
319 | int err = 0; | ||
320 | |||
321 | if (tport >= SCSI_NL_MAX_TRANSPORTS) | ||
322 | return -EINVAL; | ||
323 | |||
324 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
325 | |||
326 | if (scsi_nl_state & STATE_EHANDLER_BSY) { | ||
327 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
328 | msleep(1); | ||
329 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
330 | } | ||
331 | |||
332 | if (transports[tport].msg_handler || transports[tport].event_handler) { | ||
333 | err = -EALREADY; | ||
334 | goto register_out; | ||
335 | } | ||
336 | |||
337 | transports[tport].msg_handler = msg_handler; | ||
338 | transports[tport].event_handler = event_handler; | ||
339 | transports[tport].flags = 0; | ||
340 | transports[tport].refcnt = 0; | ||
341 | |||
342 | register_out: | ||
343 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
344 | |||
345 | return err; | ||
346 | } | ||
347 | EXPORT_SYMBOL_GPL(scsi_nl_add_transport); | ||
348 | |||
349 | |||
350 | /** | ||
351 | * scsi_nl_remove_transport - | ||
352 | * Disable transport receiption of messages and events | ||
353 | * | ||
354 | * @tport: transport deregistering handlers | ||
355 | * | ||
356 | **/ | ||
357 | void | ||
358 | scsi_nl_remove_transport(u8 tport) | ||
359 | { | ||
360 | unsigned long flags; | ||
361 | |||
362 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
363 | if (scsi_nl_state & STATE_EHANDLER_BSY) { | ||
364 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
365 | msleep(1); | ||
366 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
367 | } | ||
368 | |||
369 | if (tport < SCSI_NL_MAX_TRANSPORTS) { | ||
370 | transports[tport].flags |= HANDLER_DELETING; | ||
371 | |||
372 | while (transports[tport].refcnt != 0) { | ||
373 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
374 | schedule_timeout_uninterruptible(HZ/4); | ||
375 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
376 | } | ||
377 | transports[tport].msg_handler = NULL; | ||
378 | transports[tport].event_handler = NULL; | ||
379 | transports[tport].flags = 0; | ||
380 | } | ||
381 | |||
382 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
383 | |||
384 | return; | ||
385 | } | ||
386 | EXPORT_SYMBOL_GPL(scsi_nl_remove_transport); | ||
387 | |||
388 | |||
389 | /** | ||
390 | * scsi_nl_add_driver - | ||
391 | * A driver is registering its interfaces for SCSI netlink messages | ||
392 | * | ||
393 | * @vendor_id: A unique identification value for the driver. | ||
394 | * @hostt: address of the driver's host template. Used | ||
395 | * to verify an shost is bound to the driver | ||
396 | * @nlmsg_handler: receive message handler callback | ||
397 | * @nlevt_handler: receive event handler callback | ||
398 | * | ||
399 | * Returns: | ||
400 | * 0 on Success | ||
401 | * error result otherwise | ||
402 | **/ | ||
403 | int | ||
404 | scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt, | ||
405 | int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload, | ||
406 | u32 len, u32 pid), | ||
407 | void (*nlevt_handler)(struct notifier_block *nb, | ||
408 | unsigned long event, void *notify_ptr)) | ||
409 | { | ||
410 | struct scsi_nl_drvr *driver; | ||
411 | unsigned long flags; | ||
412 | |||
413 | driver = kzalloc(sizeof(*driver), GFP_KERNEL); | ||
414 | if (unlikely(!driver)) { | ||
415 | printk(KERN_ERR "%s: allocation failure\n", __func__); | ||
416 | return -ENOMEM; | ||
417 | } | ||
418 | |||
419 | driver->dmsg_handler = nlmsg_handler; | ||
420 | driver->devt_handler = nlevt_handler; | ||
421 | driver->hostt = hostt; | ||
422 | driver->vendor_id = vendor_id; | ||
423 | |||
424 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
425 | if (scsi_nl_state & STATE_EHANDLER_BSY) { | ||
426 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
427 | msleep(1); | ||
428 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
429 | } | ||
430 | list_add_tail(&driver->next, &scsi_nl_drivers); | ||
431 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | EXPORT_SYMBOL_GPL(scsi_nl_add_driver); | ||
436 | |||
437 | |||
438 | /** | ||
439 | * scsi_nl_remove_driver - | ||
440 | * An driver is unregistering with the SCSI netlink messages | ||
441 | * | ||
442 | * @vendor_id: The unique identification value for the driver. | ||
443 | **/ | ||
444 | void | ||
445 | scsi_nl_remove_driver(u64 vendor_id) | ||
446 | { | ||
447 | struct scsi_nl_drvr *driver; | ||
448 | unsigned long flags; | ||
449 | |||
450 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
451 | if (scsi_nl_state & STATE_EHANDLER_BSY) { | ||
452 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
453 | msleep(1); | ||
454 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
455 | } | ||
456 | |||
457 | list_for_each_entry(driver, &scsi_nl_drivers, next) { | ||
458 | if (driver->vendor_id == vendor_id) { | ||
459 | driver->flags |= HANDLER_DELETING; | ||
460 | while (driver->refcnt != 0) { | ||
461 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
462 | schedule_timeout_uninterruptible(HZ/4); | ||
463 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
464 | } | ||
465 | list_del(&driver->next); | ||
466 | kfree(driver); | ||
467 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
468 | return; | ||
469 | } | ||
470 | } | ||
471 | |||
472 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
473 | |||
474 | printk(KERN_ERR "%s: removal of driver failed - vendor_id 0x%llx\n", | ||
475 | __func__, (unsigned long long)vendor_id); | ||
476 | return; | ||
477 | } | ||
478 | EXPORT_SYMBOL_GPL(scsi_nl_remove_driver); | ||
479 | |||
480 | |||
481 | /** | ||
482 | * scsi_netlink_init - Called by SCSI subsystem to intialize | ||
483 | * the SCSI transport netlink interface | ||
132 | * | 484 | * |
133 | **/ | 485 | **/ |
134 | void | 486 | void |
@@ -136,6 +488,8 @@ scsi_netlink_init(void) | |||
136 | { | 488 | { |
137 | int error; | 489 | int error; |
138 | 490 | ||
491 | INIT_LIST_HEAD(&scsi_nl_drivers); | ||
492 | |||
139 | error = netlink_register_notifier(&scsi_netlink_notifier); | 493 | error = netlink_register_notifier(&scsi_netlink_notifier); |
140 | if (error) { | 494 | if (error) { |
141 | printk(KERN_ERR "%s: register of event handler failed - %d\n", | 495 | printk(KERN_ERR "%s: register of event handler failed - %d\n", |
@@ -150,8 +504,15 @@ scsi_netlink_init(void) | |||
150 | printk(KERN_ERR "%s: register of recieve handler failed\n", | 504 | printk(KERN_ERR "%s: register of recieve handler failed\n", |
151 | __func__); | 505 | __func__); |
152 | netlink_unregister_notifier(&scsi_netlink_notifier); | 506 | netlink_unregister_notifier(&scsi_netlink_notifier); |
507 | return; | ||
153 | } | 508 | } |
154 | 509 | ||
510 | /* Register the entry points for the generic SCSI transport */ | ||
511 | error = scsi_nl_add_transport(SCSI_NL_TRANSPORT, | ||
512 | scsi_generic_msg_handler, NULL); | ||
513 | if (error) | ||
514 | printk(KERN_ERR "%s: register of GENERIC transport handler" | ||
515 | " failed - %d\n", __func__, error); | ||
155 | return; | 516 | return; |
156 | } | 517 | } |
157 | 518 | ||
@@ -163,6 +524,8 @@ scsi_netlink_init(void) | |||
163 | void | 524 | void |
164 | scsi_netlink_exit(void) | 525 | scsi_netlink_exit(void) |
165 | { | 526 | { |
527 | scsi_nl_remove_transport(SCSI_NL_TRANSPORT); | ||
528 | |||
166 | if (scsi_nl_sock) { | 529 | if (scsi_nl_sock) { |
167 | netlink_kernel_release(scsi_nl_sock); | 530 | netlink_kernel_release(scsi_nl_sock); |
168 | netlink_unregister_notifier(&scsi_netlink_notifier); | 531 | netlink_unregister_notifier(&scsi_netlink_notifier); |
@@ -172,3 +535,147 @@ scsi_netlink_exit(void) | |||
172 | } | 535 | } |
173 | 536 | ||
174 | 537 | ||
538 | /* | ||
539 | * Exported Interfaces | ||
540 | */ | ||
541 | |||
542 | /** | ||
543 | * scsi_nl_send_transport_msg - | ||
544 | * Generic function to send a single message from a SCSI transport to | ||
545 | * a single process | ||
546 | * | ||
547 | * @pid: receiving pid | ||
548 | * @hdr: message payload | ||
549 | * | ||
550 | **/ | ||
551 | void | ||
552 | scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr) | ||
553 | { | ||
554 | struct sk_buff *skb; | ||
555 | struct nlmsghdr *nlh; | ||
556 | const char *fn; | ||
557 | char *datab; | ||
558 | u32 len, skblen; | ||
559 | int err; | ||
560 | |||
561 | if (!scsi_nl_sock) { | ||
562 | err = -ENOENT; | ||
563 | fn = "netlink socket"; | ||
564 | goto msg_fail; | ||
565 | } | ||
566 | |||
567 | len = NLMSG_SPACE(hdr->msglen); | ||
568 | skblen = NLMSG_SPACE(len); | ||
569 | |||
570 | skb = alloc_skb(skblen, GFP_KERNEL); | ||
571 | if (!skb) { | ||
572 | err = -ENOBUFS; | ||
573 | fn = "alloc_skb"; | ||
574 | goto msg_fail; | ||
575 | } | ||
576 | |||
577 | nlh = nlmsg_put(skb, pid, 0, SCSI_TRANSPORT_MSG, len - sizeof(*nlh), 0); | ||
578 | if (!nlh) { | ||
579 | err = -ENOBUFS; | ||
580 | fn = "nlmsg_put"; | ||
581 | goto msg_fail_skb; | ||
582 | } | ||
583 | datab = NLMSG_DATA(nlh); | ||
584 | memcpy(datab, hdr, hdr->msglen); | ||
585 | |||
586 | err = nlmsg_unicast(scsi_nl_sock, skb, pid); | ||
587 | if (err < 0) { | ||
588 | fn = "nlmsg_unicast"; | ||
589 | /* nlmsg_unicast already kfree_skb'd */ | ||
590 | goto msg_fail; | ||
591 | } | ||
592 | |||
593 | return; | ||
594 | |||
595 | msg_fail_skb: | ||
596 | kfree_skb(skb); | ||
597 | msg_fail: | ||
598 | printk(KERN_WARNING | ||
599 | "%s: Dropped Message : pid %d Transport %d, msgtype x%x, " | ||
600 | "msglen %d: %s : err %d\n", | ||
601 | __func__, pid, hdr->transport, hdr->msgtype, hdr->msglen, | ||
602 | fn, err); | ||
603 | return; | ||
604 | } | ||
605 | EXPORT_SYMBOL_GPL(scsi_nl_send_transport_msg); | ||
606 | |||
607 | |||
608 | /** | ||
609 | * scsi_nl_send_vendor_msg - called to send a shost vendor unique message | ||
610 | * to a specific process id. | ||
611 | * | ||
612 | * @pid: process id of the receiver | ||
613 | * @host_no: host # sending the message | ||
614 | * @vendor_id: unique identifier for the driver's vendor | ||
615 | * @data_len: amount, in bytes, of vendor unique payload data | ||
616 | * @data_buf: pointer to vendor unique data buffer | ||
617 | * | ||
618 | * Returns: | ||
619 | * 0 on succesful return | ||
620 | * otherwise, failing error code | ||
621 | * | ||
622 | * Notes: | ||
623 | * This routine assumes no locks are held on entry. | ||
624 | */ | ||
625 | int | ||
626 | scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id, | ||
627 | char *data_buf, u32 data_len) | ||
628 | { | ||
629 | struct sk_buff *skb; | ||
630 | struct nlmsghdr *nlh; | ||
631 | struct scsi_nl_host_vendor_msg *msg; | ||
632 | u32 len, skblen; | ||
633 | int err; | ||
634 | |||
635 | if (!scsi_nl_sock) { | ||
636 | err = -ENOENT; | ||
637 | goto send_vendor_fail; | ||
638 | } | ||
639 | |||
640 | len = SCSI_NL_MSGALIGN(sizeof(*msg) + data_len); | ||
641 | skblen = NLMSG_SPACE(len); | ||
642 | |||
643 | skb = alloc_skb(skblen, GFP_KERNEL); | ||
644 | if (!skb) { | ||
645 | err = -ENOBUFS; | ||
646 | goto send_vendor_fail; | ||
647 | } | ||
648 | |||
649 | nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, | ||
650 | skblen - sizeof(*nlh), 0); | ||
651 | if (!nlh) { | ||
652 | err = -ENOBUFS; | ||
653 | goto send_vendor_fail_skb; | ||
654 | } | ||
655 | msg = NLMSG_DATA(nlh); | ||
656 | |||
657 | INIT_SCSI_NL_HDR(&msg->snlh, SCSI_NL_TRANSPORT, | ||
658 | SCSI_NL_SHOST_VENDOR, len); | ||
659 | msg->vendor_id = vendor_id; | ||
660 | msg->host_no = host_no; | ||
661 | msg->vmsg_datalen = data_len; /* bytes */ | ||
662 | memcpy(&msg[1], data_buf, data_len); | ||
663 | |||
664 | err = nlmsg_unicast(scsi_nl_sock, skb, pid); | ||
665 | if (err) | ||
666 | /* nlmsg_multicast already kfree_skb'd */ | ||
667 | goto send_vendor_fail; | ||
668 | |||
669 | return 0; | ||
670 | |||
671 | send_vendor_fail_skb: | ||
672 | kfree_skb(skb); | ||
673 | send_vendor_fail: | ||
674 | printk(KERN_WARNING | ||
675 | "%s: Dropped SCSI Msg : host %d vendor_unique - err %d\n", | ||
676 | __func__, host_no, err); | ||
677 | return err; | ||
678 | } | ||
679 | EXPORT_SYMBOL(scsi_nl_send_vendor_msg); | ||
680 | |||
681 | |||
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index c6a904a45bf9..82f7b2dd08a2 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c | |||
@@ -259,8 +259,8 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) | |||
259 | int error = -ENXIO; | 259 | int error = -ENXIO; |
260 | 260 | ||
261 | shost = scsi_host_lookup(host); | 261 | shost = scsi_host_lookup(host); |
262 | if (IS_ERR(shost)) | 262 | if (!shost) |
263 | return PTR_ERR(shost); | 263 | return error; |
264 | 264 | ||
265 | if (shost->transportt->user_scan) | 265 | if (shost->transportt->user_scan) |
266 | error = shost->transportt->user_scan(shost, channel, id, lun); | 266 | error = shost->transportt->user_scan(shost, channel, id, lun); |
@@ -287,8 +287,8 @@ static int scsi_remove_single_device(uint host, uint channel, uint id, uint lun) | |||
287 | int error = -ENXIO; | 287 | int error = -ENXIO; |
288 | 288 | ||
289 | shost = scsi_host_lookup(host); | 289 | shost = scsi_host_lookup(host); |
290 | if (IS_ERR(shost)) | 290 | if (!shost) |
291 | return PTR_ERR(shost); | 291 | return error; |
292 | sdev = scsi_device_lookup(shost, channel, id, lun); | 292 | sdev = scsi_device_lookup(shost, channel, id, lun); |
293 | if (sdev) { | 293 | if (sdev) { |
294 | scsi_remove_device(sdev); | 294 | scsi_remove_device(sdev); |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 34d0de6cd511..334862e26a1b 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -730,6 +730,8 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
730 | static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | 730 | static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, |
731 | int *bflags, int async) | 731 | int *bflags, int async) |
732 | { | 732 | { |
733 | int ret; | ||
734 | |||
733 | /* | 735 | /* |
734 | * XXX do not save the inquiry, since it can change underneath us, | 736 | * XXX do not save the inquiry, since it can change underneath us, |
735 | * save just vendor/model/rev. | 737 | * save just vendor/model/rev. |
@@ -885,7 +887,17 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
885 | 887 | ||
886 | /* set the device running here so that slave configure | 888 | /* set the device running here so that slave configure |
887 | * may do I/O */ | 889 | * may do I/O */ |
888 | scsi_device_set_state(sdev, SDEV_RUNNING); | 890 | ret = scsi_device_set_state(sdev, SDEV_RUNNING); |
891 | if (ret) { | ||
892 | ret = scsi_device_set_state(sdev, SDEV_BLOCK); | ||
893 | |||
894 | if (ret) { | ||
895 | sdev_printk(KERN_ERR, sdev, | ||
896 | "in wrong state %s to complete scan\n", | ||
897 | scsi_device_state_name(sdev->sdev_state)); | ||
898 | return SCSI_SCAN_NO_RESPONSE; | ||
899 | } | ||
900 | } | ||
889 | 901 | ||
890 | if (*bflags & BLIST_MS_192_BYTES_FOR_3F) | 902 | if (*bflags & BLIST_MS_192_BYTES_FOR_3F) |
891 | sdev->use_192_bytes_for_3f = 1; | 903 | sdev->use_192_bytes_for_3f = 1; |
@@ -899,7 +911,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
899 | transport_configure_device(&sdev->sdev_gendev); | 911 | transport_configure_device(&sdev->sdev_gendev); |
900 | 912 | ||
901 | if (sdev->host->hostt->slave_configure) { | 913 | if (sdev->host->hostt->slave_configure) { |
902 | int ret = sdev->host->hostt->slave_configure(sdev); | 914 | ret = sdev->host->hostt->slave_configure(sdev); |
903 | if (ret) { | 915 | if (ret) { |
904 | /* | 916 | /* |
905 | * if LLDD reports slave not present, don't clutter | 917 | * if LLDD reports slave not present, don't clutter |
@@ -994,7 +1006,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
994 | */ | 1006 | */ |
995 | sdev = scsi_device_lookup_by_target(starget, lun); | 1007 | sdev = scsi_device_lookup_by_target(starget, lun); |
996 | if (sdev) { | 1008 | if (sdev) { |
997 | if (rescan || sdev->sdev_state != SDEV_CREATED) { | 1009 | if (rescan || !scsi_device_created(sdev)) { |
998 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO | 1010 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO |
999 | "scsi scan: device exists on %s\n", | 1011 | "scsi scan: device exists on %s\n", |
1000 | sdev->sdev_gendev.bus_id)); | 1012 | sdev->sdev_gendev.bus_id)); |
@@ -1467,7 +1479,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, | |||
1467 | kfree(lun_data); | 1479 | kfree(lun_data); |
1468 | out: | 1480 | out: |
1469 | scsi_device_put(sdev); | 1481 | scsi_device_put(sdev); |
1470 | if (sdev->sdev_state == SDEV_CREATED) | 1482 | if (scsi_device_created(sdev)) |
1471 | /* | 1483 | /* |
1472 | * the sdev we used didn't appear in the report luns scan | 1484 | * the sdev we used didn't appear in the report luns scan |
1473 | */ | 1485 | */ |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 7f618ee5ecea..93c28f30bbd7 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -34,6 +34,7 @@ static const struct { | |||
34 | { SDEV_QUIESCE, "quiesce" }, | 34 | { SDEV_QUIESCE, "quiesce" }, |
35 | { SDEV_OFFLINE, "offline" }, | 35 | { SDEV_OFFLINE, "offline" }, |
36 | { SDEV_BLOCK, "blocked" }, | 36 | { SDEV_BLOCK, "blocked" }, |
37 | { SDEV_CREATED_BLOCK, "created-blocked" }, | ||
37 | }; | 38 | }; |
38 | 39 | ||
39 | const char *scsi_device_state_name(enum scsi_device_state state) | 40 | const char *scsi_device_state_name(enum scsi_device_state state) |
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 3117bb106b5d..48ba413f7f6a 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c | |||
@@ -460,7 +460,7 @@ int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag, | |||
460 | 460 | ||
461 | /* TODO: replace with a O(1) alg */ | 461 | /* TODO: replace with a O(1) alg */ |
462 | shost = scsi_host_lookup(host_no); | 462 | shost = scsi_host_lookup(host_no); |
463 | if (IS_ERR(shost)) { | 463 | if (!shost) { |
464 | printk(KERN_ERR "Could not find host no %d\n", host_no); | 464 | printk(KERN_ERR "Could not find host no %d\n", host_no); |
465 | return -EINVAL; | 465 | return -EINVAL; |
466 | } | 466 | } |
@@ -550,7 +550,7 @@ int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result) | |||
550 | dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); | 550 | dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); |
551 | 551 | ||
552 | shost = scsi_host_lookup(host_no); | 552 | shost = scsi_host_lookup(host_no); |
553 | if (IS_ERR(shost)) { | 553 | if (!shost) { |
554 | printk(KERN_ERR "Could not find host no %d\n", host_no); | 554 | printk(KERN_ERR "Could not find host no %d\n", host_no); |
555 | return err; | 555 | return err; |
556 | } | 556 | } |
@@ -603,7 +603,7 @@ int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result) | |||
603 | dprintk("%d %d%llx\n", host_no, result, (unsigned long long)itn_id); | 603 | dprintk("%d %d%llx\n", host_no, result, (unsigned long long)itn_id); |
604 | 604 | ||
605 | shost = scsi_host_lookup(host_no); | 605 | shost = scsi_host_lookup(host_no); |
606 | if (IS_ERR(shost)) { | 606 | if (!shost) { |
607 | printk(KERN_ERR "Could not find host no %d\n", host_no); | 607 | printk(KERN_ERR "Could not find host no %d\n", host_no); |
608 | return err; | 608 | return err; |
609 | } | 609 | } |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 9168883d0dfe..d5f7653bb94b 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -40,31 +40,7 @@ | |||
40 | 40 | ||
41 | static int fc_queue_work(struct Scsi_Host *, struct work_struct *); | 41 | static int fc_queue_work(struct Scsi_Host *, struct work_struct *); |
42 | static void fc_vport_sched_delete(struct work_struct *work); | 42 | static void fc_vport_sched_delete(struct work_struct *work); |
43 | 43 | static int fc_vport_setup(struct Scsi_Host *shost, int channel, | |
44 | /* | ||
45 | * This is a temporary carrier for creating a vport. It will eventually | ||
46 | * be replaced by a real message definition for sgio or netlink. | ||
47 | * | ||
48 | * fc_vport_identifiers: This set of data contains all elements | ||
49 | * to uniquely identify and instantiate a FC virtual port. | ||
50 | * | ||
51 | * Notes: | ||
52 | * symbolic_name: The driver is to append the symbolic_name string data | ||
53 | * to the symbolic_node_name data that it generates by default. | ||
54 | * the resulting combination should then be registered with the switch. | ||
55 | * It is expected that things like Xen may stuff a VM title into | ||
56 | * this field. | ||
57 | */ | ||
58 | struct fc_vport_identifiers { | ||
59 | u64 node_name; | ||
60 | u64 port_name; | ||
61 | u32 roles; | ||
62 | bool disable; | ||
63 | enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */ | ||
64 | char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN]; | ||
65 | }; | ||
66 | |||
67 | static int fc_vport_create(struct Scsi_Host *shost, int channel, | ||
68 | struct device *pdev, struct fc_vport_identifiers *ids, | 44 | struct device *pdev, struct fc_vport_identifiers *ids, |
69 | struct fc_vport **vport); | 45 | struct fc_vport **vport); |
70 | 46 | ||
@@ -1760,7 +1736,7 @@ store_fc_host_vport_create(struct device *dev, struct device_attribute *attr, | |||
1760 | vid.disable = false; /* always enabled */ | 1736 | vid.disable = false; /* always enabled */ |
1761 | 1737 | ||
1762 | /* we only allow support on Channel 0 !!! */ | 1738 | /* we only allow support on Channel 0 !!! */ |
1763 | stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport); | 1739 | stat = fc_vport_setup(shost, 0, &shost->shost_gendev, &vid, &vport); |
1764 | return stat ? stat : count; | 1740 | return stat ? stat : count; |
1765 | } | 1741 | } |
1766 | static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL, | 1742 | static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL, |
@@ -3103,7 +3079,7 @@ fc_scsi_scan_rport(struct work_struct *work) | |||
3103 | 3079 | ||
3104 | 3080 | ||
3105 | /** | 3081 | /** |
3106 | * fc_vport_create - allocates and creates a FC virtual port. | 3082 | * fc_vport_setup - allocates and creates a FC virtual port. |
3107 | * @shost: scsi host the virtual port is connected to. | 3083 | * @shost: scsi host the virtual port is connected to. |
3108 | * @channel: Channel on shost port connected to. | 3084 | * @channel: Channel on shost port connected to. |
3109 | * @pdev: parent device for vport | 3085 | * @pdev: parent device for vport |
@@ -3118,7 +3094,7 @@ fc_scsi_scan_rport(struct work_struct *work) | |||
3118 | * This routine assumes no locks are held on entry. | 3094 | * This routine assumes no locks are held on entry. |
3119 | */ | 3095 | */ |
3120 | static int | 3096 | static int |
3121 | fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev, | 3097 | fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev, |
3122 | struct fc_vport_identifiers *ids, struct fc_vport **ret_vport) | 3098 | struct fc_vport_identifiers *ids, struct fc_vport **ret_vport) |
3123 | { | 3099 | { |
3124 | struct fc_host_attrs *fc_host = shost_to_fc_host(shost); | 3100 | struct fc_host_attrs *fc_host = shost_to_fc_host(shost); |
@@ -3231,6 +3207,28 @@ delete_vport: | |||
3231 | return error; | 3207 | return error; |
3232 | } | 3208 | } |
3233 | 3209 | ||
3210 | /** | ||
3211 | * fc_vport_create - Admin App or LLDD requests creation of a vport | ||
3212 | * @shost: scsi host the virtual port is connected to. | ||
3213 | * @channel: channel on shost port connected to. | ||
3214 | * @ids: The world wide names, FC4 port roles, etc for | ||
3215 | * the virtual port. | ||
3216 | * | ||
3217 | * Notes: | ||
3218 | * This routine assumes no locks are held on entry. | ||
3219 | */ | ||
3220 | struct fc_vport * | ||
3221 | fc_vport_create(struct Scsi_Host *shost, int channel, | ||
3222 | struct fc_vport_identifiers *ids) | ||
3223 | { | ||
3224 | int stat; | ||
3225 | struct fc_vport *vport; | ||
3226 | |||
3227 | stat = fc_vport_setup(shost, channel, &shost->shost_gendev, | ||
3228 | ids, &vport); | ||
3229 | return stat ? NULL : vport; | ||
3230 | } | ||
3231 | EXPORT_SYMBOL(fc_vport_create); | ||
3234 | 3232 | ||
3235 | /** | 3233 | /** |
3236 | * fc_vport_terminate - Admin App or LLDD requests termination of a vport | 3234 | * fc_vport_terminate - Admin App or LLDD requests termination of a vport |
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 043c3921164f..0ce5f7cdfe2a 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -1361,7 +1361,7 @@ iscsi_tgt_dscvr(struct iscsi_transport *transport, | |||
1361 | return -EINVAL; | 1361 | return -EINVAL; |
1362 | 1362 | ||
1363 | shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no); | 1363 | shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no); |
1364 | if (IS_ERR(shost)) { | 1364 | if (!shost) { |
1365 | printk(KERN_ERR "target discovery could not find host no %u\n", | 1365 | printk(KERN_ERR "target discovery could not find host no %u\n", |
1366 | ev->u.tgt_dscvr.host_no); | 1366 | ev->u.tgt_dscvr.host_no); |
1367 | return -ENODEV; | 1367 | return -ENODEV; |
@@ -1387,7 +1387,7 @@ iscsi_set_host_param(struct iscsi_transport *transport, | |||
1387 | return -ENOSYS; | 1387 | return -ENOSYS; |
1388 | 1388 | ||
1389 | shost = scsi_host_lookup(ev->u.set_host_param.host_no); | 1389 | shost = scsi_host_lookup(ev->u.set_host_param.host_no); |
1390 | if (IS_ERR(shost)) { | 1390 | if (!shost) { |
1391 | printk(KERN_ERR "set_host_param could not find host no %u\n", | 1391 | printk(KERN_ERR "set_host_param could not find host no %u\n", |
1392 | ev->u.set_host_param.host_no); | 1392 | ev->u.set_host_param.host_no); |
1393 | return -ENODEV; | 1393 | return -ENODEV; |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c0cf4acda7de..a7b53be63367 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/blkpg.h> | 47 | #include <linux/blkpg.h> |
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/mutex.h> | 49 | #include <linux/mutex.h> |
50 | #include <linux/string_helpers.h> | ||
50 | #include <asm/uaccess.h> | 51 | #include <asm/uaccess.h> |
51 | 52 | ||
52 | #include <scsi/scsi.h> | 53 | #include <scsi/scsi.h> |
@@ -1433,27 +1434,21 @@ got_data: | |||
1433 | */ | 1434 | */ |
1434 | sector_size = 512; | 1435 | sector_size = 512; |
1435 | } | 1436 | } |
1437 | blk_queue_hardsect_size(sdp->request_queue, sector_size); | ||
1438 | |||
1436 | { | 1439 | { |
1437 | /* | 1440 | char cap_str_2[10], cap_str_10[10]; |
1438 | * The msdos fs needs to know the hardware sector size | 1441 | u64 sz = sdkp->capacity << ffz(~sector_size); |
1439 | * So I have created this table. See ll_rw_blk.c | ||
1440 | * Jacques Gelinas (Jacques@solucorp.qc.ca) | ||
1441 | */ | ||
1442 | int hard_sector = sector_size; | ||
1443 | sector_t sz = (sdkp->capacity/2) * (hard_sector/256); | ||
1444 | struct request_queue *queue = sdp->request_queue; | ||
1445 | sector_t mb = sz; | ||
1446 | 1442 | ||
1447 | blk_queue_hardsect_size(queue, hard_sector); | 1443 | string_get_size(sz, STRING_UNITS_2, cap_str_2, |
1448 | /* avoid 64-bit division on 32-bit platforms */ | 1444 | sizeof(cap_str_2)); |
1449 | sector_div(sz, 625); | 1445 | string_get_size(sz, STRING_UNITS_10, cap_str_10, |
1450 | mb -= sz - 974; | 1446 | sizeof(cap_str_10)); |
1451 | sector_div(mb, 1950); | ||
1452 | 1447 | ||
1453 | sd_printk(KERN_NOTICE, sdkp, | 1448 | sd_printk(KERN_NOTICE, sdkp, |
1454 | "%llu %d-byte hardware sectors (%llu MB)\n", | 1449 | "%llu %d-byte hardware sectors: (%s/%s)\n", |
1455 | (unsigned long long)sdkp->capacity, | 1450 | (unsigned long long)sdkp->capacity, |
1456 | hard_sector, (unsigned long long)mb); | 1451 | sector_size, cap_str_10, cap_str_2); |
1457 | } | 1452 | } |
1458 | 1453 | ||
1459 | /* Rescale capacity to 512-byte units */ | 1454 | /* Rescale capacity to 512-byte units */ |
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 1723d71cbf3f..69ac6e590f1d 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c | |||
@@ -2573,8 +2573,8 @@ static struct pci_driver dc390_driver = { | |||
2573 | static int __init dc390_module_init(void) | 2573 | static int __init dc390_module_init(void) |
2574 | { | 2574 | { |
2575 | if (!disable_clustering) | 2575 | if (!disable_clustering) |
2576 | printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n" | 2576 | printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n"); |
2577 | "\twith \"disable_clustering=1\" and report to maintainers\n"); | 2577 | printk(KERN_INFO " with \"disable_clustering=1\" and report to maintainers\n"); |
2578 | 2578 | ||
2579 | if (tmscsim[0] == -1 || tmscsim[0] > 15) { | 2579 | if (tmscsim[0] == -1 || tmscsim[0] > 15) { |
2580 | tmscsim[0] = 7; | 2580 | tmscsim[0] = 7; |
diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h new file mode 100644 index 000000000000..a3eb2f65b656 --- /dev/null +++ b/include/linux/string_helpers.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef _LINUX_STRING_HELPERS_H_ | ||
2 | #define _LINUX_STRING_HELPERS_H_ | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | |||
6 | /* Descriptions of the types of units to | ||
7 | * print in */ | ||
8 | enum string_size_units { | ||
9 | STRING_UNITS_10, /* use powers of 10^3 (standard SI) */ | ||
10 | STRING_UNITS_2, /* use binary powers of 2^10 */ | ||
11 | }; | ||
12 | |||
13 | int string_get_size(u64 size, enum string_size_units units, | ||
14 | char *buf, int len); | ||
15 | |||
16 | #endif | ||
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 80b2e93c2936..b49e725be039 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h | |||
@@ -42,9 +42,11 @@ enum scsi_device_state { | |||
42 | * originate in the mid-layer) */ | 42 | * originate in the mid-layer) */ |
43 | SDEV_OFFLINE, /* Device offlined (by error handling or | 43 | SDEV_OFFLINE, /* Device offlined (by error handling or |
44 | * user request */ | 44 | * user request */ |
45 | SDEV_BLOCK, /* Device blocked by scsi lld. No scsi | 45 | SDEV_BLOCK, /* Device blocked by scsi lld. No |
46 | * commands from user or midlayer should be issued | 46 | * scsi commands from user or midlayer |
47 | * to the scsi lld. */ | 47 | * should be issued to the scsi |
48 | * lld. */ | ||
49 | SDEV_CREATED_BLOCK, /* same as above but for created devices */ | ||
48 | }; | 50 | }; |
49 | 51 | ||
50 | enum scsi_device_event { | 52 | enum scsi_device_event { |
@@ -384,10 +386,23 @@ static inline unsigned int sdev_id(struct scsi_device *sdev) | |||
384 | #define scmd_id(scmd) sdev_id((scmd)->device) | 386 | #define scmd_id(scmd) sdev_id((scmd)->device) |
385 | #define scmd_channel(scmd) sdev_channel((scmd)->device) | 387 | #define scmd_channel(scmd) sdev_channel((scmd)->device) |
386 | 388 | ||
389 | /* | ||
390 | * checks for positions of the SCSI state machine | ||
391 | */ | ||
387 | static inline int scsi_device_online(struct scsi_device *sdev) | 392 | static inline int scsi_device_online(struct scsi_device *sdev) |
388 | { | 393 | { |
389 | return sdev->sdev_state != SDEV_OFFLINE; | 394 | return sdev->sdev_state != SDEV_OFFLINE; |
390 | } | 395 | } |
396 | static inline int scsi_device_blocked(struct scsi_device *sdev) | ||
397 | { | ||
398 | return sdev->sdev_state == SDEV_BLOCK || | ||
399 | sdev->sdev_state == SDEV_CREATED_BLOCK; | ||
400 | } | ||
401 | static inline int scsi_device_created(struct scsi_device *sdev) | ||
402 | { | ||
403 | return sdev->sdev_state == SDEV_CREATED || | ||
404 | sdev->sdev_state == SDEV_CREATED_BLOCK; | ||
405 | } | ||
391 | 406 | ||
392 | /* accessor functions for the SCSI parameters */ | 407 | /* accessor functions for the SCSI parameters */ |
393 | static inline int scsi_device_sync(struct scsi_device *sdev) | 408 | static inline int scsi_device_sync(struct scsi_device *sdev) |
diff --git a/include/scsi/scsi_netlink.h b/include/scsi/scsi_netlink.h index 8c1470cc8209..536752c40d41 100644 --- a/include/scsi/scsi_netlink.h +++ b/include/scsi/scsi_netlink.h | |||
@@ -22,6 +22,9 @@ | |||
22 | #ifndef SCSI_NETLINK_H | 22 | #ifndef SCSI_NETLINK_H |
23 | #define SCSI_NETLINK_H | 23 | #define SCSI_NETLINK_H |
24 | 24 | ||
25 | #include <linux/netlink.h> | ||
26 | |||
27 | |||
25 | /* | 28 | /* |
26 | * This file intended to be included by both kernel and user space | 29 | * This file intended to be included by both kernel and user space |
27 | */ | 30 | */ |
@@ -55,7 +58,41 @@ struct scsi_nl_hdr { | |||
55 | #define SCSI_NL_TRANSPORT_FC 1 | 58 | #define SCSI_NL_TRANSPORT_FC 1 |
56 | #define SCSI_NL_MAX_TRANSPORTS 2 | 59 | #define SCSI_NL_MAX_TRANSPORTS 2 |
57 | 60 | ||
58 | /* scsi_nl_hdr->msgtype values are defined in each transport */ | 61 | /* Transport-based scsi_nl_hdr->msgtype values are defined in each transport */ |
62 | |||
63 | /* | ||
64 | * GENERIC SCSI scsi_nl_hdr->msgtype Values | ||
65 | */ | ||
66 | /* kernel -> user */ | ||
67 | #define SCSI_NL_SHOST_VENDOR 0x0001 | ||
68 | /* user -> kernel */ | ||
69 | /* SCSI_NL_SHOST_VENDOR msgtype is kernel->user and user->kernel */ | ||
70 | |||
71 | |||
72 | /* | ||
73 | * Message Structures : | ||
74 | */ | ||
75 | |||
76 | /* macro to round up message lengths to 8byte boundary */ | ||
77 | #define SCSI_NL_MSGALIGN(len) (((len) + 7) & ~7) | ||
78 | |||
79 | |||
80 | /* | ||
81 | * SCSI HOST Vendor Unique messages : | ||
82 | * SCSI_NL_SHOST_VENDOR | ||
83 | * | ||
84 | * Note: The Vendor Unique message payload will begin directly after | ||
85 | * this structure, with the length of the payload per vmsg_datalen. | ||
86 | * | ||
87 | * Note: When specifying vendor_id, be sure to read the Vendor Type and ID | ||
88 | * formatting requirements specified below | ||
89 | */ | ||
90 | struct scsi_nl_host_vendor_msg { | ||
91 | struct scsi_nl_hdr snlh; /* must be 1st element ! */ | ||
92 | uint64_t vendor_id; | ||
93 | uint16_t host_no; | ||
94 | uint16_t vmsg_datalen; | ||
95 | } __attribute__((aligned(sizeof(uint64_t)))); | ||
59 | 96 | ||
60 | 97 | ||
61 | /* | 98 | /* |
@@ -83,5 +120,28 @@ struct scsi_nl_hdr { | |||
83 | } | 120 | } |
84 | 121 | ||
85 | 122 | ||
123 | #ifdef __KERNEL__ | ||
124 | |||
125 | #include <scsi/scsi_host.h> | ||
126 | |||
127 | /* Exported Kernel Interfaces */ | ||
128 | int scsi_nl_add_transport(u8 tport, | ||
129 | int (*msg_handler)(struct sk_buff *), | ||
130 | void (*event_handler)(struct notifier_block *, unsigned long, void *)); | ||
131 | void scsi_nl_remove_transport(u8 tport); | ||
132 | |||
133 | int scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt, | ||
134 | int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload, | ||
135 | u32 len, u32 pid), | ||
136 | void (*nlevt_handler)(struct notifier_block *nb, | ||
137 | unsigned long event, void *notify_ptr)); | ||
138 | void scsi_nl_remove_driver(u64 vendor_id); | ||
139 | |||
140 | void scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr); | ||
141 | int scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id, | ||
142 | char *data_buf, u32 data_len); | ||
143 | |||
144 | #endif /* __KERNEL__ */ | ||
145 | |||
86 | #endif /* SCSI_NETLINK_H */ | 146 | #endif /* SCSI_NETLINK_H */ |
87 | 147 | ||
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 878373c32ef7..21018a4df452 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h | |||
@@ -167,6 +167,26 @@ enum fc_tgtid_binding_type { | |||
167 | struct device_attribute dev_attr_vport_##_name = \ | 167 | struct device_attribute dev_attr_vport_##_name = \ |
168 | __ATTR(_name,_mode,_show,_store) | 168 | __ATTR(_name,_mode,_show,_store) |
169 | 169 | ||
170 | /* | ||
171 | * fc_vport_identifiers: This set of data contains all elements | ||
172 | * to uniquely identify and instantiate a FC virtual port. | ||
173 | * | ||
174 | * Notes: | ||
175 | * symbolic_name: The driver is to append the symbolic_name string data | ||
176 | * to the symbolic_node_name data that it generates by default. | ||
177 | * the resulting combination should then be registered with the switch. | ||
178 | * It is expected that things like Xen may stuff a VM title into | ||
179 | * this field. | ||
180 | */ | ||
181 | #define FC_VPORT_SYMBOLIC_NAMELEN 64 | ||
182 | struct fc_vport_identifiers { | ||
183 | u64 node_name; | ||
184 | u64 port_name; | ||
185 | u32 roles; | ||
186 | bool disable; | ||
187 | enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */ | ||
188 | char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN]; | ||
189 | }; | ||
170 | 190 | ||
171 | /* | 191 | /* |
172 | * FC Virtual Port Attributes | 192 | * FC Virtual Port Attributes |
@@ -197,7 +217,6 @@ struct device_attribute dev_attr_vport_##_name = \ | |||
197 | * managed by the transport w/o driver interaction. | 217 | * managed by the transport w/o driver interaction. |
198 | */ | 218 | */ |
199 | 219 | ||
200 | #define FC_VPORT_SYMBOLIC_NAMELEN 64 | ||
201 | struct fc_vport { | 220 | struct fc_vport { |
202 | /* Fixed Attributes */ | 221 | /* Fixed Attributes */ |
203 | 222 | ||
@@ -732,6 +751,8 @@ void fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number, | |||
732 | * be sure to read the Vendor Type and ID formatting requirements | 751 | * be sure to read the Vendor Type and ID formatting requirements |
733 | * specified in scsi_netlink.h | 752 | * specified in scsi_netlink.h |
734 | */ | 753 | */ |
754 | struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel, | ||
755 | struct fc_vport_identifiers *); | ||
735 | int fc_vport_terminate(struct fc_vport *vport); | 756 | int fc_vport_terminate(struct fc_vport *vport); |
736 | 757 | ||
737 | #endif /* SCSI_TRANSPORT_FC_H */ | 758 | #endif /* SCSI_TRANSPORT_FC_H */ |
diff --git a/lib/Makefile b/lib/Makefile index 3b1f94bbe9de..44001af76a7d 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
@@ -19,7 +19,8 @@ lib-$(CONFIG_SMP) += cpumask.o | |||
19 | lib-y += kobject.o kref.o klist.o | 19 | lib-y += kobject.o kref.o klist.o |
20 | 20 | ||
21 | obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ | 21 | obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ |
22 | bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o | 22 | bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \ |
23 | string_helpers.o | ||
23 | 24 | ||
24 | ifeq ($(CONFIG_DEBUG_KOBJECT),y) | 25 | ifeq ($(CONFIG_DEBUG_KOBJECT),y) |
25 | CFLAGS_kobject.o += -DDEBUG | 26 | CFLAGS_kobject.o += -DDEBUG |
diff --git a/lib/string_helpers.c b/lib/string_helpers.c new file mode 100644 index 000000000000..8347925030ff --- /dev/null +++ b/lib/string_helpers.c | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Helpers for formatting and printing strings | ||
3 | * | ||
4 | * Copyright 31 August 2008 James Bottomley | ||
5 | */ | ||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/math64.h> | ||
8 | #include <linux/module.h> | ||
9 | #include <linux/string_helpers.h> | ||
10 | |||
11 | /** | ||
12 | * string_get_size - get the size in the specified units | ||
13 | * @size: The size to be converted | ||
14 | * @units: units to use (powers of 1000 or 1024) | ||
15 | * @buf: buffer to format to | ||
16 | * @len: length of buffer | ||
17 | * | ||
18 | * This function returns a string formatted to 3 significant figures | ||
19 | * giving the size in the required units. Returns 0 on success or | ||
20 | * error on failure. @buf is always zero terminated. | ||
21 | * | ||
22 | */ | ||
23 | int string_get_size(u64 size, const enum string_size_units units, | ||
24 | char *buf, int len) | ||
25 | { | ||
26 | const char *units_10[] = { "B", "KB", "MB", "GB", "TB", "PB", | ||
27 | "EB", "ZB", "YB", NULL}; | ||
28 | const char *units_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", | ||
29 | "EiB", "ZiB", "YiB", NULL }; | ||
30 | const char **units_str[] = { | ||
31 | [STRING_UNITS_10] = units_10, | ||
32 | [STRING_UNITS_2] = units_2, | ||
33 | }; | ||
34 | const int divisor[] = { | ||
35 | [STRING_UNITS_10] = 1000, | ||
36 | [STRING_UNITS_2] = 1024, | ||
37 | }; | ||
38 | int i, j; | ||
39 | u64 remainder = 0, sf_cap; | ||
40 | char tmp[8]; | ||
41 | |||
42 | tmp[0] = '\0'; | ||
43 | |||
44 | for (i = 0; size > divisor[units] && units_str[units][i]; i++) | ||
45 | remainder = do_div(size, divisor[units]); | ||
46 | |||
47 | sf_cap = size; | ||
48 | for (j = 0; sf_cap*10 < 1000; j++) | ||
49 | sf_cap *= 10; | ||
50 | |||
51 | if (j) { | ||
52 | remainder *= 1000; | ||
53 | do_div(remainder, divisor[units]); | ||
54 | snprintf(tmp, sizeof(tmp), ".%03lld", | ||
55 | (unsigned long long)remainder); | ||
56 | tmp[j+1] = '\0'; | ||
57 | } | ||
58 | |||
59 | snprintf(buf, len, "%lld%s%s", (unsigned long long)size, | ||
60 | tmp, units_str[units][i]); | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | EXPORT_SYMBOL(string_get_size); | ||