Skip to content

Commit

Permalink
bnxt_en: Re-structure ring indexing and mapping.
Browse files Browse the repository at this point in the history
In order to support dedicated or shared completion rings, the ring
indexing and mapping are re-structured as below:

1. bp->grp_info[] array index is 1:1 with bp->bnapi[] array index and
completion ring index.

2. rx rings 0 to n will be mapped to completion rings 0 to n.

3. If tx and rx rings share completion rings, then tx rings 0 to m will
be mapped to completion rings 0 to m.

4. If tx and rx rings use dedicated completion rings, then tx rings 0 to
m will be mapped to completion rings n + 1 to n + m.

5. Each tx or rx ring will use the corresponding completion ring index
for doorbell mapping and MSIX mapping.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Michael Chan authored and David S. Miller committed Jan 4, 2016
1 parent 3b2b7d9 commit b81a90d
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 38 deletions.
91 changes: 53 additions & 38 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
{
struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
int index = bnapi->index;
int index = txr - &bp->tx_ring[0];
struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, index);
u16 cons = txr->tx_cons;
struct pci_dev *pdev = bp->pdev;
Expand Down Expand Up @@ -3082,7 +3082,7 @@ static int bnxt_hwrm_vnic_ctx_alloc(struct bnxt *bp, u16 vnic_id)

static int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id)
{
int grp_idx = 0;
unsigned int ring = 0, grp_idx;
struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
struct hwrm_vnic_cfg_input req = {0};

Expand All @@ -3093,10 +3093,11 @@ static int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id)
req.rss_rule = cpu_to_le16(vnic->fw_rss_cos_lb_ctx);
req.cos_rule = cpu_to_le16(0xffff);
if (vnic->flags & BNXT_VNIC_RSS_FLAG)
grp_idx = 0;
ring = 0;
else if (vnic->flags & BNXT_VNIC_RFS_FLAG)
grp_idx = vnic_id - 1;
ring = vnic_id - 1;

grp_idx = bp->rx_ring[ring].bnapi->index;
req.vnic_id = cpu_to_le16(vnic->fw_vnic_id);
req.dflt_ring_grp = cpu_to_le16(bp->grp_info[grp_idx].fw_grp_id);

Expand Down Expand Up @@ -3137,22 +3138,25 @@ static void bnxt_hwrm_vnic_free(struct bnxt *bp)
bnxt_hwrm_vnic_free_one(bp, i);
}

static int bnxt_hwrm_vnic_alloc(struct bnxt *bp, u16 vnic_id, u16 start_grp_id,
u16 end_grp_id)
static int bnxt_hwrm_vnic_alloc(struct bnxt *bp, u16 vnic_id,
unsigned int start_rx_ring_idx,
unsigned int nr_rings)
{
u32 rc = 0, i, j;
int rc = 0;
unsigned int i, j, grp_idx, end_idx = start_rx_ring_idx + nr_rings;
struct hwrm_vnic_alloc_input req = {0};
struct hwrm_vnic_alloc_output *resp = bp->hwrm_cmd_resp_addr;

/* map ring groups to this vnic */
for (i = start_grp_id, j = 0; i < end_grp_id; i++, j++) {
if (bp->grp_info[i].fw_grp_id == INVALID_HW_RING_ID) {
for (i = start_rx_ring_idx, j = 0; i < end_idx; i++, j++) {
grp_idx = bp->rx_ring[i].bnapi->index;
if (bp->grp_info[grp_idx].fw_grp_id == INVALID_HW_RING_ID) {
netdev_err(bp->dev, "Not enough ring groups avail:%x req:%x\n",
j, (end_grp_id - start_grp_id));
j, nr_rings);
break;
}
bp->vnic_info[vnic_id].fw_grp_ids[j] =
bp->grp_info[i].fw_grp_id;
bp->grp_info[grp_idx].fw_grp_id;
}

bp->vnic_info[vnic_id].fw_rss_cos_lb_ctx = INVALID_HW_RING_ID;
Expand All @@ -3179,20 +3183,22 @@ static int bnxt_hwrm_ring_grp_alloc(struct bnxt *bp)
struct hwrm_ring_grp_alloc_input req = {0};
struct hwrm_ring_grp_alloc_output *resp =
bp->hwrm_cmd_resp_addr;
unsigned int grp_idx = bp->rx_ring[i].bnapi->index;

bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_GRP_ALLOC, -1, -1);

req.cr = cpu_to_le16(bp->grp_info[i].cp_fw_ring_id);
req.rr = cpu_to_le16(bp->grp_info[i].rx_fw_ring_id);
req.ar = cpu_to_le16(bp->grp_info[i].agg_fw_ring_id);
req.sc = cpu_to_le16(bp->grp_info[i].fw_stats_ctx);
req.cr = cpu_to_le16(bp->grp_info[grp_idx].cp_fw_ring_id);
req.rr = cpu_to_le16(bp->grp_info[grp_idx].rx_fw_ring_id);
req.ar = cpu_to_le16(bp->grp_info[grp_idx].agg_fw_ring_id);
req.sc = cpu_to_le16(bp->grp_info[grp_idx].fw_stats_ctx);

rc = _hwrm_send_message(bp, &req, sizeof(req),
HWRM_CMD_TIMEOUT);
if (rc)
break;

bp->grp_info[i].fw_grp_id = le32_to_cpu(resp->ring_group_id);
bp->grp_info[grp_idx].fw_grp_id =
le32_to_cpu(resp->ring_group_id);
}
mutex_unlock(&bp->hwrm_cmd_lock);
return rc;
Expand Down Expand Up @@ -3334,46 +3340,49 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
for (i = 0; i < bp->tx_nr_rings; i++) {
struct bnxt_tx_ring_info *txr = &bp->tx_ring[i];
struct bnxt_ring_struct *ring = &txr->tx_ring_struct;
u16 fw_stats_ctx = bp->grp_info[i].fw_stats_ctx;
u32 map_idx = txr->bnapi->index;
u16 fw_stats_ctx = bp->grp_info[map_idx].fw_stats_ctx;

rc = hwrm_ring_alloc_send_msg(bp, ring, HWRM_RING_ALLOC_TX, i,
fw_stats_ctx);
rc = hwrm_ring_alloc_send_msg(bp, ring, HWRM_RING_ALLOC_TX,
map_idx, fw_stats_ctx);
if (rc)
goto err_out;
txr->tx_doorbell = bp->bar1 + i * 0x80;
txr->tx_doorbell = bp->bar1 + map_idx * 0x80;
}

