be2net: refactor multi-channel config code for Skyhawk-R chip

Currently multi-channel configuration is read via the QUERY_FW_CONFIG cmd.
This method has been deprecated by the Skyhawk-R FW. Instead,
GET_PROFILE_CONFIG::port-desc must be used to query this configuration.

This patch also:
a) introduces a few macros to identify certain categories of multi-channel
configs
2) re-factors the be_cmd_set_profile_config() code to be able to read any kind
of desc (and not just the nic-desc.)

Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com>
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Vasundhara Volam 2014-02-12 16:09:25 +05:30 committed by David S. Miller
parent 40263820b4
commit f93f160b5a
5 changed files with 127 additions and 32 deletions

View File

@ -88,7 +88,6 @@ static inline char *nic_name(struct pci_dev *pdev)
#define BE_MIN_MTU 256
#define BE_NUM_VLANS_SUPPORTED 64
#define BE_UMC_NUM_VLANS_SUPPORTED 15
#define BE_MAX_EQD 128u
#define BE_MAX_TX_FRAG_COUNT 30
@ -293,7 +292,7 @@ struct be_rx_compl_info {
u8 ip_csum;
u8 l4_csum;
u8 ipv6;
u8 vtm;
u8 qnq;
u8 pkt_type;
u8 ip_frag;
};
@ -465,6 +464,7 @@ struct be_adapter {
u32 port_num;
bool promiscuous;
u8 mc_type;
u32 function_mode;
u32 function_caps;
u32 rx_fc; /* Rx flow control */
@ -534,6 +534,14 @@ static inline u16 be_max_qs(struct be_adapter *adapter)
return min_t(u16, num, num_online_cpus());
}
/* Is BE in pvid_tagging mode */
#define be_pvid_tagging_enabled(adapter) (adapter->pvid)
/* Is BE in QNQ multi-channel mode */
#define be_is_qnq_mode(adapter) (adapter->mc_type == FLEX10 || \
adapter->mc_type == vNIC1 || \
adapter->mc_type == UFP)
#define lancer_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID3 || \
adapter->pdev->device == OC_DEVICE_ID4)

View File

