Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Marek <mmarek@suse.cz>2011-08-15 17:03:47 +0200
committerMichal Marek <mmarek@suse.cz>2011-08-15 17:10:58 +0200
commitad018206999662a15597f6154357374c9eb1108c (patch)
treebb8fa23f07a7accbdb0de3924e182021d0474ce5
parentc44dd9aa273ac5952a10a1d03b7b70bb6ddb096c (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).
-rw-r--r--kernel-source.changes106
-rw-r--r--patches.drivers/0001-bnx2x-PFC-fixes.patch223
-rw-r--r--patches.drivers/0002-bnx2x-Change-BCM54616S-to-BCM54618SE.patch248
-rw-r--r--patches.drivers/0003-bnx2x-Add-CL37-BAM-for-Warpcore.patch66
-rw-r--r--patches.drivers/0004-bnx2x-Reset-PHY-due-to-fan-failure-for-578xx.patch174
-rw-r--r--patches.drivers/0005-bnx2x-Fix-false-link-indication-at-link-partner-when.patch143
-rw-r--r--patches.drivers/0006-bnx2x-Fix-BCM84833-initialization.patch136
-rw-r--r--patches.drivers/0007-bnx2x-Add-autogrEEEn-support.patch227
-rw-r--r--patches.drivers/0008-bnx2x-Fix-warning-message-during-57712-8727-initiali.patch44
-rw-r--r--patches.drivers/0009-bnx2x-remove-unnecessary-read-of-PCI_CAP_ID_EXP.patch72
-rw-r--r--patches.drivers/0010-net-bnx2x-fix-DMA-sync-direction.patch48
-rw-r--r--patches.drivers/0011-bnx2x-Renaming-the-reset_task-to-sp_rtnl_task.patch195
-rw-r--r--patches.drivers/0012-bnx2x-Multiple-concurrent-l2-traffic-classes.patch3429
-rw-r--r--patches.drivers/0013-bnx2x-add-missing-command-in-error-handling-flow.patch31
-rw-r--r--patches.drivers/0014-bnx2x-stop-tx-before-CNIC_STOP.patch46
-rw-r--r--patches.drivers/0015-bnx2x-remove-unnecessary-dma_sync.patch40
-rw-r--r--patches.drivers/0016-bnx2x-DCB-rework.patch718
-rw-r--r--patches.drivers/0017-bnx2x-use-pci_pcie_cap.patch33
-rw-r--r--patches.drivers/0018-bnx2x-disable-loacal-BH-when-scheduling-FCOE-napi.patch40
-rw-r--r--patches.drivers/0019-bnx2x-use-BNX2X_Q_FLG_TPA_IPV6-for-TPA-queue-configu.patch62
-rw-r--r--patches.drivers/0020-bnx2x-fix-memory-barriers.patch204
-rw-r--r--patches.drivers/0021-bnx2x-disable-FCoE-for-578xx-devices-since-not-yet-s.patch34
-rw-r--r--patches.drivers/0022-bnx2x-dcb-send-all-unmapped-priorities-to-same-COS-a.patch87
-rw-r--r--patches.drivers/0023-bnx2x-fix-loopback-for-non-10G-link.patch64
-rw-r--r--patches.drivers/0024-bnx2x-count-statistic-ramrods-on-EQ-to-prevent-MC-as.patch140
-rw-r--r--patches.drivers/0025-bnx2x-enable-internal-target-read-for-57712-and-up-o.patch42
-rw-r--r--patches.drivers/0026-bnx2x-fix-bnx2x_stop_on_error-flow-in-bnx2x_sp_rtnl_.patch70
-rw-r--r--patches.drivers/0027-bnx2x-Prevent-restarting-Tx-during-bnx2x_nic_unload.patch55
-rw-r--r--patches.drivers/0028-bnx2x-Fix-missing-pause-on-for-578xx.patch55
-rw-r--r--patches.drivers/0029-bnx2x-Fix-chip-hanging-due-to-TX-pipe-stall.patch48
-rw-r--r--patches.drivers/0030-bnx2x-Fix-remote-fault-handling.patch331
-rw-r--r--patches.drivers/0031-bnx2x-Fix-BCM578xx-B0-MDIO-access.patch113
-rw-r--r--patches.drivers/0032-bnx2x-Fix-LED-behavior.patch65
-rw-r--r--patches.drivers/0033-bnx2x-Fix-link-issue-with-DAC-over-578xx.patch35
-rw-r--r--patches.drivers/0034-bnx2x-Fix-BCM84833-link.patch71
-rw-r--r--patches.drivers/0035-bnx2x-Fix-BCM54618se-invalid-link-indication.patch43
-rw-r--r--patches.drivers/0036-bnx2x-Fix-BCM578xx-MAC-test.patch41
-rw-r--r--patches.drivers/0037-bnx2x-Clear-MDIO-access-warning-during-first-driver-.patch41
-rw-r--r--patches.drivers/0038-bnx2x-call-netdev_alloc_mq_with_correct_param.patch29
-rw-r--r--patches.drivers/net-3-5-bnx2x-prevent-race-between-undi_unload-and-load-flows.patch51
-rw-r--r--patches.drivers/net-4-5-bnx2x-properly-clean-indirect-addresses.patch89
-rw-r--r--patches.drivers/net-5-5-bnx2x-disable-dcb-on-unsupported-devices.patch40
-rw-r--r--series.conf43
43 files changed, 7872 insertions, 0 deletions
diff --git a/kernel-source.changes b/kernel-source.changes
index 7e416b9bf9..c596bd693a 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 0000000000..6a1d5d643d
--- /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 0000000000..66115bed03
--- /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 0000000000..2a71ae0314
--- /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 0000000000..f89422ee41
--- /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 0000000000..ffcf7afd08
--- /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 0000000000..1d1a68cf01
--- /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 0000000000..7ad5c76fbe
--- /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,
++ &params->phy[phy_index]);
+ params->phy[phy_index].link_reset(
+ &params->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 0000000000..85737a095d
--- /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,
+- &params->phy[phy_index]);
++ if (params->phy[phy_index].link_reset)
+ params->phy[phy_index].link_reset(
+ &params->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 0000000000..d51d9324c6
--- /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 0000000000..f4123b5e27
--- /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 0000000000..12117e4f17
--- /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 0000000000..4f82a4220d
--- /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, &params->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, &params->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, &params->flags);
+- data->general.activate_flg = test_bit(BNX2X_Q_FLG_ACTIVE,
+- &params->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, &params->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, &params->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, &params->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, &params->flags);
+- data->rx.outer_vlan_removal_enable_flg =
+- test_bit(BNX2X_Q_FLG_OV, &params->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,
+- &params->flags);
+-
+- if (test_bit(BNX2X_Q_FLG_MCAST, &params->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, &params->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, &params->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, &params->flags);
+- data->tx.tx_switching_flg =
+- test_bit(BNX2X_Q_FLG_TX_SWITCH, &params->flags);
+- data->tx.anti_spoofing_flg =
+- test_bit(BNX2X_Q_FLG_ANTI_SPOOF, &params->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 = &params->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 =
++ &params->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 =
++ &params->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, &params->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 =
++ &params->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 =
+- &params->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 =
+- &params->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 0000000000..fe9a9269fa
--- /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 0000000000..4a880d06c4
--- /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 0000000000..804eb57d37
--- /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 0000000000..181254158d
--- /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,
+ &params->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, &params->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, &params->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 =
++ &params->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 0000000000..cfbb270eb8
--- /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 0000000000..daf4893885
--- /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 0000000000..a368870cc3
--- /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, &params->flags) *
++ data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA_IPV6, &params->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 0000000000..e941de9f84
--- /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 0000000000..9e074fddf7
--- /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 0000000000..f36ecc8667
--- /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 0000000000..928e7c084a
--- /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 0000000000..13cdef72b2
--- /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 0000000000..3dba095ef7
--- /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 0000000000..5f90c86a4a
--- /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 0000000000..f77345f874
--- /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 0000000000..d9f9aa273c
--- /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 0000000000..d7c37a33f8
--- /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 0000000000..2c101afc85
--- /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, &params->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 0000000000..e206a69a0f
--- /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 0000000000..97d85c9f26
--- /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 0000000000..69553b45fe
--- /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 0000000000..4ad4a74720
--- /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 0000000000..cd34365733
--- /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 0000000000..13cbd5c328
--- /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, &params->phy[0]);
+- bnx2x_warpcore_reset_lane(bp, &params->phy[0], 0);
+- params->phy[INT_PHY].config_loopback(
++ bnx2x_set_aer_mmd(params, &params->phy[0]);
++ bnx2x_warpcore_reset_lane(bp, &params->phy[0], 0);
++ params->phy[INT_PHY].config_loopback(
+ &params->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 0000000000..e397833bfc
--- /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,
++ &params->phy[phy_index]);
+ params->phy[phy_index].link_reset(
+ &params->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 0000000000..6f4747495a
--- /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 0000000000..513542dcdd
--- /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 0000000000..4b7109d17d
--- /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 0000000000..7b331163a0
--- /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 af3bf86ac3..4096f4e6e5 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