diff options
author | Albert Lee <albertcc@tw.ibm.com> | 2005-08-12 02:15:34 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-08-12 02:44:20 -0400 |
commit | 6ae4cfb5711b6f2878c9e384617971d98c34a7f5 (patch) | |
tree | d5e4f3ab6381c0c5429429eb9f4159e321af8431 /drivers/scsi | |
parent | bc68552faad0e134eb22281343d5ae5a4873fa80 (diff) |
[PATCH] libata ata_data_xfer() fix
PATCH 1/2: ata_data_xfer() fix
Changes:
- Modify ata_mmio_data_xfer() and ata_pio_data_xfer() to handle odd-lengthed buffer.
- Add some function comments
This patch does not reuse ap->pad as alignment buffer since
using local variable seems good enough.
Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/libata-core.c | 111 |
1 files changed, 108 insertions, 3 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 73b1f72b7e43..8f6e536d8924 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -2519,6 +2519,20 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) | |||
2519 | #endif /* __BIG_ENDIAN */ | 2519 | #endif /* __BIG_ENDIAN */ |
2520 | } | 2520 | } |
2521 | 2521 | ||
2522 | /** | ||
2523 | * ata_mmio_data_xfer - Transfer data by MMIO | ||
2524 | * @ap: port to read/write | ||
2525 | * @buf: data buffer | ||
2526 | * @buflen: buffer length | ||
2527 | * @do_write: read/write | ||
2528 | * | ||
2529 | * Transfer data from/to the device data register by MMIO. | ||
2530 | * | ||
2531 | * LOCKING: | ||
2532 | * Inherited from caller. | ||
2533 | * | ||
2534 | */ | ||
2535 | |||
2522 | static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, | 2536 | static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, |
2523 | unsigned int buflen, int write_data) | 2537 | unsigned int buflen, int write_data) |
2524 | { | 2538 | { |
@@ -2527,6 +2541,7 @@ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, | |||
2527 | u16 *buf16 = (u16 *) buf; | 2541 | u16 *buf16 = (u16 *) buf; |
2528 | void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr; | 2542 | void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr; |
2529 | 2543 | ||
2544 | /* Transfer multiple of 2 bytes */ | ||
2530 | if (write_data) { | 2545 | if (write_data) { |
2531 | for (i = 0; i < words; i++) | 2546 | for (i = 0; i < words; i++) |
2532 | writew(le16_to_cpu(buf16[i]), mmio); | 2547 | writew(le16_to_cpu(buf16[i]), mmio); |
@@ -2534,19 +2549,76 @@ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, | |||
2534 | for (i = 0; i < words; i++) | 2549 | for (i = 0; i < words; i++) |
2535 | buf16[i] = cpu_to_le16(readw(mmio)); | 2550 | buf16[i] = cpu_to_le16(readw(mmio)); |
2536 | } | 2551 | } |
2552 | |||
2553 | /* Transfer trailing 1 byte, if any. */ | ||
2554 | if (unlikely(buflen & 0x01)) { | ||
2555 | u16 align_buf[1] = { 0 }; | ||
2556 | unsigned char *trailing_buf = buf + buflen - 1; | ||
2557 | |||
2558 | if (write_data) { | ||
2559 | memcpy(align_buf, trailing_buf, 1); | ||
2560 | writew(le16_to_cpu(align_buf[0]), mmio); | ||
2561 | } else { | ||
2562 | align_buf[0] = cpu_to_le16(readw(mmio)); | ||
2563 | memcpy(trailing_buf, align_buf, 1); | ||
2564 | } | ||
2565 | } | ||
2537 | } | 2566 | } |
2538 | 2567 | ||
2568 | /** | ||
2569 | * ata_pio_data_xfer - Transfer data by PIO | ||
2570 | * @ap: port to read/write | ||
2571 | * @buf: data buffer | ||
2572 | * @buflen: buffer length | ||
2573 | * @do_write: read/write | ||
2574 | * | ||
2575 | * Transfer data from/to the device data register by PIO. | ||
2576 | * | ||
2577 | * LOCKING: | ||
2578 | * Inherited from caller. | ||
2579 | * | ||
2580 | */ | ||
2581 | |||
2539 | static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf, | 2582 | static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf, |
2540 | unsigned int buflen, int write_data) | 2583 | unsigned int buflen, int write_data) |
2541 | { | 2584 | { |
2542 | unsigned int dwords = buflen >> 1; | 2585 | unsigned int words = buflen >> 1; |
2543 | 2586 | ||
2587 | /* Transfer multiple of 2 bytes */ | ||
2544 | if (write_data) | 2588 | if (write_data) |
2545 | outsw(ap->ioaddr.data_addr, buf, dwords); | 2589 | outsw(ap->ioaddr.data_addr, buf, words); |
2546 | else | 2590 | else |
2547 | insw(ap->ioaddr.data_addr, buf, dwords); | 2591 | insw(ap->ioaddr.data_addr, buf, words); |
2592 | |||
2593 | /* Transfer trailing 1 byte, if any. */ | ||
2594 | if (unlikely(buflen & 0x01)) { | ||
2595 | u16 align_buf[1] = { 0 }; | ||
2596 | unsigned char *trailing_buf = buf + buflen - 1; | ||
2597 | |||
2598 | if (write_data) { | ||
2599 | memcpy(align_buf, trailing_buf, 1); | ||
2600 | outw(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr); | ||
2601 | } else { | ||
2602 | align_buf[0] = cpu_to_le16(inw(ap->ioaddr.data_addr)); | ||
2603 | memcpy(trailing_buf, align_buf, 1); | ||
2604 | } | ||
2605 | } | ||
2548 | } | 2606 | } |
2549 | 2607 | ||
2608 | /** | ||
2609 | * ata_data_xfer - Transfer data from/to the data register. | ||
2610 | * @ap: port to read/write | ||
2611 | * @buf: data buffer | ||
2612 | * @buflen: buffer length | ||
2613 | * @do_write: read/write | ||
2614 | * | ||
2615 | * Transfer data from/to the device data register. | ||
2616 | * | ||
2617 | * LOCKING: | ||
2618 | * Inherited from caller. | ||
2619 | * | ||
2620 | */ | ||
2621 | |||
2550 | static void ata_data_xfer(struct ata_port *ap, unsigned char *buf, | 2622 | static void ata_data_xfer(struct ata_port *ap, unsigned char *buf, |
2551 | unsigned int buflen, int do_write) | 2623 | unsigned int buflen, int do_write) |
2552 | { | 2624 | { |
@@ -2556,6 +2628,16 @@ static void ata_data_xfer(struct ata_port *ap, unsigned char *buf, | |||
2556 | ata_pio_data_xfer(ap, buf, buflen, do_write); | 2628 | ata_pio_data_xfer(ap, buf, buflen, do_write); |
2557 | } | 2629 | } |
2558 | 2630 | ||
2631 | /** | ||
2632 | * ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data. | ||
2633 | * @qc: Command on going | ||
2634 | * | ||
2635 | * Transfer ATA_SECT_SIZE of data from/to the ATA device. | ||
2636 | * | ||
2637 | * LOCKING: | ||
2638 | * Inherited from caller. | ||
2639 | */ | ||
2640 | |||
2559 | static void ata_pio_sector(struct ata_queued_cmd *qc) | 2641 | static void ata_pio_sector(struct ata_queued_cmd *qc) |
2560 | { | 2642 | { |
2561 | int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); | 2643 | int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); |
@@ -2594,6 +2676,18 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) | |||
2594 | kunmap(page); | 2676 | kunmap(page); |
2595 | } | 2677 | } |
2596 | 2678 | ||
2679 | /** | ||
2680 | * __atapi_pio_bytes - Transfer data from/to the ATAPI device. | ||
2681 | * @qc: Command on going | ||
2682 | * @bytes: number of bytes | ||
2683 | * | ||
2684 | * Transfer Transfer data from/to the ATAPI device. | ||
2685 | * | ||
2686 | * LOCKING: | ||
2687 | * Inherited from caller. | ||
2688 | * | ||
2689 | */ | ||
2690 | |||
2597 | static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) | 2691 | static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) |
2598 | { | 2692 | { |
2599 | int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); | 2693 | int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); |
@@ -2645,6 +2739,17 @@ next_sg: | |||
2645 | } | 2739 | } |
2646 | } | 2740 | } |
2647 | 2741 | ||
2742 | /** | ||
2743 | * atapi_pio_bytes - Transfer data from/to the ATAPI device. | ||
2744 | * @qc: Command on going | ||
2745 | * | ||
2746 | * Transfer Transfer data from/to the ATAPI device. | ||
2747 | * | ||
2748 | * LOCKING: | ||
2749 | * Inherited from caller. | ||
2750 | * | ||
2751 | */ | ||
2752 | |||
2648 | static void atapi_pio_bytes(struct ata_queued_cmd *qc) | 2753 | static void atapi_pio_bytes(struct ata_queued_cmd *qc) |
2649 | { | 2754 | { |
2650 | struct ata_port *ap = qc->ap; | 2755 | struct ata_port *ap = qc->ap; |