@ -3296,6 +3296,21 @@ static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf,
return NULL;
}
static struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count)
{
struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
int i;
for (i = 0; i < desc_count; i++) {
if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1)
return (struct be_port_res_desc *)hdr;
hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
hdr = (void *)hdr + hdr->desc_len;
}
return NULL;
}
static void be_copy_nic_desc(struct be_resources *res,
struct be_nic_res_desc *desc)
{
@ -3439,6 +3454,7 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
{
struct be_cmd_resp_get_profile_config *resp;
struct be_pcie_res_desc *pcie;
struct be_port_res_desc *port;
struct be_nic_res_desc *nic;
struct be_queue_info *mccq = &adapter->mcc_obj.q;
struct be_dma_mem cmd;
@ -3466,6 +3482,10 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
if (pcie)
res->max_vfs = le16_to_cpu(pcie->num_vfs);
port = be_get_port_desc(resp->func_param, desc_count);
if (port)
adapter->mc_type = port->mc_type;
nic = be_get_nic_desc(resp->func_param, desc_count);
if (nic)
be_copy_nic_desc(res, nic);

View File

@ -1098,14 +1098,6 @@ struct be_cmd_resp_query_fw_cfg {
u32 function_caps;
};
/* Is BE in a multi-channel mode */
static inline bool be_is_mc(struct be_adapter *adapter)
{
return adapter->function_mode & FLEX10_MODE ||
adapter->function_mode & VNIC_MODE ||
adapter->function_mode & UMC_ENABLED;
}
/******************** RSS Config ****************************************/
/* RSS type Input parameters used to compute RX hash
* RSS_ENABLE_IPV4 SRC IPv4, DST IPv4
@ -1828,6 +1820,7 @@ struct be_cmd_req_set_ext_fat_caps {
#define NIC_RESOURCE_DESC_TYPE_V0 0x41
#define PCIE_RESOURCE_DESC_TYPE_V1 0x50
#define NIC_RESOURCE_DESC_TYPE_V1 0x51
#define PORT_RESOURCE_DESC_TYPE_V1 0x55
#define MAX_RESOURCE_DESC 264
/* QOS unit number */
@ -1891,6 +1884,33 @@ struct be_nic_res_desc {
u32 rsvd8[7];
} __packed;
/************ Multi-Channel type ***********/
enum mc_type {
MC_NONE = 0x01,
UMC = 0x02,
FLEX10 = 0x03,
vNIC1 = 0x04,
nPAR = 0x05,
UFP = 0x06,
vNIC2 = 0x07
};
struct be_port_res_desc {
struct be_res_desc_hdr hdr;
u8 rsvd0;
u8 flags;
u8 rsvd1;
u8 mc_type;
u16 rsvd2;
u32 rsvd3[20];
} __packed;
/* Is BE in a multi-channel mode */
static inline bool be_is_mc(struct be_adapter *adapter)
{
return adapter->mc_type > MC_NONE;
}
struct be_cmd_req_get_func_config {
struct be_cmd_req_hdr hdr;
};

View File

@ -368,7 +368,7 @@ struct amap_eth_rx_compl_v0 {
u8 numfrags[3]; /* dword 1 */
u8 rss_flush; /* dword 2 */
u8 cast_enc[2]; /* dword 2 */
u8 vtm; /* dword 2 */
u8 qnq; /* dword 2 */
u8 rss_bank; /* dword 2 */
u8 rsvd1[23]; /* dword 2 */
u8 lro_pkt; /* dword 2 */
@ -401,7 +401,7 @@ struct amap_eth_rx_compl_v1 {
u8 numfrags[3]; /* dword 1 */
u8 rss_flush; /* dword 2 */
u8 cast_enc[2]; /* dword 2 */
u8 vtm; /* dword 2 */
u8 qnq; /* dword 2 */
u8 rss_bank; /* dword 2 */
u8 port[2]; /* dword 2 */
u8 vntagp; /* dword 2 */

View File

@ -945,9 +945,9 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
}
/* If vlan tag is already inlined in the packet, skip HW VLAN
* tagging in UMC mode
* tagging in pvid-tagging mode
*/
if ((adapter->function_mode & UMC_ENABLED) &&
if (be_pvid_tagging_enabled(adapter) &&
veh->h_vlan_proto == htons(ETH_P_8021Q))
*skip_hw_vlan = true;
@ -1660,7 +1660,7 @@ static void be_parse_rx_compl_v1(struct be_eth_rx_compl *compl,
rxcp->rss_hash =
AMAP_GET_BITS(struct amap_eth_rx_compl_v1, rsshash, compl);
if (rxcp->vlanf) {
rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm,
rxcp->qnq = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, qnq,
compl);
rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag,
compl);
@ -1690,7 +1690,7 @@ static void be_parse_rx_compl_v0(struct be_eth_rx_compl *compl,
rxcp->rss_hash =
AMAP_GET_BITS(struct amap_eth_rx_compl_v0, rsshash, compl);
if (rxcp->vlanf) {
rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm,
rxcp->qnq = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, qnq,
compl);
rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag,
compl);
@ -1723,9 +1723,11 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
rxcp->l4_csum = 0;
if (rxcp->vlanf) {
/* vlanf could be wrongly set in some cards.
* ignore if vtm is not set */
if ((adapter->function_mode & FLEX10_MODE) && !rxcp->vtm)
/* In QNQ modes, if qnq bit is not set, then the packet was
* tagged only with the transparent outer vlan-tag and must
* not be treated as a vlan packet by host
*/
if (be_is_qnq_mode(adapter) && !rxcp->qnq)
rxcp->vlanf = 0;
if (!lancer_chip(adapter))
@ -3109,6 +3111,22 @@ err:
return status;
}
/* Converting function_mode bits on BE3 to SH mc_type enums */
static u8 be_convert_mc_type(u32 function_mode)
{
if (function_mode & VNIC_MODE && function_mode & FLEX10_MODE)
return vNIC1;
else if (function_mode & FLEX10_MODE)
return FLEX10;
else if (function_mode & VNIC_MODE)
return vNIC2;
else if (function_mode & UMC_ENABLED)
return UMC;
else
return MC_NONE;
}
/* On BE2/BE3 FW does not suggest the supported limits */
static void BEx_get_resources(struct be_adapter *adapter,
struct be_resources *res)
@ -3129,12 +3147,23 @@ static void BEx_get_resources(struct be_adapter *adapter,
else
res->max_uc_mac = BE_VF_UC_PMAC_COUNT;
if (adapter->function_mode & FLEX10_MODE)
res->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
else if (adapter->function_mode & UMC_ENABLED)
res->max_vlans = BE_UMC_NUM_VLANS_SUPPORTED;
else
adapter->mc_type = be_convert_mc_type(adapter->function_mode);
if (be_is_mc(adapter)) {
/* Assuming that there are 4 channels per port,
* when multi-channel is enabled
*/
if (be_is_qnq_mode(adapter))
res->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
else
/* In a non-qnq multichannel mode, the pvid
* takes up one vlan entry
*/
res->max_vlans = (BE_NUM_VLANS_SUPPORTED / 4) - 1;
} else {
res->max_vlans = BE_NUM_VLANS_SUPPORTED;
}
res->max_mcast_mac = BE_MAX_MC;
/* For BE3 1Gb ports, F/W does not properly support multiple TXQs */
@ -4417,14 +4446,32 @@ static bool be_reset_required(struct be_adapter *adapter)
static char *mc_name(struct be_adapter *adapter)
{
if (adapter->function_mode & FLEX10_MODE)
return "FLEX10";
else if (adapter->function_mode & VNIC_MODE)
return "vNIC";
else if (adapter->function_mode & UMC_ENABLED)
return "UMC";
else
return "";
char *str = ""; /* default */
switch (adapter->mc_type) {
case UMC:
str = "UMC";
break;
case FLEX10:
str = "FLEX10";
break;
case vNIC1:
str = "vNIC-1";
break;
case nPAR:
str = "nPAR";
break;
case UFP:
str = "UFP";
break;
case vNIC2:
str = "vNIC-2";
break;
default:
str = "";
}
return str;
}
static inline char *func_name(struct be_adapter *adapter)