Add disk hotswap support to libata RESEND #2
PATCH 1/3 Add disk hotswap support to libata RESEND #2
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 <[email protected]>
* 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.
drivers/scsi/sata_promise.c renamed from drivers/scsi/sata_promise.c.old +68 -18
@@ -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 irVPRINTK ("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 atstatic 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 cwritel (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 );