summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/broadcom/bnxt/bnxt.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2016-05-27 17:16:53 +0200
committerTakashi Iwai <tiwai@suse.de>2016-05-27 17:16:53 +0200
commiteb4606e64a7d548f5d60a9583baa8104890b2c6e (patch)
tree2dc8e587fc79c207dab2fb74830963cc84dcf801 /drivers/net/ethernet/broadcom/bnxt/bnxt.c
parent86c72d1ce91d804e4fa8d90b316a89597dd220f1 (diff)
parentbf65921380cd50b87618df550398e06581f4a361 (diff)
Merge tag 'asoc-v4.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v4.7 part 2 Really sorry about this late pull request. It looks like at the time I sent my pull request for v4.7 there was some conflict or other issue which caused my script to stop merging the ASoC branches at some point after the HDMI changes. It's all specific driver updates, including: - New drivers for MAX98371 and TAS5720. - SPI support for TLV320AIC32x4. - TDM support for STI Uniperf IPs. This code should all have been in -next prior to the merge window apart from some fixes, it dropped out on the 18th.
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnxt/bnxt.c')
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c86
1 files changed, 82 insertions, 4 deletions
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 72eb29ed0359..c39a7f5c6a01 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -813,6 +813,46 @@ static inline struct sk_buff *bnxt_copy_skb(struct bnxt_napi *bnapi, u8 *data,
return skb;
}
+static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_napi *bnapi,
+ u32 *raw_cons, void *cmp)
+{
+ struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ struct rx_cmp *rxcmp = cmp;
+ u32 tmp_raw_cons = *raw_cons;
+ u8 cmp_type, agg_bufs = 0;
+
+ cmp_type = RX_CMP_TYPE(rxcmp);
+
+ if (cmp_type == CMP_TYPE_RX_L2_CMP) {
+ agg_bufs = (le32_to_cpu(rxcmp->rx_cmp_misc_v1) &
+ RX_CMP_AGG_BUFS) >>
+ RX_CMP_AGG_BUFS_SHIFT;
+ } else if (cmp_type == CMP_TYPE_RX_L2_TPA_END_CMP) {
+ struct rx_tpa_end_cmp *tpa_end = cmp;
+
+ agg_bufs = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) &
+ RX_TPA_END_CMP_AGG_BUFS) >>
+ RX_TPA_END_CMP_AGG_BUFS_SHIFT;
+ }
+
+ if (agg_bufs) {
+ if (!bnxt_agg_bufs_valid(bp, cpr, agg_bufs, &tmp_raw_cons))
+ return -EBUSY;
+ }
+ *raw_cons = tmp_raw_cons;
+ return 0;
+}
+
+static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
+{
+ if (!rxr->bnapi->in_reset) {
+ rxr->bnapi->in_reset = true;
+ set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event);
+ schedule_work(&bp->sp_task);
+ }
+ rxr->rx_next_cons = 0xffff;
+}
+
static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
struct rx_tpa_start_cmp *tpa_start,
struct rx_tpa_start_cmp_ext *tpa_start1)
@@ -830,6 +870,11 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
prod_rx_buf = &rxr->rx_buf_ring[prod];
tpa_info = &rxr->rx_tpa[agg_id];
+ if (unlikely(cons != rxr->rx_next_cons)) {
+ bnxt_sched_reset(bp, rxr);
+ return;
+ }
+
prod_rx_buf->data = tpa_info->data;
mapping = tpa_info->mapping;
@@ -867,6 +912,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
rxr->rx_prod = NEXT_RX(prod);
cons = NEXT_RX(cons);
+ rxr->rx_next_cons = NEXT_RX(cons);
cons_rx_buf = &rxr->rx_buf_ring[cons];
bnxt_reuse_rx_data(rxr, cons, cons_rx_buf->data);
@@ -980,6 +1026,14 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
dma_addr_t mapping;
struct sk_buff *skb;
+ if (unlikely(bnapi->in_reset)) {
+ int rc = bnxt_discard_rx(bp, bnapi, raw_cons, tpa_end);
+
+ if (rc < 0)
+ return ERR_PTR(-EBUSY);
+ return NULL;
+ }
+
tpa_info = &rxr->rx_tpa[agg_id];
data = tpa_info->data;
prefetch(data);
@@ -1146,6 +1200,12 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
cons = rxcmp->rx_cmp_opaque;
rx_buf = &rxr->rx_buf_ring[cons];
data = rx_buf->data;
+ if (unlikely(cons != rxr->rx_next_cons)) {
+ int rc1 = bnxt_discard_rx(bp, bnapi, raw_cons, rxcmp);
+
+ bnxt_sched_reset(bp, rxr);
+ return rc1;
+ }
prefetch(data);
agg_bufs = (le32_to_cpu(rxcmp->rx_cmp_misc_v1) & RX_CMP_AGG_BUFS) >>
@@ -1245,6 +1305,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
next_rx:
rxr->rx_prod = NEXT_RX(prod);
+ rxr->rx_next_cons = NEXT_RX(cons);
next_rx_no_prod:
*raw_cons = tmp_raw_cons;
@@ -1388,6 +1449,10 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
if (!TX_CMP_VALID(txcmp, raw_cons))
break;
+ /* The valid test of the entry must be done first before
+ * reading any further.
+ */
+ rmb();
if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) {
tx_pkts++;
/* return full budget so NAPI will complete. */
@@ -2482,6 +2547,7 @@ static void bnxt_clear_ring_indices(struct bnxt *bp)
rxr->rx_prod = 0;
rxr->rx_agg_prod = 0;
rxr->rx_sw_agg_prod = 0;
+ rxr->rx_next_cons = 0;
}
}
}
@@ -4038,9 +4104,11 @@ static int bnxt_alloc_rfs_vnics(struct bnxt *bp)
}
static int bnxt_cfg_rx_mode(struct bnxt *);
+static bool bnxt_mc_list_updated(struct bnxt *, u32 *);
static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
{
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[0];
int rc = 0;
if (irq_re_init) {
@@ -4096,13 +4164,22 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
netdev_err(bp->dev, "HWRM vnic filter failure rc: %x\n", rc);
goto err_out;
}
- bp->vnic_info[0].uc_filter_count = 1;
+ vnic->uc_filter_count = 1;
- bp->vnic_info[0].rx_mask = CFA_L2_SET_RX_MASK_REQ_MASK_BCAST;
+ vnic->rx_mask = CFA_L2_SET_RX_MASK_REQ_MASK_BCAST;
if ((bp->dev->flags & IFF_PROMISC) && BNXT_PF(bp))
- bp->vnic_info[0].rx_mask |=
- CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
+ vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
+
+ if (bp->dev->flags & IFF_ALLMULTI) {
+ vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
+ vnic->mc_list_count = 0;
+ } else {
+ u32 mask = 0;
+
+ bnxt_mc_list_updated(bp, &mask);
+ vnic->rx_mask |= mask;
+ }
rc = bnxt_cfg_rx_mode(bp);
if (rc)
@@ -4447,6 +4524,7 @@ static void bnxt_enable_napi(struct bnxt *bp)
int i;
for (i = 0; i < bp->cp_nr_rings; i++) {
+ bp->bnapi[i]->in_reset = false;
bnxt_enable_poll(bp->bnapi[i]);
napi_enable(&bp->bnapi[i]->napi);
}