Commit 252dd176 authored by David S. Miller's avatar David S. Miller

Merge branch 'bnxt_en-Bug-fixes'

Michael Chan says:

====================
bnxt_en: Bug fixes.

These are bug fixes in error code paths, TC Flower VLAN TCI flow
checking bug fix, proper filtering of Broadcast packets if IFF_BROADCAST
is not set, and a bug fix in bnxt_get_max_rings() to return 0 ring
parameters when the return value is -ENOMEM.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 26420d9c c58387ab
...@@ -5712,7 +5712,9 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init) ...@@ -5712,7 +5712,9 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
} }
vnic->uc_filter_count = 1; vnic->uc_filter_count = 1;
vnic->rx_mask = CFA_L2_SET_RX_MASK_REQ_MASK_BCAST; vnic->rx_mask = 0;
if (bp->dev->flags & IFF_BROADCAST)
vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_BCAST;
if ((bp->dev->flags & IFF_PROMISC) && bnxt_promisc_ok(bp)) if ((bp->dev->flags & IFF_PROMISC) && bnxt_promisc_ok(bp))
vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS; vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
...@@ -5917,7 +5919,7 @@ unsigned int bnxt_get_max_func_irqs(struct bnxt *bp) ...@@ -5917,7 +5919,7 @@ unsigned int bnxt_get_max_func_irqs(struct bnxt *bp)
return min_t(unsigned int, hw_resc->max_irqs, hw_resc->max_cp_rings); return min_t(unsigned int, hw_resc->max_irqs, hw_resc->max_cp_rings);
} }
void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs) static void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs)
{ {
bp->hw_resc.max_irqs = max_irqs; bp->hw_resc.max_irqs = max_irqs;
} }
...@@ -6888,7 +6890,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) ...@@ -6888,7 +6890,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
rc = bnxt_request_irq(bp); rc = bnxt_request_irq(bp);
if (rc) { if (rc) {
netdev_err(bp->dev, "bnxt_request_irq err: %x\n", rc); netdev_err(bp->dev, "bnxt_request_irq err: %x\n", rc);
goto open_err; goto open_err_irq;
} }
} }
...@@ -6928,6 +6930,8 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) ...@@ -6928,6 +6930,8 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
open_err: open_err:
bnxt_debug_dev_exit(bp); bnxt_debug_dev_exit(bp);
bnxt_disable_napi(bp); bnxt_disable_napi(bp);
open_err_irq:
bnxt_del_napi(bp); bnxt_del_napi(bp);
open_err_free_mem: open_err_free_mem:
...@@ -7214,13 +7218,16 @@ static void bnxt_set_rx_mode(struct net_device *dev) ...@@ -7214,13 +7218,16 @@ static void bnxt_set_rx_mode(struct net_device *dev)
mask &= ~(CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS | mask &= ~(CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS |
CFA_L2_SET_RX_MASK_REQ_MASK_MCAST | CFA_L2_SET_RX_MASK_REQ_MASK_MCAST |
CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST); CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST |
CFA_L2_SET_RX_MASK_REQ_MASK_BCAST);
if ((dev->flags & IFF_PROMISC) && bnxt_promisc_ok(bp)) if ((dev->flags & IFF_PROMISC) && bnxt_promisc_ok(bp))
mask |= CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS; mask |= CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
uc_update = bnxt_uc_list_updated(bp); uc_update = bnxt_uc_list_updated(bp);
if (dev->flags & IFF_BROADCAST)
mask |= CFA_L2_SET_RX_MASK_REQ_MASK_BCAST;
if (dev->flags & IFF_ALLMULTI) { if (dev->flags & IFF_ALLMULTI) {
mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
vnic->mc_list_count = 0; vnic->mc_list_count = 0;
...@@ -8502,11 +8509,11 @@ int bnxt_get_max_rings(struct bnxt *bp, int *max_rx, int *max_tx, bool shared) ...@@ -8502,11 +8509,11 @@ int bnxt_get_max_rings(struct bnxt *bp, int *max_rx, int *max_tx, bool shared)
int rx, tx, cp; int rx, tx, cp;
_bnxt_get_max_rings(bp, &rx, &tx, &cp); _bnxt_get_max_rings(bp, &rx, &tx, &cp);
*max_rx = rx;
*max_tx = tx;
if (!rx || !tx || !cp) if (!rx || !tx || !cp)
return -ENOMEM; return -ENOMEM;
*max_rx = rx;
*max_tx = tx;
return bnxt_trim_rings(bp, max_rx, max_tx, cp, shared); return bnxt_trim_rings(bp, max_rx, max_tx, cp, shared);
} }
...@@ -8520,8 +8527,11 @@ static int bnxt_get_dflt_rings(struct bnxt *bp, int *max_rx, int *max_tx, ...@@ -8520,8 +8527,11 @@ static int bnxt_get_dflt_rings(struct bnxt *bp, int *max_rx, int *max_tx,
/* Not enough rings, try disabling agg rings. */ /* Not enough rings, try disabling agg rings. */
bp->flags &= ~BNXT_FLAG_AGG_RINGS; bp->flags &= ~BNXT_FLAG_AGG_RINGS;
rc = bnxt_get_max_rings(bp, max_rx, max_tx, shared); rc = bnxt_get_max_rings(bp, max_rx, max_tx, shared);
if (rc) if (rc) {
/* set BNXT_FLAG_AGG_RINGS back for consistency */
bp->flags |= BNXT_FLAG_AGG_RINGS;
return rc; return rc;
}
bp->flags |= BNXT_FLAG_NO_AGG_RINGS; bp->flags |= BNXT_FLAG_NO_AGG_RINGS;
bp->dev->hw_features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW); bp->dev->hw_features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
bp->dev->features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW); bp->dev->features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
......
...@@ -1470,7 +1470,6 @@ void bnxt_set_max_func_stat_ctxs(struct bnxt *bp, unsigned int max); ...@@ -1470,7 +1470,6 @@ void bnxt_set_max_func_stat_ctxs(struct bnxt *bp, unsigned int max);
unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp); unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp);
void bnxt_set_max_func_cp_rings(struct bnxt *bp, unsigned int max); void bnxt_set_max_func_cp_rings(struct bnxt *bp, unsigned int max);
unsigned int bnxt_get_max_func_irqs(struct bnxt *bp); unsigned int bnxt_get_max_func_irqs(struct bnxt *bp);
void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max);
int bnxt_get_avail_msix(struct bnxt *bp, int num); int bnxt_get_avail_msix(struct bnxt *bp, int num);
int bnxt_reserve_rings(struct bnxt *bp); int bnxt_reserve_rings(struct bnxt *bp);
void bnxt_tx_disable(struct bnxt *bp); void bnxt_tx_disable(struct bnxt *bp);
......
...@@ -27,6 +27,15 @@ ...@@ -27,6 +27,15 @@
#define BNXT_FID_INVALID 0xffff #define BNXT_FID_INVALID 0xffff
#define VLAN_TCI(vid, prio) ((vid) | ((prio) << VLAN_PRIO_SHIFT)) #define VLAN_TCI(vid, prio) ((vid) | ((prio) << VLAN_PRIO_SHIFT))
#define is_vlan_pcp_wildcarded(vlan_tci_mask) \
((ntohs(vlan_tci_mask) & VLAN_PRIO_MASK) == 0x0000)
#define is_vlan_pcp_exactmatch(vlan_tci_mask) \
((ntohs(vlan_tci_mask) & VLAN_PRIO_MASK) == VLAN_PRIO_MASK)
#define is_vlan_pcp_zero(vlan_tci) \
((ntohs(vlan_tci) & VLAN_PRIO_MASK) == 0x0000)
#define is_vid_exactmatch(vlan_tci_mask) \
((ntohs(vlan_tci_mask) & VLAN_VID_MASK) == VLAN_VID_MASK)
/* Return the dst fid of the func for flow forwarding /* Return the dst fid of the func for flow forwarding
* For PFs: src_fid is the fid of the PF * For PFs: src_fid is the fid of the PF
* For VF-reps: src_fid the fid of the VF * For VF-reps: src_fid the fid of the VF
...@@ -389,6 +398,21 @@ static bool is_exactmatch(void *mask, int len) ...@@ -389,6 +398,21 @@ static bool is_exactmatch(void *mask, int len)
return true; return true;
} }
static bool is_vlan_tci_allowed(__be16 vlan_tci_mask,
__be16 vlan_tci)
{
/* VLAN priority must be either exactly zero or fully wildcarded and
* VLAN id must be exact match.
*/
if (is_vid_exactmatch(vlan_tci_mask) &&
((is_vlan_pcp_exactmatch(vlan_tci_mask) &&
is_vlan_pcp_zero(vlan_tci)) ||
is_vlan_pcp_wildcarded(vlan_tci_mask)))
return true;
return false;
}
static bool bits_set(void *key, int len) static bool bits_set(void *key, int len)
{ {
const u8 *p = key; const u8 *p = key;
...@@ -803,9 +827,9 @@ static bool bnxt_tc_can_offload(struct bnxt *bp, struct bnxt_tc_flow *flow) ...@@ -803,9 +827,9 @@ static bool bnxt_tc_can_offload(struct bnxt *bp, struct bnxt_tc_flow *flow)
/* Currently VLAN fields cannot be partial wildcard */ /* Currently VLAN fields cannot be partial wildcard */
if (bits_set(&flow->l2_key.inner_vlan_tci, if (bits_set(&flow->l2_key.inner_vlan_tci,
sizeof(flow->l2_key.inner_vlan_tci)) && sizeof(flow->l2_key.inner_vlan_tci)) &&
!is_exactmatch(&flow->l2_mask.inner_vlan_tci, !is_vlan_tci_allowed(flow->l2_mask.inner_vlan_tci,
sizeof(flow->l2_mask.inner_vlan_tci))) { flow->l2_key.inner_vlan_tci)) {
netdev_info(bp->dev, "Wildcard match unsupported for VLAN TCI\n"); netdev_info(bp->dev, "Unsupported VLAN TCI\n");
return false; return false;
} }
if (bits_set(&flow->l2_key.inner_vlan_tpid, if (bits_set(&flow->l2_key.inner_vlan_tpid,
......
...@@ -169,7 +169,6 @@ static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id, ...@@ -169,7 +169,6 @@ static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id,
edev->ulp_tbl[ulp_id].msix_requested = avail_msix; edev->ulp_tbl[ulp_id].msix_requested = avail_msix;
} }
bnxt_fill_msix_vecs(bp, ent); bnxt_fill_msix_vecs(bp, ent);
bnxt_set_max_func_irqs(bp, bnxt_get_max_func_irqs(bp) - avail_msix);
bnxt_set_max_func_cp_rings(bp, max_cp_rings - avail_msix); bnxt_set_max_func_cp_rings(bp, max_cp_rings - avail_msix);
edev->flags |= BNXT_EN_FLAG_MSIX_REQUESTED; edev->flags |= BNXT_EN_FLAG_MSIX_REQUESTED;
return avail_msix; return avail_msix;
...@@ -192,7 +191,6 @@ static int bnxt_free_msix_vecs(struct bnxt_en_dev *edev, int ulp_id) ...@@ -192,7 +191,6 @@ static int bnxt_free_msix_vecs(struct bnxt_en_dev *edev, int ulp_id)
msix_requested = edev->ulp_tbl[ulp_id].msix_requested; msix_requested = edev->ulp_tbl[ulp_id].msix_requested;
bnxt_set_max_func_cp_rings(bp, max_cp_rings + msix_requested); bnxt_set_max_func_cp_rings(bp, max_cp_rings + msix_requested);
edev->ulp_tbl[ulp_id].msix_requested = 0; edev->ulp_tbl[ulp_id].msix_requested = 0;
bnxt_set_max_func_irqs(bp, bnxt_get_max_func_irqs(bp) + msix_requested);
edev->flags &= ~BNXT_EN_FLAG_MSIX_REQUESTED; edev->flags &= ~BNXT_EN_FLAG_MSIX_REQUESTED;
if (netif_running(dev)) { if (netif_running(dev)) {
bnxt_close_nic(bp, true, false); bnxt_close_nic(bp, true, false);
......
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