diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_aux.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 149 |
1 files changed, 31 insertions, 118 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 90abfd06ed55..3b56220fb900 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 | dev_set_name(&unit->sysfs_device, "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,8 @@ 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 | dev_set_name(&port->sysfs_device, "0x%016llx", wwpn); |
661 | switch (d_id) { | 614 | port->sysfs_device.parent = &adapter->ccw_device->dev; |
662 | case ZFCP_DID_DIRECTORY_SERVICE: | ||
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 | 615 | ||
689 | port->sysfs_device.release = zfcp_sysfs_port_release; | 616 | port->sysfs_device.release = zfcp_sysfs_port_release; |
690 | dev_set_drvdata(&port->sysfs_device, port); | 617 | dev_set_drvdata(&port->sysfs_device, port); |
@@ -700,12 +627,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, | |||
700 | if (device_register(&port->sysfs_device)) | 627 | if (device_register(&port->sysfs_device)) |
701 | goto err_out_free; | 628 | goto err_out_free; |
702 | 629 | ||
703 | if (status & ZFCP_STATUS_PORT_WKA) | 630 | retval = sysfs_create_group(&port->sysfs_device.kobj, |
704 | retval = sysfs_create_group(&port->sysfs_device.kobj, | 631 | &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 | 632 | ||
710 | if (retval) { | 633 | if (retval) { |
711 | device_unregister(&port->sysfs_device); | 634 | device_unregister(&port->sysfs_device); |
@@ -718,10 +641,6 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, | |||
718 | list_add_tail(&port->list, &adapter->port_list_head); | 641 | list_add_tail(&port->list, &adapter->port_list_head); |
719 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); | 642 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); |
720 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); | 643 | 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 | 644 | ||
726 | write_unlock_irq(&zfcp_data.config_lock); | 645 | write_unlock_irq(&zfcp_data.config_lock); |
727 | 646 | ||
@@ -740,21 +659,15 @@ err_out: | |||
740 | */ | 659 | */ |
741 | void zfcp_port_dequeue(struct zfcp_port *port) | 660 | void zfcp_port_dequeue(struct zfcp_port *port) |
742 | { | 661 | { |
743 | zfcp_port_wait(port); | 662 | wait_event(port->remove_wq, atomic_read(&port->refcount) == 0); |
744 | write_lock_irq(&zfcp_data.config_lock); | 663 | write_lock_irq(&zfcp_data.config_lock); |
745 | list_del(&port->list); | 664 | list_del(&port->list); |
746 | port->adapter->ports--; | ||
747 | write_unlock_irq(&zfcp_data.config_lock); | 665 | write_unlock_irq(&zfcp_data.config_lock); |
748 | if (port->rport) | 666 | if (port->rport) |
749 | fc_remote_port_delete(port->rport); | 667 | fc_remote_port_delete(port->rport); |
750 | port->rport = NULL; | 668 | port->rport = NULL; |
751 | zfcp_adapter_put(port->adapter); | 669 | zfcp_adapter_put(port->adapter); |
752 | if (atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA) | 670 | 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); | 671 | device_unregister(&port->sysfs_device); |
759 | } | 672 | } |
760 | 673 | ||