ChangeSet 1.1692.3.3, 2004/03/26 16:31:44-08:00, dlsy@snoqualmie.dp.intel.com

[PATCH] PCI: Updates for PCI Express hot-plug driver


 drivers/pci/hotplug/pciehp_hpc.c      |   91 +++++++++++++++++++++++++++-------
 drivers/pci/hotplug/pciehp_pci.c      |    2 
 drivers/pci/hotplug/shpchp_hpc.c      |   11 +---
 drivers/pci/hotplug/shpchprm_acpi.c   |    3 -
 drivers/pci/hotplug/shpchprm_legacy.c |   30 -----------
 drivers/pci/pci.h                     |    2 
 drivers/pci/quirks.c                  |   11 ++++
 include/linux/pci_ids.h               |    1 
 8 files changed, 95 insertions(+), 56 deletions(-)


diff -Nru a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
--- a/drivers/pci/hotplug/pciehp_hpc.c	Thu Apr 15 10:06:13 2004
+++ b/drivers/pci/hotplug/pciehp_hpc.c	Thu Apr 15 10:06:13 2004
@@ -37,6 +37,7 @@
 #include <linux/spinlock.h>
 #include <linux/pci.h>
 #include <asm/system.h>
+#include "../pci.h"
 #include "pciehp.h"
 
 #ifdef DEBUG
@@ -315,12 +316,13 @@
 		dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__);
 	}
 
-	retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, cmd);
+	dbg("%s: Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd);
+	retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, cmd | CMD_CMPL_INTR_ENABLE);
 	if (retval) {
 		err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
 		return retval;
 	}
-	dbg("%s : hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd);
+	dbg("%s : hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd | CMD_CMPL_INTR_ENABLE);
 	dbg("%s : Exit\n", __FUNCTION__);
 
 	DBG_LEAVE_ROUTINE 
@@ -918,13 +920,32 @@
 			return IRQ_NONE;;
 		}
 
-		temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x00;
+		dbg("%s: Set Mask Hot-plug Interrupt Enable\n", __FUNCTION__);
+		dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
+		temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
 
 		rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
 		if (rc) {
 			err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
-			return IRQ_NONE;;
+			return IRQ_NONE;
+		}
+		dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
+		
+		rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+		if (rc) {
+			err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+			return IRQ_NONE;
+		}
+		dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); 
+		
+		/* Clear command complete interrupt caused by this write */
+		temp_word = 0x1f;
+		rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+		if (rc) {
+			err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
+			return IRQ_NONE;
 		}
+		dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word);
 	}
 	
 	if (intr_loc & CMD_COMPLETED) {
@@ -949,7 +970,7 @@
 			hp_slot, php_ctlr->callback_instance_id);
 
 	/* Clear all events after serving them */
-	temp_word = slot_status | 0xff;
+	temp_word = 0x1F;
 	rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
 	if (rc) {
 		err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
@@ -963,6 +984,8 @@
 			return IRQ_NONE;
 		}
 
+		dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__);
+		dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
 		temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
 
 		rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
@@ -970,6 +993,23 @@
 			err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
 			return IRQ_NONE;
 		}
+		dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); 	
+	
+		rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+		if (rc) {
+			err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+			return IRQ_NONE;
+		}
+		dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); 
+		
+		/* Clear command complete interrupt caused by this write */
+		temp_word = 0x1F;
+		rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+		if (rc) {
+			err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
+			return IRQ_NONE;
+		}
+		dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); 
 	}
 	
 	return IRQ_HANDLED;
@@ -1330,7 +1370,7 @@
 	}
 
 	dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
-	temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x00;
+	temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
 
 	rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word);
 	if (rc) {
@@ -1346,12 +1386,13 @@
 	}
 	dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status);
 
-	rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+	temp_word = 0x1F; /* Clear all events */
+	rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
 	if (rc) {
 		err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
 		goto abort_free_ctlr;
 	}
