Merge branch 'upstream-fixes'
authorJeff Garzik <jgarzik@pobox.com>
Sun, 29 Jan 2006 17:41:09 +0000 (12:41 -0500)
committerJeff Garzik <jgarzik@pobox.com>
Sun, 29 Jan 2006 17:41:09 +0000 (12:41 -0500)
1  2 
drivers/scsi/ahci.c

diff --combined drivers/scsi/ahci.c
@@@ -66,8 -66,6 +66,8 @@@ enum 
        AHCI_IRQ_ON_SG          = (1 << 31),
        AHCI_CMD_ATAPI          = (1 << 5),
        AHCI_CMD_WRITE          = (1 << 6),
 +      AHCI_CMD_RESET          = (1 << 8),
 +      AHCI_CMD_CLR_BUSY       = (1 << 10),
  
        RX_FIS_D2H_REG          = 0x40, /* offset of D2H Register FIS data */
  
@@@ -87,7 -85,6 +87,7 @@@
  
        /* HOST_CAP bits */
        HOST_CAP_64             = (1 << 31), /* PCI DAC (64-bit DMA) support */
 +      HOST_CAP_CLO            = (1 << 24), /* Command List Override support */
  
        /* registers for each SATA port */
        PORT_LST_ADDR           = 0x00, /* command list DMA addr */
        PORT_CMD_LIST_ON        = (1 << 15), /* cmd list DMA engine running */
        PORT_CMD_FIS_ON         = (1 << 14), /* FIS DMA engine running */
        PORT_CMD_FIS_RX         = (1 << 4), /* Enable FIS receive DMA engine */
 +      PORT_CMD_CLO            = (1 << 3), /* Command list override */
        PORT_CMD_POWER_ON       = (1 << 2), /* Power up device */
        PORT_CMD_SPIN_UP        = (1 << 1), /* Spin up device */
        PORT_CMD_START          = (1 << 0), /* Enable port DMA engine */
@@@ -188,7 -184,7 +188,7 @@@ struct ahci_port_priv 
  static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg);
  static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
  static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 -static int ahci_qc_issue(struct ata_queued_cmd *qc);
 +static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
  static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
  static void ahci_phy_reset(struct ata_port *ap);
  static void ahci_irq_clear(struct ata_port *ap);
@@@ -292,6 -288,8 +292,8 @@@ static const struct pci_device_id ahci_
          board_ahci }, /* ICH8M */
        { 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_ahci }, /* JMicron JMB360 */
+       { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci }, /* JMicron JMB363 */
        { }     /* terminate list */
  };
  
