diff options
Diffstat (limited to 'drivers/scsi/ips.c')
-rw-r--r-- | drivers/scsi/ips.c | 256 |
1 files changed, 99 insertions, 157 deletions
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 84f4f5d06f9d..f9fce70f396a 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c | |||
@@ -1104,7 +1104,7 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *)) | |||
1104 | /* A Reset IOCTL is only sent by the boot CD in extreme cases. */ | 1104 | /* A Reset IOCTL is only sent by the boot CD in extreme cases. */ |
1105 | /* There can never be any system activity ( network or disk ), but check */ | 1105 | /* There can never be any system activity ( network or disk ), but check */ |
1106 | /* anyway just as a good practice. */ | 1106 | /* anyway just as a good practice. */ |
1107 | pt = (ips_passthru_t *) SC->request_buffer; | 1107 | pt = (ips_passthru_t *) scsi_sglist(SC); |
1108 | if ((pt->CoppCP.cmd.reset.op_code == IPS_CMD_RESET_CHANNEL) && | 1108 | if ((pt->CoppCP.cmd.reset.op_code == IPS_CMD_RESET_CHANNEL) && |
1109 | (pt->CoppCP.cmd.reset.adapter_flag == 1)) { | 1109 | (pt->CoppCP.cmd.reset.adapter_flag == 1)) { |
1110 | if (ha->scb_activelist.count != 0) { | 1110 | if (ha->scb_activelist.count != 0) { |
@@ -1507,30 +1507,22 @@ static int ips_is_passthru(struct scsi_cmnd *SC) | |||
1507 | if ((SC->cmnd[0] == IPS_IOCTL_COMMAND) && | 1507 | if ((SC->cmnd[0] == IPS_IOCTL_COMMAND) && |
1508 | (SC->device->channel == 0) && | 1508 | (SC->device->channel == 0) && |
1509 | (SC->device->id == IPS_ADAPTER_ID) && | 1509 | (SC->device->id == IPS_ADAPTER_ID) && |
1510 | (SC->device->lun == 0) && SC->request_buffer) { | 1510 | (SC->device->lun == 0) && scsi_sglist(SC)) { |
1511 | if ((!SC->use_sg) && SC->request_bufflen && | 1511 | struct scatterlist *sg = scsi_sglist(SC); |
1512 | (((char *) SC->request_buffer)[0] == 'C') && | 1512 | char *buffer; |
1513 | (((char *) SC->request_buffer)[1] == 'O') && | 1513 | |
1514 | (((char *) SC->request_buffer)[2] == 'P') && | 1514 | /* kmap_atomic() ensures addressability of the user buffer.*/ |
1515 | (((char *) SC->request_buffer)[3] == 'P')) | 1515 | /* local_irq_save() protects the KM_IRQ0 address slot. */ |
1516 | return 1; | 1516 | local_irq_save(flags); |
1517 | else if (SC->use_sg) { | 1517 | buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; |
1518 | struct scatterlist *sg = SC->request_buffer; | 1518 | if (buffer && buffer[0] == 'C' && buffer[1] == 'O' && |
1519 | char *buffer; | 1519 | buffer[2] == 'P' && buffer[3] == 'P') { |
1520 | 1520 | kunmap_atomic(buffer - sg->offset, KM_IRQ0); | |
1521 | /* kmap_atomic() ensures addressability of the user buffer.*/ | 1521 | local_irq_restore(flags); |
1522 | /* local_irq_save() protects the KM_IRQ0 address slot. */ | 1522 | return 1; |
1523 | local_irq_save(flags); | 1523 | } |
1524 | buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | 1524 | kunmap_atomic(buffer - sg->offset, KM_IRQ0); |
1525 | if (buffer && buffer[0] == 'C' && buffer[1] == 'O' && | 1525 | local_irq_restore(flags); |
1526 | buffer[2] == 'P' && buffer[3] == 'P') { | ||
1527 | kunmap_atomic(buffer - sg->offset, KM_IRQ0); | ||
1528 | local_irq_restore(flags); | ||
1529 | return 1; | ||
1530 | } | ||
1531 | kunmap_atomic(buffer - sg->offset, KM_IRQ0); | ||
1532 | local_irq_restore(flags); | ||
1533 | } | ||
1534 | } | 1526 | } |
1535 | return 0; | 1527 | return 0; |
1536 | } | 1528 | } |
@@ -1581,18 +1573,14 @@ ips_make_passthru(ips_ha_t *ha, struct scsi_cmnd *SC, ips_scb_t *scb, int intr) | |||
1581 | { | 1573 | { |
1582 | ips_passthru_t *pt; | 1574 | ips_passthru_t *pt; |
1583 | int length = 0; | 1575 | int length = 0; |
1584 | int ret; | 1576 | int i, ret; |
1577 | struct scatterlist *sg = scsi_sglist(SC); | ||
1585 | 1578 | ||
1586 | METHOD_TRACE("ips_make_passthru", 1); | 1579 | METHOD_TRACE("ips_make_passthru", 1); |
1587 | 1580 | ||
1588 | if (!SC->use_sg) { | 1581 | scsi_for_each_sg(SC, sg, scsi_sg_count(SC), i) |
1589 | length = SC->request_bufflen; | 1582 | length += sg[i].length; |
1590 | } else { | 1583 | |
1591 | struct scatterlist *sg = SC->request_buffer; | ||
1592 | int i; | ||
1593 | for (i = 0; i < SC->use_sg; i++) | ||
1594 | length += sg[i].length; | ||
1595 | } | ||
1596 | if (length < sizeof (ips_passthru_t)) { | 1584 | if (length < sizeof (ips_passthru_t)) { |
1597 | /* wrong size */ | 1585 | /* wrong size */ |
1598 | DEBUG_VAR(1, "(%s%d) Passthru structure wrong size", | 1586 | DEBUG_VAR(1, "(%s%d) Passthru structure wrong size", |
@@ -2016,7 +2004,7 @@ ips_cleanup_passthru(ips_ha_t * ha, ips_scb_t * scb) | |||
2016 | 2004 | ||
2017 | METHOD_TRACE("ips_cleanup_passthru", 1); | 2005 | METHOD_TRACE("ips_cleanup_passthru", 1); |
2018 | 2006 | ||
2019 | if ((!scb) || (!scb->scsi_cmd) || (!scb->scsi_cmd->request_buffer)) { | 2007 | if ((!scb) || (!scb->scsi_cmd) || (!scsi_sglist(scb->scsi_cmd))) { |
2020 | DEBUG_VAR(1, "(%s%d) couldn't cleanup after passthru", | 2008 | DEBUG_VAR(1, "(%s%d) couldn't cleanup after passthru", |
2021 | ips_name, ha->host_num); | 2009 | ips_name, ha->host_num); |
2022 | 2010 | ||
@@ -2766,41 +2754,26 @@ ips_next(ips_ha_t * ha, int intr) | |||
2766 | /* copy in the CDB */ | 2754 | /* copy in the CDB */ |
2767 | memcpy(scb->cdb, SC->cmnd, SC->cmd_len); | 2755 | memcpy(scb->cdb, SC->cmnd, SC->cmd_len); |
2768 | 2756 | ||
2769 | /* Now handle the data buffer */ | 2757 | scb->sg_count = scsi_dma_map(SC); |
2770 | if (SC->use_sg) { | 2758 | BUG_ON(scb->sg_count < 0); |
2759 | if (scb->sg_count) { | ||
2771 | struct scatterlist *sg; | 2760 | struct scatterlist *sg; |
2772 | int i; | 2761 | int i; |
2773 | 2762 | ||
2774 | sg = SC->request_buffer; | ||
2775 | scb->sg_count = pci_map_sg(ha->pcidev, sg, SC->use_sg, | ||
2776 | SC->sc_data_direction); | ||
2777 | scb->flags |= IPS_SCB_MAP_SG; | 2763 | scb->flags |= IPS_SCB_MAP_SG; |
2778 | for (i = 0; i < scb->sg_count; i++) { | 2764 | |
2765 | scsi_for_each_sg(SC, sg, scb->sg_count, i) { | ||
2779 | if (ips_fill_scb_sg_single | 2766 | if (ips_fill_scb_sg_single |
2780 | (ha, sg_dma_address(&sg[i]), scb, i, | 2767 | (ha, sg_dma_address(sg), scb, i, |
2781 | sg_dma_len(&sg[i])) < 0) | 2768 | sg_dma_len(sg)) < 0) |
2782 | break; | 2769 | break; |
2783 | } | 2770 | } |
2784 | scb->dcdb.transfer_length = scb->data_len; | 2771 | scb->dcdb.transfer_length = scb->data_len; |
2785 | } else { | 2772 | } else { |
2786 | if (SC->request_bufflen) { | 2773 | scb->data_busaddr = 0L; |
2787 | scb->data_busaddr = | 2774 | scb->sg_len = 0; |
2788 | pci_map_single(ha->pcidev, | 2775 | scb->data_len = 0; |
2789 | SC->request_buffer, | 2776 | scb->dcdb.transfer_length = 0; |
2790 | SC->request_bufflen, | ||
2791 | SC->sc_data_direction); | ||
2792 | scb->flags |= IPS_SCB_MAP_SINGLE; | ||
2793 | ips_fill_scb_sg_single(ha, scb->data_busaddr, | ||
2794 | scb, 0, | ||
2795 | SC->request_bufflen); | ||
2796 | scb->dcdb.transfer_length = scb->data_len; | ||
2797 | } else { | ||
2798 | scb->data_busaddr = 0L; | ||
2799 | scb->sg_len = 0; | ||
2800 | scb->data_len = 0; | ||
2801 | scb->dcdb.transfer_length = 0; | ||
2802 | } | ||
2803 | |||
2804 | } | 2777 | } |
2805 | 2778 | ||
2806 | scb->dcdb.cmd_attribute = | 2779 | scb->dcdb.cmd_attribute = |
@@ -3277,52 +3250,32 @@ ips_done(ips_ha_t * ha, ips_scb_t * scb) | |||
3277 | * the rest of the data and continue. | 3250 | * the rest of the data and continue. |
3278 | */ | 3251 | */ |
3279 | if ((scb->breakup) || (scb->sg_break)) { | 3252 | if ((scb->breakup) || (scb->sg_break)) { |
3253 | struct scatterlist *sg; | ||
3254 | int sg_dma_index, ips_sg_index = 0; | ||
3255 | |||
3280 | /* we had a data breakup */ | 3256 | /* we had a data breakup */ |
3281 | scb->data_len = 0; | 3257 | scb->data_len = 0; |
3282 | 3258 | ||
3283 | if (scb->sg_count) { | 3259 | sg = scsi_sglist(scb->scsi_cmd); |
3284 | /* S/G request */ | ||
3285 | struct scatterlist *sg; | ||
3286 | int ips_sg_index = 0; | ||
3287 | int sg_dma_index; | ||
3288 | |||
3289 | sg = scb->scsi_cmd->request_buffer; | ||
3290 | |||
3291 | /* Spin forward to last dma chunk */ | ||
3292 | sg_dma_index = scb->breakup; | ||
3293 | |||
3294 | /* Take care of possible partial on last chunk */ | ||
3295 | ips_fill_scb_sg_single(ha, | ||
3296 | sg_dma_address(&sg | ||
3297 | [sg_dma_index]), | ||
3298 | scb, ips_sg_index++, | ||
3299 | sg_dma_len(&sg | ||
3300 | [sg_dma_index])); | ||
3301 | |||
3302 | for (; sg_dma_index < scb->sg_count; | ||
3303 | sg_dma_index++) { | ||
3304 | if (ips_fill_scb_sg_single | ||
3305 | (ha, | ||
3306 | sg_dma_address(&sg[sg_dma_index]), | ||
3307 | scb, ips_sg_index++, | ||
3308 | sg_dma_len(&sg[sg_dma_index])) < 0) | ||
3309 | break; | ||
3310 | 3260 | ||
3311 | } | 3261 | /* Spin forward to last dma chunk */ |
3262 | sg_dma_index = scb->breakup; | ||
3312 | 3263 | ||
3313 | } else { | 3264 | /* Take care of possible partial on last chunk */ |
3314 | /* Non S/G Request */ | 3265 | ips_fill_scb_sg_single(ha, |
3315 | (void) ips_fill_scb_sg_single(ha, | 3266 | sg_dma_address(&sg[sg_dma_index]), |
3316 | scb-> | 3267 | scb, ips_sg_index++, |
3317 | data_busaddr + | 3268 | sg_dma_len(&sg[sg_dma_index])); |
3318 | (scb->sg_break * | 3269 | |
3319 | ha->max_xfer), | 3270 | for (; sg_dma_index < scsi_sg_count(scb->scsi_cmd); |
3320 | scb, 0, | 3271 | sg_dma_index++) { |
3321 | scb->scsi_cmd-> | 3272 | if (ips_fill_scb_sg_single |
3322 | request_bufflen - | 3273 | (ha, |
3323 | (scb->sg_break * | 3274 | sg_dma_address(&sg[sg_dma_index]), |
3324 | ha->max_xfer)); | 3275 | scb, ips_sg_index++, |
3325 | } | 3276 | sg_dma_len(&sg[sg_dma_index])) < 0) |
3277 | break; | ||
3278 | } | ||
3326 | 3279 | ||
3327 | scb->dcdb.transfer_length = scb->data_len; | 3280 | scb->dcdb.transfer_length = scb->data_len; |
3328 | scb->dcdb.cmd_attribute |= | 3281 | scb->dcdb.cmd_attribute |= |
@@ -3553,32 +3506,27 @@ ips_send_wait(ips_ha_t * ha, ips_scb_t * scb, int timeout, int intr) | |||
3553 | static void | 3506 | static void |
3554 | ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count) | 3507 | ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count) |
3555 | { | 3508 | { |
3556 | if (scmd->use_sg) { | 3509 | int i; |
3557 | int i; | 3510 | unsigned int min_cnt, xfer_cnt; |
3558 | unsigned int min_cnt, xfer_cnt; | 3511 | char *cdata = (char *) data; |
3559 | char *cdata = (char *) data; | 3512 | unsigned char *buffer; |
3560 | unsigned char *buffer; | 3513 | unsigned long flags; |
3561 | unsigned long flags; | 3514 | struct scatterlist *sg = scsi_sglist(scmd); |
3562 | struct scatterlist *sg = scmd->request_buffer; | 3515 | |
3563 | for (i = 0, xfer_cnt = 0; | 3516 | for (i = 0, xfer_cnt = 0; |
3564 | (i < scmd->use_sg) && (xfer_cnt < count); i++) { | 3517 | (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) { |
3565 | min_cnt = min(count - xfer_cnt, sg[i].length); | 3518 | min_cnt = min(count - xfer_cnt, sg[i].length); |
3566 | 3519 | ||
3567 | /* kmap_atomic() ensures addressability of the data buffer.*/ | 3520 | /* kmap_atomic() ensures addressability of the data buffer.*/ |
3568 | /* local_irq_save() protects the KM_IRQ0 address slot. */ | 3521 | /* local_irq_save() protects the KM_IRQ0 address slot. */ |
3569 | local_irq_save(flags); | 3522 | local_irq_save(flags); |
3570 | buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset; | 3523 | buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset; |
3571 | memcpy(buffer, &cdata[xfer_cnt], min_cnt); | 3524 | memcpy(buffer, &cdata[xfer_cnt], min_cnt); |
3572 | kunmap_atomic(buffer - sg[i].offset, KM_IRQ0); | 3525 | kunmap_atomic(buffer - sg[i].offset, KM_IRQ0); |
3573 | local_irq_restore(flags); | 3526 | local_irq_restore(flags); |
3574 | 3527 | ||
3575 | xfer_cnt += min_cnt; | 3528 | xfer_cnt += min_cnt; |
3576 | } | 3529 | } |
3577 | |||
3578 | } else { | ||
3579 | unsigned int min_cnt = min(count, scmd->request_bufflen); | ||
3580 | memcpy(scmd->request_buffer, data, min_cnt); | ||
3581 | } | ||
3582 | } | 3530 | } |
3583 | 3531 | ||
3584 | /****************************************************************************/ | 3532 | /****************************************************************************/ |
@@ -3591,32 +3539,27 @@ ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count) | |||
3591 | static void | 3539 | static void |
3592 | ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count) | 3540 | ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count) |
3593 | { | 3541 | { |
3594 | if (scmd->use_sg) { | 3542 | int i; |
3595 | int i; | 3543 | unsigned int min_cnt, xfer_cnt; |
3596 | unsigned int min_cnt, xfer_cnt; | 3544 | char *cdata = (char *) data; |
3597 | char *cdata = (char *) data; | 3545 | unsigned char *buffer; |
3598 | unsigned char *buffer; | 3546 | unsigned long flags; |
3599 | unsigned long flags; | 3547 | struct scatterlist *sg = scsi_sglist(scmd); |
3600 | struct scatterlist *sg = scmd->request_buffer; | 3548 | |
3601 | for (i = 0, xfer_cnt = 0; | 3549 | for (i = 0, xfer_cnt = 0; |
3602 | (i < scmd->use_sg) && (xfer_cnt < count); i++) { | 3550 | (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) { |
3603 | min_cnt = min(count - xfer_cnt, sg[i].length); | 3551 | min_cnt = min(count - xfer_cnt, sg[i].length); |
3604 | 3552 | ||
3605 | /* kmap_atomic() ensures addressability of the data buffer.*/ | 3553 | /* kmap_atomic() ensures addressability of the data buffer.*/ |
3606 | /* local_irq_save() protects the KM_IRQ0 address slot. */ | 3554 | /* local_irq_save() protects the KM_IRQ0 address slot. */ |
3607 | local_irq_save(flags); | 3555 | local_irq_save(flags); |
3608 | buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset; | 3556 | buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset; |
3609 | memcpy(&cdata[xfer_cnt], buffer, min_cnt); | 3557 | memcpy(&cdata[xfer_cnt], buffer, min_cnt); |
3610 | kunmap_atomic(buffer - sg[i].offset, KM_IRQ0); | 3558 | kunmap_atomic(buffer - sg[i].offset, KM_IRQ0); |
3611 | local_irq_restore(flags); | 3559 | local_irq_restore(flags); |
3612 | 3560 | ||
3613 | xfer_cnt += min_cnt; | 3561 | xfer_cnt += min_cnt; |
3614 | } | 3562 | } |
3615 | |||
3616 | } else { | ||
3617 | unsigned int min_cnt = min(count, scmd->request_bufflen); | ||
3618 | memcpy(data, scmd->request_buffer, min_cnt); | ||
3619 | } | ||
3620 | } | 3563 | } |
3621 | 3564 | ||
3622 | /****************************************************************************/ | 3565 | /****************************************************************************/ |
@@ -4250,7 +4193,7 @@ ips_rdcap(ips_ha_t * ha, ips_scb_t * scb) | |||
4250 | 4193 | ||
4251 | METHOD_TRACE("ips_rdcap", 1); | 4194 | METHOD_TRACE("ips_rdcap", 1); |
4252 | 4195 | ||
4253 | if (scb->scsi_cmd->request_bufflen < 8) | 4196 | if (scsi_bufflen(scb->scsi_cmd) < 8) |
4254 | return (0); | 4197 | return (0); |
4255 | 4198 | ||
4256 | cap.lba = | 4199 | cap.lba = |
@@ -4635,8 +4578,7 @@ ips_freescb(ips_ha_t * ha, ips_scb_t * scb) | |||
4635 | 4578 | ||
4636 | METHOD_TRACE("ips_freescb", 1); | 4579 | METHOD_TRACE("ips_freescb", 1); |
4637 | if (scb->flags & IPS_SCB_MAP_SG) | 4580 | if (scb->flags & IPS_SCB_MAP_SG) |
4638 | pci_unmap_sg(ha->pcidev, scb->scsi_cmd->request_buffer, | 4581 | scsi_dma_unmap(scb->scsi_cmd); |
4639 | scb->scsi_cmd->use_sg, IPS_DMA_DIR(scb)); | ||
4640 | else if (scb->flags & IPS_SCB_MAP_SINGLE) | 4582 | else if (scb->flags & IPS_SCB_MAP_SINGLE) |
4641 | pci_unmap_single(ha->pcidev, scb->data_busaddr, scb->data_len, | 4583 | pci_unmap_single(ha->pcidev, scb->data_busaddr, scb->data_len, |
4642 | IPS_DMA_DIR(scb)); | 4584 | IPS_DMA_DIR(scb)); |