sg: incorporate sg_build_direct into sg_start_req
[safe/jmp/linux-2.6] / drivers / scsi / stex.c
index baf516d..3790906 100644 (file)
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_eh.h>
 
 #define DRV_NAME "stex"
-#define ST_DRIVER_VERSION "3.1.0.1"
+#define ST_DRIVER_VERSION "3.6.0000.1"
 #define ST_VER_MAJOR           3
-#define ST_VER_MINOR           1
+#define ST_VER_MINOR           6
 #define ST_OEM                         0
 #define ST_BUILD_VER           1
 
@@ -113,10 +115,6 @@ enum {
        SG_CF_64B                               = 0x40, /* 64 bit item */
        SG_CF_HOST                              = 0x20, /* sg in host memory */
 
-       ST_MAX_ARRAY_SUPPORTED                  = 16,
-       ST_MAX_TARGET_NUM                       = (ST_MAX_ARRAY_SUPPORTED+1),
-       ST_MAX_LUN_PER_TARGET                   = 16,
-
        st_shasta                               = 0,
        st_vsc                                  = 1,
        st_vsc1                                 = 2,
@@ -365,22 +363,14 @@ static struct status_msg *stex_get_status(struct st_hba *hba)
        return status;
 }
 
-static void stex_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
-{
-       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
-
-       cmd->sense_buffer[0] = 0x70;    /* fixed format, current */
-       cmd->sense_buffer[2] = sk;
-       cmd->sense_buffer[7] = 18 - 8;  /* additional sense length */
-       cmd->sense_buffer[12] = asc;
-       cmd->sense_buffer[13] = ascq;
-}
-
 static void stex_invalid_field(struct scsi_cmnd *cmd,
                               void (*done)(struct scsi_cmnd *))
 {
+       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
        /* "Invalid field in cbd" */
-       stex_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0);
+       scsi_build_sense_buffer(0, cmd->sense_buffer, ILLEGAL_REQUEST, 0x24,
+                               0x0);
        done(cmd);
 }
 
@@ -429,65 +419,13 @@ static int stex_map_sg(struct st_hba *hba,
        return 0;
 }
 
-static void stex_internal_copy(struct scsi_cmnd *cmd,
-       const void *src, size_t *count, int sg_count, int direction)
-{
-       size_t lcount;
-       size_t len;
-       void *s, *d, *base = NULL;
-       size_t offset;
-
-       if (*count > scsi_bufflen(cmd))
-               *count = scsi_bufflen(cmd);
-       lcount = *count;
-       while (lcount) {
-               len = lcount;
-               s = (void *)src;
-
-               offset = *count - lcount;
-               s += offset;
-               base = scsi_kmap_atomic_sg(scsi_sglist(cmd),
-                                          sg_count, &offset, &len);
-               if (!base) {
-                       *count -= lcount;
-                       return;
-               }
-               d = base + offset;
-
-               if (direction == ST_TO_CMD)
-                       memcpy(d, s, len);
-               else
-                       memcpy(s, d, len);
-
-               lcount -= len;
-               scsi_kunmap_atomic_sg(base);
-       }
-}
-
-static int stex_direct_copy(struct scsi_cmnd *cmd,
-       const void *src, size_t count)
-{
-       size_t cp_len = count;
-       int n_elem = 0;
-
-       n_elem = scsi_dma_map(cmd);
-       if (n_elem < 0)
-               return 0;
-
-       stex_internal_copy(cmd, src, &cp_len, n_elem, ST_TO_CMD);
-
-       scsi_dma_unmap(cmd);
-
-       return cp_len == count;
-}
-
 static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
 {
        struct st_frame *p;
        size_t count = sizeof(struct st_frame);
 
        p = hba->copy_buffer;
-       stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count, ST_FROM_CMD);
+       count = scsi_sg_copy_to_buffer(ccb->cmd, p, count);
        memset(p->base, 0, sizeof(u32)*6);
        *(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0);
        p->rom_addr = 0;
@@ -505,7 +443,7 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
        p->subid =
                hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device;
 
-       stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count, ST_TO_CMD);
+       count = scsi_sg_copy_from_buffer(ccb->cmd, p, count);
 }
 
 static void
@@ -529,7 +467,7 @@ stex_slave_alloc(struct scsi_device *sdev)
        /* Cheat: usually extracted from Inquiry data */
        sdev->tagged_supported = 1;
 
-       scsi_activate_tcq(sdev, sdev->host->can_queue);
+       scsi_activate_tcq(sdev, ST_CMD_PER_LUN);
 
        return 0;
 }
