X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Fstex.c;h=72f6d8015358d6f52c967f51876d53cac2597c29;hb=c9a6ce500d78932c43361eae28c3de81b3660c77;hp=69be1324b114ffc274cadd4e805b8e89c4ea1bd3;hpb=a22a0fab32e1216df56e4b9a577dc5c922cf7524;p=linux-2.6-omap-h63xx.git diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 69be1324b11..72f6d801535 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -32,11 +32,12 @@ #include #include #include +#include #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 +114,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, @@ -398,53 +395,34 @@ static struct req_msg *stex_alloc_req(struct st_hba *hba) static int stex_map_sg(struct st_hba *hba, struct req_msg *req, struct st_ccb *ccb) { - struct pci_dev *pdev = hba->pdev; struct scsi_cmnd *cmd; - dma_addr_t dma_handle; - struct scatterlist *src; + struct scatterlist *sg; struct st_sgtable *dst; - int i; + int i, nseg; cmd = ccb->cmd; dst = (struct st_sgtable *)req->variable; dst->max_sg_count = cpu_to_le16(ST_MAX_SG); - dst->sz_in_byte = cpu_to_le32(cmd->request_bufflen); - - if (cmd->use_sg) { - int n_elem; + dst->sz_in_byte = cpu_to_le32(scsi_bufflen(cmd)); - src = (struct scatterlist *) cmd->request_buffer; - n_elem = pci_map_sg(pdev, src, - cmd->use_sg, cmd->sc_data_direction); - if (n_elem <= 0) - return -EIO; + nseg = scsi_dma_map(cmd); + if (nseg < 0) + return -EIO; + if (nseg) { + ccb->sg_count = nseg; + dst->sg_count = cpu_to_le16((u16)nseg); - ccb->sg_count = n_elem; - dst->sg_count = cpu_to_le16((u16)n_elem); - - for (i = 0; i < n_elem; i++, src++) { - dst->table[i].count = cpu_to_le32((u32)sg_dma_len(src)); + scsi_for_each_sg(cmd, sg, nseg, i) { + dst->table[i].count = cpu_to_le32((u32)sg_dma_len(sg)); dst->table[i].addr = - cpu_to_le32(sg_dma_address(src) & 0xffffffff); + cpu_to_le32(sg_dma_address(sg) & 0xffffffff); dst->table[i].addr_hi = - cpu_to_le32((sg_dma_address(src) >> 16) >> 16); + cpu_to_le32((sg_dma_address(sg) >> 16) >> 16); dst->table[i].ctrl = SG_CF_64B | SG_CF_HOST; } dst->table[--i].ctrl |= SG_CF_EOT; - return 0; } - dma_handle = pci_map_single(pdev, cmd->request_buffer, - cmd->request_bufflen, cmd->sc_data_direction); - cmd->SCp.dma_handle = dma_handle; - - ccb->sg_count = 1; - dst->sg_count = cpu_to_le16(1); - dst->table[0].addr = cpu_to_le32(dma_handle & 0xffffffff); - dst->table[0].addr_hi = cpu_to_le32((dma_handle >> 16) >> 16); - dst->table[0].count = cpu_to_le32((u32)cmd->request_bufflen); - dst->table[0].ctrl = SG_CF_EOT | SG_CF_64B | SG_CF_HOST; - return 0; } @@ -454,24 +432,24 @@ static void stex_internal_copy(struct scsi_cmnd *cmd, size_t lcount; size_t len; void *s, *d, *base = NULL; - if (*count > cmd->request_bufflen) - *count = cmd->request_bufflen; + size_t offset; + + if (*count > scsi_bufflen(cmd)) + *count = scsi_bufflen(cmd); lcount = *count; while (lcount) { len = lcount; s = (void *)src; - if (cmd->use_sg) { - size_t offset = *count - lcount; - s += offset; - base = scsi_kmap_atomic_sg(cmd->request_buffer, - sg_count, &offset, &len); - if (base == NULL) { - *count -= lcount; - return; - } - d = base + offset; - } else - d = cmd->request_buffer; + + 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); @@ -479,30 +457,24 @@ static void stex_internal_copy(struct scsi_cmnd *cmd, memcpy(s, d, len); lcount -= len; - if (cmd->use_sg) - scsi_kunmap_atomic_sg(base); + scsi_kunmap_atomic_sg(base); } } static int stex_direct_copy(struct scsi_cmnd *cmd, const void *src, size_t count) { - struct st_hba *hba = (struct st_hba *) &cmd->device->host->hostdata[0]; size_t cp_len = count; int n_elem = 0; - if (cmd->use_sg) { - n_elem = pci_map_sg(hba->pdev, cmd->request_buffer, - cmd->use_sg, cmd->sc_data_direction); - if (n_elem <= 0) - return 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); - if (cmd->use_sg) - pci_unmap_sg(hba->pdev, cmd->request_buffer, - cmd->use_sg, cmd->sc_data_direction); + scsi_dma_unmap(cmd); + return cp_len == count; } @@ -586,7 +558,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]) { @@ -605,8 +577,26 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) 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, @@ -624,7 +614,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) 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)) ? DID_OK << 16 | COMMAND_COMPLETE << 8 : @@ -645,13 +635,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); @@ -668,18 +653,6 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) return 0; } -static void stex_unmap_sg(struct st_hba *hba, struct scsi_cmnd *cmd) -{ - if (cmd->sc_data_direction != DMA_NONE) { - if (cmd->use_sg) - pci_unmap_sg(hba->pdev, cmd->request_buffer, - cmd->use_sg, cmd->sc_data_direction); - else - pci_unmap_single(hba->pdev, cmd->SCp.dma_handle, - cmd->request_bufflen, cmd->sc_data_direction); - } -} - static void stex_scsi_done(struct st_ccb *ccb) { struct scsi_cmnd *cmd = ccb->cmd; @@ -746,8 +719,8 @@ static void stex_ys_commands(struct st_hba *hba, if (ccb->cmd->cmnd[0] == MGT_CMD && resp->scsi_status != SAM_STAT_CHECK_CONDITION) { - ccb->cmd->request_bufflen = - le32_to_cpu(*(__le32 *)&resp->variable[0]); + scsi_set_resid(ccb->cmd, scsi_bufflen(ccb->cmd) - + le32_to_cpu(*(__le32 *)&resp->variable[0])); return; } @@ -767,18 +740,6 @@ static void stex_ys_commands(struct st_hba *hba, 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); - } } } @@ -857,7 +818,7 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell) ccb->cmd->cmnd[1] == PASSTHRU_GET_ADAPTER)) stex_controller_info(hba, ccb); - stex_unmap_sg(hba, ccb->cmd); + scsi_dma_unmap(ccb->cmd); stex_scsi_done(ccb); hba->out_req_cnt--; } else if (ccb->req_type & PASSTHRU_REQ_TYPE) { @@ -995,6 +956,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) @@ -1025,7 +991,7 @@ static int stex_abort(struct scsi_cmnd *cmd) } fail_out: - stex_unmap_sg(hba, cmd); + scsi_dma_unmap(cmd); hba->wait_ccb->req = NULL; /* nullify the req's future return */ hba->wait_ccb = NULL; result = FAILED; @@ -1051,7 +1017,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); @@ -1075,6 +1046,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) @@ -1194,7 +1169,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", @@ -1229,12 +1204,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;