aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/scsi/zfcp_aux.c29
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c10
-rw-r--r--drivers/s390/scsi/zfcp_def.h2
-rw-r--r--drivers/s390/scsi/zfcp_erp.c25
-rw-r--r--drivers/s390/scsi/zfcp_ext.h2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c1
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c25
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 *
1299zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, 1299zfcp_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,
1422void 1403void
1423zfcp_port_dequeue(struct zfcp_port *port) 1404zfcp_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
202zfcp_ccw_set_offline(struct ccw_device *ccw_device) 202zfcp_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 */
907struct zfcp_port { 907struct 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 *);
144extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *, 144extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
145 struct timer_list *); 145 struct timer_list *);
146extern void zfcp_set_fc_host_attrs(struct zfcp_adapter *);
147extern void zfcp_set_fc_rport_attrs(struct zfcp_port *);
146extern struct scsi_transport_template *zfcp_transport_template; 148extern struct scsi_transport_template *zfcp_transport_template;
147extern struct fc_function_template zfcp_transport_functions; 149extern 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
907void
908zfcp_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
909struct fc_function_template zfcp_transport_functions = { 919struct 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/**