|
@@ -94,8 +94,14 @@ enum {
|
|
|
VSC_SATA_INT_ERROR_P | VSC_SATA_INT_ERROR_R | \
|
|
|
VSC_SATA_INT_ERROR_E | VSC_SATA_INT_ERROR_M | \
|
|
|
VSC_SATA_INT_PHY_CHANGE),
|
|
|
+
|
|
|
+ /* Host private flags (hp_flags) */
|
|
|
+ VSC_SATA_HP_FLAG_MSI = (1 << 0),
|
|
|
};
|
|
|
|
|
|
+struct vsc_sata_host_priv {
|
|
|
+ u32 hp_flags;
|
|
|
+};
|
|
|
|
|
|
#define is_vsc_sata_int_err(port_idx, int_status) \
|
|
|
(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,
|
|
|
}
|
|
|
|
|
|
|
|
|
+static void vsc_sata_host_stop(struct ata_host_set *host_set)
|
|
|
+{
|
|
|
+ struct vsc_sata_host_priv *hpriv = host_set->private_data;
|
|
|
+ struct pci_dev *pdev = to_pci_dev(host_set->dev);
|
|
|
+
|
|
|
+ if (hpriv->hp_flags & VSC_SATA_HP_FLAG_MSI)
|
|
|
+ pci_disable_msi(pdev);
|
|
|
+ else
|
|
|
+ pci_intx(pdev, 0);
|
|
|
+ kfree (hpriv);
|
|
|
+ ata_pci_host_stop(host_set);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
|
|
|
{
|
|
|
void __iomem *mask_addr;
|
|
@@ -312,7 +332,7 @@ static const struct ata_port_operations vsc_sata_ops = {
|
|
|
.scr_write = vsc_sata_scr_write,
|
|
|
.port_start = ata_port_start,
|
|
|
.port_stop = ata_port_stop,
|
|
|
- .host_stop = ata_pci_host_stop,
|
|
|
+ .host_stop = vsc_sata_host_stop,
|
|
|
};
|
|
|
|
|
|
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
|
|
|
{
|
|
|
static int printed_version;
|
|
|
struct ata_probe_ent *probe_ent = NULL;
|
|
|
+ struct vsc_sata_host_priv *hpriv;
|
|
|
unsigned long base;
|
|
|
int pci_dev_busy = 0;
|
|
|
void __iomem *mmio_base;
|
|
@@ -382,6 +403,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
|
|
|
rc = -ENOMEM;
|
|
|
goto err_out_regions;
|
|
|
}
|
|
|
+
|
|
|
memset(probe_ent, 0, sizeof(*probe_ent));
|
|
|
probe_ent->dev = pci_dev_to_dev(pdev);
|
|
|
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
|
|
|
}
|
|
|
base = (unsigned long) mmio_base;
|
|
|
|
|
|
+ hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
|
|
|
+ if (!hpriv) {
|
|
|
+ rc = -ENOMEM;
|
|
|
+ goto err_out_iounmap;
|
|
|
+ }
|
|
|
+ memset(hpriv, 0, sizeof(*hpriv));
|
|
|
+
|
|
|
/*
|
|
|
* Due to a bug in the chip, the default cache line size can't be used
|
|
|
*/
|
|
|
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80);
|
|
|
|
|
|
+ if (pci_enable_msi(pdev) == 0) {
|
|
|
+ hpriv->hp_flags |= VSC_SATA_HP_FLAG_MSI;
|
|
|
+ pci_intx(pdev, 0);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ probe_ent->irq_flags = IRQF_SHARED;
|
|
|
+
|
|
|
probe_ent->sht = &vsc_sata_sht;
|
|
|
probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
|
|
ATA_FLAG_MMIO;
|
|
|
probe_ent->port_ops = &vsc_sata_ops;
|
|
|
probe_ent->n_ports = 4;
|
|
|
probe_ent->irq = pdev->irq;
|
|
|
- probe_ent->irq_flags = IRQF_SHARED;
|
|
|
probe_ent->mmio_base = mmio_base;
|
|
|
+ probe_ent->private_data = hpriv;
|
|
|
|
|
|
/* We don't care much about the PIO/UDMA masks, but the core won't like us
|
|
|
* 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
|
|
|
|
|
|
/* FIXME: check ata_device_add return value */
|
|
|
ata_device_add(probe_ent);
|
|
|
- kfree(probe_ent);
|
|
|
|
|
|
+ kfree(probe_ent);
|
|
|
return 0;
|
|
|
|
|
|
+err_out_iounmap:
|
|
|
+ pci_iounmap(pdev, mmio_base);
|
|
|
err_out_free_ent:
|
|
|
kfree(probe_ent);
|
|
|
err_out_regions:
|