Sophie

Sophie

distrib > PLD > ac > amd64 > by-pkgid > 950ec4453099b5125884e99014f11757 > files > 74

kernel24-2.4.34-1.src.rpm

The 'combined' branch of
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-2.4.git

contains the following updates:

 drivers/pci/quirks.c          |   86 ++
 drivers/scsi/libata-core.c    | 1743 +++++++++++++++++++++++++++---------------
 include/linux/ioport.h        |    1 
 kernel/ksyms.c                |    1 
 kernel/resource.c             |   10 

Jeff Garzik:
      [libata] resync with kernel 2.6.13
      [libata sata_sx4] trim trailing whitespace
      [libata] resync with 2.6.14
      [libata] resync with 2.6.15-rc3
      [libata] fix build
      [libata] combined mode support, using ugly ____request_resource() hack
      [libata] fix potential oops in pdev_printk() compat helper

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 1a0408f..c4c17fc 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -702,6 +702,84 @@ static void __init asus_hides_smbus_lpc(
 	}
 }
 
+#ifdef CONFIG_SCSI_SATA
+static void __init quirk_intel_ide_combined(struct pci_dev *pdev)
+{
+	u8 prog, comb, tmp;
+	int ich = 0;
+
+	/*
+	 * Narrow down to Intel SATA PCI devices.
+	 */
+	switch (pdev->device) {
+	/* PCI ids taken from drivers/scsi/ata_piix.c */
+	case 0x24d1:
+	case 0x24df:
+	case 0x25a3:
+	case 0x25b0:
+		ich = 5;
+		break;
+	case 0x2651:
+	case 0x2652:
+	case 0x2653:
+	case 0x2680:	/* ESB2 */
+		ich = 6;
+		break;
+	case 0x27c0:
+	case 0x27c4:
+		ich = 7;
+		break;
+	default:
+		/* we do not handle this PCI device */
+		return;
+	}
+
+	/*
+	 * Read combined mode register.
+	 */
+	pci_read_config_byte(pdev, 0x90, &tmp);	/* combined mode reg */
+
+	if (ich == 5) {
+		tmp &= 0x6;  /* interesting bits 2:1, PATA primary/secondary */
+		if (tmp == 0x4)		/* bits 10x */
+			comb = (1 << 0);	/* SATA port 0, PATA port 1 */
+		else if (tmp == 0x6)	/* bits 11x */
+			comb = (1 << 2);	/* PATA port 0, SATA port 1 */
+		else
+			return;			/* not in combined mode */
+	} else {
+		WARN_ON((ich != 6) && (ich != 7));
+		tmp &= 0x3;  /* interesting bits 1:0 */
+		if (tmp & (1 << 0))
+			comb = (1 << 2);	/* PATA port 0, SATA port 1 */
+		else if (tmp & (1 << 1))
+			comb = (1 << 0);	/* SATA port 0, PATA port 1 */
+		else
+			return;			/* not in combined mode */
+	}
+
+	/*
+	 * Read programming interface register.
+	 * (Tells us if it's legacy or native mode)
+	 */
+	pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
+
+	/* if SATA port is in native mode, we're ok. */
+	if (prog & comb)
+		return;
+
+	/* SATA port is in legacy mode.  Reserve port so that
+	 * IDE driver does not attempt to use it.  If request_region
+	 * fails, it will be obvious at boot time, so we don't bother
+	 * checking return values.
+	 */
+	if (comb == (1 << 0))
+		request_region(0x1f0, 8, "libata");	/* port 0 */
+	else
+		request_region(0x170, 8, "libata");	/* port 1 */
+}
+#endif /* CONFIG_SCSI_SATA */
+
 /*
  *  The main table of quirks.
  */
@@ -788,6 +866,14 @@ static struct pci_fixup pci_fixups[] __i
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc },
 
+#ifdef CONFIG_SCSI_SATA
+	/* Fixup BIOSes that configure Parallel ATA (PATA / IDE) and
+	 * Serial ATA (SATA) into the same PCI ID.
+	 */
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL,	PCI_ANY_ID,
+	  quirk_intel_ide_combined },
+#endif /* CONFIG_SCSI_SATA */
+
 	{ 0 }
 };
 
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index ed3b745..26276d8 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -4218,16 +4737,33 @@ int ata_pci_init_one (struct pci_dev *pd
 		goto err_out;
 	}
 
+	/* FIXME: Should use platform specific mappers for legacy port ranges */
 	if (legacy_mode) {
 		if (!request_region(0x1f0, 8, "libata")) {
-			disable_dev_on_err = 0;
-			printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
+			struct resource *conflict, res;
+			res.start = 0x1f0;
+			res.end = 0x1f0 + 8 - 1;
+			conflict = ____request_resource(&ioport_resource, &res);
+			if (!strcmp(conflict->name, "libata"))
+				legacy_mode |= (1 << 0);
+			else {
+				disable_dev_on_err = 0;
+				printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
+			}
 		} else
 			legacy_mode |= (1 << 0);
 
 		if (!request_region(0x170, 8, "libata")) {
-			disable_dev_on_err = 0;
-			printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
+			struct resource *conflict, res;
+			res.start = 0x170;
+			res.end = 0x170 + 8 - 1;
+			conflict = ____request_resource(&ioport_resource, &res);
+			if (!strcmp(conflict->name, "libata"))
+				legacy_mode |= (1 << 1);
+			else {
+				disable_dev_on_err = 0;
+				printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
+			}
 		} else
 			legacy_mode |= (1 << 1);
 	}
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 94df6d4..1984c5a 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -85,6 +85,7 @@ extern struct resource iomem_resource;
 
 extern int check_resource(struct resource *root, unsigned long, unsigned long);
 extern int request_resource(struct resource *root, struct resource *new);
+extern struct resource * ____request_resource(struct resource *root, struct resource *new);
 extern int release_resource(struct resource *new);
 extern int allocate_resource(struct resource *root, struct resource *new,
 			     unsigned long size,
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index d1e66c7..5209d2f 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -448,6 +448,7 @@ EXPORT_SYMBOL(enable_hlt);
 #endif
 
 /* resource handling */
+EXPORT_SYMBOL_GPL(____request_resource); /* may disappear in a few months */
 EXPORT_SYMBOL(request_resource);
 EXPORT_SYMBOL(release_resource);
 EXPORT_SYMBOL(allocate_resource);
diff --git a/kernel/resource.c b/kernel/resource.c
index cd14435..fe736a2 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -166,6 +166,16 @@ int request_resource(struct resource *ro
 	return conflict ? -EBUSY : 0;
 }
 
+struct resource *____request_resource(struct resource *root, struct resource *new)
+{
+	struct resource *conflict;
+
+	write_lock(&resource_lock);
+	conflict = __request_resource(root, new);
+	write_unlock(&resource_lock);
+	return conflict;
+}
+
 int release_resource(struct resource *old)
 {
 	int retval;