Merge branch 'be2net-next'

Ajit Khaparde says:

====================
be2net Patch series

Please consider applying these two patches to net-next

  Patch-1: Request RSS capability of Rx interface depending on number of
    Rx rings
  Patch-2: Interpret and log new data that's added to the port
    misconfigure async event
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2016-02-11 03:47:05 -05:00
commit dba6cf5560
4 changed files with 163 additions and 55 deletions

View File

@ -115,6 +115,8 @@
#define RSS_INDIR_TABLE_LEN 128
#define RSS_HASH_KEY_LEN 40
#define BE_UNKNOWN_PHY_STATE 0xFF
struct be_dma_mem {
void *va;
dma_addr_t dma;
@ -390,7 +392,7 @@ enum vf_state {
#define BE_FLAGS_QNQ_ASYNC_EVT_RCVD BIT(7)
#define BE_FLAGS_VXLAN_OFFLOADS BIT(8)
#define BE_FLAGS_SETUP_DONE BIT(9)
#define BE_FLAGS_EVT_INCOMPATIBLE_SFP BIT(10)
#define BE_FLAGS_PHY_MISCONFIGURED BIT(10)
#define BE_FLAGS_ERR_DETECTION_SCHEDULED BIT(11)
#define BE_FLAGS_OS2BMC BIT(12)
@ -603,6 +605,7 @@ struct be_adapter {
u32 bmc_filt_mask;
u32 fat_dump_len;
u16 serial_num[CNTL_SERIAL_NUM_WORDS];
u8 phy_state; /* state of sfp optics (functional, faulted, etc.,) */
};
#define be_physfn(adapter) (!adapter->virtfn)

View File

@ -19,19 +19,25 @@
#include "be.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"
char *be_misconfig_evt_port_state[] = {
"Physical Link is functional",
"Optics faulted/incorrectly installed/not installed - Reseat optics. If issue not resolved, replace.",
"Optics of two types installed Remove one optic or install matching pair of optics.",
"Incompatible optics Replace with compatible optics for card to function.",
"Unqualified optics Replace with Avago optics for Warranty and Technical Support.",
"Uncertified optics Replace with Avago-certified optics to enable link operation."
};
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 char *be_port_misconfig_evt_severity[] = {
"KERN_WARN",
"KERN_INFO",
"KERN_ERR",
"KERN_WARN"
};
static char *phy_state_oper_desc[] = {
"Link is non-operational",
"Link is operational",
""
};
@ -297,22 +303,56 @@ static void be_async_port_misconfig_event_process(struct be_adapter *adapter,
{
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);
u32 sfp_misconfig_evt_word1 = le32_to_cpu(evt->event_data_word1);
u32 sfp_misconfig_evt_word2 = le32_to_cpu(evt->event_data_word2);
u8 phy_oper_state = PHY_STATE_OPER_MSG_NONE;
struct device *dev = &adapter->pdev->dev;
u8 port_misconfig_evt;
u8 msg_severity = DEFAULT_MSG_SEVERITY;
u8 phy_state_info;
u8 new_phy_state;
port_misconfig_evt =
((sfp_mismatch_evt >> (adapter->hba_port_num * 8)) & 0xff);
new_phy_state =
(sfp_misconfig_evt_word1 >> (adapter->hba_port_num * 8)) & 0xff;
if (new_phy_state == adapter->phy_state)
return;
adapter->phy_state = new_phy_state;
/* for older fw that doesn't populate link effect data */
if (!sfp_misconfig_evt_word2)
goto log_message;
phy_state_info =
(sfp_misconfig_evt_word2 >> (adapter->hba_port_num * 8)) & 0xff;
if (phy_state_info & PHY_STATE_INFO_VALID) {
msg_severity = (phy_state_info & PHY_STATE_MSG_SEVERITY) >> 1;
if (be_phy_unqualified(new_phy_state))
phy_oper_state = (phy_state_info & PHY_STATE_OPER);
}
log_message:
/* 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 (be_phy_state_unknown(new_phy_state))
dev_printk(be_port_misconfig_evt_severity[msg_severity], dev,
"Port %c: Unrecognized Optics state: 0x%x. %s",
adapter->port_name,
new_phy_state,
phy_state_oper_desc[phy_oper_state]);
else
dev_printk(be_port_misconfig_evt_severity[msg_severity], dev,
"Port %c: %s %s",
adapter->port_name,
be_misconfig_evt_port_state[new_phy_state],
phy_state_oper_desc[phy_oper_state]);
if (port_misconfig_evt == INCOMPATIBLE_SFP)
adapter->flags |= BE_FLAGS_EVT_INCOMPATIBLE_SFP;
/* Log Vendor name and part no. if a misconfigured SFP is detected */
if (be_phy_misconfigured(new_phy_state))
adapter->flags |= BE_FLAGS_PHY_MISCONFIGURED;
}
/* Grp5 CoS Priority evt */
@ -1513,34 +1553,25 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
return status;
}
/* Uses MCCQ */
/* Uses MCCQ if available else MBOX */
int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain)
{
struct be_mcc_wrb *wrb;
struct be_mcc_wrb wrb = {0};
struct be_cmd_req_if_destroy *req;
int status;
if (interface_id == -1)
return 0;
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
if (!wrb) {
status = -EBUSY;
goto err;
}
req = embedded_payload(wrb);
req = embedded_payload(&wrb);
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_NTWK_INTERFACE_DESTROY,
sizeof(*req), wrb, NULL);
sizeof(*req), &wrb, NULL);
req->hdr.domain = domain;
req->interface_id = cpu_to_le32(interface_id);
status = be_mcc_notify_wait(adapter);
err:
spin_unlock_bh(&adapter->mcc_lock);
status = be_cmd_notify_wait(adapter, &wrb);
return status;
}

