X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fs390%2Fscsi%2Fzfcp_scsi.c;h=e21b547fd427836cc49bad40393c5643f184c5ba;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=d0a879f0a1823e5932b14c0ccf213b7f171775a1;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index d0a879f0a..e21b547fd 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -12,6 +12,7 @@ * Wolfgang Taphorn * Stefan Bader * Heiko Carstens + * Andreas Herrmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,8 +31,7 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI -/* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_SCSI_REVISION "$Revision: 1.65 $" +#define ZFCP_SCSI_REVISION "$Revision: 1.74 $" #include "zfcp_ext.h" @@ -48,6 +48,8 @@ static int zfcp_task_management_function(struct zfcp_unit *, u8); static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, scsi_lun_t); +static struct zfcp_port *zfcp_port_lookup(struct zfcp_adapter *, int, + scsi_id_t); static struct device_attribute *zfcp_sysfs_sdev_attrs[]; @@ -79,7 +81,8 @@ struct zfcp_data zfcp_data = { unchecked_isa_dma: 0, use_clustering: 1, sdev_attrs: zfcp_sysfs_sdev_attrs, - } + }, + .driver_version = ZFCP_VERSION, /* rest initialised with zeros */ }; @@ -247,15 +250,16 @@ zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) /** * zfcp_scsi_command_async - worker for zfcp_scsi_queuecommand and * zfcp_scsi_command_sync - * @adapter: adapter for where scsi command is issued + * @adapter: adapter where scsi command is issued * @unit: unit to which scsi command is sent * @scpnt: scsi command to be sent + * @timer: timer to be started if request is successfully initiated * * Note: In scsi_done function must be set in scpnt. */ int zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, - struct scsi_cmnd *scpnt) + struct scsi_cmnd *scpnt, struct timer_list *timer) { int tmp; int retval; @@ -291,7 +295,7 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, goto out; } - tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, + tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, timer, ZFCP_REQ_AUTO_CLEANUP); if (unlikely(tmp < 0)) { @@ -313,17 +317,27 @@ zfcp_scsi_command_sync_handler(struct scsi_cmnd *scpnt) /** * zfcp_scsi_command_sync - send a SCSI command and wait for completion - * returns 0, errors are indicated by scsi_cmnd->result + * @unit: unit where command is sent to + * @scpnt: scsi command to be sent + * @timer: timer to be started if request is successfully initiated + * Return: 0 + * + * Errors are indicated in scpnt->result */ int -zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt) +zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt, + struct timer_list *timer) { + int ret; DECLARE_COMPLETION(wait); scpnt->SCp.ptr = (void *) &wait; /* silent re-use */ - scpnt->done = zfcp_scsi_command_sync_handler; - zfcp_scsi_command_async(unit->port->adapter, unit, scpnt); - wait_for_completion(&wait); + scpnt->scsi_done = zfcp_scsi_command_sync_handler; + ret = zfcp_scsi_command_async(unit->port->adapter, unit, scpnt, timer); + if (ret == 0) + wait_for_completion(&wait); + + scpnt->SCp.ptr = NULL; return 0; } @@ -355,7 +369,7 @@ zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; unit = (struct zfcp_unit *) scpnt->device->hostdata; - return zfcp_scsi_command_async(adapter, unit, scpnt); + return zfcp_scsi_command_async(adapter, unit, scpnt, NULL); } /* @@ -388,6 +402,18 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id, return retval; } +static struct zfcp_port * +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) + return port; + } + return (struct zfcp_port *) NULL; +} + /* * function: zfcp_scsi_eh_abort_handler * @@ -430,7 +456,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) u64 dbf_fsf_req = 0; u64 dbf_fsf_status = 0; u64 dbf_fsf_qual[2] = { 0, 0 }; - char dbf_result[ZFCP_ABORT_DBF_LENGTH] = { "##undef" }; + char dbf_result[ZFCP_ABORT_DBF_LENGTH] = "##undef"; memset(dbf_opcode, 0, ZFCP_ABORT_DBF_LENGTH); memcpy(dbf_opcode, @@ -618,7 +644,7 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET, &unit->status)) { retval = - zfcp_task_management_function(unit, LOGICAL_UNIT_RESET); + zfcp_task_management_function(unit, FCP_LOGICAL_UNIT_RESET); if (retval) { ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit); if (retval == -ENOTSUPP) @@ -634,7 +660,7 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) goto out; } } - retval = zfcp_task_management_function(unit, TARGET_RESET); + retval = zfcp_task_management_function(unit, FCP_TARGET_RESET); if (retval) { ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit); retval = FAILED; @@ -828,39 +854,63 @@ zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter) * Support functions for FC transport class */ static void -zfcp_get_port_id(struct scsi_device *sdev) +zfcp_get_port_id(struct scsi_target *starget) { - struct zfcp_unit *unit; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; + struct zfcp_port *port; + unsigned long flags; - unit = (struct zfcp_unit *) sdev->hostdata; - fc_port_id(sdev) = unit->port->d_id; + read_lock_irqsave(&zfcp_data.config_lock, flags); + port = zfcp_port_lookup(adapter, starget->channel, starget->id); + if (port) + fc_starget_port_id(starget) = port->d_id; + else + fc_starget_port_id(starget) = -1; + read_unlock_irqrestore(&zfcp_data.config_lock, flags); } static void -zfcp_get_port_name(struct scsi_device *sdev) +zfcp_get_port_name(struct scsi_target *starget) { - struct zfcp_unit *unit; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; + struct zfcp_port *port; + unsigned long flags; - unit = (struct zfcp_unit *) sdev->hostdata; - fc_port_name(sdev) = unit->port->wwpn; + read_lock_irqsave(&zfcp_data.config_lock, flags); + port = zfcp_port_lookup(adapter, starget->channel, starget->id); + if (port) + fc_starget_port_name(starget) = port->wwpn; + else + fc_starget_port_name(starget) = -1; + read_unlock_irqrestore(&zfcp_data.config_lock, flags); } static void -zfcp_get_node_name(struct scsi_device *sdev) +zfcp_get_node_name(struct scsi_target *starget) { - struct zfcp_unit *unit; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; + struct zfcp_port *port; + unsigned long flags; - unit = (struct zfcp_unit *) sdev->hostdata; - fc_node_name(sdev) = unit->port->wwnn; + read_lock_irqsave(&zfcp_data.config_lock, flags); + port = zfcp_port_lookup(adapter, starget->channel, starget->id); + if (port) + fc_starget_node_name(starget) = port->wwnn; + else + fc_starget_node_name(starget) = -1; + read_unlock_irqrestore(&zfcp_data.config_lock, flags); } struct fc_function_template zfcp_transport_functions = { - .get_port_id = zfcp_get_port_id, - .get_port_name = zfcp_get_port_name, - .get_node_name = zfcp_get_node_name, - .show_port_id = 1, - .show_port_name = 1, - .show_node_name = 1, + .get_starget_port_id = zfcp_get_port_id, + .get_starget_port_name = zfcp_get_port_name, + .get_starget_node_name = zfcp_get_node_name, + .show_starget_port_id = 1, + .show_starget_port_name = 1, + .show_starget_node_name = 1, }; /**