@@ -561,7 +499,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
        u16 tag;
        host = cmd->device->host;
        id = cmd->device->id;
-       lun = cmd->device->channel; /* firmware lun issue work around */
+       lun = cmd->device->lun;
        hba = (struct st_hba *) &host->hostdata[0];
 
        switch (cmd->cmnd[0]) {
@@ -572,20 +510,38 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
                unsigned char page;
                page = cmd->cmnd[2] & 0x3f;
                if (page == 0x8 || page == 0x3f) {
-                       stex_direct_copy(cmd, ms10_caching_page,
-                                       sizeof(ms10_caching_page));
+                       scsi_sg_copy_from_buffer(cmd, ms10_caching_page,
+                                                sizeof(ms10_caching_page));
                        cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
                        done(cmd);
                } else
                        stex_invalid_field(cmd, done);
                return 0;
        }
+       case REPORT_LUNS:
+               /*
+                * The shasta firmware does not report actual luns in the
+                * target, so fail the command to force sequential lun scan.
+                * Also, the console device does not support this command.
+                */
+               if (hba->cardtype == st_shasta || id == host->max_id - 1) {
+                       stex_invalid_field(cmd, done);
+                       return 0;
+               }
+               break;
+       case TEST_UNIT_READY:
+               if (id == host->max_id - 1) {
+                       cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+                       done(cmd);
+                       return 0;
+               }
+               break;
        case INQUIRY:
-               if (id != ST_MAX_ARRAY_SUPPORTED)
+               if (id != host->max_id - 1)
                        break;
                if (lun == 0 && (cmd->cmnd[1] & INQUIRY_EVPD) == 0) {
-                       stex_direct_copy(cmd, console_inq_page,
-                               sizeof(console_inq_page));
+                       scsi_sg_copy_from_buffer(cmd, (void *)console_inq_page,
+                                                sizeof(console_inq_page));
                        cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
                        done(cmd);
                } else
@@ -594,14 +550,16 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
        case PASSTHRU_CMD:
                if (cmd->cmnd[1] == PASSTHRU_GET_DRVVER) {
                        struct st_drvver ver;
+                       size_t cp_len = sizeof(ver);
                        ver.major = ST_VER_MAJOR;
                        ver.minor = ST_VER_MINOR;
                        ver.oem = ST_OEM;
                        ver.build = ST_BUILD_VER;
                        ver.signature[0] = PASSTHRU_SIGNATURE;
-                       ver.console_id = ST_MAX_ARRAY_SUPPORTED;
+                       ver.console_id = host->max_id - 1;
                        ver.host_no = hba->host->host_no;
-                       cmd->result = stex_direct_copy(cmd, &ver, sizeof(ver)) ?
+                       cp_len = scsi_sg_copy_from_buffer(cmd, &ver, cp_len);
+                       cmd->result = sizeof(ver) == cp_len ?
                                DID_OK << 16 | COMMAND_COMPLETE << 8 :
                                DID_ERROR << 16 | COMMAND_COMPLETE << 8;
                        done(cmd);
@@ -620,13 +578,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
 
        req = stex_alloc_req(hba);
 
-       if (hba->cardtype == st_yosemite) {
-               req->lun = lun * (ST_MAX_TARGET_NUM - 1) + id;
-               req->target = 0;
-       } else {
-               req->lun = lun;
-               req->target = id;
-       }
+       req->lun = lun;
+       req->target = id;
 
        /* cdb */
        memcpy(req->cdb, cmd->cmnd, STEX_CDB_LENGTH);
@@ -698,19 +651,16 @@ static void stex_copy_data(struct st_ccb *ccb,
 
        if (ccb->cmd == NULL)
                return;
-       stex_internal_copy(ccb->cmd,
-               resp->variable, &count, ccb->sg_count, ST_TO_CMD);
+       count = scsi_sg_copy_from_buffer(ccb->cmd, resp->variable, count);
 }
 
 static void stex_ys_commands(struct st_hba *hba,
        struct st_ccb *ccb, struct status_msg *resp)
 {
-       size_t count;
-
        if (ccb->cmd->cmnd[0] == MGT_CMD &&
                resp->scsi_status != SAM_STAT_CHECK_CONDITION) {
-               scsi_bufflen(ccb->cmd) =
-                       le32_to_cpu(*(__le32 *)&resp->variable[0]);
+               scsi_set_resid(ccb->cmd, scsi_bufflen(ccb->cmd) -
+                       le32_to_cpu(*(__le32 *)&resp->variable[0]));
                return;
        }
 
@@ -722,26 +672,13 @@ static void stex_ys_commands(struct st_hba *hba,
                resp->scsi_status == SAM_STAT_GOOD) {
                ST_INQ *inq_data;
 
-               count = STEX_EXTRA_SIZE;
-               stex_internal_copy(ccb->cmd, hba->copy_buffer,
-                       &count, ccb->sg_count, ST_FROM_CMD);
+               scsi_sg_copy_to_buffer(ccb->cmd, hba->copy_buffer,
+                                      STEX_EXTRA_SIZE);
                inq_data = (ST_INQ *)hba->copy_buffer;
                if (inq_data->DeviceTypeQualifier != 0)
                        ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT;
                else
                        ccb->srb_status = SRB_STATUS_SUCCESS;
-       } else if (ccb->cmd->cmnd[0] == REPORT_LUNS) {
-               u8 *report_lun_data = (u8 *)hba->copy_buffer;
-
-               count = STEX_EXTRA_SIZE;
-               stex_internal_copy(ccb->cmd, report_lun_data,
-                       &count, ccb->sg_count, ST_FROM_CMD);
-               if (report_lun_data[2] || report_lun_data[3]) {
-                       report_lun_data[2] = 0x00;
-                       report_lun_data[3] = 0x08;
-                       stex_internal_copy(ccb->cmd, report_lun_data,
-                               &count, ccb->sg_count, ST_TO_CMD);
-               }
        }
 }
 
@@ -958,6 +895,11 @@ static int stex_abort(struct scsi_cmnd *cmd)
        u32 data;
        int result = SUCCESS;
        unsigned long flags;
+
+       printk(KERN_INFO DRV_NAME
+               "(%s): aborting command\n", pci_name(hba->pdev));
+       scsi_print_command(cmd);
+
        base = hba->mmio_base;
        spin_lock_irqsave(host->host_lock, flags);
        if (tag < host->can_queue && hba->ccb[tag].cmd == cmd)
@@ -1014,7 +956,12 @@ static void stex_hard_reset(struct st_hba *hba)
        pci_read_config_byte(bus->self, PCI_BRIDGE_CONTROL, &pci_bctl);
        pci_bctl |= PCI_BRIDGE_CTL_BUS_RESET;
        pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl);
