Commit 58930c03 authored by Bhargava Marreddy's avatar Bhargava Marreddy Committed by Jakub Kicinski
Browse files

bng_en: Register default VNIC



Allocate the default VNIC with the firmware and configure its RSS,
HDS, and Jumbo parameters. Add related functions to support VNIC
configuration for these parameters.

Signed-off-by: default avatarBhargava Marreddy <bhargava.marreddy@broadcom.com>
Reviewed-by: default avatarVikas Gupta <vikas.gupta@broadcom.com>
Reviewed-by: default avatarRajashekar Hudumula <rajashekar.hudumula@broadcom.com>
Link: https://patch.msgid.link/20250919174742.24969-10-bhargava.marreddy@broadcom.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent c757ef35
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -160,6 +160,7 @@ struct bnge_dev {
	u16			rss_indir_tbl_entries;

	u32			rss_cap;
	u32			rss_hash_cfg;

	u16			rx_nr_rings;
	u16			tx_nr_rings;
+12 −0
Original line number Diff line number Diff line
@@ -96,6 +96,16 @@ static void bnge_fw_unregister_dev(struct bnge_dev *bd)
	bnge_free_ctx_mem(bd);
}

static void bnge_set_dflt_rss_hash_type(struct bnge_dev *bd)
{
	bd->rss_hash_cfg = VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4 |
			   VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4 |
			   VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6 |
			   VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6 |
			   VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4 |
			   VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6;
}

static int bnge_fw_register_dev(struct bnge_dev *bd)
{
	int rc;
@@ -137,6 +147,8 @@ static int bnge_fw_register_dev(struct bnge_dev *bd)
		goto err_func_unrgtr;
	}

	bnge_set_dflt_rss_hash_type(bd);

	return 0;

err_func_unrgtr:
+207 −0
Original line number Diff line number Diff line
@@ -6,6 +6,8 @@
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/bnxt/hsi.h>
#include <linux/if_vlan.h>
#include <net/netdev_queues.h>

#include "bnge.h"
#include "bnge_hwrm.h"
@@ -702,6 +704,211 @@ int bnge_hwrm_queue_qportcfg(struct bnge_dev *bd)
	return rc;
}

int bnge_hwrm_vnic_set_hds(struct bnge_net *bn, struct bnge_vnic_info *vnic)
{
	u16 hds_thresh = (u16)bn->netdev->cfg_pending->hds_thresh;
	struct hwrm_vnic_plcmodes_cfg_input *req;
	struct bnge_dev *bd = bn->bd;
	int rc;

	rc = bnge_hwrm_req_init(bd, req, HWRM_VNIC_PLCMODES_CFG);
	if (rc)
		return rc;

	req->flags = cpu_to_le32(VNIC_PLCMODES_CFG_REQ_FLAGS_JUMBO_PLACEMENT);
	req->enables = cpu_to_le32(BNGE_PLC_EN_JUMBO_THRES_VALID);
	req->jumbo_thresh = cpu_to_le16(bn->rx_buf_use_size);

	if (bnge_is_agg_reqd(bd)) {
		req->flags |= cpu_to_le32(VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV4 |
					  VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV6);
		req->enables |=
			cpu_to_le32(BNGE_PLC_EN_HDS_THRES_VALID);
		req->hds_threshold = cpu_to_le16(hds_thresh);
	}
	req->vnic_id = cpu_to_le32(vnic->fw_vnic_id);
	return bnge_hwrm_req_send(bd, req);
}

int bnge_hwrm_vnic_ctx_alloc(struct bnge_dev *bd,
			     struct bnge_vnic_info *vnic, u16 ctx_idx)
{
	struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp;
	struct hwrm_vnic_rss_cos_lb_ctx_alloc_input *req;
	int rc;

	rc = bnge_hwrm_req_init(bd, req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
	if (rc)
		return rc;

	resp = bnge_hwrm_req_hold(bd, req);
	rc = bnge_hwrm_req_send(bd, req);
	if (!rc)
		vnic->fw_rss_cos_lb_ctx[ctx_idx] =
			le16_to_cpu(resp->rss_cos_lb_ctx_id);
	bnge_hwrm_req_drop(bd, req);

	return rc;
}

static void
__bnge_hwrm_vnic_set_rss(struct bnge_net *bn,
			 struct hwrm_vnic_rss_cfg_input *req,
			 struct bnge_vnic_info *vnic)
{
	struct bnge_dev *bd = bn->bd;

