summaryrefslogtreecommitdiffstats
path: root/sys/dev/nfe
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2010-11-14 23:37:43 +0000
committeryongari <yongari@FreeBSD.org>2010-11-14 23:37:43 +0000
commit5a7162f62d8d21d7ec6fa137495afbab65b3688a (patch)
treeef6bd73687225e86627993311b145462602f678a /sys/dev/nfe
parentbe16647d2886c423de954843da55b62db5466df2 (diff)
downloadFreeBSD-src-5a7162f62d8d21d7ec6fa137495afbab65b3688a.zip
FreeBSD-src-5a7162f62d8d21d7ec6fa137495afbab65b3688a.tar.gz
P5N32-SLI PREMIUM from ASUSTeK is known to have MSI/MSI-X issue
such that nfe(4) does not work with MSI-X. When MSI-X support was introduced, I remember MCP55 controller worked without problems so the issue could be either PCI bridge or BIOS issue. But I also noticed snd_hda(4) disabled MSI on all MCP55 chipset so I'm still not sure this is generic issue of MCP55 chipset. If this was PCI bridge issue we would have added it to a system wide black-list table but it's not clear to me at this moment whether it was caused by either broken BIOS or silicon bug of MCP55 chipset. To workaround the issue, maintain a MSI/MSI-X black-list table in driver and lookup base board manufacturer and product name from the table before attempting to use MSI-X. If driver find an matching entry, nfe(4) will not use MSI/MSI-X and fall back on traditional INTx mode. This approach should be the last resort since it relies on smbios and if another instance of MSI/MSI-X breakage is reported with different maker/product, we may have to get the PCI bridge black-listed instead of adding an new entry. PR: kern/152150
Diffstat (limited to 'sys/dev/nfe')
-rw-r--r--sys/dev/nfe/if_nfe.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/sys/dev/nfe/if_nfe.c b/sys/dev/nfe/if_nfe.c
index fcc11c2..a56bb97 100644
--- a/sys/dev/nfe/if_nfe.c
+++ b/sys/dev/nfe/if_nfe.c
@@ -77,6 +77,7 @@ static int nfe_detach(device_t);
static int nfe_suspend(device_t);
static int nfe_resume(device_t);
static int nfe_shutdown(device_t);
+static int nfe_can_use_msix(struct nfe_softc *);
static void nfe_power(struct nfe_softc *);
static int nfe_miibus_readreg(device_t, int, int);
static int nfe_miibus_writereg(device_t, int, int, int);
@@ -383,6 +384,13 @@ nfe_attach(device_t dev)
"max. width of link(x%d)\n", width, v);
}
+ if (nfe_can_use_msix(sc) == 0) {
+ device_printf(sc->nfe_dev,
+ "MSI/MSI-X capability black-listed, will use INTx\n");
+ msix_disable = 1;
+ msi_disable = 1;
+ }
+
/* Allocate interrupt */
if (msix_disable == 0 || msi_disable == 0) {
if (msix_disable == 0 &&
@@ -784,6 +792,41 @@ nfe_resume(device_t dev)
}
+static int
+nfe_can_use_msix(struct nfe_softc *sc)
+{
+ static struct msix_blacklist {
+ char *maker;
+ char *product;
+ } msix_blacklists[] = {
+ { "ASUSTeK Computer INC.", "P5N32-SLI PREMIUM" }
+ };
+
+ struct msix_blacklist *mblp;
+ char *maker, *product;
+ int count, n;
+
+ /*
+ * Search base board manufacturer and product name table
+ * to see this system has a known MSI/MSI-X issue.
+ */
+ maker = getenv("smbios.planar.maker");
+ product = getenv("smbios.planar.product");
+ if (maker != NULL && product != NULL) {
+ count = sizeof(msix_blacklists) / sizeof(msix_blacklists[0]);
+ mblp = msix_blacklists;
+ for (n = 0; n < count; n++) {
+ if (strcmp(maker, mblp->maker) == 0 &&
+ strcmp(product, mblp->product) == 0)
+ return (0);
+ mblp++;
+ }
+ }
+
+ return (1);
+}
+
+
/* Take PHY/NIC out of powerdown, from Linux */
static void
nfe_power(struct nfe_softc *sc)
OpenPOWER on IntegriCloud