提交 ce9355ac 编写于 作者: D David S. Miller

Merge branch 'bnxt_en-updates'

Michael Chan says:

====================
bnxt_en: Updates for net-next.

-Add default VLAN support for VFs.
-Add NPAR (NIC partioning) support.
-Add support for new device 5731x and 5741x. GRO logic is different.
-Support new ETHTOOL_{G|S}LINKSETTINGS.
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
......@@ -75,12 +75,22 @@ enum board_idx {
BCM57301,
BCM57302,
BCM57304,
BCM57311,
BCM57312,
BCM57402,
BCM57404,
BCM57406,
BCM57404_NPAR,
BCM57412,
BCM57414,
BCM57416,
BCM57417,
BCM57414_NPAR,
BCM57314,
BCM57304_VF,
BCM57404_VF,
BCM57414_VF,
BCM57314_VF,
};
/* indexed by enum above */
......@@ -90,25 +100,45 @@ static const struct {
{ "Broadcom BCM57301 NetXtreme-C Single-port 10Gb Ethernet" },
{ "Broadcom BCM57302 NetXtreme-C Dual-port 10Gb/25Gb Ethernet" },
{ "Broadcom BCM57304 NetXtreme-C Dual-port 10Gb/25Gb/40Gb/50Gb Ethernet" },
{ "Broadcom BCM57311 NetXtreme-C Single-port 10Gb Ethernet" },
{ "Broadcom BCM57312 NetXtreme-C Dual-port 10Gb/25Gb Ethernet" },
{ "Broadcom BCM57402 NetXtreme-E Dual-port 10Gb Ethernet" },
{ "Broadcom BCM57404 NetXtreme-E Dual-port 10Gb/25Gb Ethernet" },
{ "Broadcom BCM57406 NetXtreme-E Dual-port 10GBase-T Ethernet" },
{ "Broadcom BCM57404 NetXtreme-E Ethernet Partition" },
{ "Broadcom BCM57412 NetXtreme-E Dual-port 10Gb Ethernet" },
{ "Broadcom BCM57414 NetXtreme-E Dual-port 10Gb/25Gb Ethernet" },
{ "Broadcom BCM57416 NetXtreme-E Dual-port 10GBase-T Ethernet" },
{ "Broadcom BCM57417 NetXtreme-E Dual-port 10GBase-T Ethernet" },
{ "Broadcom BCM57414 NetXtreme-E Ethernet Partition" },
{ "Broadcom BCM57314 NetXtreme-C Dual-port 10Gb/25Gb/40Gb/50Gb Ethernet" },
{ "Broadcom BCM57304 NetXtreme-C Ethernet Virtual Function" },
{ "Broadcom BCM57404 NetXtreme-E Ethernet Virtual Function" },
{ "Broadcom BCM57414 NetXtreme-E Ethernet Virtual Function" },
{ "Broadcom BCM57314 NetXtreme-E Ethernet Virtual Function" },
};
static const struct pci_device_id bnxt_pci_tbl[] = {
{ PCI_VDEVICE(BROADCOM, 0x16c8), .driver_data = BCM57301 },
{ PCI_VDEVICE(BROADCOM, 0x16c9), .driver_data = BCM57302 },
{ PCI_VDEVICE(BROADCOM, 0x16ca), .driver_data = BCM57304 },
{ PCI_VDEVICE(BROADCOM, 0x16ce), .driver_data = BCM57311 },
{ PCI_VDEVICE(BROADCOM, 0x16cf), .driver_data = BCM57312 },
{ PCI_VDEVICE(BROADCOM, 0x16d0), .driver_data = BCM57402 },
{ PCI_VDEVICE(BROADCOM, 0x16d1), .driver_data = BCM57404 },
{ PCI_VDEVICE(BROADCOM, 0x16d2), .driver_data = BCM57406 },
{ PCI_VDEVICE(BROADCOM, 0x16d4), .driver_data = BCM57404_NPAR },
{ PCI_VDEVICE(BROADCOM, 0x16d6), .driver_data = BCM57412 },
{ PCI_VDEVICE(BROADCOM, 0x16d7), .driver_data = BCM57414 },
{ PCI_VDEVICE(BROADCOM, 0x16d8), .driver_data = BCM57416 },
{ PCI_VDEVICE(BROADCOM, 0x16d9), .driver_data = BCM57417 },
{ PCI_VDEVICE(BROADCOM, 0x16de), .driver_data = BCM57414_NPAR },
{ PCI_VDEVICE(BROADCOM, 0x16df), .driver_data = BCM57314 },
#ifdef CONFIG_BNXT_SRIOV
{ PCI_VDEVICE(BROADCOM, 0x16cb), .driver_data = BCM57304_VF },
{ PCI_VDEVICE(BROADCOM, 0x16d3), .driver_data = BCM57404_VF },
{ PCI_VDEVICE(BROADCOM, 0x16dc), .driver_data = BCM57414_VF },
{ PCI_VDEVICE(BROADCOM, 0x16e1), .driver_data = BCM57314_VF },
#endif
{ 0 }
};
......@@ -125,12 +155,14 @@ static const u16 bnxt_async_events_arr[] = {
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE,
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD,
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED,
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE,
HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE,
};
static bool bnxt_vf_pciid(enum board_idx idx)
{
return (idx == BCM57304_VF || idx == BCM57404_VF);
return (idx == BCM57304_VF || idx == BCM57404_VF ||
idx == BCM57314_VF || idx == BCM57414_VF);
}
#define DB_CP_REARM_FLAGS (DB_KEY_CP | DB_IDX_VALID)
......@@ -920,6 +952,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
}
tpa_info->flags2 = le32_to_cpu(tpa_start1->rx_tpa_start_cmp_flags2);
tpa_info->metadata = le32_to_cpu(tpa_start1->rx_tpa_start_cmp_metadata);
tpa_info->hdr_info = le32_to_cpu(tpa_start1->rx_tpa_start_cmp_hdr_info);
rxr->rx_prod = NEXT_RX(prod);
cons = NEXT_RX(cons);
......@@ -938,32 +971,102 @@ static void bnxt_abort_tpa(struct bnxt *bp, struct bnxt_napi *bnapi,
bnxt_reuse_rx_agg_bufs(bnapi, cp_cons, agg_bufs);
}
static struct sk_buff *bnxt_gro_func_5731x(struct bnxt_tpa_info *tpa_info,
int payload_off, int tcp_ts,
struct sk_buff *skb)
{
#ifdef CONFIG_INET
struct tcphdr *th;
int len, nw_off;
u16 outer_ip_off, inner_ip_off, inner_mac_off;
u32 hdr_info = tpa_info->hdr_info;
bool loopback = false;
inner_ip_off = BNXT_TPA_INNER_L3_OFF(hdr_info);
inner_mac_off = BNXT_TPA_INNER_L2_OFF(hdr_info);
outer_ip_off = BNXT_TPA_OUTER_L3_OFF(hdr_info);
/* If the packet is an internal loopback packet, the offsets will
* have an extra 4 bytes.
*/
if (inner_mac_off == 4) {
loopback = true;
} else if (inner_mac_off > 4) {
__be16 proto = *((__be16 *)(skb->data + inner_ip_off -
ETH_HLEN - 2));
/* We only support inner iPv4/ipv6. If we don't see the
* correct protocol ID, it must be a loopback packet where
* the offsets are off by 4.
*/
if (proto != htons(ETH_P_IP) && proto && htons(ETH_P_IPV6))
loopback = true;
}
if (loopback) {
/* internal loopback packet, subtract all offsets by 4 */
inner_ip_off -= 4;
inner_mac_off -= 4;
outer_ip_off -= 4;
}
nw_off = inner_ip_off - ETH_HLEN;
skb_set_network_header(skb, nw_off);
if (tpa_info->flags2 & RX_TPA_START_CMP_FLAGS2_IP_TYPE) {
struct ipv6hdr *iph = ipv6_hdr(skb);
skb_set_transport_header(skb, nw_off + sizeof(struct ipv6hdr));
len = skb->len - skb_transport_offset(skb);
th = tcp_hdr(skb);
th->check = ~tcp_v6_check(len, &iph->saddr, &iph->daddr, 0);
} else {
struct iphdr *iph = ip_hdr(skb);
skb_set_transport_header(skb, nw_off + sizeof(struct iphdr));
len = skb->len - skb_transport_offset(skb);
th = tcp_hdr(skb);
th->check = ~tcp_v4_check(len, iph->saddr, iph->daddr, 0);
}
if (inner_mac_off) { /* tunnel */
struct udphdr *uh = NULL;
__be16 proto = *((__be16 *)(skb->data + outer_ip_off -
ETH_HLEN - 2));
if (proto == htons(ETH_P_IP)) {
struct iphdr *iph = (struct iphdr *)skb->data;
if (iph->protocol == IPPROTO_UDP)
uh = (struct udphdr *)(iph + 1);
} else {
struct ipv6hdr *iph = (struct ipv6hdr *)skb->data;
if (iph->nexthdr == IPPROTO_UDP)
uh = (struct udphdr *)(iph + 1);
}
if (uh) {
if (uh->check)
skb_shinfo(skb)->gso_type |=
SKB_GSO_UDP_TUNNEL_CSUM;
else
skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL;
}
}
#endif
return skb;
}
#define BNXT_IPV4_HDR_SIZE (sizeof(struct iphdr) + sizeof(struct tcphdr))
#define BNXT_IPV6_HDR_SIZE (sizeof(struct ipv6hdr) + sizeof(struct tcphdr))
static inline struct sk_buff *bnxt_gro_skb(struct bnxt_tpa_info *tpa_info,
struct rx_tpa_end_cmp *tpa_end,
struct rx_tpa_end_cmp_ext *tpa_end1,
static struct sk_buff *bnxt_gro_func_5730x(struct bnxt_tpa_info *tpa_info,
int payload_off, int tcp_ts,
struct sk_buff *skb)
{
#ifdef CONFIG_INET
struct tcphdr *th;
int payload_off, tcp_opt_len = 0;
int len, nw_off;
u16 segs;
int len, nw_off, tcp_opt_len;
segs = TPA_END_TPA_SEGS(tpa_end);
if (segs == 1)
return skb;
NAPI_GRO_CB(skb)->count = segs;
skb_shinfo(skb)->gso_size =
le32_to_cpu(tpa_end1->rx_tpa_end_cmp_seg_len);
skb_shinfo(skb)->gso_type = tpa_info->gso_type;
payload_off = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) &
RX_TPA_END_CMP_PAYLOAD_OFFSET) >>
RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT;
if (TPA_END_GRO_TS(tpa_end))
if (tcp_ts)
tcp_opt_len = 12;
if (tpa_info->gso_type == SKB_GSO_TCPV4) {
......@@ -1020,6 +1123,32 @@ static inline struct sk_buff *bnxt_gro_skb(struct bnxt_tpa_info *tpa_info,
return skb;
}
static inline struct sk_buff *bnxt_gro_skb(struct bnxt *bp,
struct bnxt_tpa_info *tpa_info,
struct rx_tpa_end_cmp *tpa_end,
struct rx_tpa_end_cmp_ext *tpa_end1,
struct sk_buff *skb)
{
#ifdef CONFIG_INET
int payload_off;
u16 segs;
segs = TPA_END_TPA_SEGS(tpa_end);
if (segs == 1)
return skb;
NAPI_GRO_CB(skb)->count = segs;
skb_shinfo(skb)->gso_size =
le32_to_cpu(tpa_end1->rx_tpa_end_cmp_seg_len);
skb_shinfo(skb)->gso_type = tpa_info->gso_type;
payload_off = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) &
RX_TPA_END_CMP_PAYLOAD_OFFSET) >>
RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT;
skb = bp->gro_func(tpa_info, payload_off, TPA_END_GRO_TS(tpa_end), skb);
#endif
return skb;
}
static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
struct bnxt_napi *bnapi,
u32 *raw_cons,
......@@ -1130,7 +1259,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
}
if (TPA_END_GRO(tpa_end))
skb = bnxt_gro_skb(tpa_info, tpa_end, tpa_end1, skb);
skb = bnxt_gro_skb(bp, tpa_info, tpa_end, tpa_end1, skb);
return skb;
}
......@@ -1358,6 +1487,11 @@ static int bnxt_async_event_process(struct bnxt *bp,
set_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event);
break;
}
case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE:
if (BNXT_PF(bp))
goto async_event_process_exit;
set_bit(BNXT_RESET_TASK_SILENT_SP_EVENT, &bp->sp_event);
break;
default:
netdev_err(bp->dev, "unhandled ASYNC event (id 0x%x)\n",
event_id);
......@@ -2262,7 +2396,7 @@ static void bnxt_set_tpa_flags(struct bnxt *bp)
bp->flags &= ~BNXT_FLAG_TPA;
if (bp->dev->features & NETIF_F_LRO)
bp->flags |= BNXT_FLAG_LRO;
if ((bp->dev->features & NETIF_F_GRO) && (bp->pdev->revision > 0))
if (bp->dev->features & NETIF_F_GRO)
bp->flags |= BNXT_FLAG_GRO;
}
......@@ -3277,6 +3411,7 @@ static int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id)
unsigned int ring = 0, grp_idx;
struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
struct hwrm_vnic_cfg_input req = {0};
u16 def_vlan = 0;
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_CFG, -1, -1);
/* Only RSS support for now TBD: COS & LB */
......@@ -3297,7 +3432,11 @@ static int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id)
req.mru = cpu_to_le16(bp->dev->mtu + ETH_HLEN + ETH_FCS_LEN +
VLAN_HLEN);
if (bp->flags & BNXT_FLAG_STRIP_VLAN)
#ifdef CONFIG_BNXT_SRIOV
if (BNXT_VF(bp))
def_vlan = bp->vf.vlan;
#endif
if ((bp->flags & BNXT_FLAG_STRIP_VLAN) || def_vlan)
req.flags |= cpu_to_le32(VNIC_CFG_REQ_FLAGS_VLAN_STRIP_MODE);
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
......@@ -3836,6 +3975,39 @@ static int bnxt_hwrm_stat_ctx_alloc(struct bnxt *bp)
return 0;
}
static int bnxt_hwrm_func_qcfg(struct bnxt *bp)
{
struct hwrm_func_qcfg_input req = {0};
struct hwrm_func_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
int rc;
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCFG, -1, -1);
req.fid = cpu_to_le16(0xffff);
mutex_lock(&bp->hwrm_cmd_lock);
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
if (rc)
goto func_qcfg_exit;
#ifdef CONFIG_BNXT_SRIOV
if (BNXT_VF(bp)) {
struct bnxt_vf_info *vf = &bp->vf;
vf->vlan = le16_to_cpu(resp->vlan) & VLAN_VID_MASK;
}
#endif
switch (resp->port_partition_type) {
case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_0:
case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_5:
case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR2_0:
bp->port_partition_type = resp->port_partition_type;
break;
}
func_qcfg_exit:
mutex_unlock(&bp->hwrm_cmd_lock);
return rc;
}
int bnxt_hwrm_func_qcaps(struct bnxt *bp)
{
int rc = 0;
......@@ -3990,6 +4162,8 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp)
if (resp->hwrm_intf_maj >= 1)
bp->hwrm_max_req_len = le16_to_cpu(resp->max_req_win_len);
bp->chip_num = le16_to_cpu(resp->chip_num);
hwrm_ver_get_exit:
mutex_unlock(&bp->hwrm_cmd_lock);
return rc;
......@@ -4230,6 +4404,11 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
netdev_warn(bp->dev, "HWRM set coalescing failure rc: %x\n",
rc);
if (BNXT_VF(bp)) {
bnxt_hwrm_func_qcfg(bp);
netdev_update_features(bp->dev);
}
return 0;
err_out:
......@@ -4644,6 +4823,7 @@ static int bnxt_hwrm_phy_qcaps(struct bnxt *bp)
int rc = 0;
struct hwrm_port_phy_qcaps_input req = {0};
struct hwrm_port_phy_qcaps_output *resp = bp->hwrm_cmd_resp_addr;
struct bnxt_link_info *link_info = &bp->link_info;
if (bp->hwrm_spec_code < 0x10201)
return 0;
......@@ -4666,6 +4846,8 @@ static int bnxt_hwrm_phy_qcaps(struct bnxt *bp)
bp->lpi_tmr_hi = le32_to_cpu(resp->valid_tx_lpi_timer_high) &
PORT_PHY_QCAPS_RESP_TX_LPI_TIMER_HIGH_MASK;
}
link_info->support_auto_speeds =
le16_to_cpu(resp->supported_speeds_auto_mode);
hwrm_phy_qcaps_exit:
mutex_unlock(&bp->hwrm_cmd_lock);
......@@ -4923,7 +5105,7 @@ static int bnxt_hwrm_shutdown_link(struct bnxt *bp)
{
struct hwrm_port_phy_cfg_input req = {0};
if (BNXT_VF(bp))
if (!BNXT_SINGLE_PF(bp))
return 0;
if (pci_num_vf(bp->pdev))
......@@ -5469,7 +5651,14 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
features |= NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_STAG_RX;
}
#ifdef CONFIG_BNXT_SRIOV
if (BNXT_VF(bp)) {
if (bp->vf.vlan) {
features &= ~(NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_STAG_RX);
}
}
#endif
return features;
}
......@@ -5585,9 +5774,10 @@ static void bnxt_dbg_dump_states(struct bnxt *bp)
}
}
static void bnxt_reset_task(struct bnxt *bp)
static void bnxt_reset_task(struct bnxt *bp, bool silent)
{
bnxt_dbg_dump_states(bp);
if (!silent)
bnxt_dbg_dump_states(bp);
if (netif_running(bp->dev)) {
bnxt_close_nic(bp, false, false);
bnxt_open_nic(bp, false, false);
......@@ -5638,6 +5828,23 @@ static void bnxt_timer(unsigned long data)
mod_timer(&bp->timer, jiffies + bp->current_interval);
}
/* Only called from bnxt_sp_task() */
static void bnxt_reset(struct bnxt *bp, bool silent)
{
/* bnxt_reset_task() calls bnxt_close_nic() which waits
* for BNXT_STATE_IN_SP_TASK to clear.
* If there is a parallel dev_close(), bnxt_close() may be holding
* rtnl() and waiting for BNXT_STATE_IN_SP_TASK to clear. So we
* must clear BNXT_STATE_IN_SP_TASK before holding rtnl().
*/
clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
rtnl_lock();
if (test_bit(BNXT_STATE_OPEN, &bp->state))
bnxt_reset_task(bp, silent);
set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
rtnl_unlock();
}
static void bnxt_cfg_ntp_filters(struct bnxt *);
static void bnxt_sp_task(struct work_struct *work)
......@@ -5674,16 +5881,11 @@ static void bnxt_sp_task(struct work_struct *work)
bnxt_hwrm_tunnel_dst_port_free(
bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN);
}
if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event)) {
/* bnxt_reset_task() calls bnxt_close_nic() which waits
* for BNXT_STATE_IN_SP_TASK to clear.
*/
clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
rtnl_lock();
bnxt_reset_task(bp);
set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
rtnl_unlock();
}
if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
bnxt_reset(bp, false);
if (test_and_clear_bit(BNXT_RESET_TASK_SILENT_SP_EVENT, &bp->sp_event))
bnxt_reset(bp, true);
if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event))
bnxt_get_port_module_status(bp);
......@@ -6169,6 +6371,12 @@ static int bnxt_probe_phy(struct bnxt *bp)
return rc;
}
/* Older firmware does not have supported_auto_speeds, so assume
* that all supported speeds can be autonegotiated.
*/
if (link_info->auto_link_speeds && !link_info->support_auto_speeds)
link_info->support_auto_speeds = link_info->support_speeds;
/*initialize the ethool setting copy with NVM settings */
if (BNXT_AUTO_MODE(link_info->auto_mode)) {
link_info->autoneg = BNXT_AUTONEG_SPEED;
......@@ -6342,7 +6550,13 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto init_err;
mutex_init(&bp->hwrm_cmd_lock);
bnxt_hwrm_ver_get(bp);
rc = bnxt_hwrm_ver_get(bp);
if (rc)
goto init_err;
bp->gro_func = bnxt_gro_func_5730x;
if (BNXT_CHIP_NUM_57X1X(bp->chip_num))
bp->gro_func = bnxt_gro_func_5731x;
rc = bnxt_hwrm_func_drv_rgtr(bp);
if (rc)
......@@ -6365,6 +6579,8 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto init_err;
}
bnxt_hwrm_func_qcfg(bp);
bnxt_set_tpa_flags(bp);
bnxt_set_ring_params(bp);
if (BNXT_PF(bp))
......
......@@ -298,13 +298,14 @@ struct rx_tpa_start_cmp_ext {
#define RX_TPA_START_CMP_FLAGS2_L4_CS_CALC (0x1 << 1)
#define RX_TPA_START_CMP_FLAGS2_T_IP_CS_CALC (0x1 << 2)
#define RX_TPA_START_CMP_FLAGS2_T_L4_CS_CALC (0x1 << 3)
#define RX_TPA_START_CMP_FLAGS2_IP_TYPE (0x1 << 8)
__le32 rx_tpa_start_cmp_metadata;
__le32 rx_tpa_start_cmp_cfa_code_v2;
#define RX_TPA_START_CMP_V2 (0x1 << 0)
#define RX_TPA_START_CMP_CFA_CODE (0xffff << 16)
#define RX_TPA_START_CMPL_CFA_CODE_SHIFT 16
__le32 rx_tpa_start_cmp_unused5;
__le32 rx_tpa_start_cmp_hdr_info;
};
struct rx_tpa_end_cmp {
......@@ -584,6 +585,19 @@ struct bnxt_tpa_info {
u32 metadata;
enum pkt_hash_types hash_type;
u32 rss_hash;
u32 hdr_info;
#define BNXT_TPA_L4_SIZE(hdr_info) \
(((hdr_info) & 0xf8000000) ? ((hdr_info) >> 27) : 32)
#define BNXT_TPA_INNER_L3_OFF(hdr_info) \
(((hdr_info) >> 18) & 0x1ff)
#define BNXT_TPA_INNER_L2_OFF(hdr_info) \
(((hdr_info) >> 9) & 0x1ff)
#define BNXT_TPA_OUTER_L3_OFF(hdr_info) \
((hdr_info) & 0x1ff)
};
struct bnxt_rx_ring_info {
......@@ -835,6 +849,7 @@ struct bnxt_link_info {
#define BNXT_LINK_SPEED_MSK_25GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_25GB
#define BNXT_LINK_SPEED_MSK_40GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_40GB
#define BNXT_LINK_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_50GB
u16 support_auto_speeds;
u16 lp_auto_link_speeds;
u16 force_link_speed;
u32 preemphasis;
......@@ -873,6 +888,44 @@ struct bnxt {
void __iomem *bar2;
u32 reg_base;
u16 chip_num;
#define CHIP_NUM_57301 0x16c8
#define CHIP_NUM_57302 0x16c9
#define CHIP_NUM_57304 0x16ca
#define CHIP_NUM_57402 0x16d0
#define CHIP_NUM_57404 0x16d1
#define CHIP_NUM_57406 0x16d2
#define CHIP_NUM_57311 0x16ce
#define CHIP_NUM_57312 0x16cf
#define CHIP_NUM_57314 0x16df
#define CHIP_NUM_57412 0x16d6
#define CHIP_NUM_57414 0x16d7
#define CHIP_NUM_57416 0x16d8
#define CHIP_NUM_57417 0x16d9
#define BNXT_CHIP_NUM_5730X(chip_num) \
((chip_num) >= CHIP_NUM_57301 && \
(chip_num) <= CHIP_NUM_57304)
#define BNXT_CHIP_NUM_5740X(chip_num) \
((chip_num) >= CHIP_NUM_57402 && \
(chip_num) <= CHIP_NUM_57406)
#define BNXT_CHIP_NUM_5731X(chip_num) \
((chip_num) == CHIP_NUM_57311 || \
(chip_num) == CHIP_NUM_57312 || \
(chip_num) == CHIP_NUM_57314)
#define BNXT_CHIP_NUM_5741X(chip_num) \
((chip_num) >= CHIP_NUM_57412 && \
(chip_num) <= CHIP_NUM_57417)
#define BNXT_CHIP_NUM_57X0X(chip_num) \
(BNXT_CHIP_NUM_5730X(chip_num) || BNXT_CHIP_NUM_5740X(chip_num))
#define BNXT_CHIP_NUM_57X1X(chip_num) \
(BNXT_CHIP_NUM_5731X(chip_num) || BNXT_CHIP_NUM_5741X(chip_num))
struct net_device *dev;
struct pci_dev *pdev;
......@@ -907,12 +960,17 @@ struct bnxt {
#define BNXT_PF(bp) (!((bp)->flags & BNXT_FLAG_VF))
#define BNXT_VF(bp) ((bp)->flags & BNXT_FLAG_VF)
#define BNXT_NPAR(bp) ((bp)->port_partition_type)
#define BNXT_SINGLE_PF(bp) (BNXT_PF(bp) && !BNXT_NPAR(bp))
struct bnxt_napi **bnapi;
struct bnxt_rx_ring_info *rx_ring;
struct bnxt_tx_ring_info *tx_ring;
struct sk_buff * (*gro_func)(struct bnxt_tpa_info *, int, int,
struct sk_buff *);
u32 rx_buf_size;
u32 rx_buf_use_size; /* useable size */
u32 rx_ring_size;
......@@ -993,6 +1051,7 @@ struct bnxt {
__le16 vxlan_fw_dst_port_id;
u8 nge_port_cnt;
__le16 nge_fw_dst_port_id;
u8 port_partition_type;
u16 rx_coal_ticks;
u16 rx_coal_ticks_irq;
......@@ -1018,6 +1077,7 @@ struct bnxt {
#define BNXT_HWRM_PF_UNLOAD_SP_EVENT 8
#define BNXT_PERIODIC_STATS_SP_EVENT 9
#define BNXT_HWRM_PORT_MODULE_SP_EVENT 10
#define BNXT_RESET_TASK_SILENT_SP_EVENT 11
struct bnxt_pf_info pf;
#ifdef CONFIG_BNXT_SRIOV
......
......@@ -628,7 +628,66 @@ u32 _bnxt_fw_to_ethtool_adv_spds(u16 fw_speeds, u8 fw_pause)
return speed_mask;
}
static u32 bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info)
#define BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, fw_pause, lk_ksettings, name)\
{ \
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_100MB) \
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
100baseT_Full); \
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_1GB) \
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
1000baseT_Full); \
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_10GB) \
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
10000baseT_Full); \
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_25GB) \
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
25000baseCR_Full); \
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_40GB) \
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
40000baseCR4_Full);\
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_50GB) \
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
50000baseCR2_Full);\
if ((fw_pause) & BNXT_LINK_PAUSE_RX) { \
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
Pause); \
if (!((fw_pause) & BNXT_LINK_PAUSE_TX)) \
ethtool_link_ksettings_add_link_mode( \
lk_ksettings, name, Asym_Pause);\
} else if ((fw_pause) & BNXT_LINK_PAUSE_TX) { \
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
Asym_Pause); \
} \
}
#define BNXT_ETHTOOL_TO_FW_SPDS(fw_speeds, lk_ksettings, name) \
{ \
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
100baseT_Full) || \
ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
100baseT_Half)) \
(fw_speeds) |= BNXT_LINK_SPEED_MSK_100MB; \
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1000baseT_Full) || \
ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1000baseT_Half)) \
(fw_speeds) |= BNXT_LINK_SPEED_MSK_1GB; \
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
10000baseT_Full)) \
(fw_speeds) |= BNXT_LINK_SPEED_MSK_10GB; \
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
25000baseCR_Full)) \
(fw_speeds) |= BNXT_LINK_SPEED_MSK_25GB; \
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
40000baseCR4_Full)) \
(fw_speeds) |= BNXT_LINK_SPEED_MSK_40GB; \
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
50000baseCR2_Full)) \
(fw_speeds) |= BNXT_LINK_SPEED_MSK_50GB; \
}
static void bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info,
struct ethtool_link_ksettings *lk_ksettings)
{
u16 fw_speeds = link_info->auto_link_speeds;
u8 fw_pause = 0;
......@@ -636,10 +695,11 @@ static u32 bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info)
if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
fw_pause = link_info->auto_pause_setting;
return _bnxt_fw_to_ethtool_adv_spds(fw_speeds, fw_pause);
BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, fw_pause, lk_ksettings, advertising);
}
static u32 bnxt_fw_to_ethtool_lp_adv(struct bnxt_link_info *link_info)
static void bnxt_fw_to_ethtool_lp_adv(struct bnxt_link_info *link_info,
struct ethtool_link_ksettings *lk_ksettings)
{
u16 fw_speeds = link_info->lp_auto_link_speeds;
u8 fw_pause = 0;
......@@ -647,16 +707,24 @@ static u32 bnxt_fw_to_ethtool_lp_adv(struct bnxt_link_info *link_info)
if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
fw_pause = link_info->lp_pause;
return _bnxt_fw_to_ethtool_adv_spds(fw_speeds, fw_pause);
BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, fw_pause, lk_ksettings,
lp_advertising);
}
static u32 bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info)
static void bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info,
struct ethtool_link_ksettings *lk_ksettings)
{
u16 fw_speeds = link_info->support_speeds;
u32 supported;
supported = _bnxt_fw_to_ethtool_adv_spds(fw_speeds, 0);
return supported | SUPPORTED_Pause | SUPPORTED_Asym_Pause;
BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, 0, lk_ksettings, supported);
ethtool_link_ksettings_add_link_mode(lk_ksettings, supported, Pause);
ethtool_link_ksettings_add_link_mode(lk_ksettings, supported,
Asym_Pause);
if (link_info->support_auto_speeds)
ethtool_link_ksettings_add_link_mode(lk_ksettings, supported,
Autoneg);
}
u32 bnxt_fw_to_ethtool_speed(u16 fw_link_speed)
......@@ -683,65 +751,62 @@ u32 bnxt_fw_to_ethtool_speed(u16 fw_link_speed)
}
}
static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int bnxt_get_link_ksettings(struct net_device *dev,
struct ethtool_link_ksettings *lk_ksettings)
{
struct bnxt *bp = netdev_priv(dev);
struct bnxt_link_info *link_info = &bp->link_info;
u16 ethtool_speed;
struct ethtool_link_settings *base = &lk_ksettings->base;
u32 ethtool_speed;
cmd->supported = bnxt_fw_to_ethtool_support_spds(link_info);
if (link_info->auto_link_speeds)
cmd->supported |= SUPPORTED_Autoneg;
ethtool_link_ksettings_zero_link_mode(lk_ksettings, supported);
bnxt_fw_to_ethtool_support_spds(link_info, lk_ksettings);
ethtool_link_ksettings_zero_link_mode(lk_ksettings, advertising);
if (link_info->autoneg) {
cmd->advertising =
bnxt_fw_to_ethtool_advertised_spds(link_info);
cmd->advertising |= ADVERTISED_Autoneg;
cmd->autoneg = AUTONEG_ENABLE;
bnxt_fw_to_ethtool_advertised_spds(link_info, lk_ksettings);
ethtool_link_ksettings_add_link_mode(lk_ksettings,
advertising, Autoneg);
base->autoneg = AUTONEG_ENABLE;
if (link_info->phy_link_status == BNXT_LINK_LINK)
cmd->lp_advertising =
bnxt_fw_to_ethtool_lp_adv(link_info);
bnxt_fw_to_ethtool_lp_adv(link_info, lk_ksettings);
ethtool_speed = bnxt_fw_to_ethtool_speed(link_info->link_speed);
if (!netif_carrier_ok(dev))
cmd->duplex = DUPLEX_UNKNOWN;
base->duplex = DUPLEX_UNKNOWN;
else if (link_info->duplex & BNXT_LINK_DUPLEX_FULL)
cmd->duplex = DUPLEX_FULL;
base->duplex = DUPLEX_FULL;
else
cmd->duplex = DUPLEX_HALF;
base->duplex = DUPLEX_HALF;
} else {
cmd->autoneg = AUTONEG_DISABLE;
cmd->advertising = 0;
base->autoneg = AUTONEG_DISABLE;
ethtool_speed =
bnxt_fw_to_ethtool_speed(link_info->req_link_speed);
cmd->duplex = DUPLEX_HALF;
base->duplex = DUPLEX_HALF;
if (link_info->req_duplex == BNXT_LINK_DUPLEX_FULL)
cmd->duplex = DUPLEX_FULL;
base->duplex = DUPLEX_FULL;
}
ethtool_cmd_speed_set(cmd, ethtool_speed);
base->speed = ethtool_speed;
cmd->port = PORT_NONE;
base->port = PORT_NONE;
if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) {
cmd->port = PORT_TP;
cmd->supported |= SUPPORTED_TP;
cmd->advertising |= ADVERTISED_TP;
base->port = PORT_TP;
ethtool_link_ksettings_add_link_mode(lk_ksettings, supported,
TP);
ethtool_link_ksettings_add_link_mode(lk_ksettings, advertising,
TP);
} else {
cmd->supported |= SUPPORTED_FIBRE;
cmd->advertising |= ADVERTISED_FIBRE;
ethtool_link_ksettings_add_link_mode(lk_ksettings, supported,
FIBRE);
ethtool_link_ksettings_add_link_mode(lk_ksettings, advertising,
FIBRE);
if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC)
cmd->port = PORT_DA;
base->port = PORT_DA;
else if (link_info->media_type ==
PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE)
cmd->port = PORT_FIBRE;
base->port = PORT_FIBRE;
}
if (link_info->transceiver ==
PORT_PHY_QCFG_RESP_XCVR_PKG_TYPE_XCVR_INTERNAL)
cmd->transceiver = XCVR_INTERNAL;
else
cmd->transceiver = XCVR_EXTERNAL;
cmd->phy_address = link_info->phy_addr;
base->phy_address = link_info->phy_addr;
return 0;
}
......@@ -815,37 +880,25 @@ u16 bnxt_get_fw_auto_link_speeds(u32 advertising)
return fw_speed_mask;
}
static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int bnxt_set_link_ksettings(struct net_device *dev,
const struct ethtool_link_ksettings *lk_ksettings)
{
int rc = 0;
struct bnxt *bp = netdev_priv(dev);
struct bnxt_link_info *link_info = &bp->link_info;
const struct ethtool_link_settings *base = &lk_ksettings->base;
u32 speed, fw_advertising = 0;
bool set_pause = false;
int rc = 0;
if (BNXT_VF(bp))
return rc;
if (cmd->autoneg == AUTONEG_ENABLE) {
u32 supported_spds = bnxt_fw_to_ethtool_support_spds(link_info);
if (!BNXT_SINGLE_PF(bp))
return -EOPNOTSUPP;
if (cmd->advertising & ~(supported_spds | ADVERTISED_Autoneg |
ADVERTISED_TP | ADVERTISED_FIBRE)) {
netdev_err(dev, "Unsupported advertising mask (adv: 0x%x)\n",
cmd->advertising);
rc = -EINVAL;
goto set_setting_exit;
}
fw_advertising = bnxt_get_fw_auto_link_speeds(cmd->advertising);
if (fw_advertising & ~link_info->support_speeds) {
netdev_err(dev, "Advertising parameters are not supported! (adv: 0x%x)\n",
cmd->advertising);
rc = -EINVAL;
goto set_setting_exit;
}
if (base->autoneg == AUTONEG_ENABLE) {
BNXT_ETHTOOL_TO_FW_SPDS(fw_advertising, lk_ksettings,
advertising);
link_info->autoneg |= BNXT_AUTONEG_SPEED;
if (!fw_advertising)
link_info->advertising = link_info->support_speeds;
link_info->advertising = link_info->support_auto_speeds;
else
link_info->advertising = fw_advertising;
/* any change to autoneg will cause link change, therefore the
......@@ -863,16 +916,12 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
rc = -EINVAL;
goto set_setting_exit;
}
/* TODO: currently don't support half duplex */
if (cmd->duplex == DUPLEX_HALF) {
if (base->duplex == DUPLEX_HALF) {
netdev_err(dev, "HALF DUPLEX is not supported!\n");
rc = -EINVAL;
goto set_setting_exit;
}
/* If received a request for an unknown duplex, assume full*/
if (cmd->duplex == DUPLEX_UNKNOWN)
cmd->duplex = DUPLEX_FULL;
speed = ethtool_cmd_speed(cmd);
speed = base->speed;
fw_speed = bnxt_get_fw_speed(dev, speed);
if (!fw_speed) {
rc = -EINVAL;
......@@ -911,7 +960,7 @@ static int bnxt_set_pauseparam(struct net_device *dev,
struct bnxt *bp = netdev_priv(dev);
struct bnxt_link_info *link_info = &bp->link_info;
if (BNXT_VF(bp))
if (!BNXT_SINGLE_PF(bp))
return rc;
if (epause->autoneg) {
......@@ -1433,7 +1482,7 @@ static int bnxt_set_eee(struct net_device *dev, struct ethtool_eee *edata)
_bnxt_fw_to_ethtool_adv_spds(link_info->advertising, 0);
int rc = 0;
if (BNXT_VF(bp))
if (!BNXT_SINGLE_PF(bp))
return 0;
if (!(bp->flags & BNXT_FLAG_EEE_CAP))
......@@ -1618,8 +1667,8 @@ static int bnxt_get_module_eeprom(struct net_device *dev,
}
const struct ethtool_ops bnxt_ethtool_ops = {
.get_settings = bnxt_get_settings,
.set_settings = bnxt_set_settings,
.get_link_ksettings = bnxt_get_link_ksettings,
.set_link_ksettings = bnxt_set_link_ksettings,
.get_pauseparam = bnxt_get_pauseparam,
.set_pauseparam = bnxt_set_pauseparam,
.get_drvinfo = bnxt_get_drvinfo,
......
......@@ -143,6 +143,9 @@ int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos)
u16 vlan_tag;
int rc;
if (bp->hwrm_spec_code < 0x10201)
return -ENOTSUPP;
rc = bnxt_vf_ndo_prep(bp, vf_id);
if (rc)
return rc;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册