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

Commit c4eb1bf6 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:
  [libata] pata_legacy: for VLB 32bit PIO don't try tricks with slop
  [libata] pata_amd: program FIFO
  sata_mv: fix SoC interrupt breakage
  pata_it821x: resume from hibernation fails with RAID volume
parents a36e4f0c c55af1f5
Loading
Loading
Loading
Loading
+59 −17
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@
#include <linux/libata.h>

#define DRV_NAME "pata_amd"
#define DRV_VERSION "0.3.11"
#define DRV_VERSION "0.4.1"

/**
 *	timing_setup		-	shared timing computation and load
@@ -145,6 +145,13 @@ static int amd_pre_reset(struct ata_link *link, unsigned long deadline)
	return ata_sff_prereset(link, deadline);
}

/**
 *	amd_cable_detect	-	report cable type
 *	@ap: port
 *
 *	AMD controller/BIOS setups record the cable type in word 0x42
 */

static int amd_cable_detect(struct ata_port *ap)
{
	static const u32 bitmask[2] = {0x03, 0x0C};
@@ -157,6 +164,40 @@ static int amd_cable_detect(struct ata_port *ap)
	return ATA_CBL_PATA40;
}

/**
 *	amd_fifo_setup		-	set the PIO FIFO for ATA/ATAPI
 *	@ap: ATA interface
 *	@adev: ATA device
 *
 *	Set the PCI fifo for this device according to the devices present
 *	on the bus at this point in time. We need to turn the post write buffer
 *	off for ATAPI devices as we may need to issue a word sized write to the
 *	device as the final I/O
 */

static void amd_fifo_setup(struct ata_port *ap)
{
	struct ata_device *adev;
	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
	static const u8 fifobit[2] = { 0xC0, 0x30};
	u8 fifo = fifobit[ap->port_no];
	u8 r;


	ata_for_each_dev(adev, &ap->link, ENABLED) {
		if (adev->class == ATA_DEV_ATAPI)
			fifo = 0;
	}
	if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411) /* FIFO is broken */
		fifo = 0;

	/* On the later chips the read prefetch bits become no-op bits */
	pci_read_config_byte(pdev, 0x41, &r);
	r &= ~fifobit[ap->port_no];
	r |= fifo;
	pci_write_config_byte(pdev, 0x41, r);
}

/**
 *	amd33_set_piomode	-	set initial PIO mode data
 *	@ap: ATA interface
@@ -167,21 +208,25 @@ static int amd_cable_detect(struct ata_port *ap)

static void amd33_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
	amd_fifo_setup(ap);
	timing_setup(ap, adev, 0x40, adev->pio_mode, 1);
}

static void amd66_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
	amd_fifo_setup(ap);
	timing_setup(ap, adev, 0x40, adev->pio_mode, 2);
}

static void amd100_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
	amd_fifo_setup(ap);
	timing_setup(ap, adev, 0x40, adev->pio_mode, 3);
}

static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
	amd_fifo_setup(ap);
	timing_setup(ap, adev, 0x40, adev->pio_mode, 4);
}

@@ -397,6 +442,16 @@ static struct ata_port_operations nv133_port_ops = {
	.set_dmamode	= nv133_set_dmamode,
};

static void amd_clear_fifo(struct pci_dev *pdev)
{
	u8 fifo;
	/* Disable the FIFO, the FIFO logic will re-enable it as
	   appropriate */
	pci_read_config_byte(pdev, 0x41, &fifo);
	fifo &= 0x0F;
	pci_write_config_byte(pdev, 0x41, fifo);
}

static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
	static const struct ata_port_info info[10] = {
@@ -503,14 +558,8 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)

	if (type < 3)
		ata_pci_bmdma_clear_simplex(pdev);

	/* Check for AMD7411 */
	if (type == 3)
		/* FIFO is broken */
		pci_write_config_byte(pdev, 0x41, fifo & 0x0F);
	else
		pci_write_config_byte(pdev, 0x41, fifo | 0xF0);

	if (pdev->vendor == PCI_VENDOR_ID_AMD)
		amd_clear_fifo(pdev);
	/* Cable detection on Nvidia chips doesn't work too well,
	 * cache BIOS programmed UDMA mode.
	 */
@@ -536,18 +585,11 @@ static int amd_reinit_one(struct pci_dev *pdev)
		return rc;

	if (pdev->vendor == PCI_VENDOR_ID_AMD) {
		u8 fifo;
		pci_read_config_byte(pdev, 0x41, &fifo);
		if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411)
			/* FIFO is broken */
			pci_write_config_byte(pdev, 0x41, fifo & 0x0F);
		else
			pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
		amd_clear_fifo(pdev);
		if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 ||
		    pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
			ata_pci_bmdma_clear_simplex(pdev);
	}

	ata_host_resume(host);
	return 0;
}
+3 −0
Original line number Diff line number Diff line
@@ -557,6 +557,9 @@ static unsigned int it821x_read_id(struct ata_device *adev,
		id[83] |= 0x4400;	/* Word 83 is valid and LBA48 */
		id[86] |= 0x0400;	/* LBA48 on */
		id[ATA_ID_MAJOR_VER] |= 0x1F;
		/* Clear the serial number because it's different each boot
		   which breaks validation on resume */
		memset(&id[ATA_ID_SERNO], 0x20, ATA_ID_SERNO_LEN);
	}
	return err_mask;
}
+4 −3
Original line number Diff line number Diff line
@@ -283,9 +283,10 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
			unsigned char *buf, unsigned int buflen, int rw)
{
	if (ata_id_has_dword_io(dev->id)) {
		struct ata_port *ap = dev->link->ap;
	int slop = buflen & 3;
	/* 32bit I/O capable *and* we need to write a whole number of dwords */
	if (ata_id_has_dword_io(dev->id) && (slop == 0 || slop == 3)) {
		struct ata_port *ap = dev->link->ap;
		unsigned long flags;

		local_irq_save(flags);
@@ -735,7 +736,7 @@ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
	struct ata_port *ap = adev->link->ap;
	int slop = buflen & 3;

	if (ata_id_has_dword_io(adev->id)) {
	if (ata_id_has_dword_io(adev->id) && (slop == 0 || slop == 3)) {
		if (rw == WRITE)
			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
		else
+9 −11
Original line number Diff line number Diff line
@@ -3114,7 +3114,6 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
		writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
	}

	if (!IS_SOC(hpriv)) {
	/* Clear any currently outstanding host interrupt conditions */
	writelfl(0, mmio + hpriv->irq_cause_ofs);

@@ -3126,7 +3125,6 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
	 * The per-port interrupts get done later as ports are set up.
	 */
	mv_set_main_irq_mask(host, 0, PCI_ERR);
	}
done:
	return rc;
}