@@@ -452,72 -450,25 +454,72 @@@ static void ahci_scr_write (struct ata_
        writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
  }
  
 -static void ahci_phy_reset(struct ata_port *ap)
 +static int ahci_stop_engine(struct ata_port *ap)
 +{
 +      void __iomem *mmio = ap->host_set->mmio_base;
 +      void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 +      int work;
 +      u32 tmp;
 +
 +      tmp = readl(port_mmio + PORT_CMD);
 +      tmp &= ~PORT_CMD_START;
 +      writel(tmp, port_mmio + PORT_CMD);
 +
 +      /* wait for engine to stop.  TODO: this could be
 +       * as long as 500 msec
 +       */
 +      work = 1000;
 +      while (work-- > 0) {
 +              tmp = readl(port_mmio + PORT_CMD);
 +              if ((tmp & PORT_CMD_LIST_ON) == 0)
 +                      return 0;
 +              udelay(10);
 +      }
 +
 +      return -EIO;
 +}
 +
 +static void ahci_start_engine(struct ata_port *ap)
 +{
 +      void __iomem *mmio = ap->host_set->mmio_base;
 +      void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 +      u32 tmp;
 +
 +      tmp = readl(port_mmio + PORT_CMD);
 +      tmp |= PORT_CMD_START;
 +      writel(tmp, port_mmio + PORT_CMD);
 +      readl(port_mmio + PORT_CMD); /* flush */
 +}
 +
 +static unsigned int ahci_dev_classify(struct ata_port *ap)
  {
        void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
        struct ata_taskfile tf;
 +      u32 tmp;
 +
 +      tmp = readl(port_mmio + PORT_SIG);
 +      tf.lbah         = (tmp >> 24)   & 0xff;
 +      tf.lbam         = (tmp >> 16)   & 0xff;
 +      tf.lbal         = (tmp >> 8)    & 0xff;
 +      tf.nsect        = (tmp)         & 0xff;
 +
 +      return ata_dev_classify(&tf);
 +}
 +
 +static void ahci_phy_reset(struct ata_port *ap)
 +{
 +      void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
        struct ata_device *dev = &ap->device[0];
        u32 new_tmp, tmp;
  
 +      ahci_stop_engine(ap);
        __sata_phy_reset(ap);
 +      ahci_start_engine(ap);
  
        if (ap->flags & ATA_FLAG_PORT_DISABLED)
                return;
  
 -      tmp = readl(port_mmio + PORT_SIG);
 -      tf.lbah         = (tmp >> 24)   & 0xff;
 -      tf.lbam         = (tmp >> 16)   & 0xff;
 -      tf.lbal         = (tmp >> 8)    & 0xff;
 -      tf.nsect        = (tmp)         & 0xff;
 -
 -      dev->class = ata_dev_classify(&tf);
 +      dev->class = ahci_dev_classify(ap);
        if (!ata_dev_present(dev)) {
                ata_port_disable(ap);
                return;
@@@ -625,6 -576,7 +627,6 @@@ static void ahci_restart_port(struct at
        void __iomem *mmio = ap->host_set->mmio_base;
        void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
        u32 tmp;
 -      int work;
  
        if ((ap->device[0].class != ATA_DEV_ATAPI) ||
            ((irq_stat & PORT_IRQ_TF_ERR) == 0))
                        readl(port_mmio + PORT_SCR_ERR));
  
        /* stop DMA */
 -      tmp = readl(port_mmio + PORT_CMD);
 -      tmp &= ~PORT_CMD_START;
 -      writel(tmp, port_mmio + PORT_CMD);
 -
 -      /* wait for engine to stop.  TODO: this could be
 -       * as long as 500 msec
 -       */
 -      work = 1000;
 -      while (work-- > 0) {
 -              tmp = readl(port_mmio + PORT_CMD);
 -              if ((tmp & PORT_CMD_LIST_ON) == 0)
 -                      break;
 -              udelay(10);
 -      }
 +      ahci_stop_engine(ap);
  
        /* clear SATA phy error, if any */
        tmp = readl(port_mmio + PORT_SCR_ERR);
        }
  
        /* re-start DMA */
 -      tmp = readl(port_mmio + PORT_CMD);
 -      tmp |= PORT_CMD_START;
 -      writel(tmp, port_mmio + PORT_CMD);
 -      readl(port_mmio + PORT_CMD); /* flush */
 +      ahci_start_engine(ap);
  }
  
  static void ahci_eng_timeout(struct ata_port *ap)
                       ap->id);
        } else {
                ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
 -
 -              /* hack alert!  We cannot use the supplied completion
 -               * function from inside the ->eh_strategy_handler() thread.
 -               * libata is the only user of ->eh_strategy_handler() in
 -               * any kernel, so the default scsi_done() assumes it is
 -               * not being called from the SCSI EH.
 -               */
 -              qc->scsidone = scsi_finish_command;
 -              qc->err_mask |= AC_ERR_OTHER;
 -              ata_qc_complete(qc);
 +              qc->err_mask |= AC_ERR_TIMEOUT;
        }
  
        spin_unlock_irqrestore(&host_set->lock, flags);
 +
 +      if (qc)
 +              ata_eh_qc_complete(qc);
  }
  
  static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
                ahci_restart_port(ap, status);
  
                if (qc) {
 -                      qc->err_mask |= AC_ERR_OTHER;
 +                      qc->err_mask |= err_mask;
                        ata_qc_complete(qc);
                }
        }
@@@ -802,7 -776,7 +804,7 @@@ static irqreturn_t ahci_interrupt (int 
        return IRQ_RETVAL(handled);
  }
  
 -static int ahci_qc_issue(struct ata_queued_cmd *qc)
 +static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
  {
        struct ata_port *ap = qc->ap;
        void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;