Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 37e79a43 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
parents f1823acf e9c1670c
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -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;

+5 −1
Original line number Diff line number Diff line
@@ -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");
+2 −1
Original line number Diff line number Diff line
@@ -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);
}