Commit b2a6c326 authored by David S. Miller's avatar David S. Miller

Merge branch 'be2net'

Sathya Perla says:

====================
be2net: patch-set

The following patch-set has two new feature additions, and a few
minor fixes and cleanups.
Pls consider applying to the net-next tree. Thanks.

v2 changes:
        a) dropped the "don't enable pause by default" patch
        b) described how the "spoof check" works in patch 1's commit log
	c) I had to update our email addresses from "@emulex" to
	   "@avagotech". I'll send a separate patch updating the
	   maintainers

Patch 1 adds support for the "spoofchk" knob for VFs.
When it is enabled, "spoof checking" is done for both MAC-address
and VLAN. For each VF, the HW ensures that the source MAC address
(or vlan) of every outgoing packet of the VF exists in the MAC-list
(or vlan-list) configured for RX filtering for that VF.
If not, the packet is dropped and an error is reported to the driver
in the TX completion.

Patch 2 improves interrupt moderation on Skyhawk-R chip by using
the EQ-DB mechanism to set a "re-arm to interrupt" delay. Currently
interrupt moderation is adjusted by calculating and configuring an
EQ-delay every second. This is done via a FW-cmd. This patch uses
the EQ_DB facility to calculate and set the interrupt delay every 1ms.
This helps moderating interrupts better when the traffic is bursty.

Patch 3 adds L3/L4 error accounting to BE3 VFs, by passing L3/4 error
packets to the network stack.

Patch 4 adds an extra FW-cmd error value check in the driver to identify
an "out of vlan filters" scenario.

Patch 5 stops enabling pause by default as this setting fails in
some HW-configs where priority pause is enabled in FW. If the user
tries to do the same, an appropriate error is returned via ethtool.

Patch 5 posts the full RXQ in be_open() to prevent packet drops due to
bursty traffic when the interface is enabled.

Patch 6 refactors the be_check_ufi_compatibility() routine, that checks
to see if a UFI file meant for a lower rev of a chip is being flashed
on a higher rev, to make it simpler.

Patch 7 replaces the usage of !be_physfn() macro with be_virtfn()
that is already avialble in the driver.

Patch 8 updates the year in the copyright text to 2015.