	bnge_fill_hw_rss_tbl(bn, vnic);
	req->flags |= VNIC_RSS_CFG_REQ_FLAGS_IPSEC_HASH_TYPE_CFG_SUPPORT;

	req->hash_type = cpu_to_le32(bd->rss_hash_cfg);
	req->hash_mode_flags = VNIC_RSS_CFG_REQ_HASH_MODE_FLAGS_DEFAULT;
	req->ring_grp_tbl_addr = cpu_to_le64(vnic->rss_table_dma_addr);
	req->hash_key_tbl_addr = cpu_to_le64(vnic->rss_hash_key_dma_addr);
}

int bnge_hwrm_vnic_set_rss(struct bnge_net *bn,
			   struct bnge_vnic_info *vnic, bool set_rss)
{
	struct hwrm_vnic_rss_cfg_input *req;
	struct bnge_dev *bd = bn->bd;
	dma_addr_t ring_tbl_map;
	u32 i, nr_ctxs;
	int rc;

	rc = bnge_hwrm_req_init(bd, req, HWRM_VNIC_RSS_CFG);
	if (rc)
		return rc;

	req->vnic_id = cpu_to_le16(vnic->fw_vnic_id);
	if (!set_rss)
		return bnge_hwrm_req_send(bd, req);

	__bnge_hwrm_vnic_set_rss(bn, req, vnic);
	ring_tbl_map = vnic->rss_table_dma_addr;
	nr_ctxs = bnge_cal_nr_rss_ctxs(bd->rx_nr_rings);

