diff options
| -rw-r--r-- | drivers/ata/sata_promise.c | 87 |
1 files changed, 83 insertions, 4 deletions
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index deb26f04f2d7..3fdc7cbd9436 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c | |||
| @@ -50,6 +50,7 @@ | |||
| 50 | enum { | 50 | enum { |
| 51 | PDC_MAX_PORTS = 4, | 51 | PDC_MAX_PORTS = 4, |
| 52 | PDC_MMIO_BAR = 3, | 52 | PDC_MMIO_BAR = 3, |
| 53 | PDC_MAX_PRD = LIBATA_MAX_PRD - 1, /* -1 for ASIC PRD bug workaround */ | ||
| 53 | 54 | ||
| 54 | /* register offsets */ | 55 | /* register offsets */ |
| 55 | PDC_FEATURE = 0x04, /* Feature/Error reg (per port) */ | 56 | PDC_FEATURE = 0x04, /* Feature/Error reg (per port) */ |
| @@ -157,7 +158,7 @@ static struct scsi_host_template pdc_ata_sht = { | |||
| 157 | .queuecommand = ata_scsi_queuecmd, | 158 | .queuecommand = ata_scsi_queuecmd, |
| 158 | .can_queue = ATA_DEF_QUEUE, | 159 | .can_queue = ATA_DEF_QUEUE, |
| 159 | .this_id = ATA_SHT_THIS_ID, | 160 | .this_id = ATA_SHT_THIS_ID, |
| 160 | .sg_tablesize = LIBATA_MAX_PRD, | 161 | .sg_tablesize = PDC_MAX_PRD, |
| 161 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 162 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
| 162 | .emulated = ATA_SHT_EMULATED, | 163 | .emulated = ATA_SHT_EMULATED, |
| 163 | .use_clustering = ATA_SHT_USE_CLUSTERING, | 164 | .use_clustering = ATA_SHT_USE_CLUSTERING, |
| @@ -523,6 +524,84 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc) | |||
| 523 | memcpy(buf+31, cdb, cdb_len); | 524 | memcpy(buf+31, cdb, cdb_len); |
| 524 | } | 525 | } |
| 525 | 526 | ||
| 527 | /** | ||
| 528 | * pdc_fill_sg - Fill PCI IDE PRD table | ||
| 529 | * @qc: Metadata associated with taskfile to be transferred | ||
| 530 | * | ||
| 531 | * Fill PCI IDE PRD (scatter-gather) table with segments | ||
| 532 | * associated with the current disk command. | ||
| 533 | * Make sure hardware does not choke on it. | ||
| 534 | * | ||
| 535 | * LOCKING: | ||
| 536 | * spin_lock_irqsave(host lock) | ||
| 537 | * | ||
| 538 | */ | ||
| 539 | static void pdc_fill_sg(struct ata_queued_cmd *qc) | ||
| 540 | { | ||
| 541 | struct ata_port *ap = qc->ap; | ||
| 542 | struct scatterlist *sg; | ||
| 543 | unsigned int idx; | ||
| 544 | const u32 SG_COUNT_ASIC_BUG = 41*4; | ||
| 545 | |||
| 546 | if (!(qc->flags & ATA_QCFLAG_DMAMAP)) | ||
| 547 | return; | ||
| 548 | |||
| 549 | WARN_ON(qc->__sg == NULL); | ||
| 550 | WARN_ON(qc->n_elem == 0 && qc->pad_len == 0); | ||
| 551 | |||
| 552 | idx = 0; | ||
| 553 | ata_for_each_sg(sg, qc) { | ||
| 554 | u32 addr, offset; | ||
| 555 | u32 sg_len, len; | ||
| 556 | |||
| 557 | /* determine if physical DMA addr spans 64K boundary. | ||
| 558 | * Note h/w doesn't support 64-bit, so we unconditionally | ||
| 559 | * truncate dma_addr_t to u32. | ||
| 560 | */ | ||
| 561 | addr = (u32) sg_dma_address(sg); | ||
| 562 | sg_len = sg_dma_len(sg); | ||
| 563 | |||
| 564 | while (sg_len) { | ||
| 565 | offset = addr & 0xffff; | ||
| 566 | len = sg_len; | ||
| 567 | if ((offset + sg_len) > 0x10000) | ||
| 568 | len = 0x10000 - offset; | ||
| 569 | |||
| 570 | ap->prd[idx].addr = cpu_to_le32(addr); | ||
| 571 | ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff); | ||
| 572 | VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); | ||
| 573 | |||
| 574 | idx++; | ||
| 575 | sg_len -= len; | ||
| 576 | addr += len; | ||
| 577 | } | ||
| 578 | } | ||
| 579 | |||
| 580 | if (idx) { | ||
| 581 | u32 len = le32_to_cpu(ap->prd[idx - 1].flags_len); | ||
| 582 | |||
| 583 | if (len > SG_COUNT_ASIC_BUG) { | ||
| 584 | u32 addr; | ||
| 585 | |||
| 586 | VPRINTK("Splitting last PRD.\n"); | ||
| 587 | |||
| 588 | addr = le32_to_cpu(ap->prd[idx - 1].addr); | ||
| 589 | ap->prd[idx - 1].flags_len -= cpu_to_le32(SG_COUNT_ASIC_BUG); | ||
| 590 | VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG); | ||
| 591 | |||
| 592 | addr = addr + len - SG_COUNT_ASIC_BUG; | ||
| 593 | len = SG_COUNT_ASIC_BUG; | ||
| 594 | ap->prd[idx].addr = cpu_to_le32(addr); | ||
| 595 | ap->prd[idx].flags_len = cpu_to_le32(len); | ||
| 596 | VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); | ||
| 597 | |||
| 598 | idx++; | ||
| 599 | } | ||
| 600 | |||
| 601 | ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); | ||
| 602 | } | ||
| 603 | } | ||
| 604 | |||
| 526 | static void pdc_qc_prep(struct ata_queued_cmd *qc) | 605 | static void pdc_qc_prep(struct ata_queued_cmd *qc) |
| 527 | { | 606 | { |
| 528 | struct pdc_port_priv *pp = qc->ap->private_data; | 607 | struct pdc_port_priv *pp = qc->ap->private_data; |
| @@ -532,7 +611,7 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) | |||
| 532 | 611 | ||
| 533 | switch (qc->tf.protocol) { | 612 | switch (qc->tf.protocol) { |
| 534 | case ATA_PROT_DMA: | 613 | case ATA_PROT_DMA: |
| 535 | ata_qc_prep(qc); | 614 | pdc_fill_sg(qc); |
| 536 | /* fall through */ | 615 | /* fall through */ |
| 537 | 616 | ||
| 538 | case ATA_PROT_NODATA: | 617 | case ATA_PROT_NODATA: |
| @@ -548,11 +627,11 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) | |||
| 548 | break; | 627 | break; |
| 549 | 628 | ||
| 550 | case ATA_PROT_ATAPI: | 629 | case ATA_PROT_ATAPI: |
| 551 | ata_qc_prep(qc); | 630 | pdc_fill_sg(qc); |
| 552 | break; | 631 | break; |
| 553 | 632 | ||
| 554 | case ATA_PROT_ATAPI_DMA: | 633 | case ATA_PROT_ATAPI_DMA: |
| 555 | ata_qc_prep(qc); | 634 | pdc_fill_sg(qc); |
| 556 | /*FALLTHROUGH*/ | 635 | /*FALLTHROUGH*/ |
| 557 | case ATA_PROT_ATAPI_NODATA: | 636 | case ATA_PROT_ATAPI_NODATA: |
| 558 | pdc_atapi_pkt(qc); | 637 | pdc_atapi_pkt(qc); |
