forked from Minki/linux
myri10ge: replace the chipset whitelist with firmware autodetection
Remove the aligned-completion whitelist, and replace it by using the 1.4.16 firmware's auto-detection features to choose which firmware to load. The driver now loads the aligned firmware, performs a MXGEFW_CMD_UNALIGNED_TEST, and falls back to using the unaligned firmware if: - The firmware is too old (ie, MXGEFW_CMD_UNALIGNED_TEST is an unknown command). - The MXGEFW_CMD_UNALIGNED_TEST returns MXGEFW_CMD_ERROR_UNALIGNED, meaning that it has seen an unaligned completion during the DMA test. Signed-off-by: Brice Goglin <brice@myri.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
0d6ac257ab
commit
5443e9ead4
@ -355,6 +355,8 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
|
||||
return 0;
|
||||
} else if (result == MXGEFW_CMD_UNKNOWN) {
|
||||
return -ENOSYS;
|
||||
} else if (result == MXGEFW_CMD_ERROR_UNALIGNED) {
|
||||
return -E2BIG;
|
||||
} else {
|
||||
dev_err(&mgp->pdev->dev,
|
||||
"command %d failed, result = %d\n",
|
||||
@ -2483,8 +2485,6 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
|
||||
err_cap |= PCI_ERR_CAP_ECRC_GENE;
|
||||
pci_write_config_dword(bridge, cap + PCI_ERR_CAP, err_cap);
|
||||
dev_info(dev, "Enabled ECRC on upstream bridge %s\n", pci_name(bridge));
|
||||
mgp->tx.boundary = 4096;
|
||||
mgp->fw_name = myri10ge_fw_aligned;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2506,22 +2506,70 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
|
||||
* firmware image, and set tx.boundary to 4KB.
|
||||
*/
|
||||
|
||||
#define PCI_DEVICE_ID_INTEL_E5000_PCIE23 0x25f7
|
||||
#define PCI_DEVICE_ID_INTEL_E5000_PCIE47 0x25fa
|
||||
#define PCI_DEVICE_ID_INTEL_6300ESB_PCIEE1 0x3510
|
||||
#define PCI_DEVICE_ID_INTEL_6300ESB_PCIEE4 0x351b
|
||||
#define PCI_DEVICE_ID_INTEL_E3000_PCIE 0x2779
|
||||
#define PCI_DEVICE_ID_INTEL_E3010_PCIE 0x277a
|
||||
#define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST 0x140
|
||||
#define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST 0x142
|
||||
|
||||
static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
|
||||
static void myri10ge_firmware_probe(struct myri10ge_priv *mgp)
|
||||
{
|
||||
struct pci_dev *bridge = mgp->pdev->bus->self;
|
||||
struct pci_dev *pdev = mgp->pdev;
|
||||
struct device *dev = &pdev->dev;
|
||||
int cap, status;
|
||||
u16 val;
|
||||
|
||||
mgp->tx.boundary = 4096;
|
||||
/*
|
||||
* Verify the max read request size was set to 4KB
|
||||
* before trying the test with 4KB.
|
||||
*/
|
||||
cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
|
||||
if (cap < 64) {
|
||||
dev_err(dev, "Bad PCI_CAP_ID_EXP location %d\n", cap);
|
||||
goto abort;
|
||||
}
|
||||
status = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &val);
|
||||
if (status != 0) {
|
||||
dev_err(dev, "Couldn't read max read req size: %d\n", status);
|
||||
goto abort;
|
||||
}
|
||||
if ((val & (5 << 12)) != (5 << 12)) {
|
||||
dev_warn(dev, "Max Read Request size != 4096 (0x%x)\n", val);
|
||||
mgp->tx.boundary = 2048;
|
||||
}
|
||||
/*
|
||||
* load the optimized firmware (which assumes aligned PCIe
|
||||
* completions) in order to see if it works on this host.
|
||||
*/
|
||||
mgp->fw_name = myri10ge_fw_aligned;
|
||||
status = myri10ge_load_firmware(mgp);
|
||||
if (status != 0) {
|
||||
goto abort;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable ECRC if possible
|
||||
*/
|
||||
myri10ge_enable_ecrc(mgp);
|
||||
|
||||
/*
|
||||
* Run a DMA test which watches for unaligned completions and
|
||||
* aborts on the first one seen.
|
||||
*/
|
||||
|
||||
status = myri10ge_dma_test(mgp, MXGEFW_CMD_UNALIGNED_TEST);
|
||||
if (status == 0)
|
||||
return; /* keep the aligned firmware */
|
||||
|
||||
if (status != -E2BIG)
|
||||
dev_warn(dev, "DMA test failed: %d\n", status);
|
||||
if (status == -ENOSYS)
|
||||
dev_warn(dev, "Falling back to ethp! "
|
||||
"Please install up to date fw\n");
|
||||
abort:
|
||||
/* fall back to using the unaligned firmware */
|
||||
mgp->tx.boundary = 2048;
|
||||
mgp->fw_name = myri10ge_fw_unaligned;
|
||||
|
||||
}
|
||||
|
||||
static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
|
||||
{
|
||||
if (myri10ge_force_firmware == 0) {
|
||||
int link_width, exp_cap;
|
||||
u16 lnk;
|
||||
@ -2530,8 +2578,6 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
|
||||
pci_read_config_word(mgp->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
|
||||
link_width = (lnk >> 4) & 0x3f;
|
||||
|
||||
myri10ge_enable_ecrc(mgp);
|
||||
|
||||
/* Check to see if Link is less than 8 or if the
|
||||
* upstream bridge is known to provide aligned
|
||||
* completions */
|
||||
@ -2540,46 +2586,8 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
|
||||
link_width);
|
||||
mgp->tx.boundary = 4096;
|
||||
mgp->fw_name = myri10ge_fw_aligned;
|
||||
} else if (bridge &&
|
||||
/* ServerWorks HT2000/HT1000 */
|
||||
((bridge->vendor == PCI_VENDOR_ID_SERVERWORKS
|
||||
&& bridge->device ==
|
||||
PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE)
|
||||
/* ServerWorks HT2100 */
|
||||
|| (bridge->vendor == PCI_VENDOR_ID_SERVERWORKS
|
||||
&& bridge->device >=
|
||||
PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST
|
||||
&& bridge->device <=
|
||||
PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST)
|
||||
/* All Intel E3000/E3010 PCIE ports */
|
||||
|| (bridge->vendor == PCI_VENDOR_ID_INTEL
|
||||
&& (bridge->device ==
|
||||
PCI_DEVICE_ID_INTEL_E3000_PCIE
|
||||
|| bridge->device ==
|
||||
PCI_DEVICE_ID_INTEL_E3010_PCIE))
|
||||
/* All Intel 6310/6311/6321ESB PCIE ports */
|
||||
|| (bridge->vendor == PCI_VENDOR_ID_INTEL
|
||||
&& bridge->device >=
|
||||
PCI_DEVICE_ID_INTEL_6300ESB_PCIEE1
|
||||
&& bridge->device <=
|
||||
PCI_DEVICE_ID_INTEL_6300ESB_PCIEE4)
|
||||
/* All Intel E5000 PCIE ports */
|
||||
|| (bridge->vendor == PCI_VENDOR_ID_INTEL
|
||||
&& bridge->device >=
|
||||
PCI_DEVICE_ID_INTEL_E5000_PCIE23
|
||||
&& bridge->device <=
|
||||
PCI_DEVICE_ID_INTEL_E5000_PCIE47))) {
|
||||
dev_info(&mgp->pdev->dev,
|
||||
"Assuming aligned completions (0x%x:0x%x)\n",
|
||||
bridge->vendor, bridge->device);
|
||||
mgp->tx.boundary = 4096;
|
||||
mgp->fw_name = myri10ge_fw_aligned;
|
||||
} else if (bridge &&
|
||||
bridge->vendor == PCI_VENDOR_ID_SGI &&
|
||||
bridge->device == 0x4002 /* TIOCE pcie-port */ ) {
|
||||
/* this pcie bridge does not support 4K rdma request */
|
||||
mgp->tx.boundary = 2048;
|
||||
mgp->fw_name = myri10ge_fw_aligned;
|
||||
} else {
|
||||
myri10ge_firmware_probe(mgp);
|
||||
}
|
||||
} else {
|
||||
if (myri10ge_force_firmware == 1) {
|
||||
@ -2847,7 +2855,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
status = -ENODEV;
|
||||
goto abort_with_netdev;
|
||||
}
|
||||
myri10ge_select_firmware(mgp);
|
||||
|
||||
/* Find the vendor-specific cap so we can check
|
||||
* the reboot register later on */
|
||||
@ -2941,6 +2948,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
goto abort_with_ioremap;
|
||||
memset(mgp->rx_done.entry, 0, bytes);
|
||||
|
||||
myri10ge_select_firmware(mgp);
|
||||
|
||||
status = myri10ge_load_firmware(mgp);
|
||||
if (status != 0) {
|
||||
dev_err(&pdev->dev, "failed to load firmware\n");
|
||||
|
Loading…
Reference in New Issue
Block a user