View File

@ -176,10 +176,53 @@ struct be_async_event_qnq {
u32 flags;
} __packed;
#define INCOMPATIBLE_SFP 0x3
enum {
BE_PHY_FUNCTIONAL = 0,
BE_PHY_NOT_PRESENT = 1,
BE_PHY_DIFF_MEDIA = 2,
BE_PHY_INCOMPATIBLE = 3,
BE_PHY_UNQUALIFIED = 4,
BE_PHY_UNCERTIFIED = 5
};
#define PHY_STATE_MSG_SEVERITY 0x6
#define PHY_STATE_OPER 0x1
#define PHY_STATE_INFO_VALID 0x80
#define PHY_STATE_OPER_MSG_NONE 0x2
#define DEFAULT_MSG_SEVERITY 0x1
#define be_phy_state_unknown(phy_state) (phy_state > BE_PHY_UNCERTIFIED)
#define be_phy_unqualified(phy_state) \
(phy_state == BE_PHY_UNQUALIFIED || \
phy_state == BE_PHY_UNCERTIFIED)
#define be_phy_misconfigured(phy_state) \
(phy_state == BE_PHY_INCOMPATIBLE || \
phy_state == BE_PHY_UNQUALIFIED || \
phy_state == BE_PHY_UNCERTIFIED)
extern char *be_misconfig_evt_port_state[];
/* async event indicating misconfigured port */
struct be_async_event_misconfig_port {
/* DATA_WORD1:
* phy state of port 0: bits 7 - 0
* phy state of port 1: bits 15 - 8
* phy state of port 2: bits 23 - 16
* phy state of port 3: bits 31 - 24
*/
u32 event_data_word1;
/* DATA_WORD2:
* phy state info of port 0: bits 7 - 0
* phy state info of port 1: bits 15 - 8
* phy state info of port 2: bits 23 - 16
* phy state info of port 3: bits 31 - 24
*
* PHY STATE INFO:
* Link operability :bit 0
* Message severity :bit 2 - 1
* Rsvd :bits 6 - 3
* phy state info valid :bit 7
*/
u32 event_data_word2;
u32 rsvd0;
u32 flags;

View File

@ -3365,6 +3365,7 @@ done:
static void be_rx_qs_destroy(struct be_adapter *adapter)
{
struct rss_info *rss = &adapter->rss_info;
struct be_queue_info *q;
struct be_rx_obj *rxo;
int i;
@ -3391,6 +3392,12 @@ static void be_rx_qs_destroy(struct be_adapter *adapter)
}
be_queue_free(adapter, q);
}
if (rss->rss_flags) {
rss->rss_flags = RSS_ENABLE_NONE;
be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags,
128, rss->rss_hkey);
}
}
static void be_disable_if_filters(struct be_adapter *adapter)
@ -3511,20 +3518,21 @@ static int be_rx_qs_create(struct be_adapter *adapter)
if (!BEx_chip(adapter))
rss->rss_flags |= RSS_ENABLE_UDP_IPV4 |
RSS_ENABLE_UDP_IPV6;
netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN);
rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags,
RSS_INDIR_TABLE_LEN, rss_key);
if (rc) {
rss->rss_flags = RSS_ENABLE_NONE;
return rc;
}
memcpy(rss->rss_hkey, rss_key, RSS_HASH_KEY_LEN);
} else {
/* Disable RSS, if only default RX Q is created */
rss->rss_flags = RSS_ENABLE_NONE;
}
netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN);
rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags,
RSS_INDIR_TABLE_LEN, rss_key);
if (rc) {
rss->rss_flags = RSS_ENABLE_NONE;
return rc;
}
memcpy(rss->rss_hkey, rss_key, RSS_HASH_KEY_LEN);
/* Post 1 less than RXQ-len to avoid head being equal to tail,
* which is a queue empty condition
@ -4081,6 +4089,7 @@ static void be_setup_init(struct be_adapter *adapter)
adapter->if_handle = -1;
adapter->be3_native = false;
adapter->if_flags = 0;
adapter->phy_state = BE_UNKNOWN_PHY_STATE;
if (be_physfn(adapter))
adapter->cmd_privileges = MAX_PRIVILEGES;
else
@ -4306,6 +4315,23 @@ err:
return status;
}
static int be_if_create(struct be_adapter *adapter)
{
u32 en_flags = BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS;
u32 cap_flags = be_if_cap_flags(adapter);
int status;
if (adapter->cfg_num_qs == 1)
cap_flags &= ~(BE_IF_FLAGS_DEFQ_RSS | BE_IF_FLAGS_RSS);
en_flags &= cap_flags;
/* will enable all the needed filter flags in be_open() */
status = be_cmd_if_create(adapter, be_if_cap_flags(adapter), en_flags,
&adapter->if_handle, 0);
return status;
}
int be_update_queues(struct be_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@ -4323,6 +4349,9 @@ int be_update_queues(struct be_adapter *adapter)
be_msix_disable(adapter);
be_clear_queues(adapter);
status = be_cmd_if_destroy(adapter, adapter->if_handle, 0);
if (status)
return status;
if (!msix_enabled(adapter)) {
status = be_msix_enable(adapter);
@ -4330,6 +4359,10 @@ int be_update_queues(struct be_adapter *adapter)
return status;
}
status = be_if_create(adapter);
if (status)
return status;
status = be_setup_queues(adapter);
if (status)
return status;
@ -4394,7 +4427,6 @@ static int be_func_init(struct be_adapter *adapter)
static int be_setup(struct be_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
u32 en_flags;
int status;
status = be_func_init(adapter);
@ -4427,10 +4459,7 @@ static int be_setup(struct be_adapter *adapter)
goto err;
/* will enable all the needed filter flags in be_open() */
en_flags = BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS;
en_flags = en_flags & be_if_cap_flags(adapter);
status = be_cmd_if_create(adapter, be_if_cap_flags(adapter), en_flags,
&adapter->if_handle, 0);
status = be_if_create(adapter);
if (status)
goto err;
@ -4803,7 +4832,7 @@ static void be_netdev_init(struct net_device *netdev)
netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |
NETIF_F_HW_VLAN_CTAG_TX;
if (be_multi_rxq(adapter))
if ((be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
netdev->hw_features |= NETIF_F_RXHASH;
netdev->features |= netdev->hw_features |
@ -4933,11 +4962,13 @@ static void be_log_sfp_info(struct be_adapter *adapter)
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,
"Port %c: %s Vendor: %s part no: %s",
adapter->port_name,
be_misconfig_evt_port_state[adapter->phy_state],
adapter->phy.vendor_name,
adapter->phy.vendor_pn);
}
adapter->flags &= ~BE_FLAGS_EVT_INCOMPATIBLE_SFP;
adapter->flags &= ~BE_FLAGS_PHY_MISCONFIGURED;
}
static void be_worker(struct work_struct *work)
@ -4981,7 +5012,7 @@ static void be_worker(struct work_struct *work)
if (!skyhawk_chip(adapter))
be_eqd_update(adapter, false);
if (adapter->flags & BE_FLAGS_EVT_INCOMPATIBLE_SFP)
if (adapter->flags & BE_FLAGS_PHY_MISCONFIGURED)
be_log_sfp_info(adapter);
reschedule: