diff options
Diffstat (limited to 'drivers/scsi/sata_sil.c')
-rw-r--r-- | drivers/scsi/sata_sil.c | 105 |
1 files changed, 66 insertions, 39 deletions
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 7aabb45c35e5..d0a85073ebf7 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c | |||
@@ -109,6 +109,7 @@ enum { | |||
109 | }; | 109 | }; |
110 | 110 | ||
111 | static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); | 111 | static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); |
112 | static int sil_pci_device_resume(struct pci_dev *pdev); | ||
112 | static void sil_dev_config(struct ata_port *ap, struct ata_device *dev); | 113 | static void sil_dev_config(struct ata_port *ap, struct ata_device *dev); |
113 | static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg); | 114 | static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg); |
114 | static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); | 115 | static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); |
@@ -160,6 +161,8 @@ static struct pci_driver sil_pci_driver = { | |||
160 | .id_table = sil_pci_tbl, | 161 | .id_table = sil_pci_tbl, |
161 | .probe = sil_init_one, | 162 | .probe = sil_init_one, |
162 | .remove = ata_pci_remove_one, | 163 | .remove = ata_pci_remove_one, |
164 | .suspend = ata_pci_device_suspend, | ||
165 | .resume = sil_pci_device_resume, | ||
163 | }; | 166 | }; |
164 | 167 | ||
165 | static struct scsi_host_template sil_sht = { | 168 | static struct scsi_host_template sil_sht = { |
@@ -178,6 +181,8 @@ static struct scsi_host_template sil_sht = { | |||
178 | .slave_configure = ata_scsi_slave_config, | 181 | .slave_configure = ata_scsi_slave_config, |
179 | .slave_destroy = ata_scsi_slave_destroy, | 182 | .slave_destroy = ata_scsi_slave_destroy, |
180 | .bios_param = ata_std_bios_param, | 183 | .bios_param = ata_std_bios_param, |
184 | .suspend = ata_scsi_device_suspend, | ||
185 | .resume = ata_scsi_device_resume, | ||
181 | }; | 186 | }; |
182 | 187 | ||
183 | static const struct ata_port_operations sil_ops = { | 188 | static const struct ata_port_operations sil_ops = { |
@@ -370,7 +375,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) | |||
370 | * during hardreset makes controllers with broken SIEN | 375 | * during hardreset makes controllers with broken SIEN |
371 | * repeat probing needlessly. | 376 | * repeat probing needlessly. |
372 | */ | 377 | */ |
373 | if (!(ap->flags & ATA_FLAG_FROZEN)) { | 378 | if (!(ap->pflags & ATA_PFLAG_FROZEN)) { |
374 | ata_ehi_hotplugged(&ap->eh_info); | 379 | ata_ehi_hotplugged(&ap->eh_info); |
375 | ap->eh_info.serror |= serror; | 380 | ap->eh_info.serror |= serror; |
376 | } | 381 | } |
@@ -561,6 +566,52 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) | |||
561 | } | 566 | } |
562 | } | 567 | } |
563 | 568 | ||
569 | static void sil_init_controller(struct pci_dev *pdev, | ||
570 | int n_ports, unsigned long host_flags, | ||
571 | void __iomem *mmio_base) | ||
572 | { | ||
573 | u8 cls; | ||
574 | u32 tmp; | ||
575 | int i; | ||
576 | |||
577 | /* Initialize FIFO PCI bus arbitration */ | ||
578 | cls = sil_get_device_cache_line(pdev); | ||
579 | if (cls) { | ||
580 | cls >>= 3; | ||
581 | cls++; /* cls = (line_size/8)+1 */ | ||
582 | for (i = 0; i < n_ports; i++) | ||
583 | writew(cls << 8 | cls, | ||
584 | mmio_base + sil_port[i].fifo_cfg); | ||
585 | } else | ||
586 | dev_printk(KERN_WARNING, &pdev->dev, | ||
587 | "cache line size not set. Driver may not function\n"); | ||
588 | |||
589 | /* Apply R_ERR on DMA activate FIS errata workaround */ | ||
590 | if (host_flags & SIL_FLAG_RERR_ON_DMA_ACT) { | ||
591 | int cnt; | ||
592 | |||
593 | for (i = 0, cnt = 0; i < n_ports; i++) { | ||
594 | tmp = readl(mmio_base + sil_port[i].sfis_cfg); | ||
595 | if ((tmp & 0x3) != 0x01) | ||
596 | continue; | ||
597 | if (!cnt) | ||
598 | dev_printk(KERN_INFO, &pdev->dev, | ||
599 | "Applying R_ERR on DMA activate " | ||
600 | "FIS errata fix\n"); | ||
601 | writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg); | ||
602 | cnt++; | ||
603 | } | ||
604 | } | ||
605 | |||
606 | if (n_ports == 4) { | ||
607 | /* flip the magic "make 4 ports work" bit */ | ||
608 | tmp = readl(mmio_base + sil_port[2].bmdma); | ||
609 | if ((tmp & SIL_INTR_STEERING) == 0) | ||
610 | writel(tmp | SIL_INTR_STEERING, | ||
611 | mmio_base + sil_port[2].bmdma); | ||
612 | } | ||
613 | } | ||
614 | |||
564 | static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | 615 | static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) |
565 | { | 616 | { |
566 | static int printed_version; | 617 | static int printed_version; |
@@ -570,8 +621,6 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
570 | int rc; | 621 | int rc; |
571 | unsigned int i; | 622 | unsigned int i; |
572 | int pci_dev_busy = 0; | 623 | int pci_dev_busy = 0; |
573 | u32 tmp; | ||
574 | u8 cls; | ||
575 | 624 | ||
576 | if (!printed_version++) | 625 | if (!printed_version++) |
577 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); | 626 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); |
@@ -630,42 +679,8 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
630 | ata_std_ports(&probe_ent->port[i]); | 679 | ata_std_ports(&probe_ent->port[i]); |
631 | } | 680 | } |
632 | 681 | ||
633 | /* Initialize FIFO PCI bus arbitration */ | 682 | sil_init_controller(pdev, probe_ent->n_ports, probe_ent->host_flags, |
634 | cls = sil_get_device_cache_line(pdev); | 683 | mmio_base); |
635 | if (cls) { | ||
636 | cls >>= 3; | ||
637 | cls++; /* cls = (line_size/8)+1 */ | ||
638 | for (i = 0; i < probe_ent->n_ports; i++) | ||
639 | writew(cls << 8 | cls, | ||
640 | mmio_base + sil_port[i].fifo_cfg); | ||
641 | } else | ||
642 | dev_printk(KERN_WARNING, &pdev->dev, | ||
643 | "cache line size not set. Driver may not function\n"); | ||
644 | |||
645 | /* Apply R_ERR on DMA activate FIS errata workaround */ | ||
646 | if (probe_ent->host_flags & SIL_FLAG_RERR_ON_DMA_ACT) { | ||
647 | int cnt; | ||
648 | |||
649 | for (i = 0, cnt = 0; i < probe_ent->n_ports; i++) { | ||
650 | tmp = readl(mmio_base + sil_port[i].sfis_cfg); | ||
651 | if ((tmp & 0x3) != 0x01) | ||
652 | continue; | ||
653 | if (!cnt) | ||
654 | dev_printk(KERN_INFO, &pdev->dev, | ||
655 | "Applying R_ERR on DMA activate " | ||
656 | "FIS errata fix\n"); | ||
657 | writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg); | ||
658 | cnt++; | ||
659 | } | ||
660 | } | ||
661 | |||
662 | if (ent->driver_data == sil_3114) { | ||
663 | /* flip the magic "make 4 ports work" bit */ | ||
664 | tmp = readl(mmio_base + sil_port[2].bmdma); | ||
665 | if ((tmp & SIL_INTR_STEERING) == 0) | ||
666 | writel(tmp | SIL_INTR_STEERING, | ||
667 | mmio_base + sil_port[2].bmdma); | ||
668 | } | ||
669 | 684 | ||
670 | pci_set_master(pdev); | 685 | pci_set_master(pdev); |
671 | 686 | ||
@@ -685,6 +700,18 @@ err_out: | |||
685 | return rc; | 700 | return rc; |
686 | } | 701 | } |
687 | 702 | ||
703 | static int sil_pci_device_resume(struct pci_dev *pdev) | ||
704 | { | ||
705 | struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev); | ||
706 | |||
707 | ata_pci_device_do_resume(pdev); | ||
708 | sil_init_controller(pdev, host_set->n_ports, host_set->ports[0]->flags, | ||
709 | host_set->mmio_base); | ||
710 | ata_host_set_resume(host_set); | ||
711 | |||
712 | return 0; | ||
713 | } | ||
714 | |||
688 | static int __init sil_init(void) | 715 | static int __init sil_init(void) |
689 | { | 716 | { |
690 | return pci_module_init(&sil_pci_driver); | 717 | return pci_module_init(&sil_pci_driver); |