-       msleep(1);
+
+       /*
+        * 1 ms may be enough for 8-port controllers. But 16-port controllers
+        * require more time to finish bus reset. Use 100 ms here for safety
+        */
+       msleep(100);
        pci_bctl &= ~PCI_BRIDGE_CTL_BUS_RESET;
        pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl);
 
@@ -1038,6 +985,10 @@ static int stex_reset(struct scsi_cmnd *cmd)
        unsigned long before;
        hba = (struct st_hba *) &cmd->device->host->hostdata[0];
 
+       printk(KERN_INFO DRV_NAME
+               "(%s): resetting host\n", pci_name(hba->pdev));
+       scsi_print_command(cmd);
+
        hba->mu_status = MU_STATE_RESETTING;
 
        if (hba->cardtype == st_shasta)
@@ -1157,7 +1108,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto out_scsi_host_put;
        }
 
-       hba->mmio_base = ioremap(pci_resource_start(pdev, 0),
+       hba->mmio_base = ioremap_nocache(pci_resource_start(pdev, 0),
                pci_resource_len(pdev, 0));
        if ( !hba->mmio_base) {
                printk(KERN_ERR DRV_NAME "(%s): memory map failed\n",
@@ -1192,12 +1143,18 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        hba->copy_buffer = hba->dma_mem + MU_BUFFER_SIZE;
        hba->mu_status = MU_STATE_STARTING;
 
-       /* firmware uses id/lun pair for a logical drive, but lun would be
-          always 0 if CONFIG_SCSI_MULTI_LUN not configured, so we use
-          channel to map lun here */
-       host->max_channel = ST_MAX_LUN_PER_TARGET - 1;
-       host->max_id = ST_MAX_TARGET_NUM;
-       host->max_lun = 1;
+       if (hba->cardtype == st_shasta) {
+               host->max_lun = 8;
+               host->max_id = 16 + 1;
+       } else if (hba->cardtype == st_yosemite) {
+               host->max_lun = 128;
+               host->max_id = 1 + 1;
+       } else {
+               /* st_vsc and st_vsc1 */
+               host->max_lun = 1;
+               host->max_id = 128 + 1;
+       }
+       host->max_channel = 0;
        host->unique_id = host->host_no;
        host->max_cmd_len = STEX_CDB_LENGTH;