mirror of
https://github.com/torvalds/linux
synced 2024-09-22 03:55:39 +00:00
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: ata_piix: add workaround for Samsung DB-P70 libata: Keep shadow last_ctl up to date during resets sata_mv: fix MSI irq race condition
This commit is contained in:
commit
37e79a43ac
|
@ -1289,6 +1289,39 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool piix_no_sidpr(struct ata_host *host)
|
||||||
|
{
|
||||||
|
struct pci_dev *pdev = to_pci_dev(host->dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Samsung DB-P70 only has three ATA ports exposed and
|
||||||
|
* curiously the unconnected first port reports link online
|
||||||
|
* while not responding to SRST protocol causing excessive
|
||||||
|
* detection delay.
|
||||||
|
*
|
||||||
|
* Unfortunately, the system doesn't carry enough DMI
|
||||||
|
* information to identify the machine but does have subsystem
|
||||||
|
* vendor and device set. As it's unclear whether the
|
||||||
|
* subsystem vendor/device is used only for this specific
|
||||||
|
* board, the port can't be disabled solely with the
|
||||||
|
* information; however, turning off SIDPR access works around
|
||||||
|
* the problem. Turn it off.
|
||||||
|
*
|
||||||
|
* This problem is reported in bnc#441240.
|
||||||
|
*
|
||||||
|
* https://bugzilla.novell.com/show_bug.cgi?id=441420
|
||||||
|
*/
|
||||||
|
if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 &&
|
||||||
|
pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG &&
|
||||||
|
pdev->subsystem_device == 0xb049) {
|
||||||
|
dev_printk(KERN_WARNING, host->dev,
|
||||||
|
"Samsung DB-P70 detected, disabling SIDPR\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int __devinit piix_init_sidpr(struct ata_host *host)
|
static int __devinit piix_init_sidpr(struct ata_host *host)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = to_pci_dev(host->dev);
|
struct pci_dev *pdev = to_pci_dev(host->dev);
|
||||||
|
@ -1302,6 +1335,10 @@ static int __devinit piix_init_sidpr(struct ata_host *host)
|
||||||
if (hpriv->map[i] == IDE)
|
if (hpriv->map[i] == IDE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* is it blacklisted? */
|
||||||
|
if (piix_no_sidpr(host))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
|
if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -2066,6 +2066,7 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
|
||||||
iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
|
iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
|
||||||
udelay(20); /* FIXME: flush */
|
udelay(20); /* FIXME: flush */
|
||||||
iowrite8(ap->ctl, ioaddr->ctl_addr);
|
iowrite8(ap->ctl, ioaddr->ctl_addr);
|
||||||
|
ap->last_ctl = ap->ctl;
|
||||||
|
|
||||||
/* wait the port to become ready */
|
/* wait the port to become ready */
|
||||||
return ata_sff_wait_after_reset(&ap->link, devmask, deadline);
|
return ata_sff_wait_after_reset(&ap->link, devmask, deadline);
|
||||||
|
@ -2190,8 +2191,10 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set up device control */
|
/* set up device control */
|
||||||
if (ap->ioaddr.ctl_addr)
|
if (ap->ioaddr.ctl_addr) {
|
||||||
iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
|
iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
|
||||||
|
ap->last_ctl = ap->ctl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(ata_sff_postreset);
|
EXPORT_SYMBOL_GPL(ata_sff_postreset);
|
||||||
|
|
||||||
|
@ -2534,6 +2537,7 @@ void ata_bus_reset(struct ata_port *ap)
|
||||||
if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
|
if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
|
||||||
/* set up device control for ATA_FLAG_SATA_RESET */
|
/* set up device control for ATA_FLAG_SATA_RESET */
|
||||||
iowrite8(ap->ctl, ioaddr->ctl_addr);
|
iowrite8(ap->ctl, ioaddr->ctl_addr);
|
||||||
|
ap->last_ctl = ap->ctl;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTK("EXIT\n");
|
DPRINTK("EXIT\n");
|
||||||
|
|
|
@ -2218,12 +2218,13 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
|
||||||
else
|
else
|
||||||
handled = mv_host_intr(host, pending_irqs);
|
handled = mv_host_intr(host, pending_irqs);
|
||||||
}
|
}
|
||||||
spin_unlock(&host->lock);
|
|
||||||
|
|
||||||
/* for MSI: unmask; interrupt cause bits will retrigger now */
|
/* for MSI: unmask; interrupt cause bits will retrigger now */
|
||||||
if (using_msi)
|
if (using_msi)
|
||||||
writel(hpriv->main_irq_mask, hpriv->main_irq_mask_addr);
|
writel(hpriv->main_irq_mask, hpriv->main_irq_mask_addr);
|
||||||
|
|
||||||
|
spin_unlock(&host->lock);
|
||||||
|
|
||||||
return IRQ_RETVAL(handled);
|
return IRQ_RETVAL(handled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue