]> err.no Git - linux-2.6/blobdiff - drivers/scsi/sata_sil24.c
[PATCH] WAN: update info page for a bunch of my drivers
[linux-2.6] / drivers / scsi / sata_sil24.c
index 4c76f05d9b6503f1ea6ce86ff63abea13a56a529..c8b477c672475debae2c8994fefd290a3a660053 100644 (file)
@@ -37,9 +37,9 @@
  * Port request block (PRB) 32 bytes
  */
 struct sil24_prb {
-       u16     ctrl;
-       u16     prot;
-       u32     rx_cnt;
+       __le16  ctrl;
+       __le16  prot;
+       __le32  rx_cnt;
        u8      fis[6 * 4];
 };
 
@@ -47,17 +47,17 @@ struct sil24_prb {
  * Scatter gather entry (SGE) 16 bytes
  */
 struct sil24_sge {
-       u64     addr;
-       u32     cnt;
-       u32     flags;
+       __le64  addr;
+       __le32  cnt;
+       __le32  flags;
 };
 
 /*
  * Port multiplier
  */
 struct sil24_port_multiplier {
-       u32     diag;
-       u32     sactive;
+       __le32  diag;
+       __le32  sactive;
 };
 
 enum {
@@ -98,7 +98,9 @@ enum {
         * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2)
         */
        PORT_REGS_SIZE          = 0x2000,
-       PORT_PRB                = 0x0000, /* (32 bytes PRB + 16 bytes SGEs * 6) * 31 (3968 bytes) */
+
+       PORT_LRAM               = 0x0000, /* 31 LRAM slots and PM regs */
+       PORT_LRAM_SLOT_SZ       = 0x0080, /* 32 bytes PRB + 2 SGE, ACT... */
 
        PORT_PM                 = 0x0f80, /* 8 bytes PM * 16 (128 bytes) */
                /* 32 bit regs */
@@ -157,7 +159,8 @@ enum {
        PORT_IRQ_SDB_NOTIFY     = (1 << 11), /* SDB notify received */
 
        DEF_PORT_IRQ            = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR |
-                                 PORT_IRQ_DEV_XCHG | PORT_IRQ_UNK_FIS,
+                                 PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG |
+                                 PORT_IRQ_UNK_FIS,
 
        /* bits[27:16] are unmasked (raw) */
        PORT_IRQ_RAW_SHIFT      = 16,
@@ -226,7 +229,7 @@ enum {
        /* host flags */
        SIL24_COMMON_FLAGS      = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-                                 ATA_FLAG_NCQ,
+                                 ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY,
        SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
 
        IRQ_STAT_4PORTS         = 0xf,
@@ -323,7 +326,6 @@ static u8 sil24_check_status(struct ata_port *ap);
 static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg);
 static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
 static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
-static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes);
 static void sil24_qc_prep(struct ata_queued_cmd *qc);
 static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
 static void sil24_irq_clear(struct ata_port *ap);
@@ -368,6 +370,7 @@ static struct scsi_host_template sil24_sht = {
        .proc_name              = DRV_NAME,
        .dma_boundary           = ATA_DMA_BOUNDARY,
        .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
 };
 
@@ -382,8 +385,6 @@ static const struct ata_port_operations sil24_ops = {
 
        .tf_read                = sil24_tf_read,
 
-       .probe_reset            = sil24_probe_reset,
-
        .qc_prep                = sil24_qc_prep,
        .qc_issue               = sil24_qc_issue,
 
@@ -589,7 +590,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
 {
        void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
        const char *reason;
-       int tout_msec;
+       int tout_msec, rc;
        u32 tmp;
 
        /* sil24 does the right thing(tm) without any protection */
@@ -603,10 +604,14 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
        tmp = ata_wait_register(port + PORT_CTRL_STAT,
                                PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec);
 
-       /* SStatus oscillates between zero and valid status for short
-        * duration after DEV_RST, give it time to settle.
+       /* SStatus oscillates between zero and valid status after
+        * DEV_RST, debounce it.
         */
-       msleep(100);
+       rc = sata_phy_debounce(ap, sata_deb_timing_before_fsrst);
+       if (rc) {
+               reason = "PHY debouncing failed";
+               goto err;
+       }
 
        if (tmp & PORT_CS_DEV_RST) {
                if (ata_port_offline(ap))
@@ -615,28 +620,19 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
                goto err;
        }
 
-       if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
-               reason = "device not ready";
-               goto err;
-       }
-
-       /* sil24 doesn't report device class code after hardreset,
-        * leave *class alone.
+       /* Sil24 doesn't store signature FIS after hardreset, so we
+        * can't wait for BSY to clear.  Some devices take a long time
+        * to get ready and those devices will choke if we don't wait
+        * for BSY clearance here.  Tell libata to perform follow-up
+        * softreset.
         */
-       return 0;
+       return -EAGAIN;
 
  err:
        ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason);
        return -EIO;
 }
 
-static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes)
-{
-       return ata_drive_probe_reset(ap, ata_std_probeinit,
-                                    sil24_softreset, sil24_hardreset,
-                                    ata_std_postreset, classes);
-}
-
 static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
                                 struct sil24_sge *sge)
 {
@@ -767,13 +763,11 @@ static void sil24_error_intr(struct ata_port *ap)
 
        ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
 
-       if (irq_stat & PORT_IRQ_DEV_XCHG) {
-               ehi->err_mask |= AC_ERR_ATA_BUS;
-               /* sil24 doesn't recover very well from phy
-                * disconnection with a softreset.  Force hardreset.
-                */
-               ehi->action |= ATA_EH_HARDRESET;
-               ata_ehi_push_desc(ehi, ", device_exchanged");
+       if (irq_stat & (PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG)) {
+               ata_ehi_hotplugged(ehi);
+               ata_ehi_push_desc(ehi, ", %s",
+                              irq_stat & PORT_IRQ_PHYRDY_CHG ?
+                              "PHY RDY changed" : "device exchanged");
                freeze = 1;
        }
 
@@ -912,7 +906,8 @@ static void sil24_error_handler(struct ata_port *ap)
        }
 
        /* perform recovery */
-       ata_do_eh(ap, sil24_softreset, sil24_hardreset, ata_std_postreset);
+       ata_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset,
+                 ata_std_postreset);
 }
 
 static void sil24_post_internal_cmd(struct ata_queued_cmd *qc)
@@ -1102,7 +1097,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                void __iomem *port = port_base + i * PORT_REGS_SIZE;
                unsigned long portu = (unsigned long)port;
 
-               probe_ent->port[i].cmd_addr = portu + PORT_PRB;
+               probe_ent->port[i].cmd_addr = portu;
                probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
 
                ata_std_ports(&probe_ent->port[i]);