X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fs390%2Fscsi%2Fzfcp_scsi.c;h=6c08081638195e89cb14b50b0b07760723b5c979;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=34a73f2f02c0297e2ac3f4900d466ee6d1353ff0;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 34a73f2f0..6c0808163 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -31,7 +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.62 $" +#define ZFCP_SCSI_REVISION "$Revision: 1.68 $" #include "zfcp_ext.h" @@ -51,6 +51,8 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, static struct device_attribute *zfcp_sysfs_sdev_attrs[]; +struct scsi_transport_template *zfcp_transport_template; + struct zfcp_data zfcp_data = { .scsi_host_template = { name: ZFCP_NAME, @@ -245,15 +247,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; @@ -289,7 +292,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)) { @@ -311,18 +314,28 @@ 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); + scpnt->scsi_done = zfcp_scsi_command_sync_handler; + ret = zfcp_scsi_command_async(unit->port->adapter, unit, scpnt, timer); + if ((ret == 0) && (scpnt->result == 0)) wait_for_completion(&wait); + scpnt->SCp.ptr = NULL; + return 0; } @@ -353,7 +366,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); } /* @@ -428,7 +441,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, @@ -508,8 +521,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) ZFCP_LOG_DEBUG("unit 0x%016Lx (%p)\n", unit->fcp_lun, unit); /* - * The 'Abort FCP Command' routine may block (call schedule) - * because it may wait for a free SBAL. + * We block (call schedule) * That's why we must release the lock and enable the * interrupts before. * On the other hand we do not need the lock anymore since @@ -518,8 +530,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) write_unlock_irqrestore(&adapter->abort_lock, flags); /* call FSF routine which does the abort */ new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req, - adapter, - unit, ZFCP_WAIT_FOR_SBAL); + adapter, unit, 0); ZFCP_LOG_DEBUG("new_fsf_req=%p\n", new_fsf_req); if (!new_fsf_req) { retval = FAILED; @@ -657,7 +668,7 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags) /* issue task management function */ fsf_req = zfcp_fsf_send_fcp_command_task_management - (adapter, unit, tm_flags, ZFCP_WAIT_FOR_SBAL); + (adapter, unit, tm_flags, 0); if (!fsf_req) { ZFCP_LOG_INFO("error: creation of task management request " "failed for unit 0x%016Lx on port 0x%016Lx on " @@ -768,6 +779,7 @@ zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) adapter->scsi_host->max_channel = 0; adapter->scsi_host->unique_id = unique_id++; /* FIXME */ adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH; + adapter->scsi_host->transportt = zfcp_transport_template; /* * Reverse mapping of the host number to avoid race condition */ @@ -823,6 +835,44 @@ zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter) add_timer(&adapter->scsi_er_timer); } +/* + * Support functions for FC transport class + */ +static void +zfcp_get_port_id(struct scsi_device *sdev) +{ + struct zfcp_unit *unit; + + unit = (struct zfcp_unit *) sdev->hostdata; + fc_port_id(sdev) = unit->port->d_id; +} + +static void +zfcp_get_port_name(struct scsi_device *sdev) +{ + struct zfcp_unit *unit; + + unit = (struct zfcp_unit *) sdev->hostdata; + fc_port_name(sdev) = unit->port->wwpn; +} + +static void +zfcp_get_node_name(struct scsi_device *sdev) +{ + struct zfcp_unit *unit; + + unit = (struct zfcp_unit *) sdev->hostdata; + fc_node_name(sdev) = unit->port->wwnn; +} + +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, +}; /** * ZFCP_DEFINE_SCSI_ATTR