diff --git a/debian/changelog b/debian/changelog index 86e7aeacb..0c136dc8c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +linux-2.6 (3.2.18-2) UNRELEASED; urgency=low + + [ Ben Hutchings ] + * be2net: Backport most changes up to Linux 3.5-rc1 (Closes: #673391) + - Add support for Skyhawk cards + + -- Ben Hutchings Sun, 27 May 2012 01:12:44 +0100 + linux-2.6 (3.2.18-1) unstable; urgency=low * New upstream stable update: diff --git a/debian/patches/bugfix/all/ethtool-null-terminate-filename-passed-to.patch b/debian/patches/bugfix/all/ethtool-null-terminate-filename-passed-to.patch new file mode 100644 index 000000000..22b472be7 --- /dev/null +++ b/debian/patches/bugfix/all/ethtool-null-terminate-filename-passed-to.patch @@ -0,0 +1,53 @@ +From: Ben Hutchings +Date: Wed, 1 Feb 2012 09:32:25 +0000 +Subject: [PATCH] ethtool: Null-terminate filename passed to + ethtool_ops::flash_device + +commit 786f528119722f564a22ad953411374e06116333 upstream. + +The parameters for ETHTOOL_FLASHDEV include a filename, which ought to +be null-terminated. Currently the only driver that implements +ethtool_ops::flash_device attempts to add a null terminator if +necessary, but does it wrongly. Do it in the ethtool core instead. + +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_ethtool.c | 6 +----- + net/core/ethtool.c | 2 ++ + 2 files changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index 6db6b6a..802e5dd 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -716,12 +716,8 @@ static int + be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) + { + struct be_adapter *adapter = netdev_priv(netdev); +- char file_name[ETHTOOL_FLASH_MAX_FILENAME]; + +- file_name[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0; +- strcpy(file_name, efl->data); +- +- return be_load_fw(adapter, file_name); ++ return be_load_fw(adapter, efl->data); + } + + static int +diff --git a/net/core/ethtool.c b/net/core/ethtool.c +index 369b418..3f79db1 100644 +--- a/net/core/ethtool.c ++++ b/net/core/ethtool.c +@@ -1190,6 +1190,8 @@ static noinline_for_stack int ethtool_flash_device(struct net_device *dev, + if (!dev->ethtool_ops->flash_device) + return -EOPNOTSUPP; + ++ efl.data[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0; ++ + return dev->ethtool_ops->flash_device(dev, &efl); + } + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0001-sweep-the-floors-and-convert-some-.get_drvinfo-routi.patch b/debian/patches/features/all/be2net/0001-sweep-the-floors-and-convert-some-.get_drvinfo-routi.patch new file mode 100644 index 000000000..d62f1fc87 --- /dev/null +++ b/debian/patches/features/all/be2net/0001-sweep-the-floors-and-convert-some-.get_drvinfo-routi.patch @@ -0,0 +1,47 @@ +From: Rick Jones +Date: Mon, 7 Nov 2011 13:29:27 +0000 +Subject: [PATCH 01/58] sweep the floors and convert some .get_drvinfo + routines to strlcpy + +commit 68aad78c5023b8aa82da99b47f9d8cf40e8ca453 upstream. + +Per the mention made by Ben Hutchings that strlcpy is now the preferred +string copy routine for a .get_drvinfo routine, do a bit of floor +sweeping and convert some of the as-yet unconverted ethernet drivers to +it. + +Signed-off-by: Rick Jones +Signed-off-by: David S. Miller +[bwh: Restrict to drivers/net/ethernet/emulex/benet/] +--- + drivers/net/ethernet/emulex/benet/be_ethtool.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index bf8153e..1ad7a28 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -127,8 +127,8 @@ static void be_get_drvinfo(struct net_device *netdev, + memset(fw_on_flash, 0 , sizeof(fw_on_flash)); + be_cmd_get_fw_ver(adapter, adapter->fw_ver, fw_on_flash); + +- strcpy(drvinfo->driver, DRV_NAME); +- strcpy(drvinfo->version, DRV_VER); ++ strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); ++ strlcpy(drvinfo->version, DRV_VER, sizeof(drvinfo->version)); + strncpy(drvinfo->fw_version, adapter->fw_ver, FW_VER_LEN); + if (memcmp(adapter->fw_ver, fw_on_flash, FW_VER_LEN) != 0) { + strcat(drvinfo->fw_version, " ["); +@@ -136,7 +136,8 @@ static void be_get_drvinfo(struct net_device *netdev, + strcat(drvinfo->fw_version, "]"); + } + +- strcpy(drvinfo->bus_info, pci_name(adapter->pdev)); ++ strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), ++ sizeof(drvinfo->bus_info)); + drvinfo->testinfo_len = 0; + drvinfo->regdump_len = 0; + drvinfo->eedump_len = 0; +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0002-be2net-init-vf-_if_handle-vf_pmac_id-to-handle-failu.patch b/debian/patches/features/all/be2net/0002-be2net-init-vf-_if_handle-vf_pmac_id-to-handle-failu.patch new file mode 100644 index 000000000..ef3dd3937 --- /dev/null +++ b/debian/patches/features/all/be2net/0002-be2net-init-vf-_if_handle-vf_pmac_id-to-handle-failu.patch @@ -0,0 +1,227 @@ +From: Sathya Perla +Date: Thu, 10 Nov 2011 19:17:57 +0000 +Subject: [PATCH 02/58] be2net: init (vf)_if_handle/vf_pmac_id to handle + failure scenarios + +commit 30128031d71741ef7d0e32c345e3bf02aa8a0704 upstream. + +Initialize if_handle, vf_if_handle and vf_pmac_id with "-1" so that in +failure cases when be_clear() is called, we can skip over +if_destroy/pmac_del cmds if they have not been created. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 8 ++-- + drivers/net/ethernet/emulex/benet/be_cmds.c | 9 +++-- + drivers/net/ethernet/emulex/benet/be_cmds.h | 4 +- + drivers/net/ethernet/emulex/benet/be_main.c | 55 +++++++++++++++------------ + 4 files changed, 42 insertions(+), 34 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index 644e8fe..4163980 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -289,14 +289,12 @@ struct be_drv_stats { + + struct be_vf_cfg { + unsigned char vf_mac_addr[ETH_ALEN]; +- u32 vf_if_handle; +- u32 vf_pmac_id; ++ int vf_if_handle; ++ int vf_pmac_id; + u16 vf_vlan_tag; + u32 vf_tx_rate; + }; + +-#define BE_INVALID_PMAC_ID 0xffffffff +- + struct be_adapter { + struct pci_dev *pdev; + struct net_device *netdev; +@@ -347,7 +345,7 @@ struct be_adapter { + + /* Ethtool knobs and info */ + char fw_ver[FW_VER_LEN]; +- u32 if_handle; /* Used to configure filtering */ ++ int if_handle; /* Used to configure filtering */ + u32 pmac_id; /* MAC addr handle used by BE card */ + u32 beacon_state; /* for set_phys_id */ + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 2c7b366..c5912c4 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -695,12 +695,15 @@ err: + } + + /* Uses synchronous MCCQ */ +-int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id, u32 dom) ++int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_pmac_del *req; + int status; + ++ if (pmac_id == -1) ++ return 0; ++ + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); +@@ -1136,7 +1139,7 @@ err: + } + + /* Uses MCCQ */ +-int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id, u32 domain) ++int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_if_destroy *req; +@@ -1145,7 +1148,7 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id, u32 domain) + if (adapter->eeh_err) + return -EIO; + +- if (!interface_id) ++ if (interface_id == -1) + return 0; + + spin_lock_bh(&adapter->mcc_lock); +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h +index a35cd03..0818039 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.h ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.h +@@ -1417,11 +1417,11 @@ extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, + extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, + u32 if_id, u32 *pmac_id, u32 domain); + extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, +- u32 pmac_id, u32 domain); ++ int pmac_id, u32 domain); + extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, + u32 en_flags, u8 *mac, u32 *if_handle, u32 *pmac_id, + u32 domain); +-extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle, ++extern int be_cmd_if_destroy(struct be_adapter *adapter, int if_handle, + u32 domain); + extern int be_cmd_eq_create(struct be_adapter *adapter, + struct be_queue_info *eq, int eq_delay); +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index bf266a0..83d971d 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -848,15 +848,11 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) + if (!is_valid_ether_addr(mac) || (vf >= num_vfs)) + return -EINVAL; + +- if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID) +- status = be_cmd_pmac_del(adapter, +- adapter->vf_cfg[vf].vf_if_handle, +- adapter->vf_cfg[vf].vf_pmac_id, vf + 1); ++ status = be_cmd_pmac_del(adapter, adapter->vf_cfg[vf].vf_if_handle, ++ adapter->vf_cfg[vf].vf_pmac_id, vf + 1); + +- status = be_cmd_pmac_add(adapter, mac, +- adapter->vf_cfg[vf].vf_if_handle, ++ status = be_cmd_pmac_add(adapter, mac, adapter->vf_cfg[vf].vf_if_handle, + &adapter->vf_cfg[vf].vf_pmac_id, vf + 1); +- + if (status) + dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n", + mac, vf); +@@ -2488,17 +2484,13 @@ static void be_vf_clear(struct be_adapter *adapter) + { + u32 vf; + +- for (vf = 0; vf < num_vfs; vf++) { +- if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID) +- be_cmd_pmac_del(adapter, +- adapter->vf_cfg[vf].vf_if_handle, +- adapter->vf_cfg[vf].vf_pmac_id, vf + 1); +- } ++ for (vf = 0; vf < num_vfs; vf++) ++ be_cmd_pmac_del(adapter, adapter->vf_cfg[vf].vf_if_handle, ++ adapter->vf_cfg[vf].vf_pmac_id, vf + 1); + + for (vf = 0; vf < num_vfs; vf++) +- if (adapter->vf_cfg[vf].vf_if_handle) +- be_cmd_if_destroy(adapter, +- adapter->vf_cfg[vf].vf_if_handle, vf + 1); ++ be_cmd_if_destroy(adapter, adapter->vf_cfg[vf].vf_if_handle, ++ vf + 1); + } + + static int be_clear(struct be_adapter *adapter) +@@ -2511,22 +2503,30 @@ static int be_clear(struct be_adapter *adapter) + be_mcc_queues_destroy(adapter); + be_rx_queues_destroy(adapter); + be_tx_queues_destroy(adapter); +- adapter->eq_next_idx = 0; +- +- adapter->be3_native = false; +- adapter->promiscuous = false; + + /* tell fw we're done with firing cmds */ + be_cmd_fw_clean(adapter); + return 0; + } + ++static void be_vf_setup_init(struct be_adapter *adapter) ++{ ++ int vf; ++ ++ for (vf = 0; vf < num_vfs; vf++) { ++ adapter->vf_cfg[vf].vf_if_handle = -1; ++ adapter->vf_cfg[vf].vf_pmac_id = -1; ++ } ++} ++ + static int be_vf_setup(struct be_adapter *adapter) + { + u32 cap_flags, en_flags, vf; + u16 lnk_speed; + int status; + ++ be_vf_setup_init(adapter); ++ + cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST; + for (vf = 0; vf < num_vfs; vf++) { + status = be_cmd_if_create(adapter, cap_flags, en_flags, NULL, +@@ -2534,7 +2534,6 @@ static int be_vf_setup(struct be_adapter *adapter) + NULL, vf+1); + if (status) + goto err; +- adapter->vf_cfg[vf].vf_pmac_id = BE_INVALID_PMAC_ID; + } + + if (!lancer_chip(adapter)) { +@@ -2555,6 +2554,16 @@ err: + return status; + } + ++static void be_setup_init(struct be_adapter *adapter) ++{ ++ adapter->vlan_prio_bmap = 0xff; ++ adapter->link_speed = -1; ++ adapter->if_handle = -1; ++ adapter->be3_native = false; ++ adapter->promiscuous = false; ++ adapter->eq_next_idx = 0; ++} ++ + static int be_setup(struct be_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; +@@ -2563,9 +2572,7 @@ static int be_setup(struct be_adapter *adapter) + int status; + u8 mac[ETH_ALEN]; + +- /* Allow all priorities by default. A GRP5 evt may modify this */ +- adapter->vlan_prio_bmap = 0xff; +- adapter->link_speed = -1; ++ be_setup_init(adapter); + + be_cmd_req_native_mode(adapter); + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0003-be2net-stop-checking-the-UE-registers-after-an-EEH-e.patch b/debian/patches/features/all/be2net/0003-be2net-stop-checking-the-UE-registers-after-an-EEH-e.patch new file mode 100644 index 000000000..7eaf85073 --- /dev/null +++ b/debian/patches/features/all/be2net/0003-be2net-stop-checking-the-UE-registers-after-an-EEH-e.patch @@ -0,0 +1,40 @@ +From: Sathya Perla +Date: Thu, 10 Nov 2011 19:17:58 +0000 +Subject: [PATCH 03/58] be2net: stop checking the UE registers after an EEH + error + +commit 72f02485626b3e71955e54d227ede1b54021d571 upstream. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 83d971d..99da07f 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1978,6 +1978,9 @@ void be_detect_dump_ue(struct be_adapter *adapter) + u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0; + u32 i; + ++ if (adapter->eeh_err || adapter->ue_detected) ++ return; ++ + if (lancer_chip(adapter)) { + sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); + if (sliport_status & SLIPORT_STATUS_ERR_MASK) { +@@ -2039,8 +2042,7 @@ static void be_worker(struct work_struct *work) + struct be_rx_obj *rxo; + int i; + +- if (!adapter->ue_detected) +- be_detect_dump_ue(adapter); ++ be_detect_dump_ue(adapter); + + /* when interrupts are not yet enabled, just reap any pending + * mcc completions */ +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0004-be2net-don-t-log-more-than-one-error-on-detecting-EE.patch b/debian/patches/features/all/be2net/0004-be2net-don-t-log-more-than-one-error-on-detecting-EE.patch new file mode 100644 index 000000000..a38df1341 --- /dev/null +++ b/debian/patches/features/all/be2net/0004-be2net-don-t-log-more-than-one-error-on-detecting-EE.patch @@ -0,0 +1,73 @@ +From: Sathya Perla +Date: Thu, 10 Nov 2011 19:17:59 +0000 +Subject: [PATCH 04/58] be2net: don't log more than one error on detecting + EEH/UE errors + +commit 434b3648e9a58600cea5f3a1a0a7a89048e4df61 upstream. + +Currently we're spamming error messages each time a FW cmd call is made +while in EEH/UE error state. One log msg on error detection is enough. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 15 +++------------ + drivers/net/ethernet/emulex/benet/be_main.c | 3 ++- + 2 files changed, 5 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index c5912c4..94cd77c 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -31,11 +31,8 @@ static void be_mcc_notify(struct be_adapter *adapter) + struct be_queue_info *mccq = &adapter->mcc_obj.q; + u32 val = 0; + +- if (adapter->eeh_err) { +- dev_info(&adapter->pdev->dev, +- "Error in Card Detected! Cannot issue commands\n"); ++ if (adapter->eeh_err) + return; +- } + + val |= mccq->id & DB_MCCQ_RING_ID_MASK; + val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; +@@ -298,19 +295,13 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) + int msecs = 0; + u32 ready; + +- if (adapter->eeh_err) { +- dev_err(&adapter->pdev->dev, +- "Error detected in card.Cannot issue commands\n"); ++ if (adapter->eeh_err) + return -EIO; +- } + + do { + ready = ioread32(db); +- if (ready == 0xffffffff) { +- dev_err(&adapter->pdev->dev, +- "pci slot disconnected\n"); ++ if (ready == 0xffffffff) + return -1; +- } + + ready &= MPU_MAILBOX_DB_RDY_MASK; + if (ready) +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 99da07f..0e97b6d 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -2007,7 +2007,8 @@ void be_detect_dump_ue(struct be_adapter *adapter) + sliport_status & SLIPORT_STATUS_ERR_MASK) { + adapter->ue_detected = true; + adapter->eeh_err = true; +- dev_err(&adapter->pdev->dev, "UE Detected!!\n"); ++ dev_err(&adapter->pdev->dev, ++ "Unrecoverable error in the card\n"); + } + + if (ue_lo) { +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0005-be2net-stop-issuing-FW-cmds-if-any-cmd-times-out.patch b/debian/patches/features/all/be2net/0005-be2net-stop-issuing-FW-cmds-if-any-cmd-times-out.patch new file mode 100644 index 000000000..a59c78840 --- /dev/null +++ b/debian/patches/features/all/be2net/0005-be2net-stop-issuing-FW-cmds-if-any-cmd-times-out.patch @@ -0,0 +1,158 @@ +From: Sathya Perla +Date: Thu, 10 Nov 2011 19:18:00 +0000 +Subject: [PATCH 05/58] be2net: stop issuing FW cmds if any cmd times out + +commit 6589ade019dcab245d3bb847370f855b56cdf6ad upstream. + +A FW cmd timeout (with a sufficiently large timeout value in the +order of tens of seconds) indicates an unresponsive FW. In this state +issuing further cmds and waiting for a completion will only stall the process. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 8 +++++++- + drivers/net/ethernet/emulex/benet/be_cmds.c | 29 ++++++++++----------------- + drivers/net/ethernet/emulex/benet/be_main.c | 2 ++ + 3 files changed, 20 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index 4163980..34f162d 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -350,6 +350,8 @@ struct be_adapter { + u32 beacon_state; /* for set_phys_id */ + + bool eeh_err; ++ bool ue_detected; ++ bool fw_timeout; + u32 port_num; + bool promiscuous; + bool wol; +@@ -357,7 +359,6 @@ struct be_adapter { + u32 function_caps; + u32 rx_fc; /* Rx flow control */ + u32 tx_fc; /* Tx flow control */ +- bool ue_detected; + bool stats_cmd_sent; + int link_speed; + u8 port_type; +@@ -522,6 +523,11 @@ static inline bool be_multi_rxq(const struct be_adapter *adapter) + return adapter->num_rx_qs > 1; + } + ++static inline bool be_error(struct be_adapter *adapter) ++{ ++ return adapter->eeh_err || adapter->ue_detected || adapter->fw_timeout; ++} ++ + extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, + u16 num_popped); + extern void be_link_status_update(struct be_adapter *adapter, u32 link_status); +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 94cd77c..ad3eef0 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -31,7 +31,7 @@ static void be_mcc_notify(struct be_adapter *adapter) + struct be_queue_info *mccq = &adapter->mcc_obj.q; + u32 val = 0; + +- if (adapter->eeh_err) ++ if (be_error(adapter)) + return; + + val |= mccq->id & DB_MCCQ_RING_ID_MASK; +@@ -263,10 +263,10 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) + int i, num, status = 0; + struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; + +- if (adapter->eeh_err) +- return -EIO; +- + for (i = 0; i < mcc_timeout; i++) { ++ if (be_error(adapter)) ++ return -EIO; ++ + num = be_process_mcc(adapter, &status); + if (num) + be_cq_notify(adapter, mcc_obj->cq.id, +@@ -277,7 +277,8 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) + udelay(100); + } + if (i == mcc_timeout) { +- dev_err(&adapter->pdev->dev, "mccq poll timed out\n"); ++ dev_err(&adapter->pdev->dev, "FW not responding\n"); ++ adapter->fw_timeout = true; + return -1; + } + return status; +@@ -295,10 +296,10 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) + int msecs = 0; + u32 ready; + +- if (adapter->eeh_err) +- return -EIO; +- + do { ++ if (be_error(adapter)) ++ return -EIO; ++ + ready = ioread32(db); + if (ready == 0xffffffff) + return -1; +@@ -308,7 +309,8 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) + break; + + if (msecs > 4000) { +- dev_err(&adapter->pdev->dev, "mbox poll timed out\n"); ++ dev_err(&adapter->pdev->dev, "FW not responding\n"); ++ adapter->fw_timeout = true; + be_detect_dump_ue(adapter); + return -1; + } +@@ -546,9 +548,6 @@ int be_cmd_fw_clean(struct be_adapter *adapter) + u8 *wrb; + int status; + +- if (adapter->eeh_err) +- return -EIO; +- + if (mutex_lock_interruptible(&adapter->mbox_lock)) + return -1; + +@@ -1012,9 +1011,6 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, + u8 subsys = 0, opcode = 0; + int status; + +- if (adapter->eeh_err) +- return -EIO; +- + if (mutex_lock_interruptible(&adapter->mbox_lock)) + return -1; + +@@ -1136,9 +1132,6 @@ int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain) + struct be_cmd_req_if_destroy *req; + int status; + +- if (adapter->eeh_err) +- return -EIO; +- + if (interface_id == -1) + return 0; + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 0e97b6d..ce20d64 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -3569,6 +3569,8 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) + + dev_info(&adapter->pdev->dev, "EEH reset\n"); + adapter->eeh_err = false; ++ adapter->ue_detected = false; ++ adapter->fw_timeout = false; + + status = pci_enable_device(pdev); + if (status) +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0006-be2net-Fix-TX-queue-create-for-Lancer.patch b/debian/patches/features/all/be2net/0006-be2net-Fix-TX-queue-create-for-Lancer.patch new file mode 100644 index 000000000..c91fa961d --- /dev/null +++ b/debian/patches/features/all/be2net/0006-be2net-Fix-TX-queue-create-for-Lancer.patch @@ -0,0 +1,99 @@ +From: Padmanabh Ratnakar +Date: Wed, 16 Nov 2011 02:02:23 +0000 +Subject: [PATCH 06/58] be2net: Fix TX queue create for Lancer + +commit 293c4a7d9b95d0beeb5df03c14bd35bc21f9e6f2 upstream. + +Lancer uses V1 version of TXQ create. This command needs interface +id for TX queue creation. Rearrange code such that tx queue create +is after interface create. As TXQ create is now called after MCC +ring create use MCC instead of MBOX. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 15 ++++++++++----- + drivers/net/ethernet/emulex/benet/be_main.c | 12 ++++++++---- + 2 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index ad3eef0..d35a214 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -916,10 +916,14 @@ int be_cmd_txq_create(struct be_adapter *adapter, + void *ctxt; + int status; + +- if (mutex_lock_interruptible(&adapter->mbox_lock)) +- return -1; ++ spin_lock_bh(&adapter->mcc_lock); ++ ++ wrb = wrb_from_mccq(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto err; ++ } + +- wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); + ctxt = &req->context; + +@@ -945,14 +949,15 @@ int be_cmd_txq_create(struct be_adapter *adapter, + + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + +- status = be_mbox_notify_wait(adapter); ++ status = be_mcc_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_eth_tx_create *resp = embedded_payload(wrb); + txq->id = le16_to_cpu(resp->cid); + txq->created = true; + } + +- mutex_unlock(&adapter->mbox_lock); ++err: ++ spin_unlock_bh(&adapter->mcc_lock); + + return status; + } +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index ce20d64..c982b51 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1689,9 +1689,6 @@ static int be_tx_queues_create(struct be_adapter *adapter) + if (be_queue_alloc(adapter, q, TX_Q_LEN, + sizeof(struct be_eth_wrb))) + goto err; +- +- if (be_cmd_txq_create(adapter, q, cq)) +- goto err; + } + return 0; + +@@ -2572,8 +2569,9 @@ static int be_setup(struct be_adapter *adapter) + struct net_device *netdev = adapter->netdev; + u32 cap_flags, en_flags; + u32 tx_fc, rx_fc; +- int status; ++ int status, i; + u8 mac[ETH_ALEN]; ++ struct be_tx_obj *txo; + + be_setup_init(adapter); + +@@ -2613,6 +2611,12 @@ static int be_setup(struct be_adapter *adapter) + if (status != 0) + goto err; + ++ for_all_tx_queues(adapter, txo, i) { ++ status = be_cmd_txq_create(adapter, &txo->q, &txo->cq); ++ if (status) ++ goto err; ++ } ++ + /* For BEx, the VF's permanent mac queried from card is incorrect. + * Query the mac configued by the PF using if_handle + */ +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0007-be2net-add-register-dump-feature-for-Lancer.patch b/debian/patches/features/all/be2net/0007-be2net-add-register-dump-feature-for-Lancer.patch new file mode 100644 index 000000000..da53f4a31 --- /dev/null +++ b/debian/patches/features/all/be2net/0007-be2net-add-register-dump-feature-for-Lancer.patch @@ -0,0 +1,234 @@ +From: Padmanabh Ratnakar +Date: Wed, 16 Nov 2011 02:02:43 +0000 +Subject: [PATCH 07/58] be2net: add register dump feature for Lancer + +commit de49bd5a447887fa630c54bb2769102d50fbe40a upstream. + +Implement register dump using ethtool for Lancer. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 47 +++++++++++++++ + drivers/net/ethernet/emulex/benet/be_cmds.h | 34 +++++++++++ + drivers/net/ethernet/emulex/benet/be_ethtool.c | 74 ++++++++++++++++++++++-- + 3 files changed, 151 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index d35a214..1522065 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -1828,6 +1828,53 @@ err_unlock: + return status; + } + ++int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, ++ u32 data_size, u32 data_offset, const char *obj_name, ++ u32 *data_read, u32 *eof, u8 *addn_status) ++{ ++ struct be_mcc_wrb *wrb; ++ struct lancer_cmd_req_read_object *req; ++ struct lancer_cmd_resp_read_object *resp; ++ int status; ++ ++ spin_lock_bh(&adapter->mcc_lock); ++ ++ wrb = wrb_from_mccq(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto err_unlock; ++ } ++ ++ req = embedded_payload(wrb); ++ ++ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, ++ OPCODE_COMMON_READ_OBJECT, ++ sizeof(struct lancer_cmd_req_read_object), wrb, ++ NULL); ++ ++ req->desired_read_len = cpu_to_le32(data_size); ++ req->read_offset = cpu_to_le32(data_offset); ++ strcpy(req->object_name, obj_name); ++ req->descriptor_count = cpu_to_le32(1); ++ req->buf_len = cpu_to_le32(data_size); ++ req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF)); ++ req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma)); ++ ++ status = be_mcc_notify_wait(adapter); ++ ++ resp = embedded_payload(wrb); ++ if (!status) { ++ *data_read = le32_to_cpu(resp->actual_read_len); ++ *eof = le32_to_cpu(resp->eof); ++ } else { ++ *addn_status = resp->additional_status; ++ } ++ ++err_unlock: ++ spin_unlock_bh(&adapter->mcc_lock); ++ return status; ++} ++ + int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, + u32 flash_type, u32 flash_opcode, u32 buf_size) + { +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h +index 0818039..2d3fe6a 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.h ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.h +@@ -189,6 +189,7 @@ struct be_mcc_mailbox { + #define OPCODE_COMMON_GET_PHY_DETAILS 102 + #define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103 + #define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121 ++#define OPCODE_COMMON_READ_OBJECT 171 + #define OPCODE_COMMON_WRITE_OBJECT 172 + + #define OPCODE_ETH_RSS_CONFIG 1 +@@ -1161,6 +1162,36 @@ struct lancer_cmd_resp_write_object { + u32 actual_write_len; + }; + ++/************************ Lancer Read FW info **************/ ++#define LANCER_READ_FILE_CHUNK (32*1024) ++#define LANCER_READ_FILE_EOF_MASK 0x80000000 ++ ++#define LANCER_FW_DUMP_FILE "/dbg/dump.bin" ++ ++struct lancer_cmd_req_read_object { ++ struct be_cmd_req_hdr hdr; ++ u32 desired_read_len; ++ u32 read_offset; ++ u8 object_name[104]; ++ u32 descriptor_count; ++ u32 buf_len; ++ u32 addr_low; ++ u32 addr_high; ++}; ++ ++struct lancer_cmd_resp_read_object { ++ u8 opcode; ++ u8 subsystem; ++ u8 rsvd1[2]; ++ u8 status; ++ u8 additional_status; ++ u8 rsvd2[2]; ++ u32 resp_len; ++ u32 actual_resp_len; ++ u32 actual_read_len; ++ u32 eof; ++}; ++ + /************************ WOL *******************************/ + struct be_cmd_req_acpi_wol_magic_config{ + struct be_cmd_req_hdr hdr; +@@ -1480,6 +1511,9 @@ extern int lancer_cmd_write_object(struct be_adapter *adapter, + u32 data_size, u32 data_offset, + const char *obj_name, + u32 *data_written, u8 *addn_status); ++int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, ++ u32 data_size, u32 data_offset, const char *obj_name, ++ u32 *data_read, u32 *eof, u8 *addn_status); + int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, + int offset); + extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index 1ad7a28..1e7252e 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -143,15 +143,77 @@ static void be_get_drvinfo(struct net_device *netdev, + drvinfo->eedump_len = 0; + } + ++static u32 ++lancer_cmd_get_file_len(struct be_adapter *adapter, u8 *file_name) ++{ ++ u32 data_read = 0, eof; ++ u8 addn_status; ++ struct be_dma_mem data_len_cmd; ++ int status; ++ ++ memset(&data_len_cmd, 0, sizeof(data_len_cmd)); ++ /* data_offset and data_size should be 0 to get reg len */ ++ status = lancer_cmd_read_object(adapter, &data_len_cmd, 0, 0, ++ file_name, &data_read, &eof, &addn_status); ++ ++ return data_read; ++} ++ ++static int ++lancer_cmd_read_file(struct be_adapter *adapter, u8 *file_name, ++ u32 buf_len, void *buf) ++{ ++ struct be_dma_mem read_cmd; ++ u32 read_len = 0, total_read_len = 0, chunk_size; ++ u32 eof = 0; ++ u8 addn_status; ++ int status = 0; ++ ++ read_cmd.size = LANCER_READ_FILE_CHUNK; ++ read_cmd.va = pci_alloc_consistent(adapter->pdev, read_cmd.size, ++ &read_cmd.dma); ++ ++ if (!read_cmd.va) { ++ dev_err(&adapter->pdev->dev, ++ "Memory allocation failure while reading dump\n"); ++ return -ENOMEM; ++ } ++ ++ while ((total_read_len < buf_len) && !eof) { ++ chunk_size = min_t(u32, (buf_len - total_read_len), ++ LANCER_READ_FILE_CHUNK); ++ chunk_size = ALIGN(chunk_size, 4); ++ status = lancer_cmd_read_object(adapter, &read_cmd, chunk_size, ++ total_read_len, file_name, &read_len, ++ &eof, &addn_status); ++ if (!status) { ++ memcpy(buf + total_read_len, read_cmd.va, read_len); ++ total_read_len += read_len; ++ eof &= LANCER_READ_FILE_EOF_MASK; ++ } else { ++ status = -EIO; ++ break; ++ } ++ } ++ pci_free_consistent(adapter->pdev, read_cmd.size, read_cmd.va, ++ read_cmd.dma); ++ ++ return status; ++} ++ + static int + be_get_reg_len(struct net_device *netdev) + { + struct be_adapter *adapter = netdev_priv(netdev); + u32 log_size = 0; + +- if (be_physfn(adapter)) +- be_cmd_get_reg_len(adapter, &log_size); +- ++ if (be_physfn(adapter)) { ++ if (lancer_chip(adapter)) ++ log_size = lancer_cmd_get_file_len(adapter, ++ LANCER_FW_DUMP_FILE); ++ else ++ be_cmd_get_reg_len(adapter, &log_size); ++ } + return log_size; + } + +@@ -162,7 +224,11 @@ be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf) + + if (be_physfn(adapter)) { + memset(buf, 0, regs->len); +- be_cmd_get_regs(adapter, regs->len, buf); ++ if (lancer_chip(adapter)) ++ lancer_cmd_read_file(adapter, LANCER_FW_DUMP_FILE, ++ regs->len, buf); ++ else ++ be_cmd_get_regs(adapter, regs->len, buf); + } + } + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0008-be2net-Add-EEPROM-dump-feature-for-Lancer.patch b/debian/patches/features/all/be2net/0008-be2net-Add-EEPROM-dump-feature-for-Lancer.patch new file mode 100644 index 000000000..cc5e232dd --- /dev/null +++ b/debian/patches/features/all/be2net/0008-be2net-Add-EEPROM-dump-feature-for-Lancer.patch @@ -0,0 +1,70 @@ +From: Padmanabh Ratnakar +Date: Wed, 16 Nov 2011 02:03:07 +0000 +Subject: [PATCH 08/58] be2net: Add EEPROM dump feature for Lancer + +commit af5875bdfed02a10a0c76bbd547753fea7979244 upstream. + +Implemented eeprom dump using ethtool feature for Lancer. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.h | 2 ++ + drivers/net/ethernet/emulex/benet/be_ethtool.c | 21 ++++++++++++++++++++- + 2 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h +index 2d3fe6a..ac11246 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.h ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.h +@@ -1167,6 +1167,8 @@ struct lancer_cmd_resp_write_object { + #define LANCER_READ_FILE_EOF_MASK 0x80000000 + + #define LANCER_FW_DUMP_FILE "/dbg/dump.bin" ++#define LANCER_VPD_PF_FILE "/vpd/ntr_pf.vpd" ++#define LANCER_VPD_VF_FILE "/vpd/ntr_vf.vpd" + + struct lancer_cmd_req_read_object { + struct be_cmd_req_hdr hdr; +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index 1e7252e..575c783 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -727,7 +727,17 @@ be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) + static int + be_get_eeprom_len(struct net_device *netdev) + { +- return BE_READ_SEEPROM_LEN; ++ struct be_adapter *adapter = netdev_priv(netdev); ++ if (lancer_chip(adapter)) { ++ if (be_physfn(adapter)) ++ return lancer_cmd_get_file_len(adapter, ++ LANCER_VPD_PF_FILE); ++ else ++ return lancer_cmd_get_file_len(adapter, ++ LANCER_VPD_VF_FILE); ++ } else { ++ return BE_READ_SEEPROM_LEN; ++ } + } + + static int +@@ -742,6 +752,15 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, + if (!eeprom->len) + return -EINVAL; + ++ if (lancer_chip(adapter)) { ++ if (be_physfn(adapter)) ++ return lancer_cmd_read_file(adapter, LANCER_VPD_PF_FILE, ++ eeprom->len, data); ++ else ++ return lancer_cmd_read_file(adapter, LANCER_VPD_VF_FILE, ++ eeprom->len, data); ++ } ++ + eeprom->magic = BE_VENDOR_ID | (adapter->pdev->device<<16); + + memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem)); +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0009-be2net-Fix-VLAN-promiscous-mode-for-Lancer.patch b/debian/patches/features/all/be2net/0009-be2net-Fix-VLAN-promiscous-mode-for-Lancer.patch new file mode 100644 index 000000000..6dc104bf4 --- /dev/null +++ b/debian/patches/features/all/be2net/0009-be2net-Fix-VLAN-promiscous-mode-for-Lancer.patch @@ -0,0 +1,33 @@ +From: Padmanabh Ratnakar +Date: Wed, 16 Nov 2011 02:03:32 +0000 +Subject: [PATCH 09/58] be2net: Fix VLAN promiscous mode for Lancer + +commit 5d5adb93d0efca8b47cc3e649a41ba650ff3d270 upstream. + +To enable VLAN promiscous mode, the HW interface should be created +with VLAN promiscous capability in Lancer. Add this capability during +creation of the HW interface. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index c982b51..93869d4 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -2600,7 +2600,8 @@ static int be_setup(struct be_adapter *adapter) + en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS; + cap_flags = en_flags | BE_IF_FLAGS_MCAST_PROMISCUOUS | +- BE_IF_FLAGS_PROMISCUOUS; ++ BE_IF_FLAGS_VLAN_PROMISCUOUS | BE_IF_FLAGS_PROMISCUOUS; ++ + if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) { + cap_flags |= BE_IF_FLAGS_RSS; + en_flags |= BE_IF_FLAGS_RSS; +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0010-be2net-Use-V1-query-link-status-command-for-lancer.patch b/debian/patches/features/all/be2net/0010-be2net-Use-V1-query-link-status-command-for-lancer.patch new file mode 100644 index 000000000..1220a6791 --- /dev/null +++ b/debian/patches/features/all/be2net/0010-be2net-Use-V1-query-link-status-command-for-lancer.patch @@ -0,0 +1,31 @@ +From: Padmanabh Ratnakar +Date: Wed, 16 Nov 2011 02:03:45 +0000 +Subject: [PATCH 10/58] be2net: Use V1 query link status command for lancer + +commit daad6167d97b43cfc448cfe698784730b53ed3d6 upstream. + +Use V1 version of query link status command for Lancer. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 1522065..64f0c1a 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -1246,6 +1246,9 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, + } + req = embedded_payload(wrb); + ++ if (lancer_chip(adapter)) ++ req->hdr.version = 1; ++ + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL); + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0011-be2net-Move-to-new-SR-IOV-implementation-in-Lancer.patch b/debian/patches/features/all/be2net/0011-be2net-Move-to-new-SR-IOV-implementation-in-Lancer.patch new file mode 100644 index 000000000..107b345d8 --- /dev/null +++ b/debian/patches/features/all/be2net/0011-be2net-Move-to-new-SR-IOV-implementation-in-Lancer.patch @@ -0,0 +1,393 @@ +From: Padmanabh Ratnakar +Date: Fri, 25 Nov 2011 05:47:26 +0000 +Subject: [PATCH 11/58] be2net: Move to new SR-IOV implementation in Lancer + +commit 590c391dd362479b27a67c8d797ce348c5798b93 upstream. + +SR-IOV implementation is Lancer has changed in following ways - +1)PF driver assigns one MAC addresses for VF using COMMON_SET_IFACE_MAC_LIST. +2)VF driver queries its MAC address using COMMON_GET_IFACE_MAC_LIST command +and assigns it to its interface. + +Signed-off-by: Mammatha Edhala +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 99 ++++++++++++++++++++++++++- + drivers/net/ethernet/emulex/benet/be_cmds.h | 37 +++++++++- + drivers/net/ethernet/emulex/benet/be_main.c | 89 +++++++++++++++++------- + 3 files changed, 200 insertions(+), 25 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 64f0c1a..7988798 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -609,7 +609,7 @@ int be_cmd_eq_create(struct be_adapter *adapter, + + /* Use MCC */ + int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, +- u8 type, bool permanent, u32 if_handle) ++ u8 type, bool permanent, u32 if_handle, u32 pmac_id) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_mac_query *req; +@@ -631,6 +631,7 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, + req->permanent = 1; + } else { + req->if_id = cpu_to_le16((u16) if_handle); ++ req->pmac_id = cpu_to_le32(pmac_id); + req->permanent = 0; + } + +@@ -2280,3 +2281,99 @@ err: + mutex_unlock(&adapter->mbox_lock); + return status; + } ++ ++/* Uses synchronous MCCQ */ ++int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain, ++ u32 *pmac_id) ++{ ++ struct be_mcc_wrb *wrb; ++ struct be_cmd_req_get_mac_list *req; ++ int status; ++ int mac_count; ++ ++ spin_lock_bh(&adapter->mcc_lock); ++ ++ wrb = wrb_from_mccq(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto err; ++ } ++ req = embedded_payload(wrb); ++ ++ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, ++ OPCODE_COMMON_GET_MAC_LIST, sizeof(*req), ++ wrb, NULL); ++ ++ req->hdr.domain = domain; ++ ++ status = be_mcc_notify_wait(adapter); ++ if (!status) { ++ struct be_cmd_resp_get_mac_list *resp = ++ embedded_payload(wrb); ++ int i; ++ u8 *ctxt = &resp->context[0][0]; ++ status = -EIO; ++ mac_count = resp->mac_count; ++ be_dws_le_to_cpu(&resp->context, sizeof(resp->context)); ++ for (i = 0; i < mac_count; i++) { ++ if (!AMAP_GET_BITS(struct amap_get_mac_list_context, ++ act, ctxt)) { ++ *pmac_id = AMAP_GET_BITS ++ (struct amap_get_mac_list_context, ++ macid, ctxt); ++ status = 0; ++ break; ++ } ++ ctxt += sizeof(struct amap_get_mac_list_context) / 8; ++ } ++ } ++ ++err: ++ spin_unlock_bh(&adapter->mcc_lock); ++ return status; ++} ++ ++/* Uses synchronous MCCQ */ ++int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, ++ u8 mac_count, u32 domain) ++{ ++ struct be_mcc_wrb *wrb; ++ struct be_cmd_req_set_mac_list *req; ++ int status; ++ struct be_dma_mem cmd; ++ ++ memset(&cmd, 0, sizeof(struct be_dma_mem)); ++ cmd.size = sizeof(struct be_cmd_req_set_mac_list); ++ cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, ++ &cmd.dma, GFP_KERNEL); ++ if (!cmd.va) { ++ dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); ++ return -ENOMEM; ++ } ++ ++ spin_lock_bh(&adapter->mcc_lock); ++ ++ wrb = wrb_from_mccq(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto err; ++ } ++ ++ req = cmd.va; ++ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, ++ OPCODE_COMMON_SET_MAC_LIST, sizeof(*req), ++ wrb, &cmd); ++ ++ req->hdr.domain = domain; ++ req->mac_count = mac_count; ++ if (mac_count) ++ memcpy(req->mac, mac_array, ETH_ALEN*mac_count); ++ ++ status = be_mcc_notify_wait(adapter); ++ ++err: ++ dma_free_coherent(&adapter->pdev->dev, cmd.size, ++ cmd.va, cmd.dma); ++ spin_unlock_bh(&adapter->mcc_lock); ++ return status; ++} +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h +index ac11246..0b694c6 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.h ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.h +@@ -189,6 +189,8 @@ struct be_mcc_mailbox { + #define OPCODE_COMMON_GET_PHY_DETAILS 102 + #define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103 + #define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121 ++#define OPCODE_COMMON_GET_MAC_LIST 147 ++#define OPCODE_COMMON_SET_MAC_LIST 148 + #define OPCODE_COMMON_READ_OBJECT 171 + #define OPCODE_COMMON_WRITE_OBJECT 172 + +@@ -295,6 +297,7 @@ struct be_cmd_req_mac_query { + u8 type; + u8 permanent; + u16 if_id; ++ u32 pmac_id; + } __packed; + + struct be_cmd_resp_mac_query { +@@ -1340,6 +1343,34 @@ struct be_cmd_resp_set_func_cap { + u8 rsvd[212]; + }; + ++/******************** GET/SET_MACLIST **************************/ ++#define BE_MAX_MAC 64 ++struct amap_get_mac_list_context { ++ u8 macid[31]; ++ u8 act; ++} __packed; ++ ++struct be_cmd_req_get_mac_list { ++ struct be_cmd_req_hdr hdr; ++ u32 rsvd; ++} __packed; ++ ++struct be_cmd_resp_get_mac_list { ++ struct be_cmd_resp_hdr hdr; ++ u8 mac_count; ++ u8 rsvd1; ++ u16 rsvd2; ++ u8 context[sizeof(struct amap_get_mac_list_context) / 8][BE_MAX_MAC]; ++} __packed; ++ ++struct be_cmd_req_set_mac_list { ++ struct be_cmd_req_hdr hdr; ++ u8 mac_count; ++ u8 rsvd1; ++ u16 rsvd2; ++ struct macaddr mac[BE_MAX_MAC]; ++} __packed; ++ + /*************** HW Stats Get v1 **********************************/ + #define BE_TXP_SW_SZ 48 + struct be_port_rxf_stats_v1 { +@@ -1446,7 +1477,7 @@ static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter) + extern int be_pci_fnum_get(struct be_adapter *adapter); + extern int be_cmd_POST(struct be_adapter *adapter); + extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, +- u8 type, bool permanent, u32 if_handle); ++ u8 type, bool permanent, u32 if_handle, u32 pmac_id); + extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, + u32 if_id, u32 *pmac_id, u32 domain); + extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, +@@ -1542,4 +1573,8 @@ extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter); + extern int be_cmd_req_native_mode(struct be_adapter *adapter); + extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size); + extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf); ++extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain, ++ u32 *pmac_id); ++extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, ++ u8 mac_count, u32 domain); + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 93869d4..c6fb7c3 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -237,7 +237,8 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) + return -EADDRNOTAVAIL; + + status = be_cmd_mac_addr_query(adapter, current_mac, +- MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle); ++ MAC_ADDRESS_TYPE_NETWORK, false, ++ adapter->if_handle, 0); + if (status) + goto err; + +@@ -848,11 +849,18 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) + if (!is_valid_ether_addr(mac) || (vf >= num_vfs)) + return -EINVAL; + +- status = be_cmd_pmac_del(adapter, adapter->vf_cfg[vf].vf_if_handle, ++ if (lancer_chip(adapter)) { ++ status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1); ++ } else { ++ status = be_cmd_pmac_del(adapter, ++ adapter->vf_cfg[vf].vf_if_handle, + adapter->vf_cfg[vf].vf_pmac_id, vf + 1); + +- status = be_cmd_pmac_add(adapter, mac, adapter->vf_cfg[vf].vf_if_handle, ++ status = be_cmd_pmac_add(adapter, mac, ++ adapter->vf_cfg[vf].vf_if_handle, + &adapter->vf_cfg[vf].vf_pmac_id, vf + 1); ++ } ++ + if (status) + dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n", + mac, vf); +@@ -2465,13 +2473,18 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter) + be_vf_eth_addr_generate(adapter, mac); + + for (vf = 0; vf < num_vfs; vf++) { +- status = be_cmd_pmac_add(adapter, mac, ++ if (lancer_chip(adapter)) { ++ status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1); ++ } else { ++ status = be_cmd_pmac_add(adapter, mac, + adapter->vf_cfg[vf].vf_if_handle, + &adapter->vf_cfg[vf].vf_pmac_id, + vf + 1); ++ } ++ + if (status) + dev_err(&adapter->pdev->dev, +- "Mac address add failed for VF %d\n", vf); ++ "Mac address assignment failed for VF %d\n", vf); + else + memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN); + +@@ -2484,9 +2497,14 @@ static void be_vf_clear(struct be_adapter *adapter) + { + u32 vf; + +- for (vf = 0; vf < num_vfs; vf++) +- be_cmd_pmac_del(adapter, adapter->vf_cfg[vf].vf_if_handle, +- adapter->vf_cfg[vf].vf_pmac_id, vf + 1); ++ for (vf = 0; vf < num_vfs; vf++) { ++ if (lancer_chip(adapter)) ++ be_cmd_set_mac_list(adapter, NULL, 0, vf + 1); ++ else ++ be_cmd_pmac_del(adapter, ++ adapter->vf_cfg[vf].vf_if_handle, ++ adapter->vf_cfg[vf].vf_pmac_id, vf + 1); ++ } + + for (vf = 0; vf < num_vfs; vf++) + be_cmd_if_destroy(adapter, adapter->vf_cfg[vf].vf_if_handle, +@@ -2527,7 +2545,9 @@ static int be_vf_setup(struct be_adapter *adapter) + + be_vf_setup_init(adapter); + +- cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST; ++ cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | ++ BE_IF_FLAGS_MULTICAST; ++ + for (vf = 0; vf < num_vfs; vf++) { + status = be_cmd_if_create(adapter, cap_flags, en_flags, NULL, + &adapter->vf_cfg[vf].vf_if_handle, +@@ -2536,11 +2556,9 @@ static int be_vf_setup(struct be_adapter *adapter) + goto err; + } + +- if (!lancer_chip(adapter)) { +- status = be_vf_eth_addr_config(adapter); +- if (status) +- goto err; +- } ++ status = be_vf_eth_addr_config(adapter); ++ if (status) ++ goto err; + + for (vf = 0; vf < num_vfs; vf++) { + status = be_cmd_link_status_query(adapter, NULL, &lnk_speed, +@@ -2564,6 +2582,23 @@ static void be_setup_init(struct be_adapter *adapter) + adapter->eq_next_idx = 0; + } + ++static int be_configure_mac_from_list(struct be_adapter *adapter, u8 *mac) ++{ ++ u32 pmac_id; ++ int status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id); ++ if (status != 0) ++ goto do_none; ++ status = be_cmd_mac_addr_query(adapter, mac, ++ MAC_ADDRESS_TYPE_NETWORK, ++ false, adapter->if_handle, pmac_id); ++ if (status != 0) ++ goto do_none; ++ status = be_cmd_pmac_add(adapter, mac, adapter->if_handle, ++ &adapter->pmac_id, 0); ++do_none: ++ return status; ++} ++ + static int be_setup(struct be_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; +@@ -2591,7 +2626,7 @@ static int be_setup(struct be_adapter *adapter) + + memset(mac, 0, ETH_ALEN); + status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK, +- true /*permanent */, 0); ++ true /*permanent */, 0, 0); + if (status) + return status; + memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); +@@ -2618,12 +2653,17 @@ static int be_setup(struct be_adapter *adapter) + goto err; + } + +- /* For BEx, the VF's permanent mac queried from card is incorrect. +- * Query the mac configued by the PF using if_handle +- */ +- if (!be_physfn(adapter) && !lancer_chip(adapter)) { +- status = be_cmd_mac_addr_query(adapter, mac, +- MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle); ++ /* The VF's permanent mac queried from card is incorrect. ++ * For BEx: Query the mac configued by the PF using if_handle ++ * For Lancer: Get and use mac_list to obtain mac address. ++ */ ++ if (!be_physfn(adapter)) { ++ if (lancer_chip(adapter)) ++ status = be_configure_mac_from_list(adapter, mac); ++ else ++ status = be_cmd_mac_addr_query(adapter, mac, ++ MAC_ADDRESS_TYPE_NETWORK, false, ++ adapter->if_handle, 0); + if (!status) { + memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); + memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN); +@@ -2639,12 +2679,15 @@ static int be_setup(struct be_adapter *adapter) + be_set_rx_mode(adapter->netdev); + + status = be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc); +- if (status) ++ /* For Lancer: It is legal for this cmd to fail on VF */ ++ if (status && (be_physfn(adapter) || !lancer_chip(adapter))) + goto err; ++ + if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc) { + status = be_cmd_set_flow_control(adapter, adapter->tx_fc, + adapter->rx_fc); +- if (status) ++ /* For Lancer: It is legal for this cmd to fail on VF */ ++ if (status && (be_physfn(adapter) || !lancer_chip(adapter))) + goto err; + } + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0012-be2net-Fix-error-recovery-paths.patch b/debian/patches/features/all/be2net/0012-be2net-Fix-error-recovery-paths.patch new file mode 100644 index 000000000..dc251f391 --- /dev/null +++ b/debian/patches/features/all/be2net/0012-be2net-Fix-error-recovery-paths.patch @@ -0,0 +1,37 @@ +From: Padmanabh Ratnakar +Date: Fri, 25 Nov 2011 05:48:06 +0000 +Subject: [PATCH 12/58] be2net: Fix error recovery paths + +commit 3bb62f4f95ba004048bafb460179b5db33aff787 upstream. + +When TX queues are created again after error recovery, +netif_set_real_num_tx_queues() is invoked to update number of real +TX queues created. rtnl lock needs to be held when invoking this routine. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index c6fb7c3..a1b8ebc 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1666,9 +1666,12 @@ static int be_tx_queues_create(struct be_adapter *adapter) + u8 i; + + adapter->num_tx_qs = be_num_txqs_want(adapter); +- if (adapter->num_tx_qs != MAX_TX_QS) ++ if (adapter->num_tx_qs != MAX_TX_QS) { ++ rtnl_lock(); + netif_set_real_num_tx_queues(adapter->netdev, + adapter->num_tx_qs); ++ rtnl_unlock(); ++ } + + adapter->tx_eq.max_eqd = 0; + adapter->tx_eq.min_eqd = 0; +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0013-be2net-Add-error-handling-for-Lancer.patch b/debian/patches/features/all/be2net/0013-be2net-Add-error-handling-for-Lancer.patch new file mode 100644 index 000000000..f56a473c9 --- /dev/null +++ b/debian/patches/features/all/be2net/0013-be2net-Add-error-handling-for-Lancer.patch @@ -0,0 +1,212 @@ +From: Padmanabh Ratnakar +Date: Fri, 25 Nov 2011 05:48:23 +0000 +Subject: [PATCH 13/58] be2net: Add error handling for Lancer + +commit d8110f62c020ebc49108de57510a1482bfcbe86a upstream. + +Detect error in Lancer by polling a HW register and +recover from this error if it is recoverable. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 155 ++++++++++++++++++--------- + 1 file changed, 106 insertions(+), 49 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index a1b8ebc..66429ea 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -2044,52 +2044,6 @@ void be_detect_dump_ue(struct be_adapter *adapter) + } + } + +-static void be_worker(struct work_struct *work) +-{ +- struct be_adapter *adapter = +- container_of(work, struct be_adapter, work.work); +- struct be_rx_obj *rxo; +- int i; +- +- be_detect_dump_ue(adapter); +- +- /* when interrupts are not yet enabled, just reap any pending +- * mcc completions */ +- if (!netif_running(adapter->netdev)) { +- int mcc_compl, status = 0; +- +- mcc_compl = be_process_mcc(adapter, &status); +- +- if (mcc_compl) { +- struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; +- be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl); +- } +- +- goto reschedule; +- } +- +- if (!adapter->stats_cmd_sent) { +- if (lancer_chip(adapter)) +- lancer_cmd_get_pport_stats(adapter, +- &adapter->stats_cmd); +- else +- be_cmd_get_stats(adapter, &adapter->stats_cmd); +- } +- +- for_all_rx_queues(adapter, rxo, i) { +- be_rx_eqd_update(adapter, rxo); +- +- if (rxo->rx_post_starved) { +- rxo->rx_post_starved = false; +- be_post_rx_frags(rxo, GFP_KERNEL); +- } +- } +- +-reschedule: +- adapter->work_counter++; +- schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); +-} +- + static void be_msix_disable(struct be_adapter *adapter) + { + if (msix_enabled(adapter)) { +@@ -3328,7 +3282,7 @@ static int be_dev_family_check(struct be_adapter *adapter) + + static int lancer_wait_ready(struct be_adapter *adapter) + { +-#define SLIPORT_READY_TIMEOUT 500 ++#define SLIPORT_READY_TIMEOUT 30 + u32 sliport_status; + int status = 0, i; + +@@ -3337,7 +3291,7 @@ static int lancer_wait_ready(struct be_adapter *adapter) + if (sliport_status & SLIPORT_STATUS_RDY_MASK) + break; + +- msleep(20); ++ msleep(1000); + } + + if (i == SLIPORT_READY_TIMEOUT) +@@ -3374,6 +3328,104 @@ static int lancer_test_and_set_rdy_state(struct be_adapter *adapter) + return status; + } + ++static void lancer_test_and_recover_fn_err(struct be_adapter *adapter) ++{ ++ int status; ++ u32 sliport_status; ++ ++ if (adapter->eeh_err || adapter->ue_detected) ++ return; ++ ++ sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); ++ ++ if (sliport_status & SLIPORT_STATUS_ERR_MASK) { ++ dev_err(&adapter->pdev->dev, ++ "Adapter in error state." ++ "Trying to recover.\n"); ++ ++ status = lancer_test_and_set_rdy_state(adapter); ++ if (status) ++ goto err; ++ ++ netif_device_detach(adapter->netdev); ++ ++ if (netif_running(adapter->netdev)) ++ be_close(adapter->netdev); ++ ++ be_clear(adapter); ++ ++ adapter->fw_timeout = false; ++ ++ status = be_setup(adapter); ++ if (status) ++ goto err; ++ ++ if (netif_running(adapter->netdev)) { ++ status = be_open(adapter->netdev); ++ if (status) ++ goto err; ++ } ++ ++ netif_device_attach(adapter->netdev); ++ ++ dev_err(&adapter->pdev->dev, ++ "Adapter error recovery succeeded\n"); ++ } ++ return; ++err: ++ dev_err(&adapter->pdev->dev, ++ "Adapter error recovery failed\n"); ++} ++ ++static void be_worker(struct work_struct *work) ++{ ++ struct be_adapter *adapter = ++ container_of(work, struct be_adapter, work.work); ++ struct be_rx_obj *rxo; ++ int i; ++ ++ if (lancer_chip(adapter)) ++ lancer_test_and_recover_fn_err(adapter); ++ ++ be_detect_dump_ue(adapter); ++ ++ /* when interrupts are not yet enabled, just reap any pending ++ * mcc completions */ ++ if (!netif_running(adapter->netdev)) { ++ int mcc_compl, status = 0; ++ ++ mcc_compl = be_process_mcc(adapter, &status); ++ ++ if (mcc_compl) { ++ struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; ++ be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl); ++ } ++ ++ goto reschedule; ++ } ++ ++ if (!adapter->stats_cmd_sent) { ++ if (lancer_chip(adapter)) ++ lancer_cmd_get_pport_stats(adapter, ++ &adapter->stats_cmd); ++ else ++ be_cmd_get_stats(adapter, &adapter->stats_cmd); ++ } ++ ++ for_all_rx_queues(adapter, rxo, i) { ++ be_rx_eqd_update(adapter, rxo); ++ ++ if (rxo->rx_post_starved) { ++ rxo->rx_post_starved = false; ++ be_post_rx_frags(rxo, GFP_KERNEL); ++ } ++ } ++ ++reschedule: ++ adapter->work_counter++; ++ schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); ++} ++ + static int __devinit be_probe(struct pci_dev *pdev, + const struct pci_device_id *pdev_id) + { +@@ -3426,7 +3478,12 @@ static int __devinit be_probe(struct pci_dev *pdev, + goto disable_sriov; + + if (lancer_chip(adapter)) { +- status = lancer_test_and_set_rdy_state(adapter); ++ status = lancer_wait_ready(adapter); ++ if (!status) { ++ iowrite32(SLI_PORT_CONTROL_IP_MASK, ++ adapter->db + SLIPORT_CONTROL_OFFSET); ++ status = lancer_test_and_set_rdy_state(adapter); ++ } + if (status) { + dev_err(&pdev->dev, "Adapter in non recoverable error\n"); + goto ctrl_clean; +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0014-be2net-Use-new-hash-key.patch b/debian/patches/features/all/be2net/0014-be2net-Use-new-hash-key.patch new file mode 100644 index 000000000..67f33382c --- /dev/null +++ b/debian/patches/features/all/be2net/0014-be2net-Use-new-hash-key.patch @@ -0,0 +1,34 @@ +From: Padmanabh Ratnakar +Date: Fri, 25 Nov 2011 05:48:38 +0000 +Subject: [PATCH 14/58] be2net: Use new hash key + +commit 65f8584e253f4676c8b39e976a10e918ec984b7c upstream. + +This new hash key gives better distribution of packets across RX +queues. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 7988798..62868ea 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -1669,8 +1669,9 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_rss_config *req; +- u32 myhash[10] = {0x0123, 0x4567, 0x89AB, 0xCDEF, 0x01EF, +- 0x0123, 0x4567, 0x89AB, 0xCDEF, 0x01EF}; ++ u32 myhash[10] = {0x15d43fa5, 0x2534685a, 0x5f87693a, 0x5668494e, ++ 0x33cf6a53, 0x383334c6, 0x76ac4257, 0x59b242b2, ++ 0x3ea83c02, 0x4a110304}; + int status; + + if (mutex_lock_interruptible(&adapter->mbox_lock)) +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0015-be2net-Fix-non-utilization-of-RX-queues.patch b/debian/patches/features/all/be2net/0015-be2net-Fix-non-utilization-of-RX-queues.patch new file mode 100644 index 000000000..403111cf5 --- /dev/null +++ b/debian/patches/features/all/be2net/0015-be2net-Fix-non-utilization-of-RX-queues.patch @@ -0,0 +1,54 @@ +From: Padmanabh Ratnakar +Date: Fri, 25 Nov 2011 05:48:53 +0000 +Subject: [PATCH 15/58] be2net: Fix non utilization of RX queues + +commit e9008ee99c77207b2f6aee67e5f849b1e1400a11 upstream. + +When non power of two MSIX vectors are given to driver, some RX queues +are not utilized. Program RSS table in such a way that all queues +are utilized. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 66429ea..7236280 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -2312,8 +2312,8 @@ static int be_close(struct net_device *netdev) + static int be_rx_queues_setup(struct be_adapter *adapter) + { + struct be_rx_obj *rxo; +- int rc, i; +- u8 rsstable[MAX_RSS_QS]; ++ int rc, i, j; ++ u8 rsstable[128]; + + for_all_rx_queues(adapter, rxo, i) { + rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id, +@@ -2325,11 +2325,15 @@ static int be_rx_queues_setup(struct be_adapter *adapter) + } + + if (be_multi_rxq(adapter)) { +- for_all_rss_queues(adapter, rxo, i) +- rsstable[i] = rxo->rss_id; ++ for (j = 0; j < 128; j += adapter->num_rx_qs - 1) { ++ for_all_rss_queues(adapter, rxo, i) { ++ if ((j + i) >= 128) ++ break; ++ rsstable[j + i] = rxo->rss_id; ++ } ++ } ++ rc = be_cmd_rss_config(adapter, rsstable, 128); + +- rc = be_cmd_rss_config(adapter, rsstable, +- adapter->num_rx_qs - 1); + if (rc) + return rc; + } +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0016-be2net-netpoll-support.patch b/debian/patches/features/all/be2net/0016-be2net-netpoll-support.patch new file mode 100644 index 000000000..f83eb402b --- /dev/null +++ b/debian/patches/features/all/be2net/0016-be2net-netpoll-support.patch @@ -0,0 +1,53 @@ +From: Ivan Vecera +Date: Thu, 8 Dec 2011 01:31:21 +0000 +Subject: [PATCH 16/58] be2net: netpoll support + +commit 6626873980475f303367f7b709f4703b571cf854 upstream. + +Add missing netpoll support. + +Signed-off-by: Ivan Vecera +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 7236280..3854fb0 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -2666,6 +2666,19 @@ err: + return status; + } + ++#ifdef CONFIG_NET_POLL_CONTROLLER ++static void be_netpoll(struct net_device *netdev) ++{ ++ struct be_adapter *adapter = netdev_priv(netdev); ++ struct be_rx_obj *rxo; ++ int i; ++ ++ event_handle(adapter, &adapter->tx_eq, false); ++ for_all_rx_queues(adapter, rxo, i) ++ event_handle(adapter, &rxo->rx_eq, true); ++} ++#endif ++ + #define FW_FILE_HDR_SIGN "ServerEngines Corp. " + static bool be_flash_redboot(struct be_adapter *adapter, + const u8 *p, u32 img_start, int image_size, +@@ -3014,7 +3027,10 @@ static struct net_device_ops be_netdev_ops = { + .ndo_set_vf_mac = be_set_vf_mac, + .ndo_set_vf_vlan = be_set_vf_vlan, + .ndo_set_vf_tx_rate = be_set_vf_tx_rate, +- .ndo_get_vf_config = be_get_vf_config ++ .ndo_get_vf_config = be_get_vf_config, ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = be_netpoll, ++#endif + }; + + static void be_netdev_init(struct net_device *netdev) +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0017-be2net-update-some-counters-to-display-via-ethtool.patch b/debian/patches/features/all/be2net/0017-be2net-update-some-counters-to-display-via-ethtool.patch new file mode 100644 index 000000000..3c6e3b445 --- /dev/null +++ b/debian/patches/features/all/be2net/0017-be2net-update-some-counters-to-display-via-ethtool.patch @@ -0,0 +1,30 @@ +From: Ajit Khaparde +Date: Fri, 9 Dec 2011 13:53:09 +0000 +Subject: [PATCH 17/58] be2net: update some counters to display via ethtool + +commit 02fe7027961969a052fbbe453304f329d4e9735a upstream. + +update pmem_fifo_overflow_drop, rx_priority_pause_frames counters. + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 3854fb0..0da3df0 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -316,6 +316,8 @@ static void populate_be3_stats(struct be_adapter *adapter) + struct be_drv_stats *drvs = &adapter->drv_stats; + + be_dws_le_to_cpu(hw_stats, sizeof(*hw_stats)); ++ drvs->pmem_fifo_overflow_drop = port_stats->pmem_fifo_overflow_drop; ++ drvs->rx_priority_pause_frames = port_stats->rx_priority_pause_frames; + drvs->rx_pause_frames = port_stats->rx_pause_frames; + drvs->rx_crc_errors = port_stats->rx_crc_errors; + drvs->rx_control_frames = port_stats->rx_control_frames; +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0018-be2net-workaround-to-fix-a-bug-in-BE.patch b/debian/patches/features/all/be2net/0018-be2net-workaround-to-fix-a-bug-in-BE.patch new file mode 100644 index 000000000..7110bc660 --- /dev/null +++ b/debian/patches/features/all/be2net/0018-be2net-workaround-to-fix-a-bug-in-BE.patch @@ -0,0 +1,98 @@ +From: Ajit Khaparde +Date: Fri, 9 Dec 2011 13:53:17 +0000 +Subject: [PATCH 18/58] be2net: workaround to fix a bug in BE + +commit 1ded132d4c3442aa3a619c94c245d7b5e0eb9731 upstream. + +disable Tx vlan offloading in certain cases. + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 46 ++++++++++++++++++++++----- + 1 file changed, 38 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 0da3df0..f180f49 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -552,11 +552,26 @@ static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len) + wrb->frag_len = len & ETH_WRB_FRAG_LEN_MASK; + } + ++static inline u16 be_get_tx_vlan_tag(struct be_adapter *adapter, ++ struct sk_buff *skb) ++{ ++ u8 vlan_prio; ++ u16 vlan_tag; ++ ++ vlan_tag = vlan_tx_tag_get(skb); ++ vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; ++ /* If vlan priority provided by OS is NOT in available bmap */ ++ if (!(adapter->vlan_prio_bmap & (1 << vlan_prio))) ++ vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) | ++ adapter->recommended_prio; ++ ++ return vlan_tag; ++} ++ + static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, + struct sk_buff *skb, u32 wrb_cnt, u32 len) + { +- u8 vlan_prio = 0; +- u16 vlan_tag = 0; ++ u16 vlan_tag; + + memset(hdr, 0, sizeof(*hdr)); + +@@ -587,12 +602,7 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, + + if (vlan_tx_tag_present(skb)) { + AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1); +- vlan_tag = vlan_tx_tag_get(skb); +- vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; +- /* If vlan priority provided by OS is NOT in available bmap */ +- if (!(adapter->vlan_prio_bmap & (1 << vlan_prio))) +- vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) | +- adapter->recommended_prio; ++ vlan_tag = be_get_tx_vlan_tag(adapter, skb); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag, hdr, vlan_tag); + } + +@@ -695,6 +705,25 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, + u32 start = txq->head; + bool dummy_wrb, stopped = false; + ++ /* For vlan tagged pkts, BE ++ * 1) calculates checksum even when CSO is not requested ++ * 2) calculates checksum wrongly for padded pkt less than ++ * 60 bytes long. ++ * As a workaround disable TX vlan offloading in such cases. ++ */ ++ if (unlikely(vlan_tx_tag_present(skb) && ++ (skb->ip_summed != CHECKSUM_PARTIAL || skb->len <= 60))) { ++ skb = skb_share_check(skb, GFP_ATOMIC); ++ if (unlikely(!skb)) ++ goto tx_drop; ++ ++ skb = __vlan_put_tag(skb, be_get_tx_vlan_tag(adapter, skb)); ++ if (unlikely(!skb)) ++ goto tx_drop; ++ ++ skb->vlan_tci = 0; ++ } ++ + wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb); + + copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb); +@@ -722,6 +751,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, + txq->head = start; + dev_kfree_skb_any(skb); + } ++tx_drop: + return NETDEV_TX_OK; + } + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0019-be2net-fix-ethtool-ringparam-reporting.patch b/debian/patches/features/all/be2net/0019-be2net-fix-ethtool-ringparam-reporting.patch new file mode 100644 index 000000000..3572af57b --- /dev/null +++ b/debian/patches/features/all/be2net/0019-be2net-fix-ethtool-ringparam-reporting.patch @@ -0,0 +1,46 @@ +From: Sathya Perla +Date: Tue, 13 Dec 2011 00:58:49 +0000 +Subject: [PATCH 19/58] be2net: fix ethtool ringparam reporting + +commit 110b82bc6265a48c1a0bf198109bed325ed055e2 upstream. + +The ethtool "-g" option is supposed to report the max queue length and +user modified queue length for RX and TX queues. be2net doesn't support +user modification of queue lengths. So, the correct values for these +would be the max numbers. +be2net incorrectly reports the queue used values for these fields. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_ethtool.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index 575c783..6ba2dc6 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -520,16 +520,13 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + return 0; + } + +-static void +-be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) ++static void be_get_ringparam(struct net_device *netdev, ++ struct ethtool_ringparam *ring) + { + struct be_adapter *adapter = netdev_priv(netdev); + +- ring->rx_max_pending = adapter->rx_obj[0].q.len; +- ring->tx_max_pending = adapter->tx_obj[0].q.len; +- +- ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used); +- ring->tx_pending = atomic_read(&adapter->tx_obj[0].q.used); ++ ring->rx_max_pending = ring->rx_pending = adapter->rx_obj[0].q.len; ++ ring->tx_max_pending = ring->tx_pending = adapter->tx_obj[0].q.len; + } + + static void +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0020-be2net-refactor-cleanup-vf-configuration-code.patch b/debian/patches/features/all/be2net/0020-be2net-refactor-cleanup-vf-configuration-code.patch new file mode 100644 index 000000000..184bf8bbf --- /dev/null +++ b/debian/patches/features/all/be2net/0020-be2net-refactor-cleanup-vf-configuration-code.patch @@ -0,0 +1,416 @@ +From: Sathya Perla +Date: Tue, 13 Dec 2011 00:58:50 +0000 +Subject: [PATCH 20/58] be2net: refactor/cleanup vf configuration code + +commit 11ac75ed1eb9d8f5ff067fa9a82ebf5075989281 upstream. + +- use adapter->num_vfs (and not the module param) to store the actual +number of vfs created. Use the same variable to reflect SRIOV +enable/disable state. So, drop the adapter->sriov_enabled field. + +- use for_all_vfs() macro in VF configuration code + +- drop the "vf_" prefix for the fields of be_vf_cfg; the prefix is +redundant and removing it helps reduce line wrap + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 20 ++-- + drivers/net/ethernet/emulex/benet/be_main.c | 137 +++++++++++++-------------- + 2 files changed, 80 insertions(+), 77 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index 34f162d..a3588fb 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -288,11 +288,11 @@ struct be_drv_stats { + }; + + struct be_vf_cfg { +- unsigned char vf_mac_addr[ETH_ALEN]; +- int vf_if_handle; +- int vf_pmac_id; +- u16 vf_vlan_tag; +- u32 vf_tx_rate; ++ unsigned char mac_addr[ETH_ALEN]; ++ int if_handle; ++ int pmac_id; ++ u16 vlan_tag; ++ u32 tx_rate; + }; + + struct be_adapter { +@@ -368,16 +368,20 @@ struct be_adapter { + u32 flash_status; + struct completion flash_compl; + +- bool be3_native; +- bool sriov_enabled; +- struct be_vf_cfg *vf_cfg; ++ u32 num_vfs; + u8 is_virtfn; ++ struct be_vf_cfg *vf_cfg; ++ bool be3_native; + u32 sli_family; + u8 hba_port_num; + u16 pvid; + }; + + #define be_physfn(adapter) (!adapter->is_virtfn) ++#define sriov_enabled(adapter) (adapter->num_vfs > 0) ++#define for_all_vfs(adapter, vf_cfg, i) \ ++ for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \ ++ i++, vf_cfg++) + + /* BladeEngine Generation numbers */ + #define BE_GEN2 2 +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index f180f49..cf83b33 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -27,13 +27,14 @@ MODULE_DESCRIPTION(DRV_DESC " " DRV_VER); + MODULE_AUTHOR("ServerEngines Corporation"); + MODULE_LICENSE("GPL"); + +-static ushort rx_frag_size = 2048; + static unsigned int num_vfs; +-module_param(rx_frag_size, ushort, S_IRUGO); + module_param(num_vfs, uint, S_IRUGO); +-MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data."); + MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize"); + ++static ushort rx_frag_size = 2048; ++module_param(rx_frag_size, ushort, S_IRUGO); ++MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data."); ++ + static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { + { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, + { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) }, +@@ -779,15 +780,15 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) + */ + static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) + { ++ struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf_num]; + u16 vtag[BE_NUM_VLANS_SUPPORTED]; + u16 ntags = 0, i; + int status = 0; +- u32 if_handle; + + if (vf) { +- if_handle = adapter->vf_cfg[vf_num].vf_if_handle; +- vtag[0] = cpu_to_le16(adapter->vf_cfg[vf_num].vf_vlan_tag); +- status = be_cmd_vlan_config(adapter, if_handle, vtag, 1, 1, 0); ++ vtag[0] = cpu_to_le16(vf_cfg->vlan_tag); ++ status = be_cmd_vlan_config(adapter, vf_cfg->if_handle, vtag, ++ 1, 1, 0); + } + + /* No need to further configure vids if in promiscuous mode */ +@@ -873,31 +874,30 @@ done: + static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) + { + struct be_adapter *adapter = netdev_priv(netdev); ++ struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; + int status; + +- if (!adapter->sriov_enabled) ++ if (!sriov_enabled(adapter)) + return -EPERM; + +- if (!is_valid_ether_addr(mac) || (vf >= num_vfs)) ++ if (!is_valid_ether_addr(mac) || vf >= adapter->num_vfs) + return -EINVAL; + + if (lancer_chip(adapter)) { + status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1); + } else { +- status = be_cmd_pmac_del(adapter, +- adapter->vf_cfg[vf].vf_if_handle, +- adapter->vf_cfg[vf].vf_pmac_id, vf + 1); ++ status = be_cmd_pmac_del(adapter, vf_cfg->if_handle, ++ vf_cfg->pmac_id, vf + 1); + +- status = be_cmd_pmac_add(adapter, mac, +- adapter->vf_cfg[vf].vf_if_handle, +- &adapter->vf_cfg[vf].vf_pmac_id, vf + 1); ++ status = be_cmd_pmac_add(adapter, mac, vf_cfg->if_handle, ++ &vf_cfg->pmac_id, vf + 1); + } + + if (status) + dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n", + mac, vf); + else +- memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN); ++ memcpy(vf_cfg->mac_addr, mac, ETH_ALEN); + + return status; + } +@@ -906,18 +906,19 @@ static int be_get_vf_config(struct net_device *netdev, int vf, + struct ifla_vf_info *vi) + { + struct be_adapter *adapter = netdev_priv(netdev); ++ struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; + +- if (!adapter->sriov_enabled) ++ if (!sriov_enabled(adapter)) + return -EPERM; + +- if (vf >= num_vfs) ++ if (vf >= adapter->num_vfs) + return -EINVAL; + + vi->vf = vf; +- vi->tx_rate = adapter->vf_cfg[vf].vf_tx_rate; +- vi->vlan = adapter->vf_cfg[vf].vf_vlan_tag; ++ vi->tx_rate = vf_cfg->tx_rate; ++ vi->vlan = vf_cfg->vlan_tag; + vi->qos = 0; +- memcpy(&vi->mac, adapter->vf_cfg[vf].vf_mac_addr, ETH_ALEN); ++ memcpy(&vi->mac, vf_cfg->mac_addr, ETH_ALEN); + + return 0; + } +@@ -928,17 +929,17 @@ static int be_set_vf_vlan(struct net_device *netdev, + struct be_adapter *adapter = netdev_priv(netdev); + int status = 0; + +- if (!adapter->sriov_enabled) ++ if (!sriov_enabled(adapter)) + return -EPERM; + +- if ((vf >= num_vfs) || (vlan > 4095)) ++ if (vf >= adapter->num_vfs || vlan > 4095) + return -EINVAL; + + if (vlan) { +- adapter->vf_cfg[vf].vf_vlan_tag = vlan; ++ adapter->vf_cfg[vf].vlan_tag = vlan; + adapter->vlans_added++; + } else { +- adapter->vf_cfg[vf].vf_vlan_tag = 0; ++ adapter->vf_cfg[vf].vlan_tag = 0; + adapter->vlans_added--; + } + +@@ -956,16 +957,16 @@ static int be_set_vf_tx_rate(struct net_device *netdev, + struct be_adapter *adapter = netdev_priv(netdev); + int status = 0; + +- if (!adapter->sriov_enabled) ++ if (!sriov_enabled(adapter)) + return -EPERM; + +- if ((vf >= num_vfs) || (rate < 0)) ++ if (vf >= adapter->num_vfs || rate < 0) + return -EINVAL; + + if (rate > 10000) + rate = 10000; + +- adapter->vf_cfg[vf].vf_tx_rate = rate; ++ adapter->vf_cfg[vf].tx_rate = rate; + status = be_cmd_set_qos(adapter, rate / 10, vf + 1); + + if (status) +@@ -1681,8 +1682,7 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) + + static int be_num_txqs_want(struct be_adapter *adapter) + { +- if ((num_vfs && adapter->sriov_enabled) || +- be_is_mc(adapter) || ++ if (sriov_enabled(adapter) || be_is_mc(adapter) || + lancer_chip(adapter) || !be_physfn(adapter) || + adapter->generation == BE_GEN2) + return 1; +@@ -1764,8 +1764,8 @@ static void be_rx_queues_destroy(struct be_adapter *adapter) + static u32 be_num_rxqs_want(struct be_adapter *adapter) + { + if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && +- !adapter->sriov_enabled && be_physfn(adapter) && +- !be_is_mc(adapter)) { ++ !sriov_enabled(adapter) && be_physfn(adapter) && ++ !be_is_mc(adapter)) { + return 1 + MAX_RSS_QS; /* one default non-RSS queue */ + } else { + dev_warn(&adapter->pdev->dev, +@@ -2112,27 +2112,28 @@ done: + static int be_sriov_enable(struct be_adapter *adapter) + { + be_check_sriov_fn_type(adapter); ++ + #ifdef CONFIG_PCI_IOV + if (be_physfn(adapter) && num_vfs) { + int status, pos; +- u16 nvfs; ++ u16 dev_vfs; + + pos = pci_find_ext_capability(adapter->pdev, + PCI_EXT_CAP_ID_SRIOV); + pci_read_config_word(adapter->pdev, +- pos + PCI_SRIOV_TOTAL_VF, &nvfs); ++ pos + PCI_SRIOV_TOTAL_VF, &dev_vfs); + +- if (num_vfs > nvfs) { ++ adapter->num_vfs = min_t(u16, num_vfs, dev_vfs); ++ if (adapter->num_vfs != num_vfs) + dev_info(&adapter->pdev->dev, +- "Device supports %d VFs and not %d\n", +- nvfs, num_vfs); +- num_vfs = nvfs; +- } ++ "Device supports %d VFs and not %d\n", ++ adapter->num_vfs, num_vfs); + +- status = pci_enable_sriov(adapter->pdev, num_vfs); +- adapter->sriov_enabled = status ? false : true; ++ status = pci_enable_sriov(adapter->pdev, adapter->num_vfs); ++ if (status) ++ adapter->num_vfs = 0; + +- if (adapter->sriov_enabled) { ++ if (adapter->num_vfs) { + adapter->vf_cfg = kcalloc(num_vfs, + sizeof(struct be_vf_cfg), + GFP_KERNEL); +@@ -2147,10 +2148,10 @@ static int be_sriov_enable(struct be_adapter *adapter) + static void be_sriov_disable(struct be_adapter *adapter) + { + #ifdef CONFIG_PCI_IOV +- if (adapter->sriov_enabled) { ++ if (sriov_enabled(adapter)) { + pci_disable_sriov(adapter->pdev); + kfree(adapter->vf_cfg); +- adapter->sriov_enabled = false; ++ adapter->num_vfs = 0; + } + #endif + } +@@ -2462,24 +2463,24 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter) + u32 vf; + int status = 0; + u8 mac[ETH_ALEN]; ++ struct be_vf_cfg *vf_cfg; + + be_vf_eth_addr_generate(adapter, mac); + +- for (vf = 0; vf < num_vfs; vf++) { ++ for_all_vfs(adapter, vf_cfg, vf) { + if (lancer_chip(adapter)) { + status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1); + } else { + status = be_cmd_pmac_add(adapter, mac, +- adapter->vf_cfg[vf].vf_if_handle, +- &adapter->vf_cfg[vf].vf_pmac_id, +- vf + 1); ++ vf_cfg->if_handle, ++ &vf_cfg->pmac_id, vf + 1); + } + + if (status) + dev_err(&adapter->pdev->dev, + "Mac address assignment failed for VF %d\n", vf); + else +- memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN); ++ memcpy(vf_cfg->mac_addr, mac, ETH_ALEN); + + mac[5] += 1; + } +@@ -2488,25 +2489,23 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter) + + static void be_vf_clear(struct be_adapter *adapter) + { ++ struct be_vf_cfg *vf_cfg; + u32 vf; + +- for (vf = 0; vf < num_vfs; vf++) { ++ for_all_vfs(adapter, vf_cfg, vf) { + if (lancer_chip(adapter)) + be_cmd_set_mac_list(adapter, NULL, 0, vf + 1); + else +- be_cmd_pmac_del(adapter, +- adapter->vf_cfg[vf].vf_if_handle, +- adapter->vf_cfg[vf].vf_pmac_id, vf + 1); +- } ++ be_cmd_pmac_del(adapter, vf_cfg->if_handle, ++ vf_cfg->pmac_id, vf + 1); + +- for (vf = 0; vf < num_vfs; vf++) +- be_cmd_if_destroy(adapter, adapter->vf_cfg[vf].vf_if_handle, +- vf + 1); ++ be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1); ++ } + } + + static int be_clear(struct be_adapter *adapter) + { +- if (be_physfn(adapter) && adapter->sriov_enabled) ++ if (sriov_enabled(adapter)) + be_vf_clear(adapter); + + be_cmd_if_destroy(adapter, adapter->if_handle, 0); +@@ -2522,16 +2521,18 @@ static int be_clear(struct be_adapter *adapter) + + static void be_vf_setup_init(struct be_adapter *adapter) + { ++ struct be_vf_cfg *vf_cfg; + int vf; + +- for (vf = 0; vf < num_vfs; vf++) { +- adapter->vf_cfg[vf].vf_if_handle = -1; +- adapter->vf_cfg[vf].vf_pmac_id = -1; ++ for_all_vfs(adapter, vf_cfg, vf) { ++ vf_cfg->if_handle = -1; ++ vf_cfg->pmac_id = -1; + } + } + + static int be_vf_setup(struct be_adapter *adapter) + { ++ struct be_vf_cfg *vf_cfg; + u32 cap_flags, en_flags, vf; + u16 lnk_speed; + int status; +@@ -2540,11 +2541,9 @@ static int be_vf_setup(struct be_adapter *adapter) + + cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MULTICAST; +- +- for (vf = 0; vf < num_vfs; vf++) { ++ for_all_vfs(adapter, vf_cfg, vf) { + status = be_cmd_if_create(adapter, cap_flags, en_flags, NULL, +- &adapter->vf_cfg[vf].vf_if_handle, +- NULL, vf+1); ++ &vf_cfg->if_handle, NULL, vf + 1); + if (status) + goto err; + } +@@ -2553,12 +2552,12 @@ static int be_vf_setup(struct be_adapter *adapter) + if (status) + goto err; + +- for (vf = 0; vf < num_vfs; vf++) { ++ for_all_vfs(adapter, vf_cfg, vf) { + status = be_cmd_link_status_query(adapter, NULL, &lnk_speed, +- vf + 1); ++ vf + 1); + if (status) + goto err; +- adapter->vf_cfg[vf].vf_tx_rate = lnk_speed * 10; ++ vf_cfg->tx_rate = lnk_speed * 10; + } + return 0; + err: +@@ -2686,7 +2685,7 @@ static int be_setup(struct be_adapter *adapter) + + pcie_set_readrq(adapter->pdev, 4096); + +- if (be_physfn(adapter) && adapter->sriov_enabled) { ++ if (sriov_enabled(adapter)) { + status = be_vf_setup(adapter); + if (status) + goto err; +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0021-be2net-Add-support-for-Skyhawk-cards.patch b/debian/patches/features/all/be2net/0021-be2net-Add-support-for-Skyhawk-cards.patch new file mode 100644 index 000000000..3d077d4b1 --- /dev/null +++ b/debian/patches/features/all/be2net/0021-be2net-Add-support-for-Skyhawk-cards.patch @@ -0,0 +1,65 @@ +From: Ajit Khaparde +Date: Thu, 15 Dec 2011 06:31:38 +0000 +Subject: [PATCH 21/58] be2net: Add support for Skyhawk cards + +commit ecedb6ae908e3a8a19942da921a3ffb1c5a0d6ab upstream. + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 4 ++++ + drivers/net/ethernet/emulex/benet/be_main.c | 2 ++ + 2 files changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index a3588fb..995198d 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -40,6 +40,7 @@ + #define OC_NAME "Emulex OneConnect 10Gbps NIC" + #define OC_NAME_BE OC_NAME "(be3)" + #define OC_NAME_LANCER OC_NAME "(Lancer)" ++#define OC_NAME_SH OC_NAME "(Skyhawk)" + #define DRV_DESC "ServerEngines BladeEngine 10Gbps NIC Driver" + + #define BE_VENDOR_ID 0x19a2 +@@ -50,6 +51,7 @@ + #define OC_DEVICE_ID2 0x710 /* Device Id for BE3 cards */ + #define OC_DEVICE_ID3 0xe220 /* Device id for Lancer cards */ + #define OC_DEVICE_ID4 0xe228 /* Device id for VF in Lancer */ ++#define OC_DEVICE_ID5 0x720 /* Device Id for Skyhawk cards */ + + static inline char *nic_name(struct pci_dev *pdev) + { +@@ -63,6 +65,8 @@ static inline char *nic_name(struct pci_dev *pdev) + return OC_NAME_LANCER; + case BE_DEVICE_ID2: + return BE3_NAME; ++ case OC_DEVICE_ID5: ++ return OC_NAME_SH; + default: + return BE_NAME; + } +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index cf83b33..3ed2987 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -42,6 +42,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { + { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, + { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)}, + { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID4)}, ++ { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID5)}, + { 0 } + }; + MODULE_DEVICE_TABLE(pci, be_dev_ids); +@@ -3308,6 +3309,7 @@ static int be_dev_family_check(struct be_adapter *adapter) + break; + case BE_DEVICE_ID2: + case OC_DEVICE_ID2: ++ case OC_DEVICE_ID5: + adapter->generation = BE_GEN3; + break; + case OC_DEVICE_ID3: +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0022-be2net-Fix-INTx-processing-for-Lancer.patch b/debian/patches/features/all/be2net/0022-be2net-Fix-INTx-processing-for-Lancer.patch new file mode 100644 index 000000000..10e8fb054 --- /dev/null +++ b/debian/patches/features/all/be2net/0022-be2net-Fix-INTx-processing-for-Lancer.patch @@ -0,0 +1,53 @@ +From: Padmanabh Ratnakar +Date: Mon, 19 Dec 2011 01:53:35 +0000 +Subject: [PATCH 22/58] be2net: Fix INTx processing for Lancer + +commit 93c86700c0ae3a1407b979073f423e62e29372c1 upstream. + +Lancer does not have HW registers to indicate the EQ causing the INTx +interrupt. As a result EQE entries of one EQ may be consumed when interrupt +is caused by another EQ. Fix this by arming CQs at the end of NAPI poll +routine to regenerate the EQEs. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 3ed2987..a185e61 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1966,6 +1966,7 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget) + struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); + struct be_adapter *adapter = + container_of(tx_eq, struct be_adapter, tx_eq); ++ struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; + struct be_tx_obj *txo; + struct be_eth_tx_compl *txcp; + int tx_compl, mcc_compl, status = 0; +@@ -2002,12 +2003,19 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget) + mcc_compl = be_process_mcc(adapter, &status); + + if (mcc_compl) { +- struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; + be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl); + } + + napi_complete(napi); + ++ /* Arm CQ again to regenerate EQEs for Lancer in INTx mode */ ++ if (lancer_chip(adapter) && !msix_enabled(adapter)) { ++ for_all_tx_queues(adapter, txo, i) ++ be_cq_notify(adapter, txo->cq.id, true, 0); ++ ++ be_cq_notify(adapter, mcc_obj->cq.id, true, 0); ++ } ++ + be_eq_notify(adapter, tx_eq->q.id, true, false, 0); + adapter->drv_stats.tx_events++; + return 1; +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0023-be2net-fix-be_vlan_add-rem_vid.patch b/debian/patches/features/all/be2net/0023-be2net-fix-be_vlan_add-rem_vid.patch new file mode 100644 index 000000000..8f416aecd --- /dev/null +++ b/debian/patches/features/all/be2net/0023-be2net-fix-be_vlan_add-rem_vid.patch @@ -0,0 +1,65 @@ +From: Ajit Khaparde +Date: Fri, 25 May 2012 21:21:23 +0530 +Subject: [PATCH 23/58] be2net: fix be_vlan_add/rem_vid + +commit 80817cbf5ac13da76f3ee2b9259f26c09b385e84 upstream. + +1) fix be_vlan_add/rem_vid to return proper status +2) perform appropriate housekeeping if firmware command succeeds. + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index a185e61..acef082 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -817,28 +817,37 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) + static void be_vlan_add_vid(struct net_device *netdev, u16 vid) + { + struct be_adapter *adapter = netdev_priv(netdev); ++ int status = 0; + +- adapter->vlans_added++; + if (!be_physfn(adapter)) + return; + + adapter->vlan_tag[vid] = 1; + if (adapter->vlans_added <= (adapter->max_vlans + 1)) +- be_vid_config(adapter, false, 0); ++ status = be_vid_config(adapter, false, 0); ++ ++ if (!status) ++ adapter->vlans_added++; ++ else ++ adapter->vlan_tag[vid] = 0; + } + + static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) + { + struct be_adapter *adapter = netdev_priv(netdev); +- +- adapter->vlans_added--; ++ int status = 0; + + if (!be_physfn(adapter)) + return; + + adapter->vlan_tag[vid] = 0; + if (adapter->vlans_added <= adapter->max_vlans) +- be_vid_config(adapter, false, 0); ++ status = be_vid_config(adapter, false, 0); ++ ++ if (!status) ++ adapter->vlans_added--; ++ else ++ adapter->vlan_tag[vid] = 1; + } + + static void be_set_rx_mode(struct net_device *netdev) +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0024-be2net-fix-range-check-for-set_qos-for-a-VF.patch b/debian/patches/features/all/be2net/0024-be2net-fix-range-check-for-set_qos-for-a-VF.patch new file mode 100644 index 000000000..f75af073a --- /dev/null +++ b/debian/patches/features/all/be2net/0024-be2net-fix-range-check-for-set_qos-for-a-VF.patch @@ -0,0 +1,47 @@ +From: Ajit Khaparde +Date: Fri, 30 Dec 2011 12:15:30 +0000 +Subject: [PATCH 24/58] be2net: fix range check for set_qos for a VF + +commit 94f434c2055db5fe20f10d4e0ec50ab395e1f62b upstream. + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index acef082..cd7f5e3 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -970,18 +970,22 @@ static int be_set_vf_tx_rate(struct net_device *netdev, + if (!sriov_enabled(adapter)) + return -EPERM; + +- if (vf >= adapter->num_vfs || rate < 0) ++ if (vf >= adapter->num_vfs) + return -EINVAL; + +- if (rate > 10000) +- rate = 10000; ++ if (rate < 100 || rate > 10000) { ++ dev_err(&adapter->pdev->dev, ++ "tx rate must be between 100 and 10000 Mbps\n"); ++ return -EINVAL; ++ } + +- adapter->vf_cfg[vf].tx_rate = rate; + status = be_cmd_set_qos(adapter, rate / 10, vf + 1); + + if (status) +- dev_info(&adapter->pdev->dev, ++ dev_err(&adapter->pdev->dev, + "tx rate %d on VF %d failed\n", rate, vf); ++ else ++ adapter->vf_cfg[vf].tx_rate = rate; + return status; + } + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0025-be2net-query-link-status-in-be_open.patch b/debian/patches/features/all/be2net/0025-be2net-query-link-status-in-be_open.patch new file mode 100644 index 000000000..57c542c70 --- /dev/null +++ b/debian/patches/features/all/be2net/0025-be2net-query-link-status-in-be_open.patch @@ -0,0 +1,234 @@ +From: Ajit Khaparde +Date: Fri, 30 Dec 2011 12:15:40 +0000 +Subject: [PATCH 25/58] be2net: query link status in be_open() + +commit b236916a68d923acff15787b5439d7d684c17ae5 upstream. + +be2net gets an async link status notification from the FW when it creates +an MCC queue. There are some cases in which this gratuitous notification +is not received from FW. To cover this explicitly query the link status +in be_open(). + +Signed-off-by: Vasundhara Volam +Signed-off-by: Sathya Perla +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 5 ++++- + drivers/net/ethernet/emulex/benet/be_cmds.c | 21 +++++++++++++++++---- + drivers/net/ethernet/emulex/benet/be_cmds.h | 7 ++++--- + drivers/net/ethernet/emulex/benet/be_ethtool.c | 7 +++++-- + drivers/net/ethernet/emulex/benet/be_main.c | 24 +++++++++++++++--------- + 5 files changed, 45 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index 995198d..cbdec25 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -299,6 +299,8 @@ struct be_vf_cfg { + u32 tx_rate; + }; + ++#define BE_FLAGS_LINK_STATUS_INIT 1 ++ + struct be_adapter { + struct pci_dev *pdev; + struct net_device *netdev; +@@ -347,6 +349,7 @@ struct be_adapter { + struct delayed_work work; + u16 work_counter; + ++ u32 flags; + /* Ethtool knobs and info */ + char fw_ver[FW_VER_LEN]; + int if_handle; /* Used to configure filtering */ +@@ -538,7 +541,7 @@ static inline bool be_error(struct be_adapter *adapter) + + extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, + u16 num_popped); +-extern void be_link_status_update(struct be_adapter *adapter, u32 link_status); ++extern void be_link_status_update(struct be_adapter *adapter, u8 link_status); + extern void be_parse_stats(struct be_adapter *adapter); + extern int be_load_fw(struct be_adapter *adapter, u8 *func); + #endif /* BE_H */ +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 62868ea..0fcb456 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -125,7 +125,14 @@ done: + static void be_async_link_state_process(struct be_adapter *adapter, + struct be_async_event_link_state *evt) + { +- be_link_status_update(adapter, evt->port_link_status); ++ /* When link status changes, link speed must be re-queried from FW */ ++ adapter->link_speed = -1; ++ ++ /* For the initial link status do not rely on the ASYNC event as ++ * it may not be received in some cases. ++ */ ++ if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT) ++ be_link_status_update(adapter, evt->port_link_status); + } + + /* Grp5 CoS Priority evt */ +@@ -1232,7 +1239,7 @@ err: + + /* Uses synchronous mcc */ + int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, +- u16 *link_speed, u32 dom) ++ u16 *link_speed, u8 *link_status, u32 dom) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_link_status *req; +@@ -1240,6 +1247,9 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, + + spin_lock_bh(&adapter->mcc_lock); + ++ if (link_status) ++ *link_status = LINK_DOWN; ++ + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; +@@ -1247,7 +1257,7 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, + } + req = embedded_payload(wrb); + +- if (lancer_chip(adapter)) ++ if (adapter->generation == BE_GEN3 || lancer_chip(adapter)) + req->hdr.version = 1; + + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, +@@ -1257,10 +1267,13 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, + if (!status) { + struct be_cmd_resp_link_status *resp = embedded_payload(wrb); + if (resp->mac_speed != PHY_LINK_SPEED_ZERO) { +- *link_speed = le16_to_cpu(resp->link_speed); ++ if (link_speed) ++ *link_speed = le16_to_cpu(resp->link_speed); + if (mac_speed) + *mac_speed = resp->mac_speed; + } ++ if (link_status) ++ *link_status = resp->logical_link_status; + } + + err: +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h +index 0b694c6..dca8924 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.h ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.h +@@ -960,7 +960,8 @@ struct be_cmd_resp_link_status { + u8 mgmt_mac_duplex; + u8 mgmt_mac_speed; + u16 link_speed; +- u32 rsvd0; ++ u8 logical_link_status; ++ u8 rsvd1[3]; + } __packed; + + /******************** Port Identification ***************************/ +@@ -1507,8 +1508,8 @@ extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, + int type); + extern int be_cmd_rxq_destroy(struct be_adapter *adapter, + struct be_queue_info *q); +-extern int be_cmd_link_status_query(struct be_adapter *adapter, +- u8 *mac_speed, u16 *link_speed, u32 dom); ++extern int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, ++ u16 *link_speed, u8 *link_status, u32 dom); + extern int be_cmd_reset(struct be_adapter *adapter); + extern int be_cmd_get_stats(struct be_adapter *adapter, + struct be_dma_mem *nonemb_cmd); +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index 6ba2dc6..6db6b6a 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -429,11 +429,14 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + struct be_phy_info phy_info; + u8 mac_speed = 0; + u16 link_speed = 0; ++ u8 link_status; + int status; + + if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) { + status = be_cmd_link_status_query(adapter, &mac_speed, +- &link_speed, 0); ++ &link_speed, &link_status, 0); ++ if (!status) ++ be_link_status_update(adapter, link_status); + + /* link_speed is in units of 10 Mbps */ + if (link_speed) { +@@ -700,7 +703,7 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) + } + + if (be_cmd_link_status_query(adapter, &mac_speed, +- &qos_link_speed, 0) != 0) { ++ &qos_link_speed, NULL, 0) != 0) { + test->flags |= ETH_TEST_FL_FAILED; + data[4] = -1; + } else if (!mac_speed) { +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index cd7f5e3..42ee4c9 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -496,19 +496,19 @@ static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev, + return stats; + } + +-void be_link_status_update(struct be_adapter *adapter, u32 link_status) ++void be_link_status_update(struct be_adapter *adapter, u8 link_status) + { + struct net_device *netdev = adapter->netdev; + +- /* when link status changes, link speed must be re-queried from card */ +- adapter->link_speed = -1; +- if ((link_status & LINK_STATUS_MASK) == LINK_UP) { +- netif_carrier_on(netdev); +- dev_info(&adapter->pdev->dev, "%s: Link up\n", netdev->name); +- } else { ++ if (!(adapter->flags & BE_FLAGS_LINK_STATUS_INIT)) { + netif_carrier_off(netdev); +- dev_info(&adapter->pdev->dev, "%s: Link down\n", netdev->name); ++ adapter->flags |= BE_FLAGS_LINK_STATUS_INIT; + } ++ ++ if ((link_status & LINK_STATUS_MASK) == LINK_UP) ++ netif_carrier_on(netdev); ++ else ++ netif_carrier_off(netdev); + } + + static void be_tx_stats_update(struct be_tx_obj *txo, +@@ -2406,6 +2406,7 @@ static int be_open(struct net_device *netdev) + struct be_adapter *adapter = netdev_priv(netdev); + struct be_eq_obj *tx_eq = &adapter->tx_eq; + struct be_rx_obj *rxo; ++ u8 link_status; + int status, i; + + status = be_rx_queues_setup(adapter); +@@ -2429,6 +2430,11 @@ static int be_open(struct net_device *netdev) + /* Now that interrupts are on we can process async mcc */ + be_async_mcc_enable(adapter); + ++ status = be_cmd_link_status_query(adapter, NULL, NULL, ++ &link_status, 0); ++ if (!status) ++ be_link_status_update(adapter, link_status); ++ + return 0; + err: + be_close(adapter->netdev); +@@ -2576,7 +2582,7 @@ static int be_vf_setup(struct be_adapter *adapter) + + for_all_vfs(adapter, vf_cfg, vf) { + status = be_cmd_link_status_query(adapter, NULL, &lnk_speed, +- vf + 1); ++ NULL, vf + 1); + if (status) + goto err; + vf_cfg->tx_rate = lnk_speed * 10; +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0026-netdev-make-net_device_ops-const.patch b/debian/patches/features/all/be2net/0026-netdev-make-net_device_ops-const.patch new file mode 100644 index 000000000..3b0d14740 --- /dev/null +++ b/debian/patches/features/all/be2net/0026-netdev-make-net_device_ops-const.patch @@ -0,0 +1,31 @@ +From: stephen hemminger +Date: Thu, 5 Jan 2012 19:10:25 +0000 +Subject: [PATCH 26/58] netdev: make net_device_ops const + +commit e5686ad82ca2aeed7a8f24ffca115c0b7478dec9 upstream. + +More drivers where net_device_ops should be const. + +Signed-off-by: Stephen Hemminger +Signed-off-by: David S. Miller +[bwh: Restrict to drivers/net/ethernet/emulex/benet/] +--- + drivers/net/ethernet/emulex/benet/be_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 42ee4c9..804ab7e 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -3072,7 +3072,7 @@ fw_exit: + return status; + } + +-static struct net_device_ops be_netdev_ops = { ++static const struct net_device_ops be_netdev_ops = { + .ndo_open = be_open, + .ndo_stop = be_close, + .ndo_start_xmit = be_xmit, +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0027-be2net-create-RSS-rings-even-in-multi-channel-config.patch b/debian/patches/features/all/be2net/0027-be2net-create-RSS-rings-even-in-multi-channel-config.patch new file mode 100644 index 000000000..92b230534 --- /dev/null +++ b/debian/patches/features/all/be2net/0027-be2net-create-RSS-rings-even-in-multi-channel-config.patch @@ -0,0 +1,36 @@ +From: Sathya Perla +Date: Thu, 19 Jan 2012 20:34:04 +0000 +Subject: [PATCH 27/58] be2net: create RSS rings even in multi-channel configs + +commit df505eb804d5221c3164ebecd1286cb7fc7f49ba upstream. + +Currently RSS rings are not created in a multi-channel config. +RSS rings can be created on one (out of four) interfaces per port in a +multi-channel config. Doing this insulates the driver from a FW bug wherin +multi-channel config is wrongly reported even when not enabled. This also +helps performance in a multi-channel config, as one interface per port gets +RSS rings. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 804ab7e..adfd66a 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1778,8 +1778,7 @@ static void be_rx_queues_destroy(struct be_adapter *adapter) + static u32 be_num_rxqs_want(struct be_adapter *adapter) + { + if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && +- !sriov_enabled(adapter) && be_physfn(adapter) && +- !be_is_mc(adapter)) { ++ !sriov_enabled(adapter) && be_physfn(adapter)) { + return 1 + MAX_RSS_QS; /* one default non-RSS queue */ + } else { + dev_warn(&adapter->pdev->dev, +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0028-be2net-allocate-more-headroom-in-incoming-skbs.patch b/debian/patches/features/all/be2net/0028-be2net-allocate-more-headroom-in-incoming-skbs.patch new file mode 100644 index 000000000..b2b4ffd53 --- /dev/null +++ b/debian/patches/features/all/be2net/0028-be2net-allocate-more-headroom-in-incoming-skbs.patch @@ -0,0 +1,57 @@ +From: Eric Dumazet +Date: Wed, 25 Jan 2012 03:56:30 +0000 +Subject: [PATCH 28/58] be2net: allocate more headroom in incoming skbs + +commit bb349bb4b19b39830e0486aedfd7c7dca23b7baf upstream. + +Allocation of 64 bytes in skb headroom is not enough if we have to pull +ethernet + ipv6 + tcp headers, and/or extra tunneling header. + +Its currently not noticed because netdev_alloc_skb_ip_align(64) give us +more room, thanks to power-of-two kmalloc() roundups. + +Make sure we ask for 128 bytes so that side effects of upcoming patches +from Ian Campbell dont decrease benet rx performance, because of extra +skb head reallocations. + +Signed-off-by: Eric Dumazet +Cc: Ian Campbell +Cc: Vasundhara Volam +Cc: Sathya Perla +Cc: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 3 +++ + drivers/net/ethernet/emulex/benet/be_main.c | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index cbdec25..453d486 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -74,6 +74,9 @@ static inline char *nic_name(struct pci_dev *pdev) + + /* Number of bytes of an RX frame that are copied to skb->data */ + #define BE_HDR_LEN ((u16) 64) ++/* allocate extra space to allow tunneling decapsulation without head reallocation */ ++#define BE_RX_SKB_ALLOC_SIZE (BE_HDR_LEN + 64) ++ + #define BE_MAX_JUMBO_FRAME_SIZE 9018 + #define BE_MIN_MTU 256 + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index adfd66a..860c461 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1181,7 +1181,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, + struct net_device *netdev = adapter->netdev; + struct sk_buff *skb; + +- skb = netdev_alloc_skb_ip_align(netdev, BE_HDR_LEN); ++ skb = netdev_alloc_skb_ip_align(netdev, BE_RX_SKB_ALLOC_SIZE); + if (unlikely(!skb)) { + rx_stats(rxo)->rx_drops_no_skbs++; + be_rx_compl_discard(adapter, rxo, rxcp); +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0029-be2net-add-descriptions-for-stat-counters-reported-v.patch b/debian/patches/features/all/be2net/0029-be2net-add-descriptions-for-stat-counters-reported-v.patch new file mode 100644 index 000000000..471544bec --- /dev/null +++ b/debian/patches/features/all/be2net/0029-be2net-add-descriptions-for-stat-counters-reported-v.patch @@ -0,0 +1,259 @@ +From: Sathya Perla +Date: Sun, 29 Jan 2012 20:17:39 +0000 +Subject: [PATCH 29/58] be2net: add descriptions for stat counters reported + via ethtool + +commit d45b9d39a1aed7851948460d29b843ce70eb0a68 upstream. + +Also rename a few counters appropritely and delete 2 counters that are not +implemented in HW. + +vlan_mismatch_drops does not exist in BE3 and is accounted for in +address_mismatch_drops. Do the same thing for BE2 and Lancer. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 3 +- + drivers/net/ethernet/emulex/benet/be_cmds.h | 10 ++-- + drivers/net/ethernet/emulex/benet/be_ethtool.c | 64 ++++++++++++++++++++++-- + drivers/net/ethernet/emulex/benet/be_main.c | 15 +++--- + 4 files changed, 74 insertions(+), 18 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index 453d486..74aa148 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -265,7 +265,6 @@ struct be_drv_stats { + u32 rx_drops_no_erx_descr; + u32 rx_drops_no_tpre_descr; + u32 rx_drops_too_many_frags; +- u32 rx_drops_invalid_ring; + u32 forwarded_packets; + u32 rx_drops_mtu; + u32 rx_crc_errors; +@@ -276,7 +275,7 @@ struct be_drv_stats { + u32 rx_in_range_errors; + u32 rx_out_range_errors; + u32 rx_frame_too_long; +- u32 rx_address_match_errors; ++ u32 rx_address_mismatch_drops; + u32 rx_dropped_too_small; + u32 rx_dropped_too_short; + u32 rx_dropped_header_too_small; +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h +index dca8924..bbd012b 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.h ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.h +@@ -592,8 +592,8 @@ struct be_port_rxf_stats_v0 { + u32 rx_in_range_errors; /* dword 10*/ + u32 rx_out_range_errors; /* dword 11*/ + u32 rx_frame_too_long; /* dword 12*/ +- u32 rx_address_match_errors; /* dword 13*/ +- u32 rx_vlan_mismatch; /* dword 14*/ ++ u32 rx_address_mismatch_drops; /* dword 13*/ ++ u32 rx_vlan_mismatch_drops; /* dword 14*/ + u32 rx_dropped_too_small; /* dword 15*/ + u32 rx_dropped_too_short; /* dword 16*/ + u32 rx_dropped_header_too_small; /* dword 17*/ +@@ -799,8 +799,8 @@ struct lancer_pport_stats { + u32 rx_control_frames_unknown_opcode_hi; + u32 rx_in_range_errors; + u32 rx_out_of_range_errors; +- u32 rx_address_match_errors; +- u32 rx_vlan_mismatch_errors; ++ u32 rx_address_mismatch_drops; ++ u32 rx_vlan_mismatch_drops; + u32 rx_dropped_too_small; + u32 rx_dropped_too_short; + u32 rx_dropped_header_too_small; +@@ -1384,7 +1384,7 @@ struct be_port_rxf_stats_v1 { + u32 rx_in_range_errors; + u32 rx_out_range_errors; + u32 rx_frame_too_long; +- u32 rx_address_match_errors; ++ u32 rx_address_mismatch_drops; + u32 rx_dropped_too_small; + u32 rx_dropped_too_short; + u32 rx_dropped_header_too_small; +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index 6db6b6a..0a5ee22 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -42,15 +42,42 @@ static const struct be_ethtool_stat et_stats[] = { + {DRVSTAT_INFO(rx_alignment_symbol_errors)}, + {DRVSTAT_INFO(rx_pause_frames)}, + {DRVSTAT_INFO(rx_control_frames)}, ++ /* Received packets dropped when the Ethernet length field ++ * is not equal to the actual Ethernet data length. ++ */ + {DRVSTAT_INFO(rx_in_range_errors)}, ++ /* Received packets dropped when their length field is >= 1501 bytes ++ * and <= 1535 bytes. ++ */ + {DRVSTAT_INFO(rx_out_range_errors)}, ++ /* Received packets dropped when they are longer than 9216 bytes */ + {DRVSTAT_INFO(rx_frame_too_long)}, +- {DRVSTAT_INFO(rx_address_match_errors)}, ++ /* Received packets dropped when they don't pass the unicast or ++ * multicast address filtering. ++ */ ++ {DRVSTAT_INFO(rx_address_mismatch_drops)}, ++ /* Received packets dropped when IP packet length field is less than ++ * the IP header length field. ++ */ + {DRVSTAT_INFO(rx_dropped_too_small)}, ++ /* Received packets dropped when IP length field is greater than ++ * the actual packet length. ++ */ + {DRVSTAT_INFO(rx_dropped_too_short)}, ++ /* Received packets dropped when the IP header length field is less ++ * than 5. ++ */ + {DRVSTAT_INFO(rx_dropped_header_too_small)}, ++ /* Received packets dropped when the TCP header length field is less ++ * than 5 or the TCP header length + IP header length is more ++ * than IP packet length. ++ */ + {DRVSTAT_INFO(rx_dropped_tcp_length)}, + {DRVSTAT_INFO(rx_dropped_runt)}, ++ /* Number of received packets dropped when a fifo for descriptors going ++ * into the packet demux block overflows. In normal operation, this ++ * fifo must never overflow. ++ */ + {DRVSTAT_INFO(rxpp_fifo_overflow_drop)}, + {DRVSTAT_INFO(rx_input_fifo_overflow_drop)}, + {DRVSTAT_INFO(rx_ip_checksum_errs)}, +@@ -59,16 +86,35 @@ static const struct be_ethtool_stat et_stats[] = { + {DRVSTAT_INFO(tx_pauseframes)}, + {DRVSTAT_INFO(tx_controlframes)}, + {DRVSTAT_INFO(rx_priority_pause_frames)}, ++ /* Received packets dropped when an internal fifo going into ++ * main packet buffer tank (PMEM) overflows. ++ */ + {DRVSTAT_INFO(pmem_fifo_overflow_drop)}, + {DRVSTAT_INFO(jabber_events)}, ++ /* Received packets dropped due to lack of available HW packet buffers ++ * used to temporarily hold the received packets. ++ */ + {DRVSTAT_INFO(rx_drops_no_pbuf)}, +- {DRVSTAT_INFO(rx_drops_no_txpb)}, ++ /* Received packets dropped due to input receive buffer ++ * descriptor fifo overflowing. ++ */ + {DRVSTAT_INFO(rx_drops_no_erx_descr)}, ++ /* Packets dropped because the internal FIFO to the offloaded TCP ++ * receive processing block is full. This could happen only for ++ * offloaded iSCSI or FCoE trarffic. ++ */ + {DRVSTAT_INFO(rx_drops_no_tpre_descr)}, ++ /* Received packets dropped when they need more than 8 ++ * receive buffers. This cannot happen as the driver configures ++ * 2048 byte receive buffers. ++ */ + {DRVSTAT_INFO(rx_drops_too_many_frags)}, +- {DRVSTAT_INFO(rx_drops_invalid_ring)}, + {DRVSTAT_INFO(forwarded_packets)}, ++ /* Received packets dropped when the frame length ++ * is more than 9018 bytes ++ */ + {DRVSTAT_INFO(rx_drops_mtu)}, ++ /* Number of packets dropped due to random early drop function */ + {DRVSTAT_INFO(eth_red_drops)}, + {DRVSTAT_INFO(be_on_die_temperature)} + }; +@@ -84,8 +130,15 @@ static const struct be_ethtool_stat et_rx_stats[] = { + {DRVSTAT_RX_INFO(rx_events)}, + {DRVSTAT_RX_INFO(rx_compl)}, + {DRVSTAT_RX_INFO(rx_mcast_pkts)}, ++ /* Number of page allocation failures while posting receive buffers ++ * to HW. ++ */ + {DRVSTAT_RX_INFO(rx_post_fail)}, ++ /* Recevied packets dropped due to skb allocation failure */ + {DRVSTAT_RX_INFO(rx_drops_no_skbs)}, ++ /* Received packets dropped due to lack of available fetched buffers ++ * posted by the driver. ++ */ + {DRVSTAT_RX_INFO(rx_drops_no_frags)} + }; + #define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats)) +@@ -97,9 +150,14 @@ static const struct be_ethtool_stat et_tx_stats[] = { + {DRVSTAT_TX_INFO(tx_compl)}, /* If moving this member see above note */ + {DRVSTAT_TX_INFO(tx_bytes)}, + {DRVSTAT_TX_INFO(tx_pkts)}, ++ /* Number of skbs queued for trasmission by the driver */ + {DRVSTAT_TX_INFO(tx_reqs)}, ++ /* Number of TX work request blocks DMAed to HW */ + {DRVSTAT_TX_INFO(tx_wrbs)}, + {DRVSTAT_TX_INFO(tx_compl)}, ++ /* Number of times the TX queue was stopped due to lack ++ * of spaces in the TXQ. ++ */ + {DRVSTAT_TX_INFO(tx_stops)} + }; + #define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats)) +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 860c461..d1536e2 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -286,7 +286,9 @@ static void populate_be2_stats(struct be_adapter *adapter) + drvs->rx_input_fifo_overflow_drop = port_stats->rx_input_fifo_overflow; + drvs->rx_dropped_header_too_small = + port_stats->rx_dropped_header_too_small; +- drvs->rx_address_match_errors = port_stats->rx_address_match_errors; ++ drvs->rx_address_mismatch_drops = ++ port_stats->rx_address_mismatch_drops + ++ port_stats->rx_vlan_mismatch_drops; + drvs->rx_alignment_symbol_errors = + port_stats->rx_alignment_symbol_errors; + +@@ -298,9 +300,7 @@ static void populate_be2_stats(struct be_adapter *adapter) + else + drvs->jabber_events = rxf_stats->port0_jabber_events; + drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf; +- drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb; + drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr; +- drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring; + drvs->forwarded_packets = rxf_stats->forwarded_packets; + drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu; + drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr; +@@ -337,7 +337,7 @@ static void populate_be3_stats(struct be_adapter *adapter) + port_stats->rx_dropped_header_too_small; + drvs->rx_input_fifo_overflow_drop = + port_stats->rx_input_fifo_overflow_drop; +- drvs->rx_address_match_errors = port_stats->rx_address_match_errors; ++ drvs->rx_address_mismatch_drops = port_stats->rx_address_mismatch_drops; + drvs->rx_alignment_symbol_errors = + port_stats->rx_alignment_symbol_errors; + drvs->rxpp_fifo_overflow_drop = port_stats->rxpp_fifo_overflow_drop; +@@ -345,9 +345,7 @@ static void populate_be3_stats(struct be_adapter *adapter) + drvs->tx_controlframes = port_stats->tx_controlframes; + drvs->jabber_events = port_stats->jabber_events; + drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf; +- drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb; + drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr; +- drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring; + drvs->forwarded_packets = rxf_stats->forwarded_packets; + drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu; + drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr; +@@ -380,13 +378,14 @@ static void populate_lancer_stats(struct be_adapter *adapter) + drvs->rx_dropped_header_too_small = + pport_stats->rx_dropped_header_too_small; + drvs->rx_input_fifo_overflow_drop = pport_stats->rx_fifo_overflow; +- drvs->rx_address_match_errors = pport_stats->rx_address_match_errors; ++ drvs->rx_address_mismatch_drops = ++ pport_stats->rx_address_mismatch_drops + ++ pport_stats->rx_vlan_mismatch_drops; + drvs->rx_alignment_symbol_errors = pport_stats->rx_symbol_errors_lo; + drvs->rxpp_fifo_overflow_drop = pport_stats->rx_fifo_overflow; + drvs->tx_pauseframes = pport_stats->tx_pause_frames_lo; + drvs->tx_controlframes = pport_stats->tx_control_frames_lo; + drvs->jabber_events = pport_stats->rx_jabbers; +- drvs->rx_drops_invalid_ring = pport_stats->rx_drops_invalid_queue; + drvs->forwarded_packets = pport_stats->num_forwards_lo; + drvs->rx_drops_mtu = pport_stats->rx_drops_mtu_lo; + drvs->rx_drops_too_many_frags = +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0030-be2net-Fix-link-status-query-command.patch b/debian/patches/features/all/be2net/0030-be2net-Fix-link-status-query-command.patch new file mode 100644 index 000000000..96309581e --- /dev/null +++ b/debian/patches/features/all/be2net/0030-be2net-Fix-link-status-query-command.patch @@ -0,0 +1,39 @@ +From: Padmanabh Ratnakar +Date: Fri, 3 Feb 2012 09:49:46 +0000 +Subject: [PATCH 30/58] be2net: Fix link status query command + +commit 57cd80d4d511748f3973accc6919e7e1e1936ebb upstream. + +Version number in query link status command is getting overwritten in +be_wrb_cmd_hdr_prepare() routine. Move the initialization to fix this +issue. Also initialize the domain field. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 0fcb456..dd6e8e2 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -1257,11 +1257,13 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, + } + req = embedded_payload(wrb); + ++ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, ++ OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL); ++ + if (adapter->generation == BE_GEN3 || lancer_chip(adapter)) + req->hdr.version = 1; + +- be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, +- OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL); ++ req->hdr.domain = dom; + + status = be_mcc_notify_wait(adapter); + if (!status) { +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0031-be2net-Use-new-implementation-of-get-mac-list-comman.patch b/debian/patches/features/all/be2net/0031-be2net-Use-new-implementation-of-get-mac-list-comman.patch new file mode 100644 index 000000000..5f3ab3580 --- /dev/null +++ b/debian/patches/features/all/be2net/0031-be2net-Use-new-implementation-of-get-mac-list-comman.patch @@ -0,0 +1,237 @@ +From: Padmanabh Ratnakar +Date: Fri, 3 Feb 2012 09:50:17 +0000 +Subject: [PATCH 31/58] be2net: Use new implementation of get mac list command + +commit e5e1ee89461543043a0144e6dac90547fefe2f89 upstream. + +VFs use get mac list command to get their mac address. The format of +this command has changed. Update driver to use the new format. + +Signed-off-by: Mammatha Edhala +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 67 +++++++++++++++++++-------- + drivers/net/ethernet/emulex/benet/be_cmds.h | 36 +++++++++----- + drivers/net/ethernet/emulex/benet/be_main.c | 29 ++++++++---- + 3 files changed, 92 insertions(+), 40 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index dd6e8e2..29dff7d 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -2300,52 +2300,81 @@ err: + + /* Uses synchronous MCCQ */ + int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain, +- u32 *pmac_id) ++ bool *pmac_id_active, u32 *pmac_id, u8 *mac) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_mac_list *req; + int status; + int mac_count; ++ struct be_dma_mem get_mac_list_cmd; ++ int i; ++ ++ memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem)); ++ get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list); ++ get_mac_list_cmd.va = pci_alloc_consistent(adapter->pdev, ++ get_mac_list_cmd.size, ++ &get_mac_list_cmd.dma); ++ ++ if (!get_mac_list_cmd.va) { ++ dev_err(&adapter->pdev->dev, ++ "Memory allocation failure during GET_MAC_LIST\n"); ++ return -ENOMEM; ++ } + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; +- goto err; ++ goto out; + } +- req = embedded_payload(wrb); ++ ++ req = get_mac_list_cmd.va; + + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_MAC_LIST, sizeof(*req), +- wrb, NULL); ++ wrb, &get_mac_list_cmd); + + req->hdr.domain = domain; ++ req->mac_type = MAC_ADDRESS_TYPE_NETWORK; ++ req->perm_override = 1; + + status = be_mcc_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_get_mac_list *resp = +- embedded_payload(wrb); +- int i; +- u8 *ctxt = &resp->context[0][0]; +- status = -EIO; +- mac_count = resp->mac_count; +- be_dws_le_to_cpu(&resp->context, sizeof(resp->context)); ++ get_mac_list_cmd.va; ++ mac_count = resp->true_mac_count + resp->pseudo_mac_count; ++ /* Mac list returned could contain one or more active mac_ids ++ * or one or more pseudo permanant mac addresses. If an active ++ * mac_id is present, return first active mac_id found ++ */ + for (i = 0; i < mac_count; i++) { +- if (!AMAP_GET_BITS(struct amap_get_mac_list_context, +- act, ctxt)) { +- *pmac_id = AMAP_GET_BITS +- (struct amap_get_mac_list_context, +- macid, ctxt); +- status = 0; +- break; ++ struct get_list_macaddr *mac_entry; ++ u16 mac_addr_size; ++ u32 mac_id; ++ ++ mac_entry = &resp->macaddr_list[i]; ++ mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size); ++ /* mac_id is a 32 bit value and mac_addr size ++ * is 6 bytes ++ */ ++ if (mac_addr_size == sizeof(u32)) { ++ *pmac_id_active = true; ++ mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id; ++ *pmac_id = le32_to_cpu(mac_id); ++ goto out; + } +- ctxt += sizeof(struct amap_get_mac_list_context) / 8; + } ++ /* If no active mac_id found, return first pseudo mac addr */ ++ *pmac_id_active = false; ++ memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr, ++ ETH_ALEN); + } + +-err: ++out: + spin_unlock_bh(&adapter->mcc_lock); ++ pci_free_consistent(adapter->pdev, get_mac_list_cmd.size, ++ get_mac_list_cmd.va, get_mac_list_cmd.dma); + return status; + } + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h +index bbd012b..5bb66c8 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.h ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.h +@@ -1346,22 +1346,36 @@ struct be_cmd_resp_set_func_cap { + + /******************** GET/SET_MACLIST **************************/ + #define BE_MAX_MAC 64 +-struct amap_get_mac_list_context { +- u8 macid[31]; +- u8 act; +-} __packed; +- + struct be_cmd_req_get_mac_list { + struct be_cmd_req_hdr hdr; +- u32 rsvd; ++ u8 mac_type; ++ u8 perm_override; ++ u16 iface_id; ++ u32 mac_id; ++ u32 rsvd[3]; ++} __packed; ++ ++struct get_list_macaddr { ++ u16 mac_addr_size; ++ union { ++ u8 macaddr[6]; ++ struct { ++ u8 rsvd[2]; ++ u32 mac_id; ++ } __packed s_mac_id; ++ } __packed mac_addr_id; + } __packed; + + struct be_cmd_resp_get_mac_list { + struct be_cmd_resp_hdr hdr; +- u8 mac_count; +- u8 rsvd1; +- u16 rsvd2; +- u8 context[sizeof(struct amap_get_mac_list_context) / 8][BE_MAX_MAC]; ++ struct get_list_macaddr fd_macaddr; /* Factory default mac */ ++ struct get_list_macaddr macid_macaddr; /* soft mac */ ++ u8 true_mac_count; ++ u8 pseudo_mac_count; ++ u8 mac_list_size; ++ u8 rsvd; ++ /* perm override mac */ ++ struct get_list_macaddr macaddr_list[BE_MAX_MAC]; + } __packed; + + struct be_cmd_req_set_mac_list { +@@ -1575,7 +1589,7 @@ extern int be_cmd_req_native_mode(struct be_adapter *adapter); + extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size); + extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf); + extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain, +- u32 *pmac_id); ++ bool *pmac_id_active, u32 *pmac_id, u8 *mac); + extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, + u8 mac_count, u32 domain); + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index d1536e2..4364f01 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -2600,19 +2600,28 @@ static void be_setup_init(struct be_adapter *adapter) + adapter->eq_next_idx = 0; + } + +-static int be_configure_mac_from_list(struct be_adapter *adapter, u8 *mac) ++static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac) + { + u32 pmac_id; +- int status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id); +- if (status != 0) +- goto do_none; +- status = be_cmd_mac_addr_query(adapter, mac, +- MAC_ADDRESS_TYPE_NETWORK, +- false, adapter->if_handle, pmac_id); ++ int status; ++ bool pmac_id_active; ++ ++ status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id_active, ++ &pmac_id, mac); + if (status != 0) + goto do_none; +- status = be_cmd_pmac_add(adapter, mac, adapter->if_handle, +- &adapter->pmac_id, 0); ++ ++ if (pmac_id_active) { ++ status = be_cmd_mac_addr_query(adapter, mac, ++ MAC_ADDRESS_TYPE_NETWORK, ++ false, adapter->if_handle, pmac_id); ++ ++ if (!status) ++ adapter->pmac_id = pmac_id; ++ } else { ++ status = be_cmd_pmac_add(adapter, mac, ++ adapter->if_handle, &adapter->pmac_id, 0); ++ } + do_none: + return status; + } +@@ -2677,7 +2686,7 @@ static int be_setup(struct be_adapter *adapter) + */ + if (!be_physfn(adapter)) { + if (lancer_chip(adapter)) +- status = be_configure_mac_from_list(adapter, mac); ++ status = be_add_mac_from_list(adapter, mac); + else + status = be_cmd_mac_addr_query(adapter, mac, + MAC_ADDRESS_TYPE_NETWORK, false, +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0032-be2net-event-queue-re-design.patch b/debian/patches/features/all/be2net/0032-be2net-event-queue-re-design.patch new file mode 100644 index 000000000..f9c15c481 --- /dev/null +++ b/debian/patches/features/all/be2net/0032-be2net-event-queue-re-design.patch @@ -0,0 +1,1895 @@ +From: Sathya Perla +Date: Thu, 9 Feb 2012 18:05:27 +0000 +Subject: [PATCH 32/58] be2net: event queue re-design + +commit 10ef9ab4329edd08bccc7a8d34b96b85714195ce upstream. + +v2: Fixed up the bad typecasting pointed out by David... + +In the current design 8 TXQs are serviced by 1 EQ, while each RSS queue +is serviced by a separate EQ. This is being changed as follows: + +- Upto 8 EQs will be used (based on the availabilty of msix vectors). +Each EQ will handle 1 RSS and 1 TX ring. The default non-RSS RX queue and +MCC queue are handled by the last EQ. + +- On cards which provide support, upto 8 RSS rings will be used, instead +of the current limit of 4. + +The new design allows spreading the TX multi-queue completion processing +across multiple CPUs unlike the previous design. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 65 +- + drivers/net/ethernet/emulex/benet/be_cmds.c | 31 +- + drivers/net/ethernet/emulex/benet/be_cmds.h | 8 +- + drivers/net/ethernet/emulex/benet/be_ethtool.c | 96 +-- + drivers/net/ethernet/emulex/benet/be_main.c | 812 +++++++++++------------- + 5 files changed, 434 insertions(+), 578 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index 74aa148..86f51de 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -81,7 +81,7 @@ static inline char *nic_name(struct pci_dev *pdev) + #define BE_MIN_MTU 256 + + #define BE_NUM_VLANS_SUPPORTED 64 +-#define BE_MAX_EQD 96 ++#define BE_MAX_EQD 96u + #define BE_MAX_TX_FRAG_COUNT 30 + + #define EVNT_Q_LEN 1024 +@@ -92,12 +92,16 @@ static inline char *nic_name(struct pci_dev *pdev) + #define MCC_Q_LEN 128 /* total size not to exceed 8 pages */ + #define MCC_CQ_LEN 256 + +-#define MAX_RSS_QS 4 /* BE limit is 4 queues/port */ ++#define BE3_MAX_RSS_QS 8 ++#define BE2_MAX_RSS_QS 4 ++#define MAX_RSS_QS BE3_MAX_RSS_QS + #define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */ ++ + #define MAX_TX_QS 8 +-#define BE_MAX_MSIX_VECTORS (MAX_RX_QS + 1)/* RX + TX */ ++#define MAX_MSIX_VECTORS MAX_RSS_QS ++#define BE_TX_BUDGET 256 + #define BE_NAPI_WEIGHT 64 +-#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ ++#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ + #define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) + + #define FW_VER_LEN 32 +@@ -165,13 +169,16 @@ struct be_eq_obj { + + /* Adaptive interrupt coalescing (AIC) info */ + bool enable_aic; +- u16 min_eqd; /* in usecs */ +- u16 max_eqd; /* in usecs */ +- u16 cur_eqd; /* in usecs */ +- u8 eq_idx; ++ u32 min_eqd; /* in usecs */ ++ u32 max_eqd; /* in usecs */ ++ u32 eqd; /* configured val when aic is off */ ++ u32 cur_eqd; /* in usecs */ + ++ u8 idx; /* array index */ ++ u16 tx_budget; + struct napi_struct napi; +-}; ++ struct be_adapter *adapter; ++} ____cacheline_aligned_in_smp; + + struct be_mcc_obj { + struct be_queue_info q; +@@ -197,7 +204,7 @@ struct be_tx_obj { + /* Remember the skbs that were transmitted */ + struct sk_buff *sent_skb_list[TX_Q_LEN]; + struct be_tx_stats stats; +-}; ++} ____cacheline_aligned_in_smp; + + /* Struct to remember the pages posted for rx frags */ + struct be_rx_page_info { +@@ -215,8 +222,6 @@ struct be_rx_stats { + u32 rx_drops_no_skbs; /* skb allocation errors */ + u32 rx_drops_no_frags; /* HW has no fetched frags */ + u32 rx_post_fail; /* page post alloc failures */ +- u32 rx_polls; /* NAPI calls */ +- u32 rx_events; + u32 rx_compl; + u32 rx_mcast_pkts; + u32 rx_compl_err; /* completions with err set */ +@@ -249,16 +254,13 @@ struct be_rx_obj { + struct be_queue_info cq; + struct be_rx_compl_info rxcp; + struct be_rx_page_info page_info_tbl[RX_Q_LEN]; +- struct be_eq_obj rx_eq; + struct be_rx_stats stats; + u8 rss_id; + bool rx_post_starved; /* Zero rx frags have been posted to BE */ +- u32 cache_line_barrier[16]; +-}; ++} ____cacheline_aligned_in_smp; + + struct be_drv_stats { + u32 be_on_die_temperature; +- u32 tx_events; + u32 eth_red_drops; + u32 rx_drops_no_pbuf; + u32 rx_drops_no_txpb; +@@ -320,20 +322,19 @@ struct be_adapter { + spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */ + spinlock_t mcc_cq_lock; + +- struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS]; + u32 num_msix_vec; ++ u32 num_evt_qs; ++ struct be_eq_obj eq_obj[MAX_MSIX_VECTORS]; ++ struct msix_entry msix_entries[MAX_MSIX_VECTORS]; + bool isr_registered; + + /* TX Rings */ +- struct be_eq_obj tx_eq; ++ u32 num_tx_qs; + struct be_tx_obj tx_obj[MAX_TX_QS]; +- u8 num_tx_qs; +- +- u32 cache_line_break[8]; + + /* Rx rings */ +- struct be_rx_obj rx_obj[MAX_RX_QS]; + u32 num_rx_qs; ++ struct be_rx_obj rx_obj[MAX_RX_QS]; + u32 big_page_size; /* Compounded page size shared by rx wrbs */ + + u8 eq_next_idx; +@@ -404,24 +405,34 @@ struct be_adapter { + extern const struct ethtool_ops be_ethtool_ops; + + #define msix_enabled(adapter) (adapter->num_msix_vec > 0) +-#define tx_stats(txo) (&txo->stats) +-#define rx_stats(rxo) (&rxo->stats) ++#define num_irqs(adapter) (msix_enabled(adapter) ? \ ++ adapter->num_msix_vec : 1) ++#define tx_stats(txo) (&(txo)->stats) ++#define rx_stats(rxo) (&(rxo)->stats) + +-#define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) ++/* The default RXQ is the last RXQ */ ++#define default_rxo(adpt) (&adpt->rx_obj[adpt->num_rx_qs - 1]) + + #define for_all_rx_queues(adapter, rxo, i) \ + for (i = 0, rxo = &adapter->rx_obj[i]; i < adapter->num_rx_qs; \ + i++, rxo++) + +-/* Just skip the first default non-rss queue */ ++/* Skip the default non-rss queue (last one)*/ + #define for_all_rss_queues(adapter, rxo, i) \ +- for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\ ++ for (i = 0, rxo = &adapter->rx_obj[i]; i < (adapter->num_rx_qs - 1);\ + i++, rxo++) + + #define for_all_tx_queues(adapter, txo, i) \ + for (i = 0, txo = &adapter->tx_obj[i]; i < adapter->num_tx_qs; \ + i++, txo++) + ++#define for_all_evt_queues(adapter, eqo, i) \ ++ for (i = 0, eqo = &adapter->eq_obj[i]; i < adapter->num_evt_qs; \ ++ i++, eqo++) ++ ++#define is_mcc_eqo(eqo) (eqo->idx == 0) ++#define mcc_eqo(adapter) (&adapter->eq_obj[0]) ++ + #define PAGE_SHIFT_4K 12 + #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 29dff7d..6432efa 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -235,10 +235,10 @@ void be_async_mcc_disable(struct be_adapter *adapter) + adapter->mcc_obj.rearm_cq = false; + } + +-int be_process_mcc(struct be_adapter *adapter, int *status) ++int be_process_mcc(struct be_adapter *adapter) + { + struct be_mcc_compl *compl; +- int num = 0; ++ int num = 0, status = 0; + struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; + + spin_lock_bh(&adapter->mcc_cq_lock); +@@ -252,32 +252,32 @@ int be_process_mcc(struct be_adapter *adapter, int *status) + be_async_grp5_evt_process(adapter, + compl->flags, compl); + } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { +- *status = be_mcc_compl_process(adapter, compl); ++ status = be_mcc_compl_process(adapter, compl); + atomic_dec(&mcc_obj->q.used); + } + be_mcc_compl_use(compl); + num++; + } + ++ if (num) ++ be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num); ++ + spin_unlock_bh(&adapter->mcc_cq_lock); +- return num; ++ return status; + } + + /* Wait till no more pending mcc requests are present */ + static int be_mcc_wait_compl(struct be_adapter *adapter) + { + #define mcc_timeout 120000 /* 12s timeout */ +- int i, num, status = 0; ++ int i, status = 0; + struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; + + for (i = 0; i < mcc_timeout; i++) { + if (be_error(adapter)) + return -EIO; + +- num = be_process_mcc(adapter, &status); +- if (num) +- be_cq_notify(adapter, mcc_obj->cq.id, +- mcc_obj->rearm_cq, num); ++ status = be_process_mcc(adapter); + + if (atomic_read(&mcc_obj->q.used) == 0) + break; +@@ -726,9 +726,8 @@ err: + } + + /* Uses Mbox */ +-int be_cmd_cq_create(struct be_adapter *adapter, +- struct be_queue_info *cq, struct be_queue_info *eq, +- bool sol_evts, bool no_delay, int coalesce_wm) ++int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq, ++ struct be_queue_info *eq, bool no_delay, int coalesce_wm) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_cq_create *req; +@@ -759,7 +758,6 @@ int be_cmd_cq_create(struct be_adapter *adapter, + ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context_lancer, eqid, + ctxt, eq->id); +- AMAP_SET_BITS(struct amap_cq_context_lancer, armed, ctxt, 1); + } else { + AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt, + coalesce_wm); +@@ -768,11 +766,8 @@ int be_cmd_cq_create(struct be_adapter *adapter, + AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt, + __ilog2_u32(cq->len/256)); + AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1); +- AMAP_SET_BITS(struct amap_cq_context_be, solevent, +- ctxt, sol_evts); + AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id); +- AMAP_SET_BITS(struct amap_cq_context_be, armed, ctxt, 1); + } + + be_dws_cpu_to_le(ctxt, sizeof(req->context)); +@@ -973,7 +968,7 @@ err: + /* Uses MCC */ + int be_cmd_rxq_create(struct be_adapter *adapter, + struct be_queue_info *rxq, u16 cq_id, u16 frag_size, +- u16 max_frame_size, u32 if_id, u32 rss, u8 *rss_id) ++ u32 if_id, u32 rss, u8 *rss_id) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_eth_rx_create *req; +@@ -997,7 +992,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter, + req->num_pages = 2; + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + req->interface_id = cpu_to_le32(if_id); +- req->max_frame_size = cpu_to_le16(max_frame_size); ++ req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE); + req->rss_queue = cpu_to_le32(rss); + + status = be_mcc_notify_wait(adapter); +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h +index 5bb66c8..687c420 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.h ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.h +@@ -1506,8 +1506,7 @@ extern int be_cmd_eq_create(struct be_adapter *adapter, + struct be_queue_info *eq, int eq_delay); + extern int be_cmd_cq_create(struct be_adapter *adapter, + struct be_queue_info *cq, struct be_queue_info *eq, +- bool sol_evts, bool no_delay, +- int num_cqe_dma_coalesce); ++ bool no_delay, int num_cqe_dma_coalesce); + extern int be_cmd_mccq_create(struct be_adapter *adapter, + struct be_queue_info *mccq, + struct be_queue_info *cq); +@@ -1516,8 +1515,7 @@ extern int be_cmd_txq_create(struct be_adapter *adapter, + struct be_queue_info *cq); + extern int be_cmd_rxq_create(struct be_adapter *adapter, + struct be_queue_info *rxq, u16 cq_id, +- u16 frag_size, u16 max_frame_size, u32 if_id, +- u32 rss, u8 *rss_id); ++ u16 frag_size, u32 if_id, u32 rss, u8 *rss_id); + extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, + int type); + extern int be_cmd_rxq_destroy(struct be_adapter *adapter, +@@ -1546,7 +1544,7 @@ extern int be_cmd_query_fw_cfg(struct be_adapter *adapter, + extern int be_cmd_reset_function(struct be_adapter *adapter); + extern int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, + u16 table_size); +-extern int be_process_mcc(struct be_adapter *adapter, int *status); ++extern int be_process_mcc(struct be_adapter *adapter); + extern int be_cmd_set_beacon_state(struct be_adapter *adapter, + u8 port_num, u8 beacon, u8 status, u8 state); + extern int be_cmd_get_beacon_state(struct be_adapter *adapter, +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index 0a5ee22..d98ad7e 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -37,7 +37,6 @@ enum {DRVSTAT_TX, DRVSTAT_RX, DRVSTAT}; + FIELDINFO(struct be_drv_stats, field) + + static const struct be_ethtool_stat et_stats[] = { +- {DRVSTAT_INFO(tx_events)}, + {DRVSTAT_INFO(rx_crc_errors)}, + {DRVSTAT_INFO(rx_alignment_symbol_errors)}, + {DRVSTAT_INFO(rx_pause_frames)}, +@@ -126,8 +125,6 @@ static const struct be_ethtool_stat et_stats[] = { + static const struct be_ethtool_stat et_rx_stats[] = { + {DRVSTAT_RX_INFO(rx_bytes)},/* If moving this member see above note */ + {DRVSTAT_RX_INFO(rx_pkts)}, /* If moving this member see above note */ +- {DRVSTAT_RX_INFO(rx_polls)}, +- {DRVSTAT_RX_INFO(rx_events)}, + {DRVSTAT_RX_INFO(rx_compl)}, + {DRVSTAT_RX_INFO(rx_mcast_pkts)}, + /* Number of page allocation failures while posting receive buffers +@@ -154,7 +151,6 @@ static const struct be_ethtool_stat et_tx_stats[] = { + {DRVSTAT_TX_INFO(tx_reqs)}, + /* Number of TX work request blocks DMAed to HW */ + {DRVSTAT_TX_INFO(tx_wrbs)}, +- {DRVSTAT_TX_INFO(tx_compl)}, + /* Number of times the TX queue was stopped due to lack + * of spaces in the TXQ. + */ +@@ -290,86 +286,42 @@ be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf) + } + } + +-static int +-be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) ++static int be_get_coalesce(struct net_device *netdev, ++ struct ethtool_coalesce *et) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_eq_obj *rx_eq = &adapter->rx_obj[0].rx_eq; +- struct be_eq_obj *tx_eq = &adapter->tx_eq; ++ struct be_eq_obj *eqo = &adapter->eq_obj[0]; ++ + +- coalesce->rx_coalesce_usecs = rx_eq->cur_eqd; +- coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd; +- coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd; ++ et->rx_coalesce_usecs = eqo->cur_eqd; ++ et->rx_coalesce_usecs_high = eqo->max_eqd; ++ et->rx_coalesce_usecs_low = eqo->min_eqd; + +- coalesce->tx_coalesce_usecs = tx_eq->cur_eqd; +- coalesce->tx_coalesce_usecs_high = tx_eq->max_eqd; +- coalesce->tx_coalesce_usecs_low = tx_eq->min_eqd; ++ et->tx_coalesce_usecs = eqo->cur_eqd; ++ et->tx_coalesce_usecs_high = eqo->max_eqd; ++ et->tx_coalesce_usecs_low = eqo->min_eqd; + +- coalesce->use_adaptive_rx_coalesce = rx_eq->enable_aic; +- coalesce->use_adaptive_tx_coalesce = tx_eq->enable_aic; ++ et->use_adaptive_rx_coalesce = eqo->enable_aic; ++ et->use_adaptive_tx_coalesce = eqo->enable_aic; + + return 0; + } + +-/* +- * This routine is used to set interrup coalescing delay ++/* TX attributes are ignored. Only RX attributes are considered ++ * eqd cmd is issued in the worker thread. + */ +-static int +-be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) ++static int be_set_coalesce(struct net_device *netdev, ++ struct ethtool_coalesce *et) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_rx_obj *rxo; +- struct be_eq_obj *rx_eq; +- struct be_eq_obj *tx_eq = &adapter->tx_eq; +- u32 rx_max, rx_min, rx_cur; +- int status = 0, i; +- u32 tx_cur; +- +- if (coalesce->use_adaptive_tx_coalesce == 1) +- return -EINVAL; +- +- for_all_rx_queues(adapter, rxo, i) { +- rx_eq = &rxo->rx_eq; +- +- if (!rx_eq->enable_aic && coalesce->use_adaptive_rx_coalesce) +- rx_eq->cur_eqd = 0; +- rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce; +- +- rx_max = coalesce->rx_coalesce_usecs_high; +- rx_min = coalesce->rx_coalesce_usecs_low; +- rx_cur = coalesce->rx_coalesce_usecs; +- +- if (rx_eq->enable_aic) { +- if (rx_max > BE_MAX_EQD) +- rx_max = BE_MAX_EQD; +- if (rx_min > rx_max) +- rx_min = rx_max; +- rx_eq->max_eqd = rx_max; +- rx_eq->min_eqd = rx_min; +- if (rx_eq->cur_eqd > rx_max) +- rx_eq->cur_eqd = rx_max; +- if (rx_eq->cur_eqd < rx_min) +- rx_eq->cur_eqd = rx_min; +- } else { +- if (rx_cur > BE_MAX_EQD) +- rx_cur = BE_MAX_EQD; +- if (rx_eq->cur_eqd != rx_cur) { +- status = be_cmd_modify_eqd(adapter, rx_eq->q.id, +- rx_cur); +- if (!status) +- rx_eq->cur_eqd = rx_cur; +- } +- } +- } +- +- tx_cur = coalesce->tx_coalesce_usecs; +- +- if (tx_cur > BE_MAX_EQD) +- tx_cur = BE_MAX_EQD; +- if (tx_eq->cur_eqd != tx_cur) { +- status = be_cmd_modify_eqd(adapter, tx_eq->q.id, tx_cur); +- if (!status) +- tx_eq->cur_eqd = tx_cur; ++ struct be_eq_obj *eqo; ++ int i; ++ ++ for_all_evt_queues(adapter, eqo, i) { ++ eqo->enable_aic = et->use_adaptive_rx_coalesce; ++ eqo->max_eqd = min(et->rx_coalesce_usecs_high, BE_MAX_EQD); ++ eqo->min_eqd = min(et->rx_coalesce_usecs_low, eqo->max_eqd); ++ eqo->eqd = et->rx_coalesce_usecs; + } + + return 0; +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 4364f01..4a3a186 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -144,7 +144,7 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q, + mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size, &mem->dma, + GFP_KERNEL); + if (!mem->va) +- return -1; ++ return -ENOMEM; + memset(mem->va, 0, mem->size); + return 0; + } +@@ -988,18 +988,24 @@ static int be_set_vf_tx_rate(struct net_device *netdev, + return status; + } + +-static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo) ++static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo) + { +- struct be_eq_obj *rx_eq = &rxo->rx_eq; +- struct be_rx_stats *stats = rx_stats(rxo); ++ struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]); + ulong now = jiffies; + ulong delta = now - stats->rx_jiffies; + u64 pkts; + unsigned int start, eqd; + +- if (!rx_eq->enable_aic) ++ if (!eqo->enable_aic) { ++ eqd = eqo->eqd; ++ goto modify_eqd; ++ } ++ ++ if (eqo->idx >= adapter->num_rx_qs) + return; + ++ stats = rx_stats(&adapter->rx_obj[eqo->idx]); ++ + /* Wrapped around */ + if (time_before(now, stats->rx_jiffies)) { + stats->rx_jiffies = now; +@@ -1018,17 +1024,16 @@ static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo) + stats->rx_pps = (unsigned long)(pkts - stats->rx_pkts_prev) / (delta / HZ); + stats->rx_pkts_prev = pkts; + stats->rx_jiffies = now; +- eqd = stats->rx_pps / 110000; +- eqd = eqd << 3; +- if (eqd > rx_eq->max_eqd) +- eqd = rx_eq->max_eqd; +- if (eqd < rx_eq->min_eqd) +- eqd = rx_eq->min_eqd; ++ eqd = (stats->rx_pps / 110000) << 3; ++ eqd = min(eqd, eqo->max_eqd); ++ eqd = max(eqd, eqo->min_eqd); + if (eqd < 10) + eqd = 0; +- if (eqd != rx_eq->cur_eqd) { +- be_cmd_modify_eqd(adapter, rx_eq->q.id, eqd); +- rx_eq->cur_eqd = eqd; ++ ++modify_eqd: ++ if (eqd != eqo->cur_eqd) { ++ be_cmd_modify_eqd(adapter, eqo->q.id, eqd); ++ eqo->cur_eqd = eqd; + } + } + +@@ -1056,11 +1061,10 @@ static inline bool csum_passed(struct be_rx_compl_info *rxcp) + (rxcp->ip_csum || rxcp->ipv6); + } + +-static struct be_rx_page_info * +-get_rx_page_info(struct be_adapter *adapter, +- struct be_rx_obj *rxo, +- u16 frag_idx) ++static struct be_rx_page_info *get_rx_page_info(struct be_rx_obj *rxo, ++ u16 frag_idx) + { ++ struct be_adapter *adapter = rxo->adapter; + struct be_rx_page_info *rx_page_info; + struct be_queue_info *rxq = &rxo->q; + +@@ -1079,16 +1083,15 @@ get_rx_page_info(struct be_adapter *adapter, + } + + /* Throwaway the data in the Rx completion */ +-static void be_rx_compl_discard(struct be_adapter *adapter, +- struct be_rx_obj *rxo, +- struct be_rx_compl_info *rxcp) ++static void be_rx_compl_discard(struct be_rx_obj *rxo, ++ struct be_rx_compl_info *rxcp) + { + struct be_queue_info *rxq = &rxo->q; + struct be_rx_page_info *page_info; + u16 i, num_rcvd = rxcp->num_rcvd; + + for (i = 0; i < num_rcvd; i++) { +- page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx); ++ page_info = get_rx_page_info(rxo, rxcp->rxq_idx); + put_page(page_info->page); + memset(page_info, 0, sizeof(*page_info)); + index_inc(&rxcp->rxq_idx, rxq->len); +@@ -1099,8 +1102,8 @@ static void be_rx_compl_discard(struct be_adapter *adapter, + * skb_fill_rx_data forms a complete skb for an ether frame + * indicated by rxcp. + */ +-static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo, +- struct sk_buff *skb, struct be_rx_compl_info *rxcp) ++static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb, ++ struct be_rx_compl_info *rxcp) + { + struct be_queue_info *rxq = &rxo->q; + struct be_rx_page_info *page_info; +@@ -1108,7 +1111,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo, + u16 hdr_len, curr_frag_len, remaining; + u8 *start; + +- page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx); ++ page_info = get_rx_page_info(rxo, rxcp->rxq_idx); + start = page_address(page_info->page) + page_info->page_offset; + prefetch(start); + +@@ -1145,7 +1148,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo, + index_inc(&rxcp->rxq_idx, rxq->len); + remaining = rxcp->pkt_size - curr_frag_len; + for (i = 1, j = 0; i < rxcp->num_rcvd; i++) { +- page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx); ++ page_info = get_rx_page_info(rxo, rxcp->rxq_idx); + curr_frag_len = min(remaining, rx_frag_size); + + /* Coalesce all frags from the same physical page in one slot */ +@@ -1173,21 +1176,21 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo, + } + + /* Process the RX completion indicated by rxcp when GRO is disabled */ +-static void be_rx_compl_process(struct be_adapter *adapter, +- struct be_rx_obj *rxo, +- struct be_rx_compl_info *rxcp) ++static void be_rx_compl_process(struct be_rx_obj *rxo, ++ struct be_rx_compl_info *rxcp) + { ++ struct be_adapter *adapter = rxo->adapter; + struct net_device *netdev = adapter->netdev; + struct sk_buff *skb; + + skb = netdev_alloc_skb_ip_align(netdev, BE_RX_SKB_ALLOC_SIZE); + if (unlikely(!skb)) { + rx_stats(rxo)->rx_drops_no_skbs++; +- be_rx_compl_discard(adapter, rxo, rxcp); ++ be_rx_compl_discard(rxo, rxcp); + return; + } + +- skb_fill_rx_data(adapter, rxo, skb, rxcp); ++ skb_fill_rx_data(rxo, skb, rxcp); + + if (likely((netdev->features & NETIF_F_RXCSUM) && csum_passed(rxcp))) + skb->ip_summed = CHECKSUM_UNNECESSARY; +@@ -1195,7 +1198,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, + skb_checksum_none_assert(skb); + + skb->protocol = eth_type_trans(skb, netdev); +- if (adapter->netdev->features & NETIF_F_RXHASH) ++ if (netdev->features & NETIF_F_RXHASH) + skb->rxhash = rxcp->rss_hash; + + +@@ -1206,26 +1209,25 @@ static void be_rx_compl_process(struct be_adapter *adapter, + } + + /* Process the RX completion indicated by rxcp when GRO is enabled */ +-static void be_rx_compl_process_gro(struct be_adapter *adapter, +- struct be_rx_obj *rxo, +- struct be_rx_compl_info *rxcp) ++void be_rx_compl_process_gro(struct be_rx_obj *rxo, struct napi_struct *napi, ++ struct be_rx_compl_info *rxcp) + { ++ struct be_adapter *adapter = rxo->adapter; + struct be_rx_page_info *page_info; + struct sk_buff *skb = NULL; + struct be_queue_info *rxq = &rxo->q; +- struct be_eq_obj *eq_obj = &rxo->rx_eq; + u16 remaining, curr_frag_len; + u16 i, j; + +- skb = napi_get_frags(&eq_obj->napi); ++ skb = napi_get_frags(napi); + if (!skb) { +- be_rx_compl_discard(adapter, rxo, rxcp); ++ be_rx_compl_discard(rxo, rxcp); + return; + } + + remaining = rxcp->pkt_size; + for (i = 0, j = -1; i < rxcp->num_rcvd; i++) { +- page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx); ++ page_info = get_rx_page_info(rxo, rxcp->rxq_idx); + + curr_frag_len = min(remaining, rx_frag_size); + +@@ -1258,12 +1260,11 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, + if (rxcp->vlanf) + __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); + +- napi_gro_frags(&eq_obj->napi); ++ napi_gro_frags(napi); + } + +-static void be_parse_rx_compl_v1(struct be_adapter *adapter, +- struct be_eth_rx_compl *compl, +- struct be_rx_compl_info *rxcp) ++static void be_parse_rx_compl_v1(struct be_eth_rx_compl *compl, ++ struct be_rx_compl_info *rxcp) + { + rxcp->pkt_size = + AMAP_GET_BITS(struct amap_eth_rx_compl_v1, pktsize, compl); +@@ -1294,9 +1295,8 @@ static void be_parse_rx_compl_v1(struct be_adapter *adapter, + rxcp->port = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, port, compl); + } + +-static void be_parse_rx_compl_v0(struct be_adapter *adapter, +- struct be_eth_rx_compl *compl, +- struct be_rx_compl_info *rxcp) ++static void be_parse_rx_compl_v0(struct be_eth_rx_compl *compl, ++ struct be_rx_compl_info *rxcp) + { + rxcp->pkt_size = + AMAP_GET_BITS(struct amap_eth_rx_compl_v0, pktsize, compl); +@@ -1342,9 +1342,9 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo) + be_dws_le_to_cpu(compl, sizeof(*compl)); + + if (adapter->be3_native) +- be_parse_rx_compl_v1(adapter, compl, rxcp); ++ be_parse_rx_compl_v1(compl, rxcp); + else +- be_parse_rx_compl_v0(adapter, compl, rxcp); ++ be_parse_rx_compl_v0(compl, rxcp); + + if (rxcp->vlanf) { + /* vlanf could be wrongly set in some cards. +@@ -1383,7 +1383,6 @@ static inline struct page *be_alloc_pages(u32 size, gfp_t gfp) + static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp) + { + struct be_adapter *adapter = rxo->adapter; +- struct be_rx_page_info *page_info_tbl = rxo->page_info_tbl; + struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL; + struct be_queue_info *rxq = &rxo->q; + struct page *pagep = NULL; +@@ -1425,7 +1424,7 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp) + + prev_page_info = page_info; + queue_head_inc(rxq); +- page_info = &page_info_tbl[rxq->head]; ++ page_info = &rxo->page_info_tbl[rxq->head]; + } + if (pagep) + prev_page_info->last_page_user = true; +@@ -1487,62 +1486,51 @@ static u16 be_tx_compl_process(struct be_adapter *adapter, + return num_wrbs; + } + +-static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj) ++/* Return the number of events in the event queue */ ++static inline int events_get(struct be_eq_obj *eqo) + { +- struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q); ++ struct be_eq_entry *eqe; ++ int num = 0; + +- if (!eqe->evt) +- return NULL; ++ do { ++ eqe = queue_tail_node(&eqo->q); ++ if (eqe->evt == 0) ++ break; + +- rmb(); +- eqe->evt = le32_to_cpu(eqe->evt); +- queue_tail_inc(&eq_obj->q); +- return eqe; ++ rmb(); ++ eqe->evt = 0; ++ num++; ++ queue_tail_inc(&eqo->q); ++ } while (true); ++ ++ return num; + } + +-static int event_handle(struct be_adapter *adapter, +- struct be_eq_obj *eq_obj, +- bool rearm) ++static int event_handle(struct be_eq_obj *eqo) + { +- struct be_eq_entry *eqe; +- u16 num = 0; +- +- while ((eqe = event_get(eq_obj)) != NULL) { +- eqe->evt = 0; +- num++; +- } ++ bool rearm = false; ++ int num = events_get(eqo); + +- /* Deal with any spurious interrupts that come +- * without events +- */ ++ /* Deal with any spurious interrupts that come without events */ + if (!num) + rearm = true; + +- be_eq_notify(adapter, eq_obj->q.id, rearm, true, num); ++ be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num); + if (num) +- napi_schedule(&eq_obj->napi); ++ napi_schedule(&eqo->napi); + + return num; + } + +-/* Just read and notify events without processing them. +- * Used at the time of destroying event queues */ +-static void be_eq_clean(struct be_adapter *adapter, +- struct be_eq_obj *eq_obj) ++/* Leaves the EQ is disarmed state */ ++static void be_eq_clean(struct be_eq_obj *eqo) + { +- struct be_eq_entry *eqe; +- u16 num = 0; +- +- while ((eqe = event_get(eq_obj)) != NULL) { +- eqe->evt = 0; +- num++; +- } ++ int num = events_get(eqo); + +- if (num) +- be_eq_notify(adapter, eq_obj->q.id, false, true, num); ++ be_eq_notify(eqo->adapter, eqo->q.id, false, true, num); + } + +-static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo) ++static void be_rx_cq_clean(struct be_rx_obj *rxo) + { + struct be_rx_page_info *page_info; + struct be_queue_info *rxq = &rxo->q; +@@ -1552,14 +1540,14 @@ static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo) + + /* First cleanup pending rx completions */ + while ((rxcp = be_rx_compl_get(rxo)) != NULL) { +- be_rx_compl_discard(adapter, rxo, rxcp); +- be_cq_notify(adapter, rx_cq->id, false, 1); ++ be_rx_compl_discard(rxo, rxcp); ++ be_cq_notify(rxo->adapter, rx_cq->id, false, 1); + } + + /* Then free posted rx buffer that were not used */ + tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len; + for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) { +- page_info = get_rx_page_info(adapter, rxo, tail); ++ page_info = get_rx_page_info(rxo, tail); + put_page(page_info->page); + memset(page_info, 0, sizeof(*page_info)); + } +@@ -1615,6 +1603,47 @@ static void be_tx_compl_clean(struct be_adapter *adapter, + } + } + ++static void be_evt_queues_destroy(struct be_adapter *adapter) ++{ ++ struct be_eq_obj *eqo; ++ int i; ++ ++ for_all_evt_queues(adapter, eqo, i) { ++ be_eq_clean(eqo); ++ if (eqo->q.created) ++ be_cmd_q_destroy(adapter, &eqo->q, QTYPE_EQ); ++ be_queue_free(adapter, &eqo->q); ++ } ++} ++ ++static int be_evt_queues_create(struct be_adapter *adapter) ++{ ++ struct be_queue_info *eq; ++ struct be_eq_obj *eqo; ++ int i, rc; ++ ++ adapter->num_evt_qs = num_irqs(adapter); ++ ++ for_all_evt_queues(adapter, eqo, i) { ++ eqo->adapter = adapter; ++ eqo->tx_budget = BE_TX_BUDGET; ++ eqo->idx = i; ++ eqo->max_eqd = BE_MAX_EQD; ++ eqo->enable_aic = true; ++ ++ eq = &eqo->q; ++ rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN, ++ sizeof(struct be_eq_entry)); ++ if (rc) ++ return rc; ++ ++ rc = be_cmd_eq_create(adapter, eq, eqo->cur_eqd); ++ if (rc) ++ return rc; ++ } ++ return rc; ++} ++ + static void be_mcc_queues_destroy(struct be_adapter *adapter) + { + struct be_queue_info *q; +@@ -1635,22 +1664,19 @@ static int be_mcc_queues_create(struct be_adapter *adapter) + { + struct be_queue_info *q, *cq; + +- /* Alloc MCC compl queue */ + cq = &adapter->mcc_obj.cq; + if (be_queue_alloc(adapter, cq, MCC_CQ_LEN, + sizeof(struct be_mcc_compl))) + goto err; + +- /* Ask BE to create MCC compl queue; share TX's eq */ +- if (be_cmd_cq_create(adapter, cq, &adapter->tx_eq.q, false, true, 0)) ++ /* Use the default EQ for MCC completions */ ++ if (be_cmd_cq_create(adapter, cq, &mcc_eqo(adapter)->q, true, 0)) + goto mcc_cq_free; + +- /* Alloc MCC queue */ + q = &adapter->mcc_obj.q; + if (be_queue_alloc(adapter, q, MCC_Q_LEN, sizeof(struct be_mcc_wrb))) + goto mcc_cq_destroy; + +- /* Ask BE to create MCC queue */ + if (be_cmd_mccq_create(adapter, q, cq)) + goto mcc_q_free; + +@@ -1683,14 +1709,6 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) + be_cmd_q_destroy(adapter, q, QTYPE_CQ); + be_queue_free(adapter, q); + } +- +- /* Clear any residual events */ +- be_eq_clean(adapter, &adapter->tx_eq); +- +- q = &adapter->tx_eq.q; +- if (q->created) +- be_cmd_q_destroy(adapter, q, QTYPE_EQ); +- be_queue_free(adapter, q); + } + + static int be_num_txqs_want(struct be_adapter *adapter) +@@ -1703,10 +1721,10 @@ static int be_num_txqs_want(struct be_adapter *adapter) + return MAX_TX_QS; + } + +-/* One TX event queue is shared by all TX compl qs */ +-static int be_tx_queues_create(struct be_adapter *adapter) ++static int be_tx_cqs_create(struct be_adapter *adapter) + { +- struct be_queue_info *eq, *q, *cq; ++ struct be_queue_info *cq, *eq; ++ int status; + struct be_tx_obj *txo; + u8 i; + +@@ -1718,192 +1736,109 @@ static int be_tx_queues_create(struct be_adapter *adapter) + rtnl_unlock(); + } + +- adapter->tx_eq.max_eqd = 0; +- adapter->tx_eq.min_eqd = 0; +- adapter->tx_eq.cur_eqd = 96; +- adapter->tx_eq.enable_aic = false; ++ for_all_tx_queues(adapter, txo, i) { ++ cq = &txo->cq; ++ status = be_queue_alloc(adapter, cq, TX_CQ_LEN, ++ sizeof(struct be_eth_tx_compl)); ++ if (status) ++ return status; + +- eq = &adapter->tx_eq.q; +- if (be_queue_alloc(adapter, eq, EVNT_Q_LEN, +- sizeof(struct be_eq_entry))) +- return -1; ++ /* If num_evt_qs is less than num_tx_qs, then more than ++ * one txq share an eq ++ */ ++ eq = &adapter->eq_obj[i % adapter->num_evt_qs].q; ++ status = be_cmd_cq_create(adapter, cq, eq, false, 3); ++ if (status) ++ return status; ++ } ++ return 0; ++} + +- if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd)) +- goto err; +- adapter->tx_eq.eq_idx = adapter->eq_next_idx++; ++static int be_tx_qs_create(struct be_adapter *adapter) ++{ ++ struct be_tx_obj *txo; ++ int i, status; + + for_all_tx_queues(adapter, txo, i) { +- cq = &txo->cq; +- if (be_queue_alloc(adapter, cq, TX_CQ_LEN, +- sizeof(struct be_eth_tx_compl))) +- goto err; +- +- if (be_cmd_cq_create(adapter, cq, eq, false, false, 3)) +- goto err; ++ status = be_queue_alloc(adapter, &txo->q, TX_Q_LEN, ++ sizeof(struct be_eth_wrb)); ++ if (status) ++ return status; + +- q = &txo->q; +- if (be_queue_alloc(adapter, q, TX_Q_LEN, +- sizeof(struct be_eth_wrb))) +- goto err; ++ status = be_cmd_txq_create(adapter, &txo->q, &txo->cq); ++ if (status) ++ return status; + } +- return 0; + +-err: +- be_tx_queues_destroy(adapter); +- return -1; ++ return 0; + } + +-static void be_rx_queues_destroy(struct be_adapter *adapter) ++static void be_rx_cqs_destroy(struct be_adapter *adapter) + { + struct be_queue_info *q; + struct be_rx_obj *rxo; + int i; + + for_all_rx_queues(adapter, rxo, i) { +- be_queue_free(adapter, &rxo->q); +- + q = &rxo->cq; + if (q->created) + be_cmd_q_destroy(adapter, q, QTYPE_CQ); + be_queue_free(adapter, q); +- +- q = &rxo->rx_eq.q; +- if (q->created) +- be_cmd_q_destroy(adapter, q, QTYPE_EQ); +- be_queue_free(adapter, q); +- } +-} +- +-static u32 be_num_rxqs_want(struct be_adapter *adapter) +-{ +- if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && +- !sriov_enabled(adapter) && be_physfn(adapter)) { +- return 1 + MAX_RSS_QS; /* one default non-RSS queue */ +- } else { +- dev_warn(&adapter->pdev->dev, +- "No support for multiple RX queues\n"); +- return 1; + } + } + +-static int be_rx_queues_create(struct be_adapter *adapter) ++static int be_rx_cqs_create(struct be_adapter *adapter) + { +- struct be_queue_info *eq, *q, *cq; ++ struct be_queue_info *eq, *cq; + struct be_rx_obj *rxo; + int rc, i; + +- adapter->num_rx_qs = min(be_num_rxqs_want(adapter), +- msix_enabled(adapter) ? +- adapter->num_msix_vec - 1 : 1); +- if (adapter->num_rx_qs != MAX_RX_QS) +- dev_warn(&adapter->pdev->dev, +- "Can create only %d RX queues", adapter->num_rx_qs); ++ /* We'll create as many RSS rings as there are irqs. ++ * But when there's only one irq there's no use creating RSS rings ++ */ ++ adapter->num_rx_qs = (num_irqs(adapter) > 1) ? ++ num_irqs(adapter) + 1 : 1; + + adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; + for_all_rx_queues(adapter, rxo, i) { + rxo->adapter = adapter; +- rxo->rx_eq.max_eqd = BE_MAX_EQD; +- rxo->rx_eq.enable_aic = true; +- +- /* EQ */ +- eq = &rxo->rx_eq.q; +- rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN, +- sizeof(struct be_eq_entry)); +- if (rc) +- goto err; +- +- rc = be_cmd_eq_create(adapter, eq, rxo->rx_eq.cur_eqd); +- if (rc) +- goto err; +- +- rxo->rx_eq.eq_idx = adapter->eq_next_idx++; +- +- /* CQ */ + cq = &rxo->cq; + rc = be_queue_alloc(adapter, cq, RX_CQ_LEN, + sizeof(struct be_eth_rx_compl)); + if (rc) +- goto err; ++ return rc; + +- rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3); ++ eq = &adapter->eq_obj[i % adapter->num_evt_qs].q; ++ rc = be_cmd_cq_create(adapter, cq, eq, false, 3); + if (rc) +- goto err; +- +- /* Rx Q - will be created in be_open() */ +- q = &rxo->q; +- rc = be_queue_alloc(adapter, q, RX_Q_LEN, +- sizeof(struct be_eth_rx_d)); +- if (rc) +- goto err; +- ++ return rc; + } + +- return 0; +-err: +- be_rx_queues_destroy(adapter); +- return -1; +-} ++ if (adapter->num_rx_qs != MAX_RX_QS) ++ dev_info(&adapter->pdev->dev, ++ "Created only %d receive queues", adapter->num_rx_qs); + +-static bool event_peek(struct be_eq_obj *eq_obj) +-{ +- struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q); +- if (!eqe->evt) +- return false; +- else +- return true; ++ return 0; + } + + static irqreturn_t be_intx(int irq, void *dev) + { + struct be_adapter *adapter = dev; +- struct be_rx_obj *rxo; +- int isr, i, tx = 0 , rx = 0; +- +- if (lancer_chip(adapter)) { +- if (event_peek(&adapter->tx_eq)) +- tx = event_handle(adapter, &adapter->tx_eq, false); +- for_all_rx_queues(adapter, rxo, i) { +- if (event_peek(&rxo->rx_eq)) +- rx |= event_handle(adapter, &rxo->rx_eq, true); +- } +- +- if (!(tx || rx)) +- return IRQ_NONE; +- +- } else { +- isr = ioread32(adapter->csr + CEV_ISR0_OFFSET + +- (adapter->tx_eq.q.id / 8) * CEV_ISR_SIZE); +- if (!isr) +- return IRQ_NONE; +- +- if ((1 << adapter->tx_eq.eq_idx & isr)) +- event_handle(adapter, &adapter->tx_eq, false); +- +- for_all_rx_queues(adapter, rxo, i) { +- if ((1 << rxo->rx_eq.eq_idx & isr)) +- event_handle(adapter, &rxo->rx_eq, true); +- } +- } +- +- return IRQ_HANDLED; +-} +- +-static irqreturn_t be_msix_rx(int irq, void *dev) +-{ +- struct be_rx_obj *rxo = dev; +- struct be_adapter *adapter = rxo->adapter; ++ int num_evts; + +- event_handle(adapter, &rxo->rx_eq, true); +- +- return IRQ_HANDLED; ++ /* With INTx only one EQ is used */ ++ num_evts = event_handle(&adapter->eq_obj[0]); ++ if (num_evts) ++ return IRQ_HANDLED; ++ else ++ return IRQ_NONE; + } + +-static irqreturn_t be_msix_tx_mcc(int irq, void *dev) ++static irqreturn_t be_msix(int irq, void *dev) + { +- struct be_adapter *adapter = dev; +- +- event_handle(adapter, &adapter->tx_eq, false); ++ struct be_eq_obj *eqo = dev; + ++ event_handle(eqo); + return IRQ_HANDLED; + } + +@@ -1912,16 +1847,14 @@ static inline bool do_gro(struct be_rx_compl_info *rxcp) + return (rxcp->tcpf && !rxcp->err) ? true : false; + } + +-static int be_poll_rx(struct napi_struct *napi, int budget) ++static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi, ++ int budget) + { +- struct be_eq_obj *rx_eq = container_of(napi, struct be_eq_obj, napi); +- struct be_rx_obj *rxo = container_of(rx_eq, struct be_rx_obj, rx_eq); + struct be_adapter *adapter = rxo->adapter; + struct be_queue_info *rx_cq = &rxo->cq; + struct be_rx_compl_info *rxcp; + u32 work_done; + +- rx_stats(rxo)->rx_polls++; + for (work_done = 0; work_done < budget; work_done++) { + rxcp = be_rx_compl_get(rxo); + if (!rxcp) +@@ -1933,7 +1866,7 @@ static int be_poll_rx(struct napi_struct *napi, int budget) + + /* Discard compl with partial DMA Lancer B0 */ + if (unlikely(!rxcp->pkt_size)) { +- be_rx_compl_discard(adapter, rxo, rxcp); ++ be_rx_compl_discard(rxo, rxcp); + goto loop_continue; + } + +@@ -1942,94 +1875,96 @@ static int be_poll_rx(struct napi_struct *napi, int budget) + */ + if (unlikely(rxcp->port != adapter->port_num && + !lancer_chip(adapter))) { +- be_rx_compl_discard(adapter, rxo, rxcp); ++ be_rx_compl_discard(rxo, rxcp); + goto loop_continue; + } + + if (do_gro(rxcp)) +- be_rx_compl_process_gro(adapter, rxo, rxcp); ++ be_rx_compl_process_gro(rxo, napi, rxcp); + else +- be_rx_compl_process(adapter, rxo, rxcp); ++ be_rx_compl_process(rxo, rxcp); + loop_continue: + be_rx_stats_update(rxo, rxcp); + } + +- be_cq_notify(adapter, rx_cq->id, false, work_done); ++ if (work_done) { ++ be_cq_notify(adapter, rx_cq->id, true, work_done); + +- /* Refill the queue */ +- if (work_done && atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM) +- be_post_rx_frags(rxo, GFP_ATOMIC); +- +- /* All consumed */ +- if (work_done < budget) { +- napi_complete(napi); +- /* Arm CQ */ +- be_cq_notify(adapter, rx_cq->id, true, 0); ++ if (atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM) ++ be_post_rx_frags(rxo, GFP_ATOMIC); + } ++ + return work_done; + } + +-/* As TX and MCC share the same EQ check for both TX and MCC completions. +- * For TX/MCC we don't honour budget; consume everything +- */ +-static int be_poll_tx_mcc(struct napi_struct *napi, int budget) ++static bool be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo, ++ int budget, int idx) + { +- struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); +- struct be_adapter *adapter = +- container_of(tx_eq, struct be_adapter, tx_eq); +- struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; +- struct be_tx_obj *txo; + struct be_eth_tx_compl *txcp; +- int tx_compl, mcc_compl, status = 0; +- u8 i; +- u16 num_wrbs; ++ int num_wrbs = 0, work_done; + +- for_all_tx_queues(adapter, txo, i) { +- tx_compl = 0; +- num_wrbs = 0; +- while ((txcp = be_tx_compl_get(&txo->cq))) { +- num_wrbs += be_tx_compl_process(adapter, txo, ++ for (work_done = 0; work_done < budget; work_done++) { ++ txcp = be_tx_compl_get(&txo->cq); ++ if (!txcp) ++ break; ++ num_wrbs += be_tx_compl_process(adapter, txo, + AMAP_GET_BITS(struct amap_eth_tx_compl, + wrb_index, txcp)); +- tx_compl++; +- } +- if (tx_compl) { +- be_cq_notify(adapter, txo->cq.id, true, tx_compl); +- +- atomic_sub(num_wrbs, &txo->q.used); ++ } + +- /* As Tx wrbs have been freed up, wake up netdev queue +- * if it was stopped due to lack of tx wrbs. */ +- if (__netif_subqueue_stopped(adapter->netdev, i) && +- atomic_read(&txo->q.used) < txo->q.len / 2) { +- netif_wake_subqueue(adapter->netdev, i); +- } ++ if (work_done) { ++ be_cq_notify(adapter, txo->cq.id, true, work_done); ++ atomic_sub(num_wrbs, &txo->q.used); + +- u64_stats_update_begin(&tx_stats(txo)->sync_compl); +- tx_stats(txo)->tx_compl += tx_compl; +- u64_stats_update_end(&tx_stats(txo)->sync_compl); ++ /* As Tx wrbs have been freed up, wake up netdev queue ++ * if it was stopped due to lack of tx wrbs. */ ++ if (__netif_subqueue_stopped(adapter->netdev, idx) && ++ atomic_read(&txo->q.used) < txo->q.len / 2) { ++ netif_wake_subqueue(adapter->netdev, idx); + } ++ ++ u64_stats_update_begin(&tx_stats(txo)->sync_compl); ++ tx_stats(txo)->tx_compl += work_done; ++ u64_stats_update_end(&tx_stats(txo)->sync_compl); + } ++ return (work_done < budget); /* Done */ ++} + +- mcc_compl = be_process_mcc(adapter, &status); ++int be_poll(struct napi_struct *napi, int budget) ++{ ++ struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi); ++ struct be_adapter *adapter = eqo->adapter; ++ int max_work = 0, work, i; ++ bool tx_done; + +- if (mcc_compl) { +- be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl); ++ /* Process all TXQs serviced by this EQ */ ++ for (i = eqo->idx; i < adapter->num_tx_qs; i += adapter->num_evt_qs) { ++ tx_done = be_process_tx(adapter, &adapter->tx_obj[i], ++ eqo->tx_budget, i); ++ if (!tx_done) ++ max_work = budget; + } + +- napi_complete(napi); ++ /* This loop will iterate twice for EQ0 in which ++ * completions of the last RXQ (default one) are also processed ++ * For other EQs the loop iterates only once ++ */ ++ for (i = eqo->idx; i < adapter->num_rx_qs; i += adapter->num_evt_qs) { ++ work = be_process_rx(&adapter->rx_obj[i], napi, budget); ++ max_work = max(work, max_work); ++ } + +- /* Arm CQ again to regenerate EQEs for Lancer in INTx mode */ +- if (lancer_chip(adapter) && !msix_enabled(adapter)) { +- for_all_tx_queues(adapter, txo, i) +- be_cq_notify(adapter, txo->cq.id, true, 0); ++ if (is_mcc_eqo(eqo)) ++ be_process_mcc(adapter); + +- be_cq_notify(adapter, mcc_obj->cq.id, true, 0); ++ if (max_work < budget) { ++ napi_complete(napi); ++ be_eq_notify(adapter, eqo->q.id, true, false, 0); ++ } else { ++ /* As we'll continue in polling mode, count and clear events */ ++ be_eq_notify(adapter, eqo->q.id, false, false, events_get(eqo)); + } +- +- be_eq_notify(adapter, tx_eq->q.id, true, false, 0); +- adapter->drv_stats.tx_events++; +- return 1; ++ return max_work; + } + + void be_detect_dump_ue(struct be_adapter *adapter) +@@ -2104,12 +2039,24 @@ static void be_msix_disable(struct be_adapter *adapter) + } + } + ++static uint be_num_rss_want(struct be_adapter *adapter) ++{ ++ if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && ++ adapter->num_vfs == 0 && be_physfn(adapter) && ++ !be_is_mc(adapter)) ++ return (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; ++ else ++ return 0; ++} ++ + static void be_msix_enable(struct be_adapter *adapter) + { +-#define BE_MIN_MSIX_VECTORS (1 + 1) /* Rx + Tx */ ++#define BE_MIN_MSIX_VECTORS 1 + int i, status, num_vec; + +- num_vec = be_num_rxqs_want(adapter) + 1; ++ /* If RSS queues are not used, need a vec for default RX Q */ ++ num_vec = min(be_num_rss_want(adapter), num_online_cpus()); ++ num_vec = max(num_vec, BE_MIN_MSIX_VECTORS); + + for (i = 0; i < num_vec; i++) + adapter->msix_entries[i].entry = i; +@@ -2177,60 +2124,31 @@ static void be_sriov_disable(struct be_adapter *adapter) + } + + static inline int be_msix_vec_get(struct be_adapter *adapter, +- struct be_eq_obj *eq_obj) +-{ +- return adapter->msix_entries[eq_obj->eq_idx].vector; +-} +- +-static int be_request_irq(struct be_adapter *adapter, +- struct be_eq_obj *eq_obj, +- void *handler, char *desc, void *context) +-{ +- struct net_device *netdev = adapter->netdev; +- int vec; +- +- sprintf(eq_obj->desc, "%s-%s", netdev->name, desc); +- vec = be_msix_vec_get(adapter, eq_obj); +- return request_irq(vec, handler, 0, eq_obj->desc, context); +-} +- +-static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj, +- void *context) ++ struct be_eq_obj *eqo) + { +- int vec = be_msix_vec_get(adapter, eq_obj); +- free_irq(vec, context); ++ return adapter->msix_entries[eqo->idx].vector; + } + + static int be_msix_register(struct be_adapter *adapter) + { +- struct be_rx_obj *rxo; +- int status, i; +- char qname[10]; +- +- status = be_request_irq(adapter, &adapter->tx_eq, be_msix_tx_mcc, "tx", +- adapter); +- if (status) +- goto err; ++ struct net_device *netdev = adapter->netdev; ++ struct be_eq_obj *eqo; ++ int status, i, vec; + +- for_all_rx_queues(adapter, rxo, i) { +- sprintf(qname, "rxq%d", i); +- status = be_request_irq(adapter, &rxo->rx_eq, be_msix_rx, +- qname, rxo); ++ for_all_evt_queues(adapter, eqo, i) { ++ sprintf(eqo->desc, "%s-q%d", netdev->name, i); ++ vec = be_msix_vec_get(adapter, eqo); ++ status = request_irq(vec, be_msix, 0, eqo->desc, eqo); + if (status) + goto err_msix; + } + + return 0; +- + err_msix: +- be_free_irq(adapter, &adapter->tx_eq, adapter); +- +- for (i--, rxo = &adapter->rx_obj[i]; i >= 0; i--, rxo--) +- be_free_irq(adapter, &rxo->rx_eq, rxo); +- +-err: +- dev_warn(&adapter->pdev->dev, +- "MSIX Request IRQ failed - err %d\n", status); ++ for (i--, eqo = &adapter->eq_obj[i]; i >= 0; i--, eqo--) ++ free_irq(be_msix_vec_get(adapter, eqo), eqo); ++ dev_warn(&adapter->pdev->dev, "MSIX Request IRQ failed - err %d\n", ++ status); + be_msix_disable(adapter); + return status; + } +@@ -2266,7 +2184,7 @@ done: + static void be_irq_unregister(struct be_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; +- struct be_rx_obj *rxo; ++ struct be_eq_obj *eqo; + int i; + + if (!adapter->isr_registered) +@@ -2279,16 +2197,14 @@ static void be_irq_unregister(struct be_adapter *adapter) + } + + /* MSIx */ +- be_free_irq(adapter, &adapter->tx_eq, adapter); +- +- for_all_rx_queues(adapter, rxo, i) +- be_free_irq(adapter, &rxo->rx_eq, rxo); ++ for_all_evt_queues(adapter, eqo, i) ++ free_irq(be_msix_vec_get(adapter, eqo), eqo); + + done: + adapter->isr_registered = false; + } + +-static void be_rx_queues_clear(struct be_adapter *adapter) ++static void be_rx_qs_destroy(struct be_adapter *adapter) + { + struct be_queue_info *q; + struct be_rx_obj *rxo; +@@ -2303,53 +2219,33 @@ static void be_rx_queues_clear(struct be_adapter *adapter) + * arrive + */ + mdelay(1); +- be_rx_q_clean(adapter, rxo); ++ be_rx_cq_clean(rxo); + } +- +- /* Clear any residual events */ +- q = &rxo->rx_eq.q; +- if (q->created) +- be_eq_clean(adapter, &rxo->rx_eq); ++ be_queue_free(adapter, q); + } + } + + static int be_close(struct net_device *netdev) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_rx_obj *rxo; + struct be_tx_obj *txo; +- struct be_eq_obj *tx_eq = &adapter->tx_eq; +- int vec, i; ++ struct be_eq_obj *eqo; ++ int i; + + be_async_mcc_disable(adapter); + + if (!lancer_chip(adapter)) + be_intr_set(adapter, false); + +- for_all_rx_queues(adapter, rxo, i) +- napi_disable(&rxo->rx_eq.napi); +- +- napi_disable(&tx_eq->napi); +- +- if (lancer_chip(adapter)) { +- be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0); +- for_all_rx_queues(adapter, rxo, i) +- be_cq_notify(adapter, rxo->cq.id, false, 0); +- for_all_tx_queues(adapter, txo, i) +- be_cq_notify(adapter, txo->cq.id, false, 0); ++ for_all_evt_queues(adapter, eqo, i) { ++ napi_disable(&eqo->napi); ++ if (msix_enabled(adapter)) ++ synchronize_irq(be_msix_vec_get(adapter, eqo)); ++ else ++ synchronize_irq(netdev->irq); ++ be_eq_clean(eqo); + } + +- if (msix_enabled(adapter)) { +- vec = be_msix_vec_get(adapter, tx_eq); +- synchronize_irq(vec); +- +- for_all_rx_queues(adapter, rxo, i) { +- vec = be_msix_vec_get(adapter, &rxo->rx_eq); +- synchronize_irq(vec); +- } +- } else { +- synchronize_irq(netdev->irq); +- } + be_irq_unregister(adapter); + + /* Wait for all pending tx completions to arrive so that +@@ -2358,21 +2254,34 @@ static int be_close(struct net_device *netdev) + for_all_tx_queues(adapter, txo, i) + be_tx_compl_clean(adapter, txo); + +- be_rx_queues_clear(adapter); ++ be_rx_qs_destroy(adapter); + return 0; + } + +-static int be_rx_queues_setup(struct be_adapter *adapter) ++static int be_rx_qs_create(struct be_adapter *adapter) + { + struct be_rx_obj *rxo; + int rc, i, j; + u8 rsstable[128]; + + for_all_rx_queues(adapter, rxo, i) { ++ rc = be_queue_alloc(adapter, &rxo->q, RX_Q_LEN, ++ sizeof(struct be_eth_rx_d)); ++ if (rc) ++ return rc; ++ } ++ ++ /* The FW would like the default RXQ to be created first */ ++ rxo = default_rxo(adapter); ++ rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id, rx_frag_size, ++ adapter->if_handle, false, &rxo->rss_id); ++ if (rc) ++ return rc; ++ ++ for_all_rss_queues(adapter, rxo, i) { + rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id, +- rx_frag_size, BE_MAX_JUMBO_FRAME_SIZE, +- adapter->if_handle, +- (i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id); ++ rx_frag_size, adapter->if_handle, ++ true, &rxo->rss_id); + if (rc) + return rc; + } +@@ -2386,48 +2295,47 @@ static int be_rx_queues_setup(struct be_adapter *adapter) + } + } + rc = be_cmd_rss_config(adapter, rsstable, 128); +- + if (rc) + return rc; + } + + /* First time posting */ +- for_all_rx_queues(adapter, rxo, i) { ++ for_all_rx_queues(adapter, rxo, i) + be_post_rx_frags(rxo, GFP_KERNEL); +- napi_enable(&rxo->rx_eq.napi); +- } + return 0; + } + + static int be_open(struct net_device *netdev) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_eq_obj *tx_eq = &adapter->tx_eq; ++ struct be_eq_obj *eqo; + struct be_rx_obj *rxo; ++ struct be_tx_obj *txo; + u8 link_status; + int status, i; + +- status = be_rx_queues_setup(adapter); ++ status = be_rx_qs_create(adapter); + if (status) + goto err; + +- napi_enable(&tx_eq->napi); +- + be_irq_register(adapter); + + if (!lancer_chip(adapter)) + be_intr_set(adapter, true); + +- /* The evt queues are created in unarmed state; arm them */ +- for_all_rx_queues(adapter, rxo, i) { +- be_eq_notify(adapter, rxo->rx_eq.q.id, true, false, 0); ++ for_all_rx_queues(adapter, rxo, i) + be_cq_notify(adapter, rxo->cq.id, true, 0); +- } +- be_eq_notify(adapter, tx_eq->q.id, true, false, 0); + +- /* Now that interrupts are on we can process async mcc */ ++ for_all_tx_queues(adapter, txo, i) ++ be_cq_notify(adapter, txo->cq.id, true, 0); ++ + be_async_mcc_enable(adapter); + ++ for_all_evt_queues(adapter, eqo, i) { ++ napi_enable(&eqo->napi); ++ be_eq_notify(adapter, eqo->q.id, true, false, 0); ++ } ++ + status = be_cmd_link_status_query(adapter, NULL, NULL, + &link_status, 0); + if (!status) +@@ -2537,11 +2445,14 @@ static int be_clear(struct be_adapter *adapter) + be_cmd_if_destroy(adapter, adapter->if_handle, 0); + + be_mcc_queues_destroy(adapter); +- be_rx_queues_destroy(adapter); ++ be_rx_cqs_destroy(adapter); + be_tx_queues_destroy(adapter); ++ be_evt_queues_destroy(adapter); + + /* tell fw we're done with firing cmds */ + be_cmd_fw_clean(adapter); ++ ++ be_msix_disable(adapter); + return 0; + } + +@@ -2631,24 +2542,29 @@ static int be_setup(struct be_adapter *adapter) + struct net_device *netdev = adapter->netdev; + u32 cap_flags, en_flags; + u32 tx_fc, rx_fc; +- int status, i; ++ int status; + u8 mac[ETH_ALEN]; +- struct be_tx_obj *txo; + + be_setup_init(adapter); + + be_cmd_req_native_mode(adapter); + +- status = be_tx_queues_create(adapter); +- if (status != 0) ++ be_msix_enable(adapter); ++ ++ status = be_evt_queues_create(adapter); ++ if (status) + goto err; + +- status = be_rx_queues_create(adapter); +- if (status != 0) ++ status = be_tx_cqs_create(adapter); ++ if (status) ++ goto err; ++ ++ status = be_rx_cqs_create(adapter); ++ if (status) + goto err; + + status = be_mcc_queues_create(adapter); +- if (status != 0) ++ if (status) + goto err; + + memset(mac, 0, ETH_ALEN); +@@ -2674,12 +2590,6 @@ static int be_setup(struct be_adapter *adapter) + if (status != 0) + goto err; + +- for_all_tx_queues(adapter, txo, i) { +- status = be_cmd_txq_create(adapter, &txo->q, &txo->cq); +- if (status) +- goto err; +- } +- + /* The VF's permanent mac queried from card is incorrect. + * For BEx: Query the mac configued by the PF using if_handle + * For Lancer: Get and use mac_list to obtain mac address. +@@ -2697,6 +2607,10 @@ static int be_setup(struct be_adapter *adapter) + } + } + ++ status = be_tx_qs_create(adapter); ++ if (status) ++ goto err; ++ + be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL); + + status = be_vid_config(adapter, false, 0); +@@ -2736,12 +2650,13 @@ err: + static void be_netpoll(struct net_device *netdev) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_rx_obj *rxo; ++ struct be_eq_obj *eqo; + int i; + +- event_handle(adapter, &adapter->tx_eq, false); +- for_all_rx_queues(adapter, rxo, i) +- event_handle(adapter, &rxo->rx_eq, true); ++ for_all_evt_queues(adapter, eqo, i) ++ event_handle(eqo); ++ ++ return; + } + #endif + +@@ -3102,7 +3017,7 @@ static const struct net_device_ops be_netdev_ops = { + static void be_netdev_init(struct net_device *netdev) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_rx_obj *rxo; ++ struct be_eq_obj *eqo; + int i; + + netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | +@@ -3121,16 +3036,12 @@ static void be_netdev_init(struct net_device *netdev) + + netif_set_gso_max_size(netdev, 65535); + +- BE_SET_NETDEV_OPS(netdev, &be_netdev_ops); ++ netdev->netdev_ops = &be_netdev_ops; + + SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); + +- for_all_rx_queues(adapter, rxo, i) +- netif_napi_add(netdev, &rxo->rx_eq.napi, be_poll_rx, +- BE_NAPI_WEIGHT); +- +- netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc, +- BE_NAPI_WEIGHT); ++ for_all_evt_queues(adapter, eqo, i) ++ netif_napi_add(netdev, &eqo->napi, be_poll, BE_NAPI_WEIGHT); + } + + static void be_unmap_pci_bars(struct be_adapter *adapter) +@@ -3301,8 +3212,6 @@ static void __devexit be_remove(struct pci_dev *pdev) + + be_sriov_disable(adapter); + +- be_msix_disable(adapter); +- + pci_set_drvdata(pdev, NULL); + pci_release_regions(pdev); + pci_disable_device(pdev); +@@ -3469,6 +3378,7 @@ static void be_worker(struct work_struct *work) + struct be_adapter *adapter = + container_of(work, struct be_adapter, work.work); + struct be_rx_obj *rxo; ++ struct be_eq_obj *eqo; + int i; + + if (lancer_chip(adapter)) +@@ -3479,15 +3389,7 @@ static void be_worker(struct work_struct *work) + /* when interrupts are not yet enabled, just reap any pending + * mcc completions */ + if (!netif_running(adapter->netdev)) { +- int mcc_compl, status = 0; +- +- mcc_compl = be_process_mcc(adapter, &status); +- +- if (mcc_compl) { +- struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; +- be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl); +- } +- ++ be_process_mcc(adapter); + goto reschedule; + } + +@@ -3500,14 +3402,15 @@ static void be_worker(struct work_struct *work) + } + + for_all_rx_queues(adapter, rxo, i) { +- be_rx_eqd_update(adapter, rxo); +- + if (rxo->rx_post_starved) { + rxo->rx_post_starved = false; + be_post_rx_frags(rxo, GFP_KERNEL); + } + } + ++ for_all_evt_queues(adapter, eqo, i) ++ be_eqd_update(adapter, eqo); ++ + reschedule: + adapter->work_counter++; + schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); +@@ -3593,6 +3496,12 @@ static int __devinit be_probe(struct pci_dev *pdev, + if (status) + goto ctrl_clean; + ++ /* The INTR bit may be set in the card when probed by a kdump kernel ++ * after a crash. ++ */ ++ if (!lancer_chip(adapter)) ++ be_intr_set(adapter, false); ++ + status = be_stats_init(adapter); + if (status) + goto ctrl_clean; +@@ -3601,14 +3510,6 @@ static int __devinit be_probe(struct pci_dev *pdev, + if (status) + goto stats_clean; + +- /* The INTR bit may be set in the card when probed by a kdump kernel +- * after a crash. +- */ +- if (!lancer_chip(adapter)) +- be_intr_set(adapter, false); +- +- be_msix_enable(adapter); +- + INIT_DELAYED_WORK(&adapter->work, be_worker); + adapter->rx_fc = adapter->tx_fc = true; + +@@ -3621,7 +3522,8 @@ static int __devinit be_probe(struct pci_dev *pdev, + if (status != 0) + goto unsetup; + +- dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num); ++ dev_info(&pdev->dev, "%s: %s port %d\n", netdev->name, nic_name(pdev), ++ adapter->port_num); + + schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); + return 0; +@@ -3665,7 +3567,6 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) + } + be_clear(adapter); + +- be_msix_disable(adapter); + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); +@@ -3687,7 +3588,6 @@ static int be_resume(struct pci_dev *pdev) + pci_set_power_state(pdev, 0); + pci_restore_state(pdev); + +- be_msix_enable(adapter); + /* tell fw we're ready to fire cmds */ + status = be_cmd_fw_init(adapter); + if (status) +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0033-be2net-cancel-be_worker-during-EEH-recovery.patch b/debian/patches/features/all/be2net/0033-be2net-cancel-be_worker-during-EEH-recovery.patch new file mode 100644 index 000000000..a8ce85ea7 --- /dev/null +++ b/debian/patches/features/all/be2net/0033-be2net-cancel-be_worker-during-EEH-recovery.patch @@ -0,0 +1,90 @@ +From: Sathya Perla +Date: Thu, 23 Feb 2012 18:50:13 +0000 +Subject: [PATCH 33/58] be2net: cancel be_worker during EEH recovery + +commit 191eb7563164529bc7d6a693742fe5bed33cf004 upstream. + +EEH recovery involves ring cleanup and re-creation. The worker +thread must not run during EEH cleanup/resume. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 1 + + drivers/net/ethernet/emulex/benet/be_main.c | 13 ++++++++----- + 2 files changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index 86f51de..4b1994d 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -304,6 +304,7 @@ struct be_vf_cfg { + }; + + #define BE_FLAGS_LINK_STATUS_INIT 1 ++#define BE_FLAGS_WORKER_SCHEDULED (1 << 3) + + struct be_adapter { + struct pci_dev *pdev; +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 4a3a186..2c146ac 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -2439,6 +2439,11 @@ static void be_vf_clear(struct be_adapter *adapter) + + static int be_clear(struct be_adapter *adapter) + { ++ if (adapter->flags & BE_FLAGS_WORKER_SCHEDULED) { ++ cancel_delayed_work_sync(&adapter->work); ++ adapter->flags &= ~BE_FLAGS_WORKER_SCHEDULED; ++ } ++ + if (sriov_enabled(adapter)) + be_vf_clear(adapter); + +@@ -2640,6 +2645,9 @@ static int be_setup(struct be_adapter *adapter) + goto err; + } + ++ schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); ++ adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; ++ + return 0; + err: + be_clear(adapter); +@@ -3200,8 +3208,6 @@ static void __devexit be_remove(struct pci_dev *pdev) + if (!adapter) + return; + +- cancel_delayed_work_sync(&adapter->work); +- + unregister_netdev(adapter->netdev); + + be_clear(adapter); +@@ -3525,7 +3531,6 @@ static int __devinit be_probe(struct pci_dev *pdev, + dev_info(&pdev->dev, "%s: %s port %d\n", netdev->name, nic_name(pdev), + adapter->port_num); + +- schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); + return 0; + + unsetup: +@@ -3555,7 +3560,6 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + +- cancel_delayed_work_sync(&adapter->work); + if (adapter->wol) + be_setup_wol(adapter, true); + +@@ -3604,7 +3608,6 @@ static int be_resume(struct pci_dev *pdev) + if (adapter->wol) + be_setup_wol(adapter, false); + +- schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); + return 0; + } + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0034-be2net-fix-tx-completion-cleanup.patch b/debian/patches/features/all/be2net/0034-be2net-fix-tx-completion-cleanup.patch new file mode 100644 index 000000000..5e0575a8c --- /dev/null +++ b/debian/patches/features/all/be2net/0034-be2net-fix-tx-completion-cleanup.patch @@ -0,0 +1,133 @@ +From: Sathya Perla +Date: Thu, 23 Feb 2012 18:50:14 +0000 +Subject: [PATCH 34/58] be2net: fix tx completion cleanup + +commit 0ae57bb3df562e57ac89ad7bc524b6f2e83235f9 upstream. + +As a part of be_close(), instead of waiting for a max of 200ms for each TXQ, +wait for a total of 200ms for completions from all TXQs to arrive. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 75 +++++++++++++++------------ + 1 file changed, 42 insertions(+), 33 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 2c146ac..dce97dc 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1555,51 +1555,62 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo) + rxq->tail = rxq->head = 0; + } + +-static void be_tx_compl_clean(struct be_adapter *adapter, +- struct be_tx_obj *txo) ++static void be_tx_compl_clean(struct be_adapter *adapter) + { +- struct be_queue_info *tx_cq = &txo->cq; +- struct be_queue_info *txq = &txo->q; ++ struct be_tx_obj *txo; ++ struct be_queue_info *txq; + struct be_eth_tx_compl *txcp; + u16 end_idx, cmpl = 0, timeo = 0, num_wrbs = 0; +- struct sk_buff **sent_skbs = txo->sent_skb_list; + struct sk_buff *sent_skb; + bool dummy_wrb; ++ int i, pending_txqs; + + /* Wait for a max of 200ms for all the tx-completions to arrive. */ + do { +- while ((txcp = be_tx_compl_get(tx_cq))) { +- end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, +- wrb_index, txcp); +- num_wrbs += be_tx_compl_process(adapter, txo, end_idx); +- cmpl++; +- } +- if (cmpl) { +- be_cq_notify(adapter, tx_cq->id, false, cmpl); +- atomic_sub(num_wrbs, &txq->used); +- cmpl = 0; +- num_wrbs = 0; ++ pending_txqs = adapter->num_tx_qs; ++ ++ for_all_tx_queues(adapter, txo, i) { ++ txq = &txo->q; ++ while ((txcp = be_tx_compl_get(&txo->cq))) { ++ end_idx = ++ AMAP_GET_BITS(struct amap_eth_tx_compl, ++ wrb_index, txcp); ++ num_wrbs += be_tx_compl_process(adapter, txo, ++ end_idx); ++ cmpl++; ++ } ++ if (cmpl) { ++ be_cq_notify(adapter, txo->cq.id, false, cmpl); ++ atomic_sub(num_wrbs, &txq->used); ++ cmpl = 0; ++ num_wrbs = 0; ++ } ++ if (atomic_read(&txq->used) == 0) ++ pending_txqs--; + } + +- if (atomic_read(&txq->used) == 0 || ++timeo > 200) ++ if (pending_txqs == 0 || ++timeo > 200) + break; + + mdelay(1); + } while (true); + +- if (atomic_read(&txq->used)) +- dev_err(&adapter->pdev->dev, "%d pending tx-completions\n", +- atomic_read(&txq->used)); +- +- /* free posted tx for which compls will never arrive */ +- while (atomic_read(&txq->used)) { +- sent_skb = sent_skbs[txq->tail]; +- end_idx = txq->tail; +- index_adv(&end_idx, +- wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1, +- txq->len); +- num_wrbs = be_tx_compl_process(adapter, txo, end_idx); +- atomic_sub(num_wrbs, &txq->used); ++ for_all_tx_queues(adapter, txo, i) { ++ txq = &txo->q; ++ if (atomic_read(&txq->used)) ++ dev_err(&adapter->pdev->dev, "%d pending tx-compls\n", ++ atomic_read(&txq->used)); ++ ++ /* free posted tx for which compls will never arrive */ ++ while (atomic_read(&txq->used)) { ++ sent_skb = txo->sent_skb_list[txq->tail]; ++ end_idx = txq->tail; ++ num_wrbs = wrb_cnt_for_skb(adapter, sent_skb, ++ &dummy_wrb); ++ index_adv(&end_idx, num_wrbs - 1, txq->len); ++ num_wrbs = be_tx_compl_process(adapter, txo, end_idx); ++ atomic_sub(num_wrbs, &txq->used); ++ } + } + } + +@@ -2228,7 +2239,6 @@ static void be_rx_qs_destroy(struct be_adapter *adapter) + static int be_close(struct net_device *netdev) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_tx_obj *txo; + struct be_eq_obj *eqo; + int i; + +@@ -2251,8 +2261,7 @@ static int be_close(struct net_device *netdev) + /* Wait for all pending tx completions to arrive so that + * all tx skbs are freed. + */ +- for_all_tx_queues(adapter, txo, i) +- be_tx_compl_clean(adapter, txo); ++ be_tx_compl_clean(adapter); + + be_rx_qs_destroy(adapter); + return 0; +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0035-be2net-reset-queue-address-after-freeing.patch b/debian/patches/features/all/be2net/0035-be2net-reset-queue-address-after-freeing.patch new file mode 100644 index 000000000..4164b289c --- /dev/null +++ b/debian/patches/features/all/be2net/0035-be2net-reset-queue-address-after-freeing.patch @@ -0,0 +1,44 @@ +From: Sathya Perla +Date: Thu, 23 Feb 2012 18:50:15 +0000 +Subject: [PATCH 35/58] be2net: reset queue address after freeing + +commit 1cfafab965198bc0d9cb794af5065d0797969727 upstream. + +This will prevent double free in some cases where be_clear() is called +for cleanup when be_setup() fails half-way. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index dce97dc..c1b9cdf 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -127,9 +127,11 @@ static inline bool be_is_mc(struct be_adapter *adapter) { + static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q) + { + struct be_dma_mem *mem = &q->dma_mem; +- if (mem->va) ++ if (mem->va) { + dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va, + mem->dma); ++ mem->va = NULL; ++ } + } + + static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q, +@@ -1652,7 +1654,7 @@ static int be_evt_queues_create(struct be_adapter *adapter) + if (rc) + return rc; + } +- return rc; ++ return 0; + } + + static void be_mcc_queues_destroy(struct be_adapter *adapter) +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0036-be2net-enable-RSS-for-ipv6-pkts.patch b/debian/patches/features/all/be2net/0036-be2net-enable-RSS-for-ipv6-pkts.patch new file mode 100644 index 000000000..0d03b030f --- /dev/null +++ b/debian/patches/features/all/be2net/0036-be2net-enable-RSS-for-ipv6-pkts.patch @@ -0,0 +1,29 @@ +From: Sathya Perla +Date: Thu, 23 Feb 2012 18:50:16 +0000 +Subject: [PATCH 36/58] be2net: enable RSS for ipv6 pkts + +commit 1ca7ba921e8af04266881bc485be08d4fac5f1bc upstream. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 6432efa..398fb5c 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -1694,7 +1694,8 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size) + OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL); + + req->if_id = cpu_to_le32(adapter->if_handle); +- req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4); ++ req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4 | ++ RSS_ENABLE_TCP_IPV6 | RSS_ENABLE_IPV6); + req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1); + memcpy(req->cpu_table, rsstable, table_size); + memcpy(req->hash, myhash, sizeof(myhash)); +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0037-be2net-update-driver-version.patch b/debian/patches/features/all/be2net/0037-be2net-update-driver-version.patch new file mode 100644 index 000000000..5e0e822de --- /dev/null +++ b/debian/patches/features/all/be2net/0037-be2net-update-driver-version.patch @@ -0,0 +1,28 @@ +From: Sathya Perla +Date: Thu, 23 Feb 2012 18:50:17 +0000 +Subject: [PATCH 37/58] be2net: update driver version + +commit d708f6039b21ca8f0508ba1da1aaf3d00a36446f upstream. + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index 4b1994d..c357172 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -33,7 +33,7 @@ + + #include "be_hw.h" + +-#define DRV_VER "4.0.100u" ++#define DRV_VER "4.2.116u" + #define DRV_NAME "be2net" + #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" + #define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0038-be2net-Remove-unused-OFFSET_IN_PAGE-macro.patch b/debian/patches/features/all/be2net/0038-be2net-Remove-unused-OFFSET_IN_PAGE-macro.patch new file mode 100644 index 000000000..7c696874a --- /dev/null +++ b/debian/patches/features/all/be2net/0038-be2net-Remove-unused-OFFSET_IN_PAGE-macro.patch @@ -0,0 +1,30 @@ +From: Roland Dreier +Date: Wed, 29 Feb 2012 20:40:46 +0000 +Subject: [PATCH 38/58] be2net: Remove unused OFFSET_IN_PAGE() macro + +commit 97767a87f3be8834192dc3fc9412aaccf708d87f upstream. + +Signed-off-by: Roland Dreier +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index c357172..ab24e46 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -442,10 +442,6 @@ extern const struct ethtool_ops be_ethtool_ops; + ((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \ + (size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K)) + +-/* Byte offset into the page corresponding to given address */ +-#define OFFSET_IN_PAGE(addr) \ +- ((size_t)(addr) & (PAGE_SIZE_4K-1)) +- + /* Returns bit offset within a DWORD of a bitfield */ + #define AMAP_BIT_OFFSET(_struct, field) \ + (((size_t)&(((_struct *)0)->field))%32) +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0039-be2net-enable-WOL-by-default-if-h-w-supports-it.patch b/debian/patches/features/all/be2net/0039-be2net-enable-WOL-by-default-if-h-w-supports-it.patch new file mode 100644 index 000000000..eda742bc2 --- /dev/null +++ b/debian/patches/features/all/be2net/0039-be2net-enable-WOL-by-default-if-h-w-supports-it.patch @@ -0,0 +1,274 @@ +From: Ajit Khaparde +Date: Sun, 18 Mar 2012 06:23:11 +0000 +Subject: [PATCH 39/58] be2net: enable WOL by default if h/w supports it + +commit 4762f6cec4455f3bbe4ca82c100fe5d85d3c02a2 upstream. + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 26 ++++++++++- + drivers/net/ethernet/emulex/benet/be_cmds.c | 55 ++++++++++++++++++++++++ + drivers/net/ethernet/emulex/benet/be_cmds.h | 28 ++++++++++++ + drivers/net/ethernet/emulex/benet/be_ethtool.c | 27 +++++------- + drivers/net/ethernet/emulex/benet/be_main.c | 17 ++++++++ + 5 files changed, 136 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index ab24e46..cabe1b8 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -52,6 +52,10 @@ + #define OC_DEVICE_ID3 0xe220 /* Device id for Lancer cards */ + #define OC_DEVICE_ID4 0xe228 /* Device id for VF in Lancer */ + #define OC_DEVICE_ID5 0x720 /* Device Id for Skyhawk cards */ ++#define OC_SUBSYS_DEVICE_ID1 0xE602 ++#define OC_SUBSYS_DEVICE_ID2 0xE642 ++#define OC_SUBSYS_DEVICE_ID3 0xE612 ++#define OC_SUBSYS_DEVICE_ID4 0xE652 + + static inline char *nic_name(struct pci_dev *pdev) + { +@@ -365,7 +369,6 @@ struct be_adapter { + bool fw_timeout; + u32 port_num; + bool promiscuous; +- bool wol; + u32 function_mode; + u32 function_caps; + u32 rx_fc; /* Rx flow control */ +@@ -386,6 +389,8 @@ struct be_adapter { + u32 sli_family; + u8 hba_port_num; + u16 pvid; ++ u8 wol_cap; ++ bool wol; + }; + + #define be_physfn(adapter) (!adapter->is_virtfn) +@@ -549,9 +554,28 @@ static inline bool be_error(struct be_adapter *adapter) + return adapter->eeh_err || adapter->ue_detected || adapter->fw_timeout; + } + ++static inline bool be_is_wol_excluded(struct be_adapter *adapter) ++{ ++ struct pci_dev *pdev = adapter->pdev; ++ ++ if (!be_physfn(adapter)) ++ return true; ++ ++ switch (pdev->subsystem_device) { ++ case OC_SUBSYS_DEVICE_ID1: ++ case OC_SUBSYS_DEVICE_ID2: ++ case OC_SUBSYS_DEVICE_ID3: ++ case OC_SUBSYS_DEVICE_ID4: ++ return true; ++ default: ++ return false; ++ } ++} ++ + extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, + u16 num_popped); + extern void be_link_status_update(struct be_adapter *adapter, u8 link_status); + extern void be_parse_stats(struct be_adapter *adapter); + extern int be_load_fw(struct be_adapter *adapter, u8 *func); ++extern bool be_is_wol_supported(struct be_adapter *adapter); + #endif /* BE_H */ +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 398fb5c..d72c2b4 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -2418,3 +2418,58 @@ err: + spin_unlock_bh(&adapter->mcc_lock); + return status; + } ++ ++int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter) ++{ ++ struct be_mcc_wrb *wrb; ++ struct be_cmd_req_acpi_wol_magic_config_v1 *req; ++ int status; ++ int payload_len = sizeof(*req); ++ struct be_dma_mem cmd; ++ ++ memset(&cmd, 0, sizeof(struct be_dma_mem)); ++ cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1); ++ cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, ++ &cmd.dma); ++ if (!cmd.va) { ++ dev_err(&adapter->pdev->dev, ++ "Memory allocation failure\n"); ++ return -ENOMEM; ++ } ++ ++ if (mutex_lock_interruptible(&adapter->mbox_lock)) ++ return -1; ++ ++ wrb = wrb_from_mbox(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto err; ++ } ++ ++ req = cmd.va; ++ ++ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, ++ OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, ++ payload_len, wrb, &cmd); ++ ++ req->hdr.version = 1; ++ req->query_options = BE_GET_WOL_CAP; ++ ++ status = be_mbox_notify_wait(adapter); ++ if (!status) { ++ struct be_cmd_resp_acpi_wol_magic_config_v1 *resp; ++ resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *) cmd.va; ++ ++ /* the command could succeed misleadingly on old f/w ++ * which is not aware of the V1 version. fake an error. */ ++ if (resp->hdr.response_length < payload_len) { ++ status = -1; ++ goto err; ++ } ++ adapter->wol_cap = resp->wol_settings; ++ } ++err: ++ mutex_unlock(&adapter->mbox_lock); ++ pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); ++ return status; ++} +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h +index 687c420..345d49e 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.h ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.h +@@ -1206,6 +1206,33 @@ struct be_cmd_req_acpi_wol_magic_config{ + u8 rsvd2[2]; + } __packed; + ++struct be_cmd_req_acpi_wol_magic_config_v1 { ++ struct be_cmd_req_hdr hdr; ++ u8 rsvd0[2]; ++ u8 query_options; ++ u8 rsvd1[5]; ++ u32 rsvd2[288]; ++ u8 magic_mac[6]; ++ u8 rsvd3[22]; ++} __packed; ++ ++struct be_cmd_resp_acpi_wol_magic_config_v1 { ++ struct be_cmd_resp_hdr hdr; ++ u8 rsvd0[2]; ++ u8 wol_settings; ++ u8 rsvd1[5]; ++ u32 rsvd2[295]; ++} __packed; ++ ++#define BE_GET_WOL_CAP 2 ++ ++#define BE_WOL_CAP 0x1 ++#define BE_PME_D0_CAP 0x8 ++#define BE_PME_D1_CAP 0x10 ++#define BE_PME_D2_CAP 0x20 ++#define BE_PME_D3HOT_CAP 0x40 ++#define BE_PME_D3COLD_CAP 0x80 ++ + /********************** LoopBack test *********************/ + struct be_cmd_req_loopback_test { + struct be_cmd_req_hdr hdr; +@@ -1590,4 +1617,5 @@ extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain, + bool *pmac_id_active, u32 *pmac_id, u8 *mac); + extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, + u8 mac_count, u32 domain); ++extern int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter); + +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index d98ad7e..e0eb995 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -600,26 +600,16 @@ be_set_phys_id(struct net_device *netdev, + return 0; + } + +-static bool +-be_is_wol_supported(struct be_adapter *adapter) +-{ +- if (!be_physfn(adapter)) +- return false; +- else +- return true; +-} + + static void + be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) + { + struct be_adapter *adapter = netdev_priv(netdev); + +- if (be_is_wol_supported(adapter)) +- wol->supported = WAKE_MAGIC; +- +- if (adapter->wol) +- wol->wolopts = WAKE_MAGIC; +- else ++ if (be_is_wol_supported(adapter)) { ++ wol->supported |= WAKE_MAGIC; ++ wol->wolopts |= WAKE_MAGIC; ++ } else + wol->wolopts = 0; + memset(&wol->sopass, 0, sizeof(wol->sopass)); + } +@@ -630,9 +620,14 @@ be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) + struct be_adapter *adapter = netdev_priv(netdev); + + if (wol->wolopts & ~WAKE_MAGIC) +- return -EINVAL; ++ return -EOPNOTSUPP; ++ ++ if (!be_is_wol_supported(adapter)) { ++ dev_warn(&adapter->pdev->dev, "WOL not supported\n"); ++ return -EOPNOTSUPP; ++ } + +- if ((wol->wolopts & WAKE_MAGIC) && be_is_wol_supported(adapter)) ++ if (wol->wolopts & WAKE_MAGIC) + adapter->wol = true; + else + adapter->wol = false; +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index c1b9cdf..70b138f 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -3236,6 +3236,12 @@ static void __devexit be_remove(struct pci_dev *pdev) + free_netdev(adapter->netdev); + } + ++bool be_is_wol_supported(struct be_adapter *adapter) ++{ ++ return ((adapter->wol_cap & BE_WOL_CAP) && ++ !be_is_wol_excluded(adapter)) ? true : false; ++} ++ + static int be_get_config(struct be_adapter *adapter) + { + int status; +@@ -3254,6 +3260,17 @@ static int be_get_config(struct be_adapter *adapter) + if (status) + return status; + ++ status = be_cmd_get_acpi_wol_cap(adapter); ++ if (status) { ++ /* in case of a failure to get wol capabillities ++ * check the exclusion list to determine WOL capability */ ++ if (!be_is_wol_excluded(adapter)) ++ adapter->wol_cap |= BE_WOL_CAP; ++ } ++ ++ if (be_is_wol_supported(adapter)) ++ adapter->wol = true; ++ + return 0; + } + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0040-be2net-Program-secondary-UC-MAC-address-into-MAC-fil.patch b/debian/patches/features/all/be2net/0040-be2net-Program-secondary-UC-MAC-address-into-MAC-fil.patch new file mode 100644 index 000000000..935bc3e45 --- /dev/null +++ b/debian/patches/features/all/be2net/0040-be2net-Program-secondary-UC-MAC-address-into-MAC-fil.patch @@ -0,0 +1,177 @@ +From: Ajit Khaparde +Date: Sun, 18 Mar 2012 06:23:21 +0000 +Subject: [PATCH 40/58] be2net: Program secondary UC MAC address into MAC + filter + +commit fbc13f018c0043146f8eccc7d6a6c0e66339e2d5 upstream. + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 6 ++- + drivers/net/ethernet/emulex/benet/be_main.c | 53 ++++++++++++++++++++++++--- + 2 files changed, 53 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index cabe1b8..03fc3db 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -309,6 +309,8 @@ struct be_vf_cfg { + + #define BE_FLAGS_LINK_STATUS_INIT 1 + #define BE_FLAGS_WORKER_SCHEDULED (1 << 3) ++#define BE_UC_PMAC_COUNT 30 ++#define BE_VF_UC_PMAC_COUNT 2 + + struct be_adapter { + struct pci_dev *pdev; +@@ -361,7 +363,7 @@ struct be_adapter { + /* Ethtool knobs and info */ + char fw_ver[FW_VER_LEN]; + int if_handle; /* Used to configure filtering */ +- u32 pmac_id; /* MAC addr handle used by BE card */ ++ u32 *pmac_id; /* MAC addr handle used by BE card */ + u32 beacon_state; /* for set_phys_id */ + + bool eeh_err; +@@ -391,6 +393,8 @@ struct be_adapter { + u16 pvid; + u8 wol_cap; + bool wol; ++ u32 max_pmac_cnt; /* Max secondary UC MACs programmable */ ++ u32 uc_macs; /* Count of secondary UC MAC programmed */ + }; + + #define be_physfn(adapter) (!adapter->is_virtfn) +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 70b138f..b8b34f5 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -235,7 +235,7 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) + struct sockaddr *addr = p; + int status = 0; + u8 current_mac[ETH_ALEN]; +- u32 pmac_id = adapter->pmac_id; ++ u32 pmac_id = adapter->pmac_id[0]; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; +@@ -248,7 +248,7 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) + + if (memcmp(addr->sa_data, current_mac, ETH_ALEN)) { + status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data, +- adapter->if_handle, &adapter->pmac_id, 0); ++ adapter->if_handle, &adapter->pmac_id[0], 0); + if (status) + goto err; + +@@ -877,6 +877,29 @@ static void be_set_rx_mode(struct net_device *netdev) + goto done; + } + ++ if (netdev_uc_count(netdev) != adapter->uc_macs) { ++ struct netdev_hw_addr *ha; ++ int i = 1; /* First slot is claimed by the Primary MAC */ ++ ++ for (; adapter->uc_macs > 0; adapter->uc_macs--, i++) { ++ be_cmd_pmac_del(adapter, adapter->if_handle, ++ adapter->pmac_id[i], 0); ++ } ++ ++ if (netdev_uc_count(netdev) > adapter->max_pmac_cnt) { ++ be_cmd_rx_filter(adapter, IFF_PROMISC, ON); ++ adapter->promiscuous = true; ++ goto done; ++ } ++ ++ netdev_for_each_uc_addr(ha, adapter->netdev) { ++ adapter->uc_macs++; /* First slot is for Primary MAC */ ++ be_cmd_pmac_add(adapter, (u8 *)ha->addr, ++ adapter->if_handle, ++ &adapter->pmac_id[adapter->uc_macs], 0); ++ } ++ } ++ + be_cmd_rx_filter(adapter, IFF_MULTICAST, ON); + done: + return; +@@ -2450,6 +2473,8 @@ static void be_vf_clear(struct be_adapter *adapter) + + static int be_clear(struct be_adapter *adapter) + { ++ int i = 1; ++ + if (adapter->flags & BE_FLAGS_WORKER_SCHEDULED) { + cancel_delayed_work_sync(&adapter->work); + adapter->flags &= ~BE_FLAGS_WORKER_SCHEDULED; +@@ -2458,6 +2483,10 @@ static int be_clear(struct be_adapter *adapter) + if (sriov_enabled(adapter)) + be_vf_clear(adapter); + ++ for (; adapter->uc_macs > 0; adapter->uc_macs--, i++) ++ be_cmd_pmac_del(adapter, adapter->if_handle, ++ adapter->pmac_id[i], 0); ++ + be_cmd_if_destroy(adapter, adapter->if_handle, 0); + + be_mcc_queues_destroy(adapter); +@@ -2469,6 +2498,7 @@ static int be_clear(struct be_adapter *adapter) + be_cmd_fw_clean(adapter); + + be_msix_disable(adapter); ++ kfree(adapter->pmac_id); + return 0; + } + +@@ -2544,10 +2574,10 @@ static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac) + false, adapter->if_handle, pmac_id); + + if (!status) +- adapter->pmac_id = pmac_id; ++ adapter->pmac_id[0] = pmac_id; + } else { + status = be_cmd_pmac_add(adapter, mac, +- adapter->if_handle, &adapter->pmac_id, 0); ++ adapter->if_handle, &adapter->pmac_id[0], 0); + } + do_none: + return status; +@@ -2602,7 +2632,7 @@ static int be_setup(struct be_adapter *adapter) + } + status = be_cmd_if_create(adapter, cap_flags, en_flags, + netdev->dev_addr, &adapter->if_handle, +- &adapter->pmac_id, 0); ++ &adapter->pmac_id[0], 0); + if (status != 0) + goto err; + +@@ -3051,6 +3081,8 @@ static void be_netdev_init(struct net_device *netdev) + netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + ++ netdev->priv_flags |= IFF_UNICAST_FLT; ++ + netdev->flags |= IFF_MULTICAST; + + netif_set_gso_max_size(netdev, 65535); +@@ -3256,6 +3288,17 @@ static int be_get_config(struct be_adapter *adapter) + else + adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; + ++ if (be_physfn(adapter)) ++ adapter->max_pmac_cnt = BE_UC_PMAC_COUNT; ++ else ++ adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT; ++ ++ /* primary mac needs 1 pmac entry */ ++ adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1, ++ sizeof(u32), GFP_KERNEL); ++ if (!adapter->pmac_id) ++ return -ENOMEM; ++ + status = be_cmd_get_cntl_attributes(adapter); + if (status) + return status; +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0041-be2net-Fix-number-of-vlan-slots-in-flex-mode.patch b/debian/patches/features/all/be2net/0041-be2net-Fix-number-of-vlan-slots-in-flex-mode.patch new file mode 100644 index 000000000..f95dc38ac --- /dev/null +++ b/debian/patches/features/all/be2net/0041-be2net-Fix-number-of-vlan-slots-in-flex-mode.patch @@ -0,0 +1,30 @@ +From: Ajit Khaparde +Date: Sun, 18 Mar 2012 06:23:31 +0000 +Subject: [PATCH 41/58] be2net: Fix number of vlan slots in flex mode + +commit 456d9c962bb5824423fa93277c8f7f5b2e3d5e1c upstream. + +In flex10 mode the number of vlan slots supported is halved. + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index b8b34f5..c9a9bf0 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -3284,7 +3284,7 @@ static int be_get_config(struct be_adapter *adapter) + return status; + + if (adapter->function_mode & FLEX10_MODE) +- adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/4; ++ adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8; + else + adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0042-be2net-fix-programming-of-VLAN-tags-for-VF.patch b/debian/patches/features/all/be2net/0042-be2net-fix-programming-of-VLAN-tags-for-VF.patch new file mode 100644 index 000000000..c8e86963b --- /dev/null +++ b/debian/patches/features/all/be2net/0042-be2net-fix-programming-of-VLAN-tags-for-VF.patch @@ -0,0 +1,255 @@ +From: Ajit Khaparde +Date: Sun, 18 Mar 2012 06:23:41 +0000 +Subject: [PATCH 42/58] be2net: fix programming of VLAN tags for VF + +commit f1f3ee1bcc996e21f122442fd8c34de51622c76a upstream. + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 1 + + drivers/net/ethernet/emulex/benet/be_cmds.c | 83 +++++++++++++++++++++++++++ + drivers/net/ethernet/emulex/benet/be_cmds.h | 55 ++++++++++++++++++ + drivers/net/ethernet/emulex/benet/be_main.c | 23 ++++++-- + 4 files changed, 157 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index 03fc3db..9576ac0 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -303,6 +303,7 @@ struct be_vf_cfg { + unsigned char mac_addr[ETH_ALEN]; + int if_handle; + int pmac_id; ++ u16 def_vid; + u16 vlan_tag; + u32 tx_rate; + }; +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index d72c2b4..67b030d 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -2419,6 +2419,89 @@ err: + return status; + } + ++int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, ++ u32 domain, u16 intf_id) ++{ ++ struct be_mcc_wrb *wrb; ++ struct be_cmd_req_set_hsw_config *req; ++ void *ctxt; ++ int status; ++ ++ spin_lock_bh(&adapter->mcc_lock); ++ ++ wrb = wrb_from_mccq(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto err; ++ } ++ ++ req = embedded_payload(wrb); ++ ctxt = &req->context; ++ ++ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, ++ OPCODE_COMMON_SET_HSW_CONFIG, sizeof(*req), wrb, NULL); ++ ++ req->hdr.domain = domain; ++ AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, ctxt, intf_id); ++ if (pvid) { ++ AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1); ++ AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid); ++ } ++ ++ be_dws_cpu_to_le(req->context, sizeof(req->context)); ++ status = be_mcc_notify_wait(adapter); ++ ++err: ++ spin_unlock_bh(&adapter->mcc_lock); ++ return status; ++} ++ ++/* Get Hyper switch config */ ++int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, ++ u32 domain, u16 intf_id) ++{ ++ struct be_mcc_wrb *wrb; ++ struct be_cmd_req_get_hsw_config *req; ++ void *ctxt; ++ int status; ++ u16 vid; ++ ++ spin_lock_bh(&adapter->mcc_lock); ++ ++ wrb = wrb_from_mccq(adapter); ++ if (!wrb) { ++ status = -EBUSY; ++ goto err; ++ } ++ ++ req = embedded_payload(wrb); ++ ctxt = &req->context; ++ ++ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, ++ OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb, NULL); ++ ++ req->hdr.domain = domain; ++ AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id, ctxt, ++ intf_id); ++ AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1); ++ be_dws_cpu_to_le(req->context, sizeof(req->context)); ++ ++ status = be_mcc_notify_wait(adapter); ++ if (!status) { ++ struct be_cmd_resp_get_hsw_config *resp = ++ embedded_payload(wrb); ++ be_dws_le_to_cpu(&resp->context, ++ sizeof(resp->context)); ++ vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context, ++ pvid, &resp->context); ++ *pvid = le16_to_cpu(vid); ++ } ++ ++err: ++ spin_unlock_bh(&adapter->mcc_lock); ++ return status; ++} ++ + int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter) + { + struct be_mcc_wrb *wrb; +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h +index 345d49e..d5b680c 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.h ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.h +@@ -191,6 +191,8 @@ struct be_mcc_mailbox { + #define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121 + #define OPCODE_COMMON_GET_MAC_LIST 147 + #define OPCODE_COMMON_SET_MAC_LIST 148 ++#define OPCODE_COMMON_GET_HSW_CONFIG 152 ++#define OPCODE_COMMON_SET_HSW_CONFIG 153 + #define OPCODE_COMMON_READ_OBJECT 171 + #define OPCODE_COMMON_WRITE_OBJECT 172 + +@@ -1413,6 +1415,55 @@ struct be_cmd_req_set_mac_list { + struct macaddr mac[BE_MAX_MAC]; + } __packed; + ++/*********************** HSW Config ***********************/ ++struct amap_set_hsw_context { ++ u8 interface_id[16]; ++ u8 rsvd0[14]; ++ u8 pvid_valid; ++ u8 rsvd1; ++ u8 rsvd2[16]; ++ u8 pvid[16]; ++ u8 rsvd3[32]; ++ u8 rsvd4[32]; ++ u8 rsvd5[32]; ++} __packed; ++ ++struct be_cmd_req_set_hsw_config { ++ struct be_cmd_req_hdr hdr; ++ u8 context[sizeof(struct amap_set_hsw_context) / 8]; ++} __packed; ++ ++struct be_cmd_resp_set_hsw_config { ++ struct be_cmd_resp_hdr hdr; ++ u32 rsvd; ++}; ++ ++struct amap_get_hsw_req_context { ++ u8 interface_id[16]; ++ u8 rsvd0[14]; ++ u8 pvid_valid; ++ u8 pport; ++} __packed; ++ ++struct amap_get_hsw_resp_context { ++ u8 rsvd1[16]; ++ u8 pvid[16]; ++ u8 rsvd2[32]; ++ u8 rsvd3[32]; ++ u8 rsvd4[32]; ++} __packed; ++ ++struct be_cmd_req_get_hsw_config { ++ struct be_cmd_req_hdr hdr; ++ u8 context[sizeof(struct amap_get_hsw_req_context) / 8]; ++} __packed; ++ ++struct be_cmd_resp_get_hsw_config { ++ struct be_cmd_resp_hdr hdr; ++ u8 context[sizeof(struct amap_get_hsw_resp_context) / 8]; ++ u32 rsvd; ++}; ++ + /*************** HW Stats Get v1 **********************************/ + #define BE_TXP_SW_SZ 48 + struct be_port_rxf_stats_v1 { +@@ -1617,5 +1668,9 @@ extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain, + bool *pmac_id_active, u32 *pmac_id, u8 *mac); + extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, + u8 mac_count, u32 domain); ++extern int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, ++ u32 domain, u16 intf_id); ++extern int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, ++ u32 domain, u16 intf_id); + extern int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter); + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index c9a9bf0..2e54335 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -970,14 +970,21 @@ static int be_set_vf_vlan(struct net_device *netdev, + return -EINVAL; + + if (vlan) { +- adapter->vf_cfg[vf].vlan_tag = vlan; +- adapter->vlans_added++; ++ if (adapter->vf_cfg[vf].vlan_tag != vlan) { ++ /* If this is new value, program it. Else skip. */ ++ adapter->vf_cfg[vf].vlan_tag = vlan; ++ ++ status = be_cmd_set_hsw_config(adapter, vlan, ++ vf + 1, adapter->vf_cfg[vf].if_handle); ++ } + } else { ++ /* Reset Transparent Vlan Tagging. */ + adapter->vf_cfg[vf].vlan_tag = 0; +- adapter->vlans_added--; ++ vlan = adapter->vf_cfg[vf].def_vid; ++ status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, ++ adapter->vf_cfg[vf].if_handle); + } + +- status = be_vid_config(adapter, true, vf); + + if (status) + dev_info(&adapter->pdev->dev, +@@ -2517,7 +2524,7 @@ static int be_vf_setup(struct be_adapter *adapter) + { + struct be_vf_cfg *vf_cfg; + u32 cap_flags, en_flags, vf; +- u16 lnk_speed; ++ u16 def_vlan, lnk_speed; + int status; + + be_vf_setup_init(adapter); +@@ -2541,6 +2548,12 @@ static int be_vf_setup(struct be_adapter *adapter) + if (status) + goto err; + vf_cfg->tx_rate = lnk_speed * 10; ++ ++ status = be_cmd_get_hsw_config(adapter, &def_vlan, ++ vf + 1, vf_cfg->if_handle); ++ if (status) ++ goto err; ++ vf_cfg->def_vid = def_vlan; + } + return 0; + err: +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0043-be2net-fix-ethtool-get-settings.patch b/debian/patches/features/all/be2net/0043-be2net-fix-ethtool-get-settings.patch new file mode 100644 index 000000000..96364e7d4 --- /dev/null +++ b/debian/patches/features/all/be2net/0043-be2net-fix-ethtool-get-settings.patch @@ -0,0 +1,521 @@ +From: Ajit Khaparde +Date: Sat, 21 Apr 2012 18:53:22 +0000 +Subject: [PATCH 43/58] be2net: fix ethtool get settings + +commit 42f11cf20cc5b76766fd1f0e591eda26283a38ec upstream. + +ethtool get settings was not displaying all the settings correctly. +use the get_phy_info to get more information about the PHY to fix this. + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 23 ++- + drivers/net/ethernet/emulex/benet/be_cmds.c | 17 +- + drivers/net/ethernet/emulex/benet/be_cmds.h | 36 +++- + drivers/net/ethernet/emulex/benet/be_ethtool.c | 245 ++++++++++++++++-------- + drivers/net/ethernet/emulex/benet/be_main.c | 20 +- + 5 files changed, 239 insertions(+), 102 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index 9576ac0..ad69cf8 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -313,6 +313,23 @@ struct be_vf_cfg { + #define BE_UC_PMAC_COUNT 30 + #define BE_VF_UC_PMAC_COUNT 2 + ++struct phy_info { ++ u8 transceiver; ++ u8 autoneg; ++ u8 fc_autoneg; ++ u8 port_type; ++ u16 phy_type; ++ u16 interface_type; ++ u32 misc_params; ++ u16 auto_speeds_supported; ++ u16 fixed_speeds_supported; ++ int link_speed; ++ int forced_port_speed; ++ u32 dac_cable_len; ++ u32 advertising; ++ u32 supported; ++}; ++ + struct be_adapter { + struct pci_dev *pdev; + struct net_device *netdev; +@@ -377,10 +394,6 @@ struct be_adapter { + u32 rx_fc; /* Rx flow control */ + u32 tx_fc; /* Tx flow control */ + bool stats_cmd_sent; +- int link_speed; +- u8 port_type; +- u8 transceiver; +- u8 autoneg; + u8 generation; /* BladeEngine ASIC generation */ + u32 flash_status; + struct completion flash_compl; +@@ -392,6 +405,7 @@ struct be_adapter { + u32 sli_family; + u8 hba_port_num; + u16 pvid; ++ struct phy_info phy; + u8 wol_cap; + bool wol; + u32 max_pmac_cnt; /* Max secondary UC MACs programmable */ +@@ -583,4 +597,5 @@ extern void be_link_status_update(struct be_adapter *adapter, u8 link_status); + extern void be_parse_stats(struct be_adapter *adapter); + extern int be_load_fw(struct be_adapter *adapter, u8 *func); + extern bool be_is_wol_supported(struct be_adapter *adapter); ++extern bool be_pause_supported(struct be_adapter *adapter); + #endif /* BE_H */ +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 67b030d..22be08c 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -126,7 +126,7 @@ static void be_async_link_state_process(struct be_adapter *adapter, + struct be_async_event_link_state *evt) + { + /* When link status changes, link speed must be re-queried from FW */ +- adapter->link_speed = -1; ++ adapter->phy.link_speed = -1; + + /* For the initial link status do not rely on the ASYNC event as + * it may not be received in some cases. +@@ -153,7 +153,7 @@ static void be_async_grp5_qos_speed_process(struct be_adapter *adapter, + { + if (evt->physical_port == adapter->port_num) { + /* qos_link_speed is in units of 10 Mbps */ +- adapter->link_speed = evt->qos_link_speed * 10; ++ adapter->phy.link_speed = evt->qos_link_speed * 10; + } + } + +@@ -2136,8 +2136,7 @@ err: + return status; + } + +-int be_cmd_get_phy_info(struct be_adapter *adapter, +- struct be_phy_info *phy_info) ++int be_cmd_get_phy_info(struct be_adapter *adapter) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_phy_info *req; +@@ -2170,9 +2169,15 @@ int be_cmd_get_phy_info(struct be_adapter *adapter, + if (!status) { + struct be_phy_info *resp_phy_info = + cmd.va + sizeof(struct be_cmd_req_hdr); +- phy_info->phy_type = le16_to_cpu(resp_phy_info->phy_type); +- phy_info->interface_type = ++ adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type); ++ adapter->phy.interface_type = + le16_to_cpu(resp_phy_info->interface_type); ++ adapter->phy.auto_speeds_supported = ++ le16_to_cpu(resp_phy_info->auto_speeds_supported); ++ adapter->phy.fixed_speeds_supported = ++ le16_to_cpu(resp_phy_info->fixed_speeds_supported); ++ adapter->phy.misc_params = ++ le32_to_cpu(resp_phy_info->misc_params); + } + pci_free_consistent(adapter->pdev, cmd.size, + cmd.va, cmd.dma); +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h +index d5b680c..3c54361 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.h ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.h +@@ -1309,9 +1309,36 @@ enum { + PHY_TYPE_KX4_10GB, + PHY_TYPE_BASET_10GB, + PHY_TYPE_BASET_1GB, ++ PHY_TYPE_BASEX_1GB, ++ PHY_TYPE_SGMII, + PHY_TYPE_DISABLED = 255 + }; + ++#define BE_SUPPORTED_SPEED_NONE 0 ++#define BE_SUPPORTED_SPEED_10MBPS 1 ++#define BE_SUPPORTED_SPEED_100MBPS 2 ++#define BE_SUPPORTED_SPEED_1GBPS 4 ++#define BE_SUPPORTED_SPEED_10GBPS 8 ++ ++#define BE_AN_EN 0x2 ++#define BE_PAUSE_SYM_EN 0x80 ++ ++/* MAC speed valid values */ ++#define SPEED_DEFAULT 0x0 ++#define SPEED_FORCED_10GB 0x1 ++#define SPEED_FORCED_1GB 0x2 ++#define SPEED_AUTONEG_10GB 0x3 ++#define SPEED_AUTONEG_1GB 0x4 ++#define SPEED_AUTONEG_100MB 0x5 ++#define SPEED_AUTONEG_10GB_1GB 0x6 ++#define SPEED_AUTONEG_10GB_1GB_100MB 0x7 ++#define SPEED_AUTONEG_1GB_100MB 0x8 ++#define SPEED_AUTONEG_10MB 0x9 ++#define SPEED_AUTONEG_1GB_100MB_10MB 0xa ++#define SPEED_AUTONEG_100MB_10MB 0xb ++#define SPEED_FORCED_100MB 0xc ++#define SPEED_FORCED_10MB 0xd ++ + struct be_cmd_req_get_phy_info { + struct be_cmd_req_hdr hdr; + u8 rsvd0[24]; +@@ -1321,7 +1348,11 @@ struct be_phy_info { + u16 phy_type; + u16 interface_type; + u32 misc_params; +- u32 future_use[4]; ++ u16 ext_phy_details; ++ u16 rsvd; ++ u16 auto_speeds_supported; ++ u16 fixed_speeds_supported; ++ u32 future_use[2]; + }; + + struct be_cmd_resp_get_phy_info { +@@ -1655,8 +1686,7 @@ extern int be_cmd_get_seeprom_data(struct be_adapter *adapter, + struct be_dma_mem *nonemb_cmd); + extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, + u8 loopback_type, u8 enable); +-extern int be_cmd_get_phy_info(struct be_adapter *adapter, +- struct be_phy_info *phy_info); ++extern int be_cmd_get_phy_info(struct be_adapter *adapter); + extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain); + extern void be_detect_dump_ue(struct be_adapter *adapter); + extern int be_cmd_get_die_temperature(struct be_adapter *adapter); +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index e0eb995..076adeb 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -433,102 +433,193 @@ static int be_get_sset_count(struct net_device *netdev, int stringset) + } + } + ++static u32 be_get_port_type(u32 phy_type, u32 dac_cable_len) ++{ ++ u32 port; ++ ++ switch (phy_type) { ++ case PHY_TYPE_BASET_1GB: ++ case PHY_TYPE_BASEX_1GB: ++ case PHY_TYPE_SGMII: ++ port = PORT_TP; ++ break; ++ case PHY_TYPE_SFP_PLUS_10GB: ++ port = dac_cable_len ? PORT_DA : PORT_FIBRE; ++ break; ++ case PHY_TYPE_XFP_10GB: ++ case PHY_TYPE_SFP_1GB: ++ port = PORT_FIBRE; ++ break; ++ case PHY_TYPE_BASET_10GB: ++ port = PORT_TP; ++ break; ++ default: ++ port = PORT_OTHER; ++ } ++ ++ return port; ++} ++ ++static u32 convert_to_et_setting(u32 if_type, u32 if_speeds) ++{ ++ u32 val = 0; ++ ++ switch (if_type) { ++ case PHY_TYPE_BASET_1GB: ++ case PHY_TYPE_BASEX_1GB: ++ case PHY_TYPE_SGMII: ++ val |= SUPPORTED_TP; ++ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS) ++ val |= SUPPORTED_1000baseT_Full; ++ if (if_speeds & BE_SUPPORTED_SPEED_100MBPS) ++ val |= SUPPORTED_100baseT_Full; ++ if (if_speeds & BE_SUPPORTED_SPEED_10MBPS) ++ val |= SUPPORTED_10baseT_Full; ++ break; ++ case PHY_TYPE_KX4_10GB: ++ val |= SUPPORTED_Backplane; ++ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS) ++ val |= SUPPORTED_1000baseKX_Full; ++ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS) ++ val |= SUPPORTED_10000baseKX4_Full; ++ break; ++ case PHY_TYPE_KR_10GB: ++ val |= SUPPORTED_Backplane | ++ SUPPORTED_10000baseKR_Full; ++ break; ++ case PHY_TYPE_SFP_PLUS_10GB: ++ case PHY_TYPE_XFP_10GB: ++ case PHY_TYPE_SFP_1GB: ++ val |= SUPPORTED_FIBRE; ++ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS) ++ val |= SUPPORTED_10000baseT_Full; ++ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS) ++ val |= SUPPORTED_1000baseT_Full; ++ break; ++ case PHY_TYPE_BASET_10GB: ++ val |= SUPPORTED_TP; ++ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS) ++ val |= SUPPORTED_10000baseT_Full; ++ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS) ++ val |= SUPPORTED_1000baseT_Full; ++ if (if_speeds & BE_SUPPORTED_SPEED_100MBPS) ++ val |= SUPPORTED_100baseT_Full; ++ break; ++ default: ++ val |= SUPPORTED_TP; ++ } ++ ++ return val; ++} ++ ++static int convert_to_et_speed(u32 be_speed) ++{ ++ int et_speed = SPEED_10000; ++ ++ switch (be_speed) { ++ case PHY_LINK_SPEED_10MBPS: ++ et_speed = SPEED_10; ++ break; ++ case PHY_LINK_SPEED_100MBPS: ++ et_speed = SPEED_100; ++ break; ++ case PHY_LINK_SPEED_1GBPS: ++ et_speed = SPEED_1000; ++ break; ++ case PHY_LINK_SPEED_10GBPS: ++ et_speed = SPEED_10000; ++ break; ++ } ++ ++ return et_speed; ++} ++ ++bool be_pause_supported(struct be_adapter *adapter) ++{ ++ return (adapter->phy.interface_type == PHY_TYPE_SFP_PLUS_10GB || ++ adapter->phy.interface_type == PHY_TYPE_XFP_10GB) ? ++ false : true; ++} ++ + static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + { + struct be_adapter *adapter = netdev_priv(netdev); +- struct be_phy_info phy_info; +- u8 mac_speed = 0; ++ u8 port_speed = 0; + u16 link_speed = 0; + u8 link_status; ++ u32 et_speed = 0; + int status; + +- if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) { +- status = be_cmd_link_status_query(adapter, &mac_speed, +- &link_speed, &link_status, 0); +- if (!status) +- be_link_status_update(adapter, link_status); +- +- /* link_speed is in units of 10 Mbps */ +- if (link_speed) { +- ethtool_cmd_speed_set(ecmd, link_speed*10); ++ if (adapter->phy.link_speed < 0 || !(netdev->flags & IFF_UP)) { ++ if (adapter->phy.forced_port_speed < 0) { ++ status = be_cmd_link_status_query(adapter, &port_speed, ++ &link_speed, &link_status, 0); ++ if (!status) ++ be_link_status_update(adapter, link_status); ++ if (link_speed) ++ et_speed = link_speed; ++ else ++ et_speed = convert_to_et_speed(port_speed); + } else { +- switch (mac_speed) { +- case PHY_LINK_SPEED_10MBPS: +- ethtool_cmd_speed_set(ecmd, SPEED_10); +- break; +- case PHY_LINK_SPEED_100MBPS: +- ethtool_cmd_speed_set(ecmd, SPEED_100); +- break; +- case PHY_LINK_SPEED_1GBPS: +- ethtool_cmd_speed_set(ecmd, SPEED_1000); +- break; +- case PHY_LINK_SPEED_10GBPS: +- ethtool_cmd_speed_set(ecmd, SPEED_10000); +- break; +- case PHY_LINK_SPEED_ZERO: +- ethtool_cmd_speed_set(ecmd, 0); +- break; +- } ++ et_speed = adapter->phy.forced_port_speed; + } + +- status = be_cmd_get_phy_info(adapter, &phy_info); +- if (!status) { +- switch (phy_info.interface_type) { +- case PHY_TYPE_XFP_10GB: +- case PHY_TYPE_SFP_1GB: +- case PHY_TYPE_SFP_PLUS_10GB: +- ecmd->port = PORT_FIBRE; +- break; +- default: +- ecmd->port = PORT_TP; +- break; +- } ++ ethtool_cmd_speed_set(ecmd, et_speed); ++ ++ status = be_cmd_get_phy_info(adapter); ++ if (status) ++ return status; ++ ++ ecmd->supported = ++ convert_to_et_setting(adapter->phy.interface_type, ++ adapter->phy.auto_speeds_supported | ++ adapter->phy.fixed_speeds_supported); ++ ecmd->advertising = ++ convert_to_et_setting(adapter->phy.interface_type, ++ adapter->phy.auto_speeds_supported); + +- switch (phy_info.interface_type) { +- case PHY_TYPE_KR_10GB: +- case PHY_TYPE_KX4_10GB: +- ecmd->autoneg = AUTONEG_ENABLE; ++ ecmd->port = be_get_port_type(adapter->phy.interface_type, ++ adapter->phy.dac_cable_len); ++ ++ if (adapter->phy.auto_speeds_supported) { ++ ecmd->supported |= SUPPORTED_Autoneg; ++ ecmd->autoneg = AUTONEG_ENABLE; ++ ecmd->advertising |= ADVERTISED_Autoneg; ++ } ++ ++ if (be_pause_supported(adapter)) { ++ ecmd->supported |= SUPPORTED_Pause; ++ ecmd->advertising |= ADVERTISED_Pause; ++ } ++ ++ switch (adapter->phy.interface_type) { ++ case PHY_TYPE_KR_10GB: ++ case PHY_TYPE_KX4_10GB: + ecmd->transceiver = XCVR_INTERNAL; +- break; +- default: +- ecmd->autoneg = AUTONEG_DISABLE; +- ecmd->transceiver = XCVR_EXTERNAL; +- break; +- } ++ break; ++ default: ++ ecmd->transceiver = XCVR_EXTERNAL; ++ break; + } + + /* Save for future use */ +- adapter->link_speed = ethtool_cmd_speed(ecmd); +- adapter->port_type = ecmd->port; +- adapter->transceiver = ecmd->transceiver; +- adapter->autoneg = ecmd->autoneg; ++ adapter->phy.link_speed = ethtool_cmd_speed(ecmd); ++ adapter->phy.port_type = ecmd->port; ++ adapter->phy.transceiver = ecmd->transceiver; ++ adapter->phy.autoneg = ecmd->autoneg; ++ adapter->phy.advertising = ecmd->advertising; ++ adapter->phy.supported = ecmd->supported; + } else { +- ethtool_cmd_speed_set(ecmd, adapter->link_speed); +- ecmd->port = adapter->port_type; +- ecmd->transceiver = adapter->transceiver; +- ecmd->autoneg = adapter->autoneg; ++ ethtool_cmd_speed_set(ecmd, adapter->phy.link_speed); ++ ecmd->port = adapter->phy.port_type; ++ ecmd->transceiver = adapter->phy.transceiver; ++ ecmd->autoneg = adapter->phy.autoneg; ++ ecmd->advertising = adapter->phy.advertising; ++ ecmd->supported = adapter->phy.supported; + } + + ecmd->duplex = DUPLEX_FULL; + ecmd->phy_address = adapter->port_num; +- switch (ecmd->port) { +- case PORT_FIBRE: +- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); +- break; +- case PORT_TP: +- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP); +- break; +- case PORT_AUI: +- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_AUI); +- break; +- } +- +- if (ecmd->autoneg) { +- ecmd->supported |= SUPPORTED_1000baseT_Full; +- ecmd->supported |= SUPPORTED_Autoneg; +- ecmd->advertising |= (ADVERTISED_10000baseT_Full | +- ADVERTISED_1000baseT_Full); +- } + + return 0; + } +@@ -548,7 +639,7 @@ be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) + struct be_adapter *adapter = netdev_priv(netdev); + + be_cmd_get_flow_control(adapter, &ecmd->tx_pause, &ecmd->rx_pause); +- ecmd->autoneg = 0; ++ ecmd->autoneg = adapter->phy.fc_autoneg; + } + + static int +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 2e54335..376a2fa 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -2563,11 +2563,12 @@ err: + static void be_setup_init(struct be_adapter *adapter) + { + adapter->vlan_prio_bmap = 0xff; +- adapter->link_speed = -1; ++ adapter->phy.link_speed = -1; + adapter->if_handle = -1; + adapter->be3_native = false; + adapter->promiscuous = false; + adapter->eq_next_idx = 0; ++ adapter->phy.forced_port_speed = -1; + } + + static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac) +@@ -2699,6 +2700,10 @@ static int be_setup(struct be_adapter *adapter) + goto err; + } + ++ be_cmd_get_phy_info(adapter); ++ if (be_pause_supported(adapter)) ++ adapter->phy.fc_autoneg = 1; ++ + schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); + adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; + +@@ -2752,17 +2757,8 @@ static bool be_flash_redboot(struct be_adapter *adapter, + + static bool phy_flashing_required(struct be_adapter *adapter) + { +- int status = 0; +- struct be_phy_info phy_info; +- +- status = be_cmd_get_phy_info(adapter, &phy_info); +- if (status) +- return false; +- if ((phy_info.phy_type == TN_8022) && +- (phy_info.interface_type == PHY_TYPE_BASET_10GB)) { +- return true; +- } +- return false; ++ return (adapter->phy.phy_type == TN_8022 && ++ adapter->phy.interface_type == PHY_TYPE_BASET_10GB); + } + + static int be_flash_data(struct be_adapter *adapter, +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0044-be2net-Fix-VLAN-multicast-packet-reception.patch b/debian/patches/features/all/be2net/0044-be2net-Fix-VLAN-multicast-packet-reception.patch new file mode 100644 index 000000000..a49ecf62c --- /dev/null +++ b/debian/patches/features/all/be2net/0044-be2net-Fix-VLAN-multicast-packet-reception.patch @@ -0,0 +1,94 @@ +From: Padmanabh Ratnakar +Date: Fri, 25 May 2012 21:28:09 +0530 +Subject: [PATCH 44/58] be2net: Fix VLAN/multicast packet reception + +commit 0fc16ebf69fc57b42110712eaaf8a6aa2492afbe upstream. + +VLAN and multicast hardware filters are limited and can get +exhausted in adapters with many PCI functions. If setting +a VLAN or multicast filter fails due to lack of sufficient +hardware resources, these packets get dropped. Fix this by +switching to VLAN or multicast promiscous mode so that these +packets are not dropped. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 44 ++++++++++++++++++--------- + 1 file changed, 30 insertions(+), 14 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 376a2fa..34b8ad2 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -797,22 +797,30 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) + if (adapter->promiscuous) + return 0; + +- if (adapter->vlans_added <= adapter->max_vlans) { +- /* Construct VLAN Table to give to HW */ +- for (i = 0; i < VLAN_N_VID; i++) { +- if (adapter->vlan_tag[i]) { +- vtag[ntags] = cpu_to_le16(i); +- ntags++; +- } +- } +- status = be_cmd_vlan_config(adapter, adapter->if_handle, +- vtag, ntags, 1, 0); +- } else { +- status = be_cmd_vlan_config(adapter, adapter->if_handle, +- NULL, 0, 1, 1); ++ if (adapter->vlans_added > adapter->max_vlans) ++ goto set_vlan_promisc; ++ ++ /* Construct VLAN Table to give to HW */ ++ for (i = 0; i < VLAN_N_VID; i++) ++ if (adapter->vlan_tag[i]) ++ vtag[ntags++] = cpu_to_le16(i); ++ ++ status = be_cmd_vlan_config(adapter, adapter->if_handle, ++ vtag, ntags, 1, 0); ++ ++ /* Set to VLAN promisc mode as setting VLAN filter failed */ ++ if (status) { ++ dev_info(&adapter->pdev->dev, "Exhausted VLAN HW filters.\n"); ++ dev_info(&adapter->pdev->dev, "Disabling HW VLAN filtering.\n"); ++ goto set_vlan_promisc; + } + + return status; ++ ++set_vlan_promisc: ++ status = be_cmd_vlan_config(adapter, adapter->if_handle, ++ NULL, 0, 1, 1); ++ return status; + } + + static void be_vlan_add_vid(struct net_device *netdev, u16 vid) +@@ -854,6 +862,7 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) + static void be_set_rx_mode(struct net_device *netdev) + { + struct be_adapter *adapter = netdev_priv(netdev); ++ int status; + + if (netdev->flags & IFF_PROMISC) { + be_cmd_rx_filter(adapter, IFF_PROMISC, ON); +@@ -900,7 +909,14 @@ static void be_set_rx_mode(struct net_device *netdev) + } + } + +- be_cmd_rx_filter(adapter, IFF_MULTICAST, ON); ++ status = be_cmd_rx_filter(adapter, IFF_MULTICAST, ON); ++ ++ /* Set to MCAST promisc mode if setting MULTICAST address fails */ ++ if (status) { ++ dev_info(&adapter->pdev->dev, "Exhausted multicast HW filters.\n"); ++ dev_info(&adapter->pdev->dev, "Disabling HW multicast filtering.\n"); ++ be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON); ++ } + done: + return; + } +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0045-be2net-Fix-FW-download-in-Lancer.patch b/debian/patches/features/all/be2net/0045-be2net-Fix-FW-download-in-Lancer.patch new file mode 100644 index 000000000..8a5f30e4e --- /dev/null +++ b/debian/patches/features/all/be2net/0045-be2net-Fix-FW-download-in-Lancer.patch @@ -0,0 +1,44 @@ +From: Padmanabh Ratnakar +Date: Wed, 25 Apr 2012 01:46:18 +0000 +Subject: [PATCH 45/58] be2net: Fix FW download in Lancer + +commit 804c751599855a83efdc781cd9a2bda725d1391c upstream. + +Increase time given by driver to adapter for completing FW download +to 30 seconds. Also return correct status when FW download times out. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 22be08c..3ba4aed 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -1824,18 +1824,16 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, + spin_unlock_bh(&adapter->mcc_lock); + + if (!wait_for_completion_timeout(&adapter->flash_compl, +- msecs_to_jiffies(12000))) ++ msecs_to_jiffies(30000))) + status = -1; + else + status = adapter->flash_status; + + resp = embedded_payload(wrb); +- if (!status) { ++ if (!status) + *data_written = le32_to_cpu(resp->actual_write_len); +- } else { ++ else + *addn_status = resp->additional_status; +- status = resp->status; +- } + + return status; + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0046-be2net-Fix-ethtool-self-test-for-Lancer.patch b/debian/patches/features/all/be2net/0046-be2net-Fix-ethtool-self-test-for-Lancer.patch new file mode 100644 index 000000000..589d83892 --- /dev/null +++ b/debian/patches/features/all/be2net/0046-be2net-Fix-ethtool-self-test-for-Lancer.patch @@ -0,0 +1,31 @@ +From: Padmanabh Ratnakar +Date: Wed, 25 Apr 2012 01:46:28 +0000 +Subject: [PATCH 46/58] be2net: Fix ethtool self test for Lancer + +commit a70473949698c1c46e5523e1810a0a0f904a1fd2 upstream. + +Lancer does not support DDR self test. Fix ethtool self test by +skipping this test for Lancer. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_ethtool.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index 076adeb..9d71bad 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -793,7 +793,7 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) + } + } + +- if (be_test_ddr_dma(adapter) != 0) { ++ if (!lancer_chip(adapter) && be_test_ddr_dma(adapter) != 0) { + data[3] = 1; + test->flags |= ETH_TEST_FL_FAILED; + } +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0047-be2net-Fix-traffic-stall-INTx-mode.patch b/debian/patches/features/all/be2net/0047-be2net-Fix-traffic-stall-INTx-mode.patch new file mode 100644 index 000000000..fd6dd0d08 --- /dev/null +++ b/debian/patches/features/all/be2net/0047-be2net-Fix-traffic-stall-INTx-mode.patch @@ -0,0 +1,36 @@ +From: Padmanabh Ratnakar +Date: Wed, 25 Apr 2012 01:46:39 +0000 +Subject: [PATCH 47/58] be2net: Fix traffic stall INTx mode + +commit af311fe31015e2b27bd65e22fc103230fb3a78b7 upstream. + +EQ is getting armed wrongly in INTx mode as INTx interrupt is taking +some time to deassert. This can cause another interrupt while NAPI is +scheduled and scheduling a NAPI in interrupt does not take effect. +This causes interrupt to be missed and traffic stalls. Fixing this by +preventing wrong arming of EQ. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 34b8ad2..915b95e 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1563,7 +1563,9 @@ static int event_handle(struct be_eq_obj *eqo) + if (!num) + rearm = true; + +- be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num); ++ if (num || msix_enabled(eqo->adapter)) ++ be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num); ++ + if (num) + napi_schedule(&eqo->napi); + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0048-be2net-Fix-Lancer-statistics.patch b/debian/patches/features/all/be2net/0048-be2net-Fix-Lancer-statistics.patch new file mode 100644 index 000000000..2eacf504b --- /dev/null +++ b/debian/patches/features/all/be2net/0048-be2net-Fix-Lancer-statistics.patch @@ -0,0 +1,55 @@ +From: Padmanabh Ratnakar +Date: Wed, 25 Apr 2012 01:46:52 +0000 +Subject: [PATCH 48/58] be2net: Fix Lancer statistics + +commit d51ebd331166e102591e5c25805d8015df0e1e21 upstream. + +Fix port num sent in command to get stats. Also skip unnecessary +parsing of stats for Lancer. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 2 +- + drivers/net/ethernet/emulex/benet/be_main.c | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 3ba4aed..4e07e58 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -1221,7 +1221,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter, + OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size, wrb, + nonemb_cmd); + +- req->cmd_params.params.pport_num = cpu_to_le16(adapter->port_num); ++ req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num); + req->cmd_params.params.reset_stats = 0; + + be_mcc_notify(adapter); +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 915b95e..9b1c03e 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -421,6 +421,9 @@ void be_parse_stats(struct be_adapter *adapter) + populate_be2_stats(adapter); + } + ++ if (lancer_chip(adapter)) ++ goto done; ++ + /* as erx_v1 is longer than v0, ok to use v1 defn for v0 access */ + for_all_rx_queues(adapter, rxo, i) { + /* below erx HW counter can actually wrap around after +@@ -429,6 +432,8 @@ void be_parse_stats(struct be_adapter *adapter) + accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags, + (u16)erx->rx_drops_no_fragments[rxo->q.id]); + } ++done: ++ return; + } + + static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev, +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0049-be2net-Fix-wrong-status-getting-returned-for-MCC-com.patch b/debian/patches/features/all/be2net/0049-be2net-Fix-wrong-status-getting-returned-for-MCC-com.patch new file mode 100644 index 000000000..f899b3ca3 --- /dev/null +++ b/debian/patches/features/all/be2net/0049-be2net-Fix-wrong-status-getting-returned-for-MCC-com.patch @@ -0,0 +1,232 @@ +From: Padmanabh Ratnakar +Date: Wed, 25 Apr 2012 01:47:03 +0000 +Subject: [PATCH 49/58] be2net: Fix wrong status getting returned for MCC + commands + +commit 652bf64622f32c938dd4a8738ba12d51dc9fbdd4 upstream. + +MCC Response CQEs are processed as part of NAPI poll routine and +also synchronously. If MCC completions are consumed by NAPI poll +routine, wrong status is returned to synchronously waiting routine. +Fix this by getting status of MCC command from command response +instead of response CQEs. + +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 5 ++ + drivers/net/ethernet/emulex/benet/be_cmds.c | 81 ++++++++++++++++++--------- + drivers/net/ethernet/emulex/benet/be_cmds.h | 8 ++- + 3 files changed, 67 insertions(+), 27 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index ad69cf8..4bc18ef 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -162,6 +162,11 @@ static inline void queue_head_inc(struct be_queue_info *q) + index_inc(&q->head, q->len); + } + ++static inline void index_dec(u16 *index, u16 limit) ++{ ++ *index = MODULO((*index - 1), limit); ++} ++ + static inline void queue_tail_inc(struct be_queue_info *q) + { + index_inc(&q->tail, q->len); +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 4e07e58..2673081 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -61,10 +61,21 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl) + compl->flags = 0; + } + ++static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1) ++{ ++ unsigned long addr; ++ ++ addr = tag1; ++ addr = ((addr << 16) << 16) | tag0; ++ return (void *)addr; ++} ++ + static int be_mcc_compl_process(struct be_adapter *adapter, +- struct be_mcc_compl *compl) ++ struct be_mcc_compl *compl) + { + u16 compl_status, extd_status; ++ struct be_cmd_resp_hdr *resp_hdr; ++ u8 opcode = 0, subsystem = 0; + + /* Just swap the status to host endian; mcc tag is opaquely copied + * from mcc_wrb */ +@@ -73,32 +84,36 @@ static int be_mcc_compl_process(struct be_adapter *adapter, + compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & + CQE_STATUS_COMPL_MASK; + +- if (((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) || +- (compl->tag0 == OPCODE_COMMON_WRITE_OBJECT)) && +- (compl->tag1 == CMD_SUBSYSTEM_COMMON)) { ++ resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1); ++ ++ if (resp_hdr) { ++ opcode = resp_hdr->opcode; ++ subsystem = resp_hdr->subsystem; ++ } ++ ++ if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) || ++ (opcode == OPCODE_COMMON_WRITE_OBJECT)) && ++ (subsystem == CMD_SUBSYSTEM_COMMON)) { + adapter->flash_status = compl_status; + complete(&adapter->flash_compl); + } + + if (compl_status == MCC_STATUS_SUCCESS) { +- if (((compl->tag0 == OPCODE_ETH_GET_STATISTICS) || +- (compl->tag0 == OPCODE_ETH_GET_PPORT_STATS)) && +- (compl->tag1 == CMD_SUBSYSTEM_ETH)) { ++ if (((opcode == OPCODE_ETH_GET_STATISTICS) || ++ (opcode == OPCODE_ETH_GET_PPORT_STATS)) && ++ (subsystem == CMD_SUBSYSTEM_ETH)) { + be_parse_stats(adapter); + adapter->stats_cmd_sent = false; + } +- if (compl->tag0 == +- OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) { +- struct be_mcc_wrb *mcc_wrb = +- queue_index_node(&adapter->mcc_obj.q, +- compl->tag1); ++ if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES && ++ subsystem == CMD_SUBSYSTEM_COMMON) { + struct be_cmd_resp_get_cntl_addnl_attribs *resp = +- embedded_payload(mcc_wrb); ++ (void *)resp_hdr; + adapter->drv_stats.be_on_die_temperature = + resp->on_die_temperature; + } + } else { +- if (compl->tag0 == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) ++ if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) + be_get_temp_freq = 0; + + if (compl_status == MCC_STATUS_NOT_SUPPORTED || +@@ -108,13 +123,13 @@ static int be_mcc_compl_process(struct be_adapter *adapter, + if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) { + dev_warn(&adapter->pdev->dev, "This domain(VM) is not " + "permitted to execute this cmd (opcode %d)\n", +- compl->tag0); ++ opcode); + } else { + extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & + CQE_STATUS_EXTD_MASK; + dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:" + "status %d, extd-status %d\n", +- compl->tag0, compl_status, extd_status); ++ opcode, compl_status, extd_status); + } + } + done: +@@ -286,7 +301,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) + if (i == mcc_timeout) { + dev_err(&adapter->pdev->dev, "FW not responding\n"); + adapter->fw_timeout = true; +- return -1; ++ return -EIO; + } + return status; + } +@@ -294,8 +309,26 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) + /* Notify MCC requests and wait for completion */ + static int be_mcc_notify_wait(struct be_adapter *adapter) + { ++ int status; ++ struct be_mcc_wrb *wrb; ++ struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; ++ u16 index = mcc_obj->q.head; ++ struct be_cmd_resp_hdr *resp; ++ ++ index_dec(&index, mcc_obj->q.len); ++ wrb = queue_index_node(&mcc_obj->q, index); ++ ++ resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1); ++ + be_mcc_notify(adapter); +- return be_mcc_wait_compl(adapter); ++ ++ status = be_mcc_wait_compl(adapter); ++ if (status == -EIO) ++ goto out; ++ ++ status = resp->status; ++out: ++ return status; + } + + static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) +@@ -435,14 +468,17 @@ static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, + struct be_mcc_wrb *wrb, struct be_dma_mem *mem) + { + struct be_sge *sge; ++ unsigned long addr = (unsigned long)req_hdr; ++ u64 req_addr = addr; + + req_hdr->opcode = opcode; + req_hdr->subsystem = subsystem; + req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); + req_hdr->version = 0; + +- wrb->tag0 = opcode; +- wrb->tag1 = subsystem; ++ wrb->tag0 = req_addr & 0xFFFFFFFF; ++ wrb->tag1 = upper_32_bits(req_addr); ++ + wrb->payload_length = cmd_len; + if (mem) { + wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) << +@@ -1283,13 +1319,10 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter) + { + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_cntl_addnl_attribs *req; +- u16 mccq_index; + int status; + + spin_lock_bh(&adapter->mcc_lock); + +- mccq_index = adapter->mcc_obj.q.head; +- + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; +@@ -1301,8 +1334,6 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter) + OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, sizeof(*req), + wrb, NULL); + +- wrb->tag1 = mccq_index; +- + be_mcc_notify(adapter); + + err: +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h +index 3c54361..944f031 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.h ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.h +@@ -225,8 +225,12 @@ struct be_cmd_req_hdr { + #define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */ + #define RESP_HDR_INFO_SUBSYS_SHIFT 8 /* bits 8 - 15 */ + struct be_cmd_resp_hdr { +- u32 info; /* dword 0 */ +- u32 status; /* dword 1 */ ++ u8 opcode; /* dword 0 */ ++ u8 subsystem; /* dword 0 */ ++ u8 rsvd[2]; /* dword 0 */ ++ u8 status; /* dword 1 */ ++ u8 add_status; /* dword 1 */ ++ u8 rsvd1[2]; /* dword 1 */ + u32 response_length; /* dword 2 */ + u32 actual_resp_len; /* dword 3 */ + }; +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0050-be2net-Fix-FW-download-for-BE.patch b/debian/patches/features/all/be2net/0050-be2net-Fix-FW-download-for-BE.patch new file mode 100644 index 000000000..1f344a742 --- /dev/null +++ b/debian/patches/features/all/be2net/0050-be2net-Fix-FW-download-for-BE.patch @@ -0,0 +1,383 @@ +From: Padmanabh Ratnakar +Date: Wed, 25 Apr 2012 01:47:15 +0000 +Subject: [PATCH 50/58] be2net: Fix FW download for BE + +commit c165541efc4d1024d7db22ecdf64359b1f6107fc upstream. + +Skip flashing a FW component if that component is not present in a +particular FW UFI image. + +Signed-off-by: Somnath Kotur +Signed-off-by: Padmanabh Ratnakar +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 2 +- + drivers/net/ethernet/emulex/benet/be_hw.h | 74 ++++++++---- + drivers/net/ethernet/emulex/benet/be_main.c | 168 ++++++++++++++++++--------- + 3 files changed, 166 insertions(+), 78 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 2673081..43167e8 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -1979,7 +1979,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4, wrb, NULL); + +- req->params.op_type = cpu_to_le32(IMG_TYPE_REDBOOT); ++ req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT); + req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); + req->params.offset = cpu_to_le32(offset); + req->params.data_buf_size = cpu_to_le32(0x4); +diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h +index f2c89e3..0949aa6 100644 +--- a/drivers/net/ethernet/emulex/benet/be_hw.h ++++ b/drivers/net/ethernet/emulex/benet/be_hw.h +@@ -162,22 +162,23 @@ + #define QUERY_FAT 1 + + /* Flashrom related descriptors */ ++#define MAX_FLASH_COMP 32 + #define IMAGE_TYPE_FIRMWARE 160 + #define IMAGE_TYPE_BOOTCODE 224 + #define IMAGE_TYPE_OPTIONROM 32 + + #define NUM_FLASHDIR_ENTRIES 32 + +-#define IMG_TYPE_ISCSI_ACTIVE 0 +-#define IMG_TYPE_REDBOOT 1 +-#define IMG_TYPE_BIOS 2 +-#define IMG_TYPE_PXE_BIOS 3 +-#define IMG_TYPE_FCOE_BIOS 8 +-#define IMG_TYPE_ISCSI_BACKUP 9 +-#define IMG_TYPE_FCOE_FW_ACTIVE 10 +-#define IMG_TYPE_FCOE_FW_BACKUP 11 +-#define IMG_TYPE_NCSI_FW 13 +-#define IMG_TYPE_PHY_FW 99 ++#define OPTYPE_ISCSI_ACTIVE 0 ++#define OPTYPE_REDBOOT 1 ++#define OPTYPE_BIOS 2 ++#define OPTYPE_PXE_BIOS 3 ++#define OPTYPE_FCOE_BIOS 8 ++#define OPTYPE_ISCSI_BACKUP 9 ++#define OPTYPE_FCOE_FW_ACTIVE 10 ++#define OPTYPE_FCOE_FW_BACKUP 11 ++#define OPTYPE_NCSI_FW 13 ++#define OPTYPE_PHY_FW 99 + #define TN_8022 13 + + #define ILLEGAL_IOCTL_REQ 2 +@@ -223,6 +224,24 @@ + #define FLASH_REDBOOT_START_g3 (262144) + #define FLASH_PHY_FW_START_g3 1310720 + ++#define IMAGE_NCSI 16 ++#define IMAGE_OPTION_ROM_PXE 32 ++#define IMAGE_OPTION_ROM_FCoE 33 ++#define IMAGE_OPTION_ROM_ISCSI 34 ++#define IMAGE_FLASHISM_JUMPVECTOR 48 ++#define IMAGE_FLASH_ISM 49 ++#define IMAGE_JUMP_VECTOR 50 ++#define IMAGE_FIRMWARE_iSCSI 160 ++#define IMAGE_FIRMWARE_COMP_iSCSI 161 ++#define IMAGE_FIRMWARE_FCoE 162 ++#define IMAGE_FIRMWARE_COMP_FCoE 163 ++#define IMAGE_FIRMWARE_BACKUP_iSCSI 176 ++#define IMAGE_FIRMWARE_BACKUP_COMP_iSCSI 177 ++#define IMAGE_FIRMWARE_BACKUP_FCoE 178 ++#define IMAGE_FIRMWARE_BACKUP_COMP_FCoE 179 ++#define IMAGE_FIRMWARE_PHY 192 ++#define IMAGE_BOOT_CODE 224 ++ + /************* Rx Packet Type Encoding **************/ + #define BE_UNICAST_PACKET 0 + #define BE_MULTICAST_PACKET 1 +@@ -445,6 +464,7 @@ struct flash_comp { + unsigned long offset; + int optype; + int size; ++ int img_type; + }; + + struct image_hdr { +@@ -481,17 +501,19 @@ struct flash_section_hdr { + u32 format_rev; + u32 cksum; + u32 antidote; +- u32 build_no; +- u8 id_string[64]; +- u32 active_entry_mask; +- u32 valid_entry_mask; +- u32 org_content_mask; +- u32 rsvd0; +- u32 rsvd1; +- u32 rsvd2; +- u32 rsvd3; +- u32 rsvd4; +-}; ++ u32 num_images; ++ u8 id_string[128]; ++ u32 rsvd[4]; ++} __packed; ++ ++struct flash_section_hdr_g2 { ++ u32 format_rev; ++ u32 cksum; ++ u32 antidote; ++ u32 build_num; ++ u8 id_string[128]; ++ u32 rsvd[8]; ++} __packed; + + struct flash_section_entry { + u32 type; +@@ -503,10 +525,16 @@ struct flash_section_entry { + u32 rsvd0; + u32 rsvd1; + u8 ver_data[32]; +-}; ++} __packed; + + struct flash_section_info { + u8 cookie[32]; + struct flash_section_hdr fsec_hdr; + struct flash_section_entry fsec_entry[32]; +-}; ++} __packed; ++ ++struct flash_section_info_g2 { ++ u8 cookie[32]; ++ struct flash_section_hdr_g2 fsec_hdr; ++ struct flash_section_entry fsec_entry[32]; ++} __packed; +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 9b1c03e..730fb1b 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -2751,6 +2751,8 @@ static void be_netpoll(struct net_device *netdev) + #endif + + #define FW_FILE_HDR_SIGN "ServerEngines Corp. " ++char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "}; ++ + static bool be_flash_redboot(struct be_adapter *adapter, + const u8 *p, u32 img_start, int image_size, + int hdr_size) +@@ -2784,58 +2786,101 @@ static bool phy_flashing_required(struct be_adapter *adapter) + adapter->phy.interface_type == PHY_TYPE_BASET_10GB); + } + ++static bool is_comp_in_ufi(struct be_adapter *adapter, ++ struct flash_section_info *fsec, int type) ++{ ++ int i = 0, img_type = 0; ++ struct flash_section_info_g2 *fsec_g2 = NULL; ++ ++ if (adapter->generation != BE_GEN3) ++ fsec_g2 = (struct flash_section_info_g2 *)fsec; ++ ++ for (i = 0; i < MAX_FLASH_COMP; i++) { ++ if (fsec_g2) ++ img_type = le32_to_cpu(fsec_g2->fsec_entry[i].type); ++ else ++ img_type = le32_to_cpu(fsec->fsec_entry[i].type); ++ ++ if (img_type == type) ++ return true; ++ } ++ return false; ++ ++} ++ ++struct flash_section_info *get_fsec_info(struct be_adapter *adapter, ++ int header_size, ++ const struct firmware *fw) ++{ ++ struct flash_section_info *fsec = NULL; ++ const u8 *p = fw->data; ++ ++ p += header_size; ++ while (p < (fw->data + fw->size)) { ++ fsec = (struct flash_section_info *)p; ++ if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) ++ return fsec; ++ p += 32; ++ } ++ return NULL; ++} ++ + static int be_flash_data(struct be_adapter *adapter, +- const struct firmware *fw, +- struct be_dma_mem *flash_cmd, int num_of_images) ++ const struct firmware *fw, ++ struct be_dma_mem *flash_cmd, ++ int num_of_images) + + { + int status = 0, i, filehdr_size = 0; ++ int img_hdrs_size = (num_of_images * sizeof(struct image_hdr)); + u32 total_bytes = 0, flash_op; + int num_bytes; + const u8 *p = fw->data; + struct be_cmd_write_flashrom *req = flash_cmd->va; + const struct flash_comp *pflashcomp; +- int num_comp; +- +- static const struct flash_comp gen3_flash_types[10] = { +- { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE, +- FLASH_IMAGE_MAX_SIZE_g3}, +- { FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT, +- FLASH_REDBOOT_IMAGE_MAX_SIZE_g3}, +- { FLASH_iSCSI_BIOS_START_g3, IMG_TYPE_BIOS, +- FLASH_BIOS_IMAGE_MAX_SIZE_g3}, +- { FLASH_PXE_BIOS_START_g3, IMG_TYPE_PXE_BIOS, +- FLASH_BIOS_IMAGE_MAX_SIZE_g3}, +- { FLASH_FCoE_BIOS_START_g3, IMG_TYPE_FCOE_BIOS, +- FLASH_BIOS_IMAGE_MAX_SIZE_g3}, +- { FLASH_iSCSI_BACKUP_IMAGE_START_g3, IMG_TYPE_ISCSI_BACKUP, +- FLASH_IMAGE_MAX_SIZE_g3}, +- { FLASH_FCoE_PRIMARY_IMAGE_START_g3, IMG_TYPE_FCOE_FW_ACTIVE, +- FLASH_IMAGE_MAX_SIZE_g3}, +- { FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP, +- FLASH_IMAGE_MAX_SIZE_g3}, +- { FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW, +- FLASH_NCSI_IMAGE_MAX_SIZE_g3}, +- { FLASH_PHY_FW_START_g3, IMG_TYPE_PHY_FW, +- FLASH_PHY_FW_IMAGE_MAX_SIZE_g3} ++ int num_comp, hdr_size; ++ struct flash_section_info *fsec = NULL; ++ ++ struct flash_comp gen3_flash_types[] = { ++ { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, OPTYPE_ISCSI_ACTIVE, ++ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_iSCSI}, ++ { FLASH_REDBOOT_START_g3, OPTYPE_REDBOOT, ++ FLASH_REDBOOT_IMAGE_MAX_SIZE_g3, IMAGE_BOOT_CODE}, ++ { FLASH_iSCSI_BIOS_START_g3, OPTYPE_BIOS, ++ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_ISCSI}, ++ { FLASH_PXE_BIOS_START_g3, OPTYPE_PXE_BIOS, ++ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_PXE}, ++ { FLASH_FCoE_BIOS_START_g3, OPTYPE_FCOE_BIOS, ++ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_FCoE}, ++ { FLASH_iSCSI_BACKUP_IMAGE_START_g3, OPTYPE_ISCSI_BACKUP, ++ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_iSCSI}, ++ { FLASH_FCoE_PRIMARY_IMAGE_START_g3, OPTYPE_FCOE_FW_ACTIVE, ++ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_FCoE}, ++ { FLASH_FCoE_BACKUP_IMAGE_START_g3, OPTYPE_FCOE_FW_BACKUP, ++ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_FCoE}, ++ { FLASH_NCSI_START_g3, OPTYPE_NCSI_FW, ++ FLASH_NCSI_IMAGE_MAX_SIZE_g3, IMAGE_NCSI}, ++ { FLASH_PHY_FW_START_g3, OPTYPE_PHY_FW, ++ FLASH_PHY_FW_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_PHY} + }; +- static const struct flash_comp gen2_flash_types[8] = { +- { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE, +- FLASH_IMAGE_MAX_SIZE_g2}, +- { FLASH_REDBOOT_START_g2, IMG_TYPE_REDBOOT, +- FLASH_REDBOOT_IMAGE_MAX_SIZE_g2}, +- { FLASH_iSCSI_BIOS_START_g2, IMG_TYPE_BIOS, +- FLASH_BIOS_IMAGE_MAX_SIZE_g2}, +- { FLASH_PXE_BIOS_START_g2, IMG_TYPE_PXE_BIOS, +- FLASH_BIOS_IMAGE_MAX_SIZE_g2}, +- { FLASH_FCoE_BIOS_START_g2, IMG_TYPE_FCOE_BIOS, +- FLASH_BIOS_IMAGE_MAX_SIZE_g2}, +- { FLASH_iSCSI_BACKUP_IMAGE_START_g2, IMG_TYPE_ISCSI_BACKUP, +- FLASH_IMAGE_MAX_SIZE_g2}, +- { FLASH_FCoE_PRIMARY_IMAGE_START_g2, IMG_TYPE_FCOE_FW_ACTIVE, +- FLASH_IMAGE_MAX_SIZE_g2}, +- { FLASH_FCoE_BACKUP_IMAGE_START_g2, IMG_TYPE_FCOE_FW_BACKUP, +- FLASH_IMAGE_MAX_SIZE_g2} ++ ++ struct flash_comp gen2_flash_types[] = { ++ { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, OPTYPE_ISCSI_ACTIVE, ++ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_iSCSI}, ++ { FLASH_REDBOOT_START_g2, OPTYPE_REDBOOT, ++ FLASH_REDBOOT_IMAGE_MAX_SIZE_g2, IMAGE_BOOT_CODE}, ++ { FLASH_iSCSI_BIOS_START_g2, OPTYPE_BIOS, ++ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_ISCSI}, ++ { FLASH_PXE_BIOS_START_g2, OPTYPE_PXE_BIOS, ++ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_PXE}, ++ { FLASH_FCoE_BIOS_START_g2, OPTYPE_FCOE_BIOS, ++ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_FCoE}, ++ { FLASH_iSCSI_BACKUP_IMAGE_START_g2, OPTYPE_ISCSI_BACKUP, ++ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_iSCSI}, ++ { FLASH_FCoE_PRIMARY_IMAGE_START_g2, OPTYPE_FCOE_FW_ACTIVE, ++ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_FCoE}, ++ { FLASH_FCoE_BACKUP_IMAGE_START_g2, OPTYPE_FCOE_FW_BACKUP, ++ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_FCoE} + }; + + if (adapter->generation == BE_GEN3) { +@@ -2847,22 +2892,37 @@ static int be_flash_data(struct be_adapter *adapter, + filehdr_size = sizeof(struct flash_file_hdr_g2); + num_comp = ARRAY_SIZE(gen2_flash_types); + } ++ /* Get flash section info*/ ++ fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); ++ if (!fsec) { ++ dev_err(&adapter->pdev->dev, ++ "Invalid Cookie. UFI corrupted ?\n"); ++ return -1; ++ } + for (i = 0; i < num_comp; i++) { +- if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) && +- memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) ++ if (!is_comp_in_ufi(adapter, fsec, pflashcomp[i].img_type)) + continue; +- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW) { ++ ++ if ((pflashcomp[i].optype == OPTYPE_NCSI_FW) && ++ memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) ++ continue; ++ ++ if (pflashcomp[i].optype == OPTYPE_PHY_FW) { + if (!phy_flashing_required(adapter)) + continue; + } +- if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) && +- (!be_flash_redboot(adapter, fw->data, +- pflashcomp[i].offset, pflashcomp[i].size, filehdr_size + +- (num_of_images * sizeof(struct image_hdr))))) ++ ++ hdr_size = filehdr_size + ++ (num_of_images * sizeof(struct image_hdr)); ++ ++ if ((pflashcomp[i].optype == OPTYPE_REDBOOT) && ++ (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset, ++ pflashcomp[i].size, hdr_size))) + continue; ++ ++ /* Flash the component */ + p = fw->data; +- p += filehdr_size + pflashcomp[i].offset +- + (num_of_images * sizeof(struct image_hdr)); ++ p += filehdr_size + pflashcomp[i].offset + img_hdrs_size; + if (p + pflashcomp[i].size > fw->data + fw->size) + return -1; + total_bytes = pflashcomp[i].size; +@@ -2873,12 +2933,12 @@ static int be_flash_data(struct be_adapter *adapter, + num_bytes = total_bytes; + total_bytes -= num_bytes; + if (!total_bytes) { +- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW) ++ if (pflashcomp[i].optype == OPTYPE_PHY_FW) + flash_op = FLASHROM_OPER_PHY_FLASH; + else + flash_op = FLASHROM_OPER_FLASH; + } else { +- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW) ++ if (pflashcomp[i].optype == OPTYPE_PHY_FW) + flash_op = FLASHROM_OPER_PHY_SAVE; + else + flash_op = FLASHROM_OPER_SAVE; +@@ -2890,7 +2950,7 @@ static int be_flash_data(struct be_adapter *adapter, + if (status) { + if ((status == ILLEGAL_IOCTL_REQ) && + (pflashcomp[i].optype == +- IMG_TYPE_PHY_FW)) ++ OPTYPE_PHY_FW)) + break; + dev_err(&adapter->pdev->dev, + "cmd to write to flash rom failed.\n"); +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0051-be2net-Ignore-status-of-some-ioctls-during-driver-lo.patch b/debian/patches/features/all/be2net/0051-be2net-Ignore-status-of-some-ioctls-during-driver-lo.patch new file mode 100644 index 000000000..c80cab68c --- /dev/null +++ b/debian/patches/features/all/be2net/0051-be2net-Ignore-status-of-some-ioctls-during-driver-lo.patch @@ -0,0 +1,49 @@ +From: Ajit Khaparde +Date: Thu, 26 Apr 2012 15:42:31 +0000 +Subject: [PATCH 51/58] be2net: Ignore status of some ioctls during driver + load + +commit ddc3f5cbaf1ddea122ec1d51c1cce97482b4d0c2 upstream. + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 17 ++++------------- + 1 file changed, 4 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 730fb1b..9effea4 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -2696,24 +2696,15 @@ static int be_setup(struct be_adapter *adapter) + + be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL); + +- status = be_vid_config(adapter, false, 0); +- if (status) +- goto err; ++ be_vid_config(adapter, false, 0); + + be_set_rx_mode(adapter->netdev); + +- status = be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc); +- /* For Lancer: It is legal for this cmd to fail on VF */ +- if (status && (be_physfn(adapter) || !lancer_chip(adapter))) +- goto err; ++ be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc); + +- if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc) { +- status = be_cmd_set_flow_control(adapter, adapter->tx_fc, ++ if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc) ++ be_cmd_set_flow_control(adapter, adapter->tx_fc, + adapter->rx_fc); +- /* For Lancer: It is legal for this cmd to fail on VF */ +- if (status && (be_physfn(adapter) || !lancer_chip(adapter))) +- goto err; +- } + + pcie_set_readrq(adapter->pdev, 4096); + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0052-be2net-fix-speed-displayed-by-ethtool-on-certain-SKU.patch b/debian/patches/features/all/be2net/0052-be2net-fix-speed-displayed-by-ethtool-on-certain-SKU.patch new file mode 100644 index 000000000..7be6beee2 --- /dev/null +++ b/debian/patches/features/all/be2net/0052-be2net-fix-speed-displayed-by-ethtool-on-certain-SKU.patch @@ -0,0 +1,30 @@ +From: Ajit Khaparde +Date: Thu, 26 Apr 2012 15:42:39 +0000 +Subject: [PATCH 52/58] be2net: fix speed displayed by ethtool on certain SKUs + +commit 2a89611a051cdcfcf4a7ae21d18eef64fab517b4 upstream. + +logical speed returned by link_status_query needs to be multiplied by 10. + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_ethtool.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index 9d71bad..b3b5fae 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -557,7 +557,7 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + if (!status) + be_link_status_update(adapter, link_status); + if (link_speed) +- et_speed = link_speed; ++ et_speed = link_speed * 10; + else + et_speed = convert_to_et_speed(port_speed); + } else { +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0053-be2net-update-the-driver-version.patch b/debian/patches/features/all/be2net/0053-be2net-update-the-driver-version.patch new file mode 100644 index 000000000..d59371e45 --- /dev/null +++ b/debian/patches/features/all/be2net/0053-be2net-update-the-driver-version.patch @@ -0,0 +1,28 @@ +From: Ajit Khaparde +Date: Thu, 26 Apr 2012 15:42:46 +0000 +Subject: [PATCH 53/58] be2net: update the driver version + +commit 06b0ab373df74f7916282b452b35d6389a605b8a upstream. + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index 4bc18ef..c3ee910 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -33,7 +33,7 @@ + + #include "be_hw.h" + +-#define DRV_VER "4.2.116u" ++#define DRV_VER "4.2.220u" + #define DRV_NAME "be2net" + #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" + #define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0054-be2net-Fix-to-not-set-link-speed-for-disabled-functi.patch b/debian/patches/features/all/be2net/0054-be2net-Fix-to-not-set-link-speed-for-disabled-functi.patch new file mode 100644 index 000000000..0a3677df4 --- /dev/null +++ b/debian/patches/features/all/be2net/0054-be2net-Fix-to-not-set-link-speed-for-disabled-functi.patch @@ -0,0 +1,33 @@ +From: Somnath Kotur +Date: Wed, 2 May 2012 03:40:16 +0000 +Subject: [PATCH 54/58] be2net: Fix to not set link speed for disabled + functions of a UMC card + +commit 22ca7a6e9a68a7e0c149b22ebed9dcd106245bb7 upstream. + +This renders the interface view somewhat inconsistent from the Host OS POV +considering the rest of the interfaces are showing their respective speeds +based on the bandwidth assigned to them. + +Signed-off-by: Somnath Kotur +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_ethtool.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index b3b5fae..1763836 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -558,7 +558,7 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + be_link_status_update(adapter, link_status); + if (link_speed) + et_speed = link_speed * 10; +- else ++ else if (link_status) + et_speed = convert_to_et_speed(port_speed); + } else { + et_speed = adapter->phy.forced_port_speed; +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0055-be2net-Fix-to-apply-duplex-value-as-unknown-when-lin.patch b/debian/patches/features/all/be2net/0055-be2net-Fix-to-apply-duplex-value-as-unknown-when-lin.patch new file mode 100644 index 000000000..3e3774c6b --- /dev/null +++ b/debian/patches/features/all/be2net/0055-be2net-Fix-to-apply-duplex-value-as-unknown-when-lin.patch @@ -0,0 +1,31 @@ +From: Somnath Kotur +Date: Wed, 2 May 2012 03:40:32 +0000 +Subject: [PATCH 55/58] be2net: Fix to apply duplex value as unknown when link + is down. + +commit 682256dbef8e827385cf214f3ada8b62f6c227ed upstream. + +Suggested-by: Ben Hutchings +Signed-off-by: Sarveshwar Bandi +Signed-off-by: Somnath Kotur +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_ethtool.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c +index 1763836..730e96a 100644 +--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c ++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c +@@ -618,7 +618,7 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + ecmd->supported = adapter->phy.supported; + } + +- ecmd->duplex = DUPLEX_FULL; ++ ecmd->duplex = netif_carrier_ok(netdev) ? DUPLEX_FULL : DUPLEX_UNKNOWN; + ecmd->phy_address = adapter->port_num; + + return 0; +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0056-be2net-Record-receive-queue-index-in-skb-to-aid-RPS.patch b/debian/patches/features/all/be2net/0056-be2net-Record-receive-queue-index-in-skb-to-aid-RPS.patch new file mode 100644 index 000000000..4024f1f3d --- /dev/null +++ b/debian/patches/features/all/be2net/0056-be2net-Record-receive-queue-index-in-skb-to-aid-RPS.patch @@ -0,0 +1,36 @@ +From: Somnath Kotur +Date: Wed, 2 May 2012 03:40:49 +0000 +Subject: [PATCH 56/58] be2net: Record receive queue index in skb to aid RPS. + +commit aaa6daec586cd39a6cd44b3d0ab91a84b0e3d53a upstream. + +Signed-off-by: Sarveshwar Bandi +Signed-off-by: Somnath Kotur +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 9effea4..0dd4b88 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1251,6 +1251,7 @@ static void be_rx_compl_process(struct be_rx_obj *rxo, + skb_checksum_none_assert(skb); + + skb->protocol = eth_type_trans(skb, netdev); ++ skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]); + if (netdev->features & NETIF_F_RXHASH) + skb->rxhash = rxcp->rss_hash; + +@@ -1307,6 +1308,7 @@ void be_rx_compl_process_gro(struct be_rx_obj *rxo, struct napi_struct *napi, + skb->len = rxcp->pkt_size; + skb->data_len = rxcp->pkt_size; + skb->ip_summed = CHECKSUM_UNNECESSARY; ++ skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]); + if (adapter->netdev->features & NETIF_F_RXHASH) + skb->rxhash = rxcp->rss_hash; + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0057-be2net-Fix-EEH-error-reset-before-a-flash-dump-compl.patch b/debian/patches/features/all/be2net/0057-be2net-Fix-EEH-error-reset-before-a-flash-dump-compl.patch new file mode 100644 index 000000000..51e6a13f3 --- /dev/null +++ b/debian/patches/features/all/be2net/0057-be2net-Fix-EEH-error-reset-before-a-flash-dump-compl.patch @@ -0,0 +1,37 @@ +From: Somnath Kotur +Date: Wed, 2 May 2012 03:41:01 +0000 +Subject: [PATCH 57/58] be2net: Fix EEH error reset before a flash dump + completes + +commit eeb7fc7bc095546b21188e8e076a59bce73f9ca6 upstream. + +An EEH error can cause the FW to trigger a flash debug dump. +Resetting the card while flash dump is in progress can cause it not to recover. +Wait for it to finish before letting EEH flow to reset the card. + +Signed-off-by: Sathya Perla +Signed-off-by: Somnath Kotur +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be_main.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 0dd4b88..3492dc8 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -3813,6 +3813,11 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, + + pci_disable_device(pdev); + ++ /* The error could cause the FW to trigger a flash debug dump. ++ * Resetting the card while flash dump is in progress ++ * can cause it not to recover; wait for it to finish ++ */ ++ ssleep(30); + return PCI_ERS_RESULT_NEED_RESET; + } + +-- +1.7.10 + diff --git a/debian/patches/features/all/be2net/0058-be2net-avoid-disabling-sriov-while-VFs-are-assigned.patch b/debian/patches/features/all/be2net/0058-be2net-avoid-disabling-sriov-while-VFs-are-assigned.patch new file mode 100644 index 000000000..841e66a8e --- /dev/null +++ b/debian/patches/features/all/be2net/0058-be2net-avoid-disabling-sriov-while-VFs-are-assigned.patch @@ -0,0 +1,473 @@ +From: Sathya Perla +Date: Tue, 8 May 2012 19:41:24 +0000 +Subject: [PATCH 58/58] be2net: avoid disabling sriov while VFs are assigned + +commit 39f1d94d300a58eb3e9b851d077cada4e2fa9d46 upstream. + +Calling pci_disable_sriov() while VFs are assigned to VMs causes +kernel panic. This patch uses PCI_DEV_FLAGS_ASSIGNED bit state of the +VF's pci_dev to avoid this. Also, the unconditional function reset cmd +issued on a PF probe can delete the VF configuration for the +previously enabled VFs. A scratchpad register is now used to issue a +function reset only when needed (i.e., in a crash dump scenario.) + +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/emulex/benet/be.h | 22 +-- + drivers/net/ethernet/emulex/benet/be_hw.h | 2 + + drivers/net/ethernet/emulex/benet/be_main.c | 199 ++++++++++++++++----------- + 3 files changed, 134 insertions(+), 89 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index c3ee910..ecf1a81 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -313,6 +313,11 @@ struct be_vf_cfg { + u32 tx_rate; + }; + ++enum vf_state { ++ ENABLED = 0, ++ ASSIGNED = 1 ++}; ++ + #define BE_FLAGS_LINK_STATUS_INIT 1 + #define BE_FLAGS_WORKER_SCHEDULED (1 << 3) + #define BE_UC_PMAC_COUNT 30 +@@ -403,8 +408,9 @@ struct be_adapter { + u32 flash_status; + struct completion flash_compl; + +- u32 num_vfs; +- u8 is_virtfn; ++ u32 num_vfs; /* Number of VFs provisioned by PF driver */ ++ u32 dev_num_vfs; /* Number of VFs supported by HW */ ++ u8 virtfn; + struct be_vf_cfg *vf_cfg; + bool be3_native; + u32 sli_family; +@@ -417,8 +423,10 @@ struct be_adapter { + u32 uc_macs; /* Count of secondary UC MAC programmed */ + }; + +-#define be_physfn(adapter) (!adapter->is_virtfn) ++#define be_physfn(adapter) (!adapter->virtfn) + #define sriov_enabled(adapter) (adapter->num_vfs > 0) ++#define sriov_want(adapter) (adapter->dev_num_vfs && num_vfs && \ ++ be_physfn(adapter)) + #define for_all_vfs(adapter, vf_cfg, i) \ + for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \ + i++, vf_cfg++) +@@ -547,14 +555,6 @@ static inline u8 is_udp_pkt(struct sk_buff *skb) + return val; + } + +-static inline void be_check_sriov_fn_type(struct be_adapter *adapter) +-{ +- u32 sli_intf; +- +- pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); +- adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; +-} +- + static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac) + { + u32 addr; +diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h +index 0949aa6..f38b58c 100644 +--- a/drivers/net/ethernet/emulex/benet/be_hw.h ++++ b/drivers/net/ethernet/emulex/benet/be_hw.h +@@ -58,6 +58,8 @@ + + #define SLI_PORT_CONTROL_IP_MASK 0x08000000 + ++#define PCICFG_CUST_SCRATCHPAD_CSR 0x1EC ++ + /********* Memory BAR register ************/ + #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc + /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 3492dc8..910bae8 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1041,6 +1041,29 @@ static int be_set_vf_tx_rate(struct net_device *netdev, + return status; + } + ++static int be_find_vfs(struct be_adapter *adapter, int vf_state) ++{ ++ struct pci_dev *dev, *pdev = adapter->pdev; ++ int vfs = 0, assigned_vfs = 0, pos, vf_fn; ++ u16 offset, stride; ++ ++ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); ++ pci_read_config_word(pdev, pos + PCI_SRIOV_VF_OFFSET, &offset); ++ pci_read_config_word(pdev, pos + PCI_SRIOV_VF_STRIDE, &stride); ++ ++ dev = pci_get_device(pdev->vendor, PCI_ANY_ID, NULL); ++ while (dev) { ++ vf_fn = (pdev->devfn + offset + stride * vfs) & 0xFFFF; ++ if (dev->is_virtfn && dev->devfn == vf_fn) { ++ vfs++; ++ if (dev->dev_flags & PCI_DEV_FLAGS_ASSIGNED) ++ assigned_vfs++; ++ } ++ dev = pci_get_device(pdev->vendor, PCI_ANY_ID, dev); ++ } ++ return (vf_state == ASSIGNED) ? assigned_vfs : vfs; ++} ++ + static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo) + { + struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]); +@@ -1781,9 +1804,9 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) + + static int be_num_txqs_want(struct be_adapter *adapter) + { +- if (sriov_enabled(adapter) || be_is_mc(adapter) || +- lancer_chip(adapter) || !be_physfn(adapter) || +- adapter->generation == BE_GEN2) ++ if (sriov_want(adapter) || be_is_mc(adapter) || ++ lancer_chip(adapter) || !be_physfn(adapter) || ++ adapter->generation == BE_GEN2) + return 1; + else + return MAX_TX_QS; +@@ -2110,7 +2133,7 @@ static void be_msix_disable(struct be_adapter *adapter) + static uint be_num_rss_want(struct be_adapter *adapter) + { + if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && +- adapter->num_vfs == 0 && be_physfn(adapter) && ++ !sriov_want(adapter) && be_physfn(adapter) && + !be_is_mc(adapter)) + return (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; + else +@@ -2144,53 +2167,6 @@ done: + return; + } + +-static int be_sriov_enable(struct be_adapter *adapter) +-{ +- be_check_sriov_fn_type(adapter); +- +-#ifdef CONFIG_PCI_IOV +- if (be_physfn(adapter) && num_vfs) { +- int status, pos; +- u16 dev_vfs; +- +- pos = pci_find_ext_capability(adapter->pdev, +- PCI_EXT_CAP_ID_SRIOV); +- pci_read_config_word(adapter->pdev, +- pos + PCI_SRIOV_TOTAL_VF, &dev_vfs); +- +- adapter->num_vfs = min_t(u16, num_vfs, dev_vfs); +- if (adapter->num_vfs != num_vfs) +- dev_info(&adapter->pdev->dev, +- "Device supports %d VFs and not %d\n", +- adapter->num_vfs, num_vfs); +- +- status = pci_enable_sriov(adapter->pdev, adapter->num_vfs); +- if (status) +- adapter->num_vfs = 0; +- +- if (adapter->num_vfs) { +- adapter->vf_cfg = kcalloc(num_vfs, +- sizeof(struct be_vf_cfg), +- GFP_KERNEL); +- if (!adapter->vf_cfg) +- return -ENOMEM; +- } +- } +-#endif +- return 0; +-} +- +-static void be_sriov_disable(struct be_adapter *adapter) +-{ +-#ifdef CONFIG_PCI_IOV +- if (sriov_enabled(adapter)) { +- pci_disable_sriov(adapter->pdev); +- kfree(adapter->vf_cfg); +- adapter->num_vfs = 0; +- } +-#endif +-} +- + static inline int be_msix_vec_get(struct be_adapter *adapter, + struct be_eq_obj *eqo) + { +@@ -2492,6 +2468,11 @@ static void be_vf_clear(struct be_adapter *adapter) + struct be_vf_cfg *vf_cfg; + u32 vf; + ++ if (be_find_vfs(adapter, ASSIGNED)) { ++ dev_warn(&adapter->pdev->dev, "VFs are assigned to VMs\n"); ++ goto done; ++ } ++ + for_all_vfs(adapter, vf_cfg, vf) { + if (lancer_chip(adapter)) + be_cmd_set_mac_list(adapter, NULL, 0, vf + 1); +@@ -2501,6 +2482,10 @@ static void be_vf_clear(struct be_adapter *adapter) + + be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1); + } ++ pci_disable_sriov(adapter->pdev); ++done: ++ kfree(adapter->vf_cfg); ++ adapter->num_vfs = 0; + } + + static int be_clear(struct be_adapter *adapter) +@@ -2530,29 +2515,60 @@ static int be_clear(struct be_adapter *adapter) + be_cmd_fw_clean(adapter); + + be_msix_disable(adapter); +- kfree(adapter->pmac_id); ++ pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 0); + return 0; + } + +-static void be_vf_setup_init(struct be_adapter *adapter) ++static int be_vf_setup_init(struct be_adapter *adapter) + { + struct be_vf_cfg *vf_cfg; + int vf; + ++ adapter->vf_cfg = kcalloc(adapter->num_vfs, sizeof(*vf_cfg), ++ GFP_KERNEL); ++ if (!adapter->vf_cfg) ++ return -ENOMEM; ++ + for_all_vfs(adapter, vf_cfg, vf) { + vf_cfg->if_handle = -1; + vf_cfg->pmac_id = -1; + } ++ return 0; + } + + static int be_vf_setup(struct be_adapter *adapter) + { + struct be_vf_cfg *vf_cfg; ++ struct device *dev = &adapter->pdev->dev; + u32 cap_flags, en_flags, vf; + u16 def_vlan, lnk_speed; +- int status; ++ int status, enabled_vfs; ++ ++ enabled_vfs = be_find_vfs(adapter, ENABLED); ++ if (enabled_vfs) { ++ dev_warn(dev, "%d VFs are already enabled\n", enabled_vfs); ++ dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs); ++ return 0; ++ } + +- be_vf_setup_init(adapter); ++ if (num_vfs > adapter->dev_num_vfs) { ++ dev_warn(dev, "Device supports %d VFs and not %d\n", ++ adapter->dev_num_vfs, num_vfs); ++ num_vfs = adapter->dev_num_vfs; ++ } ++ ++ status = pci_enable_sriov(adapter->pdev, num_vfs); ++ if (!status) { ++ adapter->num_vfs = num_vfs; ++ } else { ++ /* Platform doesn't support SRIOV though device supports it */ ++ dev_warn(dev, "SRIOV enable failed\n"); ++ return 0; ++ } ++ ++ status = be_vf_setup_init(adapter); ++ if (status) ++ goto err; + + cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MULTICAST; +@@ -2563,9 +2579,11 @@ static int be_vf_setup(struct be_adapter *adapter) + goto err; + } + +- status = be_vf_eth_addr_config(adapter); +- if (status) +- goto err; ++ if (!enabled_vfs) { ++ status = be_vf_eth_addr_config(adapter); ++ if (status) ++ goto err; ++ } + + for_all_vfs(adapter, vf_cfg, vf) { + status = be_cmd_link_status_query(adapter, NULL, &lnk_speed, +@@ -2622,9 +2640,25 @@ do_none: + return status; + } + ++/* Routine to query per function resource limits */ ++static int be_get_config(struct be_adapter *adapter) ++{ ++ int pos; ++ u16 dev_num_vfs; ++ ++ pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV); ++ if (pos) { ++ pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF, ++ &dev_num_vfs); ++ adapter->dev_num_vfs = dev_num_vfs; ++ } ++ return 0; ++} ++ + static int be_setup(struct be_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; ++ struct device *dev = &adapter->pdev->dev; + u32 cap_flags, en_flags; + u32 tx_fc, rx_fc; + int status; +@@ -2632,6 +2666,8 @@ static int be_setup(struct be_adapter *adapter) + + be_setup_init(adapter); + ++ be_get_config(adapter); ++ + be_cmd_req_native_mode(adapter); + + be_msix_enable(adapter); +@@ -2710,10 +2746,11 @@ static int be_setup(struct be_adapter *adapter) + + pcie_set_readrq(adapter->pdev, 4096); + +- if (sriov_enabled(adapter)) { +- status = be_vf_setup(adapter); +- if (status) +- goto err; ++ if (be_physfn(adapter) && num_vfs) { ++ if (adapter->dev_num_vfs) ++ be_vf_setup(adapter); ++ else ++ dev_warn(dev, "device doesn't support SRIOV\n"); + } + + be_cmd_get_phy_info(adapter); +@@ -2723,6 +2760,7 @@ static int be_setup(struct be_adapter *adapter) + schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); + adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; + ++ pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 1); + return 0; + err: + be_clear(adapter); +@@ -3344,8 +3382,6 @@ static void __devexit be_remove(struct pci_dev *pdev) + + be_ctrl_cleanup(adapter); + +- be_sriov_disable(adapter); +- + pci_set_drvdata(pdev, NULL); + pci_release_regions(pdev); + pci_disable_device(pdev); +@@ -3359,7 +3395,7 @@ bool be_is_wol_supported(struct be_adapter *adapter) + !be_is_wol_excluded(adapter)) ? true : false; + } + +-static int be_get_config(struct be_adapter *adapter) ++static int be_get_initial_config(struct be_adapter *adapter) + { + int status; + +@@ -3402,7 +3438,7 @@ static int be_get_config(struct be_adapter *adapter) + return 0; + } + +-static int be_dev_family_check(struct be_adapter *adapter) ++static int be_dev_type_check(struct be_adapter *adapter) + { + struct pci_dev *pdev = adapter->pdev; + u32 sli_intf = 0, if_type; +@@ -3435,6 +3471,9 @@ static int be_dev_family_check(struct be_adapter *adapter) + default: + adapter->generation = 0; + } ++ ++ pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); ++ adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; + return 0; + } + +@@ -3578,6 +3617,14 @@ reschedule: + schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); + } + ++static bool be_reset_required(struct be_adapter *adapter) ++{ ++ u32 reg; ++ ++ pci_read_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, ®); ++ return reg; ++} ++ + static int __devinit be_probe(struct pci_dev *pdev, + const struct pci_device_id *pdev_id) + { +@@ -3603,7 +3650,7 @@ static int __devinit be_probe(struct pci_dev *pdev, + adapter->pdev = pdev; + pci_set_drvdata(pdev, adapter); + +- status = be_dev_family_check(adapter); ++ status = be_dev_type_check(adapter); + if (status) + goto free_netdev; + +@@ -3621,13 +3668,9 @@ static int __devinit be_probe(struct pci_dev *pdev, + } + } + +- status = be_sriov_enable(adapter); +- if (status) +- goto free_netdev; +- + status = be_ctrl_init(adapter); + if (status) +- goto disable_sriov; ++ goto free_netdev; + + if (lancer_chip(adapter)) { + status = lancer_wait_ready(adapter); +@@ -3654,9 +3697,11 @@ static int __devinit be_probe(struct pci_dev *pdev, + if (status) + goto ctrl_clean; + +- status = be_cmd_reset_function(adapter); +- if (status) +- goto ctrl_clean; ++ if (be_reset_required(adapter)) { ++ status = be_cmd_reset_function(adapter); ++ if (status) ++ goto ctrl_clean; ++ } + + /* The INTR bit may be set in the card when probed by a kdump kernel + * after a crash. +@@ -3668,7 +3713,7 @@ static int __devinit be_probe(struct pci_dev *pdev, + if (status) + goto ctrl_clean; + +- status = be_get_config(adapter); ++ status = be_get_initial_config(adapter); + if (status) + goto stats_clean; + +@@ -3697,8 +3742,6 @@ stats_clean: + be_stats_cleanup(adapter); + ctrl_clean: + be_ctrl_cleanup(adapter); +-disable_sriov: +- be_sriov_disable(adapter); + free_netdev: + free_netdev(netdev); + pci_set_drvdata(pdev, NULL); +-- +1.7.10 + diff --git a/debian/patches/series/base b/debian/patches/series/base index 63a90ccf1..f5300548d 100644 --- a/debian/patches/series/base +++ b/debian/patches/series/base @@ -232,3 +232,64 @@ + features/all/rt2x00-add-rt5372-chipset-support.patch + bugfix/all/acpi-battery-only-refresh-the-sysfs-files-when-pertinent.patch ++ bugfix/all/ethtool-null-terminate-filename-passed-to.patch + +# Update be2net driver to 3.5ish ++ features/all/be2net/0001-sweep-the-floors-and-convert-some-.get_drvinfo-routi.patch ++ features/all/be2net/0002-be2net-init-vf-_if_handle-vf_pmac_id-to-handle-failu.patch ++ features/all/be2net/0003-be2net-stop-checking-the-UE-registers-after-an-EEH-e.patch ++ features/all/be2net/0004-be2net-don-t-log-more-than-one-error-on-detecting-EE.patch ++ features/all/be2net/0005-be2net-stop-issuing-FW-cmds-if-any-cmd-times-out.patch ++ features/all/be2net/0006-be2net-Fix-TX-queue-create-for-Lancer.patch ++ features/all/be2net/0007-be2net-add-register-dump-feature-for-Lancer.patch ++ features/all/be2net/0008-be2net-Add-EEPROM-dump-feature-for-Lancer.patch ++ features/all/be2net/0009-be2net-Fix-VLAN-promiscous-mode-for-Lancer.patch ++ features/all/be2net/0010-be2net-Use-V1-query-link-status-command-for-lancer.patch ++ features/all/be2net/0011-be2net-Move-to-new-SR-IOV-implementation-in-Lancer.patch ++ features/all/be2net/0012-be2net-Fix-error-recovery-paths.patch ++ features/all/be2net/0013-be2net-Add-error-handling-for-Lancer.patch ++ features/all/be2net/0014-be2net-Use-new-hash-key.patch ++ features/all/be2net/0015-be2net-Fix-non-utilization-of-RX-queues.patch ++ features/all/be2net/0016-be2net-netpoll-support.patch ++ features/all/be2net/0017-be2net-update-some-counters-to-display-via-ethtool.patch ++ features/all/be2net/0018-be2net-workaround-to-fix-a-bug-in-BE.patch ++ features/all/be2net/0019-be2net-fix-ethtool-ringparam-reporting.patch ++ features/all/be2net/0020-be2net-refactor-cleanup-vf-configuration-code.patch ++ features/all/be2net/0021-be2net-Add-support-for-Skyhawk-cards.patch ++ features/all/be2net/0022-be2net-Fix-INTx-processing-for-Lancer.patch ++ features/all/be2net/0023-be2net-fix-be_vlan_add-rem_vid.patch ++ features/all/be2net/0024-be2net-fix-range-check-for-set_qos-for-a-VF.patch ++ features/all/be2net/0025-be2net-query-link-status-in-be_open.patch ++ features/all/be2net/0026-netdev-make-net_device_ops-const.patch ++ features/all/be2net/0027-be2net-create-RSS-rings-even-in-multi-channel-config.patch ++ features/all/be2net/0028-be2net-allocate-more-headroom-in-incoming-skbs.patch ++ features/all/be2net/0029-be2net-add-descriptions-for-stat-counters-reported-v.patch ++ features/all/be2net/0030-be2net-Fix-link-status-query-command.patch ++ features/all/be2net/0031-be2net-Use-new-implementation-of-get-mac-list-comman.patch ++ features/all/be2net/0032-be2net-event-queue-re-design.patch ++ features/all/be2net/0033-be2net-cancel-be_worker-during-EEH-recovery.patch ++ features/all/be2net/0034-be2net-fix-tx-completion-cleanup.patch ++ features/all/be2net/0035-be2net-reset-queue-address-after-freeing.patch ++ features/all/be2net/0036-be2net-enable-RSS-for-ipv6-pkts.patch ++ features/all/be2net/0037-be2net-update-driver-version.patch ++ features/all/be2net/0038-be2net-Remove-unused-OFFSET_IN_PAGE-macro.patch ++ features/all/be2net/0039-be2net-enable-WOL-by-default-if-h-w-supports-it.patch ++ features/all/be2net/0040-be2net-Program-secondary-UC-MAC-address-into-MAC-fil.patch ++ features/all/be2net/0041-be2net-Fix-number-of-vlan-slots-in-flex-mode.patch ++ features/all/be2net/0042-be2net-fix-programming-of-VLAN-tags-for-VF.patch ++ features/all/be2net/0043-be2net-fix-ethtool-get-settings.patch ++ features/all/be2net/0044-be2net-Fix-VLAN-multicast-packet-reception.patch ++ features/all/be2net/0045-be2net-Fix-FW-download-in-Lancer.patch ++ features/all/be2net/0046-be2net-Fix-ethtool-self-test-for-Lancer.patch ++ features/all/be2net/0047-be2net-Fix-traffic-stall-INTx-mode.patch ++ features/all/be2net/0048-be2net-Fix-Lancer-statistics.patch ++ features/all/be2net/0049-be2net-Fix-wrong-status-getting-returned-for-MCC-com.patch ++ features/all/be2net/0050-be2net-Fix-FW-download-for-BE.patch ++ features/all/be2net/0051-be2net-Ignore-status-of-some-ioctls-during-driver-lo.patch ++ features/all/be2net/0052-be2net-fix-speed-displayed-by-ethtool-on-certain-SKU.patch ++ features/all/be2net/0053-be2net-update-the-driver-version.patch ++ features/all/be2net/0054-be2net-Fix-to-not-set-link-speed-for-disabled-functi.patch ++ features/all/be2net/0055-be2net-Fix-to-apply-duplex-value-as-unknown-when-lin.patch ++ features/all/be2net/0056-be2net-Record-receive-queue-index-in-skb-to-aid-RPS.patch ++ features/all/be2net/0057-be2net-Fix-EEH-error-reset-before-a-flash-dump-compl.patch ++ features/all/be2net/0058-be2net-avoid-disabling-sriov-while-VFs-are-assigned.patch