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

Warner Losh imp at FreeBSD.org
Mon Jul 8 19:38:51 UTC 2019


Author: imp
Date: Mon Jul  8 19:38:49 2019
New Revision: 349845
URL: https://svnweb.freebsd.org/changeset/base/349845

Log:
  Work around devices which return all zeros for reads of existing MSI-X
  table VCTRL registers.
  
  Unconditionally program the MSI-X vector control Mask field for MSI-X
  table entries without regarud for Mask's previous value. Some devices
  return all zeros on reads of the VCTRL registers, which would cause us
  to skip disabling interrupts. This fixes the Samsung SM961/PM961 SSDs
  which are return zero starting from offset 0x3084 within the memory
  region specified by BAR0, even when they are active MSI-X vectors.
  
  The Illumos kernel writes these unconditionally to 0 or 1. However,
  section 6.8.2.9 of the PCI Local Bus 3.0 spec (dated Feb 3, 2004)
  states for bits 31::01:
  	After reset, the state of these bits must be 0. However, for
  	potential future use, software must preserve the value of
  	these reserved bits when modifying the value of other Vector
  	Control bits. If software modifies the value of these reserved
  	bits, the result is undefined."
  so we always set or clear the Mask bit, but otherwise preserves the
  old value.
  
  PR: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=211713
  Reviewed By: imp, jhb
  Submitted by: Ka Ho Ng
  MFC After: 1 week
  Differential Revision: https://reviews.freebsd.org/D20873

Modified:
  head/sys/dev/pci/pci.c

Modified: head/sys/dev/pci/pci.c
==============================================================================
--- head/sys/dev/pci/pci.c	Mon Jul  8 19:26:05 2019	(r349844)
+++ head/sys/dev/pci/pci.c	Mon Jul  8 19:38:49 2019	(r349845)
@@ -1671,10 +1671,13 @@ pci_mask_msix(device_t dev, u_int index)
 	KASSERT(msix->msix_msgnum > index, ("bogus index"));
 	offset = msix->msix_table_offset + index * 16 + 12;
 	val = bus_read_4(msix->msix_table_res, offset);
-	if (!(val & PCIM_MSIX_VCTRL_MASK)) {
-		val |= PCIM_MSIX_VCTRL_MASK;
-		bus_write_4(msix->msix_table_res, offset, val);
-	}
+	val |= PCIM_MSIX_VCTRL_MASK;
+
+	/*
+	 * Some devices (e.g. Samsung PM961) do not support reads of this
+	 * register, so always write the new value.
+	 */
+	bus_write_4(msix->msix_table_res, offset, val);
 }
 
 void
@@ -1687,10 +1690,13 @@ pci_unmask_msix(device_t dev, u_int index)
 	KASSERT(msix->msix_table_len > index, ("bogus index"));
 	offset = msix->msix_table_offset + index * 16 + 12;
 	val = bus_read_4(msix->msix_table_res, offset);
-	if (val & PCIM_MSIX_VCTRL_MASK) {
-		val &= ~PCIM_MSIX_VCTRL_MASK;
-		bus_write_4(msix->msix_table_res, offset, val);
-	}
+	val &= ~PCIM_MSIX_VCTRL_MASK;
+
+	/*
+	 * Some devices (e.g. Samsung PM961) do not support reads of this
+	 * register, so always write the new value.
+	 */
+	bus_write_4(msix->msix_table_res, offset, val);
 }
 
 int


More information about the svn-src-all mailing list