Commit 83242623 authored by Jeff Garzik's avatar Jeff Garzik

[libata ata_piix] fix combined mode device detection

SATA port detection should not have assumed that a single SATA port
mapped to a single struct ata_port.  Combined mode breaks this
assumption.

Change code to simply detect if one or more devices are present
on the struct ata_port, which is what we really wanted to do.
parent 208d680d
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "ata_piix" #define DRV_NAME "ata_piix"
#define DRV_VERSION "1.01" #define DRV_VERSION "1.02"
enum { enum {
PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ PIIX_IOCFG = 0x54, /* IDE I/O configuration register */
...@@ -44,6 +44,9 @@ enum { ...@@ -44,6 +44,9 @@ enum {
PIIX_COMB_PATA_P0 = (1 << 1), PIIX_COMB_PATA_P0 = (1 << 1),
PIIX_COMB = (1 << 2), /* combined mode enabled? */ PIIX_COMB = (1 << 2), /* combined mode enabled? */
PIIX_PORT_PRESENT = (1 << 0),
PIIX_PORT_ENABLED = (1 << 4),
PIIX_80C_PRI = (1 << 5) | (1 << 4), PIIX_80C_PRI = (1 << 5) | (1 << 4),
PIIX_80C_SEC = (1 << 7) | (1 << 6), PIIX_80C_SEC = (1 << 7) | (1 << 6),
...@@ -262,32 +265,48 @@ static void piix_pata_phy_reset(struct ata_port *ap) ...@@ -262,32 +265,48 @@ static void piix_pata_phy_reset(struct ata_port *ap)
} }
/** /**
* piix_pcs_probe - Probe SATA port configuration and status register * piix_sata_probe - Probe PCI device for present SATA devices
* @ap: Port to probe * @pdev: PCI device to probe
* @have_port: (output) Non-zero if SATA port is enabled
* @have_device: (output) Non-zero if SATA phy indicates device present
* *
* Reads SATA PCI device's PCI config register Port Configuration * Reads SATA PCI device's PCI config register Port Configuration
* and Status (PCS) to determine port and device availability. * and Status (PCS) to determine port and device availability.
* *
* LOCKING: * LOCKING:
* None (inherited from caller). * None (inherited from caller).
*
* RETURNS:
* Non-zero if device detected, zero otherwise.
*/ */
static void piix_pcs_probe (struct ata_port *ap, unsigned int *have_port, static int piix_sata_probe (struct ata_port *ap)
unsigned int *have_device)
{ {
struct pci_dev *pdev = ap->host_set->pdev; struct pci_dev *pdev = ap->host_set->pdev;
u16 pcs; int combined = (ap->flags & ATA_FLAG_SLAVE_POSS);
int orig_mask, mask, i;
pci_read_config_word(pdev, ICH5_PCS, &pcs); u8 pcs;
mask = (PIIX_PORT_PRESENT << ap->port_no) |
(PIIX_PORT_ENABLED << ap->port_no);
pci_read_config_byte(pdev, ICH5_PCS, &pcs);
orig_mask = (int) pcs & 0xff;
/* TODO: this is vaguely wrong for ICH6 combined mode,
* where only two of the four SATA ports are mapped
* onto a single ATA channel. It is also vaguely inaccurate
* for ICH5, which has only two ports. However, this is ok,
* as further device presence detection code will handle
* any false positives produced here.
*/
/* is SATA port enabled? */ for (i = 0; i < 4; i++) {
if (pcs & (1 << ap->port_no)) { mask = (PIIX_PORT_PRESENT << i) | (PIIX_PORT_ENABLED << i);
*have_port = 1;
if (pcs & (1 << (ap->port_no + 4))) if ((orig_mask & mask) == mask)
*have_device = 1; if (combined || (i == ap->port_no))
return 1;
} }
return 0;
} }
/** /**
...@@ -302,9 +321,6 @@ static void piix_pcs_probe (struct ata_port *ap, unsigned int *have_port, ...@@ -302,9 +321,6 @@ static void piix_pcs_probe (struct ata_port *ap, unsigned int *have_port,
static void piix_sata_phy_reset(struct ata_port *ap) static void piix_sata_phy_reset(struct ata_port *ap)
{ {
const char *msg;
unsigned int have_port = 0, have_dev = 0;
if (!pci_test_config_bits(ap->host_set->pdev, if (!pci_test_config_bits(ap->host_set->pdev,
&piix_enable_bits[ap->port_no])) { &piix_enable_bits[ap->port_no])) {
ata_port_disable(ap); ata_port_disable(ap);
...@@ -312,18 +328,9 @@ static void piix_sata_phy_reset(struct ata_port *ap) ...@@ -312,18 +328,9 @@ static void piix_sata_phy_reset(struct ata_port *ap)
return; return;
} }
piix_pcs_probe(ap, &have_port, &have_dev); if (!piix_sata_probe(ap)) {
if (!have_port)
msg = KERN_INFO "ata%u: SATA port disabled.\n";
else if (!have_dev)
msg = KERN_INFO "ata%u: SATA port has no device.\n";
else
msg = NULL;
if (msg) {
ata_port_disable(ap); ata_port_disable(ap);
printk(msg, ap->id); printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id);
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment