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

Commit f8a9efb5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  libata: handle broken cable reporting
  pata_hpt37x: Fix outstanding bug reports on the HPT374 and 37x cable detect
  ata_piix: Add additional PCI identifier for 40 wire short cable
  pata_serverworks: Fix problem with some drive combinations
  libata: Don't disable dipm with SET FEATURES
  libata and bogus LBA48 drives
parents 61edab8d 6bbfd53d
Loading
Loading
Loading
Loading
+30 −9
Original line number Diff line number Diff line
@@ -676,10 +676,11 @@ static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy)
		if (rc)
			return rc;

		/* disable DIPM */
		if (ata_dev_enabled(dev) && (dev->flags & ATA_DFLAG_DIPM))
			err_mask = ata_dev_set_feature(dev,
					SETFEATURES_SATA_DISABLE, SATA_DIPM);
		/*
		 * we don't have to disable DIPM since IPM flags
		 * disallow transitions to SLUMBER, which effectively
		 * disable DIPM if it does not support PARTIAL
		 */
		break;
	case NOT_AVAILABLE:
	case MAX_PERFORMANCE:
@@ -689,10 +690,11 @@ static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy)
		if (rc)
			return rc;

		/* disable DIPM */
		if (ata_dev_enabled(dev) && (dev->flags & ATA_DFLAG_DIPM))
			err_mask = ata_dev_set_feature(dev,
					SETFEATURES_SATA_DISABLE, SATA_DIPM);
		/*
		 * we don't have to disable DIPM since IPM flags
		 * disallow all transitions which effectively
		 * disable DIPM anyway.
		 */
		break;
	}

@@ -4239,6 +4241,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
	{ "ST340823A",		NULL,		ATA_HORKAGE_HPA_SIZE, },
	{ "ST320413A",		NULL,		ATA_HORKAGE_HPA_SIZE, },

	/* Devices which get the IVB wrong */
	{ "QUANTUM FIREBALLlct10 05", "A03.0900", ATA_HORKAGE_IVB, },
	{ "TSSTcorp CDDVDW SH-S202J", "SB00",	  ATA_HORKAGE_IVB, },

	/* End Marker */
	{ }
};
@@ -4299,6 +4305,21 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
	return (dev->horkage & ATA_HORKAGE_NODMA) ? 1 : 0;
}

/**
 *	ata_is_40wire		-	check drive side detection
 *	@dev: device
 *
 *	Perform drive side detection decoding, allowing for device vendors
 *	who can't follow the documentation.
 */

static int ata_is_40wire(struct ata_device *dev)
{
	if (dev->horkage & ATA_HORKAGE_IVB)
		return ata_drive_40wire_relaxed(dev->id);
	return ata_drive_40wire(dev->id);
}

/**
 *	ata_dev_xfermask - Compute supported xfermask of the given device
 *	@dev: Device to compute xfermask for
@@ -4368,7 +4389,7 @@ static void ata_dev_xfermask(struct ata_device *dev)
	if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))
		/* UDMA/44 or higher would be available */
		if ((ap->cbl == ATA_CBL_PATA40) ||
		    (ata_drive_40wire(dev->id) &&
		    (ata_is_40wire(dev) &&
		    (ap->cbl == ATA_CBL_PATA_UNK ||
		     ap->cbl == ATA_CBL_PATA80))) {
			ata_dev_printk(dev, KERN_WARNING,
+36 −13
Original line number Diff line number Diff line
@@ -295,7 +295,7 @@ static unsigned long hpt370_filter(struct ata_device *adev, unsigned long mask)

static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
{
	if (adev->class != ATA_DEV_ATA) {
	if (adev->class == ATA_DEV_ATA) {
		if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
			mask &= ~ (0x1F << ATA_SHIFT_UDMA);
	}
@@ -359,28 +359,25 @@ static int hpt374_pre_reset(struct ata_link *link, unsigned long deadline)
		{ 0x50, 1, 0x04, 0x04 },
		{ 0x54, 1, 0x04, 0x04 }
	};
	u16 mcr3, mcr6;
	u16 mcr3;
	u8 ata66;
	struct ata_port *ap = link->ap;
	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
	unsigned int mcrbase = 0x50 + 4 * ap->port_no;

	if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no]))
		return -ENOENT;

	/* Do the extra channel work */
	pci_read_config_word(pdev, 0x52, &mcr3);
	pci_read_config_word(pdev, 0x56, &mcr6);
	pci_read_config_word(pdev, mcrbase + 2, &mcr3);
	/* Set bit 15 of 0x52 to enable TCBLID as input
	   Set bit 15 of 0x56 to enable FCBLID as input
	 */
	pci_write_config_word(pdev, 0x52, mcr3 | 0x8000);
	pci_write_config_word(pdev, 0x56, mcr6 | 0x8000);
	pci_write_config_word(pdev, mcrbase + 2, mcr3 | 0x8000);
	pci_read_config_byte(pdev, 0x5A, &ata66);
	/* Reset TCBLID/FCBLID to output */
	pci_write_config_word(pdev, 0x52, mcr3);
	pci_write_config_word(pdev, 0x56, mcr6);

	if (ata66 & (1 << ap->port_no))
	if (ata66 & (2 >> ap->port_no))
		ap->cbl = ATA_CBL_PATA40;
	else
		ap->cbl = ATA_CBL_PATA80;
@@ -844,6 +841,25 @@ static int hpt37x_calibrate_dpll(struct pci_dev *dev)
	/* Never went stable */
	return 0;
}

