diff options
author | Brice Goglin <brice@myri.com> | 2007-05-07 17:52:22 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-05-08 01:15:15 -0400 |
commit | 5443e9ead4f53fd7a43e6846cf10fdc0c5366a93 (patch) | |
tree | f0fd7a9599aab29c5f609fd86b7ad49e2bd6b6ac | |
parent | 0d6ac257ab556838c3c5b1437a36251c2802285e (diff) |
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>
-rw-r--r-- | drivers/net/myri10ge/myri10ge.c | 121 |
1 files changed, 65 insertions, 56 deletions
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index f53b0dad65ab..5d14be7405a3 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
@@ -355,6 +355,8 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, | |||
355 | return 0; | 355 | return 0; |
356 | } else if (result == MXGEFW_CMD_UNKNOWN) { | 356 | } else if (result == MXGEFW_CMD_UNKNOWN) { |
357 | return -ENOSYS; | 357 | return -ENOSYS; |
358 | } else if (result == MXGEFW_CMD_ERROR_UNALIGNED) { | ||
359 | return -E2BIG; | ||
358 | } else { | 360 | } else { |
359 | dev_err(&mgp->pdev->dev, | 361 | dev_err(&mgp->pdev->dev, |
360 | "command %d failed, result = %d\n", | 362 | "command %d failed, result = %d\n", |
@@ -2483,8 +2485,6 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) | |||
2483 | err_cap |= PCI_ERR_CAP_ECRC_GENE; | 2485 | err_cap |= PCI_ERR_CAP_ECRC_GENE; |
2484 | pci_write_config_dword(bridge, cap + PCI_ERR_CAP, err_cap); | 2486 | pci_write_config_dword(bridge, cap + PCI_ERR_CAP, err_cap); |
2485 | dev_info(dev, "Enabled ECRC on upstream bridge %s\n", pci_name(bridge)); | 2487 | dev_info(dev, "Enabled ECRC on upstream bridge %s\n", pci_name(bridge)); |
2486 | mgp->tx.boundary = 4096; | ||
2487 | mgp->fw_name = myri10ge_fw_aligned; | ||
2488 | } | 2488 | } |
2489 | 2489 | ||
2490 | /* | 2490 | /* |
@@ -2506,22 +2506,70 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) | |||
2506 | * firmware image, and set tx.boundary to 4KB. | 2506 | * firmware image, and set tx.boundary to 4KB. |
2507 | */ | 2507 | */ |
2508 | 2508 | ||
2509 | #define PCI_DEVICE_ID_INTEL_E5000_PCIE23 0x25f7 | 2509 | static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) |
2510 | #define PCI_DEVICE_ID_INTEL_E5000_PCIE47 0x25fa | ||
2511 | #define PCI_DEVICE_ID_INTEL_6300ESB_PCIEE1 0x3510 | ||
2512 | #define PCI_DEVICE_ID_INTEL_6300ESB_PCIEE4 0x351b | ||
2513 | #define PCI_DEVICE_ID_INTEL_E3000_PCIE 0x2779 | ||
2514 | #define PCI_DEVICE_ID_INTEL_E3010_PCIE 0x277a | ||
2515 | #define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST 0x140 | ||
2516 | #define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST 0x142 | ||
2517 | |||
2518 | static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | ||
2519 | { | 2510 | { |
2520 | struct pci_dev *bridge = mgp->pdev->bus->self; | 2511 | struct pci_dev *pdev = mgp->pdev; |
2512 | struct device *dev = &pdev->dev; | ||
2513 | int cap, status; | ||
2514 | u16 val; | ||
2521 | 2515 | ||
2516 | mgp->tx.boundary = 4096; | ||
2517 | /* | ||
2518 | * Verify the max read request size was set to 4KB | ||
2519 | * before trying the test with 4KB. | ||
2520 | */ | ||
2521 | cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); | ||
2522 | if (cap < 64) { | ||
2523 | dev_err(dev, "Bad PCI_CAP_ID_EXP location %d\n", cap); | ||
2524 | goto abort; | ||
2525 | } | ||
2526 | status = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &val); | ||
2527 | if (status != 0) { | ||
2528 | dev_err(dev, "Couldn't read max read req size: %d\n", status); | ||
2529 | goto abort; | ||
2530 | } | ||
2531 | if ((val & (5 << 12)) != (5 << 12)) { | ||
2532 | dev_warn(dev, "Max Read Request size != 4096 (0x%x)\n", val); | ||
2533 | mgp->tx.boundary = 2048; | ||
2534 | } | ||
2535 | /* | ||
2536 | * load the optimized firmware (which assumes aligned PCIe | ||
2537 | * completions) in order to see if it works on this host. | ||
2538 | */ | ||
2539 | mgp->fw_name = myri10ge_fw_aligned; | ||
2540 | status = myri10ge_load_firmware(mgp); | ||
2541 | if (status != 0) { | ||
2542 | goto abort; | ||
2543 | } | ||
2544 | |||
2545 | /* | ||
2546 | * Enable ECRC if possible | ||
2547 | */ | ||
2548 | myri10ge_enable_ecrc(mgp); | ||
2549 | |||
2550 | /* | ||
2551 | * Run a DMA test which watches for unaligned completions and | ||
2552 | * aborts on the first one seen. | ||
2553 | */ | ||
2554 | |||
2555 | status = myri10ge_dma_test(mgp, MXGEFW_CMD_UNALIGNED_TEST); | ||
2556 | if (status == 0) | ||
2557 | return; /* keep the aligned firmware */ | ||
2558 | |||
2559 | if (status != -E2BIG) | ||
2560 | dev_warn(dev, "DMA test failed: %d\n", status); | ||
2561 | if (status == -ENOSYS) | ||
2562 | dev_warn(dev, "Falling back to ethp! " | ||
2563 | "Please install up to date fw\n"); | ||
2564 | abort: | ||
2565 | /* fall back to using the unaligned firmware */ | ||
2522 | mgp->tx.boundary = 2048; | 2566 | mgp->tx.boundary = 2048; |
2523 | mgp->fw_name = myri10ge_fw_unaligned; | 2567 | mgp->fw_name = myri10ge_fw_unaligned; |
2524 | 2568 | ||
2569 | } | ||
2570 | |||
2571 | static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | ||
2572 | { | ||
2525 | if (myri10ge_force_firmware == 0) { | 2573 | if (myri10ge_force_firmware == 0) { |
2526 | int link_width, exp_cap; | 2574 | int link_width, exp_cap; |
2527 | u16 lnk; | 2575 | u16 lnk; |
@@ -2530,8 +2578,6 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
2530 | pci_read_config_word(mgp->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk); | 2578 | pci_read_config_word(mgp->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk); |
2531 | link_width = (lnk >> 4) & 0x3f; | 2579 | link_width = (lnk >> 4) & 0x3f; |
2532 | 2580 | ||
2533 | myri10ge_enable_ecrc(mgp); | ||
2534 | |||
2535 | /* Check to see if Link is less than 8 or if the | 2581 | /* Check to see if Link is less than 8 or if the |
2536 | * upstream bridge is known to provide aligned | 2582 | * upstream bridge is known to provide aligned |
2537 | * completions */ | 2583 | * completions */ |
@@ -2540,46 +2586,8 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
2540 | link_width); | 2586 | link_width); |
2541 | mgp->tx.boundary = 4096; | 2587 | mgp->tx.boundary = 4096; |
2542 | mgp->fw_name = myri10ge_fw_aligned; | 2588 | mgp->fw_name = myri10ge_fw_aligned; |
2543 | } else if (bridge && | 2589 | } else { |
2544 | /* ServerWorks HT2000/HT1000 */ | 2590 | myri10ge_firmware_probe(mgp); |
2545 | ((bridge->vendor == PCI_VENDOR_ID_SERVERWORKS | ||
2546 | && bridge->device == | ||
2547 | PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE) | ||
2548 | /* ServerWorks HT2100 */ | ||
2549 | || (bridge->vendor == PCI_VENDOR_ID_SERVERWORKS | ||
2550 | && bridge->device >= | ||
2551 | PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST | ||
2552 | && bridge->device <= | ||
2553 | PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST) | ||
2554 | /* All Intel E3000/E3010 PCIE ports */ | ||
2555 | || (bridge->vendor == PCI_VENDOR_ID_INTEL | ||
2556 | && (bridge->device == | ||
2557 | PCI_DEVICE_ID_INTEL_E3000_PCIE | ||
2558 | || bridge->device == | ||
2559 | PCI_DEVICE_ID_INTEL_E3010_PCIE)) | ||
2560 | /* All Intel 6310/6311/6321ESB PCIE ports */ | ||
2561 | || (bridge->vendor == PCI_VENDOR_ID_INTEL | ||
2562 | && bridge->device >= | ||
2563 | PCI_DEVICE_ID_INTEL_6300ESB_PCIEE1 | ||
2564 | && bridge->device <= | ||
2565 | PCI_DEVICE_ID_INTEL_6300ESB_PCIEE4) | ||
2566 | /* All Intel E5000 PCIE ports */ | ||
2567 | || (bridge->vendor == PCI_VENDOR_ID_INTEL | ||
2568 | && bridge->device >= | ||
2569 | PCI_DEVICE_ID_INTEL_E5000_PCIE23 | ||
2570 | && bridge->device <= | ||
2571 | PCI_DEVICE_ID_INTEL_E5000_PCIE47))) { | ||
2572 | dev_info(&mgp->pdev->dev, | ||
2573 | "Assuming aligned completions (0x%x:0x%x)\n", | ||
2574 | bridge->vendor, bridge->device); | ||
2575 | mgp->tx.boundary = 4096; | ||
2576 | mgp->fw_name = myri10ge_fw_aligned; | ||
2577 | } else if (bridge && | ||
2578 | bridge->vendor == PCI_VENDOR_ID_SGI && | ||
2579 | bridge->device == 0x4002 /* TIOCE pcie-port */ ) { | ||
2580 | /* this pcie bridge does not support 4K rdma request */ | ||
2581 | mgp->tx.boundary = 2048; | ||
2582 | mgp->fw_name = myri10ge_fw_aligned; | ||
2583 | } | 2591 | } |
2584 | } else { | 2592 | } else { |
2585 | if (myri10ge_force_firmware == 1) { | 2593 | if (myri10ge_force_firmware == 1) { |
@@ -2847,7 +2855,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2847 | status = -ENODEV; | 2855 | status = -ENODEV; |
2848 | goto abort_with_netdev; | 2856 | goto abort_with_netdev; |
2849 | } | 2857 | } |
2850 | myri10ge_select_firmware(mgp); | ||
2851 | 2858 | ||
2852 | /* Find the vendor-specific cap so we can check | 2859 | /* Find the vendor-specific cap so we can check |
2853 | * the reboot register later on */ | 2860 | * the reboot register later on */ |
@@ -2941,6 +2948,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2941 | goto abort_with_ioremap; | 2948 | goto abort_with_ioremap; |
2942 | memset(mgp->rx_done.entry, 0, bytes); | 2949 | memset(mgp->rx_done.entry, 0, bytes); |
2943 | 2950 | ||
2951 | myri10ge_select_firmware(mgp); | ||
2952 | |||
2944 | status = myri10ge_load_firmware(mgp); | 2953 | status = myri10ge_load_firmware(mgp); |
2945 | if (status != 0) { | 2954 | if (status != 0) { |
2946 | dev_err(&pdev->dev, "failed to load firmware\n"); | 2955 | dev_err(&pdev->dev, "failed to load firmware\n"); |