diff options
author | Luke Kosewski <lkosewsk@gmail.com> | 2006-01-28 12:39:29 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2006-01-28 12:39:29 -0500 |
commit | 6340f019695a08e3b2e317e307014801fc86b178 (patch) | |
tree | 29ffcfd426be348c2a1f1eb0b9f3dc0034445ba6 /drivers/scsi/sata_promise.c | |
parent | b376bc1f6b4258112d714fb4ee8e5d57b53625f2 (diff) |
[libata sata_promise] add correct read/write of hotplug registers for SATAII devices
This patch adds support for correctly masking out and knowing about
hotplug events on Promise SATAII150 Tx4/Tx2 Plus controllers.
Also, a kmalloc->kzalloc cleanup.
Signed-off-by: Luke Kosewski <lkosewsk@gmail.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/scsi/sata_promise.c')
-rw-r--r-- | drivers/scsi/sata_promise.c | 104 |
1 files changed, 82 insertions, 22 deletions
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 77ef646b0f92..0950a8e45814 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #include "sata_promise.h" | 46 | #include "sata_promise.h" |
47 | 47 | ||
48 | #define DRV_NAME "sata_promise" | 48 | #define DRV_NAME "sata_promise" |
49 | #define DRV_VERSION "1.03" | 49 | #define DRV_VERSION "1.04" |
50 | 50 | ||
51 | 51 | ||
52 | enum { | 52 | enum { |
@@ -58,6 +58,7 @@ enum { | |||
58 | PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */ | 58 | PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */ |
59 | PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ | 59 | PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ |
60 | PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ | 60 | PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ |
61 | PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */ | ||
61 | PDC_SLEW_CTL = 0x470, /* slew rate control reg */ | 62 | PDC_SLEW_CTL = 0x470, /* slew rate control reg */ |
62 | 63 | ||
63 | PDC_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) | | 64 | PDC_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) | |
@@ -67,8 +68,10 @@ enum { | |||
67 | board_20319 = 1, /* FastTrak S150 TX4 */ | 68 | board_20319 = 1, /* FastTrak S150 TX4 */ |
68 | board_20619 = 2, /* FastTrak TX4000 */ | 69 | board_20619 = 2, /* FastTrak TX4000 */ |
69 | board_20771 = 3, /* FastTrak TX2300 */ | 70 | board_20771 = 3, /* FastTrak TX2300 */ |
71 | board_2057x = 4, /* SATAII150 Tx2plus */ | ||
72 | board_40518 = 5, /* SATAII150 Tx4 */ | ||
70 | 73 | ||
71 | PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */ | 74 | PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */ |
72 | 75 | ||
73 | PDC_RESET = (1 << 11), /* HDMA reset */ | 76 | PDC_RESET = (1 << 11), /* HDMA reset */ |
74 | 77 | ||
@@ -82,6 +85,10 @@ struct pdc_port_priv { | |||
82 | dma_addr_t pkt_dma; | 85 | dma_addr_t pkt_dma; |
83 | }; | 86 | }; |
84 | 87 | ||
88 | struct pdc_host_priv { | ||
89 | int hotplug_offset; | ||
90 | }; | ||
91 | |||
85 | static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); | 92 | static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); |
86 | static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); | 93 | static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); |
87 | static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); | 94 | static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); |
@@ -96,6 +103,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) | |||
96 | static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf); | 103 | static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf); |
97 | static void pdc_irq_clear(struct ata_port *ap); | 104 | static void pdc_irq_clear(struct ata_port *ap); |
98 | static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc); | 105 | static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc); |
106 | static void pdc_host_stop(struct ata_host_set *host_set); | ||
99 | 107 | ||
100 | 108 | ||
101 | static struct scsi_host_template pdc_ata_sht = { | 109 | static struct scsi_host_template pdc_ata_sht = { |
@@ -137,7 +145,7 @@ static const struct ata_port_operations pdc_sata_ops = { | |||
137 | .scr_write = pdc_sata_scr_write, | 145 | .scr_write = pdc_sata_scr_write, |
138 | .port_start = pdc_port_start, | 146 | .port_start = pdc_port_start, |
139 | .port_stop = pdc_port_stop, | 147 | .port_stop = pdc_port_stop, |
140 | .host_stop = ata_pci_host_stop, | 148 | .host_stop = pdc_host_stop, |
141 | }; | 149 | }; |
142 | 150 | ||
143 | static const struct ata_port_operations pdc_pata_ops = { | 151 | static const struct ata_port_operations pdc_pata_ops = { |
@@ -158,7 +166,7 @@ static const struct ata_port_operations pdc_pata_ops = { | |||
158 | 166 | ||
159 | .port_start = pdc_port_start, | 167 | .port_start = pdc_port_start, |
160 | .port_stop = pdc_port_stop, | 168 | .port_stop = pdc_port_stop, |
161 | .host_stop = ata_pci_host_stop, | 169 | .host_stop = pdc_host_stop, |
162 | }; | 170 | }; |
163 | 171 | ||
164 | static const struct ata_port_info pdc_port_info[] = { | 172 | static const struct ata_port_info pdc_port_info[] = { |
@@ -201,6 +209,26 @@ static const struct ata_port_info pdc_port_info[] = { | |||
201 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | 209 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ |
202 | .port_ops = &pdc_sata_ops, | 210 | .port_ops = &pdc_sata_ops, |
203 | }, | 211 | }, |
212 | |||
213 | /* board_2057x */ | ||
214 | { | ||
215 | .sht = &pdc_ata_sht, | ||
216 | .host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA, | ||
217 | .pio_mask = 0x1f, /* pio0-4 */ | ||
218 | .mwdma_mask = 0x07, /* mwdma0-2 */ | ||
219 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | ||
220 | .port_ops = &pdc_sata_ops, | ||
221 | }, | ||
222 | |||
223 | /* board_40518 */ | ||
224 | { | ||
225 | .sht = &pdc_ata_sht, | ||
226 | .host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA, | ||
227 | .pio_mask = 0x1f, /* pio0-4 */ | ||
228 | .mwdma_mask = 0x07, /* mwdma0-2 */ | ||
229 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | ||
230 | .port_ops = &pdc_sata_ops, | ||
231 | }, | ||
204 | }; | 232 | }; |
205 | 233 | ||
206 | static const struct pci_device_id pdc_ata_pci_tbl[] = { | 234 | static const struct pci_device_id pdc_ata_pci_tbl[] = { |
@@ -217,9 +245,9 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = { | |||
217 | { PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 245 | { PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
218 | board_2037x }, | 246 | board_2037x }, |
219 | { PCI_VENDOR_ID_PROMISE, 0x3574, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 247 | { PCI_VENDOR_ID_PROMISE, 0x3574, PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
220 | board_2037x }, | 248 | board_2057x }, |
221 | { PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 249 | { PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
222 | board_2037x }, | 250 | board_2057x }, |
223 | { PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 251 | { PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
224 | board_2037x }, | 252 | board_2037x }, |
225 | 253 | ||
@@ -232,7 +260,7 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = { | |||
232 | { PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 260 | { PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
233 | board_20319 }, | 261 | board_20319 }, |
234 | { PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 262 | { PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
235 | board_20319 }, | 263 | board_40518 }, |
236 | 264 | ||
237 | { PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 265 | { PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
238 | board_20619 }, | 266 | board_20619 }, |
@@ -261,12 +289,11 @@ static int pdc_port_start(struct ata_port *ap) | |||
261 | if (rc) | 289 | if (rc) |
262 | return rc; | 290 | return rc; |
263 | 291 | ||
264 | pp = kmalloc(sizeof(*pp), GFP_KERNEL); | 292 | pp = kzalloc(sizeof(*pp), GFP_KERNEL); |
265 | if (!pp) { | 293 | if (!pp) { |
266 | rc = -ENOMEM; | 294 | rc = -ENOMEM; |
267 | goto err_out; | 295 | goto err_out; |
268 | } | 296 | } |
269 | memset(pp, 0, sizeof(*pp)); | ||
270 | 297 | ||
271 | pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL); | 298 | pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL); |
272 | if (!pp->pkt) { | 299 | if (!pp->pkt) { |
@@ -298,6 +325,16 @@ static void pdc_port_stop(struct ata_port *ap) | |||
298 | } | 325 | } |
299 | 326 | ||
300 | 327 | ||
328 | static void pdc_host_stop(struct ata_host_set *host_set) | ||
329 | { | ||
330 | struct pdc_host_priv *hp = host_set->private_data; | ||
331 | |||
332 | ata_pci_host_stop(host_set); | ||
333 | |||
334 | kfree(hp); | ||
335 | } | ||
336 | |||
337 | |||
301 | static void pdc_reset_port(struct ata_port *ap) | 338 | static void pdc_reset_port(struct ata_port *ap) |
302 | { | 339 | { |
303 | void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT; | 340 | void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT; |
@@ -487,14 +524,15 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r | |||
487 | VPRINTK("QUICK EXIT 2\n"); | 524 | VPRINTK("QUICK EXIT 2\n"); |
488 | return IRQ_NONE; | 525 | return IRQ_NONE; |
489 | } | 526 | } |
527 | |||
528 | spin_lock(&host_set->lock); | ||
529 | |||
490 | mask &= 0xffff; /* only 16 tags possible */ | 530 | mask &= 0xffff; /* only 16 tags possible */ |
491 | if (!mask) { | 531 | if (!mask) { |
492 | VPRINTK("QUICK EXIT 3\n"); | 532 | VPRINTK("QUICK EXIT 3\n"); |
493 | return IRQ_NONE; | 533 | goto done_irq; |
494 | } | 534 | } |
495 | 535 | ||
496 | spin_lock(&host_set->lock); | ||
497 | |||
498 | writel(mask, mmio_base + PDC_INT_SEQMASK); | 536 | writel(mask, mmio_base + PDC_INT_SEQMASK); |
499 | 537 | ||
500 | for (i = 0; i < host_set->n_ports; i++) { | 538 | for (i = 0; i < host_set->n_ports; i++) { |
@@ -511,10 +549,10 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r | |||
511 | } | 549 | } |
512 | } | 550 | } |
513 | 551 | ||
514 | spin_unlock(&host_set->lock); | ||
515 | |||
516 | VPRINTK("EXIT\n"); | 552 | VPRINTK("EXIT\n"); |
517 | 553 | ||
554 | done_irq: | ||
555 | spin_unlock(&host_set->lock); | ||
518 | return IRQ_RETVAL(handled); | 556 | return IRQ_RETVAL(handled); |
519 | } | 557 | } |
520 | 558 | ||
@@ -592,6 +630,8 @@ static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base) | |||
592 | static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) | 630 | static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) |
593 | { | 631 | { |
594 | void __iomem *mmio = pe->mmio_base; | 632 | void __iomem *mmio = pe->mmio_base; |
633 | struct pdc_host_priv *hp = pe->private_data; | ||
634 | int hotplug_offset = hp->hotplug_offset; | ||
595 | u32 tmp; | 635 | u32 tmp; |
596 | 636 | ||
597 | /* | 637 | /* |
@@ -606,12 +646,12 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) | |||
606 | writel(tmp, mmio + PDC_FLASH_CTL); | 646 | writel(tmp, mmio + PDC_FLASH_CTL); |
607 | 647 | ||
608 | /* clear plug/unplug flags for all ports */ | 648 | /* clear plug/unplug flags for all ports */ |
609 | tmp = readl(mmio + PDC_SATA_PLUG_CSR); | 649 | tmp = readl(mmio + hotplug_offset); |
610 | writel(tmp | 0xff, mmio + PDC_SATA_PLUG_CSR); | 650 | writel(tmp | 0xff, mmio + hotplug_offset); |
611 | 651 | ||
612 | /* mask plug/unplug ints */ | 652 | /* mask plug/unplug ints */ |
613 | tmp = readl(mmio + PDC_SATA_PLUG_CSR); | 653 | tmp = readl(mmio + hotplug_offset); |
614 | writel(tmp | 0xff0000, mmio + PDC_SATA_PLUG_CSR); | 654 | writel(tmp | 0xff0000, mmio + hotplug_offset); |
615 | 655 | ||
616 | /* reduce TBG clock to 133 Mhz. */ | 656 | /* reduce TBG clock to 133 Mhz. */ |
617 | tmp = readl(mmio + PDC_TBG_MODE); | 657 | tmp = readl(mmio + PDC_TBG_MODE); |
@@ -633,6 +673,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e | |||
633 | { | 673 | { |
634 | static int printed_version; | 674 | static int printed_version; |
635 | struct ata_probe_ent *probe_ent = NULL; | 675 | struct ata_probe_ent *probe_ent = NULL; |
676 | struct pdc_host_priv *hp; | ||
636 | unsigned long base; | 677 | unsigned long base; |
637 | void __iomem *mmio_base; | 678 | void __iomem *mmio_base; |
638 | unsigned int board_idx = (unsigned int) ent->driver_data; | 679 | unsigned int board_idx = (unsigned int) ent->driver_data; |
@@ -663,13 +704,12 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e | |||
663 | if (rc) | 704 | if (rc) |
664 | goto err_out_regions; | 705 | goto err_out_regions; |
665 | 706 | ||
666 | probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); | 707 | probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); |
667 | if (probe_ent == NULL) { | 708 | if (probe_ent == NULL) { |
668 | rc = -ENOMEM; | 709 | rc = -ENOMEM; |
669 | goto err_out_regions; | 710 | goto err_out_regions; |
670 | } | 711 | } |
671 | 712 | ||
672 | memset(probe_ent, 0, sizeof(*probe_ent)); | ||
673 | probe_ent->dev = pci_dev_to_dev(pdev); | 713 | probe_ent->dev = pci_dev_to_dev(pdev); |
674 | INIT_LIST_HEAD(&probe_ent->node); | 714 | INIT_LIST_HEAD(&probe_ent->node); |
675 | 715 | ||
@@ -680,6 +720,16 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e | |||
680 | } | 720 | } |
681 | base = (unsigned long) mmio_base; | 721 | base = (unsigned long) mmio_base; |
682 | 722 | ||
723 | hp = kzalloc(sizeof(*hp), GFP_KERNEL); | ||
724 | if (hp == NULL) { | ||
725 | rc = -ENOMEM; | ||
726 | goto err_out_free_ent; | ||
727 | } | ||
728 | |||
729 | /* Set default hotplug offset */ | ||
730 | hp->hotplug_offset = PDC_SATA_PLUG_CSR; | ||
731 | probe_ent->private_data = hp; | ||
732 | |||
683 | probe_ent->sht = pdc_port_info[board_idx].sht; | 733 | probe_ent->sht = pdc_port_info[board_idx].sht; |
684 | probe_ent->host_flags = pdc_port_info[board_idx].host_flags; | 734 | probe_ent->host_flags = pdc_port_info[board_idx].host_flags; |
685 | probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; | 735 | probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; |
@@ -699,6 +749,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e | |||
699 | 749 | ||
700 | /* notice 4-port boards */ | 750 | /* notice 4-port boards */ |
701 | switch (board_idx) { | 751 | switch (board_idx) { |
752 | case board_40518: | ||
753 | /* Override hotplug offset for SATAII150 */ | ||
754 | hp->hotplug_offset = PDC2_SATA_PLUG_CSR; | ||
755 | /* Fall through */ | ||
702 | case board_20319: | 756 | case board_20319: |
703 | probe_ent->n_ports = 4; | 757 | probe_ent->n_ports = 4; |
704 | 758 | ||
@@ -708,6 +762,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e | |||
708 | probe_ent->port[2].scr_addr = base + 0x600; | 762 | probe_ent->port[2].scr_addr = base + 0x600; |
709 | probe_ent->port[3].scr_addr = base + 0x700; | 763 | probe_ent->port[3].scr_addr = base + 0x700; |
710 | break; | 764 | break; |
765 | case board_2057x: | ||
766 | /* Override hotplug offset for SATAII150 */ | ||
767 | hp->hotplug_offset = PDC2_SATA_PLUG_CSR; | ||
768 | /* Fall through */ | ||
711 | case board_2037x: | 769 | case board_2037x: |
712 | probe_ent->n_ports = 2; | 770 | probe_ent->n_ports = 2; |
713 | break; | 771 | break; |
@@ -733,8 +791,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e | |||
733 | /* initialize adapter */ | 791 | /* initialize adapter */ |
734 | pdc_host_init(board_idx, probe_ent); | 792 | pdc_host_init(board_idx, probe_ent); |
735 | 793 | ||
736 | /* FIXME: check ata_device_add return value */ | 794 | /* FIXME: Need any other frees than hp? */ |
737 | ata_device_add(probe_ent); | 795 | if (!ata_device_add(probe_ent)) |
796 | kfree(hp); | ||
797 | |||
738 | kfree(probe_ent); | 798 | kfree(probe_ent); |
739 | 799 | ||
740 | return 0; | 800 | return 0; |