static u32 hpt374_read_freq(struct pci_dev *pdev)
{
	u32 freq;
	unsigned long io_base = pci_resource_start(pdev, 4);
	if (PCI_FUNC(pdev->devfn) & 1) {
		struct pci_dev *pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1);
		/* Someone hot plugged the controller on us ? */
		if (pdev_0 == NULL)
			return 0;
		io_base = pci_resource_start(pdev_0, 4);
		freq = inl(io_base + 0x90);
		pci_dev_put(pdev_0);
	}
	else
		freq = inl(io_base + 0x90);
	return freq;
}

/**
 *	hpt37x_init_one		-	Initialise an HPT37X/302
 *	@dev: PCI device
@@ -902,7 +918,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
		.flags = ATA_FLAG_SLAVE_POSS,
		.pio_mask = 0x1f,
		.mwdma_mask = 0x07,
		.udma_mask = 0x0f,
		.udma_mask = ATA_UDMA5,
		.port_ops = &hpt370_port_ops
	};
	/* HPT370A - UDMA100 */
@@ -911,7 +927,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
		.flags = ATA_FLAG_SLAVE_POSS,
		.pio_mask = 0x1f,
		.mwdma_mask = 0x07,
		.udma_mask = 0x0f,
		.udma_mask = ATA_UDMA5,
		.port_ops = &hpt370a_port_ops
	};
	/* HPT371, 372 and friends - UDMA133 */
@@ -1047,9 +1063,16 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
		outb(0x0e, iobase + 0x9c);

	/* Some devices do not let this value be accessed via PCI space
	   according to the old driver */
	   according to the old driver. In addition we must use the value
	   from FN 0 on the HPT374 */

	if (chip_table == &hpt374) {
		freq = hpt374_read_freq(dev);
		if (freq == 0)
			return -ENODEV;
	} else
		freq = inl(iobase + 0x90);

	if ((freq >> 12) != 0xABCDE) {
		int i;
		u8 sr;
+5 −6
Original line number Diff line number Diff line
@@ -274,28 +274,27 @@ static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev
{
	static const u8 dma_mode[] = { 0x77, 0x21, 0x20 };
	int offset = 1 + 2 * ap->port_no - adev->devno;
	int devbits = (2 * ap->port_no + adev->devno);
	int devbits = 2 * ap->port_no + adev->devno;
	u8 ultra;
	u8 ultra_cfg;
	struct pci_dev *pdev = to_pci_dev(ap->host->dev);

	pci_read_config_byte(pdev, 0x54, &ultra_cfg);
	pci_read_config_byte(pdev, 0x56 + ap->port_no, &ultra);
	ultra &= ~(0x0F << (adev->devno * 4));

	if (adev->dma_mode >= XFER_UDMA_0) {
		pci_write_config_byte(pdev, 0x44 + offset,  0x20);

		pci_read_config_byte(pdev, 0x56 + ap->port_no, &ultra);
		ultra &= ~(0x0F << (ap->port_no * 4));
		ultra |= (adev->dma_mode - XFER_UDMA_0)
					<< (ap->port_no * 4);
		pci_write_config_byte(pdev, 0x56 + ap->port_no, ultra);

					<< (adev->devno * 4);
		ultra_cfg |=  (1 << devbits);
	} else {
		pci_write_config_byte(pdev, 0x44 + offset,
			dma_mode[adev->dma_mode - XFER_MW_DMA_0]);
		ultra_cfg &= ~(1 << devbits);
	}
	pci_write_config_byte(pdev, 0x56 + ap->port_no, ultra);
	pci_write_config_byte(pdev, 0x54, ultra_cfg);
}

+11 −0
Original line number Diff line number Diff line
@@ -425,6 +425,8 @@ static inline int ata_id_has_lba48(const u16 *id)
{
	if ((id[83] & 0xC000) != 0x4000)
		return 0;
	if (!ata_id_u64(id, 100))
		return 0;
	return id[83] & (1 << 10);
}

@@ -535,6 +537,15 @@ static inline int ata_drive_40wire(const u16 *dev_id)
	return 1;
}

static inline int ata_drive_40wire_relaxed(const u16 *dev_id)
{
	if (ata_id_is_sata(dev_id))
		return 0;	/* SATA */
	if ((dev_id[93] & 0x2000) == 0x2000)
		return 0;	/* 80 wire */
	return 1;
}

static inline int atapi_cdb_len(const u16 *dev_id)
{
	u16 tmp = dev_id[0] & 0x3;
+1 −0
Original line number Diff line number Diff line
@@ -339,6 +339,7 @@ enum {
	ATA_HORKAGE_SKIP_PM	= (1 << 5),	/* Skip PM operations */
	ATA_HORKAGE_HPA_SIZE	= (1 << 6),	/* native size off by one */
	ATA_HORKAGE_IPM		= (1 << 7),	/* Link PM problems */
	ATA_HORKAGE_IVB		= (1 << 8),	/* cbl det validity bit bugs */

	 /* DMA mask for user DMA control: User visible values; DO NOT
	    renumber */