Path 9 bumps up the driver version to 10.6.02.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1a676d2b 029e9330
/* /*
* Copyright (C) 2005 - 2014 Emulex * Copyright (C) 2005 - 2015 Emulex
* All rights reserved. * All rights reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include "be_hw.h" #include "be_hw.h"
#include "be_roce.h" #include "be_roce.h"
#define DRV_VER "10.6.0.1" #define DRV_VER "10.6.0.2"
#define DRV_NAME "be2net" #define DRV_NAME "be2net"
#define BE_NAME "Emulex BladeEngine2" #define BE_NAME "Emulex BladeEngine2"
#define BE3_NAME "Emulex BladeEngine3" #define BE3_NAME "Emulex BladeEngine3"
...@@ -366,6 +366,7 @@ struct be_vf_cfg { ...@@ -366,6 +366,7 @@ struct be_vf_cfg {
u32 tx_rate; u32 tx_rate;
u32 plink_tracking; u32 plink_tracking;
u32 privileges; u32 privileges;
bool spoofchk;
}; };
enum vf_state { enum vf_state {
...@@ -804,6 +805,7 @@ bool be_pause_supported(struct be_adapter *adapter); ...@@ -804,6 +805,7 @@ bool be_pause_supported(struct be_adapter *adapter);
u32 be_get_fw_log_level(struct be_adapter *adapter); u32 be_get_fw_log_level(struct be_adapter *adapter);
int be_update_queues(struct be_adapter *adapter); int be_update_queues(struct be_adapter *adapter);
int be_poll(struct napi_struct *napi, int budget); int be_poll(struct napi_struct *napi, int budget);
void be_eqd_update(struct be_adapter *adapter, bool force_update);
/* /*
* internal function to initialize-cleanup roce device. * internal function to initialize-cleanup roce device.
......
/* /*
* Copyright (C) 2005 - 2014 Emulex * Copyright (C) 2005 - 2015 Emulex
* All rights reserved. * All rights reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -140,6 +140,7 @@ static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status) ...@@ -140,6 +140,7 @@ static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status)
if (base_status == MCC_STATUS_NOT_SUPPORTED || if (base_status == MCC_STATUS_NOT_SUPPORTED ||
base_status == MCC_STATUS_ILLEGAL_REQUEST || base_status == MCC_STATUS_ILLEGAL_REQUEST ||
addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES || addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES ||
addl_status == MCC_ADDL_STATUS_INSUFFICIENT_VLANS ||
(opcode == OPCODE_COMMON_WRITE_FLASHROM && (opcode == OPCODE_COMMON_WRITE_FLASHROM &&
(base_status == MCC_STATUS_ILLEGAL_FIELD || (base_status == MCC_STATUS_ILLEGAL_FIELD ||
addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH))) addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH)))
...@@ -1457,7 +1458,7 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, ...@@ -1457,7 +1458,7 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
*if_handle = le32_to_cpu(resp->interface_id); *if_handle = le32_to_cpu(resp->interface_id);
/* Hack to retrieve VF's pmac-id on BE3 */ /* Hack to retrieve VF's pmac-id on BE3 */
if (BE3_chip(adapter) && !be_physfn(adapter)) if (BE3_chip(adapter) && be_virtfn(adapter))
adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id); adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id);
} }
return status; return status;
...@@ -3153,7 +3154,7 @@ int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom) ...@@ -3153,7 +3154,7 @@ int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom)
} }
int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
u32 domain, u16 intf_id, u16 hsw_mode) u32 domain, u16 intf_id, u16 hsw_mode, u8 spoofchk)
{ {
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
struct be_cmd_req_set_hsw_config *req; struct be_cmd_req_set_hsw_config *req;
...@@ -3189,6 +3190,14 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, ...@@ -3189,6 +3190,14 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
ctxt, hsw_mode); ctxt, hsw_mode);
} }
/* Enable/disable both mac and vlan spoof checking */
if (!BEx_chip(adapter) && spoofchk) {
AMAP_SET_BITS(struct amap_set_hsw_context, mac_spoofchk,
ctxt, spoofchk);
AMAP_SET_BITS(struct amap_set_hsw_context, vlan_spoofchk,
ctxt, spoofchk);
}
be_dws_cpu_to_le(req->context, sizeof(req->context)); be_dws_cpu_to_le(req->context, sizeof(req->context));
status = be_mcc_notify_wait(adapter); status = be_mcc_notify_wait(adapter);
...@@ -3199,7 +3208,7 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, ...@@ -3199,7 +3208,7 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
/* Get Hyper switch config */ /* Get Hyper switch config */
int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
u32 domain, u16 intf_id, u8 *mode) u32 domain, u16 intf_id, u8 *mode, bool *spoofchk)
{ {
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
struct be_cmd_req_get_hsw_config *req; struct be_cmd_req_get_hsw_config *req;
...@@ -3247,6 +3256,10 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, ...@@ -3247,6 +3256,10 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
if (mode) if (mode)
*mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context, *mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
port_fwd_type, &resp->context); port_fwd_type, &resp->context);
if (spoofchk)
*spoofchk =
AMAP_GET_BITS(struct amap_get_hsw_resp_context,
spoofchk, &resp->context);
} }
err: err:
...@@ -3258,7 +3271,7 @@ static bool be_is_wol_excluded(struct be_adapter *adapter) ...@@ -3258,7 +3271,7 @@ static bool be_is_wol_excluded(struct be_adapter *adapter)
{ {
struct pci_dev *pdev = adapter->pdev; struct pci_dev *pdev = adapter->pdev;
if (!be_physfn(adapter)) if (be_virtfn(adapter))
return true; return true;
switch (pdev->subsystem_device) { switch (pdev->subsystem_device) {
......
/* /*
* Copyright (C) 2005 - 2014 Emulex * Copyright (C) 2005 - 2015 Emulex
* All rights reserved. * All rights reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -65,7 +65,8 @@ enum mcc_base_status { ...@@ -65,7 +65,8 @@ enum mcc_base_status {
enum mcc_addl_status { enum mcc_addl_status {
MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES = 0x16, MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES = 0x16,
MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH = 0x4d, MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH = 0x4d,
MCC_ADDL_STATUS_TOO_MANY_INTERFACES = 0x4a MCC_ADDL_STATUS_TOO_MANY_INTERFACES = 0x4a,
MCC_ADDL_STATUS_INSUFFICIENT_VLANS = 0xab
}; };
#define CQE_BASE_STATUS_MASK 0xFFFF #define CQE_BASE_STATUS_MASK 0xFFFF
...@@ -1109,10 +1110,6 @@ struct be_cmd_req_query_fw_cfg { ...@@ -1109,10 +1110,6 @@ struct be_cmd_req_query_fw_cfg {
u32 rsvd[31]; u32 rsvd[31];
}; };
/* ASIC revisions */
#define ASIC_REV_B0 0x10
#define ASIC_REV_P2 0x11
struct be_cmd_resp_query_fw_cfg { struct be_cmd_resp_query_fw_cfg {
struct be_cmd_resp_hdr hdr; struct be_cmd_resp_hdr hdr;
u32 be_config_number; u32 be_config_number;
...@@ -1745,18 +1742,24 @@ struct be_cmd_req_set_mac_list { ...@@ -1745,18 +1742,24 @@ struct be_cmd_req_set_mac_list {
#define PORT_FWD_TYPE_VEPA 0x3 #define PORT_FWD_TYPE_VEPA 0x3
#define PORT_FWD_TYPE_VEB 0x2 #define PORT_FWD_TYPE_VEB 0x2
#define ENABLE_MAC_SPOOFCHK 0x2
#define DISABLE_MAC_SPOOFCHK 0x3
struct amap_set_hsw_context { struct amap_set_hsw_context {
u8 interface_id[16]; u8 interface_id[16];
u8 rsvd0[14]; u8 rsvd0[8];
u8 mac_spoofchk[2];
u8 rsvd1[4];
u8 pvid_valid; u8 pvid_valid;
u8 pport; u8 pport;
u8 rsvd1[6]; u8 rsvd2[6];
u8 port_fwd_type[3]; u8 port_fwd_type[3];
u8 rsvd2[7]; u8 rsvd3[5];
u8 vlan_spoofchk[2];
u8 pvid[16]; u8 pvid[16];
u8 rsvd3[32];
u8 rsvd4[32]; u8 rsvd4[32];
u8 rsvd5[32]; u8 rsvd5[32];
u8 rsvd6[32];
} __packed; } __packed;
struct be_cmd_req_set_hsw_config { struct be_cmd_req_set_hsw_config {
...@@ -1774,11 +1777,13 @@ struct amap_get_hsw_req_context { ...@@ -1774,11 +1777,13 @@ struct amap_get_hsw_req_context {
struct amap_get_hsw_resp_context { struct amap_get_hsw_resp_context {
u8 rsvd0[6]; u8 rsvd0[6];
u8 port_fwd_type[3]; u8 port_fwd_type[3];
u8 rsvd1[7]; u8 rsvd1[5];
u8 spoofchk;
u8 rsvd2;
u8 pvid[16]; u8 pvid[16];
u8 rsvd2[32];
u8 rsvd3[32]; u8 rsvd3[32];
u8 rsvd4[32]; u8 rsvd4[32];
u8 rsvd5[32];
} __packed; } __packed;
struct be_cmd_req_get_hsw_config { struct be_cmd_req_get_hsw_config {
...@@ -2334,9 +2339,9 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, u8 mac_count, ...@@ -2334,9 +2339,9 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, u8 mac_count,
u32 domain); u32 domain);
int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom); int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom);
int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, u32 domain, int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, u32 domain,
u16 intf_id, u16 hsw_mode); u16 intf_id, u16 hsw_mode, u8 spoofchk);
int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, u32 domain, int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, u32 domain,
u16 intf_id, u8 *mode); u16 intf_id, u8 *mode, bool *spoofchk);
int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter); int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter);
int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level); int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level);
int be_cmd_get_fw_log_level(struct be_adapter *adapter); int be_cmd_get_fw_log_level(struct be_adapter *adapter);
......
/* /*
* Copyright (C) 2005 - 2014 Emulex * Copyright (C) 2005 - 2015 Emulex
* All rights reserved. * All rights reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -368,6 +368,14 @@ static int be_set_coalesce(struct net_device *netdev, ...@@ -368,6 +368,14 @@ static int be_set_coalesce(struct net_device *netdev,
aic++; aic++;
} }
/* For Skyhawk, the EQD setting happens via EQ_DB when AIC is enabled.
* When AIC is disabled, persistently force set EQD value via the
* FW cmd, so that we don't have to calculate the delay multiplier
* encode value each time EQ_DB is rung
*/
if (!et->use_adaptive_rx_coalesce && skyhawk_chip(adapter))
be_eqd_update(adapter, true);
return 0; return 0;
} }
......
/* /*
* Copyright (C) 2005 - 2014 Emulex * Copyright (C) 2005 - 2015 Emulex
* All rights reserved. * All rights reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -132,6 +132,18 @@ ...@@ -132,6 +132,18 @@
#define DB_EQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ #define DB_EQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */
/* Rearm bit */ /* Rearm bit */
#define DB_EQ_REARM_SHIFT (29) /* bit 29 */ #define DB_EQ_REARM_SHIFT (29) /* bit 29 */
/* Rearm to interrupt delay encoding */
#define DB_EQ_R2I_DLY_SHIFT (30) /* bits 30 - 31 */
/* Rearm to interrupt (R2I) delay multiplier encoding represents 3 different
* values configured in CEV_REARM2IRPT_DLY_MULT_CSR register. This value is
* programmed by host driver while ringing an EQ doorbell(EQ_DB) if a delay
* between rearming the EQ and next interrupt on this EQ is desired.
*/
#define R2I_DLY_ENC_0 0 /* No delay */
#define R2I_DLY_ENC_1 1 /* maps to 160us EQ delay */
#define R2I_DLY_ENC_2 2 /* maps to 96us EQ delay */
#define R2I_DLY_ENC_3 3 /* maps to 48us EQ delay */
/********* Compl Q door bell *************/ /********* Compl Q door bell *************/
#define DB_CQ_OFFSET 0x120 #define DB_CQ_OFFSET 0x120
......
/* /*
* Copyright (C) 2005 - 2014 Emulex * Copyright (C) 2005 - 2015 Emulex
* All rights reserved. * All rights reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -211,7 +211,8 @@ static void be_txq_notify(struct be_adapter *adapter, struct be_tx_obj *txo, ...@@ -211,7 +211,8 @@ static void be_txq_notify(struct be_adapter *adapter, struct be_tx_obj *txo,
} }
static void be_eq_notify(struct be_adapter *adapter, u16 qid, static void be_eq_notify(struct be_adapter *adapter, u16 qid,
bool arm, bool clear_int, u16 num_popped) bool arm, bool clear_int, u16 num_popped,
u32 eq_delay_mult_enc)
{ {
u32 val = 0; u32 val = 0;
...@@ -227,6 +228,7 @@ static void be_eq_notify(struct be_adapter *adapter, u16 qid, ...@@ -227,6 +228,7 @@ static void be_eq_notify(struct be_adapter *adapter, u16 qid,
val |= 1 << DB_EQ_CLR_SHIFT; val |= 1 << DB_EQ_CLR_SHIFT;
val |= 1 << DB_EQ_EVNT_SHIFT; val |= 1 << DB_EQ_EVNT_SHIFT;
val |= num_popped << DB_EQ_NUM_POPPED_SHIFT; val |= num_popped << DB_EQ_NUM_POPPED_SHIFT;
val |= eq_delay_mult_enc << DB_EQ_R2I_DLY_SHIFT;
iowrite32(val, adapter->db + DB_EQ_OFFSET); iowrite32(val, adapter->db + DB_EQ_OFFSET);
} }
...@@ -1267,7 +1269,8 @@ static int be_vid_config(struct be_adapter *adapter) ...@@ -1267,7 +1269,8 @@ static int be_vid_config(struct be_adapter *adapter)
if (status) { if (status) {
dev_err(dev, "Setting HW VLAN filtering failed\n"); dev_err(dev, "Setting HW VLAN filtering failed\n");
/* Set to VLAN promisc mode as setting VLAN filter failed */ /* Set to VLAN promisc mode as setting VLAN filter failed */
if (addl_status(status) == if (addl_status(status) == MCC_ADDL_STATUS_INSUFFICIENT_VLANS ||
addl_status(status) ==
MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES) MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES)
return be_set_vlan_promisc(adapter); return be_set_vlan_promisc(adapter);
} else if (adapter->if_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) { } else if (adapter->if_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) {
...@@ -1468,6 +1471,7 @@ static int be_get_vf_config(struct net_device *netdev, int vf, ...@@ -1468,6 +1471,7 @@ static int be_get_vf_config(struct net_device *netdev, int vf,
vi->qos = vf_cfg->vlan_tag >> VLAN_PRIO_SHIFT; vi->qos = vf_cfg->vlan_tag >> VLAN_PRIO_SHIFT;
memcpy(&vi->mac, vf_cfg->mac_addr, ETH_ALEN); memcpy(&vi->mac, vf_cfg->mac_addr, ETH_ALEN);
vi->linkstate = adapter->vf_cfg[vf].plink_tracking; vi->linkstate = adapter->vf_cfg[vf].plink_tracking;
vi->spoofchk = adapter->vf_cfg[vf].spoofchk;
return 0; return 0;
} }
...@@ -1480,7 +1484,7 @@ static int be_set_vf_tvt(struct be_adapter *adapter, int vf, u16 vlan) ...@@ -1480,7 +1484,7 @@ static int be_set_vf_tvt(struct be_adapter *adapter, int vf, u16 vlan)
int status; int status;
/* Enable Transparent VLAN Tagging */ /* Enable Transparent VLAN Tagging */
status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, vf_if_id, 0); status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, vf_if_id, 0, 0);
if (status) if (status)
return status; return status;
...@@ -1509,7 +1513,7 @@ static int be_clear_vf_tvt(struct be_adapter *adapter, int vf) ...@@ -1509,7 +1513,7 @@ static int be_clear_vf_tvt(struct be_adapter *adapter, int vf)
/* Reset Transparent VLAN Tagging. */ /* Reset Transparent VLAN Tagging. */
status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID, vf + 1, status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID, vf + 1,
vf_cfg->if_handle, 0); vf_cfg->if_handle, 0, 0);
if (status) if (status)
return status; return status;
...@@ -1644,6 +1648,39 @@ static int be_set_vf_link_state(struct net_device *netdev, int vf, ...@@ -1644,6 +1648,39 @@ static int be_set_vf_link_state(struct net_device *netdev, int vf,
return 0; return 0;
} }
static int be_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable)
{
struct be_adapter *adapter = netdev_priv(netdev);
struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
u8 spoofchk;
int status;
if (!sriov_enabled(adapter))
return -EPERM;
if (vf >= adapter->num_vfs)
return -EINVAL;
if (BEx_chip(adapter))
return -EOPNOTSUPP;
if (enable == vf_cfg->spoofchk)
return 0;
spoofchk = enable ? ENABLE_MAC_SPOOFCHK : DISABLE_MAC_SPOOFCHK;
status = be_cmd_set_hsw_config(adapter, 0, vf + 1, vf_cfg->if_handle,
0, spoofchk);
if (status) {
dev_err(&adapter->pdev->dev,
"Spoofchk change on VF %d failed: %#x\n", vf, status);
return be_cmd_status(status);
}
vf_cfg->spoofchk = enable;
return 0;
}
static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts, static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts,
ulong now) ulong now)
{ {
...@@ -1652,38 +1689,39 @@ static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts, ...@@ -1652,38 +1689,39 @@ static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts,
aic->jiffies = now; aic->jiffies = now;
} }
static void be_eqd_update(struct be_adapter *adapter) static int be_get_new_eqd(struct be_eq_obj *eqo)
{ {
struct be_set_eqd set_eqd[MAX_EVT_QS]; struct be_adapter *adapter = eqo->adapter;
int eqd, i, num = 0, start; int eqd, start;
struct be_aic_obj *aic; struct be_aic_obj *aic;
struct be_eq_obj *eqo;
struct be_rx_obj *rxo; struct be_rx_obj *rxo;
struct be_tx_obj *txo; struct be_tx_obj *txo;
u64 rx_pkts, tx_pkts; u64 rx_pkts = 0, tx_pkts = 0;
ulong now; ulong now;
u32 pps, delta; u32 pps, delta;
int i;
for_all_evt_queues(adapter, eqo, i) {
aic = &adapter->aic_obj[eqo->idx]; aic = &adapter->aic_obj[eqo->idx];
if (!aic->enable) { if (!aic->enable) {
if (aic->jiffies) if (aic->jiffies)
aic->jiffies = 0; aic->jiffies = 0;
eqd = aic->et_eqd; eqd = aic->et_eqd;
goto modify_eqd; return eqd;
} }
rxo = &adapter->rx_obj[eqo->idx]; for_all_rx_queues_on_eq(adapter, eqo, rxo, i) {
do { do {
start = u64_stats_fetch_begin_irq(&rxo->stats.sync); start = u64_stats_fetch_begin_irq(&rxo->stats.sync);
rx_pkts = rxo->stats.rx_pkts; rx_pkts += rxo->stats.rx_pkts;
} while (u64_stats_fetch_retry_irq(&rxo->stats.sync, start)); } while (u64_stats_fetch_retry_irq(&rxo->stats.sync, start));
}
txo = &adapter->tx_obj[eqo->idx]; for_all_tx_queues_on_eq(adapter, eqo, txo, i) {
do { do {
start = u64_stats_fetch_begin_irq(&txo->stats.sync); start = u64_stats_fetch_begin_irq(&txo->stats.sync);
tx_pkts = txo->stats.tx_reqs; tx_pkts += txo->stats.tx_reqs;
} while (u64_stats_fetch_retry_irq(&txo->stats.sync, start)); } while (u64_stats_fetch_retry_irq(&txo->stats.sync, start));
}
/* Skip, if wrapped around or first calculation */ /* Skip, if wrapped around or first calculation */
now = jiffies; now = jiffies;
...@@ -1691,10 +1729,13 @@ static void be_eqd_update(struct be_adapter *adapter) ...@@ -1691,10 +1729,13 @@ static void be_eqd_update(struct be_adapter *adapter)
rx_pkts < aic->rx_pkts_prev || rx_pkts < aic->rx_pkts_prev ||
tx_pkts < aic->tx_reqs_prev) { tx_pkts < aic->tx_reqs_prev) {
be_aic_update(aic, rx_pkts, tx_pkts, now); be_aic_update(aic, rx_pkts, tx_pkts, now);
continue; return aic->prev_eqd;
} }
delta = jiffies_to_msecs(now - aic->jiffies); delta = jiffies_to_msecs(now - aic->jiffies);
if (delta == 0)
return aic->prev_eqd;
pps = (((u32)(rx_pkts - aic->rx_pkts_prev) * 1000) / delta) + pps = (((u32)(rx_pkts - aic->rx_pkts_prev) * 1000) / delta) +
(((u32)(tx_pkts - aic->tx_reqs_prev) * 1000) / delta); (((u32)(tx_pkts - aic->tx_reqs_prev) * 1000) / delta);
eqd = (pps / 15000) << 2; eqd = (pps / 15000) << 2;
...@@ -1705,8 +1746,53 @@ static void be_eqd_update(struct be_adapter *adapter) ...@@ -1705,8 +1746,53 @@ static void be_eqd_update(struct be_adapter *adapter)
eqd = max_t(u32, eqd, aic->min_eqd); eqd = max_t(u32, eqd, aic->min_eqd);
be_aic_update(aic, rx_pkts, tx_pkts, now); be_aic_update(aic, rx_pkts, tx_pkts, now);
modify_eqd:
if (eqd != aic->prev_eqd) { return eqd;
}
/* For Skyhawk-R only */
static u32 be_get_eq_delay_mult_enc(struct be_eq_obj *eqo)
{
struct be_adapter *adapter = eqo->adapter;
struct be_aic_obj *aic = &adapter->aic_obj[eqo->idx];
ulong now = jiffies;
int eqd;
u32 mult_enc;
if (!aic->enable)
return 0;
if (time_before_eq(now, aic->jiffies) ||
jiffies_to_msecs(now - aic->jiffies) < 1)
eqd = aic->prev_eqd;
else
eqd = be_get_new_eqd(eqo);
if (eqd > 100)
mult_enc = R2I_DLY_ENC_1;
else if (eqd > 60)
mult_enc = R2I_DLY_ENC_2;
else if (eqd > 20)
mult_enc = R2I_DLY_ENC_3;
else
mult_enc = R2I_DLY_ENC_0;
aic->prev_eqd = eqd;
return mult_enc;
}
void be_eqd_update(struct be_adapter *adapter, bool force_update)
{
struct be_set_eqd set_eqd[MAX_EVT_QS];
struct be_aic_obj *aic;
struct be_eq_obj *eqo;
int i, num = 0, eqd;
for_all_evt_queues(adapter, eqo, i) {
aic = &adapter->aic_obj[eqo->idx];
eqd = be_get_new_eqd(eqo);
if (force_update || eqd != aic->prev_eqd) {
set_eqd[num].delay_multiplier = (eqd * 65)/100; set_eqd[num].delay_multiplier = (eqd * 65)/100;
set_eqd[num].eq_id = eqo->q.id; set_eqd[num].eq_id = eqo->q.id;
aic->prev_eqd = eqd; aic->prev_eqd = eqd;
...@@ -2214,7 +2300,7 @@ static void be_eq_clean(struct be_eq_obj *eqo) ...@@ -2214,7 +2300,7 @@ static void be_eq_clean(struct be_eq_obj *eqo)
{ {
int num = events_get(eqo); int num = events_get(eqo);
be_eq_notify(eqo->adapter, eqo->q.id, false, true, num); be_eq_notify(eqo->adapter, eqo->q.id, false, true, num, 0);
} }
static void be_rx_cq_clean(struct be_rx_obj *rxo) static void be_rx_cq_clean(struct be_rx_obj *rxo)
...@@ -2575,7 +2661,7 @@ static irqreturn_t be_intx(int irq, void *dev) ...@@ -2575,7 +2661,7 @@ static irqreturn_t be_intx(int irq, void *dev)
if (num_evts) if (num_evts)
eqo->spurious_intr = 0; eqo->spurious_intr = 0;
} }
be_eq_notify(adapter, eqo->q.id, false, true, num_evts); be_eq_notify(adapter, eqo->q.id, false, true, num_evts, 0);
/* Return IRQ_HANDLED only for the the first spurious intr /* Return IRQ_HANDLED only for the the first spurious intr
* after a valid intr to stop the kernel from branding * after a valid intr to stop the kernel from branding
...@@ -2591,7 +2677,7 @@ static irqreturn_t be_msix(int irq, void *dev) ...@@ -2591,7 +2677,7 @@ static irqreturn_t be_msix(int irq, void *dev)
{ {
struct be_eq_obj *eqo = dev; struct be_eq_obj *eqo = dev;
be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0); be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0, 0);
napi_schedule(&eqo->napi); napi_schedule(&eqo->napi);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -2840,6 +2926,7 @@ int be_poll(struct napi_struct *napi, int budget) ...@@ -2840,6 +2926,7 @@ int be_poll(struct napi_struct *napi, int budget)
int max_work = 0, work, i, num_evts; int max_work = 0, work, i, num_evts;
struct be_rx_obj *rxo; struct be_rx_obj *rxo;
struct be_tx_obj *txo; struct be_tx_obj *txo;
u32 mult_enc = 0;
num_evts = events_get(eqo); num_evts = events_get(eqo);
...@@ -2865,10 +2952,18 @@ int be_poll(struct napi_struct *napi, int budget) ...@@ -2865,10 +2952,18 @@ int be_poll(struct napi_struct *napi, int budget)
if (max_work < budget) { if (max_work < budget) {
napi_complete(napi); napi_complete(napi);
be_eq_notify(adapter, eqo->q.id, true, false, num_evts);
/* Skyhawk EQ_DB has a provision to set the rearm to interrupt
* delay via a delay multiplier encoding value
*/
if (skyhawk_chip(adapter))
mult_enc = be_get_eq_delay_mult_enc(eqo);
be_eq_notify(adapter, eqo->q.id, true, false, num_evts,
mult_enc);
} else { } else {
/* As we'll continue in polling mode, count and clear events */ /* As we'll continue in polling mode, count and clear events */
be_eq_notify(adapter, eqo->q.id, false, false, num_evts); be_eq_notify(adapter, eqo->q.id, false, false, num_evts, 0);
} }
return max_work; return max_work;
} }
...@@ -3017,7 +3112,7 @@ static int be_msix_enable(struct be_adapter *adapter) ...@@ -3017,7 +3112,7 @@ static int be_msix_enable(struct be_adapter *adapter)
dev_warn(dev, "MSIx enable failed\n"); dev_warn(dev, "MSIx enable failed\n");
/* INTx is not supported in VFs, so fail probe if enable_msix fails */ /* INTx is not supported in VFs, so fail probe if enable_msix fails */
if (!be_physfn(adapter)) if (be_virtfn(adapter))
return num_vec; return num_vec;
return 0; return 0;
} }
...@@ -3064,7 +3159,7 @@ static int be_irq_register(struct be_adapter *adapter) ...@@ -3064,7 +3159,7 @@ static int be_irq_register(struct be_adapter *adapter)
if (status == 0) if (status == 0)
goto done; goto done;
/* INTx is not supported for VF */ /* INTx is not supported for VF */
if (!be_physfn(adapter)) if (be_virtfn(adapter))
return status; return status;
} }
...@@ -3231,9 +3326,12 @@ static int be_rx_qs_create(struct be_adapter *adapter) ...@@ -3231,9 +3326,12 @@ static int be_rx_qs_create(struct be_adapter *adapter)
memcpy(rss->rss_hkey, rss_key, RSS_HASH_KEY_LEN); memcpy(rss->rss_hkey, rss_key, RSS_HASH_KEY_LEN);
/* First time posting */ /* Post 1 less than RXQ-len to avoid head being equal to tail,
* which is a queue empty condition
*/
for_all_rx_queues(adapter, rxo, i) for_all_rx_queues(adapter, rxo, i)
be_post_rx_frags(rxo, GFP_KERNEL, MAX_RX_POST); be_post_rx_frags(rxo, GFP_KERNEL, RX_Q_LEN - 1);
return 0; return 0;
} }
...@@ -3265,7 +3363,7 @@ static int be_open(struct net_device *netdev) ...@@ -3265,7 +3363,7 @@ static int be_open(struct net_device *netdev)
for_all_evt_queues(adapter, eqo, i) { for_all_evt_queues(adapter, eqo, i) {
napi_enable(&eqo->napi); napi_enable(&eqo->napi);
be_enable_busy_poll(eqo); be_enable_busy_poll(eqo);
be_eq_notify(adapter, eqo->q.id, true, true, 0); be_eq_notify(adapter, eqo->q.id, true, true, 0, 0);
} }
adapter->flags |= BE_FLAGS_NAPI_ENABLED; adapter->flags |= BE_FLAGS_NAPI_ENABLED;
...@@ -3565,7 +3663,7 @@ static int be_vfs_if_create(struct be_adapter *adapter) ...@@ -3565,7 +3663,7 @@ static int be_vfs_if_create(struct be_adapter *adapter)
/* If a FW profile exists, then cap_flags are updated */ /* If a FW profile exists, then cap_flags are updated */
cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
BE_IF_FLAGS_MULTICAST; BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS;
for_all_vfs(adapter, vf_cfg, vf) { for_all_vfs(adapter, vf_cfg, vf) {
if (!BE3_chip(adapter)) { if (!BE3_chip(adapter)) {
...@@ -3612,6 +3710,7 @@ static int be_vf_setup(struct be_adapter *adapter) ...@@ -3612,6 +3710,7 @@ static int be_vf_setup(struct be_adapter *adapter)
struct device *dev = &adapter->pdev->dev; struct device *dev = &adapter->pdev->dev;
struct be_vf_cfg *vf_cfg; struct be_vf_cfg *vf_cfg;
int status, old_vfs, vf; int status, old_vfs, vf;
bool spoofchk;
old_vfs = pci_num_vf(adapter->pdev); old_vfs = pci_num_vf(adapter->pdev);
...@@ -3659,6 +3758,12 @@ static int be_vf_setup(struct be_adapter *adapter) ...@@ -3659,6 +3758,12 @@ static int be_vf_setup(struct be_adapter *adapter)
if (!old_vfs) if (!old_vfs)
be_cmd_config_qos(adapter, 0, 0, vf + 1); be_cmd_config_qos(adapter, 0, 0, vf + 1);
status = be_cmd_get_hsw_config(adapter, NULL, vf + 1,
vf_cfg->if_handle, NULL,
&spoofchk);
if (!status)
vf_cfg->spoofchk = spoofchk;
if (!old_vfs) { if (!old_vfs) {
be_cmd_enable_vf(adapter, vf + 1); be_cmd_enable_vf(adapter, vf + 1);
be_cmd_set_logical_link_config(adapter, be_cmd_set_logical_link_config(adapter,
...@@ -3735,7 +3840,8 @@ static void BEx_get_resources(struct be_adapter *adapter, ...@@ -3735,7 +3840,8 @@ static void BEx_get_resources(struct be_adapter *adapter,
* *only* if it is RSS-capable. * *only* if it is RSS-capable.
*/ */
if (BE2_chip(adapter) || use_sriov || (adapter->port_num > 1) || if (BE2_chip(adapter) || use_sriov || (adapter->port_num > 1) ||
!be_physfn(adapter) || (be_is_mc(adapter) && be_virtfn(adapter) ||
(be_is_mc(adapter) &&
!(adapter->function_caps & BE_FUNCTION_CAPS_RSS))) { !(adapter->function_caps & BE_FUNCTION_CAPS_RSS))) {
res->max_tx_qs = 1; res->max_tx_qs = 1;
} else if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) { } else if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) {
...@@ -4184,7 +4290,7 @@ static void be_netpoll(struct net_device *netdev) ...@@ -4184,7 +4290,7 @@ static void be_netpoll(struct net_device *netdev)
int i; int i;
for_all_evt_queues(adapter, eqo, i) { for_all_evt_queues(adapter, eqo, i) {
be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0); be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0, 0);
napi_schedule(&eqo->napi); napi_schedule(&eqo->napi);
} }
} }
...@@ -4668,13 +4774,10 @@ static int lancer_fw_download(struct be_adapter *adapter, ...@@ -4668,13 +4774,10 @@ static int lancer_fw_download(struct be_adapter *adapter,
return 0; return 0;
} }
#define BE2_UFI 2 /* Check if the flash image file is compatible with the adapter that
#define BE3_UFI 3 * is being flashed.
#define BE3R_UFI 10 */
#define SH_UFI 4 static bool be_check_ufi_compatibility(struct be_adapter *adapter,
#define SH_P2_UFI 11
static int be_get_ufi_type(struct be_adapter *adapter,
struct flash_file_hdr_g3 *fhdr) struct flash_file_hdr_g3 *fhdr)
{ {
if (!fhdr) { if (!fhdr) {
...@@ -4687,43 +4790,22 @@ static int be_get_ufi_type(struct be_adapter *adapter, ...@@ -4687,43 +4790,22 @@ static int be_get_ufi_type(struct be_adapter *adapter,
*/ */
switch (fhdr->build[0]) { switch (fhdr->build[0]) {
case BLD_STR_UFI_TYPE_SH: case BLD_STR_UFI_TYPE_SH:
return (fhdr->asic_type_rev == ASIC_REV_P2) ? SH_P2_UFI : if (!skyhawk_chip(adapter))
SH_UFI; return false;
break;
case BLD_STR_UFI_TYPE_BE3: case BLD_STR_UFI_TYPE_BE3:
return (fhdr->asic_type_rev == ASIC_REV_B0) ? BE3R_UFI : if (!BE3_chip(adapter))
BE3_UFI; return false;
break;
case BLD_STR_UFI_TYPE_BE2: case BLD_STR_UFI_TYPE_BE2:
return BE2_UFI; if (!BE2_chip(adapter))
default: return false;
return -1; break;
}
}
/* Check if the flash image file is compatible with the adapter that
* is being flashed.
* BE3 chips with asic-rev B0 must be flashed only with BE3R_UFI type.
* Skyhawk chips with asic-rev P2 must be flashed only with SH_P2_UFI type.
*/
static bool be_check_ufi_compatibility(struct be_adapter *adapter,
struct flash_file_hdr_g3 *fhdr)
{
int ufi_type = be_get_ufi_type(adapter, fhdr);
switch (ufi_type) {
case SH_P2_UFI:
return skyhawk_chip(adapter);
case SH_UFI:
return (skyhawk_chip(adapter) &&
adapter->asic_rev < ASIC_REV_P2);
case BE3R_UFI:
return BE3_chip(adapter);
case BE3_UFI:
return (BE3_chip(adapter) && adapter->asic_rev < ASIC_REV_B0);
case BE2_UFI:
return BE2_chip(adapter);
default: default:
return false; return false;
} }
return (fhdr->asic_type_rev >= adapter->asic_rev);
} }
static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
...@@ -4831,7 +4913,7 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, ...@@ -4831,7 +4913,7 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
adapter->if_handle, adapter->if_handle,
mode == BRIDGE_MODE_VEPA ? mode == BRIDGE_MODE_VEPA ?
PORT_FWD_TYPE_VEPA : PORT_FWD_TYPE_VEPA :
PORT_FWD_TYPE_VEB); PORT_FWD_TYPE_VEB, 0);
if (status) if (status)
goto err; goto err;
...@@ -4863,7 +4945,8 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, ...@@ -4863,7 +4945,8 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
hsw_mode = PORT_FWD_TYPE_VEB; hsw_mode = PORT_FWD_TYPE_VEB;
} else { } else {
status = be_cmd_get_hsw_config(adapter, NULL, 0, status = be_cmd_get_hsw_config(adapter, NULL, 0,
adapter->if_handle, &hsw_mode); adapter->if_handle, &hsw_mode,
NULL);
if (status) if (status)
return 0; return 0;
} }
...@@ -5016,6 +5099,7 @@ static const struct net_device_ops be_netdev_ops = { ...@@ -5016,6 +5099,7 @@ static const struct net_device_ops be_netdev_ops = {
.ndo_set_vf_rate = be_set_vf_tx_rate, .ndo_set_vf_rate = be_set_vf_tx_rate,
.ndo_get_vf_config = be_get_vf_config, .ndo_get_vf_config = be_get_vf_config,
.ndo_set_vf_link_state = be_set_vf_link_state, .ndo_set_vf_link_state = be_set_vf_link_state,
.ndo_set_vf_spoofchk = be_set_vf_spoofchk,
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = be_netpoll, .ndo_poll_controller = be_netpoll,
#endif #endif
...@@ -5184,7 +5268,9 @@ static void be_worker(struct work_struct *work) ...@@ -5184,7 +5268,9 @@ static void be_worker(struct work_struct *work)
be_post_rx_frags(rxo, GFP_KERNEL, MAX_RX_POST); be_post_rx_frags(rxo, GFP_KERNEL, MAX_RX_POST);
} }
be_eqd_update(adapter); /* EQ-delay update for Skyhawk is done while notifying EQ */
if (!skyhawk_chip(adapter))
be_eqd_update(adapter, false);
if (adapter->flags & BE_FLAGS_EVT_INCOMPATIBLE_SFP) if (adapter->flags & BE_FLAGS_EVT_INCOMPATIBLE_SFP)
be_log_sfp_info(adapter); be_log_sfp_info(adapter);
...@@ -5204,7 +5290,7 @@ static void be_unmap_pci_bars(struct be_adapter *adapter) ...@@ -5204,7 +5290,7 @@ static void be_unmap_pci_bars(struct be_adapter *adapter)
static int db_bar(struct be_adapter *adapter) static int db_bar(struct be_adapter *adapter)
{ {
if (lancer_chip(adapter) || !be_physfn(adapter)) if (lancer_chip(adapter) || be_virtfn(adapter))
return 0; return 0;
else else
return 4; return 4;
......
/* /*
* Copyright (C) 2005 - 2014 Emulex * Copyright (C) 2005 - 2015 Emulex
* All rights reserved. * All rights reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
......
/* /*
* Copyright (C) 2005 - 2014 Emulex * Copyright (C) 2005 - 2015 Emulex
* All rights reserved. * All rights reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment