svn commit: r300074 - head/sys/dev/pci

John Baldwin jhb at FreeBSD.org
Tue May 17 19:48:29 UTC 2016


Author: jhb
Date: Tue May 17 19:48:28 2016
New Revision: 300074
URL: https://svnweb.freebsd.org/changeset/base/300074

Log:
  Rework managing hotplug commands with command completions.
  
  Previously the command completion interrupt would post any pending
  command immediately before pcib_pcie_hotplug_update() had been
  run to inspect the current status.  Now, the command completion
  interrupt merely clears the flag and stops the timer assuming that
  the caller is always going to call pcib_pcie_hotplug_update() to
  generate the next hotplug command if one is needed.
  
  While here, fix a bug for systems with command completion where the
  old (existing) value was written to the slot control register instead
  of the new value.  This fixes the complaint about a missing hotplug
  interrupt on my T400.
  
  Differential Revision:	https://reviews.freebsd.org/D6363

Modified:
  head/sys/dev/pci/pci_pci.c
  head/sys/dev/pci/pcib_private.h

Modified: head/sys/dev/pci/pci_pci.c
==============================================================================
--- head/sys/dev/pci/pci_pci.c	Tue May 17 19:34:07 2016	(r300073)
+++ head/sys/dev/pci/pci_pci.c	Tue May 17 19:48:28 2016	(r300074)
@@ -874,8 +874,11 @@ pcib_probe_hotplug(struct pcib_softc *sc
 
 /*
  * Send a HotPlug command to the slot control register.  If this slot
- * uses command completion interrupts, these updates will be buffered
- * while a previous command is completing.
+ * uses command completion interrupts and a previous command is still
+ * in progress, then the command is dropped.  Once the previous
+ * command completes or times out, pcib_pcie_hotplug_update() will be
+ * invoked to post a new command based on the slot's state at that
+ * time.
  */
 static void
 pcib_pcie_hotplug_command(struct pcib_softc *sc, uint16_t val, uint16_t mask)
@@ -884,28 +887,20 @@ pcib_pcie_hotplug_command(struct pcib_so
 	uint16_t ctl, new;
 
 	dev = sc->dev;
-	if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_NCCS) {
-		ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2);
-		new = (ctl & ~mask) | val;
-		if (new != ctl)
-			pcie_write_config(dev, PCIER_SLOT_CTL, new, 2);
+
+	if (sc->flags & PCIB_HOTPLUG_CMD_PENDING)
 		return;
-	}
 
-	if (sc->flags & PCIB_HOTPLUG_CMD_PENDING) {
-		sc->pcie_pending_link_ctl_val &= ~mask;
-		sc->pcie_pending_link_ctl_val |= val;
-		sc->pcie_pending_link_ctl_mask |= mask;
-	} else {
-		ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2);
-		new = (ctl & ~mask) | val;
-		if (new != ctl) {
-			pcie_write_config(dev, PCIER_SLOT_CTL, ctl, 2);
-			sc->flags |= PCIB_HOTPLUG_CMD_PENDING;
-			if (!cold)
-				callout_reset(&sc->pcie_cc_timer, hz,
-				    pcib_pcie_cc_timeout, sc);
-		}
+	ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2);
+	new = (ctl & ~mask) | val;
+	if (new == ctl)
+		return;
+	pcie_write_config(dev, PCIER_SLOT_CTL, new, 2);
+	if (!(sc->pcie_slot_cap & PCIEM_SLOT_CAP_NCCS)) {
+		sc->flags |= PCIB_HOTPLUG_CMD_PENDING;
+		if (!cold)
+			callout_reset(&sc->pcie_cc_timer, hz,
+			    pcib_pcie_cc_timeout, sc);
 	}
 }
 
@@ -913,7 +908,6 @@ static void
 pcib_pcie_hotplug_command_completed(struct pcib_softc *sc)
 {
 	device_t dev;
-	uint16_t ctl, new;
 
 	dev = sc->dev;
 
@@ -921,23 +915,8 @@ pcib_pcie_hotplug_command_completed(stru
 		device_printf(dev, "Command Completed\n");
 	if (!(sc->flags & PCIB_HOTPLUG_CMD_PENDING))
 		return;
-	if (sc->pcie_pending_link_ctl_mask != 0) {
-		ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2);
-		new = ctl & ~sc->pcie_pending_link_ctl_mask;
-		new |= sc->pcie_pending_link_ctl_val;
-		if (new != ctl) {
-			pcie_write_config(dev, PCIER_SLOT_CTL, ctl, 2);
-			if (!cold)
-				callout_reset(&sc->pcie_cc_timer, hz,
-				    pcib_pcie_cc_timeout, sc);
-		} else
-			sc->flags &= ~PCIB_HOTPLUG_CMD_PENDING;
-		sc->pcie_pending_link_ctl_mask = 0;
-		sc->pcie_pending_link_ctl_val = 0;
-	} else {
-		callout_stop(&sc->pcie_cc_timer);
-		sc->flags &= ~PCIB_HOTPLUG_CMD_PENDING;
-	}
+	callout_stop(&sc->pcie_cc_timer);
+	sc->flags &= ~PCIB_HOTPLUG_CMD_PENDING;
 }
 
 /*
@@ -1041,11 +1020,10 @@ pcib_pcie_hotplug_update(struct pcib_sof
 	 * Interlock.
 	 */
 	if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_EIP) {
+		mask |= PCIEM_SLOT_CTL_EIC;
 		if (card_inserted !=
-		    !(sc->pcie_slot_sta & PCIEM_SLOT_STA_EIS)) {
-			mask |= PCIEM_SLOT_CTL_EIC;
+		    !(sc->pcie_slot_sta & PCIEM_SLOT_STA_EIS))
 			val |= PCIEM_SLOT_CTL_EIC;
-		}
 	}
 
 	/*

Modified: head/sys/dev/pci/pcib_private.h
==============================================================================
--- head/sys/dev/pci/pcib_private.h	Tue May 17 19:34:07 2016	(r300073)
+++ head/sys/dev/pci/pcib_private.h	Tue May 17 19:48:28 2016	(r300074)
@@ -134,8 +134,6 @@ struct pcib_softc 
     uint16_t	pcie_slot_sta;
     uint32_t	pcie_link_cap;
     uint32_t	pcie_slot_cap;
-    uint16_t	pcie_pending_link_ctl_mask;
-    uint16_t	pcie_pending_link_ctl_val;
     struct resource *pcie_irq;
     void	*pcie_ihand;
     struct task	pcie_hp_task;


More information about the svn-src-head mailing list