	bnge_hwrm_req_hold(bd, req);
	for (i = 0; i < nr_ctxs; ring_tbl_map += BNGE_RSS_TABLE_SIZE, i++) {
		req->ring_grp_tbl_addr = cpu_to_le64(ring_tbl_map);
		req->ring_table_pair_index = i;
		req->rss_ctx_idx = cpu_to_le16(vnic->fw_rss_cos_lb_ctx[i]);
		rc = bnge_hwrm_req_send(bd, req);
		if (rc)
			goto exit;
	}

exit:
	bnge_hwrm_req_drop(bd, req);
	return rc;
}

int bnge_hwrm_vnic_cfg(struct bnge_net *bn, struct bnge_vnic_info *vnic)
{
	struct bnge_rx_ring_info *rxr = &bn->rx_ring[0];
	struct hwrm_vnic_cfg_input *req;
	struct bnge_dev *bd = bn->bd;
	int rc;

	rc = bnge_hwrm_req_init(bd, req, HWRM_VNIC_CFG);
	if (rc)
		return rc;

	req->default_rx_ring_id =
		cpu_to_le16(rxr->rx_ring_struct.fw_ring_id);
	req->default_cmpl_ring_id =
		cpu_to_le16(bnge_cp_ring_for_rx(rxr));
	req->enables =
		cpu_to_le32(VNIC_CFG_REQ_ENABLES_DEFAULT_RX_RING_ID |
			    VNIC_CFG_REQ_ENABLES_DEFAULT_CMPL_RING_ID);
	vnic->mru = bd->netdev->mtu + ETH_HLEN + VLAN_HLEN;
	req->mru = cpu_to_le16(vnic->mru);

	req->vnic_id = cpu_to_le16(vnic->fw_vnic_id);

	if (bd->flags & BNGE_EN_STRIP_VLAN)
		req->flags |= cpu_to_le32(VNIC_CFG_REQ_FLAGS_VLAN_STRIP_MODE);
	if (vnic->vnic_id == BNGE_VNIC_DEFAULT && bnge_aux_registered(bd))
		req->flags |= cpu_to_le32(BNGE_VNIC_CFG_ROCE_DUAL_MODE);

	return bnge_hwrm_req_send(bd, req);
}

void bnge_hwrm_update_rss_hash_cfg(struct bnge_net *bn)
{
	struct bnge_vnic_info *vnic = &bn->vnic_info[BNGE_VNIC_DEFAULT];
	struct hwrm_vnic_rss_qcfg_output *resp;
	struct hwrm_vnic_rss_qcfg_input *req;
	struct bnge_dev *bd = bn->bd;

	if (bnge_hwrm_req_init(bd, req, HWRM_VNIC_RSS_QCFG))
		return;

	req->vnic_id = cpu_to_le16(vnic->fw_vnic_id);
	/* all contexts configured to same hash_type, zero always exists */
	req->rss_ctx_idx = cpu_to_le16(vnic->fw_rss_cos_lb_ctx[0]);
	resp = bnge_hwrm_req_hold(bd, req);
	if (!bnge_hwrm_req_send(bd, req))
		bd->rss_hash_cfg =
			le32_to_cpu(resp->hash_type) ?: bd->rss_hash_cfg;
	bnge_hwrm_req_drop(bd, req);
}

int bnge_hwrm_vnic_alloc(struct bnge_dev *bd, struct bnge_vnic_info *vnic,
			 unsigned int nr_rings)
{
	struct hwrm_vnic_alloc_output *resp;
	struct hwrm_vnic_alloc_input *req;
	unsigned int i;
	int rc;

	rc = bnge_hwrm_req_init(bd, req, HWRM_VNIC_ALLOC);
	if (rc)
		return rc;

	for (i = 0; i < BNGE_MAX_CTX_PER_VNIC; i++)
		vnic->fw_rss_cos_lb_ctx[i] = INVALID_HW_RING_ID;
	if (vnic->vnic_id == BNGE_VNIC_DEFAULT)
		req->flags = cpu_to_le32(VNIC_ALLOC_REQ_FLAGS_DEFAULT);

	resp = bnge_hwrm_req_hold(bd, req);
	rc = bnge_hwrm_req_send(bd, req);
	if (!rc)
		vnic->fw_vnic_id = le32_to_cpu(resp->vnic_id);
	bnge_hwrm_req_drop(bd, req);
	return rc;
}

void bnge_hwrm_vnic_free_one(struct bnge_dev *bd, struct bnge_vnic_info *vnic)
{
	if (vnic->fw_vnic_id != INVALID_HW_RING_ID) {
		struct hwrm_vnic_free_input *req;

		if (bnge_hwrm_req_init(bd, req, HWRM_VNIC_FREE))
			return;

		req->vnic_id = cpu_to_le32(vnic->fw_vnic_id);

		bnge_hwrm_req_send(bd, req);
		vnic->fw_vnic_id = INVALID_HW_RING_ID;
	}
}

void bnge_hwrm_vnic_ctx_free_one(struct bnge_dev *bd,
				 struct bnge_vnic_info *vnic, u16 ctx_idx)
{
	struct hwrm_vnic_rss_cos_lb_ctx_free_input *req;

	if (bnge_hwrm_req_init(bd, req, HWRM_VNIC_RSS_COS_LB_CTX_FREE))
		return;

	req->rss_cos_lb_ctx_id =
		cpu_to_le16(vnic->fw_rss_cos_lb_ctx[ctx_idx]);

