]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/s390/scsi/zfcp_scsi.c
Merge branch 'master' into csb1725
[mv-sheeva.git] / drivers / s390 / scsi / zfcp_scsi.c
index cb000c9833bbcee0bf687cc5f31eccf90769ae0b..63529ed801eb3e4a37c768f1b55851863b60e9cb 100644 (file)
@@ -49,11 +49,12 @@ static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth,
        return sdev->queue_depth;
 }
 
-static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
+static void zfcp_scsi_slave_destroy(struct scsi_device *sdev)
 {
-       struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
-       unit->device = NULL;
-       put_device(&unit->dev);
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+       zfcp_erp_lun_shutdown_wait(sdev, "scssd_1");
+       put_device(&zfcp_sdev->port->dev);
 }
 
 static int zfcp_scsi_slave_configure(struct scsi_device *sdp)
@@ -75,25 +76,17 @@ static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
        scpnt->scsi_done(scpnt);
 }
 
-static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
-                                 void (*done) (struct scsi_cmnd *))
+static
+int zfcp_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scpnt)
 {
-       struct zfcp_unit *unit;
-       struct zfcp_adapter *adapter;
-       int    status, scsi_result, ret;
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
+       struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
        struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
+       int    status, scsi_result, ret;
 
        /* reset the status for this request */
        scpnt->result = 0;
        scpnt->host_scribble = NULL;
-       scpnt->scsi_done = done;
-
-       /*
-        * figure out adapter and target device
-        * (stored there by zfcp_scsi_slave_alloc)
-        */
-       adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
-       unit = scpnt->device->hostdata;
 
        scsi_result = fc_remote_port_chkready(rport);
        if (unlikely(scsi_result)) {
@@ -103,11 +96,11 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
                return 0;
        }
 
-       status = atomic_read(&unit->status);
+       status = atomic_read(&zfcp_sdev->status);
        if (unlikely(status & ZFCP_STATUS_COMMON_ERP_FAILED) &&
-                    !(atomic_read(&unit->port->status) &
+                    !(atomic_read(&zfcp_sdev->port->status) &
                       ZFCP_STATUS_COMMON_ERP_FAILED)) {
-               /* only unit access denied, but port is good
+               /* only LUN access denied, but port is good
                 * not covered by FC transport, have to fail here */
                zfcp_scsi_command_fail(scpnt, DID_ERROR);
                return 0;
@@ -115,8 +108,8 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 
        if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) {
                /* This could be either
-                * open unit pending: this is temporary, will result in
-                *      open unit or ERP_FAILED, so retry command
+                * open LUN pending: this is temporary, will result in
+                *      open LUN or ERP_FAILED, so retry command
                 * call to rport_delete pending: mimic retry from
                 *      fc_remote_port_chkready until rport is BLOCKED
                 */
@@ -124,7 +117,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
                return 0;
        }
 
-       ret = zfcp_fsf_send_fcp_command_task(unit, scpnt);
+       ret = zfcp_fsf_fcp_cmnd(scpnt);
        if (unlikely(ret == -EBUSY))
                return SCSI_MLQUEUE_DEVICE_BUSY;
        else if (unlikely(ret < 0))
@@ -133,45 +126,42 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
        return ret;
 }
 
-static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter,
-                                         unsigned int id, u64 lun)
+static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
 {
-       unsigned long flags;
+       struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+       struct zfcp_adapter *adapter =
+               (struct zfcp_adapter *) sdev->host->hostdata[0];
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
        struct zfcp_port *port;
-       struct zfcp_unit *unit = NULL;
+       struct zfcp_unit *unit;
 
-       read_lock_irqsave(&adapter->port_list_lock, flags);
-       list_for_each_entry(port, &adapter->port_list, list) {
-               if (!port->rport || (id != port->rport->scsi_target_id))
-                       continue;
-               unit = zfcp_get_unit_by_lun(port, lun);
-               if (unit)
-                       break;
-       }
-       read_unlock_irqrestore(&adapter->port_list_lock, flags);
+       port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
+       if (!port)
+               return -ENXIO;
 
-       return unit;
-}
+       unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev));
+       if (unit)
+               put_device(&unit->dev);
 
