diff options
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 29 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ccw.c | 10 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 25 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 1 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 25 |
7 files changed, 63 insertions, 31 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index e17b4d58a9f6..6fed4a532ca3 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -1299,13 +1299,10 @@ struct zfcp_port * | |||
1299 | zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, | 1299 | zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, |
1300 | u32 d_id) | 1300 | u32 d_id) |
1301 | { | 1301 | { |
1302 | struct zfcp_port *port, *tmp_port; | 1302 | struct zfcp_port *port; |
1303 | int check_wwpn; | 1303 | int check_wwpn; |
1304 | scsi_id_t scsi_id; | ||
1305 | int found; | ||
1306 | 1304 | ||
1307 | check_wwpn = !(status & ZFCP_STATUS_PORT_NO_WWPN); | 1305 | check_wwpn = !(status & ZFCP_STATUS_PORT_NO_WWPN); |
1308 | |||
1309 | /* | 1306 | /* |
1310 | * check that there is no port with this WWPN already in list | 1307 | * check that there is no port with this WWPN already in list |
1311 | */ | 1308 | */ |
@@ -1368,7 +1365,7 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, | |||
1368 | } else { | 1365 | } else { |
1369 | snprintf(port->sysfs_device.bus_id, | 1366 | snprintf(port->sysfs_device.bus_id, |
1370 | BUS_ID_SIZE, "0x%016llx", wwpn); | 1367 | BUS_ID_SIZE, "0x%016llx", wwpn); |
1371 | port->sysfs_device.parent = &adapter->ccw_device->dev; | 1368 | port->sysfs_device.parent = &adapter->ccw_device->dev; |
1372 | } | 1369 | } |
1373 | port->sysfs_device.release = zfcp_sysfs_port_release; | 1370 | port->sysfs_device.release = zfcp_sysfs_port_release; |
1374 | dev_set_drvdata(&port->sysfs_device, port); | 1371 | dev_set_drvdata(&port->sysfs_device, port); |
@@ -1388,24 +1385,8 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, | |||
1388 | 1385 | ||
1389 | zfcp_port_get(port); | 1386 | zfcp_port_get(port); |
1390 | 1387 | ||
1391 | scsi_id = 1; | ||
1392 | found = 0; | ||
1393 | write_lock_irq(&zfcp_data.config_lock); | 1388 | write_lock_irq(&zfcp_data.config_lock); |
1394 | list_for_each_entry(tmp_port, &adapter->port_list_head, list) { | 1389 | list_add_tail(&port->list, &adapter->port_list_head); |
1395 | if (atomic_test_mask(ZFCP_STATUS_PORT_NO_SCSI_ID, | ||
1396 | &tmp_port->status)) | ||
1397 | continue; | ||
1398 | if (tmp_port->scsi_id != scsi_id) { | ||
1399 | found = 1; | ||
1400 | break; | ||
1401 | } | ||
1402 | scsi_id++; | ||
1403 | } | ||
1404 | port->scsi_id = scsi_id; | ||
1405 | if (found) | ||
1406 | list_add_tail(&port->list, &tmp_port->list); | ||
1407 | else | ||
1408 | list_add_tail(&port->list, &adapter->port_list_head); | ||
1409 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); | 1390 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); |
1410 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); | 1391 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); |
1411 | if (d_id == ZFCP_DID_DIRECTORY_SERVICE) | 1392 | if (d_id == ZFCP_DID_DIRECTORY_SERVICE) |
@@ -1422,11 +1403,15 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, | |||
1422 | void | 1403 | void |
1423 | zfcp_port_dequeue(struct zfcp_port *port) | 1404 | zfcp_port_dequeue(struct zfcp_port *port) |
1424 | { | 1405 | { |
1406 | struct fc_port *rport; | ||
1407 | |||
1425 | zfcp_port_wait(port); | 1408 | zfcp_port_wait(port); |
1426 | write_lock_irq(&zfcp_data.config_lock); | 1409 | write_lock_irq(&zfcp_data.config_lock); |
1427 | list_del(&port->list); | 1410 | list_del(&port->list); |
1428 | port->adapter->ports--; | 1411 | port->adapter->ports--; |
1429 | write_unlock_irq(&zfcp_data.config_lock); | 1412 | write_unlock_irq(&zfcp_data.config_lock); |
1413 | if (port->rport) | ||
1414 | fc_remote_port_delete(rport); | ||
1430 | zfcp_adapter_put(port->adapter); | 1415 | zfcp_adapter_put(port->adapter); |
1431 | zfcp_sysfs_port_remove_files(&port->sysfs_device, | 1416 | zfcp_sysfs_port_remove_files(&port->sysfs_device, |
1432 | atomic_read(&port->status)); | 1417 | atomic_read(&port->status)); |
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 0fc46381fc22..3c65aedaa97f 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -202,9 +202,19 @@ static int | |||
202 | zfcp_ccw_set_offline(struct ccw_device *ccw_device) | 202 | zfcp_ccw_set_offline(struct ccw_device *ccw_device) |
203 | { | 203 | { |
204 | struct zfcp_adapter *adapter; | 204 | struct zfcp_adapter *adapter; |
205 | struct zfcp_port *port; | ||
206 | struct fc_port *rport; | ||
205 | 207 | ||
206 | down(&zfcp_data.config_sema); | 208 | down(&zfcp_data.config_sema); |
207 | adapter = dev_get_drvdata(&ccw_device->dev); | 209 | adapter = dev_get_drvdata(&ccw_device->dev); |
210 | /* might be racy, but we cannot take config_lock due to the fact that | ||
211 | fc_remote_port_delete might sleep */ | ||
212 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
213 | if (port->rport) { | ||
214 | rport = port->rport; | ||
215 | port->rport = NULL; | ||
216 | fc_remote_port_delete(rport); | ||
217 | } | ||
208 | zfcp_erp_adapter_shutdown(adapter, 0); | 218 | zfcp_erp_adapter_shutdown(adapter, 0); |
209 | zfcp_erp_wait(adapter); | 219 | zfcp_erp_wait(adapter); |
210 | zfcp_adapter_scsi_unregister(adapter); | 220 | zfcp_adapter_scsi_unregister(adapter); |
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 4103b5be7683..455e902533a9 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -906,6 +906,7 @@ struct zfcp_adapter { | |||
906 | */ | 906 | */ |
907 | struct zfcp_port { | 907 | struct zfcp_port { |
908 | struct device sysfs_device; /* sysfs device */ | 908 | struct device sysfs_device; /* sysfs device */ |
909 | struct fc_rport *rport; /* rport of fc transport class */ | ||
909 | struct list_head list; /* list of remote ports */ | 910 | struct list_head list; /* list of remote ports */ |
910 | atomic_t refcount; /* reference count */ | 911 | atomic_t refcount; /* reference count */ |
911 | wait_queue_head_t remove_wq; /* can be used to wait for | 912 | wait_queue_head_t remove_wq; /* can be used to wait for |
@@ -916,7 +917,6 @@ struct zfcp_port { | |||
916 | list */ | 917 | list */ |
917 | u32 units; /* # of logical units in list */ | 918 | u32 units; /* # of logical units in list */ |
918 | atomic_t status; /* status of this remote port */ | 919 | atomic_t status; /* status of this remote port */ |
919 | scsi_id_t scsi_id; /* own SCSI ID */ | ||
920 | wwn_t wwnn; /* WWNN if known */ | 920 | wwn_t wwnn; /* WWNN if known */ |
921 | wwn_t wwpn; /* WWPN */ | 921 | wwn_t wwpn; /* WWPN */ |
922 | fc_id_t d_id; /* D_ID */ | 922 | fc_id_t d_id; /* D_ID */ |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 0cf31f7d1c0f..cb4f612550ba 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -3360,13 +3360,32 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, | |||
3360 | if ((result == ZFCP_ERP_SUCCEEDED) | 3360 | if ((result == ZFCP_ERP_SUCCEEDED) |
3361 | && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY, | 3361 | && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY, |
3362 | &unit->status)) | 3362 | &unit->status)) |
3363 | && (!unit->device)) | 3363 | && !unit->device |
3364 | scsi_add_device(unit->port->adapter->scsi_host, 0, | 3364 | && port->rport) |
3365 | unit->port->scsi_id, unit->scsi_lun); | 3365 | scsi_add_device(port->adapter->scsi_host, 0, |
3366 | port->rport->scsi_target_id, | ||
3367 | unit->scsi_lun); | ||
3366 | zfcp_unit_put(unit); | 3368 | zfcp_unit_put(unit); |
3367 | break; | 3369 | break; |
3368 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 3370 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
3369 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 3371 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
3372 | if ((result == ZFCP_ERP_SUCCEEDED) | ||
3373 | && !atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, | ||
3374 | &port->status) | ||
3375 | && !port->rport) { | ||
3376 | struct fc_rport_identifiers ids; | ||
3377 | ids.node_name = port->wwnn; | ||
3378 | ids.port_name = port->wwpn; | ||
3379 | ids.port_id = port->d_id; | ||
3380 | ids.roles = FC_RPORT_ROLE_FCP_TARGET; | ||
3381 | port->rport = | ||
3382 | fc_remote_port_add(adapter->scsi_host, 0, &ids); | ||
3383 | if (!port->rport) | ||
3384 | ZFCP_LOG_NORMAL("failed registration of rport" | ||
3385 | "(adapter %s, wwpn=0x%016Lx)\n", | ||
3386 | zfcp_get_busid_by_port(port), | ||
3387 | port->wwpn); | ||
3388 | } | ||
3370 | zfcp_port_put(port); | 3389 | zfcp_port_put(port); |
3371 | break; | 3390 | break; |
3372 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 3391 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 42df7e57eeae..cd98a2de9f8f 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -143,6 +143,8 @@ extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *, | |||
143 | struct scsi_cmnd *, struct timer_list *); | 143 | struct scsi_cmnd *, struct timer_list *); |
144 | extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *, | 144 | extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *, |
145 | struct timer_list *); | 145 | struct timer_list *); |
146 | extern void zfcp_set_fc_host_attrs(struct zfcp_adapter *); | ||
147 | extern void zfcp_set_fc_rport_attrs(struct zfcp_port *); | ||
146 | extern struct scsi_transport_template *zfcp_transport_template; | 148 | extern struct scsi_transport_template *zfcp_transport_template; |
147 | extern struct fc_function_template zfcp_transport_functions; | 149 | extern struct fc_function_template zfcp_transport_functions; |
148 | 150 | ||
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 0d9f20edc490..c007b6424e74 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -2062,6 +2062,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) | |||
2062 | zfcp_erp_adapter_shutdown(adapter, 0); | 2062 | zfcp_erp_adapter_shutdown(adapter, 0); |
2063 | return -EIO; | 2063 | return -EIO; |
2064 | } | 2064 | } |
2065 | zfcp_set_fc_host_attrs(adapter); | ||
2065 | return 0; | 2066 | return 0; |
2066 | } | 2067 | } |
2067 | 2068 | ||
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index b61d309352c3..31a76065cf28 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -389,7 +389,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id, | |||
389 | struct zfcp_unit *unit, *retval = NULL; | 389 | struct zfcp_unit *unit, *retval = NULL; |
390 | 390 | ||
391 | list_for_each_entry(port, &adapter->port_list_head, list) { | 391 | list_for_each_entry(port, &adapter->port_list_head, list) { |
392 | if (id != port->scsi_id) | 392 | if (!port->rport || (id != port->rport->scsi_target_id)) |
393 | continue; | 393 | continue; |
394 | list_for_each_entry(unit, &port->unit_list_head, list) { | 394 | list_for_each_entry(unit, &port->unit_list_head, list) { |
395 | if (lun == unit->scsi_lun) { | 395 | if (lun == unit->scsi_lun) { |
@@ -408,7 +408,7 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id) | |||
408 | struct zfcp_port *port; | 408 | struct zfcp_port *port; |
409 | 409 | ||
410 | list_for_each_entry(port, &adapter->port_list_head, list) { | 410 | list_for_each_entry(port, &adapter->port_list_head, list) { |
411 | if (id == port->scsi_id) | 411 | if (port->rport && (id == port->rport->scsi_target_id)) |
412 | return port; | 412 | return port; |
413 | } | 413 | } |
414 | return (struct zfcp_port *) NULL; | 414 | return (struct zfcp_port *) NULL; |
@@ -634,7 +634,6 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) | |||
634 | { | 634 | { |
635 | int retval; | 635 | int retval; |
636 | struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata; | 636 | struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata; |
637 | struct Scsi_Host *scsi_host = scpnt->device->host; | ||
638 | 637 | ||
639 | if (!unit) { | 638 | if (!unit) { |
640 | ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n"); | 639 | ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n"); |
@@ -729,7 +728,6 @@ zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt) | |||
729 | { | 728 | { |
730 | int retval = 0; | 729 | int retval = 0; |
731 | struct zfcp_unit *unit; | 730 | struct zfcp_unit *unit; |
732 | struct Scsi_Host *scsi_host = scpnt->device->host; | ||
733 | 731 | ||
734 | unit = (struct zfcp_unit *) scpnt->device->hostdata; | 732 | unit = (struct zfcp_unit *) scpnt->device->hostdata; |
735 | ZFCP_LOG_NORMAL("bus reset because of problems with " | 733 | ZFCP_LOG_NORMAL("bus reset because of problems with " |
@@ -753,7 +751,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) | |||
753 | { | 751 | { |
754 | int retval = 0; | 752 | int retval = 0; |
755 | struct zfcp_unit *unit; | 753 | struct zfcp_unit *unit; |
756 | struct Scsi_Host *scsi_host = scpnt->device->host; | ||
757 | 754 | ||
758 | unit = (struct zfcp_unit *) scpnt->device->hostdata; | 755 | unit = (struct zfcp_unit *) scpnt->device->hostdata; |
759 | ZFCP_LOG_NORMAL("host reset because of problems with " | 756 | ZFCP_LOG_NORMAL("host reset because of problems with " |
@@ -833,6 +830,7 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) | |||
833 | shost = adapter->scsi_host; | 830 | shost = adapter->scsi_host; |
834 | if (!shost) | 831 | if (!shost) |
835 | return; | 832 | return; |
833 | fc_remove_host(shost); | ||
836 | scsi_remove_host(shost); | 834 | scsi_remove_host(shost); |
837 | scsi_host_put(shost); | 835 | scsi_host_put(shost); |
838 | adapter->scsi_host = NULL; | 836 | adapter->scsi_host = NULL; |
@@ -906,6 +904,18 @@ zfcp_get_node_name(struct scsi_target *starget) | |||
906 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 904 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
907 | } | 905 | } |
908 | 906 | ||
907 | void | ||
908 | zfcp_set_fc_host_attrs(struct zfcp_adapter *adapter) | ||
909 | { | ||
910 | struct Scsi_Host *shost = adapter->scsi_host; | ||
911 | |||
912 | fc_host_node_name(shost) = adapter->wwnn; | ||
913 | fc_host_port_name(shost) = adapter->wwpn; | ||
914 | strncpy(fc_host_serial_number(shost), adapter->serial_number, | ||
915 | min(FC_SERIAL_NUMBER_SIZE, 32)); | ||
916 | fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; | ||
917 | } | ||
918 | |||
909 | struct fc_function_template zfcp_transport_functions = { | 919 | struct fc_function_template zfcp_transport_functions = { |
910 | .get_starget_port_id = zfcp_get_port_id, | 920 | .get_starget_port_id = zfcp_get_port_id, |
911 | .get_starget_port_name = zfcp_get_port_name, | 921 | .get_starget_port_name = zfcp_get_port_name, |
@@ -913,6 +923,11 @@ struct fc_function_template zfcp_transport_functions = { | |||
913 | .show_starget_port_id = 1, | 923 | .show_starget_port_id = 1, |
914 | .show_starget_port_name = 1, | 924 | .show_starget_port_name = 1, |
915 | .show_starget_node_name = 1, | 925 | .show_starget_node_name = 1, |
926 | .show_rport_supported_classes = 1, | ||
927 | .show_host_node_name = 1, | ||
928 | .show_host_port_name = 1, | ||
929 | .show_host_supported_classes = 1, | ||
930 | .show_host_serial_number = 1, | ||
916 | }; | 931 | }; |
917 | 932 | ||
918 | /** | 933 | /** |