Patch 01: add promise SATAII150 support to the sata_promise driver. As described in the archives, this patch adds support for those notorious SATAII150 controllers with their weird hotplug offset and prepares us for hotplug goodness. Jeff: The reason that ATA_FLAG_SATA is commented out on pdc_2057x controllers is to keep them consistent with the 2037x controllers in libata + sata_promise support PATA ports (as seen in 2.6.13-rc3-mm1). I've implemented all your other suggestions. Luke Kosewski
28.07.05 Luke Kosewski <lkosewsk@xxxxxx> * A patch to the sata_promise driver in libata for it to correctly mask out hotplug interrupts on SATAII150 Tx4/Tx2 Plus controllers. * This is a resend of the original patch which in particular: - does not split up the interrupt handling function, and instead uses a pdc_host_priv structure to pass along the location of the hotplug registers. - does not use spin_lock_irqsave, but the less expensive spin_lock in the interrupt handler. Signed-off-by: Luke Kosewski <lkosewsk@xxxxxx> --- linux/drivers/scsi/sata_promise.c.old 2005-07-26 15:52:51.000000000 -0700 +++ linux/drivers/scsi/sata_promise.c 2005-07-27 09:37:29.000000000 -0700 @@ -52,6 +52,7 @@ enum { PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */ PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ + PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */ PDC_SLEW_CTL = 0x470, /* slew rate control reg */ PDC_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) | @@ -60,8 +61,10 @@ enum { board_2037x = 0, /* FastTrak S150 TX2plus */ board_20319 = 1, /* FastTrak S150 TX4 */ board_20619 = 2, /* FastTrak TX4000 */ + board_2057x = 3, /* SATAII150 Tx2plus */ + board_40518 = 4, /* SATAII150 Tx4 */ - PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */ + PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */ PDC_RESET = (1 << 11), /* HDMA reset */ }; @@ -72,6 +75,10 @@ struct pdc_port_priv { dma_addr_t pkt_dma; }; +struct pdc_host_priv { + unsigned int hotplug_offset; +}; + static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); @@ -161,6 +168,28 @@ static struct ata_port_info pdc_port_inf .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_ata_ops, }, + + /* board_2057x */ + { + .sht = &pdc_ata_sht, + .host_flags = /* ATA_FLAG_SATA | */ ATA_FLAG_NO_LEGACY | + ATA_FLAG_SRST | ATA_FLAG_MMIO, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &pdc_ata_ops, + }, + + /* board_40518 */ + { + .sht = &pdc_ata_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_SRST | ATA_FLAG_MMIO, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &pdc_ata_ops, + }, }; static struct pci_device_id pdc_ata_pci_tbl[] = { @@ -175,16 +204,16 @@ static struct pci_device_id pdc_ata_pci_ { PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3574, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - board_2037x }, + board_2057x }, { PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - board_2037x }, + board_2057x }, { PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20319 }, { PCI_VENDOR_ID_PROMISE, 0x3319, 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 }, + board_40518 }, { PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20619 }, @@ -436,10 +465,9 @@ static irqreturn_t pdc_interrupt (int ir { struct ata_host_set *host_set = dev_instance; struct ata_port *ap; - u32 mask = 0; - unsigned int i, tmp; - unsigned int handled = 0; void *mmio_base; + u32 mask = 0; + unsigned int i, tmp, handled = 0; VPRINTK("ENTER\n"); @@ -449,7 +477,7 @@ static irqreturn_t pdc_interrupt (int ir } mmio_base = host_set->mmio_base; - + /* reading should also clear interrupts */ mask = readl(mmio_base + PDC_INT_SEQMASK); @@ -457,14 +485,15 @@ static irqreturn_t pdc_interrupt (int ir VPRINTK("QUICK EXIT 2\n"); return IRQ_NONE; } + + spin_lock(&host_set->lock); + mask &= 0xffff; /* only 16 tags possible */ if (!mask) { VPRINTK("QUICK EXIT 3\n"); - return IRQ_NONE; + goto done_irq; } - spin_lock(&host_set->lock); - writel(mask, mmio_base + PDC_INT_SEQMASK); for (i = 0; i < host_set->n_ports; i++) { @@ -480,10 +509,10 @@ static irqreturn_t pdc_interrupt (int ir } } - spin_unlock(&host_set->lock); - VPRINTK("EXIT\n"); - + +done_irq: + spin_unlock(&host_set->lock); return IRQ_RETVAL(handled); } @@ -561,6 +590,8 @@ static void pdc_ata_setup_port(struct at static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) { void *mmio = pe->mmio_base; + struct pdc_host_priv *hp = pe->private_data; + unsigned int hotplug_offset = hp->hotplug_offset; u32 tmp; /* @@ -575,12 +606,12 @@ static void pdc_host_init(unsigned int c writel(tmp, mmio + PDC_FLASH_CTL); /* clear plug/unplug flags for all ports */ - tmp = readl(mmio + PDC_SATA_PLUG_CSR); - writel(tmp | 0xff, mmio + PDC_SATA_PLUG_CSR); + tmp = readl(mmio + hotplug_offset); + writel(tmp | 0xff, mmio + hotplug_offset); /* mask plug/unplug ints */ - tmp = readl(mmio + PDC_SATA_PLUG_CSR); - writel(tmp | 0xff0000, mmio + PDC_SATA_PLUG_CSR); + tmp = readl(mmio + hotplug_offset); + writel(tmp | 0xff0000, mmio + hotplug_offset); /* reduce TBG clock to 133 Mhz. */ tmp = readl(mmio + PDC_TBG_MODE); @@ -602,6 +633,7 @@ static int pdc_ata_init_one (struct pci_ { static int printed_version; struct ata_probe_ent *probe_ent = NULL; + struct pdc_host_priv *hp; unsigned long base; void *mmio_base; unsigned int board_idx = (unsigned int) ent->driver_data; @@ -651,6 +683,18 @@ static int pdc_ata_init_one (struct pci_ } base = (unsigned long) mmio_base; + hp = kmalloc(sizeof(*hp), GFP_KERNEL); + if (hp == NULL) + { + rc = -ENOMEM; + goto err_out_free_ent; + } + memset(hp, 0, sizeof(*hp)); + + probe_ent->private_data = hp; + /* Set default hotplug offset */ + hp->hotplug_offset = PDC_SATA_PLUG_CSR; + probe_ent->sht = pdc_port_info[board_idx].sht; probe_ent->host_flags = pdc_port_info[board_idx].host_flags; probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; @@ -673,6 +717,9 @@ static int pdc_ata_init_one (struct pci_ /* notice 4-port boards */ switch (board_idx) { + case board_40518: + /* Override hotplug_offset for SATAII150 */ + hp->hotplug_offset = PDC2_SATA_PLUG_CSR; case board_20319: probe_ent->n_ports = 4; @@ -685,6 +732,9 @@ static int pdc_ata_init_one (struct pci_ probe_ent->port_flags[2] = ATA_FLAG_SATA; probe_ent->port_flags[3] = ATA_FLAG_SATA; break; + case board_2057x: + /* Override hotplug_offset for SATAII150 */ + hp->hotplug_offset = PDC2_SATA_PLUG_CSR; case board_2037x: /* Some boards have also PATA port */ tmp = readb(mmio_base + PDC_FLASH_CTL+1);