diff options
author | Dan Wolstenholme <daniel@wolstenholme.net> | 2007-01-09 05:59:21 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-09 17:39:31 -0500 |
commit | 7cbaa86b937b0b1fab95c159989f6a3c00bbcf78 (patch) | |
tree | 90dff6c4d7233793bdb00037024af49d6dab3ad1 /drivers/ata/sata_vsc.c | |
parent | 553c4aa630af7bc885e056d0436e4eb7f238579b (diff) |
[libata] sata_vsc: support PCI MSI
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/sata_vsc.c')
-rw-r--r-- | drivers/ata/sata_vsc.c | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index 0fa1b89f76d5..1a5f3578894d 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c | |||
@@ -94,8 +94,14 @@ enum { | |||
94 | VSC_SATA_INT_ERROR_P | VSC_SATA_INT_ERROR_R | \ | 94 | VSC_SATA_INT_ERROR_P | VSC_SATA_INT_ERROR_R | \ |
95 | VSC_SATA_INT_ERROR_E | VSC_SATA_INT_ERROR_M | \ | 95 | VSC_SATA_INT_ERROR_E | VSC_SATA_INT_ERROR_M | \ |
96 | VSC_SATA_INT_PHY_CHANGE), | 96 | VSC_SATA_INT_PHY_CHANGE), |
97 | |||
98 | /* Host private flags (hp_flags) */ | ||
99 | VSC_SATA_HP_FLAG_MSI = (1 << 0), | ||
97 | }; | 100 | }; |
98 | 101 | ||
102 | struct vsc_sata_host_priv { | ||
103 | u32 hp_flags; | ||
104 | }; | ||
99 | 105 | ||
100 | #define is_vsc_sata_int_err(port_idx, int_status) \ | 106 | #define is_vsc_sata_int_err(port_idx, int_status) \ |
101 | (int_status & (VSC_SATA_INT_ERROR << (8 * port_idx))) | 107 | (int_status & (VSC_SATA_INT_ERROR << (8 * port_idx))) |
@@ -118,6 +124,20 @@ static void vsc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, | |||
118 | } | 124 | } |
119 | 125 | ||
120 | 126 | ||
127 | static void vsc_sata_host_stop(struct ata_host_set *host_set) | ||
128 | { | ||
129 | struct vsc_sata_host_priv *hpriv = host_set->private_data; | ||
130 | struct pci_dev *pdev = to_pci_dev(host_set->dev); | ||
131 | |||
132 | if (hpriv->hp_flags & VSC_SATA_HP_FLAG_MSI) | ||
133 | pci_disable_msi(pdev); | ||
134 | else | ||
135 | pci_intx(pdev, 0); | ||
136 | kfree (hpriv); | ||
137 | ata_pci_host_stop(host_set); | ||
138 | } | ||
139 | |||
140 | |||
121 | static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl) | 141 | static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl) |
122 | { | 142 | { |
123 | void __iomem *mask_addr; | 143 | void __iomem *mask_addr; |
@@ -312,7 +332,7 @@ static const struct ata_port_operations vsc_sata_ops = { | |||
312 | .scr_write = vsc_sata_scr_write, | 332 | .scr_write = vsc_sata_scr_write, |
313 | .port_start = ata_port_start, | 333 | .port_start = ata_port_start, |
314 | .port_stop = ata_port_stop, | 334 | .port_stop = ata_port_stop, |
315 | .host_stop = ata_pci_host_stop, | 335 | .host_stop = vsc_sata_host_stop, |
316 | }; | 336 | }; |
317 | 337 | ||
318 | static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base) | 338 | static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base) |
@@ -341,6 +361,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d | |||
341 | { | 361 | { |
342 | static int printed_version; | 362 | static int printed_version; |
343 | struct ata_probe_ent *probe_ent = NULL; | 363 | struct ata_probe_ent *probe_ent = NULL; |
364 | struct vsc_sata_host_priv *hpriv; | ||
344 | unsigned long base; | 365 | unsigned long base; |
345 | int pci_dev_busy = 0; | 366 | int pci_dev_busy = 0; |
346 | void __iomem *mmio_base; | 367 | void __iomem *mmio_base; |
@@ -382,6 +403,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d | |||
382 | rc = -ENOMEM; | 403 | rc = -ENOMEM; |
383 | goto err_out_regions; | 404 | goto err_out_regions; |
384 | } | 405 | } |
406 | |||
385 | memset(probe_ent, 0, sizeof(*probe_ent)); | 407 | memset(probe_ent, 0, sizeof(*probe_ent)); |
386 | probe_ent->dev = pci_dev_to_dev(pdev); | 408 | probe_ent->dev = pci_dev_to_dev(pdev); |
387 | INIT_LIST_HEAD(&probe_ent->node); | 409 | INIT_LIST_HEAD(&probe_ent->node); |
@@ -393,19 +415,33 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d | |||
393 | } | 415 | } |
394 | base = (unsigned long) mmio_base; | 416 | base = (unsigned long) mmio_base; |
395 | 417 | ||
418 | hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL); | ||
419 | if (!hpriv) { | ||
420 | rc = -ENOMEM; | ||
421 | goto err_out_iounmap; | ||
422 | } | ||
423 | memset(hpriv, 0, sizeof(*hpriv)); | ||
424 | |||
396 | /* | 425 | /* |
397 | * Due to a bug in the chip, the default cache line size can't be used | 426 | * Due to a bug in the chip, the default cache line size can't be used |
398 | */ | 427 | */ |
399 | pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80); | 428 | pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80); |
400 | 429 | ||
430 | if (pci_enable_msi(pdev) == 0) { | ||
431 | hpriv->hp_flags |= VSC_SATA_HP_FLAG_MSI; | ||
432 | pci_intx(pdev, 0); | ||
433 | } | ||
434 | else | ||
435 | probe_ent->irq_flags = IRQF_SHARED; | ||
436 | |||
401 | probe_ent->sht = &vsc_sata_sht; | 437 | probe_ent->sht = &vsc_sata_sht; |
402 | probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 438 | probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
403 | ATA_FLAG_MMIO; | 439 | ATA_FLAG_MMIO; |
404 | probe_ent->port_ops = &vsc_sata_ops; | 440 | probe_ent->port_ops = &vsc_sata_ops; |
405 | probe_ent->n_ports = 4; | 441 | probe_ent->n_ports = 4; |
406 | probe_ent->irq = pdev->irq; | 442 | probe_ent->irq = pdev->irq; |
407 | probe_ent->irq_flags = IRQF_SHARED; | ||
408 | probe_ent->mmio_base = mmio_base; | 443 | probe_ent->mmio_base = mmio_base; |
444 | probe_ent->private_data = hpriv; | ||
409 | 445 | ||
410 | /* We don't care much about the PIO/UDMA masks, but the core won't like us | 446 | /* We don't care much about the PIO/UDMA masks, but the core won't like us |
411 | * if we don't fill these | 447 | * if we don't fill these |
@@ -432,10 +468,12 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d | |||
432 | 468 | ||
433 | /* FIXME: check ata_device_add return value */ | 469 | /* FIXME: check ata_device_add return value */ |
434 | ata_device_add(probe_ent); | 470 | ata_device_add(probe_ent); |
435 | kfree(probe_ent); | ||
436 | 471 | ||
472 | kfree(probe_ent); | ||
437 | return 0; | 473 | return 0; |
438 | 474 | ||
475 | err_out_iounmap: | ||
476 | pci_iounmap(pdev, mmio_base); | ||
439 | err_out_free_ent: | 477 | err_out_free_ent: |
440 | kfree(probe_ent); | 478 | kfree(probe_ent); |
441 | err_out_regions: | 479 | err_out_regions: |