| summaryrefslogtreecommitdiff |
| author | Michal Marek <mmarek@suse.cz> | 2011-08-15 15:03:47 (GMT) |
|---|---|---|
| committer | Michal Marek <mmarek@suse.cz> | 2011-08-15 15:10:58 (GMT) |
| commit | ad018206999662a15597f6154357374c9eb1108c (patch) (side-by-side diff) | |
| tree | bb8fa23f07a7accbdb0de3924e182021d0474ce5 | |
| parent | c44dd9aa273ac5952a10a1d03b7b70bb6ddb096c (diff) | |
- patches.drivers/0001-bnx2x-PFC-fixes.patch: bnx2x: PFC fixesrpm-2.6.32.44-0.7
(fate#311461. bnc#698050).
- patches.drivers/0002-bnx2x-Change-BCM54616S-to-BCM54618SE.patch:
bnx2x: Change BCM54616S to BCM54618SE (fate#311461. bnc#698050).
- patches.drivers/0003-bnx2x-Add-CL37-BAM-for-Warpcore.patch:
bnx2x: Add CL37 BAM for Warpcore (fate#311461. bnc#698050).
- patches.drivers/0004-bnx2x-Reset-PHY-due-to-fan-failure-for-578xx.patch:
bnx2x: Reset PHY due to fan failure for 578xx
(fate#311461. bnc#698050).
- patches.drivers/0005-bnx2x-Fix-false-link-indication-at-link-partner-when.patch:
bnx2x: Fix false link indication at link partner when DAC is
used (fate#311461. bnc#698050).
- patches.drivers/0006-bnx2x-Fix-BCM84833-initialization.patch:
bnx2x: Fix BCM84833 initialization (fate#311461. bnc#698050).
- patches.drivers/0007-bnx2x-Add-autogrEEEn-support.patch: bnx2x:
Add autogrEEEn support (fate#311461. bnc#698050).
- patches.drivers/0008-bnx2x-Fix-warning-message-during-57712-8727-initiali.patch:
bnx2x: Fix warning message during 57712/8727 initialization
(fate#311461. bnc#698050).
- patches.drivers/0009-bnx2x-remove-unnecessary-read-of-PCI_CAP_ID_EXP.patch:
bnx2x: remove unnecessary read of PCI_CAP_ID_EXP
(fate#311461. bnc#698050).
- patches.drivers/0010-net-bnx2x-fix-DMA-sync-direction.patch:
net: bnx2x: fix DMA sync direction (fate#311461. bnc#698050).
- patches.drivers/0011-bnx2x-Renaming-the-reset_task-to-sp_rtnl_task.patch:
bnx2x: Renaming the "reset_task" to "sp_rtnl_task"
(fate#311461. bnc#698050).
- patches.drivers/0012-bnx2x-Multiple-concurrent-l2-traffic-classes.patch:
bnx2x: Multiple concurrent l2 traffic classes
(fate#311461. bnc#698050).
- patches.drivers/0013-bnx2x-add-missing-command-in-error-handling-flow.patch:
bnx2x: add missing command in error handling flow
(fate#311461. bnc#698050).
- patches.drivers/0014-bnx2x-stop-tx-before-CNIC_STOP.patch:
bnx2x: stop tx before CNIC_STOP (fate#311461. bnc#698050).
- patches.drivers/0015-bnx2x-remove-unnecessary-dma_sync.patch:
bnx2x: remove unnecessary dma_sync (fate#311461. bnc#698050).
- patches.drivers/0016-bnx2x-DCB-rework.patch: bnx2x: DCB rework
(fate#311461. bnc#698050).
- patches.drivers/0017-bnx2x-use-pci_pcie_cap.patch: bnx2x:
use pci_pcie_cap() (fate#311461. bnc#698050).
- patches.drivers/0018-bnx2x-disable-loacal-BH-when-scheduling-FCOE-napi.patch:
bnx2x: disable loacal BH when scheduling FCOE napi
(fate#311461. bnc#698050).
- patches.drivers/0019-bnx2x-use-BNX2X_Q_FLG_TPA_IPV6-for-TPA-queue-configu.patch:
bnx2x: use BNX2X_Q_FLG_TPA_IPV6 for TPA queue configuration
(fate#311461. bnc#698050).
- patches.drivers/0020-bnx2x-fix-memory-barriers.patch: bnx2x:
fix memory barriers (fate#311461. bnc#698050).
- patches.drivers/0021-bnx2x-disable-FCoE-for-578xx-devices-since-not-yet-s.patch:
bnx2x: disable FCoE for 578xx devices since not yet supported
(fate#311461. bnc#698050).
- patches.drivers/0022-bnx2x-dcb-send-all-unmapped-priorities-to-same-COS-a.patch:
bnx2x: dcb - send all unmapped priorities to same COS as L2
(fate#311461. bnc#698050).
- patches.drivers/0023-bnx2x-fix-loopback-for-non-10G-link.patch:
bnx2x: fix loopback for non 10G link (fate#311461. bnc#698050).
- patches.drivers/0024-bnx2x-count-statistic-ramrods-on-EQ-to-prevent-MC-as.patch:
bnx2x: count statistic ramrods on EQ to prevent MC assert
(fate#311461. bnc#698050).
- patches.drivers/0025-bnx2x-enable-internal-target-read-for-57712-and-up-o.patch:
bnx2x: enable internal target-read for 57712 and up only
(fate#311461. bnc#698050).
- patches.drivers/0026-bnx2x-fix-bnx2x_stop_on_error-flow-in-bnx2x_sp_rtnl_.patch:
bnx2x: fix bnx2x_stop_on_error flow in bnx2x_sp_rtnl_task
(fate#311461. bnc#698050).
- patches.drivers/0027-bnx2x-Prevent-restarting-Tx-during-bnx2x_nic_unload.patch:
bnx2x: Prevent restarting Tx during bnx2x_nic_unload
(fate#311461. bnc#698050).
- patches.drivers/0028-bnx2x-Fix-missing-pause-on-for-578xx.patch:
bnx2x: Fix missing pause on for 578xx (fate#311461. bnc#698050).
- patches.drivers/0029-bnx2x-Fix-chip-hanging-due-to-TX-pipe-stall.patch:
bnx2x: Fix chip hanging due to TX pipe stall
(fate#311461. bnc#698050).
- patches.drivers/0030-bnx2x-Fix-remote-fault-handling.patch:
bnx2x: Fix remote fault handling (fate#311461. bnc#698050).
- patches.drivers/0031-bnx2x-Fix-BCM578xx-B0-MDIO-access.patch:
bnx2x: Fix BCM578xx-B0 MDIO access (fate#311461. bnc#698050).
- patches.drivers/0032-bnx2x-Fix-LED-behavior.patch: bnx2x:
Fix LED behavior (fate#311461. bnc#698050).
- patches.drivers/0033-bnx2x-Fix-link-issue-with-DAC-over-578xx.patch:
bnx2x: Fix link issue with DAC over 578xx
(fate#311461. bnc#698050).
- patches.drivers/0034-bnx2x-Fix-BCM84833-link.patch: bnx2x:
Fix BCM84833 link (fate#311461. bnc#698050).
- patches.drivers/0035-bnx2x-Fix-BCM54618se-invalid-link-indication.patch:
bnx2x: Fix BCM54618se invalid link indication
(fate#311461. bnc#698050).
- patches.drivers/0036-bnx2x-Fix-BCM578xx-MAC-test.patch: bnx2x:
Fix BCM578xx MAC test (fate#311461. bnc#698050).
- patches.drivers/0037-bnx2x-Clear-MDIO-access-warning-during-first-driver-.patch:
bnx2x: Clear MDIO access warning during first driver load
(fate#311461. bnc#698050).
- patches.drivers/0038-bnx2x-call-netdev_alloc_mq_with_correct_param.patch:
(fate#311461. bnc#698050).
- patches.drivers/net-3-5-bnx2x-prevent-race-between-undi_unload-and-load-flows.patch:
(fate#311461. bnc#698050).
- patches.drivers/net-4-5-bnx2x-properly-clean-indirect-addresses.patch:
(fate#311461. bnc#698050).
- patches.drivers/net-5-5-bnx2x-disable-dcb-on-unsupported-devices.patch:
bnx2x: disable DCB on unsupported devices
(fate#311461. bnc#698050).
43 files changed, 7872 insertions, 0 deletions
diff --git a/kernel-source.changes b/kernel-source.changes index 7e416b9..c596bd6 100644 --- a/kernel-source.changes +++ b/kernel-source.changes @@ -1,4 +1,110 @@ ------------------------------------------------------------------- +Mon Aug 15 17:03:40 CEST 2011 - mmarek@suse.cz + +- patches.drivers/0001-bnx2x-PFC-fixes.patch: bnx2x: PFC fixes + (fate#311461. bnc#698050). +- patches.drivers/0002-bnx2x-Change-BCM54616S-to-BCM54618SE.patch: + bnx2x: Change BCM54616S to BCM54618SE (fate#311461. bnc#698050). +- patches.drivers/0003-bnx2x-Add-CL37-BAM-for-Warpcore.patch: + bnx2x: Add CL37 BAM for Warpcore (fate#311461. bnc#698050). +- patches.drivers/0004-bnx2x-Reset-PHY-due-to-fan-failure-for-578xx.patch: + bnx2x: Reset PHY due to fan failure for 578xx + (fate#311461. bnc#698050). +- patches.drivers/0005-bnx2x-Fix-false-link-indication-at-link-partner-when.patch: + bnx2x: Fix false link indication at link partner when DAC is + used (fate#311461. bnc#698050). +- patches.drivers/0006-bnx2x-Fix-BCM84833-initialization.patch: + bnx2x: Fix BCM84833 initialization (fate#311461. bnc#698050). +- patches.drivers/0007-bnx2x-Add-autogrEEEn-support.patch: bnx2x: + Add autogrEEEn support (fate#311461. bnc#698050). +- patches.drivers/0008-bnx2x-Fix-warning-message-during-57712-8727-initiali.patch: + bnx2x: Fix warning message during 57712/8727 initialization + (fate#311461. bnc#698050). +- patches.drivers/0009-bnx2x-remove-unnecessary-read-of-PCI_CAP_ID_EXP.patch: + bnx2x: remove unnecessary read of PCI_CAP_ID_EXP + (fate#311461. bnc#698050). +- patches.drivers/0010-net-bnx2x-fix-DMA-sync-direction.patch: + net: bnx2x: fix DMA sync direction (fate#311461. bnc#698050). +- patches.drivers/0011-bnx2x-Renaming-the-reset_task-to-sp_rtnl_task.patch: + bnx2x: Renaming the "reset_task" to "sp_rtnl_task" + (fate#311461. bnc#698050). +- patches.drivers/0012-bnx2x-Multiple-concurrent-l2-traffic-classes.patch: + bnx2x: Multiple concurrent l2 traffic classes + (fate#311461. bnc#698050). +- patches.drivers/0013-bnx2x-add-missing-command-in-error-handling-flow.patch: + bnx2x: add missing command in error handling flow + (fate#311461. bnc#698050). +- patches.drivers/0014-bnx2x-stop-tx-before-CNIC_STOP.patch: + bnx2x: stop tx before CNIC_STOP (fate#311461. bnc#698050). +- patches.drivers/0015-bnx2x-remove-unnecessary-dma_sync.patch: + bnx2x: remove unnecessary dma_sync (fate#311461. bnc#698050). +- patches.drivers/0016-bnx2x-DCB-rework.patch: bnx2x: DCB rework + (fate#311461. bnc#698050). +- patches.drivers/0017-bnx2x-use-pci_pcie_cap.patch: bnx2x: + use pci_pcie_cap() (fate#311461. bnc#698050). +- patches.drivers/0018-bnx2x-disable-loacal-BH-when-scheduling-FCOE-napi.patch: + bnx2x: disable loacal BH when scheduling FCOE napi + (fate#311461. bnc#698050). +- patches.drivers/0019-bnx2x-use-BNX2X_Q_FLG_TPA_IPV6-for-TPA-queue-configu.patch: + bnx2x: use BNX2X_Q_FLG_TPA_IPV6 for TPA queue configuration + (fate#311461. bnc#698050). +- patches.drivers/0020-bnx2x-fix-memory-barriers.patch: bnx2x: + fix memory barriers (fate#311461. bnc#698050). +- patches.drivers/0021-bnx2x-disable-FCoE-for-578xx-devices-since-not-yet-s.patch: + bnx2x: disable FCoE for 578xx devices since not yet supported + (fate#311461. bnc#698050). +- patches.drivers/0022-bnx2x-dcb-send-all-unmapped-priorities-to-same-COS-a.patch: + bnx2x: dcb - send all unmapped priorities to same COS as L2 + (fate#311461. bnc#698050). +- patches.drivers/0023-bnx2x-fix-loopback-for-non-10G-link.patch: + bnx2x: fix loopback for non 10G link (fate#311461. bnc#698050). +- patches.drivers/0024-bnx2x-count-statistic-ramrods-on-EQ-to-prevent-MC-as.patch: + bnx2x: count statistic ramrods on EQ to prevent MC assert + (fate#311461. bnc#698050). +- patches.drivers/0025-bnx2x-enable-internal-target-read-for-57712-and-up-o.patch: + bnx2x: enable internal target-read for 57712 and up only + (fate#311461. bnc#698050). +- patches.drivers/0026-bnx2x-fix-bnx2x_stop_on_error-flow-in-bnx2x_sp_rtnl_.patch: + bnx2x: fix bnx2x_stop_on_error flow in bnx2x_sp_rtnl_task + (fate#311461. bnc#698050). +- patches.drivers/0027-bnx2x-Prevent-restarting-Tx-during-bnx2x_nic_unload.patch: + bnx2x: Prevent restarting Tx during bnx2x_nic_unload + (fate#311461. bnc#698050). +- patches.drivers/0028-bnx2x-Fix-missing-pause-on-for-578xx.patch: + bnx2x: Fix missing pause on for 578xx (fate#311461. bnc#698050). +- patches.drivers/0029-bnx2x-Fix-chip-hanging-due-to-TX-pipe-stall.patch: + bnx2x: Fix chip hanging due to TX pipe stall + (fate#311461. bnc#698050). +- patches.drivers/0030-bnx2x-Fix-remote-fault-handling.patch: + bnx2x: Fix remote fault handling (fate#311461. bnc#698050). +- patches.drivers/0031-bnx2x-Fix-BCM578xx-B0-MDIO-access.patch: + bnx2x: Fix BCM578xx-B0 MDIO access (fate#311461. bnc#698050). +- patches.drivers/0032-bnx2x-Fix-LED-behavior.patch: bnx2x: + Fix LED behavior (fate#311461. bnc#698050). +- patches.drivers/0033-bnx2x-Fix-link-issue-with-DAC-over-578xx.patch: + bnx2x: Fix link issue with DAC over 578xx + (fate#311461. bnc#698050). +- patches.drivers/0034-bnx2x-Fix-BCM84833-link.patch: bnx2x: + Fix BCM84833 link (fate#311461. bnc#698050). +- patches.drivers/0035-bnx2x-Fix-BCM54618se-invalid-link-indication.patch: + bnx2x: Fix BCM54618se invalid link indication + (fate#311461. bnc#698050). +- patches.drivers/0036-bnx2x-Fix-BCM578xx-MAC-test.patch: bnx2x: + Fix BCM578xx MAC test (fate#311461. bnc#698050). +- patches.drivers/0037-bnx2x-Clear-MDIO-access-warning-during-first-driver-.patch: + bnx2x: Clear MDIO access warning during first driver load + (fate#311461. bnc#698050). +- patches.drivers/0038-bnx2x-call-netdev_alloc_mq_with_correct_param.patch: + (fate#311461. bnc#698050). +- patches.drivers/net-3-5-bnx2x-prevent-race-between-undi_unload-and-load-flows.patch: + (fate#311461. bnc#698050). +- patches.drivers/net-4-5-bnx2x-properly-clean-indirect-addresses.patch: + (fate#311461. bnc#698050). +- patches.drivers/net-5-5-bnx2x-disable-dcb-on-unsupported-devices.patch: + bnx2x: disable DCB on unsupported devices + (fate#311461. bnc#698050). + +------------------------------------------------------------------- Mon Aug 15 12:40:16 CEST 2011 - trenn@suse.de bnc#703937: diff --git a/patches.drivers/0001-bnx2x-PFC-fixes.patch b/patches.drivers/0001-bnx2x-PFC-fixes.patch new file mode 100644 index 0000000..6a1d5d6 --- a/dev/null +++ b/patches.drivers/0001-bnx2x-PFC-fixes.patch @@ -0,0 +1,223 @@ +From 517f8c79f1ab0a9b121ab0570f40d6b15b83d3de Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 5 Jul 2011 01:06:27 +0000 +Subject: [PATCH 01/37] bnx2x: PFC fixes +Patch-mainline: v3.1-rc1 +Git-commit: b8d6d0824d064ad447e6aacbce90f3a340d93d65 +References: fate#311461. bnc#698050 + +Set the source MAC address for PFC packets and update its status during PMF migration. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_hsi.h | 2 + + drivers/net/bnx2x/bnx2x_link.c | 87 +++++++++++++++++++++++----------------- + drivers/net/bnx2x/bnx2x_reg.h | 12 +++++ + 3 files changed, 64 insertions(+), 37 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h +index df53558..d6a7aa9 100644 +--- a/drivers/net/bnx2x/bnx2x_hsi.h ++++ b/drivers/net/bnx2x/bnx2x_hsi.h +@@ -1196,6 +1196,8 @@ struct drv_port_mb { + #define LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE 0x00800000 + #define LINK_STATUS_LINK_PARTNER_20GXFD_CAPABLE 0x10000000 + ++ #define LINK_STATUS_PFC_ENABLED 0x20000000 ++ + u32 port_stx; + + u32 stat_nig_timer; +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index 8363636..57ba811 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -1344,28 +1344,21 @@ static void bnx2x_update_pfc_xmac(struct link_params *params, + REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL, pfc0_val); + REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI, pfc1_val); + +- udelay(30); +-} + ++ /* Set MAC address for source TX Pause/PFC frames */ ++ REG_WR(bp, xmac_base + XMAC_REG_CTRL_SA_LO, ++ ((params->mac_addr[2] << 24) | ++ (params->mac_addr[3] << 16) | ++ (params->mac_addr[4] << 8) | ++ (params->mac_addr[5]))); ++ REG_WR(bp, xmac_base + XMAC_REG_CTRL_SA_HI, ++ ((params->mac_addr[0] << 8) | ++ (params->mac_addr[1]))); + +-static void bnx2x_bmac2_get_pfc_stat(struct link_params *params, +- u32 pfc_frames_sent[2], +- u32 pfc_frames_received[2]) +-{ +- /* Read pfc statistic */ +- struct bnx2x *bp = params->bp; +- u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM : +- NIG_REG_INGRESS_BMAC0_MEM; +- +- DP(NETIF_MSG_LINK, "pfc statistic read from BMAC\n"); +- +- REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_STAT_GTPP, +- pfc_frames_sent, 2); ++ udelay(30); ++} + +- REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_STAT_GRPP, +- pfc_frames_received, 2); + +-} + static void bnx2x_emac_get_pfc_stat(struct link_params *params, + u32 pfc_frames_sent[2], + u32 pfc_frames_received[2]) +@@ -1397,28 +1390,23 @@ static void bnx2x_emac_get_pfc_stat(struct link_params *params, + pfc_frames_sent[0] = val_xon + val_xoff; + } + ++/* Read pfc statistic*/ + void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars, + u32 pfc_frames_sent[2], + u32 pfc_frames_received[2]) + { + /* Read pfc statistic */ + struct bnx2x *bp = params->bp; +- u32 val = 0; ++ + DP(NETIF_MSG_LINK, "pfc statistic\n"); + + if (!vars->link_up) + return; + +- val = REG_RD(bp, MISC_REG_RESET_REG_2); +- if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) +- == 0) { +- DP(NETIF_MSG_LINK, "About to read stats from EMAC\n"); ++ if (MAC_TYPE_EMAC == vars->mac_type) { ++ DP(NETIF_MSG_LINK, "About to read PFC stats from EMAC\n"); + bnx2x_emac_get_pfc_stat(params, pfc_frames_sent, + pfc_frames_received); +- } else { +- DP(NETIF_MSG_LINK, "About to read stats from BMAC\n"); +- bnx2x_bmac2_get_pfc_stat(params, pfc_frames_sent, +- pfc_frames_received); + } + } + /******************************************************************/ +@@ -1561,6 +1549,16 @@ static void bnx2x_umac_enable(struct link_params *params, + REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val); + udelay(50); + ++ /* Set MAC address for source TX Pause/PFC frames (under SW reset) */ ++ REG_WR(bp, umac_base + UMAC_REG_MAC_ADDR0, ++ ((params->mac_addr[2] << 24) | ++ (params->mac_addr[3] << 16) | ++ (params->mac_addr[4] << 8) | ++ (params->mac_addr[5]))); ++ REG_WR(bp, umac_base + UMAC_REG_MAC_ADDR1, ++ ((params->mac_addr[0] << 8) | ++ (params->mac_addr[1]))); ++ + /* Enable RX and TX */ + val &= ~UMAC_COMMAND_CONFIG_REG_PAD_EN; + val |= UMAC_COMMAND_CONFIG_REG_TX_ENA | +@@ -2358,6 +2356,15 @@ int bnx2x_pfc_nig_rx_priority_mask(struct bnx2x *bp, + + return 0; + } ++static void bnx2x_update_mng(struct link_params *params, u32 link_status) ++{ ++ struct bnx2x *bp = params->bp; ++ ++ REG_WR(bp, params->shmem_base + ++ offsetof(struct shmem_region, ++ port_mb[params->port].link_status), link_status); ++} ++ + static void bnx2x_update_pfc_nig(struct link_params *params, + struct link_vars *vars, + struct bnx2x_nig_brb_pfc_port_params *nig_params) +@@ -2467,6 +2474,14 @@ int bnx2x_update_pfc(struct link_params *params, + struct bnx2x *bp = params->bp; + int bnx2x_status = 0; + u8 bmac_loopback = (params->loopback_mode == LOOPBACK_BMAC); ++ ++ if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED) ++ vars->link_status |= LINK_STATUS_PFC_ENABLED; ++ else ++ vars->link_status &= ~LINK_STATUS_PFC_ENABLED; ++ ++ bnx2x_update_mng(params, vars->link_status); ++ + /* update NIG params */ + bnx2x_update_pfc_nig(params, vars, pfc_params); + +@@ -2695,16 +2710,6 @@ static int bnx2x_bmac_enable(struct link_params *params, + return rc; + } + +- +-static void bnx2x_update_mng(struct link_params *params, u32 link_status) +-{ +- struct bnx2x *bp = params->bp; +- +- REG_WR(bp, params->shmem_base + +- offsetof(struct shmem_region, +- port_mb[params->port].link_status), link_status); +-} +- + static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port) + { + u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM : +@@ -4453,6 +4458,14 @@ void bnx2x_link_status_update(struct link_params *params, + + vars->aeu_int_mask = REG_RD(bp, sync_offset); + ++ /* Sync PFC status */ ++ if (vars->link_status & LINK_STATUS_PFC_ENABLED) ++ params->feature_config_flags |= ++ FEATURE_CONFIG_PFC_ENABLED; ++ else ++ params->feature_config_flags &= ++ ~FEATURE_CONFIG_PFC_ENABLED; ++ + DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x int_mask 0x%x\n", + vars->link_status, vars->phy_link_up, vars->aeu_int_mask); + DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n", +diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h +index 96de859..201ca95 100644 +--- a/drivers/net/bnx2x/bnx2x_reg.h ++++ b/drivers/net/bnx2x/bnx2x_reg.h +@@ -4779,6 +4779,12 @@ + #define UMAC_COMMAND_CONFIG_REG_SW_RESET (0x1<<13) + #define UMAC_COMMAND_CONFIG_REG_TX_ENA (0x1<<0) + #define UMAC_REG_COMMAND_CONFIG 0x8 ++/* [RW 32] Register Bit 0 refers to Bit 16 of the MAC address; Bit 1 refers ++ * to bit 17 of the MAC address etc. */ ++#define UMAC_REG_MAC_ADDR0 0xc ++/* [RW 16] Register Bit 0 refers to Bit 0 of the MAC address; Register Bit 1 ++ * refers to Bit 1 of the MAC address etc. Bits 16 to 31 are reserved. */ ++#define UMAC_REG_MAC_ADDR1 0x10 + /* [RW 14] Defines a 14-Bit maximum frame length used by the MAC receive + * logic to check frames. */ + #define UMAC_REG_MAXFR 0x14 +@@ -5308,6 +5314,12 @@ + #define XMAC_PFC_CTRL_HI_REG_TX_PFC_EN (0x1<<5) + #define XMAC_REG_CLEAR_RX_LSS_STATUS 0x60 + #define XMAC_REG_CTRL 0 ++/* [RW 16] Upper 48 bits of ctrl_sa register. Used as the SA in PAUSE/PFC ++ * packets transmitted by the MAC */ ++#define XMAC_REG_CTRL_SA_HI 0x2c ++/* [RW 32] Lower 48 bits of ctrl_sa register. Used as the SA in PAUSE/PFC ++ * packets transmitted by the MAC */ ++#define XMAC_REG_CTRL_SA_LO 0x28 + #define XMAC_REG_PAUSE_CTRL 0x68 + #define XMAC_REG_PFC_CTRL 0x70 + #define XMAC_REG_PFC_CTRL_HI 0x74 +-- +1.7.2.2 + diff --git a/patches.drivers/0002-bnx2x-Change-BCM54616S-to-BCM54618SE.patch b/patches.drivers/0002-bnx2x-Change-BCM54616S-to-BCM54618SE.patch new file mode 100644 index 0000000..66115be --- a/dev/null +++ b/patches.drivers/0002-bnx2x-Change-BCM54616S-to-BCM54618SE.patch @@ -0,0 +1,248 @@ +From 10353a52324b5e5fdf60572db2c22189962b458d Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 5 Jul 2011 01:06:34 +0000 +Subject: [PATCH 02/37] bnx2x: Change BCM54616S to BCM54618SE +Patch-mainline: v3.1-rc1 +Git-commit: 52c4d6c4b543574930667bfc2a4aed8af0713519 +References: fate#311461. bnc#698050 + +Change 1G copper PHY BCM54616S to BCM54618SE since we only have HW with latter one of the two. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_hsi.h | 4 +- + drivers/net/bnx2x/bnx2x_link.c | 78 ++++++++++++++++++++++++++-------------- + drivers/net/bnx2x/bnx2x_reg.h | 10 +++++- + 3 files changed, 62 insertions(+), 30 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h +index d6a7aa9..e6f816d 100644 +--- a/drivers/net/bnx2x/bnx2x_hsi.h ++++ b/drivers/net/bnx2x/bnx2x_hsi.h +@@ -696,7 +696,7 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ + #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84823 0x00000b00 + #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54640 0x00000c00 + #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84833 0x00000d00 +- #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54616 0x00000e00 ++ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54618SE 0x00000e00 + #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8722 0x00000f00 + #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE 0x0000fd00 + #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN 0x0000ff00 +@@ -751,7 +751,7 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ + #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823 0x00000b00 + #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54640 0x00000c00 + #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833 0x00000d00 +- #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616 0x00000e00 ++ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE 0x00000e00 + #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722 0x00000f00 + #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT_WC 0x0000fc00 + #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00 +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index 57ba811..011548a 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -3530,7 +3530,7 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy, + vars->flow_ctrl = params->req_fc_auto_adv; + else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) { + ret = 1; +- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616) { ++ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) { + bnx2x_cl22_read(bp, phy, + 0x4, &ld_pause); + bnx2x_cl22_read(bp, phy, +@@ -5549,7 +5549,7 @@ static u16 bnx2x_wait_reset_complete(struct bnx2x *bp, + u16 cnt, ctrl; + /* Wait for soft reset to get cleared up to 1 sec */ + for (cnt = 0; cnt < 1000; cnt++) { +- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616) ++ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) + bnx2x_cl22_read(bp, phy, + MDIO_PMA_REG_CTRL, &ctrl); + else +@@ -9800,9 +9800,9 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, + } + + /******************************************************************/ +-/* 54616S PHY SECTION */ ++/* 54618SE PHY SECTION */ + /******************************************************************/ +-static int bnx2x_54616s_config_init(struct bnx2x_phy *phy, ++static int bnx2x_54618se_config_init(struct bnx2x_phy *phy, + struct link_params *params, + struct link_vars *vars) + { +@@ -9811,7 +9811,7 @@ static int bnx2x_54616s_config_init(struct bnx2x_phy *phy, + u16 autoneg_val, an_1000_val, an_10_100_val, fc_val, temp; + u32 cfg_pin; + +- DP(NETIF_MSG_LINK, "54616S cfg init\n"); ++ DP(NETIF_MSG_LINK, "54618SE cfg init\n"); + usleep_range(1000, 1000); + + /* This works with E3 only, no need to check the chip +@@ -9973,11 +9973,11 @@ static int bnx2x_54616s_config_init(struct bnx2x_phy *phy, + return 0; + } + +-static void bnx2x_54616s_set_link_led(struct bnx2x_phy *phy, +- struct link_params *params, u8 mode) ++static void bnx2x_54618se_set_link_led(struct bnx2x_phy *phy, ++ struct link_params *params, u8 mode) + { + struct bnx2x *bp = params->bp; +- DP(NETIF_MSG_LINK, "54616S set link led (mode=%x)\n", mode); ++ DP(NETIF_MSG_LINK, "54618SE set link led (mode=%x)\n", mode); + switch (mode) { + case LED_MODE_FRONT_PANEL_OFF: + case LED_MODE_OFF: +@@ -9989,8 +9989,8 @@ static void bnx2x_54616s_set_link_led(struct bnx2x_phy *phy, + return; + } + +-static void bnx2x_54616s_link_reset(struct bnx2x_phy *phy, +- struct link_params *params) ++static void bnx2x_54618se_link_reset(struct bnx2x_phy *phy, ++ struct link_params *params) + { + struct bnx2x *bp = params->bp; + u32 cfg_pin; +@@ -10009,9 +10009,9 @@ static void bnx2x_54616s_link_reset(struct bnx2x_phy *phy, + bnx2x_set_cfg_pin(bp, cfg_pin, 0); + } + +-static u8 bnx2x_54616s_read_status(struct bnx2x_phy *phy, +- struct link_params *params, +- struct link_vars *vars) ++static u8 bnx2x_54618se_read_status(struct bnx2x_phy *phy, ++ struct link_params *params, ++ struct link_vars *vars) + { + struct bnx2x *bp = params->bp; + u16 val; +@@ -10022,7 +10022,7 @@ static u8 bnx2x_54616s_read_status(struct bnx2x_phy *phy, + bnx2x_cl22_read(bp, phy, + 0x19, + &legacy_status); +- DP(NETIF_MSG_LINK, "54616S read_status: 0x%x\n", legacy_status); ++ DP(NETIF_MSG_LINK, "54618SE read_status: 0x%x\n", legacy_status); + + /* Read status to clear the PHY interrupt. */ + bnx2x_cl22_read(bp, phy, +@@ -10074,21 +10074,45 @@ static u8 bnx2x_54616s_read_status(struct bnx2x_phy *phy, + vars->link_status |= + LINK_STATUS_PARALLEL_DETECTION_USED; + +- DP(NETIF_MSG_LINK, "BCM54616S: link speed is %d\n", ++ DP(NETIF_MSG_LINK, "BCM54618SE: link speed is %d\n", + vars->line_speed); ++ ++ /* Report whether EEE is resolved. */ ++ bnx2x_cl22_read(bp, phy, MDIO_REG_GPHY_PHYID_LSB, &val); ++ if (val == MDIO_REG_GPHY_ID_54618SE) { ++ if (vars->link_status & ++ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) ++ val = 0; ++ else { ++ bnx2x_cl22_write(bp, phy, ++ MDIO_REG_GPHY_CL45_ADDR_REG, ++ MDIO_AN_DEVAD); ++ bnx2x_cl22_write(bp, phy, ++ MDIO_REG_GPHY_CL45_DATA_REG, ++ MDIO_REG_GPHY_EEE_RESOLVED); ++ bnx2x_cl22_write(bp, phy, ++ MDIO_REG_GPHY_CL45_ADDR_REG, ++ (0x1 << 14) | MDIO_AN_DEVAD); ++ bnx2x_cl22_read(bp, phy, ++ MDIO_REG_GPHY_CL45_DATA_REG, ++ &val); ++ } ++ DP(NETIF_MSG_LINK, "EEE resolution: 0x%x\n", val); ++ } ++ + bnx2x_ext_phy_resolve_fc(phy, params, vars); + } + return link_up; + } + +-static void bnx2x_54616s_config_loopback(struct bnx2x_phy *phy, +- struct link_params *params) ++static void bnx2x_54618se_config_loopback(struct bnx2x_phy *phy, ++ struct link_params *params) + { + struct bnx2x *bp = params->bp; + u16 val; + u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0; + +- DP(NETIF_MSG_LINK, "2PMA/PMD ext_phy_loopback: 54616s\n"); ++ DP(NETIF_MSG_LINK, "2PMA/PMD ext_phy_loopback: 54618se\n"); + + /* Enable master/slave manual mmode and set to master */ + /* mii write 9 [bits set 11 12] */ +@@ -10705,8 +10729,8 @@ static struct bnx2x_phy phy_84833 = { + .phy_specific_func = (phy_specific_func_t)NULL + }; + +-static struct bnx2x_phy phy_54616s = { +- .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616, ++static struct bnx2x_phy phy_54618se = { ++ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE, + .addr = 0xff, + .def_md_devad = 0, + .flags = FLAGS_INIT_XGXS_FIRST, +@@ -10729,13 +10753,13 @@ static struct bnx2x_phy phy_54616s = { + .speed_cap_mask = 0, + /* req_duplex = */0, + /* rsrv = */0, +- .config_init = (config_init_t)bnx2x_54616s_config_init, +- .read_status = (read_status_t)bnx2x_54616s_read_status, +- .link_reset = (link_reset_t)bnx2x_54616s_link_reset, +- .config_loopback = (config_loopback_t)bnx2x_54616s_config_loopback, ++ .config_init = (config_init_t)bnx2x_54618se_config_init, ++ .read_status = (read_status_t)bnx2x_54618se_read_status, ++ .link_reset = (link_reset_t)bnx2x_54618se_link_reset, ++ .config_loopback = (config_loopback_t)bnx2x_54618se_config_loopback, + .format_fw_ver = (format_fw_ver_t)NULL, + .hw_reset = (hw_reset_t)NULL, +- .set_link_led = (set_link_led_t)bnx2x_54616s_set_link_led, ++ .set_link_led = (set_link_led_t)bnx2x_54618se_set_link_led, + .phy_specific_func = (phy_specific_func_t)NULL + }; + /*****************************************************************/ +@@ -10978,8 +11002,8 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp, + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833: + *phy = phy_84833; + break; +- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616: +- *phy = phy_54616s; ++ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE: ++ *phy = phy_54618se; + break; + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: + *phy = phy_7101; +diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h +index 201ca95..1de1ef4 100644 +--- a/drivers/net/bnx2x/bnx2x_reg.h ++++ b/drivers/net/bnx2x/bnx2x_reg.h +@@ -6933,7 +6933,15 @@ Theotherbitsarereservedandshouldbezero*/ + + #define DIGITAL5_ACTUAL_SPEED_TX_MASK 0x003f + +-/* 54616s */ ++/* 54618se */ ++#define MDIO_REG_GPHY_PHYID_LSB 0x3 ++#define MDIO_REG_GPHY_ID_54618SE 0x5cd5 ++#define MDIO_REG_GPHY_CL45_ADDR_REG 0xd ++#define MDIO_REG_GPHY_CL45_DATA_REG 0xe ++#define MDIO_REG_GPHY_EEE_ADV 0x3c ++#define MDIO_REG_GPHY_EEE_1G (0x1 << 2) ++#define MDIO_REG_GPHY_EEE_100 (0x1 << 1) ++#define MDIO_REG_GPHY_EEE_RESOLVED 0x803e + #define MDIO_REG_INTR_STATUS 0x1a + #define MDIO_REG_INTR_MASK 0x1b + #define MDIO_REG_INTR_MASK_LINK_STATUS (0x1 << 1) +-- +1.7.2.2 + diff --git a/patches.drivers/0003-bnx2x-Add-CL37-BAM-for-Warpcore.patch b/patches.drivers/0003-bnx2x-Add-CL37-BAM-for-Warpcore.patch new file mode 100644 index 0000000..2a71ae0 --- a/dev/null +++ b/patches.drivers/0003-bnx2x-Add-CL37-BAM-for-Warpcore.patch @@ -0,0 +1,66 @@ +From db2fd26c81ee8dda6d8bd1a5fe17ddf4aa03890f Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 5 Jul 2011 01:06:41 +0000 +Subject: [PATCH 03/37] bnx2x: Add CL37 BAM for Warpcore +Patch-mainline: v3.1-rc1 +Git-commit: a34bc969a19b3a2364c03c101abb3b4d467089c0 +References: fate#311461. bnc#698050 + +Add CL37 BAM support according to configuration. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_link.c | 14 +++++++++++++- + drivers/net/bnx2x/bnx2x_reg.h | 1 + + 2 files changed, 14 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index 011548a..270a2f7 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -3564,7 +3564,7 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy, + static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, + struct link_params *params, + struct link_vars *vars) { +- u16 val16 = 0, lane; ++ u16 val16 = 0, lane, bam37 = 0; + struct bnx2x *bp = params->bp; + DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n"); + /* Check adding advertisement for 1G KX */ +@@ -3616,6 +3616,18 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, + MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16); + ++ /* Enable CL37 BAM */ ++ if (REG_RD(bp, params->shmem_base + ++ offsetof(struct shmem_region, dev_info. ++ port_hw_config[params->port].default_cfg)) & ++ PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED) { ++ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, ++ MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL, &bam37); ++ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, ++ MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL, bam37 | 1); ++ DP(NETIF_MSG_LINK, "Enable CL37 BAM on KR\n"); ++ } ++ + /* Advertise pause */ + bnx2x_ext_phy_set_pause(params, phy, vars); + +diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h +index 1de1ef4..df783c5 100644 +--- a/drivers/net/bnx2x/bnx2x_reg.h ++++ b/drivers/net/bnx2x/bnx2x_reg.h +@@ -6903,6 +6903,7 @@ Theotherbitsarereservedandshouldbezero*/ + #define MDIO_WC_REG_DIGITAL5_MISC6 0x8345 + #define MDIO_WC_REG_DIGITAL5_MISC7 0x8349 + #define MDIO_WC_REG_DIGITAL5_ACTUAL_SPEED 0x834e ++#define MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL 0x8350 + #define MDIO_WC_REG_CL49_USERB0_CTRL 0x8368 + #define MDIO_WC_REG_TX66_CONTROL 0x83b0 + #define MDIO_WC_REG_RX66_CONTROL 0x83c0 +-- +1.7.2.2 + diff --git a/patches.drivers/0004-bnx2x-Reset-PHY-due-to-fan-failure-for-578xx.patch b/patches.drivers/0004-bnx2x-Reset-PHY-due-to-fan-failure-for-578xx.patch new file mode 100644 index 0000000..f89422e --- a/dev/null +++ b/patches.drivers/0004-bnx2x-Reset-PHY-due-to-fan-failure-for-578xx.patch @@ -0,0 +1,174 @@ +From eaf15f538662f4d61ff5d3c285e2eea444347c65 Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 5 Jul 2011 01:06:48 +0000 +Subject: [PATCH 04/37] bnx2x: Reset PHY due to fan failure for 578xx +Patch-mainline: v3.1-rc1 +Git-commit: 985848f80ffc61a29d9a72fec46ddce3c9643636 +References: fate#311461. bnc#698050 + +Add hardware PHY reset action for BCM578xx when fan failure occur. +The new bnx2x_warpcore_hw_reset warps bnx2x_warpcore_power_module to fit the .hw_reset function template of the phy structure. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_link.c | 80 ++++++++++++++++++++++++++++++++------- + 1 files changed, 65 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index 270a2f7..a04fa13 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -7904,6 +7904,9 @@ static void bnx2x_warpcore_power_module(struct link_params *params, + dev_info.port_hw_config[params->port].e3_sfp_ctrl)) & + PORT_HW_CFG_E3_PWR_DIS_MASK) >> + PORT_HW_CFG_E3_PWR_DIS_SHIFT; ++ ++ if (pin_cfg == PIN_CFG_NA) ++ return; + DP(NETIF_MSG_LINK, "Setting SFP+ module power to %d using pin cfg %d\n", + power, pin_cfg); + /* +@@ -7913,6 +7916,12 @@ static void bnx2x_warpcore_power_module(struct link_params *params, + bnx2x_set_cfg_pin(bp, pin_cfg, power ^ 1); + } + ++static void bnx2x_warpcore_hw_reset(struct bnx2x_phy *phy, ++ struct link_params *params) ++{ ++ bnx2x_warpcore_power_module(params, phy, 0); ++} ++ + static void bnx2x_power_sfp_module(struct link_params *params, + struct bnx2x_phy *phy, + u8 power) +@@ -9294,9 +9303,9 @@ static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy, + } + + +-static int bnx2x_84833_common_init_phy(struct bnx2x *bp, +- u32 shmem_base_path[], +- u32 chip_id) ++static u8 bnx2x_84833_get_reset_gpios(struct bnx2x *bp, ++ u32 shmem_base_path[], ++ u32 chip_id) + { + u32 reset_pin[2]; + u32 idx; +@@ -9329,6 +9338,41 @@ static int bnx2x_84833_common_init_phy(struct bnx2x *bp, + reset_gpios = (u8)(reset_pin[0] | reset_pin[1]); + } + ++ return reset_gpios; ++} ++ ++static int bnx2x_84833_hw_reset_phy(struct bnx2x_phy *phy, ++ struct link_params *params) ++{ ++ struct bnx2x *bp = params->bp; ++ u8 reset_gpios; ++ u32 other_shmem_base_addr = REG_RD(bp, params->shmem2_base + ++ offsetof(struct shmem2_region, ++ other_shmem_base_addr)); ++ ++ u32 shmem_base_path[2]; ++ shmem_base_path[0] = params->shmem_base; ++ shmem_base_path[1] = other_shmem_base_addr; ++ ++ reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, ++ params->chip_id); ++ ++ bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW); ++ udelay(10); ++ DP(NETIF_MSG_LINK, "84833 hw reset on pin values 0x%x\n", ++ reset_gpios); ++ ++ return 0; ++} ++ ++static int bnx2x_84833_common_init_phy(struct bnx2x *bp, ++ u32 shmem_base_path[], ++ u32 chip_id) ++{ ++ u8 reset_gpios; ++ ++ reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, chip_id); ++ + bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW); + udelay(10); + bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH); +@@ -9362,17 +9406,11 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, + MISC_REGISTERS_GPIO_OUTPUT_HIGH, + port); + } else { ++ /* MDIO reset */ + bnx2x_cl45_write(bp, phy, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_CTRL, 0x8000); +- } +- +- bnx2x_wait_reset_complete(bp, phy, params); +- /* Wait for GPHY to come out of reset */ +- msleep(50); +- +- /* Bring PHY out of super isolate mode */ +- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) { ++ /* Bring PHY out of super isolate mode */ + bnx2x_cl45_read(bp, phy, + MDIO_CTL_DEVAD, + MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val); +@@ -9380,9 +9418,13 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, + bnx2x_cl45_write(bp, phy, + MDIO_CTL_DEVAD, + MDIO_84833_TOP_CFG_XGPHY_STRAP1, val); +- bnx2x_wait_reset_complete(bp, phy, params); + } + ++ bnx2x_wait_reset_complete(bp, phy, params); ++ ++ /* Wait for GPHY to come out of reset */ ++ msleep(50); ++ + if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) + bnx2x_84833_pair_swap_cfg(phy, params, vars); + +@@ -10448,7 +10490,7 @@ static struct bnx2x_phy phy_warpcore = { + .link_reset = (link_reset_t)bnx2x_warpcore_link_reset, + .config_loopback = (config_loopback_t)bnx2x_set_warpcore_loopback, + .format_fw_ver = (format_fw_ver_t)NULL, +- .hw_reset = (hw_reset_t)NULL, ++ .hw_reset = (hw_reset_t)bnx2x_warpcore_hw_reset, + .set_link_led = (set_link_led_t)NULL, + .phy_specific_func = (phy_specific_func_t)NULL + }; +@@ -10736,7 +10778,7 @@ static struct bnx2x_phy phy_84833 = { + .link_reset = (link_reset_t)bnx2x_848x3_link_reset, + .config_loopback = (config_loopback_t)NULL, + .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver, +- .hw_reset = (hw_reset_t)NULL, ++ .hw_reset = (hw_reset_t)bnx2x_84833_hw_reset_phy, + .set_link_led = (set_link_led_t)bnx2x_848xx_set_link_led, + .phy_specific_func = (phy_specific_func_t)NULL + }; +@@ -12122,7 +12164,15 @@ u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, + void bnx2x_hw_reset_phy(struct link_params *params) + { + u8 phy_index; +- for (phy_index = EXT_PHY1; phy_index < MAX_PHYS; ++ struct bnx2x *bp = params->bp; ++ bnx2x_update_mng(params, 0); ++ bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4, ++ (NIG_MASK_XGXS0_LINK_STATUS | ++ NIG_MASK_XGXS0_LINK10G | ++ NIG_MASK_SERDES0_LINK_STATUS | ++ NIG_MASK_MI_INT)); ++ ++ for (phy_index = INT_PHY; phy_index < MAX_PHYS; + phy_index++) { + if (params->phy[phy_index].hw_reset) { + params->phy[phy_index].hw_reset( +-- +1.7.2.2 + diff --git a/patches.drivers/0005-bnx2x-Fix-false-link-indication-at-link-partner-when.patch b/patches.drivers/0005-bnx2x-Fix-false-link-indication-at-link-partner-when.patch new file mode 100644 index 0000000..ffcf7af --- a/dev/null +++ b/patches.drivers/0005-bnx2x-Fix-false-link-indication-at-link-partner-when.patch @@ -0,0 +1,143 @@ +From a2f6c55f2b051e39b9fce7c268c371744587611a Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 5 Jul 2011 01:06:53 +0000 +Subject: [PATCH 05/37] bnx2x: Fix false link indication at link partner when DAC is used +Patch-mainline: v3.1-rc1 +Git-commit: 85242eea68f5039458afad0e4030828496bb4034 +References: fate#311461. bnc#698050 + +When driver is unloaded, disable PMD in addition to TX laser, provided that the management firmware will be able to enable it back. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_hsi.h | 1 + + drivers/net/bnx2x/bnx2x_link.c | 35 +++++++++++++++++++++++++++++++++++ + drivers/net/bnx2x/bnx2x_link.h | 1 + + drivers/net/bnx2x/bnx2x_main.c | 4 ++++ + drivers/net/bnx2x/bnx2x_reg.h | 1 + + 5 files changed, 42 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h +index e6f816d..52c190f 100644 +--- a/drivers/net/bnx2x/bnx2x_hsi.h ++++ b/drivers/net/bnx2x/bnx2x_hsi.h +@@ -1236,6 +1236,7 @@ struct drv_func_mb { + #define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL 0x00050006 + #define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL 0xa1000000 + #define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL 0x00050234 ++ #define REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED 0x00070014 + + #define DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG 0xb0000000 + #define DRV_MSG_CODE_DCBX_PMF_DRV_OK 0xb2000000 +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index a04fa13..144cfae 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -7195,6 +7195,30 @@ static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy, + /******************************************************************/ + /* SFP+ module Section */ + /******************************************************************/ ++static void bnx2x_set_disable_pmd_transmit(struct link_params *params, ++ struct bnx2x_phy *phy, ++ u8 pmd_dis) ++{ ++ struct bnx2x *bp = params->bp; ++ /* ++ * Disable transmitter only for bootcodes which can enable it afterwards ++ * (for D3 link) ++ */ ++ if (pmd_dis) { ++ if (params->feature_config_flags & ++ FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED) ++ DP(NETIF_MSG_LINK, "Disabling PMD transmitter\n"); ++ else { ++ DP(NETIF_MSG_LINK, "NOT disabling PMD transmitter\n"); ++ return; ++ } ++ } else ++ DP(NETIF_MSG_LINK, "Enabling PMD transmitter\n"); ++ bnx2x_cl45_write(bp, phy, ++ MDIO_PMA_DEVAD, ++ MDIO_PMA_REG_TX_DISABLE, pmd_dis); ++} ++ + static u8 bnx2x_get_gpio_port(struct link_params *params) + { + u8 gpio_port; +@@ -8598,6 +8622,9 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy, + MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs); + + ++ /* Enable/Disable PHY transmitter output */ ++ bnx2x_set_disable_pmd_transmit(params, phy, 0); ++ + /* Make MOD_ABS give interrupt on change */ + bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL, + &val); +@@ -8972,6 +8999,10 @@ static void bnx2x_8727_link_reset(struct bnx2x_phy *phy, + struct link_params *params) + { + struct bnx2x *bp = params->bp; ++ ++ /* Enable/Disable PHY transmitter output */ ++ bnx2x_set_disable_pmd_transmit(params, phy, 1); ++ + /* Disable Transmitter */ + bnx2x_sfp_set_transmitter(params, phy, 0); + /* Clear LASI */ +@@ -11895,6 +11926,10 @@ static int bnx2x_8727_common_init_phy(struct bnx2x *bp, + if (bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port], + port_of_path)) + return -EINVAL; ++ /* Disable PHY transmitter output */ ++ bnx2x_cl45_write(bp, phy_blk[port], ++ MDIO_PMA_DEVAD, ++ MDIO_PMA_REG_TX_DISABLE, 1); + + } + return 0; +diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h +index 6f299c2..ba4d1f7 100644 +--- a/drivers/net/bnx2x/bnx2x_link.h ++++ b/drivers/net/bnx2x/bnx2x_link.h +@@ -250,6 +250,7 @@ struct link_params { + #define FEATURE_CONFIG_PFC_ENABLED (1<<1) + #define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY (1<<2) + #define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY (1<<3) ++#define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED (1<<10) + /* Will be populated during common init */ + struct bnx2x_phy phy[MAX_PHYS]; + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index b268b29..3af9a75 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -8426,6 +8426,10 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) + (val >= REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL) ? + FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY : 0; + ++ bp->link_params.feature_config_flags |= ++ (val >= REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED) ? ++ FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED : 0; ++ + pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc); + bp->flags |= (pmc & PCI_PM_CAP_PME_D3cold) ? 0 : NO_WOL_FLAG; + +diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h +index df783c5..6fed5f8 100644 +--- a/drivers/net/bnx2x/bnx2x_reg.h ++++ b/drivers/net/bnx2x/bnx2x_reg.h +@@ -6632,6 +6632,7 @@ Theotherbitsarereservedandshouldbezero*/ + #define MDIO_PMA_REG_CTRL 0x0 + #define MDIO_PMA_REG_STATUS 0x1 + #define MDIO_PMA_REG_10G_CTRL2 0x7 ++#define MDIO_PMA_REG_TX_DISABLE 0x0009 + #define MDIO_PMA_REG_RX_SD 0xa + /*bcm*/ + #define MDIO_PMA_REG_BCM_CTRL 0x0096 +-- +1.7.2.2 + diff --git a/patches.drivers/0006-bnx2x-Fix-BCM84833-initialization.patch b/patches.drivers/0006-bnx2x-Fix-BCM84833-initialization.patch new file mode 100644 index 0000000..1d1a68c --- a/dev/null +++ b/patches.drivers/0006-bnx2x-Fix-BCM84833-initialization.patch @@ -0,0 +1,136 @@ +From 35148f9ac1daf5f5b3a8517e50e7abe92a78a6ed Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 5 Jul 2011 01:06:59 +0000 +Subject: [PATCH 06/37] bnx2x: Fix BCM84833 initialization +Patch-mainline: v3.1-rc1 +Git-commit: 0520e63acb387a265c2a6abbf51c44c67149cf37 +References: fate#311461. bnc#698050 + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_hsi.h | 8 ++++++- + drivers/net/bnx2x/bnx2x_link.c | 45 +++++++++++++++++++++++++++++---------- + 2 files changed, 40 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h +index 52c190f..0692d75 100644 +--- a/drivers/net/bnx2x/bnx2x_hsi.h ++++ b/drivers/net/bnx2x/bnx2x_hsi.h +@@ -538,7 +538,13 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ + u32 fcoe_wwn_node_name_upper; + u32 fcoe_wwn_node_name_lower; + +- u32 Reserved1[50]; /* 0x1C0 */ ++ u32 Reserved1[49]; /* 0x1C0 */ ++ ++ /* Enable RJ45 magjack pair swapping on 10GBase-T PHY (0=default), ++ 84833 only */ ++ u32 xgbt_phy_cfg; /* 0x284 */ ++ #define PORT_HW_CFG_RJ45_PAIR_SWAP_MASK 0x000000FF ++ #define PORT_HW_CFG_RJ45_PAIR_SWAP_SHIFT 0 + + u32 default_cfg; /* 0x288 */ + #define PORT_HW_CFG_GPIO0_CONFIG_MASK 0x00000003 +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index 144cfae..d6684b3 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -9182,11 +9182,14 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, + MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL, + an_1000_val); + +- /* set 10 speed advertisement */ ++ /* set 100 speed advertisement */ + if (((phy->req_line_speed == SPEED_AUTO_NEG) && + (phy->speed_cap_mask & +- (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL | +- PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) { ++ (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL | ++ PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) && ++ (phy->supported & ++ (SUPPORTED_100baseT_Half | ++ SUPPORTED_100baseT_Full)))) { + an_10_100_val |= (1<<7); + /* Enable autoneg and restart autoneg for legacy speeds */ + autoneg_val |= (1<<9 | 1<<12); +@@ -9197,9 +9200,12 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, + } + /* set 10 speed advertisement */ + if (((phy->req_line_speed == SPEED_AUTO_NEG) && +- (phy->speed_cap_mask & +- (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL | +- PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) { ++ (phy->speed_cap_mask & ++ (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL | ++ PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) && ++ (phy->supported & ++ (SUPPORTED_10baseT_Half | ++ SUPPORTED_10baseT_Full)))) { + an_10_100_val |= (1<<5); + autoneg_val |= (1<<9 | 1<<12); + if (phy->req_duplex == DUPLEX_FULL) +@@ -9208,7 +9214,10 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, + } + + /* Only 10/100 are allowed to work in FORCE mode */ +- if (phy->req_line_speed == SPEED_100) { ++ if ((phy->req_line_speed == SPEED_100) && ++ (phy->supported & ++ (SUPPORTED_100baseT_Half | ++ SUPPORTED_100baseT_Full))) { + autoneg_val |= (1<<13); + /* Enabled AUTO-MDIX when autoneg is disabled */ + bnx2x_cl45_write(bp, phy, +@@ -9216,7 +9225,10 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, + (1<<15 | 1<<9 | 7<<0)); + DP(NETIF_MSG_LINK, "Setting 100M force\n"); + } +- if (phy->req_line_speed == SPEED_10) { ++ if ((phy->req_line_speed == SPEED_10) && ++ (phy->supported & ++ (SUPPORTED_10baseT_Half | ++ SUPPORTED_10baseT_Full))) { + /* Enabled AUTO-MDIX when autoneg is disabled */ + bnx2x_cl45_write(bp, phy, + MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL, +@@ -9284,11 +9296,22 @@ static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy, + struct link_vars *vars) + { + u32 idx; ++ u32 pair_swap; + u16 val; +- u16 data = 0x01b1; ++ u16 data; + struct bnx2x *bp = params->bp; + /* Do pair swap */ + ++ /* Check for configuration. */ ++ pair_swap = REG_RD(bp, params->shmem_base + ++ offsetof(struct shmem_region, ++ dev_info.port_hw_config[params->port].xgbt_phy_cfg)) & ++ PORT_HW_CFG_RJ45_PAIR_SWAP_MASK; ++ ++ if (pair_swap == 0) ++ return 0; ++ ++ data = (u16)pair_swap; + + /* Write CMD_OPEN_OVERRIDE to STATUS reg */ + bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, +@@ -10787,9 +10810,7 @@ static struct bnx2x_phy phy_84833 = { + .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, + .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, + .mdio_ctrl = 0, +- .supported = (SUPPORTED_10baseT_Half | +- SUPPORTED_10baseT_Full | +- SUPPORTED_100baseT_Half | ++ .supported = (SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_10000baseT_Full | +-- +1.7.2.2 + diff --git a/patches.drivers/0007-bnx2x-Add-autogrEEEn-support.patch b/patches.drivers/0007-bnx2x-Add-autogrEEEn-support.patch new file mode 100644 index 0000000..7ad5c76 --- a/dev/null +++ b/patches.drivers/0007-bnx2x-Add-autogrEEEn-support.patch @@ -0,0 +1,227 @@ +From 8f7b87a5ddbc8ed594c603d101f5a95e4979a4eb Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 5 Jul 2011 01:07:05 +0000 +Subject: [PATCH 07/37] bnx2x: Add autogrEEEn support +Patch-mainline: v3.1-rc1 +Git-commit: a89a1d4a738668ccb2270ac218cddd30f0bef2a0 +References: fate#311461. bnc#698050 + +Add autogrEEEn support on BCM84833 and 54618se, which allows to reduce power consumption. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_link.c | 115 +++++++++++++++++++++++++++++++++++---- + drivers/net/bnx2x/bnx2x_link.h | 1 + + drivers/net/bnx2x/bnx2x_reg.h | 7 +++ + 3 files changed, 111 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index d6684b3..03a2085 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -9437,6 +9437,7 @@ static int bnx2x_84833_common_init_phy(struct bnx2x *bp, + return 0; + } + ++#define PHY84833_CONSTANT_LATENCY 1193 + static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, + struct link_params *params, + struct link_vars *vars) +@@ -9445,7 +9446,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, + u8 port, initialize = 1; + u16 val; + u16 temp; +- u32 actual_phy_selection, cms_enable; ++ u32 actual_phy_selection, cms_enable, idx; + int rc = 0; + + msleep(1); +@@ -9537,24 +9538,86 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, + DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n", + params->multi_phy_config, val); + ++ /* AutogrEEEn */ ++ if (params->feature_config_flags & ++ FEATURE_CONFIG_AUTOGREEEN_ENABLED) { ++ /* Ensure that f/w is ready */ ++ for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) { ++ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, ++ MDIO_84833_TOP_CFG_SCRATCH_REG2, &val); ++ if (val == PHY84833_CMD_OPEN_FOR_CMDS) ++ break; ++ usleep_range(1000, 1000); ++ } ++ if (idx >= PHY84833_HDSHK_WAIT) { ++ DP(NETIF_MSG_LINK, "AutogrEEEn: FW not ready.\n"); ++ return -EINVAL; ++ } ++ ++ /* Select EEE mode */ ++ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, ++ MDIO_84833_TOP_CFG_SCRATCH_REG3, ++ 0x2); ++ ++ /* Set Idle and Latency */ ++ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, ++ MDIO_84833_TOP_CFG_SCRATCH_REG4, ++ PHY84833_CONSTANT_LATENCY + 1); ++ ++ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, ++ MDIO_84833_TOP_CFG_DATA3_REG, ++ PHY84833_CONSTANT_LATENCY + 1); ++ ++ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, ++ MDIO_84833_TOP_CFG_DATA4_REG, ++ PHY84833_CONSTANT_LATENCY); ++ ++ /* Send EEE instruction to command register */ ++ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, ++ MDIO_84833_TOP_CFG_SCRATCH_REG0, ++ PHY84833_DIAG_CMD_SET_EEE_MODE); ++ ++ /* Ensure that the command has completed */ ++ for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) { ++ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, ++ MDIO_84833_TOP_CFG_SCRATCH_REG2, &val); ++ if ((val == PHY84833_CMD_COMPLETE_PASS) || ++ (val == PHY84833_CMD_COMPLETE_ERROR)) ++ break; ++ usleep_range(1000, 1000); ++ } ++ if ((idx >= PHY84833_HDSHK_WAIT) || ++ (val == PHY84833_CMD_COMPLETE_ERROR)) { ++ DP(NETIF_MSG_LINK, "AutogrEEEn: command failed.\n"); ++ return -EINVAL; ++ } ++ ++ /* Reset command handler */ ++ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, ++ MDIO_84833_TOP_CFG_SCRATCH_REG2, ++ PHY84833_CMD_CLEAR_COMPLETE); ++ } ++ + if (initialize) + rc = bnx2x_848xx_cmn_config_init(phy, params, vars); + else + bnx2x_save_848xx_spirom_version(phy, params); +- cms_enable = REG_RD(bp, params->shmem_base + ++ /* 84833 PHY has a better feature and doesn't need to support this. */ ++ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) { ++ cms_enable = REG_RD(bp, params->shmem_base + + offsetof(struct shmem_region, + dev_info.port_hw_config[params->port].default_cfg)) & + PORT_HW_CFG_ENABLE_CMS_MASK; + +- bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, +- MDIO_CTL_REG_84823_USER_CTRL_REG, &val); +- if (cms_enable) +- val |= MDIO_CTL_REG_84823_USER_CTRL_CMS; +- else +- val &= ~MDIO_CTL_REG_84823_USER_CTRL_CMS; +- bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, +- MDIO_CTL_REG_84823_USER_CTRL_REG, val); +- ++ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, ++ MDIO_CTL_REG_84823_USER_CTRL_REG, &val); ++ if (cms_enable) ++ val |= MDIO_CTL_REG_84823_USER_CTRL_CMS; ++ else ++ val &= ~MDIO_CTL_REG_84823_USER_CTRL_CMS; ++ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD, ++ MDIO_CTL_REG_84823_USER_CTRL_REG, val); ++ } + + return rc; + } +@@ -10068,6 +10131,30 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy, + DP(NETIF_MSG_LINK, "Setting 10M force\n"); + } + ++ /* Check if we should turn on Auto-GrEEEn */ ++ bnx2x_cl22_read(bp, phy, MDIO_REG_GPHY_PHYID_LSB, &temp); ++ if (temp == MDIO_REG_GPHY_ID_54618SE) { ++ if (params->feature_config_flags & ++ FEATURE_CONFIG_AUTOGREEEN_ENABLED) { ++ temp = 6; ++ DP(NETIF_MSG_LINK, "Enabling Auto-GrEEEn\n"); ++ } else { ++ temp = 0; ++ DP(NETIF_MSG_LINK, "Disabling Auto-GrEEEn\n"); ++ } ++ bnx2x_cl22_write(bp, phy, ++ MDIO_REG_GPHY_CL45_ADDR_REG, MDIO_AN_DEVAD); ++ bnx2x_cl22_write(bp, phy, ++ MDIO_REG_GPHY_CL45_DATA_REG, ++ MDIO_REG_GPHY_EEE_ADV); ++ bnx2x_cl22_write(bp, phy, ++ MDIO_REG_GPHY_CL45_ADDR_REG, ++ (0x1 << 14) | MDIO_AN_DEVAD); ++ bnx2x_cl22_write(bp, phy, ++ MDIO_REG_GPHY_CL45_DATA_REG, ++ temp); ++ } ++ + bnx2x_cl22_write(bp, phy, + 0x04, + an_10_100_val | fc_val); +@@ -11597,12 +11684,16 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars, + bnx2x_set_led(params, vars, LED_MODE_OFF, 0); + + if (reset_ext_phy) { ++ bnx2x_set_mdio_clk(bp, params->chip_id, port); + for (phy_index = EXT_PHY1; phy_index < params->num_phys; + phy_index++) { +- if (params->phy[phy_index].link_reset) ++ if (params->phy[phy_index].link_reset) { ++ bnx2x_set_aer_mmd(params, ++ ¶ms->phy[phy_index]); + params->phy[phy_index].link_reset( + ¶ms->phy[phy_index], + params); ++ } + if (params->phy[phy_index].flags & + FLAGS_REARM_LATCH_SIGNAL) + clear_latch_ind = 1; +diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h +index ba4d1f7..6a7708d 100644 +--- a/drivers/net/bnx2x/bnx2x_link.h ++++ b/drivers/net/bnx2x/bnx2x_link.h +@@ -250,6 +250,7 @@ struct link_params { + #define FEATURE_CONFIG_PFC_ENABLED (1<<1) + #define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY (1<<2) + #define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY (1<<3) ++#define FEATURE_CONFIG_AUTOGREEEN_ENABLED (1<<9) + #define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED (1<<10) + /* Will be populated during common init */ + struct bnx2x_phy phy[MAX_PHYS]; +diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h +index 6fed5f8..02461fe 100644 +--- a/drivers/net/bnx2x/bnx2x_reg.h ++++ b/drivers/net/bnx2x/bnx2x_reg.h +@@ -6806,6 +6806,8 @@ Theotherbitsarereservedandshouldbezero*/ + #define MDIO_84833_TOP_CFG_SCRATCH_REG2 0x4007 + #define MDIO_84833_TOP_CFG_SCRATCH_REG3 0x4008 + #define MDIO_84833_TOP_CFG_SCRATCH_REG4 0x4009 ++#define MDIO_84833_TOP_CFG_DATA3_REG 0x4011 ++#define MDIO_84833_TOP_CFG_DATA4_REG 0x4012 + + /* Mailbox command set used by 84833. */ + #define PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE 0x2 +@@ -6820,6 +6822,11 @@ Theotherbitsarereservedandshouldbezero*/ + #define PHY84833_CMD_CLEAR_COMPLETE 0x0080 + #define PHY84833_CMD_OPEN_OVERRIDE 0xa5a5 + ++ ++/* 84833 F/W Feature Commands */ ++#define PHY84833_DIAG_CMD_GET_EEE_MODE 0x27 ++#define PHY84833_DIAG_CMD_SET_EEE_MODE 0x28 ++ + /* Warpcore clause 45 addressing */ + #define MDIO_WC_DEVAD 0x3 + #define MDIO_WC_REG_IEEE0BLK_MIICNTL 0x0 +-- +1.7.2.2 + diff --git a/patches.drivers/0008-bnx2x-Fix-warning-message-during-57712-8727-initiali.patch b/patches.drivers/0008-bnx2x-Fix-warning-message-during-57712-8727-initiali.patch new file mode 100644 index 0000000..85737a0 --- a/dev/null +++ b/patches.drivers/0008-bnx2x-Fix-warning-message-during-57712-8727-initiali.patch @@ -0,0 +1,44 @@ +From 6cd4eb399543bc2a14f7ef9fc28d9be3f8f52bfc Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 5 Jul 2011 01:07:16 +0000 +Subject: [PATCH 08/37] bnx2x: Fix warning message during 57712/8727 initialization +Patch-mainline: v3.1-rc1 +Git-commit: 7d09926d1decb658d4e24f70216b6b0b74168026 +References: fate#311461. bnc#698050 + +Clear warning message "MDC/MDIO access timeout" during first driver load by setting MDIO clock. +This warning has no significant meaning, since it occurs prior to the first PHY initialization. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_link.c | 6 +----- + 1 files changed, 1 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index 03a2085..bcd8f00 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -11684,16 +11684,12 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars, + bnx2x_set_led(params, vars, LED_MODE_OFF, 0); + + if (reset_ext_phy) { +- bnx2x_set_mdio_clk(bp, params->chip_id, port); + for (phy_index = EXT_PHY1; phy_index < params->num_phys; + phy_index++) { +- if (params->phy[phy_index].link_reset) { +- bnx2x_set_aer_mmd(params, +- ¶ms->phy[phy_index]); ++ if (params->phy[phy_index].link_reset) + params->phy[phy_index].link_reset( + ¶ms->phy[phy_index], + params); +- } + if (params->phy[phy_index].flags & + FLAGS_REARM_LATCH_SIGNAL) + clear_latch_ind = 1; +-- +1.7.2.2 + diff --git a/patches.drivers/0009-bnx2x-remove-unnecessary-read-of-PCI_CAP_ID_EXP.patch b/patches.drivers/0009-bnx2x-remove-unnecessary-read-of-PCI_CAP_ID_EXP.patch new file mode 100644 index 0000000..d51d932 --- a/dev/null +++ b/patches.drivers/0009-bnx2x-remove-unnecessary-read-of-PCI_CAP_ID_EXP.patch @@ -0,0 +1,72 @@ +From edf6376d0fea632cade2f98ff4901aa8254bfa93 Mon Sep 17 00:00:00 2001 +From: Jon Mason <jdmason@kudzu.us> +Date: Mon, 27 Jun 2011 07:45:12 +0000 +Subject: [PATCH 09/37] bnx2x: remove unnecessary read of PCI_CAP_ID_EXP +Patch-mainline: v3.1-rc1 +Git-commit: 77c98e6a7a3ab76340b315d31fe1edded17cba15 +References: fate#311461. bnc#698050 + +The PCIE capability offset is saved during PCI bus walking. It will +remove an unnecessary search in the PCI configuration space if this +value is referenced instead of reacquiring it. Also, pci_is_pcie is a +better way of determining if the device is PCIE or not (as it uses the +same saved PCIE capability offset). + +Signed-off-by: Jon Mason <jdmason@kudzu.us> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x.h | 1 - + drivers/net/bnx2x/bnx2x_main.c | 10 ++++------ + 2 files changed, 4 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h +index 362fd09..0c67d50 100644 +--- a/drivers/net/bnx2x/bnx2x.h ++++ b/drivers/net/bnx2x/bnx2x.h +@@ -1161,7 +1161,6 @@ struct bnx2x { + #define NO_FCOE(bp) ((bp)->flags & NO_FCOE_FLAG) + + int pm_cap; +- int pcie_cap; + int mrrs; + + struct delayed_work sp_task; +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index 3af9a75..47825bc 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -1222,7 +1222,7 @@ static inline u8 bnx2x_is_pcie_pending(struct pci_dev *dev) + int pos; + u16 status; + +- pos = pci_find_capability(dev, PCI_CAP_ID_EXP); ++ pos = pci_pcie_cap(dev); + if (!pos) + return false; + +@@ -5555,7 +5555,7 @@ static void bnx2x_init_pxp(struct bnx2x *bp) + int r_order, w_order; + + pci_read_config_word(bp->pdev, +- bp->pcie_cap + PCI_EXP_DEVCTL, &devctl); ++ bp->pdev->pcie_cap + PCI_EXP_DEVCTL, &devctl); + DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl); + w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); + if (bp->mrrs == -1) +@@ -9834,10 +9834,8 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, + goto err_out_release; + } + +- bp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); +- if (bp->pcie_cap == 0) { +- dev_err(&bp->pdev->dev, +- "Cannot find PCI Express capability, aborting\n"); ++ if (!pci_is_pcie(pdev)) { ++ dev_err(&bp->pdev->dev, "Not PCI Express, aborting\n"); + rc = -EIO; + goto err_out_release; + } +-- +1.7.2.2 + diff --git a/patches.drivers/0010-net-bnx2x-fix-DMA-sync-direction.patch b/patches.drivers/0010-net-bnx2x-fix-DMA-sync-direction.patch new file mode 100644 index 0000000..f4123b5 --- a/dev/null +++ b/patches.drivers/0010-net-bnx2x-fix-DMA-sync-direction.patch @@ -0,0 +1,48 @@ +From c2a72fd35ecdae15e389eec857add10ab4b9fe04 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= <mirq-linux@rere.qmqm.pl> +Date: Sun, 10 Jul 2011 14:52:46 +0000 +Subject: [PATCH 10/37] net: bnx2x: fix DMA sync direction +Patch-mainline: v3.1-rc1 +Git-commit: 9924cafc403ca74614c0a8b1ad198406ae02c68b +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +References: fate#311461. bnc#698050 + +Signed-off-by: MichaÅ‚ MirosÅ‚aw <mirq-linux@rere.qmqm.pl> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_cmn.c | 2 +- + drivers/net/bnx2x/bnx2x_ethtool.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c +index 449b599..9e32b77 100644 +--- a/drivers/net/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/bnx2x/bnx2x_cmn.c +@@ -657,7 +657,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) + /* non TPA */ + len = le16_to_cpu(cqe_fp->pkt_len); + pad = cqe_fp->placement_offset; +- dma_sync_single_for_device(&bp->pdev->dev, ++ dma_sync_single_for_cpu(&bp->pdev->dev, + pci_unmap_addr(rx_buf, mapping), + pad + RX_COPY_THRESH, + DMA_FROM_DEVICE); +diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c +index 9406003..114da42 100644 +--- a/drivers/net/bnx2x/bnx2x_ethtool.c ++++ b/drivers/net/bnx2x/bnx2x_ethtool.c +@@ -1910,7 +1910,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) + goto test_loopback_rx_exit; + + rx_buf = &fp_rx->rx_buf_ring[RX_BD(fp_rx->rx_bd_cons)]; +- dma_sync_single_for_device(&bp->pdev->dev, ++ dma_sync_single_for_cpu(&bp->pdev->dev, + pci_unmap_addr(rx_buf, mapping), + fp_rx->rx_buf_size, DMA_FROM_DEVICE); + skb = rx_buf->skb; +-- +1.7.2.2 + diff --git a/patches.drivers/0011-bnx2x-Renaming-the-reset_task-to-sp_rtnl_task.patch b/patches.drivers/0011-bnx2x-Renaming-the-reset_task-to-sp_rtnl_task.patch new file mode 100644 index 0000000..12117e4 --- a/dev/null +++ b/patches.drivers/0011-bnx2x-Renaming-the-reset_task-to-sp_rtnl_task.patch @@ -0,0 +1,195 @@ +From 3cc844c86bd18e9cb237c534e16fbfe208d1f693 Mon Sep 17 00:00:00 2001 +From: Ariel Elior <ariele@broadcom.com> +Date: Thu, 14 Jul 2011 08:31:19 +0000 +Subject: [PATCH 11/37] bnx2x: Renaming the "reset_task" to "sp_rtnl_task" +Patch-mainline: v3.1-rc1 +Git-commit: 7be08a7222c345798b0697a89ea3dd2c7c83f47c +References: fate#311461. bnc#698050 + +Renaming the "reset_task" to a more general purpose name, + "sp_rtnl_task", as it is already used for another purpose + other than reset which is parity recovery, and since I + plan to add a third operation for this task, updating the + priority to traffic class and traffic class to transmission + queues mappings after dcbx negotiation takes place. + Signed-off-by: Ariel Elior <ariele@broadcom.com> + Signed-off-by: Eilon Greenstein <eilong@broadcom.com> + +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x.h | 11 ++++++++- + drivers/net/bnx2x/bnx2x_cmn.c | 7 +++++- + drivers/net/bnx2x/bnx2x_main.c | 48 ++++++++++++++++++++++++--------------- + 3 files changed, 45 insertions(+), 21 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h +index 0c67d50..2584be7 100644 +--- a/drivers/net/bnx2x/bnx2x.h ++++ b/drivers/net/bnx2x/bnx2x.h +@@ -1044,6 +1044,12 @@ struct bnx2x_fw_stats_data { + struct per_queue_stats queue_stats[1]; + }; + ++/* Public slow path states */ ++enum { ++ BNX2X_SP_RTNL_TX_TIMEOUT, ++}; ++ ++ + struct bnx2x { + /* Fields used in the tx and intr/napi performance paths + * are grouped together in the beginning of the structure +@@ -1164,7 +1170,7 @@ struct bnx2x { + int mrrs; + + struct delayed_work sp_task; +- struct delayed_work reset_task; ++ struct delayed_work sp_rtnl_task; + + struct delayed_work period_task; + struct timer_list timer; +@@ -1394,6 +1400,9 @@ struct bnx2x { + + unsigned long sp_state; + ++ /* operation indication for the sp_rtnl task */ ++ unsigned long sp_rtnl_state; ++ + /* DCBX Negotation results */ + struct dcbx_features dcbx_local_feat; + u32 dcbx_error; +diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c +index 9e32b77..6f1c196 100644 +--- a/drivers/net/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/bnx2x/bnx2x_cmn.c +@@ -3209,8 +3209,13 @@ void bnx2x_tx_timeout(struct net_device *dev) + if (!bp->panic) + bnx2x_panic(); + #endif ++ ++ smp_mb__before_clear_bit(); ++ set_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state); ++ smp_mb__after_clear_bit(); ++ + /* This allows the netif to be shutdown gracefully before resetting */ +- schedule_delayed_work(&bp->reset_task, 0); ++ schedule_delayed_work(&bp->sp_rtnl_task, 0); + } + + int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state) +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index 47825bc..1fb0195 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -4076,7 +4076,7 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted) + if (bnx2x_chk_parity_attn(bp, &global, true)) { + #ifndef BNX2X_STOP_ON_ERROR + bp->recovery_state = BNX2X_RECOVERY_INIT; +- schedule_delayed_work(&bp->reset_task, 0); ++ schedule_delayed_work(&bp->sp_rtnl_task, 0); + /* Disable HW interrupts */ + bnx2x_int_disable(bp); + /* In case of parity errors don't handle attentions so that +@@ -8040,7 +8040,7 @@ static void bnx2x_parity_recover(struct bnx2x *bp) + /* Wait until all other functions get + * down. + */ +- schedule_delayed_work(&bp->reset_task, ++ schedule_delayed_work(&bp->sp_rtnl_task, + HZ/10); + return; + } else { +@@ -8077,7 +8077,7 @@ static void bnx2x_parity_recover(struct bnx2x *bp) + break; + } + +- schedule_delayed_work(&bp->reset_task, ++ schedule_delayed_work(&bp->sp_rtnl_task, + HZ/10); + return; + +@@ -8088,7 +8088,8 @@ static void bnx2x_parity_recover(struct bnx2x *bp) + */ + if (bnx2x_reset_is_global(bp)) { + schedule_delayed_work( +- &bp->reset_task, HZ/10); ++ &bp->sp_rtnl_task, ++ HZ/10); + return; + } + +@@ -8112,30 +8113,39 @@ static void bnx2x_parity_recover(struct bnx2x *bp) + /* bnx2x_nic_unload() flushes the bnx2x_wq, thus reset task is + * scheduled on a general queue in order to prevent a dead lock. + */ +-static void bnx2x_reset_task(struct work_struct *work) ++static void bnx2x_sp_rtnl_task(struct work_struct *work) + { +- struct bnx2x *bp = container_of(work, struct bnx2x, reset_task.work); +- +-#ifdef BNX2X_STOP_ON_ERROR +- BNX2X_ERR("reset task called but STOP_ON_ERROR defined" +- " so reset not done to allow debug dump,\n" +- KERN_ERR " you will need to reboot when done\n"); +- return; +-#endif ++ struct bnx2x *bp = container_of(work, struct bnx2x, sp_rtnl_task.work); + + rtnl_lock(); + + if (!netif_running(bp->dev)) +- goto reset_task_exit; ++ goto sp_rtnl_exit; ++ ++ /* if stop on error is defined no recovery flows should be executed */ ++#ifdef BNX2X_STOP_ON_ERROR ++ BNX2X_ERR("recovery flow called but STOP_ON_ERROR defined " ++ "so reset not done to allow debug dump,\n" ++ "you will need to reboot when done\n"); ++ goto sp_rtnl_exit; ++#endif + +- if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE)) ++ if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE)) { ++ /* ++ * Clear TX_TIMEOUT bit as we are going to reset the function ++ * anyway. ++ */ ++ smp_mb__before_clear_bit(); ++ clear_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state); ++ smp_mb__after_clear_bit(); + bnx2x_parity_recover(bp); +- else { ++ } else if (test_and_clear_bit(BNX2X_SP_RTNL_TX_TIMEOUT, ++ &bp->sp_rtnl_state)){ + bnx2x_nic_unload(bp, UNLOAD_NORMAL); + bnx2x_nic_load(bp, LOAD_NORMAL); + } + +-reset_task_exit: ++sp_rtnl_exit: + rtnl_unlock(); + } + +@@ -9357,7 +9367,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) + #endif + + INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task); +- INIT_DELAYED_WORK(&bp->reset_task, bnx2x_reset_task); ++ INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task); + INIT_DELAYED_WORK(&bp->period_task, bnx2x_period_task); + rc = bnx2x_get_hwinfo(bp); + if (rc) +@@ -10407,7 +10417,7 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) + bnx2x_set_power_state(bp, PCI_D3hot); + + /* Make sure RESET task is not scheduled before continuing */ +- cancel_delayed_work_sync(&bp->reset_task); ++ cancel_delayed_work_sync(&bp->sp_rtnl_task); + + if (bp->regview) + iounmap(bp->regview); +-- +1.7.2.2 + diff --git a/patches.drivers/0012-bnx2x-Multiple-concurrent-l2-traffic-classes.patch b/patches.drivers/0012-bnx2x-Multiple-concurrent-l2-traffic-classes.patch new file mode 100644 index 0000000..4f82a42 --- a/dev/null +++ b/patches.drivers/0012-bnx2x-Multiple-concurrent-l2-traffic-classes.patch @@ -0,0 +1,3429 @@ +From 1fbaa2196a12eccf10611d9aa4b9be09ee79e832 Mon Sep 17 00:00:00 2001 +From: Ariel Elior <ariele@broadcom.com> +Date: Thu, 14 Jul 2011 08:31:57 +0000 +Subject: [PATCH 12/37] bnx2x: Multiple concurrent l2 traffic classes +Patch-mainline: v3.1-rc1 +Git-commit: 6383c0b35b48bfbd0fc8c6fe126a6603c5a9a4b3 +References: fate#311461. bnc#698050 + +Overview: Support mapping of priorities to traffic classes and + traffic classes to transmission queues ranges in the net device. + The queue ranges are (count, offset) pairs relating to the txq + array. + This can be done via DCBX negotiation or by kernel. + As a result Enhanced Transmission Selection (ETS) and Priority Flow + Control (PFC) are supported between L2 network traffic classes. + + Mapping: + This patch uses the netdev_set_num_tc, netdev_set_prio_tc_map and + netdev_set_tc_queue functions to map priorities to traffic classes + and traffic classes to transmission queue ranges. + This mapping is performed by bnx2x_setup_tc function which is + connected to the ndo_setup_tc. + This function is always called at nic load where by default it + maps all priorities to tc 0, and it may also be called by the + kernel or by the bnx2x upon DCBX negotiation to modify the mapping. + + rtnl lock: + When the ndo_setup_tc is called at nic load or by kernel the rtnl + lock is already taken. However, when DCBX negotiation takes place + the lock is not taken. The work is therefore scheduled to be + handled by the sp_rtnl task. + + Fastpath: + The fastpath structure of the bnx2x which was previously used + to hold the information of one tx queue and one rx queue was + redesigned to represent multiple tx queues, one for each traffic + class. + The transmission queue supplied in the skb by the kernel can no + longer be interpreted as a straightforward index into the fastpath + structure array, but it must rather be decoded to the appropriate + fastpath index and the tc within that fastpath. + + Slowpath: + The bnx2x's queue object was redesigned to accommodate multiple + transmission queues. The queue object's state machine was enhanced + to allow opening multiple transmission-only connections on top of + the regular tx-rx connection. + + Firmware: + This feature relies on the tx-only queue feature introduced in the + bnx2x 7.0.23 firmware and the FW likewise must have the bnx2x multi + cos support. + + Signed-off-by: Ariel Elior <ariele@broadcom.com> + Signed-off-by: Eilon Greenstein <eilong@broadcom.com> + +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x.h | 179 +++++++++----- + drivers/net/bnx2x/bnx2x_cmn.c | 325 ++++++++++++++++-------- + drivers/net/bnx2x/bnx2x_cmn.h | 105 +++++--- + drivers/net/bnx2x/bnx2x_dcb.c | 25 ++ + drivers/net/bnx2x/bnx2x_ethtool.c | 27 +- + drivers/net/bnx2x/bnx2x_hsi.h | 2 +- + drivers/net/bnx2x/bnx2x_init.h | 19 +- + drivers/net/bnx2x/bnx2x_main.c | 503 ++++++++++++++++++++++++++----------- + drivers/net/bnx2x/bnx2x_sp.c | 476 +++++++++++++++++++++++++---------- + drivers/net/bnx2x/bnx2x_sp.h | 70 +++++- + drivers/net/bnx2x/bnx2x_stats.c | 40 ++- + 11 files changed, 1240 insertions(+), 531 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h +index 2584be7..bff9f7b 100644 +--- a/drivers/net/bnx2x/bnx2x.h ++++ b/drivers/net/bnx2x/bnx2x.h +@@ -118,6 +118,7 @@ do { \ + + + #ifdef BNX2X_STOP_ON_ERROR ++void bnx2x_int_disable(struct bnx2x *bp); + #define bnx2x_panic() do { \ + bp->panic = 1; \ + BNX2X_ERR("driver assert\n"); \ +@@ -238,21 +239,21 @@ do { \ + */ + /* iSCSI L2 */ + #define BNX2X_ISCSI_ETH_CL_ID_IDX 1 +-#define BNX2X_ISCSI_ETH_CID 17 ++#define BNX2X_ISCSI_ETH_CID 49 + + /* FCoE L2 */ + #define BNX2X_FCOE_ETH_CL_ID_IDX 2 +-#define BNX2X_FCOE_ETH_CID 18 ++#define BNX2X_FCOE_ETH_CID 50 + + /** Additional rings budgeting */ + #ifdef BCM_CNIC +-#define CNIC_CONTEXT_USE 1 +-#define FCOE_CONTEXT_USE 1 ++#define CNIC_PRESENT 1 ++#define FCOE_PRESENT 1 + #else +-#define CNIC_CONTEXT_USE 0 +-#define FCOE_CONTEXT_USE 0 ++#define CNIC_PRESENT 0 ++#define FCOE_PRESENT 0 + #endif /* BCM_CNIC */ +-#define NONE_ETH_CONTEXT_USE (FCOE_CONTEXT_USE) ++#define NON_ETH_CONTEXT_USE (FCOE_PRESENT) + + #define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \ + AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR +@@ -260,8 +261,35 @@ do { \ + #define SM_RX_ID 0 + #define SM_TX_ID 1 + +-/* fast path */ ++/* defines for multiple tx priority indices */ ++#define FIRST_TX_ONLY_COS_INDEX 1 ++#define FIRST_TX_COS_INDEX 0 ++ ++/* defines for decodeing the fastpath index and the cos index out of the ++ * transmission queue index ++ */ ++#define MAX_TXQS_PER_COS FP_SB_MAX_E1x ++ ++#define TXQ_TO_FP(txq_index) ((txq_index) % MAX_TXQS_PER_COS) ++#define TXQ_TO_COS(txq_index) ((txq_index) / MAX_TXQS_PER_COS) ++ ++/* rules for calculating the cids of tx-only connections */ ++#define CID_TO_FP(cid) ((cid) % MAX_TXQS_PER_COS) ++#define CID_COS_TO_TX_ONLY_CID(cid, cos) (cid + cos * MAX_TXQS_PER_COS) ++ ++/* fp index inside class of service range */ ++#define FP_COS_TO_TXQ(fp, cos) ((fp)->index + cos * MAX_TXQS_PER_COS) ++ ++/* ++ * 0..15 eth cos0 ++ * 16..31 eth cos1 if applicable ++ * 32..47 eth cos2 If applicable ++ * fcoe queue follows eth queues (16, 32, 48 depending on cos) ++ */ ++#define MAX_ETH_TXQ_IDX(bp) (MAX_TXQS_PER_COS * (bp)->max_cos) ++#define FCOE_TXQ_IDX(bp) (MAX_ETH_TXQ_IDX(bp)) + ++/* fast path */ + struct sw_rx_bd { + struct sk_buff *skb; + DECLARE_PCI_UNMAP_ADDR(mapping) +@@ -386,6 +414,29 @@ struct bnx2x_agg_info { + #define Q_STATS_OFFSET32(stat_name) \ + (offsetof(struct bnx2x_eth_q_stats, stat_name) / 4) + ++struct bnx2x_fp_txdata { ++ ++ struct sw_tx_bd *tx_buf_ring; ++ ++ union eth_tx_bd_types *tx_desc_ring; ++ dma_addr_t tx_desc_mapping; ++ ++ u32 cid; ++ ++ union db_prod tx_db; ++ ++ u16 tx_pkt_prod; ++ u16 tx_pkt_cons; ++ u16 tx_bd_prod; ++ u16 tx_bd_cons; ++ ++ unsigned long tx_pkt; ++ ++ __le16 *tx_cons_sb; ++ ++ int txq_index; ++}; ++ + struct bnx2x_fastpath { + struct bnx2x *bp; /* parent */ + +@@ -402,10 +453,8 @@ struct bnx2x_fastpath { + + dma_addr_t status_blk_mapping; + +- struct sw_tx_bd *tx_buf_ring; +- +- union eth_tx_bd_types *tx_desc_ring; +- dma_addr_t tx_desc_mapping; ++ u8 max_cos; /* actual number of active tx coses */ ++ struct bnx2x_fp_txdata txdata[BNX2X_MULTI_TX_COS]; + + struct sw_rx_bd *rx_buf_ring; /* BDs mappings ring */ + struct sw_rx_page *rx_page_ring; /* SGE pages mappings ring */ +@@ -424,20 +473,13 @@ struct bnx2x_fastpath { + + u32 cid; + ++ __le16 fp_hc_idx; ++ + u8 index; /* number in fp array */ + u8 cl_id; /* eth client id */ + u8 cl_qzone_id; + u8 fw_sb_id; /* status block number in FW */ + u8 igu_sb_id; /* status block number in HW */ +- union db_prod tx_db; +- +- u16 tx_pkt_prod; +- u16 tx_pkt_cons; +- u16 tx_bd_prod; +- u16 tx_bd_cons; +- __le16 *tx_cons_sb; +- +- __le16 fp_hc_idx; + + u16 rx_bd_prod; + u16 rx_bd_cons; +@@ -447,8 +489,7 @@ struct bnx2x_fastpath { + /* The last maximal completed SGE */ + u16 last_max_sge; + __le16 *rx_cons_sb; +- unsigned long tx_pkt, +- rx_pkt, ++ unsigned long rx_pkt, + rx_calls; + + /* TPA related */ +@@ -487,8 +528,12 @@ struct bnx2x_fastpath { + #define FCOE_IDX BNX2X_NUM_ETH_QUEUES(bp) + #define bnx2x_fcoe_fp(bp) (&bp->fp[FCOE_IDX]) + #define bnx2x_fcoe(bp, var) (bnx2x_fcoe_fp(bp)->var) ++#define bnx2x_fcoe_tx(bp, var) (bnx2x_fcoe_fp(bp)-> \ ++ txdata[FIRST_TX_COS_INDEX].var) + + ++#define IS_ETH_FP(fp) (fp->index < \ ++ BNX2X_NUM_ETH_QUEUES(fp->bp)) + #ifdef BCM_CNIC + #define IS_FCOE_FP(fp) (fp->index == FCOE_IDX) + #define IS_FCOE_IDX(idx) ((idx) == FCOE_IDX) +@@ -647,18 +692,23 @@ struct bnx2x_fastpath { + + #define HC_INDEX_TOE_TX_CQ_CONS 4 /* Formerly Cstorm TOE CQ index */ + /* (HC_INDEX_C_TOE_TX_CQ_CONS) */ +-#define HC_INDEX_ETH_TX_CQ_CONS 5 /* Formerly Cstorm ETH CQ index */ ++#define HC_INDEX_ETH_TX_CQ_CONS_COS0 5 /* Formerly Cstorm ETH CQ index */ ++ /* (HC_INDEX_C_ETH_TX_CQ_CONS) */ ++#define HC_INDEX_ETH_TX_CQ_CONS_COS1 6 /* Formerly Cstorm ETH CQ index */ ++ /* (HC_INDEX_C_ETH_TX_CQ_CONS) */ ++#define HC_INDEX_ETH_TX_CQ_CONS_COS2 7 /* Formerly Cstorm ETH CQ index */ + /* (HC_INDEX_C_ETH_TX_CQ_CONS) */ + +-#define U_SB_ETH_RX_CQ_INDEX HC_INDEX_ETH_RX_CQ_CONS +-#define U_SB_ETH_RX_BD_INDEX HC_INDEX_ETH_RX_BD_CONS +-#define C_SB_ETH_TX_CQ_INDEX HC_INDEX_ETH_TX_CQ_CONS ++#define HC_INDEX_ETH_FIRST_TX_CQ_CONS HC_INDEX_ETH_TX_CQ_CONS_COS0 ++ + + #define BNX2X_RX_SB_INDEX \ + (&fp->sb_index_values[HC_INDEX_ETH_RX_CQ_CONS]) + +-#define BNX2X_TX_SB_INDEX \ +- (&fp->sb_index_values[C_SB_ETH_TX_CQ_INDEX]) ++#define BNX2X_TX_SB_INDEX_BASE BNX2X_TX_SB_INDEX_COS0 ++ ++#define BNX2X_TX_SB_INDEX_COS0 \ ++ (&fp->sb_index_values[HC_INDEX_ETH_TX_CQ_CONS_COS0]) + + /* end of fast path */ + +@@ -843,25 +893,6 @@ extern struct workqueue_struct *bnx2x_wq; + /* fast-path interrupt contexts E2 */ + #define FP_SB_MAX_E2 HC_SB_MAX_SB_E2 + +-/* +- * cid_cnt paramter below refers to the value returned by +- * 'bnx2x_get_l2_cid_count()' routine +- */ +- +-/* +- * The number of FP context allocated by the driver == max number of regular +- * L2 queues + 1 for the FCoE L2 queue +- */ +-#define L2_FP_COUNT(cid_cnt) ((cid_cnt) - FCOE_CONTEXT_USE) +- +-/* +- * The number of FP-SB allocated by the driver == max number of regular L2 +- * queues + 1 for the CNIC which also consumes an FP-SB +- */ +-#define FP_SB_COUNT(cid_cnt) ((cid_cnt) - CNIC_CONTEXT_USE) +-#define NUM_IGU_SB_REQUIRED(cid_cnt) \ +- (FP_SB_COUNT(cid_cnt) - NONE_ETH_CONTEXT_USE) +- + union cdu_context { + struct eth_context eth; + char pad[1024]; +@@ -869,7 +900,7 @@ union cdu_context { + + /* CDU host DB constants */ + #define CDU_ILT_PAGE_SZ_HW 3 +-#define CDU_ILT_PAGE_SZ (4096 << CDU_ILT_PAGE_SZ_HW) /* 32K */ ++#define CDU_ILT_PAGE_SZ (8192 << CDU_ILT_PAGE_SZ_HW) /* 64K */ + #define ILT_PAGE_CIDS (CDU_ILT_PAGE_SZ / sizeof(union cdu_context)) + + #ifdef BCM_CNIC +@@ -1046,6 +1077,7 @@ struct bnx2x_fw_stats_data { + + /* Public slow path states */ + enum { ++ BNX2X_SP_RTNL_SETUP_TC, + BNX2X_SP_RTNL_TX_TIMEOUT, + }; + +@@ -1231,6 +1263,10 @@ struct bnx2x { + #define BNX2X_STATE_ERROR 0xf000 + + int multi_mode; ++#define BNX2X_MAX_PRIORITY 8 ++#define BNX2X_MAX_ENTRIES_PER_PRI 16 ++#define BNX2X_MAX_COS 3 ++#define BNX2X_MAX_TX_COS 2 + int num_queues; + int disable_tpa; + +@@ -1280,11 +1316,21 @@ struct bnx2x { + struct bnx2x_ilt *ilt; + #define BP_ILT(bp) ((bp)->ilt) + #define ILT_MAX_LINES 256 ++/* ++ * Maximum supported number of RSS queues: number of IGU SBs minus one that goes ++ * to CNIC. ++ */ ++#define BNX2X_MAX_RSS_COUNT(bp) ((bp)->igu_sb_cnt - CNIC_PRESENT) + +- int l2_cid_count; +-#define L2_ILT_LINES(bp) (DIV_ROUND_UP((bp)->l2_cid_count, \ +- ILT_PAGE_CIDS)) +-#define BNX2X_DB_SIZE(bp) ((bp)->l2_cid_count * (1 << BNX2X_DB_SHIFT)) ++/* ++ * Maximum CID count that might be required by the bnx2x: ++ * Max Tss * Max_Tx_Multi_Cos + CNIC L2 Clients (FCoE and iSCSI related) ++ */ ++#define BNX2X_L2_CID_COUNT(bp) (MAX_TXQS_PER_COS * BNX2X_MULTI_TX_COS +\ ++ NON_ETH_CONTEXT_USE + CNIC_PRESENT) ++#define L2_ILT_LINES(bp) (DIV_ROUND_UP(BNX2X_L2_CID_COUNT(bp),\ ++ ILT_PAGE_CIDS)) ++#define BNX2X_DB_SIZE(bp) (BNX2X_L2_CID_COUNT(bp) * (1 << BNX2X_DB_SHIFT)) + + int qm_cid_count; + +@@ -1408,16 +1454,24 @@ struct bnx2x { + u32 dcbx_error; + + u32 pending_max; ++ ++ /* multiple tx classes of service */ ++ u8 max_cos; ++ ++ /* priority to cos mapping */ ++ u8 prio_to_cos[8]; + }; + + /* Tx queues may be less or equal to Rx queues */ + extern int num_queues; + #define BNX2X_NUM_QUEUES(bp) (bp->num_queues) +-#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NONE_ETH_CONTEXT_USE) ++#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE) ++#define BNX2X_NUM_RX_QUEUES(bp) BNX2X_NUM_QUEUES(bp) + + #define is_multi(bp) (BNX2X_NUM_QUEUES(bp) > 1) + +-#define BNX2X_MAX_QUEUES(bp) (bp->igu_sb_cnt - CNIC_CONTEXT_USE) ++#define BNX2X_MAX_QUEUES(bp) BNX2X_MAX_RSS_COUNT(bp) ++/* #define is_eth_multi(bp) (BNX2X_NUM_ETH_QUEUES(bp) > 1) */ + + #define RSS_IPV4_CAP_MASK \ + TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY +@@ -1452,35 +1506,38 @@ struct bnx2x_func_init_params { + }; + + #define for_each_eth_queue(bp, var) \ +- for (var = 0; var < BNX2X_NUM_ETH_QUEUES(bp); var++) ++ for ((var) = 0; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++) + + #define for_each_nondefault_eth_queue(bp, var) \ +- for (var = 1; var < BNX2X_NUM_ETH_QUEUES(bp); var++) ++ for ((var) = 1; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++) + + #define for_each_queue(bp, var) \ +- for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) \ ++ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \ + if (skip_queue(bp, var)) \ + continue; \ + else + + #define for_each_rx_queue(bp, var) \ +- for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) \ ++ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \ + if (skip_rx_queue(bp, var)) \ + continue; \ + else + + #define for_each_tx_queue(bp, var) \ +- for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) \ ++ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \ + if (skip_tx_queue(bp, var)) \ + continue; \ + else + + #define for_each_nondefault_queue(bp, var) \ +- for (var = 1; var < BNX2X_NUM_QUEUES(bp); var++) \ ++ for ((var) = 1; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \ + if (skip_queue(bp, var)) \ + continue; \ + else + ++#define for_each_cos_in_tx_queue(fp, var) \ ++ for ((var) = 0; (var) < (fp)->max_cos; (var)++) ++ + /* skip rx queue + * if FCOE l2 support is diabled and this is the fcoe L2 queue + */ +diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c +index 6f1c196..4f2a28c 100644 +--- a/drivers/net/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/bnx2x/bnx2x_cmn.c +@@ -50,6 +50,26 @@ static inline void bnx2x_bz_fp(struct bnx2x *bp, int index) + + /* Restore the NAPI object as it has been already initialized */ + fp->napi = orig_napi; ++ ++ fp->bp = bp; ++ fp->index = index; ++ if (IS_ETH_FP(fp)) ++ fp->max_cos = bp->max_cos; ++ else ++ /* Special queues support only one CoS */ ++ fp->max_cos = 1; ++ ++ /* ++ * set the tpa flag for each queue. The tpa flag determines the queue ++ * minimal size so it must be set prior to queue memory allocation ++ */ ++ fp->disable_tpa = ((bp->flags & TPA_ENABLE_FLAG) == 0); ++ ++#ifdef BCM_CNIC ++ /* We don't want TPA on an FCoE L2 ring */ ++ if (IS_FCOE_FP(fp)) ++ fp->disable_tpa = 1; ++#endif + } + + /** +@@ -80,10 +100,10 @@ int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */ + /* free skb in the packet ring at pos idx + * return idx of last bd freed + */ +-static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp, ++static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, + u16 idx) + { +- struct sw_tx_bd *tx_buf = &fp->tx_buf_ring[idx]; ++ struct sw_tx_bd *tx_buf = &txdata->tx_buf_ring[idx]; + struct eth_tx_start_bd *tx_start_bd; + struct eth_tx_bd *tx_data_bd; + struct sk_buff *skb = tx_buf->skb; +@@ -94,11 +114,11 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp, + prefetch(&skb->end); + + DP(BNX2X_MSG_FP, "fp[%d]: pkt_idx %d buff @(%p)->skb %p\n", +- fp->index, idx, tx_buf, skb); ++ txdata->txq_index, idx, tx_buf, skb); + + /* unmap first bd */ + DP(BNX2X_MSG_OFF, "free bd_idx %d\n", bd_idx); +- tx_start_bd = &fp->tx_desc_ring[bd_idx].start_bd; ++ tx_start_bd = &txdata->tx_desc_ring[bd_idx].start_bd; + dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd), + BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE); + +@@ -129,7 +149,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp, + while (nbd > 0) { + + DP(BNX2X_MSG_OFF, "free frag bd_idx %d\n", bd_idx); +- tx_data_bd = &fp->tx_desc_ring[bd_idx].reg_bd; ++ tx_data_bd = &txdata->tx_desc_ring[bd_idx].reg_bd; + dma_unmap_page(&bp->pdev->dev, BD_UNMAP_ADDR(tx_data_bd), + BD_UNMAP_LEN(tx_data_bd), DMA_TO_DEVICE); + if (--nbd) +@@ -145,20 +165,19 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp, + return new_cons; + } + +-int bnx2x_tx_int(struct bnx2x_fastpath *fp) ++int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata) + { +- struct bnx2x *bp = fp->bp; + struct netdev_queue *txq; +- u16 hw_cons, sw_cons, bd_cons = fp->tx_bd_cons; ++ u16 hw_cons, sw_cons, bd_cons = txdata->tx_bd_cons; + + #ifdef BNX2X_STOP_ON_ERROR + if (unlikely(bp->panic)) + return -1; + #endif + +- txq = netdev_get_tx_queue(bp->dev, fp->index); +- hw_cons = le16_to_cpu(*fp->tx_cons_sb); +- sw_cons = fp->tx_pkt_cons; ++ txq = netdev_get_tx_queue(bp->dev, txdata->txq_index); ++ hw_cons = le16_to_cpu(*txdata->tx_cons_sb); ++ sw_cons = txdata->tx_pkt_cons; + + while (sw_cons != hw_cons) { + u16 pkt_cons; +@@ -167,14 +186,14 @@ int bnx2x_tx_int(struct bnx2x_fastpath *fp) + + DP(NETIF_MSG_TX_DONE, "queue[%d]: hw_cons %u sw_cons %u " + " pkt_cons %u\n", +- fp->index, hw_cons, sw_cons, pkt_cons); ++ txdata->txq_index, hw_cons, sw_cons, pkt_cons); + +- bd_cons = bnx2x_free_tx_pkt(bp, fp, pkt_cons); ++ bd_cons = bnx2x_free_tx_pkt(bp, txdata, pkt_cons); + sw_cons++; + } + +- fp->tx_pkt_cons = sw_cons; +- fp->tx_bd_cons = bd_cons; ++ txdata->tx_pkt_cons = sw_cons; ++ txdata->tx_bd_cons = bd_cons; + + /* Need to make the tx_bd_cons update visible to start_xmit() + * before checking for netif_tx_queue_stopped(). Without the +@@ -202,7 +221,7 @@ int bnx2x_tx_int(struct bnx2x_fastpath *fp) + + if ((netif_tx_queue_stopped(txq)) && + (bp->state == BNX2X_STATE_OPEN) && +- (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3)) ++ (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3)) + netif_tx_wake_queue(txq); + + __netif_tx_unlock(txq); +@@ -777,6 +796,7 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie) + { + struct bnx2x_fastpath *fp = fp_cookie; + struct bnx2x *bp = fp->bp; ++ u8 cos; + + DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB " + "[fp %d fw_sd %d igusb %d]\n", +@@ -790,7 +810,10 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie) + + /* Handle Rx and Tx according to MSI-X vector */ + prefetch(fp->rx_cons_sb); +- prefetch(fp->tx_cons_sb); ++ ++ for_each_cos_in_tx_queue(fp, cos) ++ prefetch(fp->txdata[cos].tx_cons_sb); ++ + prefetch(&fp->sb_running_index[SM_RX_ID]); + napi_schedule(&bnx2x_fp(bp, fp->index, napi)); + +@@ -1060,17 +1083,22 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) + static void bnx2x_free_tx_skbs(struct bnx2x *bp) + { + int i; ++ u8 cos; + + for_each_tx_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; ++ for_each_cos_in_tx_queue(fp, cos) { ++ struct bnx2x_fp_txdata *txdata = &fp->txdata[cos]; + +- u16 bd_cons = fp->tx_bd_cons; +- u16 sw_prod = fp->tx_pkt_prod; +- u16 sw_cons = fp->tx_pkt_cons; ++ u16 bd_cons = txdata->tx_bd_cons; ++ u16 sw_prod = txdata->tx_pkt_prod; ++ u16 sw_cons = txdata->tx_pkt_cons; + +- while (sw_cons != sw_prod) { +- bd_cons = bnx2x_free_tx_pkt(bp, fp, TX_BD(sw_cons)); +- sw_cons++; ++ while (sw_cons != sw_prod) { ++ bd_cons = bnx2x_free_tx_pkt(bp, txdata, ++ TX_BD(sw_cons)); ++ sw_cons++; ++ } + } + } + } +@@ -1174,7 +1202,7 @@ void bnx2x_free_irq(struct bnx2x *bp) + { + if (bp->flags & USING_MSIX_FLAG) + bnx2x_free_msix_irqs(bp, BNX2X_NUM_ETH_QUEUES(bp) + +- CNIC_CONTEXT_USE + 1); ++ CNIC_PRESENT + 1); + else if (bp->flags & USING_MSI_FLAG) + free_irq(bp->pdev->irq, bp->dev); + else +@@ -1196,6 +1224,7 @@ int bnx2x_enable_msix(struct bnx2x *bp) + bp->msix_table[msix_vec].entry, bp->msix_table[msix_vec].entry); + msix_vec++; + #endif ++ /* We need separate vectors for ETH queues only (not FCoE) */ + for_each_eth_queue(bp, i) { + bp->msix_table[msix_vec].entry = msix_vec; + DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d " +@@ -1203,7 +1232,7 @@ int bnx2x_enable_msix(struct bnx2x *bp) + msix_vec++; + } + +- req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_CONTEXT_USE + 1; ++ req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_PRESENT + 1; + + rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt); + +@@ -1278,7 +1307,7 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp) + } + + i = BNX2X_NUM_ETH_QUEUES(bp); +- offset = 1 + CNIC_CONTEXT_USE; ++ offset = 1 + CNIC_PRESENT; + netdev_info(bp->dev, "using MSI-X IRQs: sp %d fp[%d] %d" + " ... fp[%d] %d\n", + bp->msix_table[0].vector, +@@ -1375,11 +1404,9 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw) + + u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb) + { +-#ifdef BCM_CNIC + struct bnx2x *bp = netdev_priv(dev); +- if (NO_FCOE(bp)) +- return skb_tx_hash(dev, skb); +- else { ++#ifdef BCM_CNIC ++ if (!NO_FCOE(bp)) { + struct ethhdr *hdr = (struct ethhdr *)skb->data; + u16 ether_type = ntohs(hdr->h_proto); + +@@ -1393,13 +1420,11 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb) + + /* If ethertype is FCoE or FIP - use FCoE ring */ + if ((ether_type == ETH_P_FCOE) || (ether_type == ETH_P_FIP)) +- return bnx2x_fcoe(bp, index); ++ return bnx2x_fcoe_tx(bp, txq_index); + } + #endif +- /* Select a none-FCoE queue: if FCoE is enabled, exclude FCoE L2 ring +- */ +- return __skb_tx_hash(dev, skb, +- dev->real_num_tx_queues - FCOE_CONTEXT_USE); ++ /* select a non-FCoE queue */ ++ return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp)); + } + + void bnx2x_set_num_queues(struct bnx2x *bp) +@@ -1418,20 +1443,56 @@ void bnx2x_set_num_queues(struct bnx2x *bp) + } + + /* Add special queues */ +- bp->num_queues += NONE_ETH_CONTEXT_USE; ++ bp->num_queues += NON_ETH_CONTEXT_USE; + } + ++/** ++ * bnx2x_set_real_num_queues - configure netdev->real_num_[tx,rx]_queues ++ * ++ * @bp: Driver handle ++ * ++ * We currently support for at most 16 Tx queues for each CoS thus we will ++ * allocate a multiple of 16 for ETH L2 rings according to the value of the ++ * bp->max_cos. ++ * ++ * If there is an FCoE L2 queue the appropriate Tx queue will have the next ++ * index after all ETH L2 indices. ++ * ++ * If the actual number of Tx queues (for each CoS) is less than 16 then there ++ * will be the holes at the end of each group of 16 ETh L2 indices (0..15, ++ * 16..31,...) with indicies that are not coupled with any real Tx queue. ++ * ++ * The proper configuration of skb->queue_mapping is handled by ++ * bnx2x_select_queue() and __skb_tx_hash(). ++ * ++ * bnx2x_setup_tc() takes care of the proper TC mappings so that __skb_tx_hash() ++ * will return a proper Tx index if TC is enabled (netdev->num_tc > 0). ++ */ + static inline int bnx2x_set_real_num_queues(struct bnx2x *bp) + { +- int rc, num = bp->num_queues; ++ int rc, tx, rx; + +-#ifdef BCM_CNIC +- if (NO_FCOE(bp)) +- num -= FCOE_CONTEXT_USE; ++ tx = MAX_TXQS_PER_COS * bp->max_cos; ++ rx = BNX2X_NUM_ETH_QUEUES(bp); + ++/* account for fcoe queue */ ++#ifdef BCM_CNIC ++ if (!NO_FCOE(bp)) { ++ rx += FCOE_PRESENT; ++ tx += FCOE_PRESENT; ++ } + #endif +- netif_set_real_num_tx_queues(bp->dev, num); +- rc = netif_set_real_num_rx_queues(bp->dev, num); ++ ++ netif_set_real_num_tx_queues(bp->dev, tx); ++ rc = netif_set_real_num_rx_queues(bp->dev, rx); ++ if (rc) { ++ BNX2X_ERR("Failed to set real number of Rx queues: %d\n", rc); ++ return rc; ++ } ++ ++ DP(NETIF_MSG_DRV, "Setting real num queues to (tx, rx) (%d, %d)\n", ++ tx, rx); ++ + return rc; + } + +@@ -1661,28 +1722,18 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) + /* must be called before memory allocation and HW init */ + bnx2x_ilt_set_info(bp); + +- /* zero fastpath structures preserving invariants like napi which are +- * allocated only once ++ /* ++ * Zero fastpath structures preserving invariants like napi, which are ++ * allocated only once, fp index, max_cos, bp pointer. ++ * Also set fp->disable_tpa. + */ + for_each_queue(bp, i) + bnx2x_bz_fp(bp, i); + ++ + /* Set the receive queues buffer size */ + bnx2x_set_rx_buf_size(bp); + +- /* +- * set the tpa flag for each queue. The tpa flag determines the queue +- * minimal size so it must be set prior to queue memory allocation +- */ +- for_each_queue(bp, i) +- bnx2x_fp(bp, i, disable_tpa) = +- ((bp->flags & TPA_ENABLE_FLAG) == 0); +- +-#ifdef BCM_CNIC +- /* We don't want TPA on FCoE L2 ring */ +- bnx2x_fcoe(bp, disable_tpa) = 1; +-#endif +- + if (bnx2x_alloc_mem(bp)) + return -ENOMEM; + +@@ -1747,6 +1798,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) + queue_delayed_work(bnx2x_wq, &bp->period_task, 0); + } else + bp->port.pmf = 0; ++ + DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf); + + /* Init Function state controlling object */ +@@ -2092,6 +2144,7 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state) + int bnx2x_poll(struct napi_struct *napi, int budget) + { + int work_done = 0; ++ u8 cos; + struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath, + napi); + struct bnx2x *bp = fp->bp; +@@ -2104,8 +2157,10 @@ int bnx2x_poll(struct napi_struct *napi, int budget) + } + #endif + +- if (bnx2x_has_tx_work(fp)) +- bnx2x_tx_int(fp); ++ for_each_cos_in_tx_queue(fp, cos) ++ if (bnx2x_tx_queue_has_work(&fp->txdata[cos])) ++ bnx2x_tx_int(bp, &fp->txdata[cos]); ++ + + if (bnx2x_has_rx_work(fp)) { + work_done += bnx2x_rx_int(fp, budget - work_done); +@@ -2167,7 +2222,7 @@ int bnx2x_poll(struct napi_struct *napi, int budget) + * in Other Operating Systems(TM) + */ + static noinline u16 bnx2x_tx_split(struct bnx2x *bp, +- struct bnx2x_fastpath *fp, ++ struct bnx2x_fp_txdata *txdata, + struct sw_tx_bd *tx_buf, + struct eth_tx_start_bd **tx_bd, u16 hlen, + u16 bd_prod, int nbd) +@@ -2188,7 +2243,7 @@ static noinline u16 bnx2x_tx_split(struct bnx2x *bp, + /* now get a new data BD + * (after the pbd) and fill it */ + bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); +- d_tx_bd = &fp->tx_desc_ring[bd_prod].reg_bd; ++ d_tx_bd = &txdata->tx_desc_ring[bd_prod].reg_bd; + + mapping = HILO_U64(le32_to_cpu(h_tx_bd->addr_hi), + le32_to_cpu(h_tx_bd->addr_lo)) + hlen; +@@ -2484,8 +2539,10 @@ static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb, + netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct bnx2x *bp = netdev_priv(dev); ++ + struct bnx2x_fastpath *fp; + struct netdev_queue *txq; ++ struct bnx2x_fp_txdata *txdata; + struct sw_tx_bd *tx_buf; + struct eth_tx_start_bd *tx_start_bd, *first_bd; + struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL; +@@ -2493,7 +2550,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + struct eth_tx_parse_bd_e2 *pbd_e2 = NULL; + u32 pbd_e2_parsing_data = 0; + u16 pkt_prod, bd_prod; +- int nbd, fp_index; ++ int nbd, txq_index, fp_index, txdata_index; + dma_addr_t mapping; + u32 xmit_type = bnx2x_xmit_type(bp, skb); + int i; +@@ -2507,12 +2564,43 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + return NETDEV_TX_BUSY; + #endif + +- fp_index = skb_get_queue_mapping(skb); +- txq = netdev_get_tx_queue(dev, fp_index); ++ txq_index = skb_get_queue_mapping(skb); ++ txq = netdev_get_tx_queue(dev, txq_index); ++ ++ BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + FCOE_PRESENT); ++ ++ /* decode the fastpath index and the cos index from the txq */ ++ fp_index = TXQ_TO_FP(txq_index); ++ txdata_index = TXQ_TO_COS(txq_index); ++ ++#ifdef BCM_CNIC ++ /* ++ * Override the above for the FCoE queue: ++ * - FCoE fp entry is right after the ETH entries. ++ * - FCoE L2 queue uses bp->txdata[0] only. ++ */ ++ if (unlikely(!NO_FCOE(bp) && (txq_index == ++ bnx2x_fcoe_tx(bp, txq_index)))) { ++ fp_index = FCOE_IDX; ++ txdata_index = 0; ++ } ++#endif ++ ++ /* enable this debug print to view the transmission queue being used ++ DP(BNX2X_MSG_FP, "indices: txq %d, fp %d, txdata %d", ++ txq_index, fp_index, txdata_index); */ + ++ /* locate the fastpath and the txdata */ + fp = &bp->fp[fp_index]; ++ txdata = &fp->txdata[txdata_index]; ++ ++ /* enable this debug print to view the tranmission details ++ DP(BNX2X_MSG_FP,"transmitting packet cid %d fp index %d txdata_index %d" ++ " tx_data ptr %p fp pointer %p", ++ txdata->cid, fp_index, txdata_index, txdata, fp); */ + +- if (unlikely(bnx2x_tx_avail(fp) < (skb_shinfo(skb)->nr_frags + 3))) { ++ if (unlikely(bnx2x_tx_avail(bp, txdata) < ++ (skb_shinfo(skb)->nr_frags + 3))) { + fp->eth_q_stats.driver_xoff++; + netif_tx_stop_queue(txq); + BNX2X_ERR("BUG! Tx ring full when queue awake!\n"); +@@ -2521,7 +2609,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + + DP(NETIF_MSG_TX_QUEUED, "queue[%d]: SKB: summed %x protocol %x " + "protocol(%x,%x) gso type %x xmit_type %x\n", +- fp_index, skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr, ++ txq_index, skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr, + ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type); + + eth = (struct ethhdr *)skb->data; +@@ -2570,15 +2658,15 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + /* get current pkt produced now - advance it just before sending packet + * since mapping of pages may fail and cause packet to be dropped + */ +- pkt_prod = fp->tx_pkt_prod; +- bd_prod = TX_BD(fp->tx_bd_prod); ++ pkt_prod = txdata->tx_pkt_prod; ++ bd_prod = TX_BD(txdata->tx_bd_prod); + + /* get a tx_buf and first BD + * tx_start_bd may be changed during SPLIT, + * but first_bd will always stay first + */ +- tx_buf = &fp->tx_buf_ring[TX_BD(pkt_prod)]; +- tx_start_bd = &fp->tx_desc_ring[bd_prod].start_bd; ++ tx_buf = &txdata->tx_buf_ring[TX_BD(pkt_prod)]; ++ tx_start_bd = &txdata->tx_desc_ring[bd_prod].start_bd; + first_bd = tx_start_bd; + + tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD; +@@ -2589,13 +2677,13 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_HDR_NBDS, 1); + + /* remember the first BD of the packet */ +- tx_buf->first_bd = fp->tx_bd_prod; ++ tx_buf->first_bd = txdata->tx_bd_prod; + tx_buf->skb = skb; + tx_buf->flags = 0; + + DP(NETIF_MSG_TX_QUEUED, + "sending pkt %u @%p next_idx %u bd %u @%p\n", +- pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_start_bd); ++ pkt_prod, tx_buf, txdata->tx_pkt_prod, bd_prod, tx_start_bd); + + #ifdef BCM_VLAN + if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb) && +@@ -2615,7 +2703,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + bnx2x_set_sbd_csum(bp, skb, tx_start_bd, xmit_type); + + if (!CHIP_IS_E1x(bp)) { +- pbd_e2 = &fp->tx_desc_ring[bd_prod].parse_bd_e2; ++ pbd_e2 = &txdata->tx_desc_ring[bd_prod].parse_bd_e2; + memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2)); + /* Set PBD in checksum offload case */ + if (xmit_type & XMIT_CSUM) +@@ -2637,7 +2725,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + eth->h_dest); + } + } else { +- pbd_e1x = &fp->tx_desc_ring[bd_prod].parse_bd_e1x; ++ pbd_e1x = &txdata->tx_desc_ring[bd_prod].parse_bd_e1x; + memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x)); + /* Set PBD in checksum offload case */ + if (xmit_type & XMIT_CSUM) +@@ -2669,8 +2757,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_SW_LSO; + + if (unlikely(skb_headlen(skb) > hlen)) +- bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd, +- hlen, bd_prod, ++nbd); ++ bd_prod = bnx2x_tx_split(bp, txdata, tx_buf, ++ &tx_start_bd, hlen, ++ bd_prod, ++nbd); + if (!CHIP_IS_E1x(bp)) + bnx2x_set_pbd_gso_e2(skb, &pbd_e2_parsing_data, + xmit_type); +@@ -2704,14 +2793,15 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + * before call to bnx2x_free_tx_pkt + */ + first_bd->nbd = cpu_to_le16(nbd); +- bnx2x_free_tx_pkt(bp, fp, TX_BD(fp->tx_pkt_prod)); ++ bnx2x_free_tx_pkt(bp, txdata, ++ TX_BD(txdata->tx_pkt_prod)); + return NETDEV_TX_OK; + } + + bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); +- tx_data_bd = &fp->tx_desc_ring[bd_prod].reg_bd; ++ tx_data_bd = &txdata->tx_desc_ring[bd_prod].reg_bd; + if (total_pkt_bd == NULL) +- total_pkt_bd = &fp->tx_desc_ring[bd_prod].reg_bd; ++ total_pkt_bd = &txdata->tx_desc_ring[bd_prod].reg_bd; + + tx_data_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); + tx_data_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); +@@ -2765,7 +2855,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + pbd_e2->parsing_data); + DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod); + +- fp->tx_pkt_prod++; ++ txdata->tx_pkt_prod++; + /* + * Make sure that the BD data is updated before updating the producer + * since FW might read the BD right after the producer is updated. +@@ -2775,16 +2865,16 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + */ + wmb(); + +- fp->tx_db.data.prod += nbd; ++ txdata->tx_db.data.prod += nbd; + barrier(); + +- DOORBELL(bp, fp->cid, fp->tx_db.raw); ++ DOORBELL(bp, txdata->cid, txdata->tx_db.raw); + + mmiowb(); + +- fp->tx_bd_prod += nbd; ++ txdata->tx_bd_prod += nbd; + +- if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) { ++ if (unlikely(bnx2x_tx_avail(bp, txdata) < MAX_SKB_FRAGS + 3)) { + netif_tx_stop_queue(txq); + + /* paired memory barrier is in bnx2x_tx_int(), we have to keep +@@ -2793,10 +2883,10 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + smp_mb(); + + fp->eth_q_stats.driver_xoff++; +- if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3) ++ if (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3) + netif_tx_wake_queue(txq); + } +- fp->tx_pkt++; ++ txdata->tx_pkt++; + + return NETDEV_TX_OK; + } +@@ -2829,6 +2919,7 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index) + { + union host_hc_status_block *sb = &bnx2x_fp(bp, fp_index, status_blk); + struct bnx2x_fastpath *fp = &bp->fp[fp_index]; ++ u8 cos; + + /* Common */ + #ifdef BCM_CNIC +@@ -2877,10 +2968,18 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index) + /* Tx */ + if (!skip_tx_queue(bp, fp_index)) { + /* fastpath tx rings: tx_buf tx_desc */ +- BNX2X_FREE(bnx2x_fp(bp, fp_index, tx_buf_ring)); +- BNX2X_PCI_FREE(bnx2x_fp(bp, fp_index, tx_desc_ring), +- bnx2x_fp(bp, fp_index, tx_desc_mapping), +- sizeof(union eth_tx_bd_types) * NUM_TX_BD); ++ for_each_cos_in_tx_queue(fp, cos) { ++ struct bnx2x_fp_txdata *txdata = &fp->txdata[cos]; ++ ++ DP(BNX2X_MSG_SP, ++ "freeing tx memory of fp %d cos %d cid %d", ++ fp_index, cos, txdata->cid); ++ ++ BNX2X_FREE(txdata->tx_buf_ring); ++ BNX2X_PCI_FREE(txdata->tx_desc_ring, ++ txdata->tx_desc_mapping, ++ sizeof(union eth_tx_bd_types) * NUM_TX_BD); ++ } + } + /* end of fastpath */ + } +@@ -2913,19 +3012,17 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index) + union host_hc_status_block *sb; + struct bnx2x_fastpath *fp = &bp->fp[index]; + int ring_size = 0; ++ u8 cos; + + /* if rx_ring_size specified - use it */ + int rx_ring_size = bp->rx_ring_size ? bp->rx_ring_size : +- MAX_RX_AVAIL/bp->num_queues; ++ MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp); + + /* allocate at least number of buffers required by FW */ +- rx_ring_size = max_t(int, fp->disable_tpa ? MIN_RX_SIZE_NONTPA : ++ rx_ring_size = max_t(int, bp->disable_tpa ? MIN_RX_SIZE_NONTPA : + MIN_RX_SIZE_TPA, + rx_ring_size); + +- bnx2x_fp(bp, index, bp) = bp; +- bnx2x_fp(bp, index, index) = index; +- + /* Common */ + sb = &bnx2x_fp(bp, index, status_blk); + #ifdef BCM_CNIC +@@ -2953,11 +3050,19 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index) + /* Tx */ + if (!skip_tx_queue(bp, index)) { + /* fastpath tx rings: tx_buf tx_desc */ +- BNX2X_ALLOC(bnx2x_fp(bp, index, tx_buf_ring), ++ for_each_cos_in_tx_queue(fp, cos) { ++ struct bnx2x_fp_txdata *txdata = &fp->txdata[cos]; ++ ++ DP(BNX2X_MSG_SP, "allocating tx memory of " ++ "fp %d cos %d", ++ index, cos); ++ ++ BNX2X_ALLOC(txdata->tx_buf_ring, + sizeof(struct sw_tx_bd) * NUM_TX_BD); +- BNX2X_PCI_ALLOC(bnx2x_fp(bp, index, tx_desc_ring), +- &bnx2x_fp(bp, index, tx_desc_mapping), ++ BNX2X_PCI_ALLOC(txdata->tx_desc_ring, ++ &txdata->tx_desc_mapping, + sizeof(union eth_tx_bd_types) * NUM_TX_BD); ++ } + } + + /* Rx */ +@@ -3000,7 +3105,7 @@ alloc_mem_err: + index, ring_size); + /* FW will drop all packets if queue is not big enough, + * In these cases we disable the queue +- * Min size diferent for TPA and non-TPA queues ++ * Min size is different for OOO, TPA and non-TPA queues + */ + if (ring_size < (fp->disable_tpa ? + MIN_RX_SIZE_NONTPA : MIN_RX_SIZE_TPA)) { +@@ -3018,12 +3123,14 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp) + /** + * 1. Allocate FP for leading - fatal if error + * 2. {CNIC} Allocate FCoE FP - fatal if error +- * 3. Allocate RSS - fix number of queues if error ++ * 3. {CNIC} Allocate OOO + FWD - disable OOO if error ++ * 4. Allocate RSS - fix number of queues if error + */ + + /* leading */ + if (bnx2x_alloc_fp_mem_at(bp, 0)) + return -ENOMEM; ++ + #ifdef BCM_CNIC + if (!NO_FCOE(bp)) + /* FCoE */ +@@ -3033,6 +3140,7 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp) + */ + return -ENOMEM; + #endif ++ + /* RSS */ + for_each_nondefault_eth_queue(bp, i) + if (bnx2x_alloc_fp_mem_at(bp, i)) +@@ -3050,7 +3158,7 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp) + * FCOE_IDX < FWD_IDX < OOO_IDX + */ + +- /* move FCoE fp */ ++ /* move FCoE fp even NO_FCOE_FLAG is on */ + bnx2x_move_fp(bp, FCOE_IDX, FCOE_IDX - delta); + #endif + bp->num_queues -= delta; +@@ -3073,16 +3181,23 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp) + struct bnx2x_fastpath *fp; + struct msix_entry *tbl; + struct bnx2x_ilt *ilt; ++ int msix_table_size = 0; ++ ++ /* ++ * The biggest MSI-X table we might need is as a maximum number of fast ++ * path IGU SBs plus default SB (for PF). ++ */ ++ msix_table_size = bp->igu_sb_cnt + 1; + +- /* fp array */ +- fp = kzalloc(L2_FP_COUNT(bp->l2_cid_count)*sizeof(*fp), GFP_KERNEL); ++ /* fp array: RSS plus CNIC related L2 queues */ ++ fp = kzalloc((BNX2X_MAX_RSS_COUNT(bp) + NON_ETH_CONTEXT_USE) * ++ sizeof(*fp), GFP_KERNEL); + if (!fp) + goto alloc_err; + bp->fp = fp; + + /* msix table */ +- tbl = kzalloc((FP_SB_COUNT(bp->l2_cid_count) + 1) * sizeof(*tbl), +- GFP_KERNEL); ++ tbl = kzalloc(msix_table_size * sizeof(*tbl), GFP_KERNEL); + if (!tbl) + goto alloc_err; + bp->msix_table = tbl; +diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h +index 4caf01c..871531c 100644 +--- a/drivers/net/bnx2x/bnx2x_cmn.h ++++ b/drivers/net/bnx2x/bnx2x_cmn.h +@@ -451,7 +451,7 @@ void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp, + u16 bd_prod, u16 rx_comp_prod, u16 rx_sge_prod); + + /* NAPI poll Tx part */ +-int bnx2x_tx_int(struct bnx2x_fastpath *fp); ++int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata); + + /* suspend/resume callbacks */ + int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state); +@@ -735,21 +735,22 @@ static inline u16 bnx2x_ack_int(struct bnx2x *bp) + return bnx2x_igu_ack_int(bp); + } + +-static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp) ++static inline int bnx2x_has_tx_work_unload(struct bnx2x_fp_txdata *txdata) + { + /* Tell compiler that consumer and producer can change */ + barrier(); +- return fp->tx_pkt_prod != fp->tx_pkt_cons; ++ return txdata->tx_pkt_prod != txdata->tx_pkt_cons; + } + +-static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp) ++static inline u16 bnx2x_tx_avail(struct bnx2x *bp, ++ struct bnx2x_fp_txdata *txdata) + { + s16 used; + u16 prod; + u16 cons; + +- prod = fp->tx_bd_prod; +- cons = fp->tx_bd_cons; ++ prod = txdata->tx_bd_prod; ++ cons = txdata->tx_bd_cons; + + /* NUM_TX_RINGS = number of "next-page" entries + It will be used as a threshold */ +@@ -757,21 +758,30 @@ static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp) + + #ifdef BNX2X_STOP_ON_ERROR + WARN_ON(used < 0); +- WARN_ON(used > fp->bp->tx_ring_size); +- WARN_ON((fp->bp->tx_ring_size - used) > MAX_TX_AVAIL); ++ WARN_ON(used > bp->tx_ring_size); ++ WARN_ON((bp->tx_ring_size - used) > MAX_TX_AVAIL); + #endif + +- return (s16)(fp->bp->tx_ring_size) - used; ++ return (s16)(bp->tx_ring_size) - used; + } + +-static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp) ++static inline int bnx2x_tx_queue_has_work(struct bnx2x_fp_txdata *txdata) + { + u16 hw_cons; + + /* Tell compiler that status block fields can change */ + barrier(); +- hw_cons = le16_to_cpu(*fp->tx_cons_sb); +- return hw_cons != fp->tx_pkt_cons; ++ hw_cons = le16_to_cpu(*txdata->tx_cons_sb); ++ return hw_cons != txdata->tx_pkt_cons; ++} ++ ++static inline bool bnx2x_has_tx_work(struct bnx2x_fastpath *fp) ++{ ++ u8 cos; ++ for_each_cos_in_tx_queue(fp, cos) ++ if (bnx2x_tx_queue_has_work(&fp->txdata[cos])) ++ return true; ++ return false; + } + + static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp) +@@ -983,7 +993,7 @@ static inline int bnx2x_func_start(struct bnx2x *bp) + /* Function parameters */ + start_params->mf_mode = bp->mf_mode; + start_params->sd_vlan_tag = bp->mf_ov; +- start_params->network_cos_mode = OVERRIDE_COS; ++ start_params->network_cos_mode = OVERRIDE_COS; + + return bnx2x_func_state_change(bp, &func_params); + } +@@ -1043,39 +1053,41 @@ static inline void bnx2x_free_tpa_pool(struct bnx2x *bp, + } + } + +-static inline void bnx2x_init_tx_ring_one(struct bnx2x_fastpath *fp) ++static inline void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata) + { + int i; + + for (i = 1; i <= NUM_TX_RINGS; i++) { + struct eth_tx_next_bd *tx_next_bd = +- &fp->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd; ++ &txdata->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd; + + tx_next_bd->addr_hi = +- cpu_to_le32(U64_HI(fp->tx_desc_mapping + ++ cpu_to_le32(U64_HI(txdata->tx_desc_mapping + + BCM_PAGE_SIZE*(i % NUM_TX_RINGS))); + tx_next_bd->addr_lo = +- cpu_to_le32(U64_LO(fp->tx_desc_mapping + ++ cpu_to_le32(U64_LO(txdata->tx_desc_mapping + + BCM_PAGE_SIZE*(i % NUM_TX_RINGS))); + } + +- SET_FLAG(fp->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1); +- fp->tx_db.data.zero_fill1 = 0; +- fp->tx_db.data.prod = 0; ++ SET_FLAG(txdata->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1); ++ txdata->tx_db.data.zero_fill1 = 0; ++ txdata->tx_db.data.prod = 0; + +- fp->tx_pkt_prod = 0; +- fp->tx_pkt_cons = 0; +- fp->tx_bd_prod = 0; +- fp->tx_bd_cons = 0; +- fp->tx_pkt = 0; ++ txdata->tx_pkt_prod = 0; ++ txdata->tx_pkt_cons = 0; ++ txdata->tx_bd_prod = 0; ++ txdata->tx_bd_cons = 0; ++ txdata->tx_pkt = 0; + } + + static inline void bnx2x_init_tx_rings(struct bnx2x *bp) + { + int i; ++ u8 cos; + + for_each_tx_queue(bp, i) +- bnx2x_init_tx_ring_one(&bp->fp[i]); ++ for_each_cos_in_tx_queue(&bp->fp[i], cos) ++ bnx2x_init_tx_ring_one(&bp->fp[i].txdata[cos]); + } + + static inline void bnx2x_set_next_page_rx_bd(struct bnx2x_fastpath *fp) +@@ -1277,12 +1289,23 @@ static inline u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp) + return USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), fp->cl_id); + } + ++static inline void bnx2x_init_txdata(struct bnx2x *bp, ++ struct bnx2x_fp_txdata *txdata, u32 cid, int txq_index, ++ __le16 *tx_cons_sb) ++{ ++ txdata->cid = cid; ++ txdata->txq_index = txq_index; ++ txdata->tx_cons_sb = tx_cons_sb; ++ ++ DP(BNX2X_MSG_SP, "created tx data cid %d, txq %d", ++ txdata->cid, txdata->txq_index); ++} + + #ifdef BCM_CNIC + static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx) + { + return bp->cnic_base_cl_id + cl_idx + +- (bp->pf_num >> 1) * NONE_ETH_CONTEXT_USE; ++ (bp->pf_num >> 1) * NON_ETH_CONTEXT_USE; + } + + static inline u8 bnx2x_cnic_fw_sb_id(struct bnx2x *bp) +@@ -1313,10 +1336,13 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp) + bnx2x_fcoe(bp, cid) = BNX2X_FCOE_ETH_CID; + bnx2x_fcoe(bp, fw_sb_id) = DEF_SB_ID; + bnx2x_fcoe(bp, igu_sb_id) = bp->igu_dsb_id; +- bnx2x_fcoe(bp, bp) = bp; +- bnx2x_fcoe(bp, index) = FCOE_IDX; + bnx2x_fcoe(bp, rx_cons_sb) = BNX2X_FCOE_L2_RX_INDEX; +- bnx2x_fcoe(bp, tx_cons_sb) = BNX2X_FCOE_L2_TX_INDEX; ++ ++ bnx2x_init_txdata(bp, &bnx2x_fcoe(bp, txdata[0]), ++ fp->cid, FCOE_TXQ_IDX(bp), BNX2X_FCOE_L2_TX_INDEX); ++ ++ DP(BNX2X_MSG_SP, "created fcoe tx data (fp index %d)", fp->index); ++ + /* qZone id equals to FW (per path) client id */ + bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fp_qzone_id(fp); + /* init shortcut */ +@@ -1326,9 +1352,13 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp) + /* Configure Queue State object */ + __set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type); + __set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type); +- bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, fp->cid, BP_FUNC(bp), +- bnx2x_sp(bp, q_rdata), bnx2x_sp_mapping(bp, q_rdata), +- q_type); ++ ++ /* No multi-CoS for FCoE L2 client */ ++ BUG_ON(fp->max_cos != 1); ++ ++ bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, &fp->cid, 1, ++ BP_FUNC(bp), bnx2x_sp(bp, q_rdata), ++ bnx2x_sp_mapping(bp, q_rdata), q_type); + + DP(NETIF_MSG_IFUP, "queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d fw_sb %d " + "igu_sb %d\n", +@@ -1338,15 +1368,16 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp) + #endif + + static inline int bnx2x_clean_tx_queue(struct bnx2x *bp, +- struct bnx2x_fastpath *fp) ++ struct bnx2x_fp_txdata *txdata) + { + int cnt = 1000; + +- while (bnx2x_has_tx_work_unload(fp)) { ++ while (bnx2x_has_tx_work_unload(txdata)) { + if (!cnt) { + BNX2X_ERR("timeout waiting for queue[%d]: " +- "fp->tx_pkt_prod(%d) != fp->tx_pkt_cons(%d)\n", +- fp->index, fp->tx_pkt_prod, fp->tx_pkt_cons); ++ "txdata->tx_pkt_prod(%d) != txdata->tx_pkt_cons(%d)\n", ++ txdata->txq_index, txdata->tx_pkt_prod, ++ txdata->tx_pkt_cons); + #ifdef BNX2X_STOP_ON_ERROR + bnx2x_panic(); + return -EBUSY; +diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c +index db7b53c..d006a59 100644 +--- a/drivers/net/bnx2x/bnx2x_dcb.c ++++ b/drivers/net/bnx2x/bnx2x_dcb.c +@@ -573,6 +573,26 @@ static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set) + } + } + ++static inline void bnx2x_dcbx_update_tc_mapping(struct bnx2x *bp) ++{ ++ u8 prio, cos; ++ for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++) { ++ for (prio = 0; prio < BNX2X_MAX_PRIORITY; prio++) { ++ if (bp->dcbx_port_params.ets.cos_params[cos].pri_bitmask ++ & (1 << prio)) { ++ bp->prio_to_cos[prio] = cos; ++ } ++ } ++ } ++ ++ /* setup tc must be called under rtnl lock, but we can't take it here ++ * as we are handling an attetntion on a work queue which must be ++ * flushed at some rtnl-locked contexts (e.g. if down) ++ */ ++ if (!test_and_set_bit(BNX2X_SP_RTNL_SETUP_TC, &bp->sp_rtnl_state)) ++ schedule_delayed_work(&bp->sp_rtnl_task, 0); ++} ++ + void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state) + { + switch (state) { +@@ -594,6 +614,11 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state) + bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 1); + bnx2x_dcbx_stop_hw_tx(bp); + ++ /* reconfigure the netdevice with the results of the new ++ * dcbx negotiation. ++ */ ++ bnx2x_dcbx_update_tc_mapping(bp); ++ + return; + } + case BNX2X_DCBX_STATE_TX_PAUSED: +diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c +index 114da42..00053ee 100644 +--- a/drivers/net/bnx2x/bnx2x_ethtool.c ++++ b/drivers/net/bnx2x/bnx2x_ethtool.c +@@ -1775,6 +1775,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) + unsigned char *packet; + struct bnx2x_fastpath *fp_rx = &bp->fp[0]; + struct bnx2x_fastpath *fp_tx = &bp->fp[0]; ++ struct bnx2x_fp_txdata *txdata = &fp_tx->txdata[0]; + u16 tx_start_idx, tx_idx; + u16 rx_start_idx, rx_idx; + u16 pkt_prod, bd_prod, rx_comp_cons; +@@ -1829,17 +1830,17 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) + + /* send the loopback packet */ + num_pkts = 0; +- tx_start_idx = le16_to_cpu(*fp_tx->tx_cons_sb); ++ tx_start_idx = le16_to_cpu(*txdata->tx_cons_sb); + rx_start_idx = le16_to_cpu(*fp_rx->rx_cons_sb); + +- pkt_prod = fp_tx->tx_pkt_prod++; +- tx_buf = &fp_tx->tx_buf_ring[TX_BD(pkt_prod)]; +- tx_buf->first_bd = fp_tx->tx_bd_prod; ++ pkt_prod = txdata->tx_pkt_prod++; ++ tx_buf = &txdata->tx_buf_ring[TX_BD(pkt_prod)]; ++ tx_buf->first_bd = txdata->tx_bd_prod; + tx_buf->skb = skb; + tx_buf->flags = 0; + +- bd_prod = TX_BD(fp_tx->tx_bd_prod); +- tx_start_bd = &fp_tx->tx_desc_ring[bd_prod].start_bd; ++ bd_prod = TX_BD(txdata->tx_bd_prod); ++ tx_start_bd = &txdata->tx_desc_ring[bd_prod].start_bd; + tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping)); + tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); + tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */ +@@ -1856,27 +1857,27 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) + /* turn on parsing and get a BD */ + bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); + +- pbd_e1x = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e1x; +- pbd_e2 = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e2; ++ pbd_e1x = &txdata->tx_desc_ring[bd_prod].parse_bd_e1x; ++ pbd_e2 = &txdata->tx_desc_ring[bd_prod].parse_bd_e2; + + memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2)); + memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x)); + + wmb(); + +- fp_tx->tx_db.data.prod += 2; ++ txdata->tx_db.data.prod += 2; + barrier(); +- DOORBELL(bp, fp_tx->index, fp_tx->tx_db.raw); ++ DOORBELL(bp, txdata->cid, txdata->tx_db.raw); + + mmiowb(); + barrier(); + + num_pkts++; +- fp_tx->tx_bd_prod += 2; /* start + pbd */ ++ txdata->tx_bd_prod += 2; /* start + pbd */ + + udelay(100); + +- tx_idx = le16_to_cpu(*fp_tx->tx_cons_sb); ++ tx_idx = le16_to_cpu(*txdata->tx_cons_sb); + if (tx_idx != tx_start_idx + num_pkts) + goto test_loopback_exit; + +@@ -1890,7 +1891,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) + * bnx2x_tx_int()), as both are taking netif_tx_lock(). + */ + local_bh_disable(); +- bnx2x_tx_int(fp_tx); ++ bnx2x_tx_int(bp, txdata); + local_bh_enable(); + } + +diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h +index 0692d75..ce3b566 100644 +--- a/drivers/net/bnx2x/bnx2x_hsi.h ++++ b/drivers/net/bnx2x/bnx2x_hsi.h +@@ -2545,7 +2545,7 @@ struct host_func_stats { + + #define BCM_5710_FW_MAJOR_VERSION 7 + #define BCM_5710_FW_MINOR_VERSION 0 +-#define BCM_5710_FW_REVISION_VERSION 20 ++#define BCM_5710_FW_REVISION_VERSION 23 + #define BCM_5710_FW_ENGINEERING_VERSION 0 + #define BCM_5710_FW_COMPILE_FLAGS 1 + +diff --git a/drivers/net/bnx2x/bnx2x_init.h b/drivers/net/bnx2x/bnx2x_init.h +index 3e9073f..4d748e7 100644 +--- a/drivers/net/bnx2x/bnx2x_init.h ++++ b/drivers/net/bnx2x/bnx2x_init.h +@@ -128,11 +128,10 @@ enum { + MODE_MF_NIV = 0x00000800, + MODE_E3_A0 = 0x00001000, + MODE_E3_B0 = 0x00002000, +- MODE_COS_BC = 0x00004000, +- MODE_COS3 = 0x00008000, +- MODE_COS6 = 0x00010000, +- MODE_LITTLE_ENDIAN = 0x00020000, +- MODE_BIG_ENDIAN = 0x00040000, ++ MODE_COS3 = 0x00004000, ++ MODE_COS6 = 0x00008000, ++ MODE_LITTLE_ENDIAN = 0x00010000, ++ MODE_BIG_ENDIAN = 0x00020000, + }; + + /* Init Blocks */ +@@ -179,7 +178,7 @@ enum { + #define BNX2X_TOE_Q 3 + #define BNX2X_TOE_ACK_Q 6 + #define BNX2X_ISCSI_Q 9 +-#define BNX2X_ISCSI_ACK_Q 8 ++#define BNX2X_ISCSI_ACK_Q 11 + #define BNX2X_FCOE_Q 10 + + /* Vnics per mode */ +@@ -257,14 +256,16 @@ static inline void bnx2x_map_q_cos(struct bnx2x *bp, u32 q_num, u32 new_cos) + } + + /* Configures the QM according to the specified per-traffic-type COSes */ +-static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, ++static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, enum cos_mode mode, + struct priority_cos *traffic_cos) + { + bnx2x_map_q_cos(bp, BNX2X_FCOE_Q, + traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos); + bnx2x_map_q_cos(bp, BNX2X_ISCSI_Q, + traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos); +- if (INIT_MODE_FLAGS(bp) & MODE_COS_BC) { ++ bnx2x_map_q_cos(bp, BNX2X_ISCSI_ACK_Q, ++ traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos); ++ if (mode != STATIC_COS) { + /* required only in backward compatible COS mode */ + bnx2x_map_q_cos(bp, BNX2X_ETH_Q, + traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); +@@ -272,8 +273,6 @@ static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, + traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); + bnx2x_map_q_cos(bp, BNX2X_TOE_ACK_Q, + traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); +- bnx2x_map_q_cos(bp, BNX2X_ISCSI_ACK_Q, +- traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos); + } + } + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index 1fb0195..96ecd60 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -766,6 +766,7 @@ void bnx2x_panic_dump(struct bnx2x *bp) + int func = BP_FUNC(bp); + #ifdef BNX2X_STOP_ON_ERROR + u16 start = 0, end = 0; ++ u8 cos; + #endif + + bp->stats_state = STATS_STATE_DISABLED; +@@ -821,8 +822,9 @@ void bnx2x_panic_dump(struct bnx2x *bp) + CHIP_IS_E1x(bp) ? + sb_data_e1x.index_data : + sb_data_e2.index_data; +- int data_size; ++ u8 data_size, cos; + u32 *sb_data_p; ++ struct bnx2x_fp_txdata txdata; + + /* Rx */ + BNX2X_ERR("fp%d: rx_bd_prod(0x%x) rx_bd_cons(0x%x)" +@@ -837,11 +839,17 @@ void bnx2x_panic_dump(struct bnx2x *bp) + le16_to_cpu(fp->fp_hc_idx)); + + /* Tx */ +- BNX2X_ERR("fp%d: tx_pkt_prod(0x%x) tx_pkt_cons(0x%x)" +- " tx_bd_prod(0x%x) tx_bd_cons(0x%x)" +- " *tx_cons_sb(0x%x)\n", +- i, fp->tx_pkt_prod, fp->tx_pkt_cons, fp->tx_bd_prod, +- fp->tx_bd_cons, le16_to_cpu(*fp->tx_cons_sb)); ++ for_each_cos_in_tx_queue(fp, cos) ++ { ++ txdata = fp->txdata[cos]; ++ BNX2X_ERR("fp%d: tx_pkt_prod(0x%x) tx_pkt_cons(0x%x)" ++ " tx_bd_prod(0x%x) tx_bd_cons(0x%x)" ++ " *tx_cons_sb(0x%x)\n", ++ i, txdata.tx_pkt_prod, ++ txdata.tx_pkt_cons, txdata.tx_bd_prod, ++ txdata.tx_bd_cons, ++ le16_to_cpu(*txdata.tx_cons_sb)); ++ } + + loop = CHIP_IS_E1x(bp) ? + HC_SB_MAX_INDICES_E1X : HC_SB_MAX_INDICES_E2; +@@ -960,23 +968,31 @@ void bnx2x_panic_dump(struct bnx2x *bp) + /* Tx */ + for_each_tx_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; ++ for_each_cos_in_tx_queue(fp, cos) { ++ struct bnx2x_fp_txdata *txdata = &fp->txdata[cos]; ++ ++ start = TX_BD(le16_to_cpu(*txdata->tx_cons_sb) - 10); ++ end = TX_BD(le16_to_cpu(*txdata->tx_cons_sb) + 245); ++ for (j = start; j != end; j = TX_BD(j + 1)) { ++ struct sw_tx_bd *sw_bd = ++ &txdata->tx_buf_ring[j]; ++ ++ BNX2X_ERR("fp%d: txdata %d, " ++ "packet[%x]=[%p,%x]\n", ++ i, cos, j, sw_bd->skb, ++ sw_bd->first_bd); ++ } + +- start = TX_BD(le16_to_cpu(*fp->tx_cons_sb) - 10); +- end = TX_BD(le16_to_cpu(*fp->tx_cons_sb) + 245); +- for (j = start; j != end; j = TX_BD(j + 1)) { +- struct sw_tx_bd *sw_bd = &fp->tx_buf_ring[j]; +- +- BNX2X_ERR("fp%d: packet[%x]=[%p,%x]\n", +- i, j, sw_bd->skb, sw_bd->first_bd); +- } +- +- start = TX_BD(fp->tx_bd_cons - 10); +- end = TX_BD(fp->tx_bd_cons + 254); +- for (j = start; j != end; j = TX_BD(j + 1)) { +- u32 *tx_bd = (u32 *)&fp->tx_desc_ring[j]; ++ start = TX_BD(txdata->tx_bd_cons - 10); ++ end = TX_BD(txdata->tx_bd_cons + 254); ++ for (j = start; j != end; j = TX_BD(j + 1)) { ++ u32 *tx_bd = (u32 *)&txdata->tx_desc_ring[j]; + +- BNX2X_ERR("fp%d: tx_bd[%x]=[%x:%x:%x:%x]\n", +- i, j, tx_bd[0], tx_bd[1], tx_bd[2], tx_bd[3]); ++ BNX2X_ERR("fp%d: txdata %d, tx_bd[%x]=" ++ "[%x:%x:%x:%x]\n", ++ i, cos, j, tx_bd[0], tx_bd[1], ++ tx_bd[2], tx_bd[3]); ++ } + } + } + #endif +@@ -1532,7 +1548,7 @@ static void bnx2x_igu_int_disable(struct bnx2x *bp) + BNX2X_ERR("BUG! proper val not read from IGU!\n"); + } + +-static void bnx2x_int_disable(struct bnx2x *bp) ++void bnx2x_int_disable(struct bnx2x *bp) + { + if (bp->common.int_block == INT_BLOCK_HC) + bnx2x_hc_int_disable(bp); +@@ -1662,6 +1678,11 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe) + drv_cmd = BNX2X_Q_CMD_SETUP; + break; + ++ case (RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP): ++ DP(NETIF_MSG_IFUP, "got MULTI[%d] tx-only setup ramrod\n", cid); ++ drv_cmd = BNX2X_Q_CMD_SETUP_TX_ONLY; ++ break; ++ + case (RAMROD_CMD_ID_ETH_HALT): + DP(NETIF_MSG_IFDOWN, "got MULTI[%d] halt ramrod\n", cid); + drv_cmd = BNX2X_Q_CMD_HALT; +@@ -1721,6 +1742,7 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) + u16 status = bnx2x_ack_int(bp); + u16 mask; + int i; ++ u8 cos; + + /* Return here if interrupt is shared and it's not for us */ + if (unlikely(status == 0)) { +@@ -1737,11 +1759,12 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) + for_each_eth_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + +- mask = 0x2 << (fp->index + CNIC_CONTEXT_USE); ++ mask = 0x2 << (fp->index + CNIC_PRESENT); + if (status & mask) { + /* Handle Rx or Tx according to SB id */ + prefetch(fp->rx_cons_sb); +- prefetch(fp->tx_cons_sb); ++ for_each_cos_in_tx_queue(fp, cos) ++ prefetch(fp->txdata[cos].tx_cons_sb); + prefetch(&fp->sb_running_index[SM_RX_ID]); + napi_schedule(&bnx2x_fp(bp, fp->index, napi)); + status &= ~mask; +@@ -2631,15 +2654,43 @@ void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p) + } + } + +-static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp, +- struct bnx2x_fastpath *fp, +- bool leading) ++/** ++ * bnx2x_get_tx_only_flags - Return common flags ++ * ++ * @bp device handle ++ * @fp queue handle ++ * @zero_stats TRUE if statistics zeroing is needed ++ * ++ * Return the flags that are common for the Tx-only and not normal connections. ++ */ ++static inline unsigned long bnx2x_get_common_flags(struct bnx2x *bp, ++ struct bnx2x_fastpath *fp, ++ bool zero_stats) + { + unsigned long flags = 0; + + /* PF driver will always initialize the Queue to an ACTIVE state */ + __set_bit(BNX2X_Q_FLG_ACTIVE, &flags); + ++ /* tx only connections collect statistics (on the same index as the ++ * parent connection). The statistics are zeroed when the parent ++ * connection is initialized. ++ */ ++ if (stat_counter_valid(bp, fp)) { ++ __set_bit(BNX2X_Q_FLG_STATS, &flags); ++ if (zero_stats) ++ __set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags); ++ } ++ ++ return flags; ++} ++ ++static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp, ++ struct bnx2x_fastpath *fp, ++ bool leading) ++{ ++ unsigned long flags = 0; ++ + /* calculate other queue flags */ + if (IS_MF_SD(bp)) + __set_bit(BNX2X_Q_FLG_OV, &flags); +@@ -2650,11 +2701,6 @@ static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp, + if (!fp->disable_tpa) + __set_bit(BNX2X_Q_FLG_TPA, &flags); + +- if (stat_counter_valid(bp, fp)) { +- __set_bit(BNX2X_Q_FLG_STATS, &flags); +- __set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags); +- } +- + if (leading) { + __set_bit(BNX2X_Q_FLG_LEADING_RSS, &flags); + __set_bit(BNX2X_Q_FLG_MCAST, &flags); +@@ -2666,11 +2712,12 @@ static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp, + /* configure silent vlan removal */ + __set_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, &flags); + +- return flags; ++ return flags | bnx2x_get_common_flags(bp, fp, true); + } + + static void bnx2x_pf_q_prep_general(struct bnx2x *bp, +- struct bnx2x_fastpath *fp, struct bnx2x_general_setup_params *gen_init) ++ struct bnx2x_fastpath *fp, struct bnx2x_general_setup_params *gen_init, ++ u8 cos) + { + gen_init->stat_id = bnx2x_stats_id(fp); + gen_init->spcl_id = fp->cl_id; +@@ -2680,6 +2727,8 @@ static void bnx2x_pf_q_prep_general(struct bnx2x *bp, + gen_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU; + else + gen_init->mtu = bp->dev->mtu; ++ ++ gen_init->cos = cos; + } + + static void bnx2x_pf_rx_q_prep(struct bnx2x *bp, +@@ -2747,7 +2796,7 @@ static void bnx2x_pf_rx_q_prep(struct bnx2x *bp, + if (IS_FCOE_FP(fp)) + rxq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS; + else +- rxq_init->sb_cq_index = U_SB_ETH_RX_CQ_INDEX; ++ rxq_init->sb_cq_index = HC_INDEX_ETH_RX_CQ_CONS; + + if (IS_FCOE_FP(fp)) { + rxq_init->silent_removal_value = 0; +@@ -2759,10 +2808,11 @@ static void bnx2x_pf_rx_q_prep(struct bnx2x *bp, + } + + static void bnx2x_pf_tx_q_prep(struct bnx2x *bp, +- struct bnx2x_fastpath *fp, struct bnx2x_txq_setup_params *txq_init) ++ struct bnx2x_fastpath *fp, struct bnx2x_txq_setup_params *txq_init, ++ u8 cos) + { +- txq_init->dscr_map = fp->tx_desc_mapping; +- txq_init->sb_cq_index = C_SB_ETH_TX_CQ_INDEX; ++ txq_init->dscr_map = fp->txdata[cos].tx_desc_mapping; ++ txq_init->sb_cq_index = HC_INDEX_ETH_FIRST_TX_CQ_CONS + cos; + txq_init->traffic_type = LLFC_TRAFFIC_TYPE_NW; + txq_init->fw_sb_id = fp->fw_sb_id; + +@@ -2958,6 +3008,7 @@ static inline void bnx2x_sp_prod_update(struct bnx2x *bp) + static inline bool bnx2x_is_contextless_ramrod(int cmd, int cmd_type) + { + if ((cmd_type == NONE_CONNECTION_TYPE) || ++ (cmd == RAMROD_CMD_ID_ETH_FORWARD_SETUP) || + (cmd == RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES) || + (cmd == RAMROD_CMD_ID_ETH_FILTER_RULES) || + (cmd == RAMROD_CMD_ID_ETH_MULTICAST_RULES) || +@@ -4326,12 +4377,13 @@ static inline void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp) + static inline struct bnx2x_queue_sp_obj *bnx2x_cid_to_q_obj( + struct bnx2x *bp, u32 cid) + { ++ DP(BNX2X_MSG_SP, "retrieving fp from cid %d", cid); + #ifdef BCM_CNIC + if (cid == BNX2X_FCOE_ETH_CID) + return &bnx2x_fcoe(bp, q_obj); + else + #endif +- return &bnx2x_fp(bp, cid, q_obj); ++ return &bnx2x_fp(bp, CID_TO_FP(cid), q_obj); + } + + static void bnx2x_eq_int(struct bnx2x *bp) +@@ -4578,6 +4630,7 @@ void bnx2x_drv_pulse(struct bnx2x *bp) + + static void bnx2x_timer(unsigned long data) + { ++ u8 cos; + struct bnx2x *bp = (struct bnx2x *) data; + + if (!netif_running(bp->dev)) +@@ -4586,7 +4639,8 @@ static void bnx2x_timer(unsigned long data) + if (poll) { + struct bnx2x_fastpath *fp = &bp->fp[0]; + +- bnx2x_tx_int(fp); ++ for_each_cos_in_tx_queue(fp, cos) ++ bnx2x_tx_int(bp, &fp->txdata[cos]); + bnx2x_rx_int(fp, 1000); + } + +@@ -4791,10 +4845,17 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, + static void bnx2x_update_coalesce_sb(struct bnx2x *bp, u8 fw_sb_id, + u16 tx_usec, u16 rx_usec) + { +- bnx2x_update_coalesce_sb_index(bp, fw_sb_id, U_SB_ETH_RX_CQ_INDEX, ++ bnx2x_update_coalesce_sb_index(bp, fw_sb_id, HC_INDEX_ETH_RX_CQ_CONS, + false, rx_usec); +- bnx2x_update_coalesce_sb_index(bp, fw_sb_id, C_SB_ETH_TX_CQ_INDEX, +- false, tx_usec); ++ bnx2x_update_coalesce_sb_index(bp, fw_sb_id, ++ HC_INDEX_ETH_TX_CQ_CONS_COS0, false, ++ tx_usec); ++ bnx2x_update_coalesce_sb_index(bp, fw_sb_id, ++ HC_INDEX_ETH_TX_CQ_CONS_COS1, false, ++ tx_usec); ++ bnx2x_update_coalesce_sb_index(bp, fw_sb_id, ++ HC_INDEX_ETH_TX_CQ_CONS_COS2, false, ++ tx_usec); + } + + static void bnx2x_init_def_sb(struct bnx2x *bp) +@@ -5091,12 +5152,12 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code) + + static inline u8 bnx2x_fp_igu_sb_id(struct bnx2x_fastpath *fp) + { +- return fp->bp->igu_base_sb + fp->index + CNIC_CONTEXT_USE; ++ return fp->bp->igu_base_sb + fp->index + CNIC_PRESENT; + } + + static inline u8 bnx2x_fp_fw_sb_id(struct bnx2x_fastpath *fp) + { +- return fp->bp->base_fw_ndsb + fp->index + CNIC_CONTEXT_USE; ++ return fp->bp->base_fw_ndsb + fp->index + CNIC_PRESENT; + } + + static inline u8 bnx2x_fp_cl_id(struct bnx2x_fastpath *fp) +@@ -5107,10 +5168,12 @@ static inline u8 bnx2x_fp_cl_id(struct bnx2x_fastpath *fp) + return bnx2x_fp_igu_sb_id(fp); + } + +-static void bnx2x_init_fp(struct bnx2x *bp, int fp_idx) ++static void bnx2x_init_eth_fp(struct bnx2x *bp, int fp_idx) + { + struct bnx2x_fastpath *fp = &bp->fp[fp_idx]; ++ u8 cos; + unsigned long q_type = 0; ++ u32 cids[BNX2X_MULTI_TX_COS] = { 0 }; + + fp->cid = fp_idx; + fp->cl_id = bnx2x_fp_cl_id(fp); +@@ -5123,14 +5186,25 @@ static void bnx2x_init_fp(struct bnx2x *bp, int fp_idx) + fp->ustorm_rx_prods_offset = bnx2x_rx_ustorm_prods_offset(fp); + /* Setup SB indicies */ + fp->rx_cons_sb = BNX2X_RX_SB_INDEX; +- fp->tx_cons_sb = BNX2X_TX_SB_INDEX; + + /* Configure Queue State object */ + __set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type); + __set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type); +- bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, fp->cid, BP_FUNC(bp), +- bnx2x_sp(bp, q_rdata), bnx2x_sp_mapping(bp, q_rdata), +- q_type); ++ ++ BUG_ON(fp->max_cos > BNX2X_MULTI_TX_COS); ++ ++ /* init tx data */ ++ for_each_cos_in_tx_queue(fp, cos) { ++ bnx2x_init_txdata(bp, &fp->txdata[cos], ++ CID_COS_TO_TX_ONLY_CID(fp->cid, cos), ++ FP_COS_TO_TXQ(fp, cos), ++ BNX2X_TX_SB_INDEX_BASE + cos); ++ cids[cos] = fp->txdata[cos].cid; ++ } ++ ++ bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, cids, fp->max_cos, ++ BP_FUNC(bp), bnx2x_sp(bp, q_rdata), ++ bnx2x_sp_mapping(bp, q_rdata), q_type); + + /** + * Configure classification DBs: Always enable Tx switching +@@ -5152,7 +5226,7 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code) + int i; + + for_each_eth_queue(bp, i) +- bnx2x_init_fp(bp, i); ++ bnx2x_init_eth_fp(bp, i); + #ifdef BCM_CNIC + if (!NO_FCOE(bp)) + bnx2x_init_fcoe_fp(bp); +@@ -6774,7 +6848,7 @@ int bnx2x_alloc_mem(struct bnx2x *bp) + if (bnx2x_alloc_fw_stats_mem(bp)) + goto alloc_mem_err; + +- bp->context.size = sizeof(union cdu_context) * bp->l2_cid_count; ++ bp->context.size = sizeof(union cdu_context) * BNX2X_L2_CID_COUNT(bp); + + BNX2X_PCI_ALLOC(bp->context.vcxt, &bp->context.cxt_mapping, + bp->context.size); +@@ -6892,7 +6966,7 @@ static void __devinit bnx2x_set_int_mode(struct bnx2x *bp) + bnx2x_enable_msi(bp); + /* falling through... */ + case INT_MODE_INTx: +- bp->num_queues = 1 + NONE_ETH_CONTEXT_USE; ++ bp->num_queues = 1 + NON_ETH_CONTEXT_USE; + DP(NETIF_MSG_IFUP, "set number of queues to 1\n"); + break; + default: +@@ -6914,8 +6988,8 @@ static void __devinit bnx2x_set_int_mode(struct bnx2x *bp) + "enable MSI-X (%d), " + "set number of queues to %d\n", + bp->num_queues, +- 1 + NONE_ETH_CONTEXT_USE); +- bp->num_queues = 1 + NONE_ETH_CONTEXT_USE; ++ 1 + NON_ETH_CONTEXT_USE); ++ bp->num_queues = 1 + NON_ETH_CONTEXT_USE; + + /* Try to enable MSI */ + if (!(bp->flags & DISABLE_MSI_FLAG)) +@@ -7043,6 +7117,8 @@ void bnx2x_ilt_set_info(struct bnx2x *bp) + static inline void bnx2x_pf_q_prep_init(struct bnx2x *bp, + struct bnx2x_fastpath *fp, struct bnx2x_queue_init_params *init_params) + { ++ ++ u8 cos; + /* FCoE Queue uses Default SB, thus has no HC capabilities */ + if (!IS_FCOE_FP(fp)) { + __set_bit(BNX2X_Q_FLG_HC, &init_params->rx.flags); +@@ -7068,13 +7144,56 @@ static inline void bnx2x_pf_q_prep_init(struct bnx2x *bp, + * CQ index among the SB indices: FCoE clients uses the default + * SB, therefore it's different. + */ +- init_params->rx.sb_cq_index = U_SB_ETH_RX_CQ_INDEX; +- init_params->tx.sb_cq_index = C_SB_ETH_TX_CQ_INDEX; ++ init_params->rx.sb_cq_index = HC_INDEX_ETH_RX_CQ_CONS; ++ init_params->tx.sb_cq_index = HC_INDEX_ETH_FIRST_TX_CQ_CONS; + } + +- init_params->cxt = &bp->context.vcxt[fp->cid].eth; ++ /* set maximum number of COSs supported by this queue */ ++ init_params->max_cos = fp->max_cos; ++ ++ DP(BNX2X_MSG_SP, "fp: %d setting queue params max cos to: %d", ++ fp->index, init_params->max_cos); ++ ++ /* set the context pointers queue object */ ++ for (cos = FIRST_TX_COS_INDEX; cos < init_params->max_cos; cos++) ++ init_params->cxts[cos] = ++ &bp->context.vcxt[fp->txdata[cos].cid].eth; ++} ++ ++int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp, ++ struct bnx2x_queue_state_params *q_params, ++ struct bnx2x_queue_setup_tx_only_params *tx_only_params, ++ int tx_index, bool leading) ++{ ++ memset(tx_only_params, 0, sizeof(*tx_only_params)); ++ ++ /* Set the command */ ++ q_params->cmd = BNX2X_Q_CMD_SETUP_TX_ONLY; ++ ++ /* Set tx-only QUEUE flags: don't zero statistics */ ++ tx_only_params->flags = bnx2x_get_common_flags(bp, fp, false); ++ ++ /* choose the index of the cid to send the slow path on */ ++ tx_only_params->cid_index = tx_index; ++ ++ /* Set general TX_ONLY_SETUP parameters */ ++ bnx2x_pf_q_prep_general(bp, fp, &tx_only_params->gen_params, tx_index); ++ ++ /* Set Tx TX_ONLY_SETUP parameters */ ++ bnx2x_pf_tx_q_prep(bp, fp, &tx_only_params->txq_params, tx_index); ++ ++ DP(BNX2X_MSG_SP, "preparing to send tx-only ramrod for connection:" ++ "cos %d, primary cid %d, cid %d, " ++ "client id %d, sp-client id %d, flags %lx", ++ tx_index, q_params->q_obj->cids[FIRST_TX_COS_INDEX], ++ q_params->q_obj->cids[tx_index], q_params->q_obj->cl_id, ++ tx_only_params->gen_params.spcl_id, tx_only_params->flags); ++ ++ /* send the ramrod */ ++ return bnx2x_queue_state_change(bp, q_params); + } + ++ + /** + * bnx2x_setup_queue - setup queue + * +@@ -7092,7 +7211,12 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp, + struct bnx2x_queue_state_params q_params = {0}; + struct bnx2x_queue_setup_params *setup_params = + &q_params.params.setup; ++ struct bnx2x_queue_setup_tx_only_params *tx_only_params = ++ &q_params.params.tx_only; + int rc; ++ u8 tx_index; ++ ++ DP(BNX2X_MSG_SP, "setting up queue %d", fp->index); + + /* reset IGU state skip FCoE L2 queue */ + if (!IS_FCOE_FP(fp)) +@@ -7112,10 +7236,13 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp, + /* Change the state to INIT */ + rc = bnx2x_queue_state_change(bp, &q_params); + if (rc) { +- BNX2X_ERR("Queue INIT failed\n"); ++ BNX2X_ERR("Queue(%d) INIT failed\n", fp->index); + return rc; + } + ++ DP(BNX2X_MSG_SP, "init complete"); ++ ++ + /* Now move the Queue to the SETUP state... */ + memset(setup_params, 0, sizeof(*setup_params)); + +@@ -7123,20 +7250,39 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp, + setup_params->flags = bnx2x_get_q_flags(bp, fp, leading); + + /* Set general SETUP parameters */ +- bnx2x_pf_q_prep_general(bp, fp, &setup_params->gen_params); ++ bnx2x_pf_q_prep_general(bp, fp, &setup_params->gen_params, ++ FIRST_TX_COS_INDEX); + +- bnx2x_pf_rx_q_prep(bp, fp, &setup_params->pause, ++ bnx2x_pf_rx_q_prep(bp, fp, &setup_params->pause_params, + &setup_params->rxq_params); + +- bnx2x_pf_tx_q_prep(bp, fp, &setup_params->txq_params); ++ bnx2x_pf_tx_q_prep(bp, fp, &setup_params->txq_params, ++ FIRST_TX_COS_INDEX); + + /* Set the command */ + q_params.cmd = BNX2X_Q_CMD_SETUP; + + /* Change the state to SETUP */ + rc = bnx2x_queue_state_change(bp, &q_params); +- if (rc) +- BNX2X_ERR("Queue SETUP failed\n"); ++ if (rc) { ++ BNX2X_ERR("Queue(%d) SETUP failed\n", fp->index); ++ return rc; ++ } ++ ++ /* loop through the relevant tx-only indices */ ++ for (tx_index = FIRST_TX_ONLY_COS_INDEX; ++ tx_index < fp->max_cos; ++ tx_index++) { ++ ++ /* prepare and send tx-only ramrod*/ ++ rc = bnx2x_setup_tx_only(bp, fp, &q_params, ++ tx_only_params, tx_index, leading); ++ if (rc) { ++ BNX2X_ERR("Queue(%d.%d) TX_ONLY_SETUP failed\n", ++ fp->index, tx_index); ++ return rc; ++ } ++ } + + return rc; + } +@@ -7144,27 +7290,67 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp, + static int bnx2x_stop_queue(struct bnx2x *bp, int index) + { + struct bnx2x_fastpath *fp = &bp->fp[index]; ++ struct bnx2x_fp_txdata *txdata; + struct bnx2x_queue_state_params q_params = {0}; +- int rc; ++ int rc, tx_index; ++ ++ DP(BNX2X_MSG_SP, "stopping queue %d cid %d", index, fp->cid); + + q_params.q_obj = &fp->q_obj; + /* We want to wait for completion in this context */ + __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags); + +- /* halt the connection */ ++ ++ /* close tx-only connections */ ++ for (tx_index = FIRST_TX_ONLY_COS_INDEX; ++ tx_index < fp->max_cos; ++ tx_index++){ ++ ++ /* ascertain this is a normal queue*/ ++ txdata = &fp->txdata[tx_index]; ++ ++ DP(BNX2X_MSG_SP, "stopping tx-only queue %d", ++ txdata->txq_index); ++ ++ /* send halt terminate on tx-only connection */ ++ q_params.cmd = BNX2X_Q_CMD_TERMINATE; ++ memset(&q_params.params.terminate, 0, ++ sizeof(q_params.params.terminate)); ++ q_params.params.terminate.cid_index = tx_index; ++ ++ rc = bnx2x_queue_state_change(bp, &q_params); ++ if (rc) ++ return rc; ++ ++ /* send halt terminate on tx-only connection */ ++ q_params.cmd = BNX2X_Q_CMD_CFC_DEL; ++ memset(&q_params.params.cfc_del, 0, ++ sizeof(q_params.params.cfc_del)); ++ q_params.params.cfc_del.cid_index = tx_index; ++ rc = bnx2x_queue_state_change(bp, &q_params); ++ if (rc) ++ return rc; ++ } ++ /* Stop the primary connection: */ ++ /* ...halt the connection */ + q_params.cmd = BNX2X_Q_CMD_HALT; + rc = bnx2x_queue_state_change(bp, &q_params); + if (rc) + return rc; + +- /* terminate the connection */ ++ /* ...terminate the connection */ + q_params.cmd = BNX2X_Q_CMD_TERMINATE; ++ memset(&q_params.params.terminate, 0, ++ sizeof(q_params.params.terminate)); ++ q_params.params.terminate.cid_index = FIRST_TX_COS_INDEX; + rc = bnx2x_queue_state_change(bp, &q_params); + if (rc) + return rc; +- +- /* delete cfc entry */ ++ /* ...delete cfc entry */ + q_params.cmd = BNX2X_Q_CMD_CFC_DEL; ++ memset(&q_params.params.cfc_del, 0, ++ sizeof(q_params.params.cfc_del)); ++ q_params.params.cfc_del.cid_index = FIRST_TX_COS_INDEX; + return bnx2x_queue_state_change(bp, &q_params); + } + +@@ -7185,8 +7371,8 @@ static void bnx2x_reset_func(struct bnx2x *bp) + for_each_eth_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + REG_WR8(bp, BAR_CSTRORM_INTMEM + +- CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(fp->fw_sb_id), +- SB_DISABLED); ++ CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(fp->fw_sb_id), ++ SB_DISABLED); + } + + #ifdef BCM_CNIC +@@ -7197,8 +7383,8 @@ static void bnx2x_reset_func(struct bnx2x *bp) + #endif + /* SP SB */ + REG_WR8(bp, BAR_CSTRORM_INTMEM + +- CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(func), +- SB_DISABLED); ++ CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(func), ++ SB_DISABLED); + + for (i = 0; i < XSTORM_SPQ_DATA_SIZE / 4; i++) + REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_DATA_OFFSET(func), +@@ -7407,7 +7593,8 @@ void bnx2x_send_unload_done(struct bnx2x *bp) + void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) + { + int port = BP_PORT(bp); +- int i, rc; ++ int i, rc = 0; ++ u8 cos; + struct bnx2x_mcast_ramrod_params rparam = {0}; + u32 reset_code; + +@@ -7415,7 +7602,8 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) + for_each_tx_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + +- rc = bnx2x_clean_tx_queue(bp, fp); ++ for_each_cos_in_tx_queue(fp, cos) ++ rc = bnx2x_clean_tx_queue(bp, &fp->txdata[cos]); + #ifdef BNX2X_STOP_ON_ERROR + if (rc) + return; +@@ -7965,7 +8153,7 @@ static inline void bnx2x_recovery_failed(struct bnx2x *bp) + + /* + * Assumption: runs under rtnl lock. This together with the fact +- * that it's called only from bnx2x_reset_task() ensure that it ++ * that it's called only from bnx2x_sp_rtnl() ensure that it + * will never be called when netif_running(bp->dev) is false. + */ + static void bnx2x_parity_recover(struct bnx2x *bp) +@@ -8464,14 +8652,11 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp) + int vn = BP_E1HVN(bp); + int igu_sb_id; + u32 val; +- u8 fid; ++ u8 fid, igu_sb_cnt = 0; + + bp->igu_base_sb = 0xff; +- bp->igu_sb_cnt = 0; + if (CHIP_INT_MODE_IS_BC(bp)) { +- bp->igu_sb_cnt = min_t(u8, FP_SB_MAX_E1x, +- NUM_IGU_SB_REQUIRED(bp->l2_cid_count)); +- ++ igu_sb_cnt = bp->igu_sb_cnt; + bp->igu_base_sb = (CHIP_MODE_IS_4_PORT(bp) ? pfid : vn) * + FP_SB_MAX_E1x; + +@@ -8497,19 +8682,21 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp) + else { + if (bp->igu_base_sb == 0xff) + bp->igu_base_sb = igu_sb_id; +- bp->igu_sb_cnt++; ++ igu_sb_cnt++; + } + } + } + +- /* It's expected that number of CAM entries for this +- * functions is equal to the MSI-X table size (which was a +- * used during bp->l2_cid_count value calculation. +- * We want a harsh warning if these values are different! ++#ifdef CONFIG_PCI_MSI ++ /* ++ * It's expected that number of CAM entries for this functions is equal ++ * to the number evaluated based on the MSI-X table size. We want a ++ * harsh warning if these values are different! + */ +- WARN_ON(bp->igu_sb_cnt != NUM_IGU_SB_REQUIRED(bp->l2_cid_count)); ++ WARN_ON(bp->igu_sb_cnt != igu_sb_cnt); ++#endif + +- if (bp->igu_sb_cnt == 0) ++ if (igu_sb_cnt == 0) + BNX2X_ERR("CAM configuration error\n"); + } + +@@ -9091,13 +9278,14 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) + + bnx2x_get_common_hwinfo(bp); + ++ /* ++ * initialize IGU parameters ++ */ + if (CHIP_IS_E1x(bp)) { + bp->common.int_block = INT_BLOCK_HC; + + bp->igu_dsb_id = DEF_SB_IGU_ID; + bp->igu_base_sb = 0; +- bp->igu_sb_cnt = min_t(u8, FP_SB_MAX_E1x, +- NUM_IGU_SB_REQUIRED(bp->l2_cid_count)); + } else { + bp->common.int_block = INT_BLOCK_IGU; + val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION); +@@ -9326,10 +9514,8 @@ static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp) + SET_FLAGS(flags, MODE_E3); + if (CHIP_REV(bp) == CHIP_REV_Ax) + SET_FLAGS(flags, MODE_E3_A0); +- else {/*if (CHIP_REV(bp) == CHIP_REV_Bx)*/ +- SET_FLAGS(flags, MODE_E3_B0); +- SET_FLAGS(flags, MODE_COS_BC); +- } ++ else /*if (CHIP_REV(bp) == CHIP_REV_Bx)*/ ++ SET_FLAGS(flags, MODE_E3_B0 | MODE_COS3); + } + + if (IS_MF(bp)) { +@@ -9438,6 +9624,9 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) + bp->cnic_base_cl_id = FP_SB_MAX_E2; + #endif + ++ /* multiple tx priority */ ++ bp->max_cos = 1; ++ + return rc; + } + +@@ -9868,16 +10057,6 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, + goto err_out_release; + } + +- bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2), +- min_t(u64, BNX2X_DB_SIZE(bp), +- pci_resource_len(pdev, 2))); +- if (!bp->doorbells) { +- dev_err(&bp->pdev->dev, +- "Cannot map doorbell space, aborting\n"); +- rc = -ENOMEM; +- goto err_out_unmap; +- } +- + bnx2x_set_power_state(bp, PCI_D0); + + /* clean indirect addresses */ +@@ -9929,16 +10108,6 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, + + return 0; + +-err_out_unmap: +- if (bp->regview) { +- iounmap(bp->regview); +- bp->regview = NULL; +- } +- if (bp->doorbells) { +- iounmap(bp->doorbells); +- bp->doorbells = NULL; +- } +- + err_out_release: + if (atomic_read(&pdev->enable_cnt) == 1) + pci_release_regions(pdev); +@@ -10213,9 +10382,9 @@ void bnx2x__init_func_obj(struct bnx2x *bp) + } + + /* must be called after sriov-enable */ +-static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp, int l2_cid_count) ++static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp) + { +- int cid_count = L2_FP_COUNT(l2_cid_count); ++ int cid_count = BNX2X_L2_CID_COUNT(bp); + + #ifdef BCM_CNIC + cid_count += CNIC_CID_MAX; +@@ -10224,22 +10393,33 @@ static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp, int l2_cid_count) + } + + /** +- * bnx2x_pci_msix_table_size - get the size of the MSI-X table. ++ * bnx2x_get_num_none_def_sbs - return the number of none default SBs + * + * @dev: pci device + * + */ +-static inline int bnx2x_pci_msix_table_size(struct pci_dev *pdev) ++static inline int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev) + { + int pos; + u16 control; + + pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX); ++ ++ /* ++ * If MSI-X is not supported - return number of SBs needed to support ++ * one fast path queue: one FP queue + SB for CNIC ++ */ + if (!pos) +- return 0; ++ return 1 + CNIC_PRESENT; + ++ /* ++ * The value in the PCI configuration space is the index of the last ++ * entry, namely one less than the actual size of the table, which is ++ * exactly what we want to return from this function: number of all SBs ++ * without the default SB. ++ */ + pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &control); +- return (control & PCI_MSIX_FLAGS_QSIZE) + 1; ++ return control & PCI_MSIX_FLAGS_QSIZE; + } + + static int __devinit bnx2x_init_one(struct pci_dev *pdev, +@@ -10248,7 +10428,18 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, + struct net_device *dev = NULL; + struct bnx2x *bp; + int pcie_width, pcie_speed; +- int rc, cid_count; ++ int rc, max_non_def_sbs; ++ int rx_count, tx_count, rss_count; ++ /* ++ * An estimated maximum supported CoS number according to the chip ++ * version. ++ * We will try to roughly estimate the maximum number of CoSes this chip ++ * may support in order to minimize the memory allocated for Tx ++ * netdev_queue's. This number will be accurately calculated during the ++ * initialization of bp->max_cos based on the chip versions AND chip ++ * revision in the bnx2x_init_bp(). ++ */ ++ u8 max_cos_est = 1; + + switch (ent->driver_data) { + case BCM57710: +@@ -10262,20 +10453,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, + case BCM57810_MF: + case BCM57840: + case BCM57840_MF: +- /* The size requested for the MSI-X table corresponds to the +- * actual amount of avaliable IGU/HC status blocks. It includes +- * the default SB vector but we want cid_count to contain the +- * amount of only non-default SBs, that's what '-1' stands for. +- */ +- cid_count = bnx2x_pci_msix_table_size(pdev) - 1; +- +- /* do not allow initial cid_count grow above 16 +- * since Special CIDs starts from this number +- * use old FP_SB_MAX_E1x define for this matter +- */ +- cid_count = min_t(int, FP_SB_MAX_E1x, cid_count); +- +- WARN_ON(!cid_count); + break; + + default: +@@ -10284,26 +10461,44 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, + return -ENODEV; + } + +- cid_count += FCOE_CONTEXT_USE; ++ max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev); ++ ++ /* !!! FIXME !!! ++ * Do not allow the maximum SB count to grow above 16 ++ * since Special CIDs starts from 16*BNX2X_MULTI_TX_COS=48. ++ * We will use the FP_SB_MAX_E1x macro for this matter. ++ */ ++ max_non_def_sbs = min_t(int, FP_SB_MAX_E1x, max_non_def_sbs); ++ ++ WARN_ON(!max_non_def_sbs); ++ ++ /* Maximum number of RSS queues: one IGU SB goes to CNIC */ ++ rss_count = max_non_def_sbs - CNIC_PRESENT; ++ ++ /* Maximum number of netdev Rx queues: RSS + FCoE L2 */ ++ rx_count = rss_count + FCOE_PRESENT; ++ ++ /* ++ * Maximum number of netdev Tx queues: ++ * Maximum TSS queues * Maximum supported number of CoS + FCoE L2 ++ */ ++ tx_count = MAX_TXQS_PER_COS * max_cos_est + FCOE_PRESENT; + + /* dev zeroed in init_etherdev */ +- dev = alloc_etherdev_mq(sizeof(*bp), cid_count); ++ dev = alloc_etherdev_mq(sizeof(*bp), rx_count); + if (!dev) { + dev_err(&pdev->dev, "Cannot allocate net device\n"); + return -ENOMEM; + } + +- /* We don't need a Tx queue for a CNIC and an OOO Rx-only ring, +- * so update a cid_count after a netdev allocation. +- */ +- cid_count += CNIC_CONTEXT_USE; +- + bp = netdev_priv(dev); +- bp->msg_enable = debug; + +- pci_set_drvdata(pdev, dev); ++ DP(NETIF_MSG_DRV, "Allocated netdev with %d tx and %d rx queues\n", ++ tx_count, rx_count); + +- bp->l2_cid_count = cid_count; ++ bp->igu_sb_cnt = max_non_def_sbs; ++ bp->msg_enable = debug; ++ pci_set_drvdata(pdev, dev); + + rc = bnx2x_init_dev(pdev, dev, ent->driver_data); + if (rc < 0) { +@@ -10311,14 +10506,28 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, + return rc; + } + +- BNX2X_DEV_INFO("cid_count=%d\n", cid_count); ++ DP(NETIF_MSG_DRV, "max_non_def_sbs %d", max_non_def_sbs); + + rc = bnx2x_init_bp(bp); + if (rc) + goto init_one_exit; + ++ /* ++ * Map doorbels here as we need the real value of bp->max_cos which ++ * is initialized in bnx2x_init_bp(). ++ */ ++ bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2), ++ min_t(u64, BNX2X_DB_SIZE(bp), ++ pci_resource_len(pdev, 2))); ++ if (!bp->doorbells) { ++ dev_err(&bp->pdev->dev, ++ "Cannot map doorbell space, aborting\n"); ++ rc = -ENOMEM; ++ goto init_one_exit; ++ } ++ + /* calc qm_cid_count */ +- bp->qm_cid_count = bnx2x_set_qm_cid_count(bp, cid_count); ++ bp->qm_cid_count = bnx2x_set_qm_cid_count(bp); + + #ifdef BCM_CNIC + /* disable FCOE L2 queue for E1x*/ +diff --git a/drivers/net/bnx2x/bnx2x_sp.c b/drivers/net/bnx2x/bnx2x_sp.c +index 250f2d0..ce1efdb9 100644 +--- a/drivers/net/bnx2x/bnx2x_sp.c ++++ b/drivers/net/bnx2x/bnx2x_sp.c +@@ -4203,15 +4203,29 @@ static int bnx2x_queue_comp_cmd(struct bnx2x *bp, + + if (!test_and_clear_bit(cmd, &cur_pending)) { + BNX2X_ERR("Bad MC reply %d for queue %d in state %d " +- "pending 0x%lx, next_state %d\n", cmd, o->cid, ++ "pending 0x%lx, next_state %d\n", cmd, ++ o->cids[BNX2X_PRIMARY_CID_INDEX], + o->state, cur_pending, o->next_state); + return -EINVAL; + } + ++ if (o->next_tx_only >= o->max_cos) ++ /* >= becuase tx only must always be smaller than cos since the ++ * primary connection suports COS 0 ++ */ ++ BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d", ++ o->next_tx_only, o->max_cos); ++ + DP(BNX2X_MSG_SP, "Completing command %d for queue %d, " +- "setting state to %d\n", cmd, o->cid, o->next_state); ++ "setting state to %d\n", cmd, ++ o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_state); ++ ++ if (o->next_tx_only) /* print num tx-only if any exist */ ++ DP(BNX2X_MSG_SP, "primary cid %d: num tx-only cons %d", ++ o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_tx_only); + + o->state = o->next_state; ++ o->num_tx_only = o->next_tx_only; + o->next_state = BNX2X_Q_STATE_MAX; + + /* It's important that o->state and o->next_state are +@@ -4238,135 +4252,193 @@ static void bnx2x_q_fill_setup_data_e2(struct bnx2x *bp, + CLIENT_INIT_RX_DATA_TPA_EN_IPV6; + } + +-static void bnx2x_q_fill_setup_data_cmn(struct bnx2x *bp, +- struct bnx2x_queue_state_params *cmd_params, +- struct client_init_ramrod_data *data) +-{ +- struct bnx2x_queue_sp_obj *o = cmd_params->q_obj; +- struct bnx2x_queue_setup_params *params = &cmd_params->params.setup; +- +- +- /* general */ +- data->general.client_id = o->cl_id; +- +- if (test_bit(BNX2X_Q_FLG_STATS, ¶ms->flags)) { +- data->general.statistics_counter_id = +- params->gen_params.stat_id; +- data->general.statistics_en_flg = 1; +- data->general.statistics_zero_flg = +- test_bit(BNX2X_Q_FLG_ZERO_STATS, ¶ms->flags); ++static void bnx2x_q_fill_init_general_data(struct bnx2x *bp, ++ struct bnx2x_queue_sp_obj *o, ++ struct bnx2x_general_setup_params *params, ++ struct client_init_general_data *gen_data, ++ unsigned long *flags) ++{ ++ gen_data->client_id = o->cl_id; ++ ++ if (test_bit(BNX2X_Q_FLG_STATS, flags)) { ++ gen_data->statistics_counter_id = ++ params->stat_id; ++ gen_data->statistics_en_flg = 1; ++ gen_data->statistics_zero_flg = ++ test_bit(BNX2X_Q_FLG_ZERO_STATS, flags); + } else +- data->general.statistics_counter_id = ++ gen_data->statistics_counter_id = + DISABLE_STATISTIC_COUNTER_ID_VALUE; + +- data->general.is_fcoe_flg = test_bit(BNX2X_Q_FLG_FCOE, ¶ms->flags); +- data->general.activate_flg = test_bit(BNX2X_Q_FLG_ACTIVE, +- ¶ms->flags); +- data->general.sp_client_id = params->gen_params.spcl_id; +- data->general.mtu = cpu_to_le16(params->gen_params.mtu); +- data->general.func_id = o->func_id; ++ gen_data->is_fcoe_flg = test_bit(BNX2X_Q_FLG_FCOE, flags); ++ gen_data->activate_flg = test_bit(BNX2X_Q_FLG_ACTIVE, flags); ++ gen_data->sp_client_id = params->spcl_id; ++ gen_data->mtu = cpu_to_le16(params->mtu); ++ gen_data->func_id = o->func_id; + + +- data->general.cos = params->txq_params.cos; ++ gen_data->cos = params->cos; + +- data->general.traffic_type = +- test_bit(BNX2X_Q_FLG_FCOE, ¶ms->flags) ? ++ gen_data->traffic_type = ++ test_bit(BNX2X_Q_FLG_FCOE, flags) ? + LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW; + +- /* Rx data */ +- data->rx.tpa_en = test_bit(BNX2X_Q_FLG_TPA, ¶ms->flags) * ++ DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d", ++ gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg); ++} ++ ++static void bnx2x_q_fill_init_tx_data(struct bnx2x_queue_sp_obj *o, ++ struct bnx2x_txq_setup_params *params, ++ struct client_init_tx_data *tx_data, ++ unsigned long *flags) ++{ ++ tx_data->enforce_security_flg = ++ test_bit(BNX2X_Q_FLG_TX_SEC, flags); ++ tx_data->default_vlan = ++ cpu_to_le16(params->default_vlan); ++ tx_data->default_vlan_flg = ++ test_bit(BNX2X_Q_FLG_DEF_VLAN, flags); ++ tx_data->tx_switching_flg = ++ test_bit(BNX2X_Q_FLG_TX_SWITCH, flags); ++ tx_data->anti_spoofing_flg = ++ test_bit(BNX2X_Q_FLG_ANTI_SPOOF, flags); ++ tx_data->tx_status_block_id = params->fw_sb_id; ++ tx_data->tx_sb_index_number = params->sb_cq_index; ++ tx_data->tss_leading_client_id = params->tss_leading_cl_id; ++ ++ tx_data->tx_bd_page_base.lo = ++ cpu_to_le32(U64_LO(params->dscr_map)); ++ tx_data->tx_bd_page_base.hi = ++ cpu_to_le32(U64_HI(params->dscr_map)); ++ ++ /* Don't configure any Tx switching mode during queue SETUP */ ++ tx_data->state = 0; ++} ++ ++static void bnx2x_q_fill_init_pause_data(struct bnx2x_queue_sp_obj *o, ++ struct rxq_pause_params *params, ++ struct client_init_rx_data *rx_data) ++{ ++ /* flow control data */ ++ rx_data->cqe_pause_thr_low = cpu_to_le16(params->rcq_th_lo); ++ rx_data->cqe_pause_thr_high = cpu_to_le16(params->rcq_th_hi); ++ rx_data->bd_pause_thr_low = cpu_to_le16(params->bd_th_lo); ++ rx_data->bd_pause_thr_high = cpu_to_le16(params->bd_th_hi); ++ rx_data->sge_pause_thr_low = cpu_to_le16(params->sge_th_lo); ++ rx_data->sge_pause_thr_high = cpu_to_le16(params->sge_th_hi); ++ rx_data->rx_cos_mask = cpu_to_le16(params->pri_map); ++} ++ ++static void bnx2x_q_fill_init_rx_data(struct bnx2x_queue_sp_obj *o, ++ struct bnx2x_rxq_setup_params *params, ++ struct client_init_rx_data *rx_data, ++ unsigned long *flags) ++{ ++ /* Rx data */ ++ rx_data->tpa_en = test_bit(BNX2X_Q_FLG_TPA, flags) * + CLIENT_INIT_RX_DATA_TPA_EN_IPV4; +- data->rx.vmqueue_mode_en_flg = 0; ++ rx_data->vmqueue_mode_en_flg = 0; + +- data->rx.cache_line_alignment_log_size = +- params->rxq_params.cache_line_log; +- data->rx.enable_dynamic_hc = +- test_bit(BNX2X_Q_FLG_DHC, ¶ms->flags); +- data->rx.max_sges_for_packet = params->rxq_params.max_sges_pkt; +- data->rx.client_qzone_id = params->rxq_params.cl_qzone_id; +- data->rx.max_agg_size = cpu_to_le16(params->rxq_params.tpa_agg_sz); ++ rx_data->cache_line_alignment_log_size = ++ params->cache_line_log; ++ rx_data->enable_dynamic_hc = ++ test_bit(BNX2X_Q_FLG_DHC, flags); ++ rx_data->max_sges_for_packet = params->max_sges_pkt; ++ rx_data->client_qzone_id = params->cl_qzone_id; ++ rx_data->max_agg_size = cpu_to_le16(params->tpa_agg_sz); + + /* Always start in DROP_ALL mode */ +- data->rx.state = cpu_to_le16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL | ++ rx_data->state = cpu_to_le16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL | + CLIENT_INIT_RX_DATA_MCAST_DROP_ALL); + + /* We don't set drop flags */ +- data->rx.drop_ip_cs_err_flg = 0; +- data->rx.drop_tcp_cs_err_flg = 0; +- data->rx.drop_ttl0_flg = 0; +- data->rx.drop_udp_cs_err_flg = 0; +- data->rx.inner_vlan_removal_enable_flg = +- test_bit(BNX2X_Q_FLG_VLAN, ¶ms->flags); +- data->rx.outer_vlan_removal_enable_flg = +- test_bit(BNX2X_Q_FLG_OV, ¶ms->flags); +- data->rx.status_block_id = params->rxq_params.fw_sb_id; +- data->rx.rx_sb_index_number = params->rxq_params.sb_cq_index; +- data->rx.max_tpa_queues = params->rxq_params.max_tpa_queues; +- data->rx.max_bytes_on_bd = cpu_to_le16(params->rxq_params.buf_sz); +- data->rx.sge_buff_size = cpu_to_le16(params->rxq_params.sge_buf_sz); +- data->rx.bd_page_base.lo = +- cpu_to_le32(U64_LO(params->rxq_params.dscr_map)); +- data->rx.bd_page_base.hi = +- cpu_to_le32(U64_HI(params->rxq_params.dscr_map)); +- data->rx.sge_page_base.lo = +- cpu_to_le32(U64_LO(params->rxq_params.sge_map)); +- data->rx.sge_page_base.hi = +- cpu_to_le32(U64_HI(params->rxq_params.sge_map)); +- data->rx.cqe_page_base.lo = +- cpu_to_le32(U64_LO(params->rxq_params.rcq_map)); +- data->rx.cqe_page_base.hi = +- cpu_to_le32(U64_HI(params->rxq_params.rcq_map)); +- data->rx.is_leading_rss = test_bit(BNX2X_Q_FLG_LEADING_RSS, +- ¶ms->flags); +- +- if (test_bit(BNX2X_Q_FLG_MCAST, ¶ms->flags)) { +- data->rx.approx_mcast_engine_id = o->func_id; +- data->rx.is_approx_mcast = 1; ++ rx_data->drop_ip_cs_err_flg = 0; ++ rx_data->drop_tcp_cs_err_flg = 0; ++ rx_data->drop_ttl0_flg = 0; ++ rx_data->drop_udp_cs_err_flg = 0; ++ rx_data->inner_vlan_removal_enable_flg = ++ test_bit(BNX2X_Q_FLG_VLAN, flags); ++ rx_data->outer_vlan_removal_enable_flg = ++ test_bit(BNX2X_Q_FLG_OV, flags); ++ rx_data->status_block_id = params->fw_sb_id; ++ rx_data->rx_sb_index_number = params->sb_cq_index; ++ rx_data->max_tpa_queues = params->max_tpa_queues; ++ rx_data->max_bytes_on_bd = cpu_to_le16(params->buf_sz); ++ rx_data->sge_buff_size = cpu_to_le16(params->sge_buf_sz); ++ rx_data->bd_page_base.lo = ++ cpu_to_le32(U64_LO(params->dscr_map)); ++ rx_data->bd_page_base.hi = ++ cpu_to_le32(U64_HI(params->dscr_map)); ++ rx_data->sge_page_base.lo = ++ cpu_to_le32(U64_LO(params->sge_map)); ++ rx_data->sge_page_base.hi = ++ cpu_to_le32(U64_HI(params->sge_map)); ++ rx_data->cqe_page_base.lo = ++ cpu_to_le32(U64_LO(params->rcq_map)); ++ rx_data->cqe_page_base.hi = ++ cpu_to_le32(U64_HI(params->rcq_map)); ++ rx_data->is_leading_rss = test_bit(BNX2X_Q_FLG_LEADING_RSS, flags); ++ ++ if (test_bit(BNX2X_Q_FLG_MCAST, flags)) { ++ rx_data->approx_mcast_engine_id = o->func_id; ++ rx_data->is_approx_mcast = 1; + } + +- data->rx.rss_engine_id = params->rxq_params.rss_engine_id; +- +- /* flow control data */ +- data->rx.cqe_pause_thr_low = cpu_to_le16(params->pause.rcq_th_lo); +- data->rx.cqe_pause_thr_high = cpu_to_le16(params->pause.rcq_th_hi); +- data->rx.bd_pause_thr_low = cpu_to_le16(params->pause.bd_th_lo); +- data->rx.bd_pause_thr_high = cpu_to_le16(params->pause.bd_th_hi); +- data->rx.sge_pause_thr_low = cpu_to_le16(params->pause.sge_th_lo); +- data->rx.sge_pause_thr_high = cpu_to_le16(params->pause.sge_th_hi); +- data->rx.rx_cos_mask = cpu_to_le16(params->pause.pri_map); ++ rx_data->rss_engine_id = params->rss_engine_id; + + /* silent vlan removal */ +- data->rx.silent_vlan_removal_flg = +- test_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, ¶ms->flags); +- data->rx.silent_vlan_value = +- cpu_to_le16(params->rxq_params.silent_removal_value); +- data->rx.silent_vlan_mask = +- cpu_to_le16(params->rxq_params.silent_removal_mask); +- +- /* Tx data */ +- data->tx.enforce_security_flg = +- test_bit(BNX2X_Q_FLG_TX_SEC, ¶ms->flags); +- data->tx.default_vlan = +- cpu_to_le16(params->txq_params.default_vlan); +- data->tx.default_vlan_flg = +- test_bit(BNX2X_Q_FLG_DEF_VLAN, ¶ms->flags); +- data->tx.tx_switching_flg = +- test_bit(BNX2X_Q_FLG_TX_SWITCH, ¶ms->flags); +- data->tx.anti_spoofing_flg = +- test_bit(BNX2X_Q_FLG_ANTI_SPOOF, ¶ms->flags); +- data->tx.tx_status_block_id = params->txq_params.fw_sb_id; +- data->tx.tx_sb_index_number = params->txq_params.sb_cq_index; +- data->tx.tss_leading_client_id = params->txq_params.tss_leading_cl_id; +- +- data->tx.tx_bd_page_base.lo = +- cpu_to_le32(U64_LO(params->txq_params.dscr_map)); +- data->tx.tx_bd_page_base.hi = +- cpu_to_le32(U64_HI(params->txq_params.dscr_map)); ++ rx_data->silent_vlan_removal_flg = ++ test_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, flags); ++ rx_data->silent_vlan_value = ++ cpu_to_le16(params->silent_removal_value); ++ rx_data->silent_vlan_mask = ++ cpu_to_le16(params->silent_removal_mask); + +- /* Don't configure any Tx switching mode during queue SETUP */ +- data->tx.state = 0; + } + ++/* initialize the general, tx and rx parts of a queue object */ ++static void bnx2x_q_fill_setup_data_cmn(struct bnx2x *bp, ++ struct bnx2x_queue_state_params *cmd_params, ++ struct client_init_ramrod_data *data) ++{ ++ bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj, ++ &cmd_params->params.setup.gen_params, ++ &data->general, ++ &cmd_params->params.setup.flags); ++ ++ bnx2x_q_fill_init_tx_data(cmd_params->q_obj, ++ &cmd_params->params.setup.txq_params, ++ &data->tx, ++ &cmd_params->params.setup.flags); ++ ++ bnx2x_q_fill_init_rx_data(cmd_params->q_obj, ++ &cmd_params->params.setup.rxq_params, ++ &data->rx, ++ &cmd_params->params.setup.flags); ++ ++ bnx2x_q_fill_init_pause_data(cmd_params->q_obj, ++ &cmd_params->params.setup.pause_params, ++ &data->rx); ++} ++ ++/* initialize the general and tx parts of a tx-only queue object */ ++static void bnx2x_q_fill_setup_tx_only(struct bnx2x *bp, ++ struct bnx2x_queue_state_params *cmd_params, ++ struct tx_queue_init_ramrod_data *data) ++{ ++ bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj, ++ &cmd_params->params.tx_only.gen_params, ++ &data->general, ++ &cmd_params->params.tx_only.flags); ++ ++ bnx2x_q_fill_init_tx_data(cmd_params->q_obj, ++ &cmd_params->params.tx_only.txq_params, ++ &data->tx, ++ &cmd_params->params.tx_only.flags); ++ DP(BNX2X_MSG_SP, "cid %d, tx bd page lo %x hi %x", ++ cmd_params->q_obj->cids[0], ++ data->tx.tx_bd_page_base.lo, data->tx.tx_bd_page_base.hi); ++} + + /** + * bnx2x_q_init - init HW/FW queue +@@ -4385,6 +4457,7 @@ static inline int bnx2x_q_init(struct bnx2x *bp, + struct bnx2x_queue_sp_obj *o = params->q_obj; + struct bnx2x_queue_init_params *init = ¶ms->params.init; + u16 hc_usec; ++ u8 cos; + + /* Tx HC configuration */ + if (test_bit(BNX2X_Q_TYPE_HAS_TX, &o->type) && +@@ -4409,7 +4482,12 @@ static inline int bnx2x_q_init(struct bnx2x *bp, + } + + /* Set CDU context validation values */ +- bnx2x_set_ctx_validation(bp, init->cxt, o->cid); ++ for (cos = 0; cos < o->max_cos; cos++) { ++ DP(BNX2X_MSG_SP, "setting context validation. cid %d, cos %d", ++ o->cids[cos], cos); ++ DP(BNX2X_MSG_SP, "context pointer %p", init->cxts[cos]); ++ bnx2x_set_ctx_validation(bp, init->cxts[cos], o->cids[cos]); ++ } + + /* As no ramrod is sent, complete the command immediately */ + o->complete_cmd(bp, o, BNX2X_Q_CMD_INIT); +@@ -4437,7 +4515,8 @@ static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp, + + mb(); + +- return bnx2x_sp_post(bp, ramrod, o->cid, U64_HI(data_mapping), ++ return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX], ++ U64_HI(data_mapping), + U64_LO(data_mapping), ETH_CONNECTION_TYPE); + } + +@@ -4457,9 +4536,57 @@ static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp, + bnx2x_q_fill_setup_data_cmn(bp, params, rdata); + bnx2x_q_fill_setup_data_e2(bp, params, rdata); + +- mb(); + +- return bnx2x_sp_post(bp, ramrod, o->cid, U64_HI(data_mapping), ++ return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX], ++ U64_HI(data_mapping), ++ U64_LO(data_mapping), ETH_CONNECTION_TYPE); ++} ++ ++static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp, ++ struct bnx2x_queue_state_params *params) ++{ ++ struct bnx2x_queue_sp_obj *o = params->q_obj; ++ struct tx_queue_init_ramrod_data *rdata = ++ (struct tx_queue_init_ramrod_data *)o->rdata; ++ dma_addr_t data_mapping = o->rdata_mapping; ++ int ramrod = RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP; ++ struct bnx2x_queue_setup_tx_only_params *tx_only_params = ++ ¶ms->params.tx_only; ++ u8 cid_index = tx_only_params->cid_index; ++ ++ ++ if (cid_index >= o->max_cos) { ++ BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n", ++ o->cl_id, cid_index); ++ return -EINVAL; ++ } ++ ++ DP(BNX2X_MSG_SP, "parameters received: cos: %d sp-id: %d", ++ tx_only_params->gen_params.cos, ++ tx_only_params->gen_params.spcl_id); ++ ++ /* Clear the ramrod data */ ++ memset(rdata, 0, sizeof(*rdata)); ++ ++ /* Fill the ramrod data */ ++ bnx2x_q_fill_setup_tx_only(bp, params, rdata); ++ ++ DP(BNX2X_MSG_SP, "sending tx-only ramrod: cid %d, client-id %d," ++ "sp-client id %d, cos %d", ++ o->cids[cid_index], ++ rdata->general.client_id, ++ rdata->general.sp_client_id, rdata->general.cos); ++ ++ /* ++ * No need for an explicit memory barrier here as long we would ++ * need to ensure the ordering of writing to the SPQ element ++ * and updating of the SPQ producer which involves a memory ++ * read and we will have to put a full memory barrier there ++ * (inside bnx2x_sp_post()). ++ */ ++ ++ return bnx2x_sp_post(bp, ramrod, o->cids[cid_index], ++ U64_HI(data_mapping), + U64_LO(data_mapping), ETH_CONNECTION_TYPE); + } + +@@ -4529,17 +4656,27 @@ static inline int bnx2x_q_send_update(struct bnx2x *bp, + struct client_update_ramrod_data *rdata = + (struct client_update_ramrod_data *)o->rdata; + dma_addr_t data_mapping = o->rdata_mapping; ++ struct bnx2x_queue_update_params *update_params = ++ ¶ms->params.update; ++ u8 cid_index = update_params->cid_index; ++ ++ if (cid_index >= o->max_cos) { ++ BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n", ++ o->cl_id, cid_index); ++ return -EINVAL; ++ } ++ + + /* Clear the ramrod data */ + memset(rdata, 0, sizeof(*rdata)); + + /* Fill the ramrod data */ +- bnx2x_q_fill_update_data(bp, o, ¶ms->params.update, rdata); ++ bnx2x_q_fill_update_data(bp, o, update_params, rdata); + + mb(); + +- return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE, o->cid, +- U64_HI(data_mapping), ++ return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE, ++ o->cids[cid_index], U64_HI(data_mapping), + U64_LO(data_mapping), ETH_CONNECTION_TYPE); + } + +@@ -4596,7 +4733,8 @@ static inline int bnx2x_q_send_halt(struct bnx2x *bp, + { + struct bnx2x_queue_sp_obj *o = params->q_obj; + +- return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, o->cid, 0, o->cl_id, ++ return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, ++ o->cids[BNX2X_PRIMARY_CID_INDEX], 0, o->cl_id, + ETH_CONNECTION_TYPE); + } + +@@ -4604,18 +4742,32 @@ static inline int bnx2x_q_send_cfc_del(struct bnx2x *bp, + struct bnx2x_queue_state_params *params) + { + struct bnx2x_queue_sp_obj *o = params->q_obj; ++ u8 cid_idx = params->params.cfc_del.cid_index; + +- return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL, o->cid, 0, 0, +- NONE_CONNECTION_TYPE); ++ if (cid_idx >= o->max_cos) { ++ BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n", ++ o->cl_id, cid_idx); ++ return -EINVAL; ++ } ++ ++ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL, ++ o->cids[cid_idx], 0, 0, NONE_CONNECTION_TYPE); + } + + static inline int bnx2x_q_send_terminate(struct bnx2x *bp, + struct bnx2x_queue_state_params *params) + { + struct bnx2x_queue_sp_obj *o = params->q_obj; ++ u8 cid_index = params->params.terminate.cid_index; + +- return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE, o->cid, 0, 0, +- ETH_CONNECTION_TYPE); ++ if (cid_index >= o->max_cos) { ++ BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n", ++ o->cl_id, cid_index); ++ return -EINVAL; ++ } ++ ++ return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE, ++ o->cids[cid_index], 0, 0, ETH_CONNECTION_TYPE); + } + + static inline int bnx2x_q_send_empty(struct bnx2x *bp, +@@ -4623,7 +4775,8 @@ static inline int bnx2x_q_send_empty(struct bnx2x *bp, + { + struct bnx2x_queue_sp_obj *o = params->q_obj; + +- return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_EMPTY, o->cid, 0, 0, ++ return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_EMPTY, ++ o->cids[BNX2X_PRIMARY_CID_INDEX], 0, 0, + ETH_CONNECTION_TYPE); + } + +@@ -4633,6 +4786,8 @@ static inline int bnx2x_queue_send_cmd_cmn(struct bnx2x *bp, + switch (params->cmd) { + case BNX2X_Q_CMD_INIT: + return bnx2x_q_init(bp, params); ++ case BNX2X_Q_CMD_SETUP_TX_ONLY: ++ return bnx2x_q_send_setup_tx_only(bp, params); + case BNX2X_Q_CMD_DEACTIVATE: + return bnx2x_q_send_deactivate(bp, params); + case BNX2X_Q_CMD_ACTIVATE: +@@ -4662,6 +4817,7 @@ static int bnx2x_queue_send_cmd_e1x(struct bnx2x *bp, + case BNX2X_Q_CMD_SETUP: + return bnx2x_q_send_setup_e1x(bp, params); + case BNX2X_Q_CMD_INIT: ++ case BNX2X_Q_CMD_SETUP_TX_ONLY: + case BNX2X_Q_CMD_DEACTIVATE: + case BNX2X_Q_CMD_ACTIVATE: + case BNX2X_Q_CMD_UPDATE: +@@ -4684,6 +4840,7 @@ static int bnx2x_queue_send_cmd_e2(struct bnx2x *bp, + case BNX2X_Q_CMD_SETUP: + return bnx2x_q_send_setup_e2(bp, params); + case BNX2X_Q_CMD_INIT: ++ case BNX2X_Q_CMD_SETUP_TX_ONLY: + case BNX2X_Q_CMD_DEACTIVATE: + case BNX2X_Q_CMD_ACTIVATE: + case BNX2X_Q_CMD_UPDATE: +@@ -4721,6 +4878,9 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, + { + enum bnx2x_q_state state = o->state, next_state = BNX2X_Q_STATE_MAX; + enum bnx2x_queue_cmd cmd = params->cmd; ++ struct bnx2x_queue_update_params *update_params = ++ ¶ms->params.update; ++ u8 next_tx_only = o->num_tx_only; + + switch (state) { + case BNX2X_Q_STATE_RESET: +@@ -4746,13 +4906,42 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, + (cmd == BNX2X_Q_CMD_UPDATE_TPA)) + next_state = BNX2X_Q_STATE_ACTIVE; + ++ else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) { ++ next_state = BNX2X_Q_STATE_MULTI_COS; ++ next_tx_only = 1; ++ } ++ + else if (cmd == BNX2X_Q_CMD_HALT) + next_state = BNX2X_Q_STATE_STOPPED; + + else if (cmd == BNX2X_Q_CMD_UPDATE) { +- struct bnx2x_queue_update_params *update_params = +- ¶ms->params.update; ++ /* If "active" state change is requested, update the ++ * state accordingly. ++ */ ++ if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, ++ &update_params->update_flags) && ++ !test_bit(BNX2X_Q_UPDATE_ACTIVATE, ++ &update_params->update_flags)) ++ next_state = BNX2X_Q_STATE_INACTIVE; ++ else ++ next_state = BNX2X_Q_STATE_ACTIVE; ++ } ++ ++ break; ++ case BNX2X_Q_STATE_MULTI_COS: ++ if (cmd == BNX2X_Q_CMD_TERMINATE) ++ next_state = BNX2X_Q_STATE_MCOS_TERMINATED; ++ ++ else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) { ++ next_state = BNX2X_Q_STATE_MULTI_COS; ++ next_tx_only = o->num_tx_only + 1; ++ } ++ ++ else if ((cmd == BNX2X_Q_CMD_EMPTY) || ++ (cmd == BNX2X_Q_CMD_UPDATE_TPA)) ++ next_state = BNX2X_Q_STATE_MULTI_COS; + ++ else if (cmd == BNX2X_Q_CMD_UPDATE) { + /* If "active" state change is requested, update the + * state accordingly. + */ +@@ -4762,7 +4951,17 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, + &update_params->update_flags)) + next_state = BNX2X_Q_STATE_INACTIVE; + else ++ next_state = BNX2X_Q_STATE_MULTI_COS; ++ } ++ ++ break; ++ case BNX2X_Q_STATE_MCOS_TERMINATED: ++ if (cmd == BNX2X_Q_CMD_CFC_DEL) { ++ next_tx_only = o->num_tx_only - 1; ++ if (next_tx_only == 0) + next_state = BNX2X_Q_STATE_ACTIVE; ++ else ++ next_state = BNX2X_Q_STATE_MULTI_COS; + } + + break; +@@ -4778,18 +4977,18 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, + next_state = BNX2X_Q_STATE_STOPPED; + + else if (cmd == BNX2X_Q_CMD_UPDATE) { +- struct bnx2x_queue_update_params *update_params = +- ¶ms->params.update; +- + /* If "active" state change is requested, update the + * state accordingly. + */ + if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, + &update_params->update_flags) && + test_bit(BNX2X_Q_UPDATE_ACTIVATE, +- &update_params->update_flags)) +- next_state = BNX2X_Q_STATE_ACTIVE; +- else ++ &update_params->update_flags)){ ++ if (o->num_tx_only == 0) ++ next_state = BNX2X_Q_STATE_ACTIVE; ++ else /* tx only queues exist for this queue */ ++ next_state = BNX2X_Q_STATE_MULTI_COS; ++ } else + next_state = BNX2X_Q_STATE_INACTIVE; + } + +@@ -4813,6 +5012,7 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, + DP(BNX2X_MSG_SP, "Good state transition: %d(%d)->%d\n", + state, cmd, next_state); + o->next_state = next_state; ++ o->next_tx_only = next_tx_only; + return 0; + } + +@@ -4823,12 +5023,17 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, + + void bnx2x_init_queue_obj(struct bnx2x *bp, + struct bnx2x_queue_sp_obj *obj, +- u8 cl_id, u32 cid, u8 func_id, void *rdata, ++ u8 cl_id, u32 *cids, u8 cid_cnt, u8 func_id, ++ void *rdata, + dma_addr_t rdata_mapping, unsigned long type) + { + memset(obj, 0, sizeof(*obj)); + +- obj->cid = cid; ++ /* We support only BNX2X_MULTI_TX_COS Tx CoS at the moment */ ++ BUG_ON(BNX2X_MULTI_TX_COS < cid_cnt); ++ ++ memcpy(obj->cids, cids, sizeof(obj->cids[0]) * cid_cnt); ++ obj->max_cos = cid_cnt; + obj->cl_id = cl_id; + obj->func_id = func_id; + obj->rdata = rdata; +@@ -4848,6 +5053,13 @@ void bnx2x_init_queue_obj(struct bnx2x *bp, + obj->set_pending = bnx2x_queue_set_pending; + } + ++void bnx2x_queue_set_cos_cid(struct bnx2x *bp, ++ struct bnx2x_queue_sp_obj *obj, ++ u32 cid, u8 index) ++{ ++ obj->cids[index] = cid; ++} ++ + /********************** Function state object *********************************/ + + static int bnx2x_func_wait_comp(struct bnx2x *bp, +diff --git a/drivers/net/bnx2x/bnx2x_sp.h b/drivers/net/bnx2x/bnx2x_sp.h +index 86eaa80..83f3b0b 100644 +--- a/drivers/net/bnx2x/bnx2x_sp.h ++++ b/drivers/net/bnx2x/bnx2x_sp.h +@@ -721,6 +721,8 @@ enum bnx2x_q_state { + BNX2X_Q_STATE_RESET, + BNX2X_Q_STATE_INITIALIZED, + BNX2X_Q_STATE_ACTIVE, ++ BNX2X_Q_STATE_MULTI_COS, ++ BNX2X_Q_STATE_MCOS_TERMINATED, + BNX2X_Q_STATE_INACTIVE, + BNX2X_Q_STATE_STOPPED, + BNX2X_Q_STATE_TERMINATED, +@@ -732,6 +734,7 @@ enum bnx2x_q_state { + enum bnx2x_queue_cmd { + BNX2X_Q_CMD_INIT, + BNX2X_Q_CMD_SETUP, ++ BNX2X_Q_CMD_SETUP_TX_ONLY, + BNX2X_Q_CMD_DEACTIVATE, + BNX2X_Q_CMD_ACTIVATE, + BNX2X_Q_CMD_UPDATE, +@@ -774,6 +777,13 @@ enum bnx2x_q_type { + BNX2X_Q_TYPE_HAS_TX, + }; + ++#define BNX2X_PRIMARY_CID_INDEX 0 ++#define BNX2X_MULTI_TX_COS_E1X 1 ++#define BNX2X_MULTI_TX_COS_E2_E3A0 2 ++#define BNX2X_MULTI_TX_COS_E3B0 3 ++#define BNX2X_MULTI_TX_COS BNX2X_MULTI_TX_COS_E3B0 ++ ++ + struct bnx2x_queue_init_params { + struct { + unsigned long flags; +@@ -790,7 +800,20 @@ struct bnx2x_queue_init_params { + } rx; + + /* CID context in the host memory */ +- struct eth_context *cxt; ++ struct eth_context *cxts[BNX2X_MULTI_TX_COS]; ++ ++ /* maximum number of cos supported by hardware */ ++ u8 max_cos; ++}; ++ ++struct bnx2x_queue_terminate_params { ++ /* index within the tx_only cids of this queue object */ ++ u8 cid_index; ++}; ++ ++struct bnx2x_queue_cfc_del_params { ++ /* index within the tx_only cids of this queue object */ ++ u8 cid_index; + }; + + struct bnx2x_queue_update_params { +@@ -798,6 +821,8 @@ struct bnx2x_queue_update_params { + u16 def_vlan; + u16 silent_removal_value; + u16 silent_removal_mask; ++/* index within the tx_only cids of this queue object */ ++ u8 cid_index; + }; + + struct rxq_pause_params { +@@ -817,6 +842,7 @@ struct bnx2x_general_setup_params { + + u8 spcl_id; + u16 mtu; ++ u8 cos; + }; + + struct bnx2x_rxq_setup_params { +@@ -863,13 +889,20 @@ struct bnx2x_txq_setup_params { + }; + + struct bnx2x_queue_setup_params { +- struct rxq_pause_params pause; + struct bnx2x_general_setup_params gen_params; +- struct bnx2x_rxq_setup_params rxq_params; + struct bnx2x_txq_setup_params txq_params; ++ struct bnx2x_rxq_setup_params rxq_params; ++ struct rxq_pause_params pause_params; + unsigned long flags; + }; + ++struct bnx2x_queue_setup_tx_only_params { ++ struct bnx2x_general_setup_params gen_params; ++ struct bnx2x_txq_setup_params txq_params; ++ unsigned long flags; ++ /* index within the tx_only cids of this queue object */ ++ u8 cid_index; ++}; + + struct bnx2x_queue_state_params { + struct bnx2x_queue_sp_obj *q_obj; +@@ -878,21 +911,36 @@ struct bnx2x_queue_state_params { + enum bnx2x_queue_cmd cmd; + + /* may have RAMROD_COMP_WAIT set only */ +- unsigned long ramrod_flags; ++ unsigned long ramrod_flags; + + /* Params according to the current command */ + union { +- struct bnx2x_queue_update_params update; +- struct bnx2x_queue_setup_params setup; +- struct bnx2x_queue_init_params init; ++ struct bnx2x_queue_update_params update; ++ struct bnx2x_queue_setup_params setup; ++ struct bnx2x_queue_init_params init; ++ struct bnx2x_queue_setup_tx_only_params tx_only; ++ struct bnx2x_queue_terminate_params terminate; ++ struct bnx2x_queue_cfc_del_params cfc_del; + } params; + }; + + struct bnx2x_queue_sp_obj { +- u32 cid; ++ u32 cids[BNX2X_MULTI_TX_COS]; + u8 cl_id; + u8 func_id; + ++ /* ++ * number of traffic classes supported by queue. ++ * The primary connection of the queue suppotrs the first traffic ++ * class. Any further traffic class is suppoted by a tx-only ++ * connection. ++ * ++ * Therefore max_cos is also a number of valid entries in the cids ++ * array. ++ */ ++ u8 max_cos; ++ u8 num_tx_only, next_tx_only; ++ + enum bnx2x_q_state state, next_state; + + /* bits from enum bnx2x_q_type */ +@@ -1106,9 +1154,9 @@ int bnx2x_func_state_change(struct bnx2x *bp, + + /******************* Queue State **************/ + void bnx2x_init_queue_obj(struct bnx2x *bp, +- struct bnx2x_queue_sp_obj *obj, u8 cl_id, u32 cid, +- u8 func_id, void *rdata, dma_addr_t rdata_mapping, +- unsigned long type); ++ struct bnx2x_queue_sp_obj *obj, u8 cl_id, u32 *cids, ++ u8 cid_cnt, u8 func_id, void *rdata, ++ dma_addr_t rdata_mapping, unsigned long type); + + int bnx2x_queue_state_change(struct bnx2x *bp, + struct bnx2x_queue_state_params *params); +diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/bnx2x/bnx2x_stats.c +index 54c07f5..771f680 100644 +--- a/drivers/net/bnx2x/bnx2x_stats.c ++++ b/drivers/net/bnx2x/bnx2x_stats.c +@@ -1185,7 +1185,7 @@ static void bnx2x_stats_update(struct bnx2x *bp) + + if (netif_msg_timer(bp)) { + struct bnx2x_eth_stats *estats = &bp->eth_stats; +- int i; ++ int i, cos; + + netdev_dbg(bp->dev, "brb drops %u brb truncate %u\n", + estats->brb_drop_lo, estats->brb_truncate_lo); +@@ -1206,20 +1206,32 @@ static void bnx2x_stats_update(struct bnx2x *bp) + + for_each_eth_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; ++ struct bnx2x_fp_txdata *txdata; + struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats; +- struct netdev_queue *txq = +- netdev_get_tx_queue(bp->dev, i); +- +- printk(KERN_DEBUG "%s: tx avail(%4u) *tx_cons_sb(%u)" +- " tx pkt(%lu) tx calls (%lu)" +- " %s (Xoff events %u)\n", +- fp->name, bnx2x_tx_avail(fp), +- le16_to_cpu(*fp->tx_cons_sb), +- bnx2x_hilo(&qstats-> +- total_unicast_packets_transmitted_hi), +- fp->tx_pkt, +- (netif_tx_queue_stopped(txq) ? "Xoff" : "Xon"), +- qstats->driver_xoff); ++ struct netdev_queue *txq; ++ ++ printk(KERN_DEBUG "%s: tx pkt(%lu) (Xoff events %u)", ++ fp->name, bnx2x_hilo( ++ &qstats->total_unicast_packets_transmitted_hi), ++ qstats->driver_xoff); ++ ++ for_each_cos_in_tx_queue(fp, cos) { ++ txdata = &fp->txdata[cos]; ++ txq = netdev_get_tx_queue(bp->dev, ++ FP_COS_TO_TXQ(fp, cos)); ++ ++ printk(KERN_DEBUG "%d: tx avail(%4u)" ++ " *tx_cons_sb(%u)" ++ " tx calls (%lu)" ++ " %s\n", ++ cos, ++ bnx2x_tx_avail(bp, txdata), ++ le16_to_cpu(*txdata->tx_cons_sb), ++ txdata->tx_pkt, ++ (netif_tx_queue_stopped(txq) ? ++ "Xoff" : "Xon") ++ ); ++ } + } + } + +-- +1.7.2.2 + diff --git a/patches.drivers/0013-bnx2x-add-missing-command-in-error-handling-flow.patch b/patches.drivers/0013-bnx2x-add-missing-command-in-error-handling-flow.patch new file mode 100644 index 0000000..fe9a926 --- a/dev/null +++ b/patches.drivers/0013-bnx2x-add-missing-command-in-error-handling-flow.patch @@ -0,0 +1,31 @@ +From 5b9147c7572e3d2135f5db2b2c222ace732f9fe7 Mon Sep 17 00:00:00 2001 +From: Dmitry Kravkov <dmitry@broadcom.com> +Date: Tue, 19 Jul 2011 01:38:53 +0000 +Subject: [PATCH 13/37] bnx2x: add missing command in error handling flow +Patch-mainline: v3.1-rc1 +Git-commit: c636322b24eb69b7c1ccdc070164de51cee3f37c +References: fate#311461. bnc#698050 + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_cmn.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c +index 4f2a28c..e9e1dbc 100644 +--- a/drivers/net/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/bnx2x/bnx2x_cmn.c +@@ -1838,6 +1838,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) + rc = bnx2x_func_start(bp); + if (rc) { + BNX2X_ERR("Function start failed!\n"); ++ bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0); + LOAD_ERROR_EXIT(bp, load_error3); + } + +-- +1.7.2.2 + diff --git a/patches.drivers/0014-bnx2x-stop-tx-before-CNIC_STOP.patch b/patches.drivers/0014-bnx2x-stop-tx-before-CNIC_STOP.patch new file mode 100644 index 0000000..4a880d0 --- a/dev/null +++ b/patches.drivers/0014-bnx2x-stop-tx-before-CNIC_STOP.patch @@ -0,0 +1,46 @@ +From b9545f33726a028e2f1a8e316f640f9fe67f3f7c Mon Sep 17 00:00:00 2001 +From: Vladislav Zolotarov <vladz@broadcom.com> +Date: Tue, 19 Jul 2011 01:39:41 +0000 +Subject: [PATCH 14/37] bnx2x: stop tx before CNIC_STOP +Patch-mainline: v3.1-rc1 +Git-commit: 9505ee376739c26cf1d7d4e551d2f63b9d7e5729 +References: fate#311461. bnc#698050 + +It may take some time to cnic to respond, this prevents tx_timeout +when it happens. + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_cmn.c | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c +index e9e1dbc..6d30ea7 100644 +--- a/drivers/net/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/bnx2x/bnx2x_cmn.c +@@ -1999,6 +1999,9 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) + return -EINVAL; + } + ++ /* Stop Tx */ ++ bnx2x_tx_disable(bp); ++ + #ifdef BCM_CNIC + bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD); + #endif +@@ -2007,9 +2010,6 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) + + bp->rx_mode = BNX2X_RX_MODE_NONE; + +- /* Stop Tx */ +- bnx2x_tx_disable(bp); +- + del_timer_sync(&bp->timer); + + /* Set ALWAYS_ALIVE bit in shmem */ +-- +1.7.2.2 + diff --git a/patches.drivers/0015-bnx2x-remove-unnecessary-dma_sync.patch b/patches.drivers/0015-bnx2x-remove-unnecessary-dma_sync.patch new file mode 100644 index 0000000..804eb57 --- a/dev/null +++ b/patches.drivers/0015-bnx2x-remove-unnecessary-dma_sync.patch @@ -0,0 +1,40 @@ +From 360e34bcf00cae8896a18711f01de47c5cc1432a Mon Sep 17 00:00:00 2001 +From: Vladislav Zolotarov <vladz@broadcom.com> +Date: Tue, 19 Jul 2011 01:40:27 +0000 +Subject: [PATCH 15/37] bnx2x: remove unnecessary dma_sync +Patch-mainline: v3.1-rc1 +Git-commit: f13ac41f5165c0ac0441f9d42f7d6f6f9ee7c075 +References: fate#311461. bnc#698050 + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_cmn.h | 5 ----- + 1 files changed, 0 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h +index 871531c..df24ad7 100644 +--- a/drivers/net/bnx2x/bnx2x_cmn.h ++++ b/drivers/net/bnx2x/bnx2x_cmn.h +@@ -953,16 +953,11 @@ static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp, + static inline void bnx2x_reuse_rx_skb(struct bnx2x_fastpath *fp, + u16 cons, u16 prod) + { +- struct bnx2x *bp = fp->bp; + struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons]; + struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod]; + struct eth_rx_bd *cons_bd = &fp->rx_desc_ring[cons]; + struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod]; + +- dma_sync_single_for_device(&bp->pdev->dev, +- pci_unmap_addr(cons_rx_buf, mapping), +- RX_COPY_THRESH, DMA_FROM_DEVICE); +- + pci_unmap_addr_set(prod_rx_buf, mapping, + pci_unmap_addr(cons_rx_buf, mapping)); + prod_rx_buf->skb = cons_rx_buf->skb; +-- +1.7.2.2 + diff --git a/patches.drivers/0016-bnx2x-DCB-rework.patch b/patches.drivers/0016-bnx2x-DCB-rework.patch new file mode 100644 index 0000000..1812541 --- a/dev/null +++ b/patches.drivers/0016-bnx2x-DCB-rework.patch @@ -0,0 +1,718 @@ +From 826cb826998215798408f822397caec1ebe8c22c Mon Sep 17 00:00:00 2001 +From: Dmitry Kravkov <dmitry@broadcom.com> +Date: Tue, 19 Jul 2011 01:42:04 +0000 +Subject: [PATCH 16/37] bnx2x: DCB rework +Patch-mainline: v3.1-rc1 +Git-commit: 6debea870a66be4aac2e28be0e3952dad6c7fcdb +References: fate#311461. bnc#698050 + +create DCB related states in function state-machine +allow handling of DCB errors from FW +allow disablement of DCB in FW, when peer disappears or error +clean up unused functions/variables as pointed by +David Binderman <dcb314@hotmail.com> + +Reported-by: David Binderman <dcb314@hotmail.com> +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x.h | 7 +- + drivers/net/bnx2x/bnx2x_dcb.c | 173 ++++++++++++++++----------------------- + drivers/net/bnx2x/bnx2x_hsi.h | 1 + + drivers/net/bnx2x/bnx2x_main.c | 98 +++++++++++++++++++++-- + drivers/net/bnx2x/bnx2x_sp.c | 90 +++++++++++++++++++++ + drivers/net/bnx2x/bnx2x_sp.h | 13 +++ + 6 files changed, 268 insertions(+), 114 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h +index bff9f7b..cfab443 100644 +--- a/drivers/net/bnx2x/bnx2x.h ++++ b/drivers/net/bnx2x/bnx2x.h +@@ -964,6 +964,8 @@ struct bnx2x_slowpath { + + union { + struct function_start_data func_start; ++ /* pfc configuration for DCBX ramrod */ ++ struct flow_control_configuration pfc_config; + } func_rdata; + + /* used by dmae command executer */ +@@ -978,8 +980,6 @@ struct bnx2x_slowpath { + + u32 wb_comp; + u32 wb_data[4]; +- /* pfc configuration for DCBX ramrod */ +- struct flow_control_configuration pfc_config; + }; + + #define bnx2x_sp(bp, var) (&bp->slowpath->var) +@@ -1421,9 +1421,6 @@ struct bnx2x { + #define PHY_FW_VER_LEN 20 + const struct firmware *firmware; + +- /* LLDP params */ +- struct bnx2x_config_lldp_params lldp_config_params; +- + /* DCBX params */ + struct bnx2x_config_dcbx_params dcbx_config_params; + struct bnx2x_dcbx_port_params dcbx_port_params; +diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c +index d006a59..3b55b7c 100644 +--- a/drivers/net/bnx2x/bnx2x_dcb.c ++++ b/drivers/net/bnx2x/bnx2x_dcb.c +@@ -26,10 +26,10 @@ + + + /* forward declarations of dcbx related functions */ +-static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp); ++static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp); + static void bnx2x_pfc_set_pfc(struct bnx2x *bp); + static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp); +-static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp); ++static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp); + static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp, + u32 *set_configuration_ets_pg, + u32 *pri_pg_tbl); +@@ -44,8 +44,25 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp, + struct cos_help_data *cos_data, + u32 *pg_pri_orginal_spread, + struct dcbx_ets_feature *ets); +-static void bnx2x_dcbx_fw_struct(struct bnx2x *bp); ++static void bnx2x_dcbx_fw_struct(struct bnx2x *bp, ++ struct bnx2x_func_tx_start_params*); + ++/* helpers: read/write len bytes from addr into buff by REG_RD/REG_WR */ ++static void bnx2x_read_data(struct bnx2x *bp, u32 *buff, ++ u32 addr, u32 len) ++{ ++ int i; ++ for (i = 0; i < len; i += 4, buff++) ++ *buff = REG_RD(bp, addr + i); ++} ++ ++static void bnx2x_write_data(struct bnx2x *bp, u32 *buff, ++ u32 addr, u32 len) ++{ ++ int i; ++ for (i = 0; i < len; i += 4, buff++) ++ REG_WR(bp, addr + i, *buff); ++} + + static void bnx2x_pfc_set(struct bnx2x *bp) + { +@@ -202,7 +219,11 @@ static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp, + if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR)) + DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_ERROR\n"); + +- if (app->enabled && !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR)) { ++ if (GET_FLAGS(error, DCBX_LOCAL_APP_MISMATCH)) ++ DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_MISMATCH\n"); ++ ++ if (app->enabled && ++ !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR | DCBX_LOCAL_APP_MISMATCH)) { + + bp->dcbx_port_params.app.enabled = true; + +@@ -297,7 +318,7 @@ static void bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp, + DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_ERROR\n"); + + if (bp->dcbx_port_params.app.enabled && +- !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR) && ++ !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR | DCBX_LOCAL_PFC_MISMATCH) && + pfc->enabled) { + bp->dcbx_port_params.pfc.enabled = true; + bp->dcbx_port_params.pfc.priority_non_pauseable_mask = +@@ -326,8 +347,8 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp, + u32 offset, + int read_mib_type) + { +- int max_try_read = 0, i; +- u32 *buff, mib_size, prefix_seq_num, suffix_seq_num; ++ int max_try_read = 0; ++ u32 mib_size, prefix_seq_num, suffix_seq_num; + struct lldp_remote_mib *remote_mib ; + struct lldp_local_mib *local_mib; + +@@ -346,9 +367,7 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp, + offset += BP_PORT(bp) * mib_size; + + do { +- buff = base_mib_addr; +- for (i = 0; i < mib_size; i += 4, buff++) +- *buff = REG_RD(bp, offset + i); ++ bnx2x_read_data(bp, base_mib_addr, offset, mib_size); + + max_try_read++; + +@@ -379,12 +398,8 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp, + + static void bnx2x_pfc_set_pfc(struct bnx2x *bp) + { +- if (BP_PORT(bp)) { +- BNX2X_ERR("4 port mode is not supported"); +- return; +- } +- +- if (bp->dcbx_port_params.pfc.enabled) ++ if (bp->dcbx_port_params.pfc.enabled && ++ !(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR)) + /* + * 1. Fills up common PFC structures if required + * 2. Configure NIG, MAC and BRB via the elink +@@ -394,25 +409,30 @@ static void bnx2x_pfc_set_pfc(struct bnx2x *bp) + bnx2x_pfc_clear(bp); + } + +-static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp) ++static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp) + { +- DP(NETIF_MSG_LINK, "sending STOP TRAFFIC\n"); +- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, +- 0 /* connectionless */, +- 0 /* dataHi is zero */, +- 0 /* dataLo is zero */, +- NONE_CONNECTION_TYPE); ++ struct bnx2x_func_state_params func_params = {0}; ++ ++ func_params.f_obj = &bp->func_obj; ++ func_params.cmd = BNX2X_F_CMD_TX_STOP; ++ ++ DP(NETIF_MSG_LINK, "STOP TRAFFIC\n"); ++ return bnx2x_func_state_change(bp, &func_params); + } + +-static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp) ++static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp) + { +- bnx2x_dcbx_fw_struct(bp); +- DP(NETIF_MSG_LINK, "sending START TRAFFIC\n"); +- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, +- 0, /* connectionless */ +- U64_HI(bnx2x_sp_mapping(bp, pfc_config)), +- U64_LO(bnx2x_sp_mapping(bp, pfc_config)), +- NONE_CONNECTION_TYPE); ++ struct bnx2x_func_state_params func_params = {0}; ++ struct bnx2x_func_tx_start_params *tx_params = ++ &func_params.params.tx_start; ++ ++ func_params.f_obj = &bp->func_obj; ++ func_params.cmd = BNX2X_F_CMD_TX_START; ++ ++ bnx2x_dcbx_fw_struct(bp, tx_params); ++ ++ DP(NETIF_MSG_LINK, "START TRAFFIC\n"); ++ return bnx2x_func_state_change(bp, &func_params); + } + + static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x *bp) +@@ -519,7 +539,8 @@ static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp) + { + bnx2x_ets_disabled(&bp->link_params, &bp->link_vars); + +- if (!bp->dcbx_port_params.ets.enabled) ++ if (!bp->dcbx_port_params.ets.enabled || ++ (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR)) + return; + + if (CHIP_IS_E3B0(bp)) +@@ -637,61 +658,14 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state) + } + } + +- +-#define LLDP_STATS_OFFSET(bp) (BP_PORT(bp)*\ +- sizeof(struct lldp_dcbx_stat)) +- +-/* calculate struct offset in array according to chip information */ +-#define LLDP_PARAMS_OFFSET(bp) (BP_PORT(bp)*sizeof(struct lldp_params)) +- + #define LLDP_ADMIN_MIB_OFFSET(bp) (PORT_MAX*sizeof(struct lldp_params) + \ + BP_PORT(bp)*sizeof(struct lldp_admin_mib)) + +-static void bnx2x_dcbx_lldp_updated_params(struct bnx2x *bp, +- u32 dcbx_lldp_params_offset) +-{ +- struct lldp_params lldp_params = {0}; +- u32 i = 0, *buff = NULL; +- u32 offset = dcbx_lldp_params_offset + LLDP_PARAMS_OFFSET(bp); +- +- DP(NETIF_MSG_LINK, "lldp_offset 0x%x\n", offset); +- +- if ((bp->lldp_config_params.overwrite_settings == +- BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE)) { +- /* Read the data first */ +- buff = (u32 *)&lldp_params; +- for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++) +- *buff = REG_RD(bp, (offset + i)); +- +- lldp_params.msg_tx_hold = +- (u8)bp->lldp_config_params.msg_tx_hold; +- lldp_params.msg_fast_tx_interval = +- (u8)bp->lldp_config_params.msg_fast_tx; +- lldp_params.tx_crd_max = +- (u8)bp->lldp_config_params.tx_credit_max; +- lldp_params.msg_tx_interval = +- (u8)bp->lldp_config_params.msg_tx_interval; +- lldp_params.tx_fast = +- (u8)bp->lldp_config_params.tx_fast; +- +- /* Write the data.*/ +- buff = (u32 *)&lldp_params; +- for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++) +- REG_WR(bp, (offset + i) , *buff); +- +- +- } else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE == +- bp->lldp_config_params.overwrite_settings) +- bp->lldp_config_params.overwrite_settings = +- BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID; +-} +- + static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp, + u32 dcbx_lldp_params_offset) + { + struct lldp_admin_mib admin_mib; + u32 i, other_traf_type = PREDEFINED_APP_IDX_MAX, traf_type = 0; +- u32 *buff; + u32 offset = dcbx_lldp_params_offset + LLDP_ADMIN_MIB_OFFSET(bp); + + /*shortcuts*/ +@@ -699,11 +673,10 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp, + struct bnx2x_config_dcbx_params *dp = &bp->dcbx_config_params; + + memset(&admin_mib, 0, sizeof(struct lldp_admin_mib)); +- buff = (u32 *)&admin_mib; +- /* Read the data first */ +- for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++) +- *buff = REG_RD(bp, (offset + i)); + ++ /* Read the data first */ ++ bnx2x_read_data(bp, (u32 *)&admin_mib, offset, ++ sizeof(struct lldp_admin_mib)); + + if (BNX2X_DCBX_CONFIG_INV_VALUE != dp->admin_dcbx_enable) { + if (dp->admin_dcbx_enable) +@@ -712,8 +685,8 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp, + RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED); + } + +- if ((BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE == +- dp->overwrite_settings)) { ++ if (dp->overwrite_settings == BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE) { ++ + RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_CEE_VERSION_MASK); + admin_mib.ver_cfg_flags |= + (dp->admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) & +@@ -809,14 +782,12 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp, + + af->app.default_pri = (u8)dp->admin_default_priority; + +- } else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE == +- dp->overwrite_settings) +- dp->overwrite_settings = BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID; ++ } + + /* Write the data. */ +- buff = (u32 *)&admin_mib; +- for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++) +- REG_WR(bp, (offset + i), *buff); ++ bnx2x_write_data(bp, (u32 *)&admin_mib, offset, ++ sizeof(struct lldp_admin_mib)); ++ + } + + /* default */ +@@ -901,8 +872,7 @@ void bnx2x_dcbx_init(struct bnx2x *bp) + DP(NETIF_MSG_LINK, "dcb_enable %d bp->port.pmf %d\n", + bp->dcbx_config_params.dcb_enable, bp->port.pmf); + +- if (CHIP_IS_E2(bp) && !CHIP_MODE_IS_4_PORT(bp) && +- bp->dcbx_config_params.dcb_enable && ++ if (bp->dcbx_config_params.dcb_enable && + bp->port.pmf && + SHMEM2_HAS(bp, dcbx_lldp_params_offset)) { + dcbx_lldp_params_offset = SHMEM2_RD(bp, +@@ -913,9 +883,6 @@ void bnx2x_dcbx_init(struct bnx2x *bp) + bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 0); + + if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) { +- bnx2x_dcbx_lldp_updated_params(bp, +- dcbx_lldp_params_offset); +- + bnx2x_dcbx_admin_mib_updated_params(bp, + dcbx_lldp_params_offset); + +@@ -927,7 +894,7 @@ void bnx2x_dcbx_init(struct bnx2x *bp) + } + static void + bnx2x_dcbx_print_cos_params(struct bnx2x *bp, +- struct flow_control_configuration *pfc_fw_cfg) ++ struct bnx2x_func_tx_start_params *pfc_fw_cfg) + { + u8 pri = 0; + u8 cos = 0; +@@ -1705,17 +1672,19 @@ static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp, + } + } + +-static void bnx2x_dcbx_fw_struct(struct bnx2x *bp) ++static void bnx2x_dcbx_fw_struct(struct bnx2x *bp, ++ struct bnx2x_func_tx_start_params *pfc_fw_cfg) + { +- struct flow_control_configuration *pfc_fw_cfg = NULL; + u16 pri_bit = 0; + u8 cos = 0, pri = 0; + struct priority_cos *tt2cos; + u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority; + +- pfc_fw_cfg = (struct flow_control_configuration *) +- bnx2x_sp(bp, pfc_config); +- memset(pfc_fw_cfg, 0, sizeof(struct flow_control_configuration)); ++ memset(pfc_fw_cfg, 0, sizeof(*pfc_fw_cfg)); ++ ++ /* to disable DCB - the structure must be zeroed */ ++ if (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) ++ return; + + /*shortcut*/ + tt2cos = pfc_fw_cfg->traffic_type_to_priority_cos; +diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h +index ce3b566..06727f3 100644 +--- a/drivers/net/bnx2x/bnx2x_hsi.h ++++ b/drivers/net/bnx2x/bnx2x_hsi.h +@@ -1834,6 +1834,7 @@ struct lldp_local_mib { + #define DCBX_LOCAL_APP_ERROR 0x00000004 + #define DCBX_LOCAL_PFC_MISMATCH 0x00000010 + #define DCBX_LOCAL_APP_MISMATCH 0x00000020 ++ #define DCBX_REMOTE_MIB_ERROR 0x00000040 + struct dcbx_features features; + u32 suffix_seq_num; + }; +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index 96ecd60..63ab9af 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -4458,11 +4458,17 @@ static void bnx2x_eq_int(struct bnx2x *bp) + + case EVENT_RING_OPCODE_STOP_TRAFFIC: + DP(BNX2X_MSG_SP, "got STOP TRAFFIC\n"); ++ if (f_obj->complete_cmd(bp, f_obj, ++ BNX2X_F_CMD_TX_STOP)) ++ break; + bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_PAUSED); + goto next_spqe; + + case EVENT_RING_OPCODE_START_TRAFFIC: + DP(BNX2X_MSG_SP, "got START TRAFFIC\n"); ++ if (f_obj->complete_cmd(bp, f_obj, ++ BNX2X_F_CMD_TX_START)) ++ break; + bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED); + goto next_spqe; + case EVENT_RING_OPCODE_FUNCTION_START: +@@ -7590,6 +7596,71 @@ void bnx2x_send_unload_done(struct bnx2x *bp) + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); + } + ++static inline int bnx2x_func_wait_started(struct bnx2x *bp) ++{ ++ int tout = 50; ++ int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0; ++ ++ if (!bp->port.pmf) ++ return 0; ++ ++ /* ++ * (assumption: No Attention from MCP at this stage) ++ * PMF probably in the middle of TXdisable/enable transaction ++ * 1. Sync IRS for default SB ++ * 2. Sync SP queue - this guarantes us that attention handling started ++ * 3. Wait, that TXdisable/enable transaction completes ++ * ++ * 1+2 guranty that if DCBx attention was scheduled it already changed ++ * pending bit of transaction from STARTED-->TX_STOPPED, if we alredy ++ * received complettion for the transaction the state is TX_STOPPED. ++ * State will return to STARTED after completion of TX_STOPPED-->STARTED ++ * transaction. ++ */ ++ ++ /* make sure default SB ISR is done */ ++ if (msix) ++ synchronize_irq(bp->msix_table[0].vector); ++ else ++ synchronize_irq(bp->pdev->irq); ++ ++ flush_workqueue(bnx2x_wq); ++ ++ while (bnx2x_func_get_state(bp, &bp->func_obj) != ++ BNX2X_F_STATE_STARTED && tout--) ++ msleep(20); ++ ++ if (bnx2x_func_get_state(bp, &bp->func_obj) != ++ BNX2X_F_STATE_STARTED) { ++#ifdef BNX2X_STOP_ON_ERROR ++ return -EBUSY; ++#else ++ /* ++ * Failed to complete the transaction in a "good way" ++ * Force both transactions with CLR bit ++ */ ++ struct bnx2x_func_state_params func_params = {0}; ++ ++ DP(BNX2X_MSG_SP, "Hmmm... unexpected function state! " ++ "Forcing STARTED-->TX_ST0PPED-->STARTED\n"); ++ ++ func_params.f_obj = &bp->func_obj; ++ __set_bit(RAMROD_DRV_CLR_ONLY, ++ &func_params.ramrod_flags); ++ ++ /* STARTED-->TX_ST0PPED */ ++ func_params.cmd = BNX2X_F_CMD_TX_STOP; ++ bnx2x_func_state_change(bp, &func_params); ++ ++ /* TX_ST0PPED-->STARTED */ ++ func_params.cmd = BNX2X_F_CMD_TX_START; ++ return bnx2x_func_state_change(bp, &func_params); ++#endif ++ } ++ ++ return 0; ++} ++ + void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) + { + int port = BP_PORT(bp); +@@ -7649,6 +7720,26 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode) + netif_addr_unlock_bh(bp->dev); + + ++ ++ /* ++ * Send the UNLOAD_REQUEST to the MCP. This will return if ++ * this function should perform FUNC, PORT or COMMON HW ++ * reset. ++ */ ++ reset_code = bnx2x_send_unload_req(bp, unload_mode); ++ ++ /* ++ * (assumption: No Attention from MCP at this stage) ++ * PMF probably in the middle of TXdisable/enable transaction ++ */ ++ rc = bnx2x_func_wait_started(bp); ++ if (rc) { ++ BNX2X_ERR("bnx2x_func_wait_started failed\n"); ++#ifdef BNX2X_STOP_ON_ERROR ++ return; ++#endif ++ } ++ + /* Close multi and leading connections + * Completions for ramrods are collected in a synchronous way + */ +@@ -7676,13 +7767,6 @@ unload_error: + #endif + } + +- /* +- * Send the UNLOAD_REQUEST to the MCP. This will return if +- * this function should perform FUNC, PORT or COMMON HW +- * reset. +- */ +- reset_code = bnx2x_send_unload_req(bp, unload_mode); +- + /* Disable HW interrupts, NAPI */ + bnx2x_netif_stop(bp, 1); + +diff --git a/drivers/net/bnx2x/bnx2x_sp.c b/drivers/net/bnx2x/bnx2x_sp.c +index ce1efdb9..a18e0e7 100644 +--- a/drivers/net/bnx2x/bnx2x_sp.c ++++ b/drivers/net/bnx2x/bnx2x_sp.c +@@ -4882,6 +4882,22 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, + ¶ms->params.update; + u8 next_tx_only = o->num_tx_only; + ++ /* ++ * Forget all pending for completion commands if a driver only state ++ * transition has been requested. ++ */ ++ if (test_bit(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags)) { ++ o->pending = 0; ++ o->next_state = BNX2X_Q_STATE_MAX; ++ } ++ ++ /* ++ * Don't allow a next state transition if we are in the middle of ++ * the previous one. ++ */ ++ if (o->pending) ++ return -EBUSY; ++ + switch (state) { + case BNX2X_Q_STATE_RESET: + if (cmd == BNX2X_Q_CMD_INIT) +@@ -5061,6 +5077,21 @@ void bnx2x_queue_set_cos_cid(struct bnx2x *bp, + } + + /********************** Function state object *********************************/ ++enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp, ++ struct bnx2x_func_sp_obj *o) ++{ ++ /* in the middle of transaction - return INVALID state */ ++ if (o->pending) ++ return BNX2X_F_STATE_MAX; ++ ++ /* ++ * unsure the order of reading of o->pending and o->state ++ * o->pending should be read first ++ */ ++ rmb(); ++ ++ return o->state; ++} + + static int bnx2x_func_wait_comp(struct bnx2x *bp, + struct bnx2x_func_sp_obj *o, +@@ -5151,6 +5182,22 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp, + enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX; + enum bnx2x_func_cmd cmd = params->cmd; + ++ /* ++ * Forget all pending for completion commands if a driver only state ++ * transition has been requested. ++ */ ++ if (test_bit(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags)) { ++ o->pending = 0; ++ o->next_state = BNX2X_F_STATE_MAX; ++ } ++ ++ /* ++ * Don't allow a next state transition if we are in the middle of ++ * the previous one. ++ */ ++ if (o->pending) ++ return -EBUSY; ++ + switch (state) { + case BNX2X_F_STATE_RESET: + if (cmd == BNX2X_F_CMD_HW_INIT) +@@ -5168,6 +5215,13 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp, + case BNX2X_F_STATE_STARTED: + if (cmd == BNX2X_F_CMD_STOP) + next_state = BNX2X_F_STATE_INITIALIZED; ++ else if (cmd == BNX2X_F_CMD_TX_STOP) ++ next_state = BNX2X_F_STATE_TX_STOPPED; ++ ++ break; ++ case BNX2X_F_STATE_TX_STOPPED: ++ if (cmd == BNX2X_F_CMD_TX_START) ++ next_state = BNX2X_F_STATE_STARTED; + + break; + default: +@@ -5452,6 +5506,38 @@ static inline int bnx2x_func_send_stop(struct bnx2x *bp, + NONE_CONNECTION_TYPE); + } + ++static inline int bnx2x_func_send_tx_stop(struct bnx2x *bp, ++ struct bnx2x_func_state_params *params) ++{ ++ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, 0, 0, 0, ++ NONE_CONNECTION_TYPE); ++} ++static inline int bnx2x_func_send_tx_start(struct bnx2x *bp, ++ struct bnx2x_func_state_params *params) ++{ ++ struct bnx2x_func_sp_obj *o = params->f_obj; ++ struct flow_control_configuration *rdata = ++ (struct flow_control_configuration *)o->rdata; ++ dma_addr_t data_mapping = o->rdata_mapping; ++ struct bnx2x_func_tx_start_params *tx_start_params = ++ ¶ms->params.tx_start; ++ int i; ++ ++ memset(rdata, 0, sizeof(*rdata)); ++ ++ rdata->dcb_enabled = tx_start_params->dcb_enabled; ++ rdata->dcb_version = tx_start_params->dcb_version; ++ rdata->dont_add_pri_0_en = tx_start_params->dont_add_pri_0_en; ++ ++ for (i = 0; i < ARRAY_SIZE(rdata->traffic_type_to_priority_cos); i++) ++ rdata->traffic_type_to_priority_cos[i] = ++ tx_start_params->traffic_type_to_priority_cos[i]; ++ ++ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0, ++ U64_HI(data_mapping), ++ U64_LO(data_mapping), NONE_CONNECTION_TYPE); ++} ++ + static int bnx2x_func_send_cmd(struct bnx2x *bp, + struct bnx2x_func_state_params *params) + { +@@ -5464,6 +5550,10 @@ static int bnx2x_func_send_cmd(struct bnx2x *bp, + return bnx2x_func_send_stop(bp, params); + case BNX2X_F_CMD_HW_RESET: + return bnx2x_func_hw_reset(bp, params); ++ case BNX2X_F_CMD_TX_STOP: ++ return bnx2x_func_send_tx_stop(bp, params); ++ case BNX2X_F_CMD_TX_START: ++ return bnx2x_func_send_tx_start(bp, params); + default: + BNX2X_ERR("Unknown command: %d\n", params->cmd); + return -EINVAL; +diff --git a/drivers/net/bnx2x/bnx2x_sp.h b/drivers/net/bnx2x/bnx2x_sp.h +index 83f3b0b..73400dd 100644 +--- a/drivers/net/bnx2x/bnx2x_sp.h ++++ b/drivers/net/bnx2x/bnx2x_sp.h +@@ -996,6 +996,7 @@ enum bnx2x_func_state { + BNX2X_F_STATE_RESET, + BNX2X_F_STATE_INITIALIZED, + BNX2X_F_STATE_STARTED, ++ BNX2X_F_STATE_TX_STOPPED, + BNX2X_F_STATE_MAX, + }; + +@@ -1005,6 +1006,8 @@ enum bnx2x_func_cmd { + BNX2X_F_CMD_START, + BNX2X_F_CMD_STOP, + BNX2X_F_CMD_HW_RESET, ++ BNX2X_F_CMD_TX_STOP, ++ BNX2X_F_CMD_TX_START, + BNX2X_F_CMD_MAX, + }; + +@@ -1047,6 +1050,13 @@ struct bnx2x_func_start_params { + u8 network_cos_mode; + }; + ++struct bnx2x_func_tx_start_params { ++ struct priority_cos traffic_type_to_priority_cos[MAX_TRAFFIC_TYPES]; ++ u8 dcb_enabled; ++ u8 dcb_version; ++ u8 dont_add_pri_0_en; ++}; ++ + struct bnx2x_func_state_params { + struct bnx2x_func_sp_obj *f_obj; + +@@ -1061,6 +1071,7 @@ struct bnx2x_func_state_params { + struct bnx2x_func_hw_init_params hw_init; + struct bnx2x_func_hw_reset_params hw_reset; + struct bnx2x_func_start_params start; ++ struct bnx2x_func_tx_start_params tx_start; + } params; + }; + +@@ -1152,6 +1163,8 @@ void bnx2x_init_func_obj(struct bnx2x *bp, + int bnx2x_func_state_change(struct bnx2x *bp, + struct bnx2x_func_state_params *params); + ++enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp, ++ struct bnx2x_func_sp_obj *o); + /******************* Queue State **************/ + void bnx2x_init_queue_obj(struct bnx2x *bp, + struct bnx2x_queue_sp_obj *obj, u8 cl_id, u32 *cids, +-- +1.7.2.2 + diff --git a/patches.drivers/0017-bnx2x-use-pci_pcie_cap.patch b/patches.drivers/0017-bnx2x-use-pci_pcie_cap.patch new file mode 100644 index 0000000..cfbb270 --- a/dev/null +++ b/patches.drivers/0017-bnx2x-use-pci_pcie_cap.patch @@ -0,0 +1,33 @@ +From 05d549d9b70741d487089813343664082a7c813b Mon Sep 17 00:00:00 2001 +From: Vladislav Zolotarov <vladz@broadcom.com> +Date: Sun, 24 Jul 2011 03:58:38 +0000 +Subject: [PATCH 17/37] bnx2x: use pci_pcie_cap() +Patch-mainline: v3.1-rc1 +Git-commit: b6c2f86e6305be612f1196459f22343523f7049f +References: fate#311461. bnc#698050 + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_main.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index 63ab9af..61032cc 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -5635,7 +5635,7 @@ static void bnx2x_init_pxp(struct bnx2x *bp) + int r_order, w_order; + + pci_read_config_word(bp->pdev, +- bp->pdev->pcie_cap + PCI_EXP_DEVCTL, &devctl); ++ pci_pcie_cap(bp->pdev) + PCI_EXP_DEVCTL, &devctl); + DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl); + w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); + if (bp->mrrs == -1) +-- +1.7.2.2 + diff --git a/patches.drivers/0018-bnx2x-disable-loacal-BH-when-scheduling-FCOE-napi.patch b/patches.drivers/0018-bnx2x-disable-loacal-BH-when-scheduling-FCOE-napi.patch new file mode 100644 index 0000000..daf4893 --- a/dev/null +++ b/patches.drivers/0018-bnx2x-disable-loacal-BH-when-scheduling-FCOE-napi.patch @@ -0,0 +1,40 @@ +From f3051db7aa65168fb51a91f56559bbbf4d717688 Mon Sep 17 00:00:00 2001 +From: Vladislav Zolotarov <vladz@broadcom.com> +Date: Tue, 19 Jul 2011 01:43:25 +0000 +Subject: [PATCH 18/37] bnx2x: disable loacal BH when scheduling FCOE napi +Patch-mainline: v3.1-rc1 +Git-commit: 019dbb4c0106f11b5c6543bffaedf10067e28398 +References: fate#311461. bnc#698050 + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_main.c | 9 ++++++++- + 1 files changed, 8 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index 61032cc..e6701d2 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -4575,8 +4575,15 @@ static void bnx2x_sp_task(struct work_struct *work) + struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp); + + if ((!NO_FCOE(bp)) && +- (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) ++ (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { ++ /* ++ * Prevent local bottom-halves from running as ++ * we are going to change the local NAPI list. ++ */ ++ local_bh_disable(); + napi_schedule(&bnx2x_fcoe(bp, napi)); ++ local_bh_enable(); ++ } + #endif + /* Handle EQ completions */ + bnx2x_eq_int(bp); +-- +1.7.2.2 + diff --git a/patches.drivers/0019-bnx2x-use-BNX2X_Q_FLG_TPA_IPV6-for-TPA-queue-configu.patch b/patches.drivers/0019-bnx2x-use-BNX2X_Q_FLG_TPA_IPV6-for-TPA-queue-configu.patch new file mode 100644 index 0000000..a368870 --- a/dev/null +++ b/patches.drivers/0019-bnx2x-use-BNX2X_Q_FLG_TPA_IPV6-for-TPA-queue-configu.patch @@ -0,0 +1,62 @@ +From 84f5abc5014cd1eb3a1b1c5d2575397d5519af09 Mon Sep 17 00:00:00 2001 +From: Vladislav Zolotarov <vladz@broadcom.com> +Date: Tue, 19 Jul 2011 01:44:11 +0000 +Subject: [PATCH 19/37] bnx2x: use BNX2X_Q_FLG_TPA_IPV6 for TPA queue configuration +Patch-mainline: v3.1-rc1 +Git-commit: f5219d8eb8b32eb32522063d2163f95e1cf7bb5c +References: fate#311461. bnc#698050 + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_main.c | 4 +++- + drivers/net/bnx2x/bnx2x_sp.c | 2 +- + drivers/net/bnx2x/bnx2x_sp.h | 1 + + 3 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index e6701d2..f671555 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -2698,8 +2698,10 @@ static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp, + if (IS_FCOE_FP(fp)) + __set_bit(BNX2X_Q_FLG_FCOE, &flags); + +- if (!fp->disable_tpa) ++ if (!fp->disable_tpa) { + __set_bit(BNX2X_Q_FLG_TPA, &flags); ++ __set_bit(BNX2X_Q_FLG_TPA_IPV6, &flags); ++ } + + if (leading) { + __set_bit(BNX2X_Q_FLG_LEADING_RSS, &flags); +diff --git a/drivers/net/bnx2x/bnx2x_sp.c b/drivers/net/bnx2x/bnx2x_sp.c +index a18e0e7..891958d 100644 +--- a/drivers/net/bnx2x/bnx2x_sp.c ++++ b/drivers/net/bnx2x/bnx2x_sp.c +@@ -4248,7 +4248,7 @@ static void bnx2x_q_fill_setup_data_e2(struct bnx2x *bp, + /* Rx data */ + + /* IPv6 TPA supported for E2 and above only */ +- data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA, ¶ms->flags) * ++ data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA_IPV6, ¶ms->flags) * + CLIENT_INIT_RX_DATA_TPA_EN_IPV6; + } + +diff --git a/drivers/net/bnx2x/bnx2x_sp.h b/drivers/net/bnx2x/bnx2x_sp.h +index 73400dd..9a517c2 100644 +--- a/drivers/net/bnx2x/bnx2x_sp.h ++++ b/drivers/net/bnx2x/bnx2x_sp.h +@@ -749,6 +749,7 @@ enum bnx2x_queue_cmd { + /* queue SETUP + INIT flags */ + enum { + BNX2X_Q_FLG_TPA, ++ BNX2X_Q_FLG_TPA_IPV6, + BNX2X_Q_FLG_STATS, + BNX2X_Q_FLG_ZERO_STATS, + BNX2X_Q_FLG_ACTIVE, +-- +1.7.2.2 + diff --git a/patches.drivers/0020-bnx2x-fix-memory-barriers.patch b/patches.drivers/0020-bnx2x-fix-memory-barriers.patch new file mode 100644 index 0000000..e941de9 --- a/dev/null +++ b/patches.drivers/0020-bnx2x-fix-memory-barriers.patch @@ -0,0 +1,204 @@ +From f7bffe78aa0a113b0b226147980b61c6011a0b61 Mon Sep 17 00:00:00 2001 +From: Vladislav Zolotarov <vladz@broadcom.com> +Date: Tue, 19 Jul 2011 01:45:02 +0000 +Subject: [PATCH 20/37] bnx2x: fix memory barriers +Patch-mainline: v3.1-rc1 +Git-commit: 53e51e2f480aaa000b0a7d2704ce2b4b646a73c7 +References: fate#311461. bnc#698050 + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_main.c | 8 +++- + drivers/net/bnx2x/bnx2x_sp.c | 86 ++++++++++++++++++++++++++++++++-------- + 2 files changed, 75 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index f671555..fae7994 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -2993,8 +2993,12 @@ static inline void bnx2x_sp_prod_update(struct bnx2x *bp) + { + int func = BP_FUNC(bp); + +- /* Make sure that BD data is updated before writing the producer */ +- wmb(); ++ /* ++ * Make sure that BD data is updated before writing the producer: ++ * BD data is written to the memory, the producer is read from the ++ * memory, thus we need a full memory barrier to ensure the ordering. ++ */ ++ mb(); + + REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func), + bp->spq_prod_idx); +diff --git a/drivers/net/bnx2x/bnx2x_sp.c b/drivers/net/bnx2x/bnx2x_sp.c +index 891958d..f4e18af 100644 +--- a/drivers/net/bnx2x/bnx2x_sp.c ++++ b/drivers/net/bnx2x/bnx2x_sp.c +@@ -1565,8 +1565,13 @@ static int bnx2x_execute_vlan_mac(struct bnx2x *bp, + idx++; + } + +- /* Commit the data writes towards the memory */ +- mb(); ++ /* ++ * No need for an explicit memory barrier here as long we would ++ * need to ensure the ordering of writing to the SPQ element ++ * and updating of the SPQ producer which involves a memory ++ * read and we will have to put a full memory barrier there ++ * (inside bnx2x_sp_post()). ++ */ + + rc = bnx2x_sp_post(bp, o->ramrod_cmd, r->cid, + U64_HI(r->rdata_mapping), +@@ -2232,8 +2237,13 @@ static int bnx2x_set_rx_mode_e2(struct bnx2x *bp, + data->header.rule_cnt, p->rx_accept_flags, + p->tx_accept_flags); + +- /* Commit writes towards the memory before sending a ramrod */ +- mb(); ++ /* ++ * No need for an explicit memory barrier here as long we would ++ * need to ensure the ordering of writing to the SPQ element ++ * and updating of the SPQ producer which involves a memory ++ * read and we will have to put a full memory barrier there ++ * (inside bnx2x_sp_post()). ++ */ + + /* Send a ramrod */ + rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_FILTER_RULES, p->cid, +@@ -2926,16 +2936,22 @@ static int bnx2x_mcast_setup_e2(struct bnx2x *bp, + if (!o->total_pending_num) + bnx2x_mcast_refresh_registry_e2(bp, o); + +- /* Commit writes towards the memory before sending a ramrod */ +- mb(); +- +- /* If CLEAR_ONLY was requested - don't send a ramrod and clear ++ /* ++ * If CLEAR_ONLY was requested - don't send a ramrod and clear + * RAMROD_PENDING status immediately. + */ + if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) { + raw->clear_pending(raw); + return 0; + } else { ++ /* ++ * No need for an explicit memory barrier here as long we would ++ * need to ensure the ordering of writing to the SPQ element ++ * and updating of the SPQ producer which involves a memory ++ * read and we will have to put a full memory barrier there ++ * (inside bnx2x_sp_post()). ++ */ ++ + /* Send a ramrod */ + rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_MULTICAST_RULES, + raw->cid, U64_HI(raw->rdata_mapping), +@@ -3412,16 +3428,22 @@ static int bnx2x_mcast_setup_e1(struct bnx2x *bp, + if (rc) + return rc; + +- /* Commit writes towards the memory before sending a ramrod */ +- mb(); +- +- /* If CLEAR_ONLY was requested - don't send a ramrod and clear ++ /* ++ * If CLEAR_ONLY was requested - don't send a ramrod and clear + * RAMROD_PENDING status immediately. + */ + if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) { + raw->clear_pending(raw); + return 0; + } else { ++ /* ++ * No need for an explicit memory barrier here as long we would ++ * need to ensure the ordering of writing to the SPQ element ++ * and updating of the SPQ producer which involves a memory ++ * read and we will have to put a full memory barrier there ++ * (inside bnx2x_sp_post()). ++ */ ++ + /* Send a ramrod */ + rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, raw->cid, + U64_HI(raw->rdata_mapping), +@@ -4046,8 +4068,13 @@ static int bnx2x_setup_rss(struct bnx2x *bp, + data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY; + } + +- /* Commit writes towards the memory before sending a ramrod */ +- mb(); ++ /* ++ * No need for an explicit memory barrier here as long we would ++ * need to ensure the ordering of writing to the SPQ element ++ * and updating of the SPQ producer which involves a memory ++ * read and we will have to put a full memory barrier there ++ * (inside bnx2x_sp_post()). ++ */ + + /* Send a ramrod */ + rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_RSS_UPDATE, r->cid, +@@ -4513,7 +4540,13 @@ static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp, + /* Fill the ramrod data */ + bnx2x_q_fill_setup_data_cmn(bp, params, rdata); + +- mb(); ++ /* ++ * No need for an explicit memory barrier here as long we would ++ * need to ensure the ordering of writing to the SPQ element ++ * and updating of the SPQ producer which involves a memory ++ * read and we will have to put a full memory barrier there ++ * (inside bnx2x_sp_post()). ++ */ + + return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX], + U64_HI(data_mapping), +@@ -4536,6 +4569,13 @@ static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp, + bnx2x_q_fill_setup_data_cmn(bp, params, rdata); + bnx2x_q_fill_setup_data_e2(bp, params, rdata); + ++ /* ++ * No need for an explicit memory barrier here as long we would ++ * need to ensure the ordering of writing to the SPQ element ++ * and updating of the SPQ producer which involves a memory ++ * read and we will have to put a full memory barrier there ++ * (inside bnx2x_sp_post()). ++ */ + + return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX], + U64_HI(data_mapping), +@@ -4673,7 +4713,13 @@ static inline int bnx2x_q_send_update(struct bnx2x *bp, + /* Fill the ramrod data */ + bnx2x_q_fill_update_data(bp, o, update_params, rdata); + +- mb(); ++ /* ++ * No need for an explicit memory barrier here as long we would ++ * need to ensure the ordering of writing to the SPQ element ++ * and updating of the SPQ producer which involves a memory ++ * read and we will have to put a full memory barrier there ++ * (inside bnx2x_sp_post()). ++ */ + + return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE, + o->cids[cid_index], U64_HI(data_mapping), +@@ -5492,7 +5538,13 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp, + rdata->path_id = BP_PATH(bp); + rdata->network_cos_mode = start_params->network_cos_mode; + +- mb(); ++ /* ++ * No need for an explicit memory barrier here as long we would ++ * need to ensure the ordering of writing to the SPQ element ++ * and updating of the SPQ producer which involves a memory ++ * read and we will have to put a full memory barrier there ++ * (inside bnx2x_sp_post()). ++ */ + + return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0, + U64_HI(data_mapping), +-- +1.7.2.2 + diff --git a/patches.drivers/0021-bnx2x-disable-FCoE-for-578xx-devices-since-not-yet-s.patch b/patches.drivers/0021-bnx2x-disable-FCoE-for-578xx-devices-since-not-yet-s.patch new file mode 100644 index 0000000..9e074fd --- a/dev/null +++ b/patches.drivers/0021-bnx2x-disable-FCoE-for-578xx-devices-since-not-yet-s.patch @@ -0,0 +1,34 @@ +From a77f493ab8202a0349b43a98937cbabc6bb04e26 Mon Sep 17 00:00:00 2001 +From: Dmitry Kravkov <dmitry@broadcom.com> +Date: Tue, 19 Jul 2011 01:46:11 +0000 +Subject: [PATCH 21/37] bnx2x: disable FCoE for 578xx devices since not yet supported +Patch-mainline: v3.1-rc1 +Git-commit: 928ad22a3b033a994081dbf49f3c046195dd2349 +References: fate#311461. bnc#698050 + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_main.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index fae7994..2776865 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -10627,8 +10627,8 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, + bp->qm_cid_count = bnx2x_set_qm_cid_count(bp); + + #ifdef BCM_CNIC +- /* disable FCOE L2 queue for E1x*/ +- if (CHIP_IS_E1x(bp)) ++ /* disable FCOE L2 queue for E1x and E3*/ ++ if (CHIP_IS_E1x(bp) || CHIP_IS_E3(bp)) + bp->flags |= NO_FCOE_FLAG; + + #endif +-- +1.7.2.2 + diff --git a/patches.drivers/0022-bnx2x-dcb-send-all-unmapped-priorities-to-same-COS-a.patch b/patches.drivers/0022-bnx2x-dcb-send-all-unmapped-priorities-to-same-COS-a.patch new file mode 100644 index 0000000..f36ecc8 --- a/dev/null +++ b/patches.drivers/0022-bnx2x-dcb-send-all-unmapped-priorities-to-same-COS-a.patch @@ -0,0 +1,87 @@ +From 20e97599ee3d8b1bad2e43d2cd4f4b78cec9bd1a Mon Sep 17 00:00:00 2001 +From: Dmitry Kravkov <dmitry@broadcom.com> +Date: Sun, 24 Jul 2011 04:09:43 +0000 +Subject: [PATCH 22/37] bnx2x: dcb - send all unmapped priorities to same COS as L2 +Patch-mainline: v3.1-rc1 +Git-commit: 09b775e7ec08ae92b8d976b7e34ba7f83b904c97 +References: fate#311461. bnc#698050 + +As a result of DCBX negotiation some priorities maybe untouched and still +unmapped to any COS; instead of sending them to COS0 we assign them +to the same COS as L2 traffic - to avoid collisions with storage class of +service. + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_dcb.c | 31 ++++++++++++++++++++++++++++++- + 1 files changed, 30 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c +index 3b55b7c..eb470c7 100644 +--- a/drivers/net/bnx2x/bnx2x_dcb.c ++++ b/drivers/net/bnx2x/bnx2x_dcb.c +@@ -330,6 +330,32 @@ static void bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp, + } + } + ++/* maps unmapped priorities to to the same COS as L2 */ ++static void bnx2x_dcbx_map_nw(struct bnx2x *bp) ++{ ++ int i; ++ u32 unmapped = (1 << MAX_PFC_PRIORITIES) - 1; /* all ones */ ++ u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority; ++ u32 nw_prio = 1 << ttp[LLFC_TRAFFIC_TYPE_NW]; ++ struct bnx2x_dcbx_cos_params *cos_params = ++ bp->dcbx_port_params.ets.cos_params; ++ ++ /* get unmapped priorities by clearing mapped bits */ ++ for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++) ++ unmapped &= ~(1 << ttp[i]); ++ ++ /* find cos for nw prio and extend it with unmapped */ ++ for (i = 0; i < ARRAY_SIZE(bp->dcbx_port_params.ets.cos_params); i++) { ++ if (cos_params[i].pri_bitmask & nw_prio) { ++ /* extend the bitmask with unmapped */ ++ DP(NETIF_MSG_LINK, ++ "cos %d extended with 0x%08x", i, unmapped); ++ cos_params[i].pri_bitmask |= unmapped; ++ break; ++ } ++ } ++} ++ + static void bnx2x_get_dcbx_drv_param(struct bnx2x *bp, + struct dcbx_features *features, + u32 error) +@@ -339,6 +365,8 @@ static void bnx2x_get_dcbx_drv_param(struct bnx2x *bp, + bnx2x_dcbx_get_pfc_feature(bp, &features->pfc, error); + + bnx2x_dcbx_get_ets_feature(bp, &features->ets, error); ++ ++ bnx2x_dcbx_map_nw(bp); + } + + #define DCBX_LOCAL_MIB_MAX_TRY_READ (100) +@@ -602,6 +630,8 @@ static inline void bnx2x_dcbx_update_tc_mapping(struct bnx2x *bp) + if (bp->dcbx_port_params.ets.cos_params[cos].pri_bitmask + & (1 << prio)) { + bp->prio_to_cos[prio] = cos; ++ DP(NETIF_MSG_LINK, ++ "tx_mapping %d --> %d\n", prio, cos); + } + } + } +@@ -1614,7 +1644,6 @@ static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp, + pri_join_mask, + num_of_dif_pri); + +- + for (i = 0; i < cos_data.num_of_cos ; i++) { + struct bnx2x_dcbx_cos_params *p = + &bp->dcbx_port_params.ets.cos_params[i]; +-- +1.7.2.2 + diff --git a/patches.drivers/0023-bnx2x-fix-loopback-for-non-10G-link.patch b/patches.drivers/0023-bnx2x-fix-loopback-for-non-10G-link.patch new file mode 100644 index 0000000..928e7c0 --- a/dev/null +++ b/patches.drivers/0023-bnx2x-fix-loopback-for-non-10G-link.patch @@ -0,0 +1,64 @@ +From a346865bc358d2fd8fce6e07c43c6820a2580310 Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Sun, 24 Jul 2011 03:53:21 +0000 +Subject: [PATCH 23/37] bnx2x: fix loopback for non 10G link +Patch-mainline: v3.1-rc1 +Git-commit: 1cb0c788e03da59f14699530aa031a07a89f0056 +References: fate#311461. bnc#698050 + +Also fixes minor formatting in that function. + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_main.c | 24 ++++++++++++++++++------ + 1 files changed, 18 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index 2776865..4192560 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -2150,10 +2150,12 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) + u8 rc; + int cfx_idx = bnx2x_get_link_cfg_idx(bp); + u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx]; +- /* Initialize link parameters structure variables */ +- /* It is recommended to turn off RX FC for jumbo frames +- for better performance */ +- if ((CHIP_IS_E1x(bp)) && (bp->dev->mtu > 5000)) ++ /* ++ * Initialize link parameters structure variables ++ * It is recommended to turn off RX FC for jumbo frames ++ * for better performance ++ */ ++ if (CHIP_IS_E1x(bp) && (bp->dev->mtu > 5000)) + bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX; + else + bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH; +@@ -2161,8 +2163,18 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) + bnx2x_acquire_phy_lock(bp); + + if (load_mode == LOAD_DIAG) { +- bp->link_params.loopback_mode = LOOPBACK_XGXS; +- bp->link_params.req_line_speed[cfx_idx] = SPEED_10000; ++ struct link_params *lp = &bp->link_params; ++ lp->loopback_mode = LOOPBACK_XGXS; ++ /* do PHY loopback at 10G speed, if possible */ ++ if (lp->req_line_speed[cfx_idx] < SPEED_10000) { ++ if (lp->speed_cap_mask[cfx_idx] & ++ PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) ++ lp->req_line_speed[cfx_idx] = ++ SPEED_10000; ++ else ++ lp->req_line_speed[cfx_idx] = ++ SPEED_1000; ++ } + } + + rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars); +-- +1.7.2.2 + diff --git a/patches.drivers/0024-bnx2x-count-statistic-ramrods-on-EQ-to-prevent-MC-as.patch b/patches.drivers/0024-bnx2x-count-statistic-ramrods-on-EQ-to-prevent-MC-as.patch new file mode 100644 index 0000000..13cdef7 --- a/dev/null +++ b/patches.drivers/0024-bnx2x-count-statistic-ramrods-on-EQ-to-prevent-MC-as.patch @@ -0,0 +1,140 @@ +From af142b26308c3917931e77e61ae602c99b1cc693 Mon Sep 17 00:00:00 2001 +From: Vladislav Zolotarov <vladz@broadcom.com> +Date: Sun, 24 Jul 2011 03:54:17 +0000 +Subject: [PATCH 24/37] bnx2x: count statistic ramrods on EQ to prevent MC assert +Patch-mainline: v3.1-rc1 +Git-commit: d6cae2385f00522b3da8a5f964bf8dfa32a0d138 +References: fate#311461. bnc#698050 + +This patch includes: + - Counting statistics ramrods as EQ ramrods the way they should be. This + accounting is meant to prevent MC asserts in case of software bugs. + - Fixes in debug facilities which were added while working on one of such + bugs. + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_main.c | 45 ++++++++++++++++++++------------------- + 1 files changed, 23 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index 4192560..bf0b562 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -1670,11 +1670,12 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe) + + switch (command) { + case (RAMROD_CMD_ID_ETH_CLIENT_UPDATE): +- DP(NETIF_MSG_IFUP, "got UPDATE ramrod. CID %d\n", cid); ++ DP(BNX2X_MSG_SP, "got UPDATE ramrod. CID %d\n", cid); + drv_cmd = BNX2X_Q_CMD_UPDATE; + break; ++ + case (RAMROD_CMD_ID_ETH_CLIENT_SETUP): +- DP(NETIF_MSG_IFUP, "got MULTI[%d] setup ramrod\n", cid); ++ DP(BNX2X_MSG_SP, "got MULTI[%d] setup ramrod\n", cid); + drv_cmd = BNX2X_Q_CMD_SETUP; + break; + +@@ -1684,17 +1685,17 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe) + break; + + case (RAMROD_CMD_ID_ETH_HALT): +- DP(NETIF_MSG_IFDOWN, "got MULTI[%d] halt ramrod\n", cid); ++ DP(BNX2X_MSG_SP, "got MULTI[%d] halt ramrod\n", cid); + drv_cmd = BNX2X_Q_CMD_HALT; + break; + + case (RAMROD_CMD_ID_ETH_TERMINATE): +- DP(NETIF_MSG_IFDOWN, "got MULTI[%d] teminate ramrod\n", cid); ++ DP(BNX2X_MSG_SP, "got MULTI[%d] teminate ramrod\n", cid); + drv_cmd = BNX2X_Q_CMD_TERMINATE; + break; + + case (RAMROD_CMD_ID_ETH_EMPTY): +- DP(NETIF_MSG_IFDOWN, "got MULTI[%d] empty ramrod\n", cid); ++ DP(BNX2X_MSG_SP, "got MULTI[%d] empty ramrod\n", cid); + drv_cmd = BNX2X_Q_CMD_EMPTY; + break; + +@@ -1724,6 +1725,8 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe) + /* push the change in bp->spq_left and towards the memory */ + smp_mb__after_atomic_inc(); + ++ DP(BNX2X_MSG_SP, "bp->cq_spq_left %x\n", atomic_read(&bp->cq_spq_left)); ++ + return; + } + +@@ -3098,26 +3101,23 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, + spe->data.update_data_addr.hi = cpu_to_le32(data_hi); + spe->data.update_data_addr.lo = cpu_to_le32(data_lo); + +- /* stats ramrod has it's own slot on the spq */ +- if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY) { +- /* +- * It's ok if the actual decrement is issued towards the memory +- * somewhere between the spin_lock and spin_unlock. Thus no +- * more explict memory barrier is needed. +- */ +- if (common) +- atomic_dec(&bp->eq_spq_left); +- else +- atomic_dec(&bp->cq_spq_left); +- } ++ /* ++ * It's ok if the actual decrement is issued towards the memory ++ * somewhere between the spin_lock and spin_unlock. Thus no ++ * more explict memory barrier is needed. ++ */ ++ if (common) ++ atomic_dec(&bp->eq_spq_left); ++ else ++ atomic_dec(&bp->cq_spq_left); + + + DP(BNX2X_MSG_SP/*NETIF_MSG_TIMER*/, +- "SPQE[%x] (%x:%x) command %d hw_cid %x data (%x:%x) " +- "type(0x%x) left (ETH, COMMON) (%x,%x)\n", ++ "SPQE[%x] (%x:%x) (cmd, common?) (%d,%d) hw_cid %x data (%x:%x) " ++ "type(0x%x) left (CQ, EQ) (%x,%x)\n", + bp->spq_prod_idx, (u32)U64_HI(bp->spq_mapping), + (u32)(U64_LO(bp->spq_mapping) + +- (void *)bp->spq_prod_bd - (void *)bp->spq), command, ++ (void *)bp->spq_prod_bd - (void *)bp->spq), command, common, + HW_CID(bp, cid), data_hi, data_lo, type, + atomic_read(&bp->cq_spq_left), atomic_read(&bp->eq_spq_left)); + +@@ -3473,6 +3473,7 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn) + } else if (attn & BNX2X_MC_ASSERT_BITS) { + + BNX2X_ERR("MC assert!\n"); ++ bnx2x_mc_assert(bp); + REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_10, 0); + REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_9, 0); + REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_8, 0); +@@ -4432,7 +4433,7 @@ static void bnx2x_eq_int(struct bnx2x *bp) + sw_cons = bp->eq_cons; + sw_prod = bp->eq_prod; + +- DP(BNX2X_MSG_SP, "EQ: hw_cons %u sw_cons %u bp->cq_spq_left %u\n", ++ DP(BNX2X_MSG_SP, "EQ: hw_cons %u sw_cons %u bp->eq_spq_left %x\n", + hw_cons, sw_cons, atomic_read(&bp->eq_spq_left)); + + for (; sw_cons != hw_cons; +@@ -4451,7 +4452,7 @@ static void bnx2x_eq_int(struct bnx2x *bp) + DP(NETIF_MSG_TIMER, "got statistics comp event %d\n", + bp->stats_comp++); + /* nothing to do with stats comp */ +- continue; ++ goto next_spqe; + + case EVENT_RING_OPCODE_CFC_DEL: + /* handle according to cid range */ +-- +1.7.2.2 + diff --git a/patches.drivers/0025-bnx2x-enable-internal-target-read-for-57712-and-up-o.patch b/patches.drivers/0025-bnx2x-enable-internal-target-read-for-57712-and-up-o.patch new file mode 100644 index 0000000..3dba095 --- a/dev/null +++ b/patches.drivers/0025-bnx2x-enable-internal-target-read-for-57712-and-up-o.patch @@ -0,0 +1,42 @@ +From 4518e3bd61e9c6af72fb43241e38d8138687de5a Mon Sep 17 00:00:00 2001 +From: Shmulik Ravid <shmulikr@broadcom.com> +Date: Sun, 24 Jul 2011 03:57:04 +0000 +Subject: [PATCH 25/37] bnx2x: enable internal target-read for 57712 and up only +Patch-mainline: v3.1-rc1 +Git-commit: 2189400b3c29a03360cbe2e3af3299eb5e2b950c +References: fate#311461. bnc#698050 + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Shmulik Ravid <shmulikr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_main.c | 9 ++++++--- + 1 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index bf0b562..39159bb 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -10177,11 +10177,14 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, + REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0 + BP_PORT(bp)*16, 0); + REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0 + BP_PORT(bp)*16, 0); + +- /** ++ /* + * Enable internal target-read (in case we are probed after PF FLR). +- * Must be done prior to any BAR read access ++ * Must be done prior to any BAR read access. Only for 57712 and up + */ +- REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); ++ if (board_type != BCM57710 && ++ board_type != BCM57711 && ++ board_type != BCM57711E) ++ REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); + + /* Reset the load counter */ + bnx2x_clear_load_cnt(bp); +-- +1.7.2.2 + diff --git a/patches.drivers/0026-bnx2x-fix-bnx2x_stop_on_error-flow-in-bnx2x_sp_rtnl_.patch b/patches.drivers/0026-bnx2x-fix-bnx2x_stop_on_error-flow-in-bnx2x_sp_rtnl_.patch new file mode 100644 index 0000000..5f90c86 --- a/dev/null +++ b/patches.drivers/0026-bnx2x-fix-bnx2x_stop_on_error-flow-in-bnx2x_sp_rtnl_.patch @@ -0,0 +1,70 @@ +From ed06b4bfba4aa168e38cd57e11a53700dd2583b5 Mon Sep 17 00:00:00 2001 +From: Vladislav Zolotarov <vladz@broadcom.com> +Date: Sun, 24 Jul 2011 03:57:46 +0000 +Subject: [PATCH 26/37] bnx2x: fix bnx2x_stop_on_error flow in bnx2x_sp_rtnl_task +Patch-mainline: v3.1-rc1 +Git-commit: b1fb8740a279a96d8b6ceedfce334b887908b91d +References: fate#311461. bnc#698050 + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_main.c | 30 +++++++++++++++++++++--------- + 1 files changed, 21 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index 39159bb..b4380a3 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -8425,24 +8425,36 @@ static void bnx2x_sp_rtnl_task(struct work_struct *work) + BNX2X_ERR("recovery flow called but STOP_ON_ERROR defined " + "so reset not done to allow debug dump,\n" + "you will need to reboot when done\n"); +- goto sp_rtnl_exit; ++ goto sp_rtnl_not_reset; + #endif + + if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE)) { + /* +- * Clear TX_TIMEOUT bit as we are going to reset the function +- * anyway. ++ * Clear all pending SP commands as we are going to reset the ++ * function anyway. + */ +- smp_mb__before_clear_bit(); +- clear_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state); +- smp_mb__after_clear_bit(); ++ bp->sp_rtnl_state = 0; + bnx2x_parity_recover(bp); +- } else if (test_and_clear_bit(BNX2X_SP_RTNL_TX_TIMEOUT, +- &bp->sp_rtnl_state)){ ++ ++ goto sp_rtnl_exit; ++ } ++ ++ if (test_and_clear_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state)) { ++ /* ++ * Clear all pending SP commands as we are going to reset the ++ * function anyway. ++ */ ++ bp->sp_rtnl_state = 0; ++ smp_mb(); ++ + bnx2x_nic_unload(bp, UNLOAD_NORMAL); + bnx2x_nic_load(bp, LOAD_NORMAL); +- } + ++ goto sp_rtnl_exit; ++ } ++#ifdef BNX2X_STOP_ON_ERROR ++sp_rtnl_not_reset: ++#endif + sp_rtnl_exit: + rtnl_unlock(); + } +-- +1.7.2.2 + diff --git a/patches.drivers/0027-bnx2x-Prevent-restarting-Tx-during-bnx2x_nic_unload.patch b/patches.drivers/0027-bnx2x-Prevent-restarting-Tx-during-bnx2x_nic_unload.patch new file mode 100644 index 0000000..f77345f --- a/dev/null +++ b/patches.drivers/0027-bnx2x-Prevent-restarting-Tx-during-bnx2x_nic_unload.patch @@ -0,0 +1,55 @@ +From c7d3330e2d66bfaced350807f0e9ac39af5842b9 Mon Sep 17 00:00:00 2001 +From: Vladislav Zolotarov <vladz@broadcom.com> +Date: Mon, 1 Aug 2011 21:52:37 +0000 +Subject: [PATCH 27/37] bnx2x: Prevent restarting Tx during bnx2x_nic_unload +Patch-mainline: v3.1-rc1 +Git-commit: 87b7ba3d24a25cf18aece447de27d7804fa9668c +References: fate#311461. bnc#698050 + +Tx queues were stopped before bp->state was changed to a value different +from BNX2X_STATE_OPEN, which allowed the bnx2x_tx_int() called from the +NAPI context to re-enable it. This then allowed the netdev->ndo_start_xmit() +to be called in the middle of the function reset and rings freeing. + +This patch changes bp->state to a value different +from BNX2X_STATE_OPEN BEFORE disabling the Tx queues in order to restore the +broken protection against the above race in the bnx2x_tx_int(). + +Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_cmn.c | 10 ++++++++-- + 1 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c +index 6d30ea7..a2918be 100644 +--- a/drivers/net/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/bnx2x/bnx2x_cmn.c +@@ -1999,14 +1999,20 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) + return -EINVAL; + } + ++ /* ++ * It's important to set the bp->state to the value different from ++ * BNX2X_STATE_OPEN and only then stop the Tx. Otherwise bnx2x_tx_int() ++ * may restart the Tx from the NAPI context (see bnx2x_tx_int()). ++ */ ++ bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; ++ smp_mb(); ++ + /* Stop Tx */ + bnx2x_tx_disable(bp); + + #ifdef BCM_CNIC + bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD); + #endif +- bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; +- smp_mb(); + + bp->rx_mode = BNX2X_RX_MODE_NONE; + +-- +1.7.2.2 + diff --git a/patches.drivers/0028-bnx2x-Fix-missing-pause-on-for-578xx.patch b/patches.drivers/0028-bnx2x-Fix-missing-pause-on-for-578xx.patch new file mode 100644 index 0000000..d9f9aa2 --- a/dev/null +++ b/patches.drivers/0028-bnx2x-Fix-missing-pause-on-for-578xx.patch @@ -0,0 +1,55 @@ +From 85ff2eeef0fd8dd962de16615ab1e1372060c980 Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 2 Aug 2011 22:59:10 +0000 +Subject: [PATCH 28/37] bnx2x: Fix missing pause on for 578xx +Patch-mainline: v3.1-rc1 +Git-commit: 9d5b36be64b42058e7fd12b71266bbf2bb7600fc +References: fate#311461. bnc#698050 + +When link speed is 1G and below, pause weren't sent due to missing pause setting in the UMAC. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_link.c | 6 ++++++ + drivers/net/bnx2x/bnx2x_reg.h | 2 ++ + 2 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index bcd8f00..aa9958e 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -1546,6 +1546,12 @@ static void bnx2x_umac_enable(struct link_params *params, + vars->line_speed); + break; + } ++ if (!(vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)) ++ val |= UMAC_COMMAND_CONFIG_REG_IGNORE_TX_PAUSE; ++ ++ if (!(vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)) ++ val |= UMAC_COMMAND_CONFIG_REG_PAUSE_IGNORE; ++ + REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val); + udelay(50); + +diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h +index 02461fe..d84642a 100644 +--- a/drivers/net/bnx2x/bnx2x_reg.h ++++ b/drivers/net/bnx2x/bnx2x_reg.h +@@ -4771,9 +4771,11 @@ + The fields are: [4:0] - tail pointer; 10:5] - Link List size; 15:11] - + header pointer. */ + #define UCM_REG_XX_TABLE 0xe0300 ++#define UMAC_COMMAND_CONFIG_REG_IGNORE_TX_PAUSE (0x1<<28) + #define UMAC_COMMAND_CONFIG_REG_LOOP_ENA (0x1<<15) + #define UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK (0x1<<24) + #define UMAC_COMMAND_CONFIG_REG_PAD_EN (0x1<<5) ++#define UMAC_COMMAND_CONFIG_REG_PAUSE_IGNORE (0x1<<8) + #define UMAC_COMMAND_CONFIG_REG_PROMIS_EN (0x1<<4) + #define UMAC_COMMAND_CONFIG_REG_RX_ENA (0x1<<1) + #define UMAC_COMMAND_CONFIG_REG_SW_RESET (0x1<<13) +-- +1.7.2.2 + diff --git a/patches.drivers/0029-bnx2x-Fix-chip-hanging-due-to-TX-pipe-stall.patch b/patches.drivers/0029-bnx2x-Fix-chip-hanging-due-to-TX-pipe-stall.patch new file mode 100644 index 0000000..d7c37a3 --- a/dev/null +++ b/patches.drivers/0029-bnx2x-Fix-chip-hanging-due-to-TX-pipe-stall.patch @@ -0,0 +1,48 @@ +From a0e54fae2c172ad344ab695d03b2cece57938642 Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 2 Aug 2011 22:59:18 +0000 +Subject: [PATCH 29/37] bnx2x: Fix chip hanging due to TX pipe stall. +Patch-mainline: v3.1-rc1 +Git-commit: b507766205f85d6d69892287e346a7c264a216b4 +References: fate#311461. bnc#698050 + +Fix a problem in which the 578xx chip hangs after running traffic, and then pulling the network cable. +This occurs since TX pipe is stalled due to missing XON indication towards the NIG. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_link.c | 12 +++++++++++- + 1 files changed, 11 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index aa9958e..0a7091d 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -1667,10 +1667,20 @@ static void bnx2x_xmac_disable(struct link_params *params) + { + u8 port = params->port; + struct bnx2x *bp = params->bp; +- u32 xmac_base = (port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0; ++ u32 pfc_ctrl, xmac_base = (port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0; + + if (REG_RD(bp, MISC_REG_RESET_REG_2) & + MISC_REGISTERS_RESET_REG_2_XMAC) { ++ /* ++ * Send an indication to change the state in the NIG back to XON ++ * Clearing this bit enables the next set of this bit to get ++ * rising edge ++ */ ++ pfc_ctrl = REG_RD(bp, xmac_base + XMAC_REG_PFC_CTRL_HI); ++ REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI, ++ (pfc_ctrl & ~(1<<1))); ++ REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI, ++ (pfc_ctrl | (1<<1))); + DP(NETIF_MSG_LINK, "Disable XMAC on port %x\n", port); + REG_WR(bp, xmac_base + XMAC_REG_CTRL, 0); + usleep_range(1000, 1000); +-- +1.7.2.2 + diff --git a/patches.drivers/0030-bnx2x-Fix-remote-fault-handling.patch b/patches.drivers/0030-bnx2x-Fix-remote-fault-handling.patch new file mode 100644 index 0000000..2c101af --- a/dev/null +++ b/patches.drivers/0030-bnx2x-Fix-remote-fault-handling.patch @@ -0,0 +1,331 @@ +From 97b5b5270d1983720366718a8468f0807db63592 Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 2 Aug 2011 22:59:25 +0000 +Subject: [PATCH 30/37] bnx2x: Fix remote fault handling +Patch-mainline: v3.1-rc1 +Git-commit: de6f3377d2da3b384ca3d716ffb8687ad175788a +References: fate#311461. bnc#698050 + +Fix couple of issues of remote fault detection and handling: +Link may go down due to remote fault indications during link establishment. +Possible link down after primary function migration. +Remote fault was not detected on 578xx. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_hsi.h | 2 + + drivers/net/bnx2x/bnx2x_link.c | 110 ++++++++++++++++++++++++---------------- + drivers/net/bnx2x/bnx2x_link.h | 2 +- + 3 files changed, 69 insertions(+), 45 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h +index 06727f3..dc24de4 100644 +--- a/drivers/net/bnx2x/bnx2x_hsi.h ++++ b/drivers/net/bnx2x/bnx2x_hsi.h +@@ -1204,6 +1204,8 @@ struct drv_port_mb { + + #define LINK_STATUS_PFC_ENABLED 0x20000000 + ++ #define LINK_STATUS_PHYSICAL_LINK_FLAG 0x40000000 ++ + u32 port_stx; + + u32 stat_nig_timer; +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index 0a7091d..8e68e15 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -1745,6 +1745,10 @@ static int bnx2x_emac_enable(struct link_params *params, + + DP(NETIF_MSG_LINK, "enabling EMAC\n"); + ++ /* Disable BMAC */ ++ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, ++ (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); ++ + /* enable emac and not bmac */ + REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1); + +@@ -2599,12 +2603,6 @@ static int bnx2x_bmac1_enable(struct link_params *params, + REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS, + wb_data, 2); + +- if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) { +- REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LSS_STATUS, +- wb_data, 2); +- if (wb_data[0] > 0) +- return -ESRCH; +- } + return 0; + } + +@@ -2670,16 +2668,6 @@ static int bnx2x_bmac2_enable(struct link_params *params, + udelay(30); + bnx2x_update_pfc_bmac2(params, vars, is_lb); + +- if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) { +- REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LSS_STAT, +- wb_data, 2); +- if (wb_data[0] > 0) { +- DP(NETIF_MSG_LINK, "Got bad LSS status 0x%x\n", +- wb_data[0]); +- return -ESRCH; +- } +- } +- + return 0; + } + +@@ -4369,6 +4357,9 @@ void bnx2x_link_status_update(struct link_params *params, + + vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP); + vars->phy_flags = PHY_XGXS_FLAG; ++ if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG) ++ vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG; ++ + if (vars->link_up) { + DP(NETIF_MSG_LINK, "phy link up\n"); + +@@ -4460,6 +4451,8 @@ void bnx2x_link_status_update(struct link_params *params, + + /* indicate no mac active */ + vars->mac_type = MAC_TYPE_NONE; ++ if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG) ++ vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG; + } + + /* Sync media type */ +@@ -6176,6 +6169,7 @@ static int bnx2x_update_link_down(struct link_params *params, + /* update shared memory */ + vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK | + LINK_STATUS_LINK_UP | ++ LINK_STATUS_PHYSICAL_LINK_FLAG | + LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | + LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | + LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | +@@ -6213,7 +6207,8 @@ static int bnx2x_update_link_up(struct link_params *params, + u8 port = params->port; + int rc = 0; + +- vars->link_status |= LINK_STATUS_LINK_UP; ++ vars->link_status |= (LINK_STATUS_LINK_UP | ++ LINK_STATUS_PHYSICAL_LINK_FLAG); + vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG; + + if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) +@@ -8132,7 +8127,6 @@ void bnx2x_handle_module_detect_int(struct link_params *params) + offsetof(struct shmem_region, dev_info. + port_feature_config[params->port]. + config)); +- + bnx2x_set_gpio_int(bp, gpio_num, + MISC_REGISTERS_GPIO_INT_OUTPUT_SET, + gpio_port); +@@ -8141,8 +8135,9 @@ void bnx2x_handle_module_detect_int(struct link_params *params) + * Disable transmit for this module + */ + phy->media_type = ETH_PHY_NOT_PRESENT; +- if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == +- PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) ++ if (((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == ++ PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) || ++ CHIP_IS_E3(bp)) + bnx2x_sfp_set_transmitter(params, phy, 0); + } + } +@@ -8244,9 +8239,6 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy, + u16 cnt, val, tmp1; + struct bnx2x *bp = params->bp; + +- /* SPF+ PHY: Set flag to check for Tx error */ +- vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG; +- + bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, + MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); + /* HW reset */ +@@ -8430,9 +8422,6 @@ static int bnx2x_8726_config_init(struct bnx2x_phy *phy, + struct bnx2x *bp = params->bp; + DP(NETIF_MSG_LINK, "Initializing BCM8726\n"); + +- /* SPF+ PHY: Set flag to check for Tx error */ +- vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG; +- + bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15); + bnx2x_wait_reset_complete(bp, phy, params); + +@@ -8601,9 +8590,6 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy, + struct bnx2x *bp = params->bp; + /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */ + +- /* SPF+ PHY: Set flag to check for Tx error */ +- vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG; +- + bnx2x_wait_reset_complete(bp, phy, params); + rx_alarm_ctrl_val = (1<<2) | (1<<5) ; + /* Should be 0x6 to enable XS on Tx side. */ +@@ -10619,7 +10605,8 @@ static struct bnx2x_phy phy_warpcore = { + .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT, + .addr = 0xff, + .def_md_devad = 0, +- .flags = FLAGS_HW_LOCK_REQUIRED, ++ .flags = (FLAGS_HW_LOCK_REQUIRED | ++ FLAGS_TX_ERROR_CHECK), + .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, + .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, + .mdio_ctrl = 0, +@@ -10745,7 +10732,8 @@ static struct bnx2x_phy phy_8706 = { + .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706, + .addr = 0xff, + .def_md_devad = 0, +- .flags = FLAGS_INIT_XGXS_FIRST, ++ .flags = (FLAGS_INIT_XGXS_FIRST | ++ FLAGS_TX_ERROR_CHECK), + .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, + .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, + .mdio_ctrl = 0, +@@ -10776,7 +10764,8 @@ static struct bnx2x_phy phy_8726 = { + .addr = 0xff, + .def_md_devad = 0, + .flags = (FLAGS_HW_LOCK_REQUIRED | +- FLAGS_INIT_XGXS_FIRST), ++ FLAGS_INIT_XGXS_FIRST | ++ FLAGS_TX_ERROR_CHECK), + .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, + .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, + .mdio_ctrl = 0, +@@ -10807,7 +10796,8 @@ static struct bnx2x_phy phy_8727 = { + .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727, + .addr = 0xff, + .def_md_devad = 0, +- .flags = FLAGS_FAN_FAILURE_DET_REQ, ++ .flags = (FLAGS_FAN_FAILURE_DET_REQ | ++ FLAGS_TX_ERROR_CHECK), + .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, + .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, + .mdio_ctrl = 0, +@@ -12194,10 +12184,6 @@ static void bnx2x_analyze_link_error(struct link_params *params, + u8 led_mode; + u32 half_open_conn = (vars->phy_flags & PHY_HALF_OPEN_CONN_FLAG) > 0; + +- /*DP(NETIF_MSG_LINK, "CHECK LINK: %x half_open:%x-> lss:%x\n", +- vars->link_up, +- half_open_conn, lss_status);*/ +- + if ((lss_status ^ half_open_conn) == 0) + return; + +@@ -12210,6 +12196,7 @@ static void bnx2x_analyze_link_error(struct link_params *params, + * b. Update link_vars->link_up + */ + if (lss_status) { ++ DP(NETIF_MSG_LINK, "Remote Fault detected !!!\n"); + vars->link_status &= ~LINK_STATUS_LINK_UP; + vars->link_up = 0; + vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG; +@@ -12219,6 +12206,7 @@ static void bnx2x_analyze_link_error(struct link_params *params, + */ + led_mode = LED_MODE_OFF; + } else { ++ DP(NETIF_MSG_LINK, "Remote Fault cleared\n"); + vars->link_status |= LINK_STATUS_LINK_UP; + vars->link_up = 1; + vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG; +@@ -12235,6 +12223,15 @@ static void bnx2x_analyze_link_error(struct link_params *params, + bnx2x_notify_link_changed(bp); + } + ++/****************************************************************************** ++* Description: ++* This function checks for half opened connection change indication. ++* When such change occurs, it calls the bnx2x_analyze_link_error ++* to check if Remote Fault is set or cleared. Reception of remote fault ++* status message in the MAC indicates that the peer's MAC has detected ++* a fault, for example, due to break in the TX side of fiber. ++* ++******************************************************************************/ + static void bnx2x_check_half_open_conn(struct link_params *params, + struct link_vars *vars) + { +@@ -12245,9 +12242,28 @@ static void bnx2x_check_half_open_conn(struct link_params *params, + if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0) + return; + +- if (!CHIP_IS_E3(bp) && ++ if (CHIP_IS_E3(bp) && + (REG_RD(bp, MISC_REG_RESET_REG_2) & +- (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))) { ++ (MISC_REGISTERS_RESET_REG_2_XMAC))) { ++ /* Check E3 XMAC */ ++ /* ++ * Note that link speed cannot be queried here, since it may be ++ * zero while link is down. In case UMAC is active, LSS will ++ * simply not be set ++ */ ++ mac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0; ++ ++ /* Clear stick bits (Requires rising edge) */ ++ REG_WR(bp, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0); ++ REG_WR(bp, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, ++ XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS | ++ XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS); ++ if (REG_RD(bp, mac_base + XMAC_REG_RX_LSS_STATUS)) ++ lss_status = 1; ++ ++ bnx2x_analyze_link_error(params, vars, lss_status); ++ } else if (REG_RD(bp, MISC_REG_RESET_REG_2) & ++ (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) { + /* Check E1X / E2 BMAC */ + u32 lss_status_reg; + u32 wb_data[2]; +@@ -12269,14 +12285,20 @@ static void bnx2x_check_half_open_conn(struct link_params *params, + void bnx2x_period_func(struct link_params *params, struct link_vars *vars) + { + struct bnx2x *bp = params->bp; ++ u16 phy_idx; + if (!params) { +- DP(NETIF_MSG_LINK, "Ininitliazed params !\n"); ++ DP(NETIF_MSG_LINK, "Uninitialized params !\n"); + return; + } +- /* DP(NETIF_MSG_LINK, "Periodic called vars->phy_flags 0x%x speed 0x%x +- RESET_REG_2 0x%x\n", vars->phy_flags, vars->line_speed, +- REG_RD(bp, MISC_REG_RESET_REG_2)); */ +- bnx2x_check_half_open_conn(params, vars); ++ ++ for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) { ++ if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) { ++ bnx2x_set_aer_mmd(params, ¶ms->phy[phy_idx]); ++ bnx2x_check_half_open_conn(params, vars); ++ break; ++ } ++ } ++ + if (CHIP_IS_E3(bp)) + bnx2x_check_over_curr(params, vars); + } +diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h +index 6a7708d..7ee6b51 100644 +--- a/drivers/net/bnx2x/bnx2x_link.h ++++ b/drivers/net/bnx2x/bnx2x_link.h +@@ -145,6 +145,7 @@ struct bnx2x_phy { + #define FLAGS_SFP_NOT_APPROVED (1<<7) + #define FLAGS_MDC_MDIO_WA (1<<8) + #define FLAGS_DUMMY_READ (1<<9) ++#define FLAGS_TX_ERROR_CHECK (1<<12) + + /* preemphasis values for the rx side */ + u16 rx_preemphasis[4]; +@@ -276,7 +277,6 @@ struct link_vars { + #define PHY_PHYSICAL_LINK_FLAG (1<<2) + #define PHY_HALF_OPEN_CONN_FLAG (1<<3) + #define PHY_OVER_CURRENT_FLAG (1<<4) +-#define PHY_TX_ERROR_CHECK_FLAG (1<<5) + + u8 mac_type; + #define MAC_TYPE_NONE 0 +-- +1.7.2.2 + diff --git a/patches.drivers/0031-bnx2x-Fix-BCM578xx-B0-MDIO-access.patch b/patches.drivers/0031-bnx2x-Fix-BCM578xx-B0-MDIO-access.patch new file mode 100644 index 0000000..e206a69 --- a/dev/null +++ b/patches.drivers/0031-bnx2x-Fix-BCM578xx-B0-MDIO-access.patch @@ -0,0 +1,113 @@ +From d82b3acc306600368a61447b9c3562960fce7fa7 Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 2 Aug 2011 22:59:32 +0000 +Subject: [PATCH 31/37] bnx2x: Fix BCM578xx-B0 MDIO access +Patch-mainline: v3.1-rc1 +Git-commit: 157fa283a7cb5bc6a55dd4e0daf6eeef66adf354 +References: fate#311461. bnc#698050 + +Fix MDIO access to Warpcore on new chip version of 578xx. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_link.c | 16 ++++++++++++++-- + drivers/net/bnx2x/bnx2x_link.h | 1 + + drivers/net/bnx2x/bnx2x_reg.h | 4 +++- + 3 files changed, 18 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index 8e68e15..45255bd 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -2953,7 +2953,9 @@ static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy, + u32 val; + u16 i; + int rc = 0; +- ++ if (phy->flags & FLAGS_MDC_MDIO_WA_B0) ++ bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS, ++ EMAC_MDIO_STATUS_10MB); + /* address */ + val = ((phy->addr << 21) | (devad << 16) | reg | + EMAC_MDIO_COMM_COMMAND_ADDRESS | +@@ -3007,6 +3009,9 @@ static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy, + } + } + ++ if (phy->flags & FLAGS_MDC_MDIO_WA_B0) ++ bnx2x_bits_dis(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS, ++ EMAC_MDIO_STATUS_10MB); + return rc; + } + +@@ -3016,6 +3021,9 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy, + u32 tmp; + u8 i; + int rc = 0; ++ if (phy->flags & FLAGS_MDC_MDIO_WA_B0) ++ bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS, ++ EMAC_MDIO_STATUS_10MB); + + /* address */ + +@@ -3069,7 +3077,9 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy, + bnx2x_cl45_read(bp, phy, devad, 0xf, &temp_val); + } + } +- ++ if (phy->flags & FLAGS_MDC_MDIO_WA_B0) ++ bnx2x_bits_dis(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS, ++ EMAC_MDIO_STATUS_10MB); + return rc; + } + +@@ -11118,6 +11128,8 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port, + */ + if (CHIP_REV(bp) == CHIP_REV_Ax) + phy->flags |= FLAGS_MDC_MDIO_WA; ++ else ++ phy->flags |= FLAGS_MDC_MDIO_WA_B0; + } else { + switch (switch_cfg) { + case SWITCH_CFG_1G: +diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h +index 7ee6b51..c12db6d 100644 +--- a/drivers/net/bnx2x/bnx2x_link.h ++++ b/drivers/net/bnx2x/bnx2x_link.h +@@ -145,6 +145,7 @@ struct bnx2x_phy { + #define FLAGS_SFP_NOT_APPROVED (1<<7) + #define FLAGS_MDC_MDIO_WA (1<<8) + #define FLAGS_DUMMY_READ (1<<9) ++#define FLAGS_MDC_MDIO_WA_B0 (1<<10) + #define FLAGS_TX_ERROR_CHECK (1<<12) + + /* preemphasis values for the rx side */ +diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h +index d84642a..27b5ecb 100644 +--- a/drivers/net/bnx2x/bnx2x_reg.h ++++ b/drivers/net/bnx2x/bnx2x_reg.h +@@ -5624,8 +5624,9 @@ + #define EMAC_MDIO_COMM_START_BUSY (1L<<29) + #define EMAC_MDIO_MODE_AUTO_POLL (1L<<4) + #define EMAC_MDIO_MODE_CLAUSE_45 (1L<<31) +-#define EMAC_MDIO_MODE_CLOCK_CNT (0x3fL<<16) ++#define EMAC_MDIO_MODE_CLOCK_CNT (0x3ffL<<16) + #define EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT 16 ++#define EMAC_MDIO_STATUS_10MB (1L<<1) + #define EMAC_MODE_25G_MODE (1L<<5) + #define EMAC_MODE_HALF_DUPLEX (1L<<1) + #define EMAC_MODE_PORT_GMII (2L<<2) +@@ -5636,6 +5637,7 @@ + #define EMAC_REG_EMAC_MAC_MATCH 0x10 + #define EMAC_REG_EMAC_MDIO_COMM 0xac + #define EMAC_REG_EMAC_MDIO_MODE 0xb4 ++#define EMAC_REG_EMAC_MDIO_STATUS 0xb0 + #define EMAC_REG_EMAC_MODE 0x0 + #define EMAC_REG_EMAC_RX_MODE 0xc8 + #define EMAC_REG_EMAC_RX_MTU_SIZE 0x9c +-- +1.7.2.2 + diff --git a/patches.drivers/0032-bnx2x-Fix-LED-behavior.patch b/patches.drivers/0032-bnx2x-Fix-LED-behavior.patch new file mode 100644 index 0000000..97d85c9 --- a/dev/null +++ b/patches.drivers/0032-bnx2x-Fix-LED-behavior.patch @@ -0,0 +1,65 @@ +From 1e957f3f000a59278113af7986d5c2269ba716ba Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 2 Aug 2011 22:59:40 +0000 +Subject: [PATCH 32/37] bnx2x: Fix LED behavior +Patch-mainline: v3.1-rc1 +Git-commit: 793bd450370bf85cd63cccaff5e2f1a62908a52f +References: fate#311461. bnc#698050 + +This fix resolve two problems seen regarding LED: +1. LED doesn't flash during port identification. +2. Traffic LED sometimes do not blink. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_link.c | 24 +++++++++++++++++------- + 1 files changed, 17 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index 45255bd..d8f6eff 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -5922,20 +5922,30 @@ int bnx2x_set_led(struct link_params *params, + tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED); + EMAC_WR(bp, EMAC_REG_EMAC_LED, + (tmp | EMAC_LED_OVERRIDE)); +- return rc; ++ /* ++ * return here without enabling traffic ++ * LED blink andsetting rate in ON mode. ++ * In oper mode, enabling LED blink ++ * and setting rate is needed. ++ */ ++ if (mode == LED_MODE_ON) ++ return rc; + } +- } else if (SINGLE_MEDIA_DIRECT(params) && +- (CHIP_IS_E1x(bp) || +- CHIP_IS_E2(bp))) { ++ } else if (SINGLE_MEDIA_DIRECT(params)) { + /* + * This is a work-around for HW issue found when link + * is up in CL73 + */ +- REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0); + REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1); +- } else { ++ if (CHIP_IS_E1x(bp) || ++ CHIP_IS_E2(bp) || ++ (mode == LED_MODE_ON)) ++ REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0); ++ else ++ REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, ++ hw_led_mode); ++ } else + REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode); +- } + + REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + port*4, 0); + /* Set blinking rate to ~15.9Hz */ +-- +1.7.2.2 + diff --git a/patches.drivers/0033-bnx2x-Fix-link-issue-with-DAC-over-578xx.patch b/patches.drivers/0033-bnx2x-Fix-link-issue-with-DAC-over-578xx.patch new file mode 100644 index 0000000..69553b4 --- a/dev/null +++ b/patches.drivers/0033-bnx2x-Fix-link-issue-with-DAC-over-578xx.patch @@ -0,0 +1,35 @@ +From 80fbd14047e359bce6cd33c0f046f1e5f5b0db73 Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 2 Aug 2011 22:59:47 +0000 +Subject: [PATCH 33/37] bnx2x: Fix link issue with DAC over 578xx +Patch-mainline: v3.1-rc1 +Git-commit: 19af03a3c8cb1e07e31c070dfde9fac2e5e7796c +References: fate#311461. bnc#698050 + +Fix no-link issue on BCM578xx when direct attached cable is connected since Warpcore microcode restart was missing to re-read the new mode. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_link.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index d8f6eff..6a3fdf8 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -8029,6 +8029,9 @@ static void bnx2x_warpcore_set_limiting_mode(struct link_params *params, + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val); + ++ /* Restart microcode to re-read the new mode */ ++ bnx2x_warpcore_reset_lane(bp, phy, 1); ++ bnx2x_warpcore_reset_lane(bp, phy, 0); + + } + +-- +1.7.2.2 + diff --git a/patches.drivers/0034-bnx2x-Fix-BCM84833-link.patch b/patches.drivers/0034-bnx2x-Fix-BCM84833-link.patch new file mode 100644 index 0000000..4ad4a74 --- a/dev/null +++ b/patches.drivers/0034-bnx2x-Fix-BCM84833-link.patch @@ -0,0 +1,71 @@ +From f90c7f51b80c4b0ebd4f493f874559d95e658fea Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 2 Aug 2011 22:59:53 +0000 +Subject: [PATCH 34/37] bnx2x: Fix BCM84833 link +Patch-mainline: v3.1-rc1 +Git-commit: fd38f73eb936f9d9f28e4f7ff598cc0780e09424 +References: fate#311461. bnc#698050 + +BCM84833 fail to link due to incorrect auto-negotiation setting. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_link.c | 21 ++++++++++++--------- + 1 files changed, 12 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index 6a3fdf8..cf8b8d1 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -9268,7 +9268,13 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, + if (phy->req_duplex == DUPLEX_FULL) + autoneg_val |= (1<<8); + +- bnx2x_cl45_write(bp, phy, ++ /* ++ * Always write this if this is not 84833. ++ * For 84833, write it only when it's a forced speed. ++ */ ++ if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) || ++ ((autoneg_val & (1<<12)) == 0)) ++ bnx2x_cl45_write(bp, phy, + MDIO_AN_DEVAD, + MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val); + +@@ -9282,13 +9288,12 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, + bnx2x_cl45_write(bp, phy, + MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, + 0x3200); +- } else if (phy->req_line_speed != SPEED_10 && +- phy->req_line_speed != SPEED_100) { ++ } else + bnx2x_cl45_write(bp, phy, + MDIO_AN_DEVAD, + MDIO_AN_REG_8481_10GBASE_T_AN_CTRL, + 1); +- } ++ + /* Save spirom version */ + bnx2x_save_848xx_spirom_version(phy, params); + +@@ -9781,11 +9786,9 @@ static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy, + bnx2x_cl45_read(bp, phy, + MDIO_CTL_DEVAD, + 0x400f, &val16); +- /* Put to low power mode on newer FW */ +- if ((val16 & 0x303f) > 0x1009) +- bnx2x_cl45_write(bp, phy, +- MDIO_PMA_DEVAD, +- MDIO_PMA_REG_CTRL, 0x800); ++ bnx2x_cl45_write(bp, phy, ++ MDIO_PMA_DEVAD, ++ MDIO_PMA_REG_CTRL, 0x800); + } + } + +-- +1.7.2.2 + diff --git a/patches.drivers/0035-bnx2x-Fix-BCM54618se-invalid-link-indication.patch b/patches.drivers/0035-bnx2x-Fix-BCM54618se-invalid-link-indication.patch new file mode 100644 index 0000000..cd34365 --- a/dev/null +++ b/patches.drivers/0035-bnx2x-Fix-BCM54618se-invalid-link-indication.patch @@ -0,0 +1,43 @@ +From 8c8e7f15262170ccaf140b0f5cd425b3155f7acf Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 2 Aug 2011 23:00:00 +0000 +Subject: [PATCH 35/37] bnx2x: Fix BCM54618se invalid link indication +Patch-mainline: v3.1-rc1 +Git-commit: d2059a061164120a1e44a0ca46fe08044d6d7c2d +References: fate#311461. bnc#698050 + +After resetting BCM54618se, link partner would still see link since the PHY wasn't put into low-power state. + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_link.c | 11 +++++++++-- + 1 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index cf8b8d1..5e6f351 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -10219,8 +10219,15 @@ static void bnx2x_54618se_link_reset(struct bnx2x_phy *phy, + u32 cfg_pin; + u8 port; + +- /* This works with E3 only, no need to check the chip +- before determining the port. */ ++ /* ++ * In case of no EPIO routed to reset the GPHY, put it ++ * in low power mode. ++ */ ++ bnx2x_cl22_write(bp, phy, MDIO_PMA_REG_CTRL, 0x800); ++ /* ++ * This works with E3 only, no need to check the chip ++ * before determining the port. ++ */ + port = params->port; + cfg_pin = (REG_RD(bp, params->shmem_base + + offsetof(struct shmem_region, +-- +1.7.2.2 + diff --git a/patches.drivers/0036-bnx2x-Fix-BCM578xx-MAC-test.patch b/patches.drivers/0036-bnx2x-Fix-BCM578xx-MAC-test.patch new file mode 100644 index 0000000..13cbd5c --- a/dev/null +++ b/patches.drivers/0036-bnx2x-Fix-BCM578xx-MAC-test.patch @@ -0,0 +1,41 @@ +From 4417a7aba3400925ba3b0858f7357714443fe709 Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 2 Aug 2011 23:00:06 +0000 +Subject: [PATCH 36/37] bnx2x: Fix BCM578xx MAC test +Patch-mainline: v3.1-rc1 +Git-commit: afad009ad76ece72a3c9629bbc08f14459b9bba7 +References: fate#311461. bnc#698050 + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_link.c | 9 ++++----- + 1 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index 5e6f351..01fb92c 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -11541,13 +11541,12 @@ void bnx2x_init_xmac_loopback(struct link_params *params, + * Set WC to loopback mode since link is required to provide clock + * to the XMAC in 20G mode + */ +- if (vars->line_speed == SPEED_20000) { +- bnx2x_set_aer_mmd(params, ¶ms->phy[0]); +- bnx2x_warpcore_reset_lane(bp, ¶ms->phy[0], 0); +- params->phy[INT_PHY].config_loopback( ++ bnx2x_set_aer_mmd(params, ¶ms->phy[0]); ++ bnx2x_warpcore_reset_lane(bp, ¶ms->phy[0], 0); ++ params->phy[INT_PHY].config_loopback( + ¶ms->phy[INT_PHY], + params); +- } ++ + bnx2x_xmac_enable(params, vars, 1); + REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); + } +-- +1.7.2.2 + diff --git a/patches.drivers/0037-bnx2x-Clear-MDIO-access-warning-during-first-driver-.patch b/patches.drivers/0037-bnx2x-Clear-MDIO-access-warning-during-first-driver-.patch new file mode 100644 index 0000000..e397833 --- a/dev/null +++ b/patches.drivers/0037-bnx2x-Clear-MDIO-access-warning-during-first-driver-.patch @@ -0,0 +1,41 @@ +From 5dbb1744937fb4409d64228cfc2668f4bfb56f63 Mon Sep 17 00:00:00 2001 +From: Yaniv Rosner <yanivr@broadcom.com> +Date: Tue, 2 Aug 2011 23:00:12 +0000 +Subject: [PATCH 37/37] bnx2x: Clear MDIO access warning during first driver load +Patch-mainline: v3.1-rc1 +Git-commit: 28f4881cbf9ce285edfc245a8990af36d21c062f +References: fate#311461. bnc#698050 + +Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_link.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c +index 01fb92c..d45b155 100644 +--- a/drivers/net/bnx2x/bnx2x_link.c ++++ b/drivers/net/bnx2x/bnx2x_link.c +@@ -11724,12 +11724,16 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars, + bnx2x_set_led(params, vars, LED_MODE_OFF, 0); + + if (reset_ext_phy) { ++ bnx2x_set_mdio_clk(bp, params->chip_id, port); + for (phy_index = EXT_PHY1; phy_index < params->num_phys; + phy_index++) { +- if (params->phy[phy_index].link_reset) ++ if (params->phy[phy_index].link_reset) { ++ bnx2x_set_aer_mmd(params, ++ ¶ms->phy[phy_index]); + params->phy[phy_index].link_reset( + ¶ms->phy[phy_index], + params); ++ } + if (params->phy[phy_index].flags & + FLAGS_REARM_LATCH_SIGNAL) + clear_latch_ind = 1; +-- +1.7.2.2 + diff --git a/patches.drivers/0038-bnx2x-call-netdev_alloc_mq_with_correct_param.patch b/patches.drivers/0038-bnx2x-call-netdev_alloc_mq_with_correct_param.patch new file mode 100644 index 0000000..6f47474 --- a/dev/null +++ b/patches.drivers/0038-bnx2x-call-netdev_alloc_mq_with_correct_param.patch @@ -0,0 +1,29 @@ +From 5aa3bcb53113e49e0f9421e85950ca6c231a724e Mon Sep 17 00:00:00 2001 +References: fate#311461. bnc#698050 + +From: Dmitry Kravkov <dmitry@broadcom.com> +Date: Tue, 9 Aug 2011 13:04:45 -0700 +Subject: [PATCH 38/38] bnx2x: call netdev_alloc_mq +Patch-mainline: no (backport fix only) +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_main.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index 4669679..ef8a9d0 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -10611,7 +10611,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, + tx_count = MAX_TXQS_PER_COS * max_cos_est + FCOE_PRESENT; + + /* dev zeroed in init_etherdev */ +- dev = alloc_etherdev_mq(sizeof(*bp), rx_count); ++ dev = alloc_etherdev_mq(sizeof(*bp), tx_count); + if (!dev) { + dev_err(&pdev->dev, "Cannot allocate net device\n"); + return -ENOMEM; +-- +1.7.6.178.g55272 + diff --git a/patches.drivers/net-3-5-bnx2x-prevent-race-between-undi_unload-and-load-flows.patch b/patches.drivers/net-3-5-bnx2x-prevent-race-between-undi_unload-and-load-flows.patch new file mode 100644 index 0000000..513542d --- a/dev/null +++ b/patches.drivers/net-3-5-bnx2x-prevent-race-between-undi_unload-and-load-flows.patch @@ -0,0 +1,51 @@ +References: fate#311461. bnc#698050 + +From patchwork Tue Aug 9 13:09:52 2011 +Content-type: text/plain; charset="utf-8" +Mime-version: 1.0 +Content-transfer-encoding: 7bit +Subject: [net,3/5] bnx2x: prevent race between undi_unload and load flows +Patch-mainline: v3.1-rc2 +Git-commit: 2031bd3a8adce1259756e7f142b230c010035995 +Date: Tue, 09 Aug 2011 03:09:52 -0000 +From: Dmitry Kravkov <dmitry@broadcom.com> +X-patchwork-id: 109218 +Message-id: <1312895392.21856.2.camel@lb-tlvb-dmitry> +To: davem@davemloft.net, netdev@vger.kernel.org +Cc: "Vladislav Zolotarov" <vladz@broadcom.com>, + "Eilon Greenstein" <eilong@broadcom.com> + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- +drivers/net/bnx2x/bnx2x_main.c | 8 ++++++++ + 1 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index 1507091..1f5467f 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -5798,6 +5798,12 @@ static int bnx2x_init_hw_common(struct bnx2x *bp) + + DP(BNX2X_MSG_MCP, "starting common init func %d\n", BP_ABS_FUNC(bp)); + ++ /* ++ * take the UNDI lock to protect undi_unload flow from accessing ++ * registers while we're resetting the chip ++ */ ++ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); ++ + bnx2x_reset_common(bp); + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff); + +@@ -5808,6 +5814,8 @@ static int bnx2x_init_hw_common(struct bnx2x *bp) + } + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, val); + ++ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); ++ + bnx2x_init_block(bp, BLOCK_MISC, PHASE_COMMON); + + if (!CHIP_IS_E1x(bp)) { diff --git a/patches.drivers/net-4-5-bnx2x-properly-clean-indirect-addresses.patch b/patches.drivers/net-4-5-bnx2x-properly-clean-indirect-addresses.patch new file mode 100644 index 0000000..4b7109d --- a/dev/null +++ b/patches.drivers/net-4-5-bnx2x-properly-clean-indirect-addresses.patch @@ -0,0 +1,89 @@ +References: fate#311461. bnc#698050 + +From patchwork Tue Aug 9 13:10:29 2011 +Content-type: text/plain; charset="utf-8" +Mime-version: 1.0 +Content-transfer-encoding: 7bit +Subject: [net,4/5] bnx2x: properly clean indirect addresses +Patch-mainline: v3.1-rc2 +Git-commit: 9f0096a1578bca77b28762c89b29affee69a20f4 +Date: Tue, 09 Aug 2011 03:10:29 -0000 +From: Dmitry Kravkov <dmitry@broadcom.com> +X-patchwork-id: 109219 +Message-id: <1312895429.21856.3.camel@lb-tlvb-dmitry> +To: davem@davemloft.net, netdev@vger.kernel.org +Cc: "Vladislav Zolotarov" <vladz@broadcom.com>, + "Eilon Greenstein" <eilong@broadcom.com> + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Signed-off-by: Eilon Greenstein <eilong@broadcom.com> +Acked-by: mmarek@suse.cz + +--- +drivers/net/bnx2x/bnx2x_main.c | 15 +++++++++++---- + drivers/net/bnx2x/bnx2x_reg.h | 26 +++++++++++++++++++++----- + 2 files changed, 32 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c +index 1f5467f..f74582a 100644 +--- a/drivers/net/bnx2x/bnx2x_main.c ++++ b/drivers/net/bnx2x/bnx2x_main.c +@@ -10259,10 +10259,17 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, + /* clean indirect addresses */ + pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS, + PCICFG_VENDOR_ID_OFFSET); +- REG_WR(bp, PXP2_REG_PGL_ADDR_88_F0 + BP_PORT(bp)*16, 0); +- REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F0 + BP_PORT(bp)*16, 0); +- REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0 + BP_PORT(bp)*16, 0); +- REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0 + BP_PORT(bp)*16, 0); ++ /* Clean the following indirect addresses for all functions since it ++ * is not used by the driver. ++ */ ++ REG_WR(bp, PXP2_REG_PGL_ADDR_88_F0, 0); ++ REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F0, 0); ++ REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0, 0); ++ REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0, 0); ++ REG_WR(bp, PXP2_REG_PGL_ADDR_88_F1, 0); ++ REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F1, 0); ++ REG_WR(bp, PXP2_REG_PGL_ADDR_90_F1, 0); ++ REG_WR(bp, PXP2_REG_PGL_ADDR_94_F1, 0); + + /* + * Enable internal target-read (in case we are probed after PF FLR). +diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h +index 27b5ecb..40266c1 100644 +--- a/drivers/net/bnx2x/bnx2x_reg.h ++++ b/drivers/net/bnx2x/bnx2x_reg.h +@@ -3007,11 +3007,27 @@ + /* [R 6] Debug only: Number of used entries in the data FIFO */ + #define PXP2_REG_HST_DATA_FIFO_STATUS 0x12047c + /* [R 7] Debug only: Number of used entries in the header FIFO */ +-#define PXP2_REG_HST_HEADER_FIFO_STATUS 0x120478 +-#define PXP2_REG_PGL_ADDR_88_F0 0x120534 +-#define PXP2_REG_PGL_ADDR_8C_F0 0x120538 +-#define PXP2_REG_PGL_ADDR_90_F0 0x12053c +-#define PXP2_REG_PGL_ADDR_94_F0 0x120540 ++#define PXP2_REG_HST_HEADER_FIFO_STATUS 0x120478 ++#define PXP2_REG_PGL_ADDR_88_F0 0x120534 ++/* [R 32] GRC address for configuration access to PCIE config address 0x88. ++ * any write to this PCIE address will cause a GRC write access to the ++ * address that's in t this register */ ++#define PXP2_REG_PGL_ADDR_88_F1 0x120544 ++#define PXP2_REG_PGL_ADDR_8C_F0 0x120538 ++/* [R 32] GRC address for configuration access to PCIE config address 0x8c. ++ * any write to this PCIE address will cause a GRC write access to the ++ * address that's in t this register */ ++#define PXP2_REG_PGL_ADDR_8C_F1 0x120548 ++#define PXP2_REG_PGL_ADDR_90_F0 0x12053c ++/* [R 32] GRC address for configuration access to PCIE config address 0x90. ++ * any write to this PCIE address will cause a GRC write access to the ++ * address that's in t this register */ ++#define PXP2_REG_PGL_ADDR_90_F1 0x12054c ++#define PXP2_REG_PGL_ADDR_94_F0 0x120540 ++/* [R 32] GRC address for configuration access to PCIE config address 0x94. ++ * any write to this PCIE address will cause a GRC write access to the ++ * address that's in t this register */ ++#define PXP2_REG_PGL_ADDR_94_F1 0x120550 + #define PXP2_REG_PGL_CONTROL0 0x120490 + #define PXP2_REG_PGL_CONTROL1 0x120514 + #define PXP2_REG_PGL_DEBUG 0x120520 diff --git a/patches.drivers/net-5-5-bnx2x-disable-dcb-on-unsupported-devices.patch b/patches.drivers/net-5-5-bnx2x-disable-dcb-on-unsupported-devices.patch new file mode 100644 index 0000000..7b33116 --- a/dev/null +++ b/patches.drivers/net-5-5-bnx2x-disable-dcb-on-unsupported-devices.patch @@ -0,0 +1,40 @@ +From 39115b91c145ae43c3c724d7935ac6efb198abb4 Mon Sep 17 00:00:00 2001 +From: Dmitry Kravkov <dmitry@broadcom.com> +Date: Thu, 11 Aug 2011 17:48:23 +0300 +Subject: [PATCH] bnx2x: disable DCB on unsupported devices +Patch-mainline: No (code is different upstream) +References: fate#311461. bnc#698050 + +Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> +Acked-by: mmarek@suse.cz + +--- + drivers/net/bnx2x/bnx2x_dcb.c | 5 +++-- + 1 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c +index eb470c7..b1fca38 100644 +--- a/drivers/net/bnx2x/bnx2x_dcb.c ++++ b/drivers/net/bnx2x/bnx2x_dcb.c +@@ -894,7 +894,7 @@ void bnx2x_dcbx_init(struct bnx2x *bp) + { + u32 dcbx_lldp_params_offset = SHMEM_LLDP_DCBX_PARAMS_NONE; + /* validate: +- * chip of good for dcbx version, ++ * chip rev is good for dcbx, + * dcb is wanted + * the function is pmf + * shmem2 contains DCBX support fields +@@ -902,7 +902,8 @@ void bnx2x_dcbx_init(struct bnx2x *bp) + DP(NETIF_MSG_LINK, "dcb_enable %d bp->port.pmf %d\n", + bp->dcbx_config_params.dcb_enable, bp->port.pmf); + +- if (bp->dcbx_config_params.dcb_enable && ++ if (!CHIP_IS_E1x(bp) && !CHIP_IS_E3(bp) && ++ bp->dcbx_config_params.dcb_enable && + bp->port.pmf && + SHMEM2_HAS(bp, dcbx_lldp_params_offset)) { + dcbx_lldp_params_offset = SHMEM2_RD(bp, +-- +1.7.2.2 + diff --git a/series.conf b/series.conf index af3bf86..4096f4e 100644 --- a/series.conf +++ b/series.conf @@ -9301,6 +9301,49 @@ patches.drivers/bnx2x-broken-self-test-in-sf-mode-on-578xx patches.drivers/bnx2x-configure-silent-stripping-for-a-vid0-vlan-tag + patches.drivers/0001-bnx2x-PFC-fixes.patch + patches.drivers/0002-bnx2x-Change-BCM54616S-to-BCM54618SE.patch + patches.drivers/0003-bnx2x-Add-CL37-BAM-for-Warpcore.patch + patches.drivers/0004-bnx2x-Reset-PHY-due-to-fan-failure-for-578xx.patch + patches.drivers/0005-bnx2x-Fix-false-link-indication-at-link-partner-when.patch + patches.drivers/0006-bnx2x-Fix-BCM84833-initialization.patch + patches.drivers/0007-bnx2x-Add-autogrEEEn-support.patch + patches.drivers/0008-bnx2x-Fix-warning-message-during-57712-8727-initiali.patch + patches.drivers/0009-bnx2x-remove-unnecessary-read-of-PCI_CAP_ID_EXP.patch + patches.drivers/0010-net-bnx2x-fix-DMA-sync-direction.patch + patches.drivers/0011-bnx2x-Renaming-the-reset_task-to-sp_rtnl_task.patch + patches.drivers/0012-bnx2x-Multiple-concurrent-l2-traffic-classes.patch + patches.drivers/0013-bnx2x-add-missing-command-in-error-handling-flow.patch + patches.drivers/0014-bnx2x-stop-tx-before-CNIC_STOP.patch + patches.drivers/0015-bnx2x-remove-unnecessary-dma_sync.patch + patches.drivers/0016-bnx2x-DCB-rework.patch + patches.drivers/0017-bnx2x-use-pci_pcie_cap.patch + patches.drivers/0018-bnx2x-disable-loacal-BH-when-scheduling-FCOE-napi.patch + patches.drivers/0019-bnx2x-use-BNX2X_Q_FLG_TPA_IPV6-for-TPA-queue-configu.patch + patches.drivers/0020-bnx2x-fix-memory-barriers.patch + patches.drivers/0021-bnx2x-disable-FCoE-for-578xx-devices-since-not-yet-s.patch + patches.drivers/0022-bnx2x-dcb-send-all-unmapped-priorities-to-same-COS-a.patch + patches.drivers/0023-bnx2x-fix-loopback-for-non-10G-link.patch + patches.drivers/0024-bnx2x-count-statistic-ramrods-on-EQ-to-prevent-MC-as.patch + patches.drivers/0025-bnx2x-enable-internal-target-read-for-57712-and-up-o.patch + patches.drivers/0026-bnx2x-fix-bnx2x_stop_on_error-flow-in-bnx2x_sp_rtnl_.patch + patches.drivers/0027-bnx2x-Prevent-restarting-Tx-during-bnx2x_nic_unload.patch + patches.drivers/0028-bnx2x-Fix-missing-pause-on-for-578xx.patch + patches.drivers/0029-bnx2x-Fix-chip-hanging-due-to-TX-pipe-stall.patch + patches.drivers/0030-bnx2x-Fix-remote-fault-handling.patch + patches.drivers/0031-bnx2x-Fix-BCM578xx-B0-MDIO-access.patch + patches.drivers/0032-bnx2x-Fix-LED-behavior.patch + patches.drivers/0033-bnx2x-Fix-link-issue-with-DAC-over-578xx.patch + patches.drivers/0034-bnx2x-Fix-BCM84833-link.patch + patches.drivers/0035-bnx2x-Fix-BCM54618se-invalid-link-indication.patch + patches.drivers/0036-bnx2x-Fix-BCM578xx-MAC-test.patch + patches.drivers/0037-bnx2x-Clear-MDIO-access-warning-during-first-driver-.patch + patches.drivers/0038-bnx2x-call-netdev_alloc_mq_with_correct_param.patch + patches.drivers/net-3-5-bnx2x-prevent-race-between-undi_unload-and-load-flows.patch + patches.drivers/net-4-5-bnx2x-properly-clean-indirect-addresses.patch + patches.drivers/net-5-5-bnx2x-disable-dcb-on-unsupported-devices.patch + + patches.drivers/cnic-replace-get_random_bytes-with-random32 patches.drivers/cnic-fix-port_mode-setting patches.drivers/cnic-fix-ring-setup-shutdown-code |