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

Merge branch 'be2net'

Sathya Perla says:

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

Hi Dave, pls consider applying the following patch-set to the
net-next tree. It has 5 code/style cleanup patches and 4 patches that
add functionality to the driver.

Patch 1 moves routines that were not needed to be in be.h to the respective
src files, to avoid unnecessary compilation.

Patch 2 replaces (1 << x) with BIT(x) macro

Patch 3 refactors code that checks if a FW flash file is compatible
with the adapter. The code is now refactored into 2 routines, the first one
gets the file type from the image file and the 2nd routine checks if the
file type is compatible with the adapter.

Patch 4 adds compatibility checks for flashing a FW image on the new
Skyhawk P2 HW revision.

Patch 5 adds support for a new "offset based" flashing scheme, wherein
the driver informs the FW of the offset at which each component in the flash
file is to be flashed at. This helps flashing components that were
previously not recognized by the running FW.

Patch 6 simplifies the be_cmd_rx_filter() routine, by passing to it the
filter flags already used in the FW cmd, instead of the netdev flags that
were converted to the FW-cmd flags.

Patch 7 introduces helper routines in be_set_rx_mode() and be_vid_config()
to improve code readability.

Patch 8 adds processing of port-misconfig async event sent by the FW.

Patch 9 removes unnecessary swapping of a field in the TX desc.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1fd0bddb f986afcb
...@@ -59,26 +59,6 @@ ...@@ -59,26 +59,6 @@
#define OC_SUBSYS_DEVICE_ID3 0xE612 #define OC_SUBSYS_DEVICE_ID3 0xE612
#define OC_SUBSYS_DEVICE_ID4 0xE652 #define OC_SUBSYS_DEVICE_ID4 0xE652
static inline char *nic_name(struct pci_dev *pdev)
{
switch (pdev->device) {
case OC_DEVICE_ID1:
return OC_NAME;
case OC_DEVICE_ID2:
return OC_NAME_BE;
case OC_DEVICE_ID3:
case OC_DEVICE_ID4:
return OC_NAME_LANCER;
case BE_DEVICE_ID2:
return BE3_NAME;
case OC_DEVICE_ID5:
case OC_DEVICE_ID6:
return OC_NAME_SH;
default:
return BE_NAME;
}
}
/* Number of bytes of an RX frame that are copied to skb->data */ /* Number of bytes of an RX frame that are copied to skb->data */
#define BE_HDR_LEN ((u16) 64) #define BE_HDR_LEN ((u16) 64)
/* allocate extra space to allow tunneling decapsulation without head reallocation */ /* allocate extra space to allow tunneling decapsulation without head reallocation */
...@@ -381,15 +361,14 @@ enum vf_state { ...@@ -381,15 +361,14 @@ enum vf_state {
ASSIGNED = 1 ASSIGNED = 1
}; };
#define BE_FLAGS_LINK_STATUS_INIT 1 #define BE_FLAGS_LINK_STATUS_INIT BIT(1)
#define BE_FLAGS_SRIOV_ENABLED (1 << 2) #define BE_FLAGS_SRIOV_ENABLED BIT(2)
#define BE_FLAGS_WORKER_SCHEDULED (1 << 3) #define BE_FLAGS_WORKER_SCHEDULED BIT(3)
#define BE_FLAGS_VLAN_PROMISC (1 << 4) #define BE_FLAGS_NAPI_ENABLED BIT(6)
#define BE_FLAGS_MCAST_PROMISC (1 << 5) #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD BIT(7)
#define BE_FLAGS_NAPI_ENABLED (1 << 9) #define BE_FLAGS_VXLAN_OFFLOADS BIT(8)
#define BE_FLAGS_QNQ_ASYNC_EVT_RCVD (1 << 11) #define BE_FLAGS_SETUP_DONE BIT(9)
#define BE_FLAGS_VXLAN_OFFLOADS (1 << 12) #define BE_FLAGS_EVT_INCOMPATIBLE_SFP BIT(10)
#define BE_FLAGS_SETUP_DONE (1 << 13)
#define BE_UC_PMAC_COUNT 30 #define BE_UC_PMAC_COUNT 30
#define BE_VF_UC_PMAC_COUNT 2 #define BE_VF_UC_PMAC_COUNT 2
...@@ -399,6 +378,8 @@ enum vf_state { ...@@ -399,6 +378,8 @@ enum vf_state {
#define LANCER_DELETE_FW_DUMP 0x2 #define LANCER_DELETE_FW_DUMP 0x2
struct phy_info { struct phy_info {
/* From SFF-8472 spec */
#define SFP_VENDOR_NAME_LEN 17
u8 transceiver; u8 transceiver;
u8 autoneg; u8 autoneg;
u8 fc_autoneg; u8 fc_autoneg;
...@@ -412,6 +393,8 @@ struct phy_info { ...@@ -412,6 +393,8 @@ struct phy_info {
u32 advertising; u32 advertising;
u32 supported; u32 supported;
u8 cable_type; u8 cable_type;
u8 vendor_name[SFP_VENDOR_NAME_LEN];
u8 vendor_pn[SFP_VENDOR_NAME_LEN];
}; };
struct be_resources { struct be_resources {
...@@ -469,8 +452,6 @@ struct be_adapter { ...@@ -469,8 +452,6 @@ struct be_adapter {
struct be_drv_stats drv_stats; struct be_drv_stats drv_stats;
struct be_aic_obj aic_obj[MAX_EVT_QS]; struct be_aic_obj aic_obj[MAX_EVT_QS];
u16 vlans_added;
unsigned long vids[BITS_TO_LONGS(VLAN_N_VID)];
u8 vlan_prio_bmap; /* Available Priority BitMap */ u8 vlan_prio_bmap; /* Available Priority BitMap */
u16 recommended_prio; /* Recommended Priority */ u16 recommended_prio; /* Recommended Priority */
struct be_dma_mem rx_filter; /* Cmd DMA mem for rx-filter */ struct be_dma_mem rx_filter; /* Cmd DMA mem for rx-filter */
...@@ -486,8 +467,15 @@ struct be_adapter { ...@@ -486,8 +467,15 @@ struct be_adapter {
/* Ethtool knobs and info */ /* Ethtool knobs and info */
char fw_ver[FW_VER_LEN]; char fw_ver[FW_VER_LEN];
char fw_on_flash[FW_VER_LEN]; char fw_on_flash[FW_VER_LEN];
/* IFACE filtering fields */
int if_handle; /* Used to configure filtering */ int if_handle; /* Used to configure filtering */
u32 if_flags; /* Interface filtering flags */
u32 *pmac_id; /* MAC addr handle used by BE card */ u32 *pmac_id; /* MAC addr handle used by BE card */
u32 uc_macs; /* Count of secondary UC MAC programmed */
unsigned long vids[BITS_TO_LONGS(VLAN_N_VID)];
u16 vlans_added;
u32 beacon_state; /* for set_phys_id */ u32 beacon_state; /* for set_phys_id */
bool eeh_error; bool eeh_error;
...@@ -495,7 +483,7 @@ struct be_adapter { ...@@ -495,7 +483,7 @@ struct be_adapter {
bool hw_error; bool hw_error;
u32 port_num; u32 port_num;
bool promiscuous; char port_name;
u8 mc_type; u8 mc_type;
u32 function_mode; u32 function_mode;
u32 function_caps; u32 function_caps;
...@@ -528,7 +516,6 @@ struct be_adapter { ...@@ -528,7 +516,6 @@ struct be_adapter {
struct phy_info phy; struct phy_info phy;
u8 wol_cap; u8 wol_cap;
bool wol_en; bool wol_en;
u32 uc_macs; /* Count of secondary UC MAC programmed */
u16 asic_rev; u16 asic_rev;
u16 qnq_vid; u16 qnq_vid;
u32 msg_enable; u32 msg_enable;
...@@ -734,19 +721,6 @@ static inline bool is_ipv4_pkt(struct sk_buff *skb) ...@@ -734,19 +721,6 @@ static inline bool is_ipv4_pkt(struct sk_buff *skb)
return skb->protocol == htons(ETH_P_IP) && ip_hdr(skb)->version == 4; return skb->protocol == htons(ETH_P_IP) && ip_hdr(skb)->version == 4;
} }
static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
{
u32 addr;
addr = jhash(adapter->netdev->dev_addr, ETH_ALEN, 0);
mac[5] = (u8)(addr & 0xFF);
mac[4] = (u8)((addr >> 8) & 0xFF);
mac[3] = (u8)((addr >> 16) & 0xFF);
/* Use the OUI from the current MAC address */
memcpy(mac, adapter->netdev->dev_addr, 3);
}
static inline bool be_multi_rxq(const struct be_adapter *adapter) static inline bool be_multi_rxq(const struct be_adapter *adapter)
{ {
return adapter->num_rx_qs > 1; return adapter->num_rx_qs > 1;
...@@ -769,129 +743,6 @@ static inline void be_clear_all_error(struct be_adapter *adapter) ...@@ -769,129 +743,6 @@ static inline void be_clear_all_error(struct be_adapter *adapter)
adapter->fw_timeout = false; adapter->fw_timeout = false;
} }
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;
}
}
static inline int qnq_async_evt_rcvd(struct be_adapter *adapter)
{
return adapter->flags & BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
}
#ifdef CONFIG_NET_RX_BUSY_POLL
static inline bool be_lock_napi(struct be_eq_obj *eqo)
{
bool status = true;
spin_lock(&eqo->lock); /* BH is already disabled */
if (eqo->state & BE_EQ_LOCKED) {
WARN_ON(eqo->state & BE_EQ_NAPI);
eqo->state |= BE_EQ_NAPI_YIELD;
status = false;
} else {
eqo->state = BE_EQ_NAPI;
}
spin_unlock(&eqo->lock);
return status;
}
static inline void be_unlock_napi(struct be_eq_obj *eqo)
{
spin_lock(&eqo->lock); /* BH is already disabled */
WARN_ON(eqo->state & (BE_EQ_POLL | BE_EQ_NAPI_YIELD));
eqo->state = BE_EQ_IDLE;
spin_unlock(&eqo->lock);
}
static inline bool be_lock_busy_poll(struct be_eq_obj *eqo)
{
bool status = true;
spin_lock_bh(&eqo->lock);
if (eqo->state & BE_EQ_LOCKED) {
eqo->state |= BE_EQ_POLL_YIELD;
status = false;
} else {
eqo->state |= BE_EQ_POLL;
}
spin_unlock_bh(&eqo->lock);
return status;
}
static inline void be_unlock_busy_poll(struct be_eq_obj *eqo)
{
spin_lock_bh(&eqo->lock);
WARN_ON(eqo->state & (BE_EQ_NAPI));
eqo->state = BE_EQ_IDLE;
spin_unlock_bh(&eqo->lock);
}
static inline void be_enable_busy_poll(struct be_eq_obj *eqo)
{
spin_lock_init(&eqo->lock);
eqo->state = BE_EQ_IDLE;
}
static inline void be_disable_busy_poll(struct be_eq_obj *eqo)
{
local_bh_disable();
/* It's enough to just acquire napi lock on the eqo to stop
* be_busy_poll() from processing any queueus.
*/
while (!be_lock_napi(eqo))
mdelay(1);
local_bh_enable();
}
#else /* CONFIG_NET_RX_BUSY_POLL */
static inline bool be_lock_napi(struct be_eq_obj *eqo)
{
return true;
}
static inline void be_unlock_napi(struct be_eq_obj *eqo)
{
}
static inline bool be_lock_busy_poll(struct be_eq_obj *eqo)
{
return false;
}
static inline void be_unlock_busy_poll(struct be_eq_obj *eqo)
{
}
static inline void be_enable_busy_poll(struct be_eq_obj *eqo)
{
}
static inline void be_disable_busy_poll(struct be_eq_obj *eqo)
{
}
#endif /* CONFIG_NET_RX_BUSY_POLL */
void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
u16 num_popped); u16 num_popped);
void be_link_status_update(struct be_adapter *adapter, u8 link_status); void be_link_status_update(struct be_adapter *adapter, u8 link_status);
...@@ -900,16 +751,6 @@ int be_load_fw(struct be_adapter *adapter, u8 *func); ...@@ -900,16 +751,6 @@ int be_load_fw(struct be_adapter *adapter, u8 *func);
bool be_is_wol_supported(struct be_adapter *adapter); bool be_is_wol_supported(struct be_adapter *adapter);
bool be_pause_supported(struct be_adapter *adapter); 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);
static inline int fw_major_num(const char *fw_ver)
{
int fw_major = 0;
sscanf(fw_ver, "%d.", &fw_major);
return fw_major;
}
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);
......
...@@ -19,6 +19,22 @@ ...@@ -19,6 +19,22 @@
#include "be.h" #include "be.h"
#include "be_cmds.h" #include "be_cmds.h"
static char *be_port_misconfig_evt_desc[] = {
"A valid SFP module detected",
"Optics faulted/ incorrectly installed/ not installed.",
"Optics of two types installed.",
"Incompatible optics.",
"Unknown port SFP status"
};
static char *be_port_misconfig_remedy_desc[] = {
"",
"Reseat optics. If issue not resolved, replace",
"Remove one optic or install matching pair of optics",
"Replace with compatible optics for card to function",
""
};
static struct be_cmd_priv_map cmd_priv_map[] = { static struct be_cmd_priv_map cmd_priv_map[] = {
{ {
OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
...@@ -249,6 +265,29 @@ static void be_async_link_state_process(struct be_adapter *adapter, ...@@ -249,6 +265,29 @@ static void be_async_link_state_process(struct be_adapter *adapter,
evt->port_link_status & LINK_STATUS_MASK); evt->port_link_status & LINK_STATUS_MASK);
} }
static void be_async_port_misconfig_event_process(struct be_adapter *adapter,
struct be_mcc_compl *compl)
{
struct be_async_event_misconfig_port *evt =
(struct be_async_event_misconfig_port *)compl;
u32 sfp_mismatch_evt = le32_to_cpu(evt->event_data_word1);
struct device *dev = &adapter->pdev->dev;
u8 port_misconfig_evt;
port_misconfig_evt =
((sfp_mismatch_evt >> (adapter->hba_port_num * 8)) & 0xff);
/* Log an error message that would allow a user to determine
* whether the SFPs have an issue
*/
dev_info(dev, "Port %c: %s %s", adapter->port_name,
be_port_misconfig_evt_desc[port_misconfig_evt],
be_port_misconfig_remedy_desc[port_misconfig_evt]);
if (port_misconfig_evt == INCOMPATIBLE_SFP)
adapter->flags |= BE_FLAGS_EVT_INCOMPATIBLE_SFP;
}
/* Grp5 CoS Priority evt */ /* Grp5 CoS Priority evt */
static void be_async_grp5_cos_priority_process(struct be_adapter *adapter, static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
struct be_mcc_compl *compl) struct be_mcc_compl *compl)
...@@ -334,6 +373,16 @@ static void be_async_dbg_evt_process(struct be_adapter *adapter, ...@@ -334,6 +373,16 @@ static void be_async_dbg_evt_process(struct be_adapter *adapter,
} }
} }
static void be_async_sliport_evt_process(struct be_adapter *adapter,
struct be_mcc_compl *cmp)
{
u8 event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
ASYNC_EVENT_TYPE_MASK;
if (event_type == ASYNC_EVENT_PORT_MISCONFIG)
be_async_port_misconfig_event_process(adapter, cmp);
}
static inline bool is_link_state_evt(u32 flags) static inline bool is_link_state_evt(u32 flags)
{ {
return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
...@@ -352,6 +401,12 @@ static inline bool is_dbg_evt(u32 flags) ...@@ -352,6 +401,12 @@ static inline bool is_dbg_evt(u32 flags)
ASYNC_EVENT_CODE_QNQ; ASYNC_EVENT_CODE_QNQ;
} }
static inline bool is_sliport_evt(u32 flags)
{
return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
ASYNC_EVENT_CODE_SLIPORT;
}
static void be_mcc_event_process(struct be_adapter *adapter, static void be_mcc_event_process(struct be_adapter *adapter,
struct be_mcc_compl *compl) struct be_mcc_compl *compl)
{ {
...@@ -361,6 +416,8 @@ static void be_mcc_event_process(struct be_adapter *adapter, ...@@ -361,6 +416,8 @@ static void be_mcc_event_process(struct be_adapter *adapter,
be_async_grp5_evt_process(adapter, compl); be_async_grp5_evt_process(adapter, compl);
else if (is_dbg_evt(compl->flags)) else if (is_dbg_evt(compl->flags))
be_async_dbg_evt_process(adapter, compl); be_async_dbg_evt_process(adapter, compl);
else if (is_sliport_evt(compl->flags))
be_async_sliport_evt_process(adapter, compl);
} }
static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter) static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
...@@ -1171,9 +1228,15 @@ static int be_cmd_mccq_ext_create(struct be_adapter *adapter, ...@@ -1171,9 +1228,15 @@ static int be_cmd_mccq_ext_create(struct be_adapter *adapter,
ctxt, 1); ctxt, 1);
} }
/* Subscribe to Link State and Group 5 Events(bits 1 and 5 set) */ /* Subscribe to Link State, Sliport Event and Group 5 Events
req->async_event_bitmap[0] = cpu_to_le32(0x00000022); * (bits 1, 5 and 17 set)
req->async_event_bitmap[0] |= cpu_to_le32(1 << ASYNC_EVENT_CODE_QNQ); */
req->async_event_bitmap[0] =
cpu_to_le32(BIT(ASYNC_EVENT_CODE_LINK_STATE) |
BIT(ASYNC_EVENT_CODE_GRP_5) |
BIT(ASYNC_EVENT_CODE_QNQ) |
BIT(ASYNC_EVENT_CODE_SLIPORT));
be_dws_cpu_to_le(ctxt, sizeof(req->context)); be_dws_cpu_to_le(ctxt, sizeof(req->context));
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
...@@ -1886,7 +1949,7 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, ...@@ -1886,7 +1949,7 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
return status; return status;
} }
int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
{ {
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
struct be_dma_mem *mem = &adapter->rx_filter; struct be_dma_mem *mem = &adapter->rx_filter;
...@@ -1906,31 +1969,13 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) ...@@ -1906,31 +1969,13 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
wrb, mem); wrb, mem);
req->if_id = cpu_to_le32(adapter->if_handle); req->if_id = cpu_to_le32(adapter->if_handle);
if (flags & IFF_PROMISC) { req->if_flags_mask = cpu_to_le32(flags);
req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS | req->if_flags = (value == ON) ? req->if_flags_mask : 0;
BE_IF_FLAGS_VLAN_PROMISCUOUS |
BE_IF_FLAGS_MCAST_PROMISCUOUS); if (flags & BE_IF_FLAGS_MULTICAST) {
if (value == ON)
req->if_flags =
cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS |
BE_IF_FLAGS_VLAN_PROMISCUOUS |
BE_IF_FLAGS_MCAST_PROMISCUOUS);
} else if (flags & IFF_ALLMULTI) {
req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS);
req->if_flags = cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS);
} else if (flags & BE_FLAGS_VLAN_PROMISC) {
req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_VLAN_PROMISCUOUS);
if (value == ON)
req->if_flags =
cpu_to_le32(BE_IF_FLAGS_VLAN_PROMISCUOUS);
} else {
struct netdev_hw_addr *ha; struct netdev_hw_addr *ha;
int i = 0; int i = 0;
req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_MULTICAST);
req->if_flags = cpu_to_le32(BE_IF_FLAGS_MULTICAST);
/* Reset mcast promisc mode if already set by setting mask /* Reset mcast promisc mode if already set by setting mask
* and not setting flags field * and not setting flags field
*/ */
...@@ -1942,24 +1987,26 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) ...@@ -1942,24 +1987,26 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN); memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN);
} }
if ((req->if_flags_mask & cpu_to_le32(be_if_cap_flags(adapter))) !=
req->if_flags_mask) {
dev_warn(&adapter->pdev->dev,
"Cannot set rx filter flags 0x%x\n",
req->if_flags_mask);
dev_warn(&adapter->pdev->dev,
"Interface is capable of 0x%x flags only\n",
be_if_cap_flags(adapter));
}
req->if_flags_mask &= cpu_to_le32(be_if_cap_flags(adapter));
status = be_mcc_notify_wait(adapter); status = be_mcc_notify_wait(adapter);
err: err:
spin_unlock_bh(&adapter->mcc_lock); spin_unlock_bh(&adapter->mcc_lock);
return status; return status;
} }
int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
{
struct device *dev = &adapter->pdev->dev;
if ((flags & be_if_cap_flags(adapter)) != flags) {
dev_warn(dev, "Cannot set rx filter flags 0x%x\n", flags);
dev_warn(dev, "Interface is capable of 0x%x flags only\n",
be_if_cap_flags(adapter));
}
flags &= be_if_cap_flags(adapter);
return __be_cmd_rx_filter(adapter, flags, value);
}
/* Uses synchrounous mcc */ /* Uses synchrounous mcc */
int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
{ {
...@@ -2360,6 +2407,24 @@ int be_cmd_query_cable_type(struct be_adapter *adapter) ...@@ -2360,6 +2407,24 @@ int be_cmd_query_cable_type(struct be_adapter *adapter)
return status; return status;
} }
int be_cmd_query_sfp_info(struct be_adapter *adapter)
{
u8 page_data[PAGE_DATA_LEN];
int status;
status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
page_data);
if (!status) {
strlcpy(adapter->phy.vendor_name, page_data +
SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1);
strlcpy(adapter->phy.vendor_pn,
page_data + SFP_VENDOR_PN_OFFSET,
SFP_VENDOR_NAME_LEN - 1);
}
return status;
}
int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name) int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name)
{ {
struct lancer_cmd_req_delete_object *req; struct lancer_cmd_req_delete_object *req;
...@@ -2436,7 +2501,8 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, ...@@ -2436,7 +2501,8 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
} }
int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
u32 flash_type, u32 flash_opcode, u32 buf_size) u32 flash_type, u32 flash_opcode, u32 img_offset,
u32 buf_size)
{ {
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
struct be_cmd_write_flashrom *req; struct be_cmd_write_flashrom *req;
...@@ -2457,6 +2523,9 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, ...@@ -2457,6 +2523,9 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
cmd); cmd);
req->params.op_type = cpu_to_le32(flash_type); req->params.op_type = cpu_to_le32(flash_type);
if (flash_type == OPTYPE_OFFSET_SPECIFIED)
req->params.offset = cpu_to_le32(img_offset);
req->params.op_code = cpu_to_le32(flash_opcode); req->params.op_code = cpu_to_le32(flash_opcode);
req->params.data_buf_size = cpu_to_le32(buf_size); req->params.data_buf_size = cpu_to_le32(buf_size);
...@@ -2477,10 +2546,10 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, ...@@ -2477,10 +2546,10 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
} }
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
u16 optype, int offset) u16 img_optype, u32 img_offset, u32 crc_offset)
{ {
struct be_mcc_wrb *wrb;
struct be_cmd_read_flash_crc *req; struct be_cmd_read_flash_crc *req;
struct be_mcc_wrb *wrb;
int status; int status;
spin_lock_bh(&adapter->mcc_lock); spin_lock_bh(&adapter->mcc_lock);
...@@ -2496,9 +2565,13 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, ...@@ -2496,9 +2565,13 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
OPCODE_COMMON_READ_FLASHROM, sizeof(*req), OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
wrb, NULL); wrb, NULL);
req->params.op_type = cpu_to_le32(optype); req->params.op_type = cpu_to_le32(img_optype);
if (img_optype == OPTYPE_OFFSET_SPECIFIED)
req->params.offset = cpu_to_le32(img_offset + crc_offset);
else
req->params.offset = cpu_to_le32(crc_offset);
req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); 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); req->params.data_buf_size = cpu_to_le32(0x4);
status = be_mcc_notify_wait(adapter); status = be_mcc_notify_wait(adapter);
...@@ -3241,6 +3314,24 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, ...@@ -3241,6 +3314,24 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
return status; return status;
} }
static 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;
}
}
int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter) int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
{ {
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
...@@ -3427,42 +3518,34 @@ int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, ...@@ -3427,42 +3518,34 @@ int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
return status; return status;
} }
int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name) int be_cmd_query_port_name(struct be_adapter *adapter)
{ {
struct be_mcc_wrb *wrb;
struct be_cmd_req_get_port_name *req; struct be_cmd_req_get_port_name *req;
struct be_mcc_wrb *wrb;
int status; int status;
if (!lancer_chip(adapter)) { if (mutex_lock_interruptible(&adapter->mbox_lock))
*port_name = adapter->hba_port_num + '0'; return -1;
return 0;
}
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); req = embedded_payload(wrb);
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb, OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb,
NULL); NULL);
req->hdr.version = 1; if (!BEx_chip(adapter))
req->hdr.version = 1;
status = be_mcc_notify_wait(adapter); status = be_mbox_notify_wait(adapter);
if (!status) { if (!status) {
struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb); struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb);
*port_name = resp->port_name[adapter->hba_port_num]; adapter->port_name = resp->port_name[adapter->hba_port_num];
} else { } else {
*port_name = adapter->hba_port_num + '0'; adapter->port_name = adapter->hba_port_num + '0';
} }
err:
spin_unlock_bh(&adapter->mcc_lock); mutex_unlock(&adapter->mbox_lock);
return status; return status;
} }
......
...@@ -44,10 +44,10 @@ struct be_mcc_wrb { ...@@ -44,10 +44,10 @@ struct be_mcc_wrb {
} payload; } payload;
}; };
#define CQE_FLAGS_VALID_MASK (1 << 31) #define CQE_FLAGS_VALID_MASK BIT(31)
#define CQE_FLAGS_ASYNC_MASK (1 << 30) #define CQE_FLAGS_ASYNC_MASK BIT(30)
#define CQE_FLAGS_COMPLETED_MASK (1 << 28) #define CQE_FLAGS_COMPLETED_MASK BIT(28)
#define CQE_FLAGS_CONSUMED_MASK (1 << 27) #define CQE_FLAGS_CONSUMED_MASK BIT(27)
/* Completion Status */ /* Completion Status */
enum mcc_base_status { enum mcc_base_status {
...@@ -102,6 +102,8 @@ struct be_mcc_compl { ...@@ -102,6 +102,8 @@ struct be_mcc_compl {
#define ASYNC_EVENT_PVID_STATE 0x3 #define ASYNC_EVENT_PVID_STATE 0x3
#define ASYNC_EVENT_CODE_QNQ 0x6 #define ASYNC_EVENT_CODE_QNQ 0x6
#define ASYNC_DEBUG_EVENT_TYPE_QNQ 1 #define ASYNC_DEBUG_EVENT_TYPE_QNQ 1
#define ASYNC_EVENT_CODE_SLIPORT 0x11
#define ASYNC_EVENT_PORT_MISCONFIG 0x9
enum { enum {
LINK_DOWN = 0x0, LINK_DOWN = 0x0,
...@@ -169,6 +171,15 @@ struct be_async_event_qnq { ...@@ -169,6 +171,15 @@ struct be_async_event_qnq {
u32 flags; u32 flags;
} __packed; } __packed;
#define INCOMPATIBLE_SFP 0x3
/* async event indicating misconfigured port */
struct be_async_event_misconfig_port {
u32 event_data_word1;
u32 event_data_word2;
u32 rsvd0;
u32 flags;
} __packed;
struct be_mcc_mailbox { struct be_mcc_mailbox {
struct be_mcc_wrb wrb; struct be_mcc_wrb wrb;
struct be_mcc_compl compl; struct be_mcc_compl compl;
...@@ -586,6 +597,10 @@ enum be_if_flags { ...@@ -586,6 +597,10 @@ enum be_if_flags {
BE_IF_FLAGS_PASS_L3L4_ERRORS | BE_IF_FLAGS_MULTICAST |\ BE_IF_FLAGS_PASS_L3L4_ERRORS | BE_IF_FLAGS_MULTICAST |\
BE_IF_FLAGS_UNTAGGED) BE_IF_FLAGS_UNTAGGED)
#define BE_IF_FLAGS_ALL_PROMISCUOUS (BE_IF_FLAGS_PROMISCUOUS | \
BE_IF_FLAGS_VLAN_PROMISCUOUS |\
BE_IF_FLAGS_MCAST_PROMISCUOUS)
/* An RX interface is an object with one or more MAC addresses and /* An RX interface is an object with one or more MAC addresses and
* filtering capabilities. */ * filtering capabilities. */
struct be_cmd_req_if_create { struct be_cmd_req_if_create {
...@@ -1024,6 +1039,8 @@ enum { ...@@ -1024,6 +1039,8 @@ enum {
#define SFP_PLUS_SFF_8472_COMP 0x5E #define SFP_PLUS_SFF_8472_COMP 0x5E
#define SFP_PLUS_CABLE_TYPE_OFFSET 0x8 #define SFP_PLUS_CABLE_TYPE_OFFSET 0x8
#define SFP_PLUS_COPPER_CABLE 0x4 #define SFP_PLUS_COPPER_CABLE 0x4
#define SFP_VENDOR_NAME_OFFSET 0x14
#define SFP_VENDOR_PN_OFFSET 0x28
#define PAGE_DATA_LEN 256 #define PAGE_DATA_LEN 256
struct be_cmd_resp_port_type { struct be_cmd_resp_port_type {
...@@ -1091,6 +1108,10 @@ struct be_cmd_req_query_fw_cfg { ...@@ -1091,6 +1108,10 @@ 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;
...@@ -1168,6 +1189,7 @@ struct be_cmd_resp_get_beacon_state { ...@@ -1168,6 +1189,7 @@ struct be_cmd_resp_get_beacon_state {
#define OPTYPE_REDBOOT 1 #define OPTYPE_REDBOOT 1
#define OPTYPE_BIOS 2 #define OPTYPE_BIOS 2
#define OPTYPE_PXE_BIOS 3 #define OPTYPE_PXE_BIOS 3
#define OPTYPE_OFFSET_SPECIFIED 7
#define OPTYPE_FCOE_BIOS 8 #define OPTYPE_FCOE_BIOS 8
#define OPTYPE_ISCSI_BACKUP 9 #define OPTYPE_ISCSI_BACKUP 9
#define OPTYPE_FCOE_FW_ACTIVE 10 #define OPTYPE_FCOE_FW_ACTIVE 10
...@@ -1260,6 +1282,11 @@ struct flash_file_hdr_g2 { ...@@ -1260,6 +1282,11 @@ struct flash_file_hdr_g2 {
u8 build[24]; u8 build[24];
}; };
/* First letter of the build version of the image */
#define BLD_STR_UFI_TYPE_BE2 '2'
#define BLD_STR_UFI_TYPE_BE3 '3'
#define BLD_STR_UFI_TYPE_SH '4'
struct flash_file_hdr_g3 { struct flash_file_hdr_g3 {
u8 sign[52]; u8 sign[52];
u8 ufi_version[4]; u8 ufi_version[4];
...@@ -2245,8 +2272,10 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, ...@@ -2245,8 +2272,10 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num,
int be_cmd_read_port_transceiver_data(struct be_adapter *adapter, int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
u8 page_num, u8 *data); u8 page_num, u8 *data);
int be_cmd_query_cable_type(struct be_adapter *adapter); int be_cmd_query_cable_type(struct be_adapter *adapter);
int be_cmd_query_sfp_info(struct be_adapter *adapter);
int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
u32 flash_oper, u32 flash_opcode, u32 buf_size); u32 flash_oper, u32 flash_opcode, u32 img_offset,
u32 buf_size);
int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
u32 data_size, u32 data_offset, u32 data_size, u32 data_offset,
const char *obj_name, u32 *data_written, const char *obj_name, u32 *data_written,
...@@ -2256,7 +2285,7 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, ...@@ -2256,7 +2285,7 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
u32 *data_read, u32 *eof, u8 *addn_status); u32 *data_read, u32 *eof, u8 *addn_status);
int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name); int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name);
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
u16 optype, int offset); u16 img_optype, u32 img_offset, u32 crc_offset);
int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
struct be_dma_mem *nonemb_cmd); struct be_dma_mem *nonemb_cmd);
int be_cmd_fw_init(struct be_adapter *adapter); int be_cmd_fw_init(struct be_adapter *adapter);
...@@ -2311,7 +2340,7 @@ int lancer_initiate_dump(struct be_adapter *adapter); ...@@ -2311,7 +2340,7 @@ int lancer_initiate_dump(struct be_adapter *adapter);
int lancer_delete_dump(struct be_adapter *adapter); int lancer_delete_dump(struct be_adapter *adapter);
bool dump_present(struct be_adapter *adapter); bool dump_present(struct be_adapter *adapter);
int lancer_test_and_set_rdy_state(struct be_adapter *adapter); int lancer_test_and_set_rdy_state(struct be_adapter *adapter);
int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name); int be_cmd_query_port_name(struct be_adapter *adapter);
int be_cmd_get_func_config(struct be_adapter *adapter, int be_cmd_get_func_config(struct be_adapter *adapter,
struct be_resources *res); struct be_resources *res);
int be_cmd_get_profile_config(struct be_adapter *adapter, int be_cmd_get_profile_config(struct be_adapter *adapter,
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
* atomically without having to arbitrate for the PCI Interrupt Disable bit * atomically without having to arbitrate for the PCI Interrupt Disable bit
* with the OS. * with the OS.
*/ */
#define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */ #define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK BIT(29) /* bit 29 */
/********* PCI Function Capability *********/ /********* PCI Function Capability *********/
#define BE_FUNCTION_CAPS_RSS 0x2 #define BE_FUNCTION_CAPS_RSS 0x2
...@@ -193,10 +193,10 @@ struct be_eq_entry { ...@@ -193,10 +193,10 @@ struct be_eq_entry {
/* TX Queue Descriptor */ /* TX Queue Descriptor */
#define ETH_WRB_FRAG_LEN_MASK 0xFFFF #define ETH_WRB_FRAG_LEN_MASK 0xFFFF
struct be_eth_wrb { struct be_eth_wrb {
u32 frag_pa_hi; /* dword 0 */ __le32 frag_pa_hi; /* dword 0 */
u32 frag_pa_lo; /* dword 1 */ __le32 frag_pa_lo; /* dword 1 */
u32 rsvd0; /* dword 2 */ u32 rsvd0; /* dword 2 */
u32 frag_len; /* dword 3: bits 0 - 15 */ __le32 frag_len; /* dword 3: bits 0 - 15 */
} __packed; } __packed;
/* Pseudo amap definition for eth_hdr_wrb in which each bit of the /* Pseudo amap definition for eth_hdr_wrb in which each bit of the
...@@ -224,12 +224,12 @@ struct amap_eth_hdr_wrb { ...@@ -224,12 +224,12 @@ struct amap_eth_hdr_wrb {
} __packed; } __packed;
#define TX_HDR_WRB_COMPL 1 /* word 2 */ #define TX_HDR_WRB_COMPL 1 /* word 2 */
#define TX_HDR_WRB_EVT (1 << 1) /* word 2 */ #define TX_HDR_WRB_EVT BIT(1) /* word 2 */
#define TX_HDR_WRB_NUM_SHIFT 13 /* word 2: bits 13:17 */ #define TX_HDR_WRB_NUM_SHIFT 13 /* word 2: bits 13:17 */
#define TX_HDR_WRB_NUM_MASK 0x1F /* word 2: bits 13:17 */ #define TX_HDR_WRB_NUM_MASK 0x1F /* word 2: bits 13:17 */
struct be_eth_hdr_wrb { struct be_eth_hdr_wrb {
u32 dw[4]; __le32 dw[4];
}; };
/********* Tx Compl Status Encoding *********/ /********* Tx Compl Status Encoding *********/
......
...@@ -682,9 +682,20 @@ static u32 skb_wrb_cnt(struct sk_buff *skb) ...@@ -682,9 +682,20 @@ static u32 skb_wrb_cnt(struct sk_buff *skb)
static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len) static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len)
{ {
wrb->frag_pa_hi = upper_32_bits(addr); wrb->frag_pa_hi = cpu_to_le32(upper_32_bits(addr));
wrb->frag_pa_lo = addr & 0xFFFFFFFF; wrb->frag_pa_lo = cpu_to_le32(lower_32_bits(addr));
wrb->frag_len = len & ETH_WRB_FRAG_LEN_MASK; wrb->frag_len = cpu_to_le32(len & ETH_WRB_FRAG_LEN_MASK);
wrb->rsvd0 = 0;
}
/* A dummy wrb is just all zeros. Using a separate routine for dummy-wrb
* to avoid the swap and shift/mask operations in wrb_fill().
*/
static inline void wrb_fill_dummy(struct be_eth_wrb *wrb)
{
wrb->frag_pa_hi = 0;
wrb->frag_pa_lo = 0;
wrb->frag_len = 0;
wrb->rsvd0 = 0; wrb->rsvd0 = 0;
} }
...@@ -765,16 +776,16 @@ static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb, ...@@ -765,16 +776,16 @@ static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb,
bool unmap_single) bool unmap_single)
{ {
dma_addr_t dma; dma_addr_t dma;
u32 frag_len = le32_to_cpu(wrb->frag_len);
be_dws_le_to_cpu(wrb, sizeof(*wrb));
dma = (u64)wrb->frag_pa_hi << 32 | (u64)wrb->frag_pa_lo; dma = (u64)le32_to_cpu(wrb->frag_pa_hi) << 32 |
if (wrb->frag_len) { (u64)le32_to_cpu(wrb->frag_pa_lo);
if (frag_len) {
if (unmap_single) if (unmap_single)
dma_unmap_single(dev, dma, wrb->frag_len, dma_unmap_single(dev, dma, frag_len, DMA_TO_DEVICE);
DMA_TO_DEVICE);
else else
dma_unmap_page(dev, dma, wrb->frag_len, DMA_TO_DEVICE); dma_unmap_page(dev, dma, frag_len, DMA_TO_DEVICE);
} }
} }
...@@ -806,7 +817,6 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo, ...@@ -806,7 +817,6 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo,
map_single = true; map_single = true;
wrb = queue_head_node(txq); wrb = queue_head_node(txq);
wrb_fill(wrb, busaddr, len); wrb_fill(wrb, busaddr, len);
be_dws_cpu_to_le(wrb, sizeof(*wrb));
queue_head_inc(txq); queue_head_inc(txq);
copied += len; copied += len;
} }
...@@ -820,7 +830,6 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo, ...@@ -820,7 +830,6 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo,
goto dma_err; goto dma_err;
wrb = queue_head_node(txq); wrb = queue_head_node(txq);
wrb_fill(wrb, busaddr, skb_frag_size(frag)); wrb_fill(wrb, busaddr, skb_frag_size(frag));
be_dws_cpu_to_le(wrb, sizeof(*wrb));
queue_head_inc(txq); queue_head_inc(txq);
copied += skb_frag_size(frag); copied += skb_frag_size(frag);
} }
...@@ -846,7 +855,7 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo, ...@@ -846,7 +855,7 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo,
wrb = queue_head_node(txq); wrb = queue_head_node(txq);
unmap_tx_frag(dev, wrb, map_single); unmap_tx_frag(dev, wrb, map_single);
map_single = false; map_single = false;
copied -= wrb->frag_len; copied -= le32_to_cpu(wrb->frag_len);
adapter->drv_stats.dma_map_errors++; adapter->drv_stats.dma_map_errors++;
queue_head_inc(txq); queue_head_inc(txq);
} }
...@@ -854,6 +863,11 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo, ...@@ -854,6 +863,11 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo,
return 0; return 0;
} }
static inline int qnq_async_evt_rcvd(struct be_adapter *adapter)
{
return adapter->flags & BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
}
static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter, static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
struct sk_buff *skb, struct sk_buff *skb,
bool *skip_hw_vlan) bool *skip_hw_vlan)
...@@ -1032,7 +1046,7 @@ static void be_xmit_flush(struct be_adapter *adapter, struct be_tx_obj *txo) ...@@ -1032,7 +1046,7 @@ static void be_xmit_flush(struct be_adapter *adapter, struct be_tx_obj *txo)
/* compose a dummy wrb if there are odd set of wrbs to notify */ /* compose a dummy wrb if there are odd set of wrbs to notify */
if (!lancer_chip(adapter) && (txo->pend_wrb_cnt & 1)) { if (!lancer_chip(adapter) && (txo->pend_wrb_cnt & 1)) {
wrb_fill(queue_head_node(txq), 0, 0); wrb_fill_dummy(queue_head_node(txq));
queue_head_inc(txq); queue_head_inc(txq);
atomic_inc(&txq->used); atomic_inc(&txq->used);
txo->pend_wrb_cnt++; txo->pend_wrb_cnt++;
...@@ -1099,6 +1113,43 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) ...@@ -1099,6 +1113,43 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu)
return 0; return 0;
} }
static inline bool be_in_all_promisc(struct be_adapter *adapter)
{
return (adapter->if_flags & BE_IF_FLAGS_ALL_PROMISCUOUS) ==
BE_IF_FLAGS_ALL_PROMISCUOUS;
}
static int be_set_vlan_promisc(struct be_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
int status;
if (adapter->if_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS)
return 0;
status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_VLAN_PROMISCUOUS, ON);
if (!status) {
dev_info(dev, "Enabled VLAN promiscuous mode\n");
adapter->if_flags |= BE_IF_FLAGS_VLAN_PROMISCUOUS;
} else {
dev_err(dev, "Failed to enable VLAN promiscuous mode\n");
}
return status;
}
static int be_clear_vlan_promisc(struct be_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
int status;
status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_VLAN_PROMISCUOUS, OFF);
if (!status) {
dev_info(dev, "Disabling VLAN promiscuous mode\n");
adapter->if_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS;
}
return status;
}
/* /*
* A max of 64 (BE_NUM_VLANS_SUPPORTED) vlans can be configured in BE. * A max of 64 (BE_NUM_VLANS_SUPPORTED) vlans can be configured in BE.
* If the user configures more, place BE in vlan promiscuous mode. * If the user configures more, place BE in vlan promiscuous mode.
...@@ -1111,11 +1162,11 @@ static int be_vid_config(struct be_adapter *adapter) ...@@ -1111,11 +1162,11 @@ static int be_vid_config(struct be_adapter *adapter)
int status = 0; int status = 0;
/* No need to further configure vids if in promiscuous mode */ /* No need to further configure vids if in promiscuous mode */
if (adapter->promiscuous) if (be_in_all_promisc(adapter))
return 0; return 0;
if (adapter->vlans_added > be_max_vlans(adapter)) if (adapter->vlans_added > be_max_vlans(adapter))
goto set_vlan_promisc; return be_set_vlan_promisc(adapter);
/* Construct VLAN Table to give to HW */ /* Construct VLAN Table to give to HW */
for_each_set_bit(i, adapter->vids, VLAN_N_VID) for_each_set_bit(i, adapter->vids, VLAN_N_VID)
...@@ -1123,36 +1174,14 @@ static int be_vid_config(struct be_adapter *adapter) ...@@ -1123,36 +1174,14 @@ static int be_vid_config(struct be_adapter *adapter)
status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num); status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num);
if (status) { if (status) {
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_RESOURCES) MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES)
goto set_vlan_promisc; return be_set_vlan_promisc(adapter);
dev_err(dev, "Setting HW VLAN filtering failed\n"); } else if (adapter->if_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) {
} else { status = be_clear_vlan_promisc(adapter);
if (adapter->flags & BE_FLAGS_VLAN_PROMISC) {
/* hw VLAN filtering re-enabled. */
status = be_cmd_rx_filter(adapter,
BE_FLAGS_VLAN_PROMISC, OFF);
if (!status) {
dev_info(dev,
"Disabling VLAN Promiscuous mode\n");
adapter->flags &= ~BE_FLAGS_VLAN_PROMISC;
}
}
} }
return status;
set_vlan_promisc:
if (adapter->flags & BE_FLAGS_VLAN_PROMISC)
return 0;
status = be_cmd_rx_filter(adapter, BE_FLAGS_VLAN_PROMISC, ON);
if (!status) {
dev_info(dev, "Enable VLAN Promiscuous mode\n");
adapter->flags |= BE_FLAGS_VLAN_PROMISC;
} else
dev_err(dev, "Failed to enable VLAN Promiscuous mode\n");
return status; return status;
} }
...@@ -1194,79 +1223,99 @@ static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid) ...@@ -1194,79 +1223,99 @@ static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid)
return be_vid_config(adapter); return be_vid_config(adapter);
} }
static void be_clear_promisc(struct be_adapter *adapter) static void be_clear_all_promisc(struct be_adapter *adapter)
{ {
adapter->promiscuous = false; be_cmd_rx_filter(adapter, BE_IF_FLAGS_ALL_PROMISCUOUS, OFF);
adapter->flags &= ~(BE_FLAGS_VLAN_PROMISC | BE_FLAGS_MCAST_PROMISC); adapter->if_flags &= ~BE_IF_FLAGS_ALL_PROMISCUOUS;
}
be_cmd_rx_filter(adapter, IFF_PROMISC, OFF); static void be_set_all_promisc(struct be_adapter *adapter)
{
be_cmd_rx_filter(adapter, BE_IF_FLAGS_ALL_PROMISCUOUS, ON);
adapter->if_flags |= BE_IF_FLAGS_ALL_PROMISCUOUS;
} }
static void be_set_rx_mode(struct net_device *netdev) static void be_set_mc_promisc(struct be_adapter *adapter)
{ {
struct be_adapter *adapter = netdev_priv(netdev);
int status; int status;
if (netdev->flags & IFF_PROMISC) { if (adapter->if_flags & BE_IF_FLAGS_MCAST_PROMISCUOUS)
be_cmd_rx_filter(adapter, IFF_PROMISC, ON); return;
adapter->promiscuous = true;
goto done;
}
/* BE was previously in promiscuous mode; disable it */ status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_MCAST_PROMISCUOUS, ON);
if (adapter->promiscuous) { if (!status)
be_clear_promisc(adapter); adapter->if_flags |= BE_IF_FLAGS_MCAST_PROMISCUOUS;
if (adapter->vlans_added) }
be_vid_config(adapter);
static void be_set_mc_list(struct be_adapter *adapter)
{
int status;
status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_MULTICAST, ON);
if (!status)
adapter->if_flags &= ~BE_IF_FLAGS_MCAST_PROMISCUOUS;
else
be_set_mc_promisc(adapter);
}
static void be_set_uc_list(struct be_adapter *adapter)
{
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(adapter->netdev) > be_max_uc(adapter)) {
be_set_all_promisc(adapter);
return;
} }
/* Enable multicast promisc if num configured exceeds what we support */ netdev_for_each_uc_addr(ha, adapter->netdev) {
if (netdev->flags & IFF_ALLMULTI || adapter->uc_macs++; /* First slot is for Primary MAC */
netdev_mc_count(netdev) > be_max_mc(adapter)) be_cmd_pmac_add(adapter, (u8 *)ha->addr, adapter->if_handle,
goto set_mcast_promisc; &adapter->pmac_id[adapter->uc_macs], 0);
}
}
if (netdev_uc_count(netdev) != adapter->uc_macs) { static void be_clear_uc_list(struct be_adapter *adapter)
struct netdev_hw_addr *ha; {
int i = 1; /* First slot is claimed by the Primary MAC */ int i;
for (; adapter->uc_macs > 0; adapter->uc_macs--, i++) { for (i = 1; i < (adapter->uc_macs + 1); i++)
be_cmd_pmac_del(adapter, adapter->if_handle, be_cmd_pmac_del(adapter, adapter->if_handle,
adapter->pmac_id[i], 0); adapter->pmac_id[i], 0);
} adapter->uc_macs = 0;
}
if (netdev_uc_count(netdev) > be_max_uc(adapter)) { static void be_set_rx_mode(struct net_device *netdev)
be_cmd_rx_filter(adapter, IFF_PROMISC, ON); {
adapter->promiscuous = true; struct be_adapter *adapter = netdev_priv(netdev);
goto done;
}
netdev_for_each_uc_addr(ha, adapter->netdev) { if (netdev->flags & IFF_PROMISC) {
adapter->uc_macs++; /* First slot is for Primary MAC */ be_set_all_promisc(adapter);
be_cmd_pmac_add(adapter, (u8 *)ha->addr, return;
adapter->if_handle,
&adapter->pmac_id[adapter->uc_macs], 0);
}
} }
status = be_cmd_rx_filter(adapter, IFF_MULTICAST, ON); /* Interface was previously in promiscuous mode; disable it */
if (!status) { if (be_in_all_promisc(adapter)) {
if (adapter->flags & BE_FLAGS_MCAST_PROMISC) be_clear_all_promisc(adapter);
adapter->flags &= ~BE_FLAGS_MCAST_PROMISC; if (adapter->vlans_added)
goto done; be_vid_config(adapter);
} }
set_mcast_promisc: /* Enable multicast promisc if num configured exceeds what we support */
if (adapter->flags & BE_FLAGS_MCAST_PROMISC) if (netdev->flags & IFF_ALLMULTI ||
netdev_mc_count(netdev) > be_max_mc(adapter)) {
be_set_mc_promisc(adapter);
return; return;
}
/* Set to MCAST promisc mode if setting MULTICAST address fails if (netdev_uc_count(netdev) != adapter->uc_macs)
* or if num configured exceeds what we support be_set_uc_list(adapter);
*/
status = be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON); be_set_mc_list(adapter);
if (!status)
adapter->flags |= BE_FLAGS_MCAST_PROMISC;
done:
return;
} }
static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
...@@ -2526,6 +2575,106 @@ static void be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo, ...@@ -2526,6 +2575,106 @@ static void be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo,
} }
} }
#ifdef CONFIG_NET_RX_BUSY_POLL
static inline bool be_lock_napi(struct be_eq_obj *eqo)
{
bool status = true;
spin_lock(&eqo->lock); /* BH is already disabled */
if (eqo->state & BE_EQ_LOCKED) {
WARN_ON(eqo->state & BE_EQ_NAPI);
eqo->state |= BE_EQ_NAPI_YIELD;
status = false;
} else {
eqo->state = BE_EQ_NAPI;
}
spin_unlock(&eqo->lock);
return status;
}
static inline void be_unlock_napi(struct be_eq_obj *eqo)
{
spin_lock(&eqo->lock); /* BH is already disabled */
WARN_ON(eqo->state & (BE_EQ_POLL | BE_EQ_NAPI_YIELD));
eqo->state = BE_EQ_IDLE;
spin_unlock(&eqo->lock);
}
static inline bool be_lock_busy_poll(struct be_eq_obj *eqo)
{
bool status = true;
spin_lock_bh(&eqo->lock);
if (eqo->state & BE_EQ_LOCKED) {
eqo->state |= BE_EQ_POLL_YIELD;
status = false;
} else {
eqo->state |= BE_EQ_POLL;
}
spin_unlock_bh(&eqo->lock);
return status;
}
static inline void be_unlock_busy_poll(struct be_eq_obj *eqo)
{
spin_lock_bh(&eqo->lock);
WARN_ON(eqo->state & (BE_EQ_NAPI));
eqo->state = BE_EQ_IDLE;
spin_unlock_bh(&eqo->lock);
}
static inline void be_enable_busy_poll(struct be_eq_obj *eqo)
{
spin_lock_init(&eqo->lock);
eqo->state = BE_EQ_IDLE;
}
static inline void be_disable_busy_poll(struct be_eq_obj *eqo)
{
local_bh_disable();
/* It's enough to just acquire napi lock on the eqo to stop
* be_busy_poll() from processing any queueus.
*/
while (!be_lock_napi(eqo))
mdelay(1);
local_bh_enable();
}
#else /* CONFIG_NET_RX_BUSY_POLL */
static inline bool be_lock_napi(struct be_eq_obj *eqo)
{
return true;
}
static inline void be_unlock_napi(struct be_eq_obj *eqo)
{
}
static inline bool be_lock_busy_poll(struct be_eq_obj *eqo)
{
return false;
}
static inline void be_unlock_busy_poll(struct be_eq_obj *eqo)
{
}
static inline void be_enable_busy_poll(struct be_eq_obj *eqo)
{
}
static inline void be_disable_busy_poll(struct be_eq_obj *eqo)
{
}
#endif /* CONFIG_NET_RX_BUSY_POLL */
int be_poll(struct napi_struct *napi, int budget) int be_poll(struct napi_struct *napi, int budget)
{ {
struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi); struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi);
...@@ -2845,11 +2994,7 @@ static int be_close(struct net_device *netdev) ...@@ -2845,11 +2994,7 @@ static int be_close(struct net_device *netdev)
be_tx_compl_clean(adapter); be_tx_compl_clean(adapter);
be_rx_qs_destroy(adapter); be_rx_qs_destroy(adapter);
be_clear_uc_list(adapter);
for (i = 1; i < (adapter->uc_macs + 1); i++)
be_cmd_pmac_del(adapter, adapter->if_handle,
adapter->pmac_id[i], 0);
adapter->uc_macs = 0;
for_all_evt_queues(adapter, eqo, i) { for_all_evt_queues(adapter, eqo, i) {
if (msix_enabled(adapter)) if (msix_enabled(adapter))
...@@ -3020,6 +3165,19 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable) ...@@ -3020,6 +3165,19 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable)
return status; return status;
} }
static void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
{
u32 addr;
addr = jhash(adapter->netdev->dev_addr, ETH_ALEN, 0);
mac[5] = (u8)(addr & 0xFF);
mac[4] = (u8)((addr >> 8) & 0xFF);
mac[3] = (u8)((addr >> 16) & 0xFF);
/* Use the OUI from the current MAC address */
memcpy(mac, adapter->netdev->dev_addr, 3);
}
/* /*
* Generate a seed MAC address from the PF MAC Address using jhash. * Generate a seed MAC address from the PF MAC Address using jhash.
* MAC Address for VFs are assigned incrementally starting from the seed. * MAC Address for VFs are assigned incrementally starting from the seed.
...@@ -3120,14 +3278,9 @@ static void be_cancel_worker(struct be_adapter *adapter) ...@@ -3120,14 +3278,9 @@ static void be_cancel_worker(struct be_adapter *adapter)
static void be_mac_clear(struct be_adapter *adapter) static void be_mac_clear(struct be_adapter *adapter)
{ {
int i;
if (adapter->pmac_id) { if (adapter->pmac_id) {
for (i = 0; i < (adapter->uc_macs + 1); i++) be_cmd_pmac_del(adapter, adapter->if_handle,
be_cmd_pmac_del(adapter, adapter->if_handle, adapter->pmac_id[0], 0);
adapter->pmac_id[i], 0);
adapter->uc_macs = 0;
kfree(adapter->pmac_id); kfree(adapter->pmac_id);
adapter->pmac_id = NULL; adapter->pmac_id = NULL;
} }
...@@ -3411,7 +3564,7 @@ static void be_setup_init(struct be_adapter *adapter) ...@@ -3411,7 +3564,7 @@ static void be_setup_init(struct be_adapter *adapter)
adapter->phy.link_speed = -1; adapter->phy.link_speed = -1;
adapter->if_handle = -1; adapter->if_handle = -1;
adapter->be3_native = false; adapter->be3_native = false;
adapter->promiscuous = false; adapter->if_flags = 0;
if (be_physfn(adapter)) if (be_physfn(adapter))
adapter->cmd_privileges = MAX_PRIVILEGES; adapter->cmd_privileges = MAX_PRIVILEGES;
else else
...@@ -3538,7 +3691,9 @@ static int be_get_config(struct be_adapter *adapter) ...@@ -3538,7 +3691,9 @@ static int be_get_config(struct be_adapter *adapter)
if (status) if (status)
return status; return status;
if (be_physfn(adapter)) { be_cmd_query_port_name(adapter);
if (be_physfn(adapter)) {
status = be_cmd_get_active_profile(adapter, &profile_id); status = be_cmd_get_active_profile(adapter, &profile_id);
if (!status) if (!status)
dev_info(&adapter->pdev->dev, dev_info(&adapter->pdev->dev,
...@@ -3664,6 +3819,17 @@ int be_update_queues(struct be_adapter *adapter) ...@@ -3664,6 +3819,17 @@ int be_update_queues(struct be_adapter *adapter)
return status; return status;
} }
static inline int fw_major_num(const char *fw_ver)
{
int fw_major = 0, i;
i = sscanf(fw_ver, "%d.", &fw_major);
if (i != 1)
return 0;
return fw_major;
}
static int be_setup(struct be_adapter *adapter) static int be_setup(struct be_adapter *adapter)
{ {
struct device *dev = &adapter->pdev->dev; struct device *dev = &adapter->pdev->dev;
...@@ -3813,7 +3979,8 @@ static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p, ...@@ -3813,7 +3979,8 @@ static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p,
int status; int status;
u8 crc[4]; u8 crc[4];
status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_size - 4); status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_offset,
img_size - 4);
if (status) if (status)
return status; return status;
...@@ -3829,13 +3996,13 @@ static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p, ...@@ -3829,13 +3996,13 @@ static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p,
} }
static int be_flash(struct be_adapter *adapter, const u8 *img, static int be_flash(struct be_adapter *adapter, const u8 *img,
struct be_dma_mem *flash_cmd, int optype, int img_size) struct be_dma_mem *flash_cmd, int optype, int img_size,
u32 img_offset)
{ {
u32 flash_op, num_bytes, total_bytes = img_size, bytes_sent = 0;
struct be_cmd_write_flashrom *req = flash_cmd->va; struct be_cmd_write_flashrom *req = flash_cmd->va;
u32 total_bytes, flash_op, num_bytes;
int status; int status;
total_bytes = img_size;
while (total_bytes) { while (total_bytes) {
num_bytes = min_t(u32, 32*1024, total_bytes); num_bytes = min_t(u32, 32*1024, total_bytes);
...@@ -3856,12 +4023,15 @@ static int be_flash(struct be_adapter *adapter, const u8 *img, ...@@ -3856,12 +4023,15 @@ static int be_flash(struct be_adapter *adapter, const u8 *img,
memcpy(req->data_buf, img, num_bytes); memcpy(req->data_buf, img, num_bytes);
img += num_bytes; img += num_bytes;
status = be_cmd_write_flashrom(adapter, flash_cmd, optype, status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
flash_op, num_bytes); flash_op, img_offset +
bytes_sent, num_bytes);
if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST && if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST &&
optype == OPTYPE_PHY_FW) optype == OPTYPE_PHY_FW)
break; break;
else if (status) else if (status)
return status; return status;
bytes_sent += num_bytes;
} }
return 0; return 0;
} }
...@@ -3929,6 +4099,7 @@ static int be_flash_BEx(struct be_adapter *adapter, ...@@ -3929,6 +4099,7 @@ static int be_flash_BEx(struct be_adapter *adapter,
pflashcomp = gen2_flash_types; pflashcomp = gen2_flash_types;
filehdr_size = sizeof(struct flash_file_hdr_g2); filehdr_size = sizeof(struct flash_file_hdr_g2);
num_comp = ARRAY_SIZE(gen2_flash_types); num_comp = ARRAY_SIZE(gen2_flash_types);
img_hdrs_size = 0;
} }
/* Get flash section info*/ /* Get flash section info*/
...@@ -3973,7 +4144,7 @@ static int be_flash_BEx(struct be_adapter *adapter, ...@@ -3973,7 +4144,7 @@ static int be_flash_BEx(struct be_adapter *adapter,
return -1; return -1;
status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype, status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
pflashcomp[i].size); pflashcomp[i].size, 0);
if (status) { if (status) {
dev_err(dev, "Flashing section type 0x%x failed\n", dev_err(dev, "Flashing section type 0x%x failed\n",
pflashcomp[i].img_type); pflashcomp[i].img_type);
...@@ -4040,12 +4211,12 @@ static int be_flash_skyhawk(struct be_adapter *adapter, ...@@ -4040,12 +4211,12 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
struct be_dma_mem *flash_cmd, int num_of_images) struct be_dma_mem *flash_cmd, int num_of_images)
{ {
int img_hdrs_size = num_of_images * sizeof(struct image_hdr); int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
bool crc_match, old_fw_img, flash_offset_support = true;
struct device *dev = &adapter->pdev->dev; struct device *dev = &adapter->pdev->dev;
struct flash_section_info *fsec = NULL; struct flash_section_info *fsec = NULL;
u32 img_offset, img_size, img_type; u32 img_offset, img_size, img_type;
u16 img_optype, flash_optype;
int status, i, filehdr_size; int status, i, filehdr_size;
bool crc_match, old_fw_img;
u16 img_optype;
const u8 *p; const u8 *p;
filehdr_size = sizeof(struct flash_file_hdr_g3); filehdr_size = sizeof(struct flash_file_hdr_g3);
...@@ -4055,6 +4226,7 @@ static int be_flash_skyhawk(struct be_adapter *adapter, ...@@ -4055,6 +4226,7 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
return -EINVAL; return -EINVAL;
} }
retry_flash:
for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) { for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
img_offset = le32_to_cpu(fsec->fsec_entry[i].offset); img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size); img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size);
...@@ -4064,6 +4236,12 @@ static int be_flash_skyhawk(struct be_adapter *adapter, ...@@ -4064,6 +4236,12 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
if (img_optype == 0xFFFF) if (img_optype == 0xFFFF)
continue; continue;
if (flash_offset_support)
flash_optype = OPTYPE_OFFSET_SPECIFIED;
else
flash_optype = img_optype;
/* Don't bother verifying CRC if an old FW image is being /* Don't bother verifying CRC if an old FW image is being
* flashed * flashed
*/ */
...@@ -4072,16 +4250,26 @@ static int be_flash_skyhawk(struct be_adapter *adapter, ...@@ -4072,16 +4250,26 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
status = be_check_flash_crc(adapter, fw->data, img_offset, status = be_check_flash_crc(adapter, fw->data, img_offset,
img_size, filehdr_size + img_size, filehdr_size +
img_hdrs_size, img_optype, img_hdrs_size, flash_optype,
&crc_match); &crc_match);
/* The current FW image on the card does not recognize the new
* FLASH op_type. The FW download is partially complete.
* Reboot the server now to enable FW image to recognize the
* new FLASH op_type. To complete the remaining process,
* download the same FW again after the reboot.
*/
if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST || if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST ||
base_status(status) == MCC_STATUS_ILLEGAL_FIELD) { base_status(status) == MCC_STATUS_ILLEGAL_FIELD) {
/* The current FW image on the card does not support
* OFFSET based flashing. Retry using older mechanism
* of OPTYPE based flashing
*/
if (flash_optype == OPTYPE_OFFSET_SPECIFIED) {
flash_offset_support = false;
goto retry_flash;
}
/* The current FW image on the card does not recognize
* the new FLASH op_type. The FW download is partially
* complete. Reboot the server now to enable FW image
* to recognize the new FLASH op_type. To complete the
* remaining process, download the same FW again after
* the reboot.
*/
dev_err(dev, "Flash incomplete. Reset the server\n"); dev_err(dev, "Flash incomplete. Reset the server\n");
dev_err(dev, "Download FW image again after reset\n"); dev_err(dev, "Download FW image again after reset\n");
return -EAGAIN; return -EAGAIN;
...@@ -4099,7 +4287,19 @@ static int be_flash_skyhawk(struct be_adapter *adapter, ...@@ -4099,7 +4287,19 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
if (p + img_size > fw->data + fw->size) if (p + img_size > fw->data + fw->size)
return -1; return -1;
status = be_flash(adapter, p, flash_cmd, img_optype, img_size); status = be_flash(adapter, p, flash_cmd, flash_optype, img_size,
img_offset);
/* The current FW image on the card does not support OFFSET
* based flashing. Retry using older mechanism of OPTYPE based
* flashing
*/
if (base_status(status) == MCC_STATUS_ILLEGAL_FIELD &&
flash_optype == OPTYPE_OFFSET_SPECIFIED) {
flash_offset_support = false;
goto retry_flash;
}
/* For old FW images ignore ILLEGAL_FIELD error or errors on /* For old FW images ignore ILLEGAL_FIELD error or errors on
* UFI_DIR region * UFI_DIR region
*/ */
...@@ -4202,98 +4402,105 @@ static int lancer_fw_download(struct be_adapter *adapter, ...@@ -4202,98 +4402,105 @@ static int lancer_fw_download(struct be_adapter *adapter,
return 0; return 0;
} }
#define UFI_TYPE2 2 #define BE2_UFI 2
#define UFI_TYPE3 3 #define BE3_UFI 3
#define UFI_TYPE3R 10 #define BE3R_UFI 10
#define UFI_TYPE4 4 #define SH_UFI 4
#define SH_P2_UFI 11
static int be_get_ufi_type(struct be_adapter *adapter, 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) {
goto be_get_ufi_exit; dev_err(&adapter->pdev->dev, "Invalid FW UFI file");
return -1;
}
if (skyhawk_chip(adapter) && fhdr->build[0] == '4') /* First letter of the build version is used to identify
return UFI_TYPE4; * which chip this image file is meant for.
else if (BE3_chip(adapter) && fhdr->build[0] == '3') { */
if (fhdr->asic_type_rev == 0x10) switch (fhdr->build[0]) {
return UFI_TYPE3R; case BLD_STR_UFI_TYPE_SH:
else return (fhdr->asic_type_rev == ASIC_REV_P2) ? SH_P2_UFI :
return UFI_TYPE3; SH_UFI;
} else if (BE2_chip(adapter) && fhdr->build[0] == '2') case BLD_STR_UFI_TYPE_BE3:
return UFI_TYPE2; return (fhdr->asic_type_rev == ASIC_REV_B0) ? BE3R_UFI :
BE3_UFI;
case BLD_STR_UFI_TYPE_BE2:
return BE2_UFI;
default:
return -1;
}
}
be_get_ufi_exit: /* Check if the flash image file is compatible with the adapter that
dev_err(&adapter->pdev->dev, * is being flashed.
"UFI and Interface are not compatible for flashing\n"); * BE3 chips with asic-rev B0 must be flashed only with BE3R_UFI type.
return -1; * 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:
return false;
}
} }
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)
{ {
struct device *dev = &adapter->pdev->dev;
struct flash_file_hdr_g3 *fhdr3; struct flash_file_hdr_g3 *fhdr3;
struct image_hdr *img_hdr_ptr = NULL; struct image_hdr *img_hdr_ptr;
int status = 0, i, num_imgs;
struct be_dma_mem flash_cmd; struct be_dma_mem flash_cmd;
const u8 *p;
int status = 0, i = 0, num_imgs = 0, ufi_type = 0;
flash_cmd.size = sizeof(struct be_cmd_write_flashrom); fhdr3 = (struct flash_file_hdr_g3 *)fw->data;
flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size, if (!be_check_ufi_compatibility(adapter, fhdr3)) {
&flash_cmd.dma, GFP_KERNEL); dev_err(dev, "Flash image is not compatible with adapter\n");
if (!flash_cmd.va) { return -EINVAL;
status = -ENOMEM;
goto be_fw_exit;
} }
p = fw->data; flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
fhdr3 = (struct flash_file_hdr_g3 *)p; flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
GFP_KERNEL);
ufi_type = be_get_ufi_type(adapter, fhdr3); if (!flash_cmd.va)
return -ENOMEM;
num_imgs = le32_to_cpu(fhdr3->num_imgs); num_imgs = le32_to_cpu(fhdr3->num_imgs);
for (i = 0; i < num_imgs; i++) { for (i = 0; i < num_imgs; i++) {
img_hdr_ptr = (struct image_hdr *)(fw->data + img_hdr_ptr = (struct image_hdr *)(fw->data +
(sizeof(struct flash_file_hdr_g3) + (sizeof(struct flash_file_hdr_g3) +
i * sizeof(struct image_hdr))); i * sizeof(struct image_hdr)));
if (le32_to_cpu(img_hdr_ptr->imageid) == 1) { if (!BE2_chip(adapter) &&
switch (ufi_type) { le32_to_cpu(img_hdr_ptr->imageid) != 1)
case UFI_TYPE4: continue;
status = be_flash_skyhawk(adapter, fw,
&flash_cmd, num_imgs);
break;
case UFI_TYPE3R:
status = be_flash_BEx(adapter, fw, &flash_cmd,
num_imgs);
break;
case UFI_TYPE3:
/* Do not flash this ufi on BE3-R cards */
if (adapter->asic_rev < 0x10)
status = be_flash_BEx(adapter, fw,
&flash_cmd,
num_imgs);
else {
status = -EINVAL;
dev_err(&adapter->pdev->dev,
"Can't load BE3 UFI on BE3R\n");
}
}
}
}
if (ufi_type == UFI_TYPE2)
status = be_flash_BEx(adapter, fw, &flash_cmd, 0);
else if (ufi_type == -1)
status = -EINVAL;
dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va, if (skyhawk_chip(adapter))
flash_cmd.dma); status = be_flash_skyhawk(adapter, fw, &flash_cmd,
if (status) { num_imgs);
dev_err(&adapter->pdev->dev, "Firmware load error\n"); else
goto be_fw_exit; status = be_flash_BEx(adapter, fw, &flash_cmd,
num_imgs);
} }
dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n"); dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma);
if (!status)
dev_info(dev, "Firmware flashed successfully\n");
be_fw_exit:
return status; return status;
} }
...@@ -4856,6 +5063,20 @@ static void be_func_recovery_task(struct work_struct *work) ...@@ -4856,6 +5063,20 @@ static void be_func_recovery_task(struct work_struct *work)
msecs_to_jiffies(1000)); msecs_to_jiffies(1000));
} }
static void be_log_sfp_info(struct be_adapter *adapter)
{
int status;
status = be_cmd_query_sfp_info(adapter);
if (!status) {
dev_err(&adapter->pdev->dev,
"Unqualified SFP+ detected on %c from %s part no: %s",
adapter->port_name, adapter->phy.vendor_name,
adapter->phy.vendor_pn);
}
adapter->flags &= ~BE_FLAGS_EVT_INCOMPATIBLE_SFP;
}
static void be_worker(struct work_struct *work) static void be_worker(struct work_struct *work)
{ {
struct be_adapter *adapter = struct be_adapter *adapter =
...@@ -4894,6 +5115,9 @@ static void be_worker(struct work_struct *work) ...@@ -4894,6 +5115,9 @@ static void be_worker(struct work_struct *work)
be_eqd_update(adapter); be_eqd_update(adapter);
if (adapter->flags & BE_FLAGS_EVT_INCOMPATIBLE_SFP)
be_log_sfp_info(adapter);
reschedule: reschedule:
adapter->work_counter++; adapter->work_counter++;
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
...@@ -4940,12 +5164,31 @@ static inline char *func_name(struct be_adapter *adapter) ...@@ -4940,12 +5164,31 @@ static inline char *func_name(struct be_adapter *adapter)
return be_physfn(adapter) ? "PF" : "VF"; return be_physfn(adapter) ? "PF" : "VF";
} }
static inline char *nic_name(struct pci_dev *pdev)
{
switch (pdev->device) {
case OC_DEVICE_ID1:
return OC_NAME;
case OC_DEVICE_ID2:
return OC_NAME_BE;
case OC_DEVICE_ID3:
case OC_DEVICE_ID4:
return OC_NAME_LANCER;
case BE_DEVICE_ID2:
return BE3_NAME;
case OC_DEVICE_ID5:
case OC_DEVICE_ID6:
return OC_NAME_SH;
default:
return BE_NAME;
}
}
static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
{ {
int status = 0;
struct be_adapter *adapter; struct be_adapter *adapter;
struct net_device *netdev; struct net_device *netdev;
char port_name; int status = 0;
dev_info(&pdev->dev, "%s version is %s\n", DRV_NAME, DRV_VER); dev_info(&pdev->dev, "%s version is %s\n", DRV_NAME, DRV_VER);
...@@ -5039,10 +5282,8 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) ...@@ -5039,10 +5282,8 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
schedule_delayed_work(&adapter->func_recovery_work, schedule_delayed_work(&adapter->func_recovery_work,
msecs_to_jiffies(1000)); msecs_to_jiffies(1000));
be_cmd_query_port_name(adapter, &port_name);
dev_info(&pdev->dev, "%s: %s %s port %c\n", nic_name(pdev), dev_info(&pdev->dev, "%s: %s %s port %c\n", nic_name(pdev),
func_name(adapter), mc_name(adapter), port_name); func_name(adapter), mc_name(adapter), adapter->port_name);
return 0; return 0;
......
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