-	dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status);
+	dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, temp_word);
 
 	if (pciehp_poll_mode)  {/* Install interrupt polling code */
 		/* Install and start the interrupt polling timer */
@@ -1359,15 +1400,16 @@
 		start_int_poll_timer( php_ctlr, 10 );   /* start with 10 second delay */
 	} else {
 		/* Installs the interrupt handler */
-#ifdef CONFIG_PCI_USE_VECTOR 
-		rc = pci_enable_msi(pdev);
-		if (rc) {
-			err("Can't get msi for the hotplug controller\n");
-			dbg("%s: rc = %x\n", __FUNCTION__, rc);
-			goto abort_free_ctlr;
+		dbg("%s: pciehp_msi_quirk = %x\n", __FUNCTION__, pciehp_msi_quirk);
+		if (!pciehp_msi_quirk) {
+			rc = pci_enable_msi(pdev);
+			if (rc) {
+				info("Can't get msi for the hotplug controller\n");
+				info("Use INTx for the hotplug controller\n");
+				dbg("%s: rc = %x\n", __FUNCTION__, rc);
+			} else 
+				php_ctlr->irq = pdev->irq;
 		}
-		php_ctlr->irq = pdev->irq;
-#endif		
 		rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);
 		dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
 		if (rc) {
@@ -1384,7 +1426,7 @@
 	dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
 
 	intr_enable = ATTN_BUTTN_ENABLE | PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
-					PRSN_DETECT_ENABLE | CMD_CMPL_INTR_ENABLE;
+					PRSN_DETECT_ENABLE;
 
 	temp_word = (temp_word & ~intr_enable) | intr_enable; 
 
@@ -1402,6 +1444,21 @@
 		goto abort_free_ctlr;
 	}
 	dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word);
+	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+	if (rc) {
+		err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+	dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, 
+		SLOT_STATUS, slot_status);
+	
+	temp_word =  0x1F; /* Clear all events */
+	rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+	if (rc) {
+		err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
+		goto abort_free_ctlr;
+	}
+	dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, temp_word);
 	
 	/*  Add this HPC instance into the HPC list */
 	spin_lock(&list_lock);
diff -Nru a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
--- a/drivers/pci/hotplug/pciehp_pci.c	Thu Apr 15 10:06:13 2004
+++ b/drivers/pci/hotplug/pciehp_pci.c	Thu Apr 15 10:06:13 2004
@@ -192,7 +192,6 @@
 	for (device = FirstSupported; device <= LastSupported; device++) {
 		ID = 0xFFFFFFFF;
 		rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
-		dbg("%s: ID = %x\n", __FUNCTION__, ID);
 
 		if (ID != 0xFFFFFFFF) {	  /*  device in slot */
 			dbg("%s: ID = %x\n", __FUNCTION__, ID);
@@ -325,7 +324,6 @@
 			new_slot->presence_save = 0;
 			new_slot->switch_save = 0;
 		}
-		dbg("%s: End of For loop\n", __FUNCTION__);
 	} 			/* End of FOR loop */
 
 	dbg("%s: Exit\n", __FUNCTION__);
diff -Nru a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
--- a/drivers/pci/hotplug/shpchp_hpc.c	Thu Apr 15 10:06:13 2004
+++ b/drivers/pci/hotplug/shpchp_hpc.c	Thu Apr 15 10:06:13 2004
@@ -1441,6 +1441,7 @@
 			err("%s : shpc_cap_offset == 0\n", __FUNCTION__);
 			goto abort_free_ctlr;
 		}
+		dbg("%s: shpc_cap_offset = %x\n", __FUNCTION__, shpc_cap_offset);	
 	
 		rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , BASE_OFFSET);
 		if (rc) {
@@ -1547,15 +1548,13 @@
 		start_int_poll_timer( php_ctlr, 10 );   /* start with 10 second delay */
 	} else {
 		/* Installs the interrupt handler */
-#ifdef CONFIG_PCI_USE_VECTOR 
 		rc = pci_enable_msi(pdev);
 		if (rc) {
-			err("Can't get msi for the hotplug controller\n");
+			info("Can't get msi for the hotplug controller\n");
+			info("Use INTx for the hotplug controller\n");
 			dbg("%s: rc = %x\n", __FUNCTION__, rc);
-			goto abort_free_ctlr;
-		}
-		php_ctlr->irq = pdev->irq;
-#endif
+		} else
+			php_ctlr->irq = pdev->irq;
 		
 		rc = request_irq(php_ctlr->irq, shpc_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);
 		dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
