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:
Brice Goglin 2007-05-07 23:52:22 +02:00 committed by Jeff Garzik
parent 0d6ac257ab
commit 5443e9ead4

View file

@ -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");