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:
Linus Torvalds 2009-03-14 12:00:42 -07:00
commit 37e79a43ac
3 changed files with 44 additions and 2 deletions

View File

@ -1289,6 +1289,39 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
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)
{
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)
return 0;
/* is it blacklisted? */
if (piix_no_sidpr(host))
return 0;
if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
return 0;

View File

@ -2066,6 +2066,7 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
udelay(20); /* FIXME: flush */
iowrite8(ap->ctl, ioaddr->ctl_addr);
ap->last_ctl = ap->ctl;
/* wait the port to become ready */
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 */
if (ap->ioaddr.ctl_addr)
if (ap->ioaddr.ctl_addr) {
iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
ap->last_ctl = ap->ctl;
}
}
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)) {
/* set up device control for ATA_FLAG_SATA_RESET */
iowrite8(ap->ctl, ioaddr->ctl_addr);
ap->last_ctl = ap->ctl;
}
DPRINTK("EXIT\n");

View File

@ -2218,12 +2218,13 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
else
handled = mv_host_intr(host, pending_irqs);
}
spin_unlock(&host->lock);
/* for MSI: unmask; interrupt cause bits will retrigger now */
if (using_msi)
writel(hpriv->main_irq_mask, hpriv->main_irq_mask_addr);
spin_unlock(&host->lock);
return IRQ_RETVAL(handled);
}