aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/dc395x.c163
1 files changed, 60 insertions, 103 deletions
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 564ea90ed3a0..7b8a3457b696 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -979,6 +979,7 @@ static void send_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
979static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, 979static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
980 struct ScsiReqBlk *srb) 980 struct ScsiReqBlk *srb)
981{ 981{
982 int nseg;
982 enum dma_data_direction dir = cmd->sc_data_direction; 983 enum dma_data_direction dir = cmd->sc_data_direction;
983 dprintkdbg(DBG_0, "build_srb: (pid#%li) <%02i-%i>\n", 984 dprintkdbg(DBG_0, "build_srb: (pid#%li) <%02i-%i>\n",
984 cmd->pid, dcb->target_id, dcb->target_lun); 985 cmd->pid, dcb->target_id, dcb->target_lun);
@@ -1000,27 +1001,30 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
1000 srb->scsi_phase = PH_BUS_FREE; /* initial phase */ 1001 srb->scsi_phase = PH_BUS_FREE; /* initial phase */
1001 srb->end_message = 0; 1002 srb->end_message = 0;
1002 1003
1003 if (dir == PCI_DMA_NONE || !cmd->request_buffer) { 1004 nseg = scsi_dma_map(cmd);
1005 BUG_ON(nseg < 0);
1006
1007 if (dir == PCI_DMA_NONE || !nseg) {
1004 dprintkdbg(DBG_0, 1008 dprintkdbg(DBG_0,
1005 "build_srb: [0] len=%d buf=%p use_sg=%d !MAP=%08x\n", 1009 "build_srb: [0] len=%d buf=%p use_sg=%d !MAP=%08x\n",
1006 cmd->bufflen, cmd->request_buffer, 1010 cmd->bufflen, scsi_sglist(cmd), scsi_sg_count(cmd),
1007 cmd->use_sg, srb->segment_x[0].address); 1011 srb->segment_x[0].address);
1008 } else if (cmd->use_sg) { 1012 } else {
1009 int i; 1013 int i;
1010 u32 reqlen = cmd->request_bufflen; 1014 u32 reqlen = scsi_bufflen(cmd);
1011 struct scatterlist *sl = (struct scatterlist *) 1015 struct scatterlist *sg;
1012 cmd->request_buffer;
1013 struct SGentry *sgp = srb->segment_x; 1016 struct SGentry *sgp = srb->segment_x;
1014 srb->sg_count = pci_map_sg(dcb->acb->dev, sl, cmd->use_sg, 1017
1015 dir); 1018 srb->sg_count = nseg;
1019
1016 dprintkdbg(DBG_0, 1020 dprintkdbg(DBG_0,
1017 "build_srb: [n] len=%d buf=%p use_sg=%d segs=%d\n", 1021 "build_srb: [n] len=%d buf=%p use_sg=%d segs=%d\n",
1018 reqlen, cmd->request_buffer, cmd->use_sg, 1022 reqlen, scsi_sglist(cmd), scsi_sg_count(cmd),
1019 srb->sg_count); 1023 srb->sg_count);
1020 1024
1021 for (i = 0; i < srb->sg_count; i++) { 1025 scsi_for_each_sg(cmd, sg, srb->sg_count, i) {
1022 u32 busaddr = (u32)sg_dma_address(&sl[i]); 1026 u32 busaddr = (u32)sg_dma_address(sg);
1023 u32 seglen = (u32)sl[i].length; 1027 u32 seglen = (u32)sg->length;
1024 sgp[i].address = busaddr; 1028 sgp[i].address = busaddr;
1025 sgp[i].length = seglen; 1029 sgp[i].length = seglen;
1026 srb->total_xfer_length += seglen; 1030 srb->total_xfer_length += seglen;
@@ -1050,23 +1054,6 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
1050 1054
1051 dprintkdbg(DBG_SG, "build_srb: [n] map sg %p->%08x(%05x)\n", 1055 dprintkdbg(DBG_SG, "build_srb: [n] map sg %p->%08x(%05x)\n",
1052 srb->segment_x, srb->sg_bus_addr, SEGMENTX_LEN); 1056 srb->segment_x, srb->sg_bus_addr, SEGMENTX_LEN);
1053 } else {
1054 srb->total_xfer_length = cmd->request_bufflen;
1055 srb->sg_count = 1;
1056 srb->segment_x[0].address =
1057 pci_map_single(dcb->acb->dev, cmd->request_buffer,
1058 srb->total_xfer_length, dir);
1059
1060 /* Fixup for WIDE padding - make sure length is even */
1061 if (dcb->sync_period & WIDE_SYNC && srb->total_xfer_length % 2)
1062 srb->total_xfer_length++;
1063
1064 srb->segment_x[0].length = srb->total_xfer_length;
1065
1066 dprintkdbg(DBG_0,
1067 "build_srb: [1] len=%d buf=%p use_sg=%d map=%08x\n",
1068 srb->total_xfer_length, cmd->request_buffer,
1069 cmd->use_sg, srb->segment_x[0].address);
1070 } 1057 }
1071 1058
1072 srb->request_length = srb->total_xfer_length; 1059 srb->request_length = srb->total_xfer_length;
@@ -2128,7 +2115,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
2128 /*clear_fifo(acb, "DOP1"); */ 2115 /*clear_fifo(acb, "DOP1"); */
2129 /* KG: What is this supposed to be useful for? WIDE padding stuff? */ 2116 /* KG: What is this supposed to be useful for? WIDE padding stuff? */
2130 if (d_left_counter == 1 && dcb->sync_period & WIDE_SYNC 2117 if (d_left_counter == 1 && dcb->sync_period & WIDE_SYNC
2131 && srb->cmd->request_bufflen % 2) { 2118 && scsi_bufflen(srb->cmd) % 2) {
2132 d_left_counter = 0; 2119 d_left_counter = 0;
2133 dprintkl(KERN_INFO, 2120 dprintkl(KERN_INFO,
2134 "data_out_phase0: Discard 1 byte (0x%02x)\n", 2121 "data_out_phase0: Discard 1 byte (0x%02x)\n",
@@ -2159,7 +2146,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
2159 sg_update_list(srb, d_left_counter); 2146 sg_update_list(srb, d_left_counter);
2160 /* KG: Most ugly hack! Apparently, this works around a chip bug */ 2147 /* KG: Most ugly hack! Apparently, this works around a chip bug */
2161 if ((srb->segment_x[srb->sg_index].length == 2148 if ((srb->segment_x[srb->sg_index].length ==
2162 diff && srb->cmd->use_sg) 2149 diff && scsi_sg_count(srb->cmd))
2163 || ((oldxferred & ~PAGE_MASK) == 2150 || ((oldxferred & ~PAGE_MASK) ==
2164 (PAGE_SIZE - diff)) 2151 (PAGE_SIZE - diff))
2165 ) { 2152 ) {
@@ -2289,19 +2276,15 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
2289 unsigned char *virt, *base = NULL; 2276 unsigned char *virt, *base = NULL;
2290 unsigned long flags = 0; 2277 unsigned long flags = 0;
2291 size_t len = left_io; 2278 size_t len = left_io;
2279 size_t offset = srb->request_length - left_io;
2280
2281 local_irq_save(flags);
2282 /* Assumption: it's inside one page as it's at most 4 bytes and
2283 I just assume it's on a 4-byte boundary */
2284 base = scsi_kmap_atomic_sg(scsi_sglist(srb->cmd),
2285 srb->sg_count, &offset, &len);
2286 virt = base + offset;
2292 2287
2293 if (srb->cmd->use_sg) {
2294 size_t offset = srb->request_length - left_io;
2295 local_irq_save(flags);
2296 /* Assumption: it's inside one page as it's at most 4 bytes and
2297 I just assume it's on a 4-byte boundary */
2298 base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer,
2299 srb->sg_count, &offset, &len);
2300 virt = base + offset;
2301 } else {
2302 virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io;
2303 len = left_io;
2304 }
2305 left_io -= len; 2288 left_io -= len;
2306 2289
2307 while (len) { 2290 while (len) {
@@ -2341,10 +2324,8 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
2341 DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0); 2324 DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0);
2342 } 2325 }
2343 2326
2344 if (srb->cmd->use_sg) { 2327 scsi_kunmap_atomic_sg(base);
2345 scsi_kunmap_atomic_sg(base); 2328 local_irq_restore(flags);
2346 local_irq_restore(flags);
2347 }
2348 } 2329 }
2349 /*printk(" %08x", *(u32*)(bus_to_virt (addr))); */ 2330 /*printk(" %08x", *(u32*)(bus_to_virt (addr))); */
2350 /*srb->total_xfer_length = 0; */ 2331 /*srb->total_xfer_length = 0; */
@@ -2455,7 +2436,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
2455 */ 2436 */
2456 srb->state |= SRB_DATA_XFER; 2437 srb->state |= SRB_DATA_XFER;
2457 DC395x_write32(acb, TRM_S1040_DMA_XHIGHADDR, 0); 2438 DC395x_write32(acb, TRM_S1040_DMA_XHIGHADDR, 0);
2458 if (srb->cmd->use_sg) { /* with S/G */ 2439 if (scsi_sg_count(srb->cmd)) { /* with S/G */
2459 io_dir |= DMACMD_SG; 2440 io_dir |= DMACMD_SG;
2460 DC395x_write32(acb, TRM_S1040_DMA_XLOWADDR, 2441 DC395x_write32(acb, TRM_S1040_DMA_XLOWADDR,
2461 srb->sg_bus_addr + 2442 srb->sg_bus_addr +
@@ -2513,18 +2494,14 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
2513 unsigned char *virt, *base = NULL; 2494 unsigned char *virt, *base = NULL;
2514 unsigned long flags = 0; 2495 unsigned long flags = 0;
2515 size_t len = left_io; 2496 size_t len = left_io;
2497 size_t offset = srb->request_length - left_io;
2498
2499 local_irq_save(flags);
2500 /* Again, max 4 bytes */
2501 base = scsi_kmap_atomic_sg(scsi_sglist(srb->cmd),
2502 srb->sg_count, &offset, &len);
2503 virt = base + offset;
2516 2504
2517 if (srb->cmd->use_sg) {
2518 size_t offset = srb->request_length - left_io;
2519 local_irq_save(flags);
2520 /* Again, max 4 bytes */
2521 base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer,
2522 srb->sg_count, &offset, &len);
2523 virt = base + offset;
2524 } else {
2525 virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io;
2526 len = left_io;
2527 }
2528 left_io -= len; 2505 left_io -= len;
2529 2506
2530 while (len--) { 2507 while (len--) {
@@ -2536,10 +2513,8 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
2536 sg_subtract_one(srb); 2513 sg_subtract_one(srb);
2537 } 2514 }
2538 2515
2539 if (srb->cmd->use_sg) { 2516 scsi_kunmap_atomic_sg(base);
2540 scsi_kunmap_atomic_sg(base); 2517 local_irq_restore(flags);
2541 local_irq_restore(flags);
2542 }
2543 } 2518 }
2544 if (srb->dcb->sync_period & WIDE_SYNC) { 2519 if (srb->dcb->sync_period & WIDE_SYNC) {
2545 if (ln % 2) { 2520 if (ln % 2) {
@@ -3295,7 +3270,8 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
3295{ 3270{
3296 struct scsi_cmnd *cmd = srb->cmd; 3271 struct scsi_cmnd *cmd = srb->cmd;
3297 enum dma_data_direction dir = cmd->sc_data_direction; 3272 enum dma_data_direction dir = cmd->sc_data_direction;
3298 if (cmd->use_sg && dir != PCI_DMA_NONE) { 3273
3274 if (scsi_sg_count(cmd) && dir != PCI_DMA_NONE) {
3299 /* unmap DC395x SG list */ 3275 /* unmap DC395x SG list */
3300 dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n", 3276 dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
3301 srb->sg_bus_addr, SEGMENTX_LEN); 3277 srb->sg_bus_addr, SEGMENTX_LEN);
@@ -3303,16 +3279,9 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
3303 SEGMENTX_LEN, 3279 SEGMENTX_LEN,
3304 PCI_DMA_TODEVICE); 3280 PCI_DMA_TODEVICE);
3305 dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n", 3281 dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n",
3306 cmd->use_sg, cmd->request_buffer); 3282 scsi_sg_count(cmd), scsi_bufflen(cmd));
3307 /* unmap the sg segments */ 3283 /* unmap the sg segments */
3308 pci_unmap_sg(acb->dev, 3284 scsi_dma_unmap(cmd);
3309 (struct scatterlist *)cmd->request_buffer,
3310 cmd->use_sg, dir);
3311 } else if (cmd->request_buffer && dir != PCI_DMA_NONE) {
3312 dprintkdbg(DBG_SG, "pci_unmap_srb: buffer=%08x(%05x)\n",
3313 srb->segment_x[0].address, cmd->request_bufflen);
3314 pci_unmap_single(acb->dev, srb->segment_x[0].address,
3315 cmd->request_bufflen, dir);
3316 } 3285 }
3317} 3286}
3318 3287
@@ -3352,8 +3321,8 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
3352 dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid, 3321 dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid,
3353 srb->cmd->device->id, srb->cmd->device->lun); 3322 srb->cmd->device->id, srb->cmd->device->lun);
3354 dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n", 3323 dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n",
3355 srb, cmd->use_sg, srb->sg_index, srb->sg_count, 3324 srb, scsi_sg_count(cmd), srb->sg_index, srb->sg_count,
3356 cmd->request_buffer); 3325 scsi_sgtalbe(cmd));
3357 status = srb->target_status; 3326 status = srb->target_status;
3358 if (srb->flag & AUTO_REQSENSE) { 3327 if (srb->flag & AUTO_REQSENSE) {
3359 dprintkdbg(DBG_0, "srb_done: AUTO_REQSENSE1\n"); 3328 dprintkdbg(DBG_0, "srb_done: AUTO_REQSENSE1\n");
@@ -3482,16 +3451,10 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
3482 } 3451 }
3483 } 3452 }
3484 3453
3485 if (dir != PCI_DMA_NONE) { 3454 if (dir != PCI_DMA_NONE && scsi_sg_count(cmd))
3486 if (cmd->use_sg) 3455 pci_dma_sync_sg_for_cpu(acb->dev, scsi_sglist(cmd),
3487 pci_dma_sync_sg_for_cpu(acb->dev, 3456 scsi_sg_count(cmd), dir);
3488 (struct scatterlist *)cmd-> 3457
3489 request_buffer, cmd->use_sg, dir);
3490 else if (cmd->request_buffer)
3491 pci_dma_sync_single_for_cpu(acb->dev,
3492 srb->segment_x[0].address,
3493 cmd->request_bufflen, dir);
3494 }
3495 ckc_only = 0; 3458 ckc_only = 0;
3496/* Check Error Conditions */ 3459/* Check Error Conditions */
3497 ckc_e: 3460 ckc_e:
@@ -3500,19 +3463,15 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
3500 unsigned char *base = NULL; 3463 unsigned char *base = NULL;
3501 struct ScsiInqData *ptr; 3464 struct ScsiInqData *ptr;
3502 unsigned long flags = 0; 3465 unsigned long flags = 0;
3466 struct scatterlist* sg = scsi_sglist(cmd);
3467 size_t offset = 0, len = sizeof(struct ScsiInqData);
3503 3468
3504 if (cmd->use_sg) { 3469 local_irq_save(flags);
3505 struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer; 3470 base = scsi_kmap_atomic_sg(sg, scsi_sg_count(cmd), &offset, &len);
3506 size_t offset = 0, len = sizeof(struct ScsiInqData); 3471 ptr = (struct ScsiInqData *)(base + offset);
3507
3508 local_irq_save(flags);
3509 base = scsi_kmap_atomic_sg(sg, cmd->use_sg, &offset, &len);
3510 ptr = (struct ScsiInqData *)(base + offset);
3511 } else
3512 ptr = (struct ScsiInqData *)(cmd->request_buffer);
3513 3472
3514 if (!ckc_only && (cmd->result & RES_DID) == 0 3473 if (!ckc_only && (cmd->result & RES_DID) == 0
3515 && cmd->cmnd[2] == 0 && cmd->request_bufflen >= 8 3474 && cmd->cmnd[2] == 0 && scsi_bufflen(cmd) >= 8
3516 && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2) 3475 && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2)
3517 dcb->inquiry7 = ptr->Flags; 3476 dcb->inquiry7 = ptr->Flags;
3518 3477
@@ -3527,14 +3486,12 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
3527 } 3486 }
3528 } 3487 }
3529 3488
3530 if (cmd->use_sg) { 3489 scsi_kunmap_atomic_sg(base);
3531 scsi_kunmap_atomic_sg(base); 3490 local_irq_restore(flags);
3532 local_irq_restore(flags);
3533 }
3534 } 3491 }
3535 3492
3536 /* Here is the info for Doug Gilbert's sg3 ... */ 3493 /* Here is the info for Doug Gilbert's sg3 ... */
3537 cmd->resid = srb->total_xfer_length; 3494 scsi_set_resid(cmd, srb->total_xfer_length);
3538 /* This may be interpreted by sb. or not ... */ 3495 /* This may be interpreted by sb. or not ... */
3539 cmd->SCp.this_residual = srb->total_xfer_length; 3496 cmd->SCp.this_residual = srb->total_xfer_length;
3540 cmd->SCp.buffers_residual = 0; 3497 cmd->SCp.buffers_residual = 0;