Commit 3859f6a2 authored by Andreas Herrmann's avatar Andreas Herrmann Committed by Linus Torvalds

[PATCH] zfcp: add rports to enable scsi_add_device to work again

This patch fixes a severe problem with 2.6.13-rc7.

Due to recent SCSI changes it is not possible to add any LUNs to the zfcp
device driver anymore.  With registration of remote ports this is fixed.
Signed-off-by: default avatarAndreas Herrmann <aherrman@de.ibm.com>
Acked-by: default avatarJames Bottomley <jejb@steeleye.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 729d70f5
...@@ -1299,13 +1299,10 @@ struct zfcp_port * ...@@ -1299,13 +1299,10 @@ struct zfcp_port *
zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
u32 d_id) u32 d_id)
{ {
struct zfcp_port *port, *tmp_port; struct zfcp_port *port;
int check_wwpn; int check_wwpn;
scsi_id_t scsi_id;
int found;
check_wwpn = !(status & ZFCP_STATUS_PORT_NO_WWPN); check_wwpn = !(status & ZFCP_STATUS_PORT_NO_WWPN);
/* /*
* check that there is no port with this WWPN already in list * check that there is no port with this WWPN already in list
*/ */
...@@ -1368,7 +1365,7 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, ...@@ -1368,7 +1365,7 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
} else { } else {
snprintf(port->sysfs_device.bus_id, snprintf(port->sysfs_device.bus_id,
BUS_ID_SIZE, "0x%016llx", wwpn); BUS_ID_SIZE, "0x%016llx", wwpn);
port->sysfs_device.parent = &adapter->ccw_device->dev; port->sysfs_device.parent = &adapter->ccw_device->dev;
} }
port->sysfs_device.release = zfcp_sysfs_port_release; port->sysfs_device.release = zfcp_sysfs_port_release;
dev_set_drvdata(&port->sysfs_device, port); dev_set_drvdata(&port->sysfs_device, port);
...@@ -1388,24 +1385,8 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, ...@@ -1388,24 +1385,8 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
zfcp_port_get(port); zfcp_port_get(port);
scsi_id = 1;
found = 0;
write_lock_irq(&zfcp_data.config_lock); write_lock_irq(&zfcp_data.config_lock);
list_for_each_entry(tmp_port, &adapter->port_list_head, list) { list_add_tail(&port->list, &adapter->port_list_head);
if (atomic_test_mask(ZFCP_STATUS_PORT_NO_SCSI_ID,
&tmp_port->status))
continue;
if (tmp_port->scsi_id != scsi_id) {
found = 1;
break;
}
scsi_id++;
}
port->scsi_id = scsi_id;
if (found)
list_add_tail(&port->list, &tmp_port->list);
else
list_add_tail(&port->list, &adapter->port_list_head);
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
if (d_id == ZFCP_DID_DIRECTORY_SERVICE) if (d_id == ZFCP_DID_DIRECTORY_SERVICE)
...@@ -1422,11 +1403,15 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, ...@@ -1422,11 +1403,15 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
void void
zfcp_port_dequeue(struct zfcp_port *port) zfcp_port_dequeue(struct zfcp_port *port)
{ {
struct fc_port *rport;
zfcp_port_wait(port); zfcp_port_wait(port);
write_lock_irq(&zfcp_data.config_lock); write_lock_irq(&zfcp_data.config_lock);
list_del(&port->list); list_del(&port->list);
port->adapter->ports--; port->adapter->ports--;
write_unlock_irq(&zfcp_data.config_lock); write_unlock_irq(&zfcp_data.config_lock);
if (port->rport)
fc_remote_port_delete(rport);
zfcp_adapter_put(port->adapter); zfcp_adapter_put(port->adapter);
zfcp_sysfs_port_remove_files(&port->sysfs_device, zfcp_sysfs_port_remove_files(&port->sysfs_device,
atomic_read(&port->status)); atomic_read(&port->status));
......
...@@ -202,9 +202,19 @@ static int ...@@ -202,9 +202,19 @@ static int
zfcp_ccw_set_offline(struct ccw_device *ccw_device) zfcp_ccw_set_offline(struct ccw_device *ccw_device)
{ {
struct zfcp_adapter *adapter; struct zfcp_adapter *adapter;
struct zfcp_port *port;
struct fc_port *rport;
down(&zfcp_data.config_sema); down(&zfcp_data.config_sema);
adapter = dev_get_drvdata(&ccw_device->dev); adapter = dev_get_drvdata(&ccw_device->dev);
/* might be racy, but we cannot take config_lock due to the fact that
fc_remote_port_delete might sleep */
list_for_each_entry(port, &adapter->port_list_head, list)
if (port->rport) {
rport = port->rport;
port->rport = NULL;
fc_remote_port_delete(rport);
}
zfcp_erp_adapter_shutdown(adapter, 0); zfcp_erp_adapter_shutdown(adapter, 0);
zfcp_erp_wait(adapter); zfcp_erp_wait(adapter);
zfcp_adapter_scsi_unregister(adapter); zfcp_adapter_scsi_unregister(adapter);
......
...@@ -906,6 +906,7 @@ struct zfcp_adapter { ...@@ -906,6 +906,7 @@ struct zfcp_adapter {
*/ */
struct zfcp_port { struct zfcp_port {
struct device sysfs_device; /* sysfs device */ struct device sysfs_device; /* sysfs device */
struct fc_rport *rport; /* rport of fc transport class */
struct list_head list; /* list of remote ports */ struct list_head list; /* list of remote ports */
atomic_t refcount; /* reference count */ atomic_t refcount; /* reference count */
wait_queue_head_t remove_wq; /* can be used to wait for wait_queue_head_t remove_wq; /* can be used to wait for
...@@ -916,7 +917,6 @@ struct zfcp_port { ...@@ -916,7 +917,6 @@ struct zfcp_port {
list */ list */
u32 units; /* # of logical units in list */ u32 units; /* # of logical units in list */
atomic_t status; /* status of this remote port */ atomic_t status; /* status of this remote port */
scsi_id_t scsi_id; /* own SCSI ID */
wwn_t wwnn; /* WWNN if known */ wwn_t wwnn; /* WWNN if known */
wwn_t wwpn; /* WWPN */ wwn_t wwpn; /* WWPN */
fc_id_t d_id; /* D_ID */ fc_id_t d_id; /* D_ID */
......
...@@ -3360,13 +3360,32 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, ...@@ -3360,13 +3360,32 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
if ((result == ZFCP_ERP_SUCCEEDED) if ((result == ZFCP_ERP_SUCCEEDED)
&& (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY, && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY,
&unit->status)) &unit->status))
&& (!unit->device)) && !unit->device
scsi_add_device(unit->port->adapter->scsi_host, 0, && port->rport)
unit->port->scsi_id, unit->scsi_lun); scsi_add_device(port->adapter->scsi_host, 0,
port->rport->scsi_target_id,
unit->scsi_lun);
zfcp_unit_put(unit); zfcp_unit_put(unit);
break; break;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
case ZFCP_ERP_ACTION_REOPEN_PORT: case ZFCP_ERP_ACTION_REOPEN_PORT:
if ((result == ZFCP_ERP_SUCCEEDED)
&& !atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN,
&port->status)
&& !port->rport) {
struct fc_rport_identifiers ids;
ids.node_name = port->wwnn;
ids.port_name = port->wwpn;
ids.port_id = port->d_id;
ids.roles = FC_RPORT_ROLE_FCP_TARGET;
port->rport =
fc_remote_port_add(adapter->scsi_host, 0, &ids);
if (!port->rport)
ZFCP_LOG_NORMAL("failed registration of rport"
"(adapter %s, wwpn=0x%016Lx)\n",
zfcp_get_busid_by_port(port),
port->wwpn);
}
zfcp_port_put(port); zfcp_port_put(port);
break; break;
case ZFCP_ERP_ACTION_REOPEN_ADAPTER: case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
......
...@@ -143,6 +143,8 @@ extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *, ...@@ -143,6 +143,8 @@ extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *,
struct scsi_cmnd *, struct timer_list *); struct scsi_cmnd *, struct timer_list *);
extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *, extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
struct timer_list *); struct timer_list *);
extern void zfcp_set_fc_host_attrs(struct zfcp_adapter *);
extern void zfcp_set_fc_rport_attrs(struct zfcp_port *);
extern struct scsi_transport_template *zfcp_transport_template; extern struct scsi_transport_template *zfcp_transport_template;
extern struct fc_function_template zfcp_transport_functions; extern struct fc_function_template zfcp_transport_functions;
......
...@@ -2062,6 +2062,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) ...@@ -2062,6 +2062,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
zfcp_erp_adapter_shutdown(adapter, 0); zfcp_erp_adapter_shutdown(adapter, 0);
return -EIO; return -EIO;
} }
zfcp_set_fc_host_attrs(adapter);
return 0; return 0;
} }
......
...@@ -389,7 +389,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id, ...@@ -389,7 +389,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
struct zfcp_unit *unit, *retval = NULL; struct zfcp_unit *unit, *retval = NULL;
list_for_each_entry(port, &adapter->port_list_head, list) { list_for_each_entry(port, &adapter->port_list_head, list) {
if (id != port->scsi_id) if (!port->rport || (id != port->rport->scsi_target_id))
continue; continue;
list_for_each_entry(unit, &port->unit_list_head, list) { list_for_each_entry(unit, &port->unit_list_head, list) {
if (lun == unit->scsi_lun) { if (lun == unit->scsi_lun) {
...@@ -408,7 +408,7 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id) ...@@ -408,7 +408,7 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
struct zfcp_port *port; struct zfcp_port *port;
list_for_each_entry(port, &adapter->port_list_head, list) { list_for_each_entry(port, &adapter->port_list_head, list) {
if (id == port->scsi_id) if (port->rport && (id == port->rport->scsi_target_id))
return port; return port;
} }
return (struct zfcp_port *) NULL; return (struct zfcp_port *) NULL;
...@@ -634,7 +634,6 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) ...@@ -634,7 +634,6 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
{ {
int retval; int retval;
struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata; struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
struct Scsi_Host *scsi_host = scpnt->device->host;
if (!unit) { if (!unit) {
ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n"); 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,7 +728,6 @@ zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
{ {
int retval = 0; int retval = 0;
struct zfcp_unit *unit; struct zfcp_unit *unit;
struct Scsi_Host *scsi_host = scpnt->device->host;
unit = (struct zfcp_unit *) scpnt->device->hostdata; unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_NORMAL("bus reset because of problems with " ZFCP_LOG_NORMAL("bus reset because of problems with "
...@@ -753,7 +751,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) ...@@ -753,7 +751,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
{ {
int retval = 0; int retval = 0;
struct zfcp_unit *unit; struct zfcp_unit *unit;
struct Scsi_Host *scsi_host = scpnt->device->host;
unit = (struct zfcp_unit *) scpnt->device->hostdata; unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_NORMAL("host reset because of problems with " ZFCP_LOG_NORMAL("host reset because of problems with "
...@@ -833,6 +830,7 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) ...@@ -833,6 +830,7 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
shost = adapter->scsi_host; shost = adapter->scsi_host;
if (!shost) if (!shost)
return; return;
fc_remove_host(shost);
scsi_remove_host(shost); scsi_remove_host(shost);
scsi_host_put(shost); scsi_host_put(shost);
adapter->scsi_host = NULL; adapter->scsi_host = NULL;
...@@ -906,6 +904,18 @@ zfcp_get_node_name(struct scsi_target *starget) ...@@ -906,6 +904,18 @@ zfcp_get_node_name(struct scsi_target *starget)
read_unlock_irqrestore(&zfcp_data.config_lock, flags); read_unlock_irqrestore(&zfcp_data.config_lock, flags);
} }
void
zfcp_set_fc_host_attrs(struct zfcp_adapter *adapter)
{
struct Scsi_Host *shost = adapter->scsi_host;
fc_host_node_name(shost) = adapter->wwnn;
fc_host_port_name(shost) = adapter->wwpn;
strncpy(fc_host_serial_number(shost), adapter->serial_number,
min(FC_SERIAL_NUMBER_SIZE, 32));
fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
}
struct fc_function_template zfcp_transport_functions = { struct fc_function_template zfcp_transport_functions = {
.get_starget_port_id = zfcp_get_port_id, .get_starget_port_id = zfcp_get_port_id,
.get_starget_port_name = zfcp_get_port_name, .get_starget_port_name = zfcp_get_port_name,
...@@ -913,6 +923,11 @@ struct fc_function_template zfcp_transport_functions = { ...@@ -913,6 +923,11 @@ struct fc_function_template zfcp_transport_functions = {
.show_starget_port_id = 1, .show_starget_port_id = 1,
.show_starget_port_name = 1, .show_starget_port_name = 1,
.show_starget_node_name = 1, .show_starget_node_name = 1,
.show_rport_supported_classes = 1,
.show_host_node_name = 1,
.show_host_port_name = 1,
.show_host_supported_classes = 1,
.show_host_serial_number = 1,
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment