vserver 1.9.3
[linux-2.6.git] / drivers / s390 / scsi / zfcp_scsi.c
index 34a73f2..6c08081 100644 (file)
@@ -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