	bnge_hwrm_req_send(bd, req);
	vnic->fw_rss_cos_lb_ctx[ctx_idx] = INVALID_HW_RING_ID;
}

void bnge_hwrm_stat_ctx_free(struct bnge_net *bn)
{
	struct hwrm_stat_ctx_free_input *req;
+19 −0
Original line number Diff line number Diff line
@@ -4,6 +4,13 @@
#ifndef _BNGE_HWRM_LIB_H_
#define _BNGE_HWRM_LIB_H_

#define BNGE_PLC_EN_JUMBO_THRES_VALID		\
	VNIC_PLCMODES_CFG_REQ_ENABLES_JUMBO_THRESH_VALID
#define BNGE_PLC_EN_HDS_THRES_VALID		\
	VNIC_PLCMODES_CFG_REQ_ENABLES_HDS_THRESHOLD_VALID
#define BNGE_VNIC_CFG_ROCE_DUAL_MODE		\
	VNIC_CFG_REQ_FLAGS_ROCE_DUAL_VNIC_MODE

int bnge_hwrm_ver_get(struct bnge_dev *bd);
int bnge_hwrm_func_reset(struct bnge_dev *bd);
int bnge_hwrm_fw_set_time(struct bnge_dev *bd);
@@ -24,6 +31,18 @@ int bnge_hwrm_func_qcfg(struct bnge_dev *bd);
int bnge_hwrm_func_resc_qcaps(struct bnge_dev *bd);
int bnge_hwrm_queue_qportcfg(struct bnge_dev *bd);

int bnge_hwrm_vnic_set_hds(struct bnge_net *bn, struct bnge_vnic_info *vnic);
int bnge_hwrm_vnic_ctx_alloc(struct bnge_dev *bd,
			     struct bnge_vnic_info *vnic, u16 ctx_idx);
int bnge_hwrm_vnic_set_rss(struct bnge_net *bn,
			   struct bnge_vnic_info *vnic, bool set_rss);
int bnge_hwrm_vnic_cfg(struct bnge_net *bn, struct bnge_vnic_info *vnic);
void bnge_hwrm_update_rss_hash_cfg(struct bnge_net *bn);
int bnge_hwrm_vnic_alloc(struct bnge_dev *bd, struct bnge_vnic_info *vnic,
			 unsigned int nr_rings);
void bnge_hwrm_vnic_free_one(struct bnge_dev *bd, struct bnge_vnic_info *vnic);
void bnge_hwrm_vnic_ctx_free_one(struct bnge_dev *bd,
				 struct bnge_vnic_info *vnic, u16 ctx_idx);
void bnge_hwrm_stat_ctx_free(struct bnge_net *bn);
int bnge_hwrm_stat_ctx_alloc(struct bnge_net *bn);
int hwrm_ring_free_send_msg(struct bnge_net *bn, struct bnge_ring_struct *ring,
+122 −0
Original line number Diff line number Diff line
@@ -1462,6 +1462,104 @@ static int bnge_hwrm_ring_alloc(struct bnge_net *bn)
	return rc;
}

void bnge_fill_hw_rss_tbl(struct bnge_net *bn, struct bnge_vnic_info *vnic)
{
	__le16 *ring_tbl = vnic->rss_table;
	struct bnge_rx_ring_info *rxr;
	struct bnge_dev *bd = bn->bd;
	u16 tbl_size, i;

	tbl_size = bnge_get_rxfh_indir_size(bd);

	for (i = 0; i < tbl_size; i++) {
		u16 ring_id, j;

		j = bd->rss_indir_tbl[i];
		rxr = &bn->rx_ring[j];

		ring_id = rxr->rx_ring_struct.fw_ring_id;
		*ring_tbl++ = cpu_to_le16(ring_id);
		ring_id = bnge_cp_ring_for_rx(rxr);
		*ring_tbl++ = cpu_to_le16(ring_id);
	}
}

static int bnge_hwrm_vnic_rss_cfg(struct bnge_net *bn,
				  struct bnge_vnic_info *vnic)
{
	int rc;

	rc = bnge_hwrm_vnic_set_rss(bn, vnic, true);
	if (rc) {
		netdev_err(bn->netdev, "hwrm vnic %d set rss failure rc: %d\n",
			   vnic->vnic_id, rc);
		return rc;
	}
	rc = bnge_hwrm_vnic_cfg(bn, vnic);
	if (rc)
		netdev_err(bn->netdev, "hwrm vnic %d cfg failure rc: %d\n",
			   vnic->vnic_id, rc);
	return rc;
}

static int bnge_setup_vnic(struct bnge_net *bn, struct bnge_vnic_info *vnic)
{
	struct bnge_dev *bd = bn->bd;
	int rc, i, nr_ctxs;

	nr_ctxs = bnge_cal_nr_rss_ctxs(bd->rx_nr_rings);
	for (i = 0; i < nr_ctxs; i++) {
		rc = bnge_hwrm_vnic_ctx_alloc(bd, vnic, i);
		if (rc) {
			netdev_err(bn->netdev, "hwrm vnic %d ctx %d alloc failure rc: %d\n",
				   vnic->vnic_id, i, rc);
			return -ENOMEM;
		}
		bn->rsscos_nr_ctxs++;
	}

	rc = bnge_hwrm_vnic_rss_cfg(bn, vnic);
	if (rc)
		return rc;

	if (bnge_is_agg_reqd(bd)) {
		rc = bnge_hwrm_vnic_set_hds(bn, vnic);
		if (rc)
			netdev_err(bn->netdev, "hwrm vnic %d set hds failure rc: %d\n",
				   vnic->vnic_id, rc);
	}
	return rc;
}

static void bnge_hwrm_vnic_free(struct bnge_net *bn)
{
	int i;

	for (i = 0; i < bn->nr_vnics; i++)
		bnge_hwrm_vnic_free_one(bn->bd, &bn->vnic_info[i]);
}

static void bnge_hwrm_vnic_ctx_free(struct bnge_net *bn)
{
	int i, j;

	for (i = 0; i < bn->nr_vnics; i++) {
		struct bnge_vnic_info *vnic = &bn->vnic_info[i];

		for (j = 0; j < BNGE_MAX_CTX_PER_VNIC; j++) {
			if (vnic->fw_rss_cos_lb_ctx[j] != INVALID_HW_RING_ID)
				bnge_hwrm_vnic_ctx_free_one(bn->bd, vnic, j);
		}
	}
	bn->rsscos_nr_ctxs = 0;
}

static void bnge_clear_vnic(struct bnge_net *bn)
{
	bnge_hwrm_vnic_free(bn);
	bnge_hwrm_vnic_ctx_free(bn);
}

static void bnge_hwrm_rx_ring_free(struct bnge_net *bn,
				   struct bnge_rx_ring_info *rxr,
				   bool close_path)
@@ -1605,6 +1703,7 @@ static int bnge_setup_interrupts(struct bnge_net *bn)

static void bnge_hwrm_resource_free(struct bnge_net *bn, bool close_path)
{
	bnge_clear_vnic(bn);
	bnge_hwrm_ring_free(bn, close_path);
	bnge_hwrm_stat_ctx_free(bn);
}
@@ -1678,6 +1777,8 @@ static int bnge_request_irq(struct bnge_net *bn)

static int bnge_init_chip(struct bnge_net *bn)
{
	struct bnge_vnic_info *vnic = &bn->vnic_info[BNGE_VNIC_DEFAULT];
	struct bnge_dev *bd = bn->bd;
	int rc;

#define BNGE_DEF_STATS_COAL_TICKS	 1000000
@@ -1694,6 +1795,19 @@ static int bnge_init_chip(struct bnge_net *bn)
		netdev_err(bn->netdev, "hwrm ring alloc failure rc: %d\n", rc);
		goto err_out;
	}

	rc = bnge_hwrm_vnic_alloc(bd, vnic, bd->rx_nr_rings);
	if (rc) {
		netdev_err(bn->netdev, "hwrm vnic alloc failure rc: %d\n", rc);
		goto err_out;
	}

	rc = bnge_setup_vnic(bn, vnic);
	if (rc)
		goto err_out;

	if (bd->rss_cap & BNGE_RSS_CAP_RSS_HASH_TYPE_DELTA)
		bnge_hwrm_update_rss_hash_cfg(bn);
	return 0;

err_out:
@@ -1838,11 +1952,19 @@ static int bnge_open(struct net_device *dev)
	return rc;
}

static int bnge_shutdown_nic(struct bnge_net *bn)
{
	/* TODO: close_path = 0 until we make NAPI functional */
	bnge_hwrm_resource_free(bn, 0);
	return 0;
}

static void bnge_close_core(struct bnge_net *bn)
{
	struct bnge_dev *bd = bn->bd;

	clear_bit(BNGE_STATE_OPEN, &bd->state);
	bnge_shutdown_nic(bn);
	bnge_free_all_rings_bufs(bn);
	bnge_free_irq(bn);
	bnge_del_napi(bn);
Loading