diff -Nru a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c
--- a/drivers/pci/hotplug/shpchprm_acpi.c	Thu Apr 15 10:06:13 2004
+++ b/drivers/pci/hotplug/shpchprm_acpi.c	Thu Apr 15 10:06:13 2004
@@ -1267,7 +1267,8 @@
 int shpchprm_print_pirt(void)
 {
 	dbg("SHPCHPRM ACPI Slots\n");
-	print_acpi_resources (acpi_bridges_head);
+	if (acpi_bridges_head)
+		print_acpi_resources (acpi_bridges_head);
 	return 0;
 }
 
diff -Nru a/drivers/pci/hotplug/shpchprm_legacy.c b/drivers/pci/hotplug/shpchprm_legacy.c
--- a/drivers/pci/hotplug/shpchprm_legacy.c	Thu Apr 15 10:06:13 2004
+++ b/drivers/pci/hotplug/shpchprm_legacy.c	Thu Apr 15 10:06:13 2004
@@ -96,23 +96,6 @@
 	return fp;
 }
 
-#if link_available
-/*
- *  Links available memory, IO, and IRQ resources for programming
- *  devices which may be added to the system
- *
- *  Returns 0 if success
- */
-static int
-link_available_resources (
-	struct controller *ctrl,
-	struct pci_func *func,
-	int index )
-{
-	return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);
-}
-#endif
-
 /*
  * shpchprm_find_available_resources
  *
@@ -345,19 +328,6 @@
 			}
 		}
 
-#if link_available
-		++index;
-
-		while (index < 8) {
-			if (((func = shpchp_slot_find(primary_bus, dev_func >> 3, index)) != NULL) && populated_slot)
-				rc = link_available_resources(ctrl, func, index);
-			
-			if (rc)
-				break;
-
-			++index;
-		}
-#endif
 		i--;
 		one_slot += sizeof(struct slot_rt);
 	}
diff -Nru a/drivers/pci/pci.h b/drivers/pci/pci.h
--- a/drivers/pci/pci.h	Thu Apr 15 10:06:13 2004
+++ b/drivers/pci/pci.h	Thu Apr 15 10:06:13 2004
@@ -60,3 +60,5 @@
 
 /* Lock for read/write access to pci device and bus lists */
 extern spinlock_t pci_bus_lock;
+
+extern int pciehp_msi_quirk;
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	Thu Apr 15 10:06:13 2004
+++ b/drivers/pci/quirks.c	Thu Apr 15 10:06:13 2004
@@ -868,6 +868,13 @@
 }
 #endif /* CONFIG_SCSI_SATA */
 
+int pciehp_msi_quirk;
+
+static void __devinit quirk_pciehp_msi(struct pci_dev *pdev)
+{
+	pciehp_msi_quirk = 1;
+}
+
 /*
  *  The main table of quirks.
  *
@@ -984,6 +991,8 @@
 	  quirk_intel_ide_combined },
 #endif /* CONFIG_SCSI_SATA */
 
+	{ PCI_FIXUP_FINAL,      PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_SMCH,	quirk_pciehp_msi },
+
 	{ 0 }
 };
 
@@ -1008,3 +1017,5 @@
 	pci_do_fixups(dev, pass, pcibios_fixups);
 	pci_do_fixups(dev, pass, pci_fixups);
 }
+
+EXPORT_SYMBOL(pciehp_msi_quirk);
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	Thu Apr 15 10:06:13 2004
+++ b/include/linux/pci_ids.h	Thu Apr 15 10:06:13 2004
@@ -2073,6 +2073,7 @@
 #define PCI_DEVICE_ID_INTEL_82830_CGC	0x3577
 #define PCI_DEVICE_ID_INTEL_82855GM_HB	0x3580
 #define PCI_DEVICE_ID_INTEL_82855GM_IG	0x3582
+#define PCI_DEVICE_ID_INTEL_SMCH	0x3590
 #define PCI_DEVICE_ID_INTEL_80310	0x530d
 #define PCI_DEVICE_ID_INTEL_82371SB_0	0x7000
 #define PCI_DEVICE_ID_INTEL_82371SB_1	0x7010
