forked from Minki/linux
[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: Andreas Herrmann <aherrman@de.ibm.com> Acked-by: James Bottomley <jejb@steeleye.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
729d70f5df
commit
3859f6a248
@ -1299,13 +1299,10 @@ struct zfcp_port *
|
||||
zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
|
||||
u32 d_id)
|
||||
{
|
||||
struct zfcp_port *port, *tmp_port;
|
||||
struct zfcp_port *port;
|
||||
int check_wwpn;
|
||||
scsi_id_t scsi_id;
|
||||
int found;
|
||||
|
||||
check_wwpn = !(status & ZFCP_STATUS_PORT_NO_WWPN);
|
||||
|
||||
/*
|
||||
* 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,
|
||||
} else {
|
||||
snprintf(port->sysfs_device.bus_id,
|
||||
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;
|
||||
dev_set_drvdata(&port->sysfs_device, port);
|
||||
@ -1388,24 +1385,8 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
|
||||
|
||||
zfcp_port_get(port);
|
||||
|
||||
scsi_id = 1;
|
||||
found = 0;
|
||||
write_lock_irq(&zfcp_data.config_lock);
|
||||
list_for_each_entry(tmp_port, &adapter->port_list_head, list) {
|
||||
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);
|
||||
list_add_tail(&port->list, &adapter->port_list_head);
|
||||
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
|
||||
atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
|
||||
if (d_id == ZFCP_DID_DIRECTORY_SERVICE)
|
||||
@ -1422,11 +1403,15 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
|
||||
void
|
||||
zfcp_port_dequeue(struct zfcp_port *port)
|
||||
{
|
||||
struct fc_port *rport;
|
||||
|
||||
zfcp_port_wait(port);
|
||||
write_lock_irq(&zfcp_data.config_lock);
|
||||
list_del(&port->list);
|
||||
port->adapter->ports--;
|
||||
write_unlock_irq(&zfcp_data.config_lock);
|
||||
if (port->rport)
|
||||
fc_remote_port_delete(rport);
|
||||
zfcp_adapter_put(port->adapter);
|
||||
zfcp_sysfs_port_remove_files(&port->sysfs_device,
|
||||
atomic_read(&port->status));
|
||||
|
@ -202,9 +202,19 @@ static int
|
||||
zfcp_ccw_set_offline(struct ccw_device *ccw_device)
|
||||
{
|
||||
struct zfcp_adapter *adapter;
|
||||
struct zfcp_port *port;
|
||||
struct fc_port *rport;
|
||||
|
||||
down(&zfcp_data.config_sema);
|
||||
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_wait(adapter);
|
||||
zfcp_adapter_scsi_unregister(adapter);
|
||||
|
@ -906,6 +906,7 @@ struct zfcp_adapter {
|
||||
*/
|
||||
struct zfcp_port {
|
||||
struct device sysfs_device; /* sysfs device */
|
||||
struct fc_rport *rport; /* rport of fc transport class */
|
||||
struct list_head list; /* list of remote ports */
|
||||
atomic_t refcount; /* reference count */
|
||||
wait_queue_head_t remove_wq; /* can be used to wait for
|
||||
@ -916,7 +917,6 @@ struct zfcp_port {
|
||||
list */
|
||||
u32 units; /* # of logical units in list */
|
||||
atomic_t status; /* status of this remote port */
|
||||
scsi_id_t scsi_id; /* own SCSI ID */
|
||||
wwn_t wwnn; /* WWNN if known */
|
||||
wwn_t wwpn; /* WWPN */
|
||||
fc_id_t d_id; /* D_ID */
|
||||
|
@ -3360,13 +3360,32 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
|
||||
if ((result == ZFCP_ERP_SUCCEEDED)
|
||||
&& (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY,
|
||||
&unit->status))
|
||||
&& (!unit->device))
|
||||
scsi_add_device(unit->port->adapter->scsi_host, 0,
|
||||
unit->port->scsi_id, unit->scsi_lun);
|
||||
&& !unit->device
|
||||
&& port->rport)
|
||||
scsi_add_device(port->adapter->scsi_host, 0,
|
||||
port->rport->scsi_target_id,
|
||||
unit->scsi_lun);
|
||||
zfcp_unit_put(unit);
|
||||
break;
|
||||
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
|
||||
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);
|
||||
break;
|
||||
case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
|
||||
|
@ -143,6 +143,8 @@ extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *,
|
||||
struct scsi_cmnd *, struct timer_list *);
|
||||
extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
|
||||
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 fc_function_template zfcp_transport_functions;
|
||||
|
||||
|
@ -2062,6 +2062,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
|
||||
zfcp_erp_adapter_shutdown(adapter, 0);
|
||||
return -EIO;
|
||||
}
|
||||
zfcp_set_fc_host_attrs(adapter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -389,7 +389,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
|
||||
struct zfcp_unit *unit, *retval = NULL;
|
||||
|
||||
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;
|
||||
list_for_each_entry(unit, &port->unit_list_head, list) {
|
||||
if (lun == unit->scsi_lun) {
|
||||
@ -408,7 +408,7 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
|
||||
struct zfcp_port *port;
|
||||
|
||||
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 (struct zfcp_port *) NULL;
|
||||
@ -634,7 +634,6 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
|
||||
{
|
||||
int retval;
|
||||
struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
|
||||
struct Scsi_Host *scsi_host = scpnt->device->host;
|
||||
|
||||
if (!unit) {
|
||||
ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n");
|
||||
@ -729,7 +728,6 @@ zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
|
||||
{
|
||||
int retval = 0;
|
||||
struct zfcp_unit *unit;
|
||||
struct Scsi_Host *scsi_host = scpnt->device->host;
|
||||
|
||||
unit = (struct zfcp_unit *) scpnt->device->hostdata;
|
||||
ZFCP_LOG_NORMAL("bus reset because of problems with "
|
||||
@ -753,7 +751,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
|
||||
{
|
||||
int retval = 0;
|
||||
struct zfcp_unit *unit;
|
||||
struct Scsi_Host *scsi_host = scpnt->device->host;
|
||||
|
||||
unit = (struct zfcp_unit *) scpnt->device->hostdata;
|
||||
ZFCP_LOG_NORMAL("host reset because of problems with "
|
||||
@ -833,6 +830,7 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
|
||||
shost = adapter->scsi_host;
|
||||
if (!shost)
|
||||
return;
|
||||
fc_remove_host(shost);
|
||||
scsi_remove_host(shost);
|
||||
scsi_host_put(shost);
|
||||
adapter->scsi_host = NULL;
|
||||
@ -906,6 +904,18 @@ zfcp_get_node_name(struct scsi_target *starget)
|
||||
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 = {
|
||||
.get_starget_port_id = zfcp_get_port_id,
|
||||
.get_starget_port_name = zfcp_get_port_name,
|
||||
@ -913,6 +923,11 @@ struct fc_function_template zfcp_transport_functions = {
|
||||
.show_starget_port_id = 1,
|
||||
.show_starget_port_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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user