diff options
Diffstat (limited to 'drivers')
| -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 | /** |