-static int zfcp_scsi_slave_alloc(struct scsi_device *sdp)
-{
-       struct zfcp_adapter *adapter;
-       struct zfcp_unit *unit;
-       u64 lun;
+       if (!unit && !(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) {
+               put_device(&port->dev);
+               return -ENXIO;
+       }
 
-       adapter = (struct zfcp_adapter *) sdp->host->hostdata[0];
-       if (!adapter)
-               goto out;
+       zfcp_sdev->port = port;
+       zfcp_sdev->latencies.write.channel.min = 0xFFFFFFFF;
+       zfcp_sdev->latencies.write.fabric.min = 0xFFFFFFFF;
+       zfcp_sdev->latencies.read.channel.min = 0xFFFFFFFF;
+       zfcp_sdev->latencies.read.fabric.min = 0xFFFFFFFF;
+       zfcp_sdev->latencies.cmd.channel.min = 0xFFFFFFFF;
+       zfcp_sdev->latencies.cmd.fabric.min = 0xFFFFFFFF;
+       spin_lock_init(&zfcp_sdev->latencies.lock);
 
-       int_to_scsilun(sdp->lun, (struct scsi_lun *)&lun);
-       unit = zfcp_unit_lookup(adapter, sdp->id, lun);
-       if (unit) {
-               sdp->hostdata = unit;
-               unit->device = sdp;
-               return 0;
-       }
-out:
-       return -ENXIO;
+       zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
+       zfcp_erp_lun_reopen(sdev, 0, "scsla_1", NULL);
+       zfcp_erp_wait(port->adapter);
+
+       return 0;
 }
 
 static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
@@ -179,7 +169,6 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
        struct Scsi_Host *scsi_host = scpnt->device->host;
        struct zfcp_adapter *adapter =
                (struct zfcp_adapter *) scsi_host->hostdata[0];
-       struct zfcp_unit *unit = scpnt->device->hostdata;
        struct zfcp_fsf_req *old_req, *abrt_req;
        unsigned long flags;
        unsigned long old_reqid = (unsigned long) scpnt->host_scribble;
@@ -203,7 +192,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
        write_unlock_irqrestore(&adapter->abort_lock, flags);
 
        while (retry--) {
-               abrt_req = zfcp_fsf_abort_fcp_command(old_reqid, unit);
+               abrt_req = zfcp_fsf_abort_fcp_cmnd(scpnt);
                if (abrt_req)
                        break;
 
@@ -238,14 +227,14 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
 
 static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
 {
-       struct zfcp_unit *unit = scpnt->device->hostdata;
-       struct zfcp_adapter *adapter = unit->port->adapter;
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
+       struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
        struct zfcp_fsf_req *fsf_req = NULL;
        int retval = SUCCESS, ret;
        int retry = 3;
 
        while (retry--) {
-               fsf_req = zfcp_fsf_send_fcp_ctm(unit, tm_flags);
+               fsf_req = zfcp_fsf_fcp_task_mgmt(scpnt, tm_flags);
                if (fsf_req)
                        break;
 
@@ -256,7 +245,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
 
                if (!(atomic_read(&adapter->status) &
                      ZFCP_STATUS_COMMON_RUNNING)) {
-                       zfcp_dbf_scsi_devreset("nres", tm_flags, unit, scpnt);
+                       zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags);
                        return SUCCESS;
                }
        }
@@ -266,10 +255,10 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
        wait_for_completion(&fsf_req->completion);
 
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
-               zfcp_dbf_scsi_devreset("fail", tm_flags, unit, scpnt);
+               zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags);
                retval = FAILED;
        } else
-               zfcp_dbf_scsi_devreset("okay", tm_flags, unit, scpnt);
+               zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags);
 
        zfcp_fsf_req_free(fsf_req);
        return retval;
@@ -287,8 +276,8 @@ static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
 
 static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
 {
-       struct zfcp_unit *unit = scpnt->device->hostdata;
-       struct zfcp_adapter *adapter = unit->port->adapter;
+       struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
+       struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
        int ret;
 
        zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt);
@@ -319,8 +308,8 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
        }
 
        /* tell the SCSI stack some characteristics of this adapter */
-       adapter->scsi_host->max_id = 1;
-       adapter->scsi_host->max_lun = 1;
+       adapter->scsi_host->max_id = 511;
+       adapter->scsi_host->max_lun = 0xFFFFFFFF;
        adapter->scsi_host->max_channel = 0;
        adapter->scsi_host->unique_id = dev_id.devno;
        adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */
@@ -534,20 +523,6 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
        }
 }
 
-static void zfcp_scsi_queue_unit_register(struct zfcp_port *port)
-{
-       struct zfcp_unit *unit;
-
-       read_lock_irq(&port->unit_list_lock);
-       list_for_each_entry(unit, &port->unit_list, list) {
-               get_device(&unit->dev);
-               if (scsi_queue_work(port->adapter->scsi_host,
-                                   &unit->scsi_work) <= 0)
-                       put_device(&unit->dev);
-       }
-       read_unlock_irq(&port->unit_list_lock);
-}
-
 static void zfcp_scsi_rport_register(struct zfcp_port *port)
 {
        struct fc_rport_identifiers ids;
@@ -574,7 +549,7 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
        port->rport = rport;
        port->starget_id = rport->scsi_target_id;
 
-       zfcp_scsi_queue_unit_register(port);
+       zfcp_unit_queue_scsi_scan(port);
 }
 
 static void zfcp_scsi_rport_block(struct zfcp_port *port)
@@ -637,29 +612,6 @@ void zfcp_scsi_rport_work(struct work_struct *work)
        put_device(&port->dev);
 }
 
-/**
- * zfcp_scsi_scan - Register LUN with SCSI midlayer
- * @unit: The LUN/unit to register
- */
-void zfcp_scsi_scan(struct zfcp_unit *unit)
-{
-       struct fc_rport *rport = unit->port->rport;
-
-       if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
-               scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
-                                scsilun_to_int((struct scsi_lun *)
-                                               &unit->fcp_lun), 0);
-}
-
-void zfcp_scsi_scan_work(struct work_struct *work)
-{
-       struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
-                                             scsi_work);
-
-       zfcp_scsi_scan(unit);
-       put_device(&unit->dev);
-}
-
 /**
  * zfcp_scsi_set_prot - Configure DIF/DIX support in scsi_host
  * @adapter: The adapter where to configure DIF/DIX for the SCSI host
@@ -681,6 +633,7 @@ void zfcp_scsi_set_prot(struct zfcp_adapter *adapter)
            adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) {
                mask |= SHOST_DIX_TYPE1_PROTECTION;
                scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP);
+               shost->sg_prot_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2;
                shost->sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2;
                shost->max_sectors = ZFCP_QDIO_MAX_SBALES_PER_REQ * 8 / 2;
        }
@@ -734,7 +687,6 @@ struct fc_function_template zfcp_transport_functions = {
        .show_host_port_type = 1,
        .show_host_speed = 1,
        .show_host_port_id = 1,
-       .disable_target_scan = 1,
        .dd_bsg_size = sizeof(struct zfcp_fsf_ct_els),
 };