/spare/repo/libata-dev branch 'upstream-fixes'
authorJeff Garzik <jgarzik@pobox.com>
Tue, 23 Aug 2005 07:35:44 +0000 (03:35 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Tue, 23 Aug 2005 07:35:44 +0000 (03:35 -0400)
1  2 
drivers/scsi/ahci.c
drivers/scsi/ata_piix.c
drivers/scsi/libata-core.c
drivers/scsi/libata.h
drivers/scsi/sata_promise.c

diff --combined drivers/scsi/ahci.c
index 0b228ff671439fedc0a24a10afd2e1f6b7215aa7,e3b9692b9688063e28e098617fed3980645a3f9b..348493982b56d550486497fa3de9294ac5bc1f10
@@@ -269,8 -269,6 +269,8 @@@ static struct pci_device_id ahci_pci_tb
          board_ahci }, /* ESB2 */
        { PCI_VENDOR_ID_INTEL, 0x2683, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_ahci }, /* ESB2 */
 +      { PCI_VENDOR_ID_INTEL, 0x27c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 +        board_ahci }, /* ICH7-M DH */
        { }     /* terminate list */
  };
  
@@@ -698,6 -696,9 +698,6 @@@ static int ahci_qc_issue(struct ata_que
        struct ata_port *ap = qc->ap;
        void *port_mmio = (void *) ap->ioaddr.cmd_addr;
  
 -      writel(1, port_mmio + PORT_SCR_ACT);
 -      readl(port_mmio + PORT_SCR_ACT);        /* flush */
 -
        writel(1, port_mmio + PORT_CMD_ISSUE);
        readl(port_mmio + PORT_CMD_ISSUE);      /* flush */
  
@@@ -1104,6 -1105,7 +1104,7 @@@ MODULE_AUTHOR("Jeff Garzik")
  MODULE_DESCRIPTION("AHCI SATA low-level driver");
  MODULE_LICENSE("GPL");
  MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
+ MODULE_VERSION(DRV_VERSION);
  
  module_init(ahci_init);
  module_exit(ahci_exit);
diff --combined drivers/scsi/ata_piix.c
index 9f1bdfbd8d0a00c7fa09a674e6311ed52124ba0e,d96ebf9d22280944dccefbb78e2e60f2029694d6..03695616e59ef597c9c3ce51a8c425814f96af63
@@@ -32,7 -32,7 +32,7 @@@
  #include <linux/libata.h>
  
  #define DRV_NAME      "ata_piix"
- #define DRV_VERSION   "1.03"
+ #define DRV_VERSION   "1.04"
  
  enum {
        PIIX_IOCFG              = 0x54, /* IDE I/O configuration register */
@@@ -629,13 -629,13 +629,13 @@@ static int piix_init_one (struct pci_de
        port_info[1] = NULL;
  
        if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
 -               u8 tmp;
 -               pci_read_config_byte(pdev, PIIX_SCC, &tmp);
 -               if (tmp == PIIX_AHCI_DEVICE) {
 -                       int rc = piix_disable_ahci(pdev);
 -                       if (rc)
 -                           return rc;
 -               }
 +              u8 tmp;
 +              pci_read_config_byte(pdev, PIIX_SCC, &tmp);
 +              if (tmp == PIIX_AHCI_DEVICE) {
 +                      int rc = piix_disable_ahci(pdev);
 +                      if (rc)
 +                              return rc;
 +              }
        }
  
        if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {
index 2f68563ac3a33050cd7bb83078f397521fcca31e,f4e7dcb6492bcdbfed7d9dced994caf44d24d38b..157a3e914cb73a3c62bc4e19443edcb99d48ac3b
@@@ -1304,12 -1304,12 +1304,12 @@@ static inline u8 ata_dev_knobble(struc
  /**
   *    ata_dev_config - Run device specific handlers and check for
   *                     SATA->PATA bridges
 - *    @ap: Bus 
 + *    @ap: Bus
   *    @i:  Device
   *
   *    LOCKING:
   */
 - 
 +
  void ata_dev_config(struct ata_port *ap, unsigned int i)
  {
        /* limit bridge transfers to udma5, 200 sectors */
@@@ -2268,19 -2268,6 +2268,6 @@@ void ata_qc_prep(struct ata_queued_cmd 
   *    spin_lock_irqsave(host_set lock)
   */
  
- /**
-  *    ata_sg_init_one - Prepare a one-entry scatter-gather list.
-  *    @qc:  Queued command
-  *    @buf:  transfer buffer
-  *    @buflen:  length of buf
-  *
-  *    Builds a single-entry scatter-gather list to initiate a
-  *    transfer utilizing the specified buffer.
-  *
-  *    LOCKING:
-  */
  void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
  {
        struct scatterlist *sg;
   *    spin_lock_irqsave(host_set lock)
   */
  
- /**
-  *    ata_sg_init - Assign a scatter gather list to a queued command
-  *    @qc:  Queued command
-  *    @sg:  Scatter-gather list
-  *    @n_elem:  length of sg list
-  *
-  *    Attaches a scatter-gather list to a queued command.
-  *
-  *    LOCKING:
-  */
  void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
                 unsigned int n_elem)
  {
@@@ -2401,26 -2376,6 +2376,26 @@@ static int ata_sg_setup(struct ata_queu
        return 0;
  }
  
 +/**
 + *    ata_poll_qc_complete - turn irq back on and finish qc
 + *    @qc: Command to complete
 + *    @drv_stat: ATA status register content
 + *
 + *    LOCKING:
 + *    None.  (grabs host lock)
 + */
 +
 +void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
 +{
 +      struct ata_port *ap = qc->ap;
 +
 +      spin_lock_irq(&ap->host_set->lock);
 +      ap->flags &= ~ATA_FLAG_NOINTR;
 +      ata_irq_on(ap);
 +      ata_qc_complete(qc, drv_stat);
 +      spin_unlock_irq(&ap->host_set->lock);
 +}
 +
  /**
   *    ata_pio_poll -
   *    @ap:
@@@ -2512,7 -2467,9 +2487,7 @@@ static void ata_pio_complete (struct at
  
        ap->pio_task_state = PIO_ST_IDLE;
  
 -      ata_irq_on(ap);
 -
 -      ata_qc_complete(qc, drv_stat);
 +      ata_poll_qc_complete(qc, drv_stat);
  }
  
  
@@@ -2537,20 -2494,6 +2512,20 @@@ void swap_buf_le16(u16 *buf, unsigned i
  #endif /* __BIG_ENDIAN */
  }
  
 +/**
 + *    ata_mmio_data_xfer - Transfer data by MMIO
 + *    @ap: port to read/write
 + *    @buf: data buffer
 + *    @buflen: buffer length
 + *    @do_write: read/write
 + *
 + *    Transfer data from/to the device data register by MMIO.
 + *
 + *    LOCKING:
 + *    Inherited from caller.
 + *
 + */
 +
  static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
                               unsigned int buflen, int write_data)
  {
        u16 *buf16 = (u16 *) buf;
        void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
  
 +      /* Transfer multiple of 2 bytes */
        if (write_data) {
                for (i = 0; i < words; i++)
                        writew(le16_to_cpu(buf16[i]), mmio);
                for (i = 0; i < words; i++)
                        buf16[i] = cpu_to_le16(readw(mmio));
        }
 +
 +      /* Transfer trailing 1 byte, if any. */
 +      if (unlikely(buflen & 0x01)) {
 +              u16 align_buf[1] = { 0 };
 +              unsigned char *trailing_buf = buf + buflen - 1;
 +
 +              if (write_data) {
 +                      memcpy(align_buf, trailing_buf, 1);
 +                      writew(le16_to_cpu(align_buf[0]), mmio);
 +              } else {
 +                      align_buf[0] = cpu_to_le16(readw(mmio));
 +                      memcpy(trailing_buf, align_buf, 1);
 +              }
 +      }
  }
  
 +/**
 + *    ata_pio_data_xfer - Transfer data by PIO
 + *    @ap: port to read/write
 + *    @buf: data buffer
 + *    @buflen: buffer length
 + *    @do_write: read/write
 + *
 + *    Transfer data from/to the device data register by PIO.
 + *
 + *    LOCKING:
 + *    Inherited from caller.
 + *
 + */
 +
  static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
                              unsigned int buflen, int write_data)
  {
 -      unsigned int dwords = buflen >> 1;
 +      unsigned int words = buflen >> 1;
  
 +      /* Transfer multiple of 2 bytes */
        if (write_data)
 -              outsw(ap->ioaddr.data_addr, buf, dwords);
 +              outsw(ap->ioaddr.data_addr, buf, words);
        else
 -              insw(ap->ioaddr.data_addr, buf, dwords);
 +              insw(ap->ioaddr.data_addr, buf, words);
 +
 +      /* Transfer trailing 1 byte, if any. */
 +      if (unlikely(buflen & 0x01)) {
 +              u16 align_buf[1] = { 0 };
 +              unsigned char *trailing_buf = buf + buflen - 1;
 +
 +              if (write_data) {
 +                      memcpy(align_buf, trailing_buf, 1);
 +                      outw(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
 +              } else {
 +                      align_buf[0] = cpu_to_le16(inw(ap->ioaddr.data_addr));
 +                      memcpy(trailing_buf, align_buf, 1);
 +              }
 +      }
  }
  
 +/**
 + *    ata_data_xfer - Transfer data from/to the data register.
 + *    @ap: port to read/write
 + *    @buf: data buffer
 + *    @buflen: buffer length
 + *    @do_write: read/write
 + *
 + *    Transfer data from/to the device data register.
 + *
 + *    LOCKING:
 + *    Inherited from caller.
 + *
 + */
 +
  static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
                          unsigned int buflen, int do_write)
  {
                ata_pio_data_xfer(ap, buf, buflen, do_write);
  }
  
 +/**
 + *    ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data.
 + *    @qc: Command on going
 + *
 + *    Transfer ATA_SECT_SIZE of data from/to the ATA device.
 + *
 + *    LOCKING:
 + *    Inherited from caller.
 + */
 +
  static void ata_pio_sector(struct ata_queued_cmd *qc)
  {
        int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
        kunmap(page);
  }
  
 +/**
 + *    __atapi_pio_bytes - Transfer data from/to the ATAPI device.
 + *    @qc: Command on going
 + *    @bytes: number of bytes
 + *
 + *    Transfer Transfer data from/to the ATAPI device.
 + *
 + *    LOCKING:
 + *    Inherited from caller.
 + *
 + */
 +
  static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
  {
        int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
        unsigned char *buf;
        unsigned int offset, count;
  
 -      if (qc->curbytes == qc->nbytes - bytes)
 +      if (qc->curbytes + bytes >= qc->nbytes)
                ap->pio_task_state = PIO_ST_LAST;
  
  next_sg:
 +      if (unlikely(qc->cursg >= qc->n_elem)) {
 +              /* 
 +               * The end of qc->sg is reached and the device expects
 +               * more data to transfer. In order not to overrun qc->sg
 +               * and fulfill length specified in the byte count register,
 +               *    - for read case, discard trailing data from the device
 +               *    - for write case, padding zero data to the device
 +               */
 +              u16 pad_buf[1] = { 0 };
 +              unsigned int words = bytes >> 1;
 +              unsigned int i;
 +
 +              if (words) /* warning if bytes > 1 */
 +                      printk(KERN_WARNING "ata%u: %u bytes trailing data\n", 
 +                             ap->id, bytes);
 +
 +              for (i = 0; i < words; i++)
 +                      ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
 +
 +              ap->pio_task_state = PIO_ST_LAST;
 +              return;
 +      }
 +
        sg = &qc->sg[qc->cursg];
  
        page = sg->page;
  
        kunmap(page);
  
 -      if (bytes) {
 +      if (bytes)
                goto next_sg;
 -      }
  }
  
 +/**
 + *    atapi_pio_bytes - Transfer data from/to the ATAPI device.
 + *    @qc: Command on going
 + *
 + *    Transfer Transfer data from/to the ATAPI device.
 + *
 + *    LOCKING:
 + *    Inherited from caller.
 + *
 + */
 +
  static void atapi_pio_bytes(struct ata_queued_cmd *qc)
  {
        struct ata_port *ap = qc->ap;
@@@ -2862,7 -2692,9 +2837,7 @@@ static void ata_pio_block(struct ata_po
                if ((status & ATA_DRQ) == 0) {
                        ap->pio_task_state = PIO_ST_IDLE;
  
 -                      ata_irq_on(ap);
 -
 -                      ata_qc_complete(qc, status);
 +                      ata_poll_qc_complete(qc, status);
                        return;
                }
  
@@@ -2892,7 -2724,9 +2867,7 @@@ static void ata_pio_error(struct ata_po
  
        ap->pio_task_state = PIO_ST_IDLE;
  
 -      ata_irq_on(ap);
 -
 -      ata_qc_complete(qc, drv_stat | ATA_ERR);
 +      ata_poll_qc_complete(qc, drv_stat | ATA_ERR);
  }
  
  static void ata_pio_task(void *_data)
@@@ -3227,14 -3061,9 +3202,14 @@@ void ata_qc_complete(struct ata_queued_
        if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
                ata_sg_clean(qc);
  
 +      /* atapi: mark qc as inactive to prevent the interrupt handler
 +       * from completing the command twice later, before the error handler
 +       * is called. (when rc != 0 and atapi request sense is needed)
 +       */
 +      qc->flags &= ~ATA_QCFLAG_ACTIVE;
 +
        /* call completion callback */
        rc = qc->complete_fn(qc, drv_stat);
 -      qc->flags &= ~ATA_QCFLAG_ACTIVE;
  
        /* if callback indicates not to complete command (non-zero),
         * return immediately
@@@ -3364,13 -3193,11 +3339,13 @@@ int ata_qc_issue_prot(struct ata_queued
                break;
  
        case ATA_PROT_ATAPI_NODATA:
 +              ap->flags |= ATA_FLAG_NOINTR;
                ata_tf_to_host_nolock(ap, &qc->tf);
                queue_work(ata_wq, &ap->packet_task);
                break;
  
        case ATA_PROT_ATAPI_DMA:
 +              ap->flags |= ATA_FLAG_NOINTR;
                ap->ops->tf_load(ap, &qc->tf);   /* load tf registers */
                ap->ops->bmdma_setup(qc);           /* set up bmdma */
                queue_work(ata_wq, &ap->packet_task);
@@@ -3724,8 -3551,7 +3699,8 @@@ irqreturn_t ata_interrupt (int irq, voi
                struct ata_port *ap;
  
                ap = host_set->ports[i];
 -              if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
 +              if (ap &&
 +                  !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
                        struct ata_queued_cmd *qc;
  
                        qc = ata_qc_from_tag(ap, ap->active_tag);
@@@ -3777,27 -3603,19 +3752,27 @@@ static void atapi_packet_task(void *_da
        /* send SCSI cdb */
        DPRINTK("send cdb\n");
        assert(ap->cdb_len >= 12);
 -      ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
  
 -      /* if we are DMA'ing, irq handler takes over from here */
 -      if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
 -              ap->ops->bmdma_start(qc);           /* initiate bmdma */
 +      if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
 +          qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
 +              unsigned long flags;
  
 -      /* non-data commands are also handled via irq */
 -      else if (qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
 -              /* do nothing */
 -      }
 +              /* Once we're done issuing command and kicking bmdma,
 +               * irq handler takes over.  To not lose irq, we need
 +               * to clear NOINTR flag before sending cdb, but
 +               * interrupt handler shouldn't be invoked before we're
 +               * finished.  Hence, the following locking.
 +               */
 +              spin_lock_irqsave(&ap->host_set->lock, flags);
 +              ap->flags &= ~ATA_FLAG_NOINTR;
 +              ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
 +              if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
 +                      ap->ops->bmdma_start(qc);       /* initiate bmdma */
 +              spin_unlock_irqrestore(&ap->host_set->lock, flags);
 +      } else {
 +              ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
  
 -      /* PIO commands are handled by polling */
 -      else {
 +              /* PIO commands are handled by polling */
                ap->pio_task_state = PIO_ST;
                queue_work(ata_wq, &ap->pio_task);
        }
        return;
  
  err_out:
 -      ata_qc_complete(qc, ATA_ERR);
 +      ata_poll_qc_complete(qc, ATA_ERR);
  }
  
  
diff --combined drivers/scsi/libata.h
index 91b68eedb3c9bc24f1871dfb0c027089a76b0168,3e7f4843020f50eb58744d6dbacc1d9cb592aeb6..620d21772bd6d23341ca1454374c632db44b74f7
@@@ -26,7 -26,7 +26,7 @@@
  #define __LIBATA_H__
  
  #define DRV_NAME      "libata"
- #define DRV_VERSION   "1.11"  /* must be exactly four chars */
+ #define DRV_VERSION   "1.12"  /* must be exactly four chars */
  
  struct ata_scsi_args {
        u16                     *id;
@@@ -72,7 -72,7 +72,7 @@@ extern unsigned int ata_scsiop_report_l
  extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
                            void (*done)(struct scsi_cmnd *),
                            u8 asc, u8 ascq);
 -extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, 
 +extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
                          unsigned int (*actor) (struct ata_scsi_args *args,
                                             u8 *rbuf, unsigned int buflen));
  
index 6defd79623592858ec4031c7c612c5c18e03ad3f,919fb314ad10c226ebaccdd1c8ace32980fc55d0..defcc1fb3f1684e4399d1d008d3d67deffca4f58
@@@ -40,7 -40,7 +40,7 @@@
  #include "sata_promise.h"
  
  #define DRV_NAME      "sata_promise"
- #define DRV_VERSION   "1.01"
+ #define DRV_VERSION   "1.02"
  
  
  enum {
@@@ -181,10 -181,6 +181,10 @@@ static struct pci_device_id pdc_ata_pci
          board_20319 },
        { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_20319 },
 +      { PCI_VENDOR_ID_PROMISE, 0x3519, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 +        board_20319 },
 +      { PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 +        board_20319 },
        { PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_20319 },
  
@@@ -445,8 -441,7 +445,8 @@@ static irqreturn_t pdc_interrupt (int i
                VPRINTK("port %u\n", i);
                ap = host_set->ports[i];
                tmp = mask & (1 << (i + 1));
 -              if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
 +              if (tmp && ap &&
 +                  !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
                        struct ata_queued_cmd *qc;
  
                        qc = ata_qc_from_tag(ap, ap->active_tag);