for (i = 0; i < bp->rx_nr_rings; i++) {
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
struct bnxt_ring_struct *ring = &rxr->rx_ring_struct;
u32 map_idx = rxr->bnapi->index;

rc = hwrm_ring_alloc_send_msg(bp, ring, HWRM_RING_ALLOC_RX, i,
INVALID_STATS_CTX_ID);
rc = hwrm_ring_alloc_send_msg(bp, ring, HWRM_RING_ALLOC_RX,
map_idx, INVALID_STATS_CTX_ID);
if (rc)
goto err_out;
rxr->rx_doorbell = bp->bar1 + i * 0x80;
rxr->rx_doorbell = bp->bar1 + map_idx * 0x80;
writel(DB_KEY_RX | rxr->rx_prod, rxr->rx_doorbell);
bp->grp_info[i].rx_fw_ring_id = ring->fw_ring_id;
bp->grp_info[map_idx].rx_fw_ring_id = ring->fw_ring_id;
}

if (bp->flags & BNXT_FLAG_AGG_RINGS) {
for (i = 0; i < bp->rx_nr_rings; i++) {
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
struct bnxt_ring_struct *ring =
&rxr->rx_agg_ring_struct;
u32 grp_idx = rxr->bnapi->index;
u32 map_idx = grp_idx + bp->rx_nr_rings;

rc = hwrm_ring_alloc_send_msg(bp, ring,
HWRM_RING_ALLOC_AGG,
bp->rx_nr_rings + i,
map_idx,
INVALID_STATS_CTX_ID);
if (rc)
goto err_out;

rxr->rx_agg_doorbell =
bp->bar1 + (bp->rx_nr_rings + i) * 0x80;
rxr->rx_agg_doorbell = bp->bar1 + map_idx * 0x80;
writel(DB_KEY_RX | rxr->rx_agg_prod,
rxr->rx_agg_doorbell);
bp->grp_info[i].agg_fw_ring_id = ring->fw_ring_id;
bp->grp_info[grp_idx].agg_fw_ring_id = ring->fw_ring_id;
}
}
err_out:
Expand Down Expand Up @@ -3430,7 +3439,8 @@ static void bnxt_hwrm_ring_free(struct bnxt *bp, bool close_path)
for (i = 0; i < bp->tx_nr_rings; i++) {
struct bnxt_tx_ring_info *txr = &bp->tx_ring[i];
struct bnxt_ring_struct *ring = &txr->tx_ring_struct;
u32 cmpl_ring_id = bp->grp_info[i].cp_fw_ring_id;
u32 grp_idx = txr->bnapi->index;
u32 cmpl_ring_id = bp->grp_info[grp_idx].cp_fw_ring_id;

if (ring->fw_ring_id != INVALID_HW_RING_ID) {
hwrm_ring_free_send_msg(bp, ring,
Expand All @@ -3444,30 +3454,34 @@ static void bnxt_hwrm_ring_free(struct bnxt *bp, bool close_path)
for (i = 0; i < bp->rx_nr_rings; i++) {
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
struct bnxt_ring_struct *ring = &rxr->rx_ring_struct;
u32 cmpl_ring_id = bp->grp_info[i].cp_fw_ring_id;
u32 grp_idx = rxr->bnapi->index;
u32 cmpl_ring_id = bp->grp_info[grp_idx].cp_fw_ring_id;

if (ring->fw_ring_id != INVALID_HW_RING_ID) {
hwrm_ring_free_send_msg(bp, ring,
RING_FREE_REQ_RING_TYPE_RX,
close_path ? cmpl_ring_id :
INVALID_HW_RING_ID);
ring->fw_ring_id = INVALID_HW_RING_ID;
bp->grp_info[i].rx_fw_ring_id = INVALID_HW_RING_ID;
bp->grp_info[grp_idx].rx_fw_ring_id =
INVALID_HW_RING_ID;
}
}

for (i = 0; i < bp->rx_nr_rings; i++) {
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
struct bnxt_ring_struct *ring = &rxr->rx_agg_ring_struct;
u32 cmpl_ring_id = bp->grp_info[i].cp_fw_ring_id;
u32 grp_idx = rxr->bnapi->index;
u32 cmpl_ring_id = bp->grp_info[grp_idx].cp_fw_ring_id;

if (ring->fw_ring_id != INVALID_HW_RING_ID) {
hwrm_ring_free_send_msg(bp, ring,
RING_FREE_REQ_RING_TYPE_RX,
close_path ? cmpl_ring_id :
INVALID_HW_RING_ID);
ring->fw_ring_id = INVALID_HW_RING_ID;
bp->grp_info[i].agg_fw_ring_id = INVALID_HW_RING_ID;
bp->grp_info[grp_idx].agg_fw_ring_id =
INVALID_HW_RING_ID;
}
}

Expand Down Expand Up @@ -3859,7 +3873,7 @@ static int bnxt_alloc_rfs_vnics(struct bnxt *bp)
break;

bp->vnic_info[vnic_id].flags |= BNXT_VNIC_RFS_FLAG;
rc = bnxt_hwrm_vnic_alloc(bp, vnic_id, ring_id, ring_id + 1);
rc = bnxt_hwrm_vnic_alloc(bp, vnic_id, ring_id, 1);
if (rc) {
netdev_err(bp->dev, "hwrm vnic %d alloc failure rc: %x\n",
vnic_id, rc);
Expand Down Expand Up @@ -4165,7 +4179,7 @@ static void bnxt_free_irq(struct bnxt *bp)

static int bnxt_request_irq(struct bnxt *bp)
{
int i, rc = 0;
int i, j, rc = 0;
unsigned long flags = 0;
#ifdef CONFIG_RFS_ACCEL
struct cpu_rmap *rmap = bp->dev->rx_cpu_rmap;
Expand All @@ -4174,14 +4188,15 @@ static int bnxt_request_irq(struct bnxt *bp)
if (!(bp->flags & BNXT_FLAG_USING_MSIX))
flags = IRQF_SHARED;

for (i = 0; i < bp->cp_nr_rings; i++) {
for (i = 0, j = 0; i < bp->cp_nr_rings; i++) {
struct bnxt_irq *irq = &bp->irq_tbl[i];
#ifdef CONFIG_RFS_ACCEL
if (rmap && (i < bp->rx_nr_rings)) {
if (rmap && bp->bnapi[i]->rx_ring) {
rc = irq_cpu_rmap_add(rmap, irq->vector);
if (rc)
netdev_warn(bp->dev, "failed adding irq rmap for ring %d\n",
i);
j);
j++;
}
#endif
rc = request_irq(irq->vector, irq->handler, flags, irq->name,
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.h
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,8 @@ struct bnxt {
int cp_nr_rings;

int num_stat_ctxs;

/* grp_info indexed by completion ring index */
struct bnxt_ring_grp_info *grp_info;
struct bnxt_vnic_info *vnic_info;
int nr_vnics;
Expand Down

0 comments on commit b81a90d

Please sign in to comment.