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

bng_en: Register rings with the firmware



Enable ring functionality by registering RX, AGG, TX, CMPL, and
NQ rings with the firmware. Initialise the doorbells associated
with the rings.

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-9-bhargava.marreddy@broadcom.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 23df6aeb
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -102,6 +102,10 @@ struct bnge_dev {
	u16		chip_num;
	u8		chip_rev;

#if BITS_PER_LONG == 32
	/* ensure atomic 64-bit doorbell writes on 32-bit systems. */
	spinlock_t	db_lock;
#endif
	int		db_offset; /* db_offset within db_size */
	int		db_size;

@@ -214,6 +218,26 @@ static inline bool bnge_is_agg_reqd(struct bnge_dev *bd)
	return true;
}

static inline void bnge_writeq(struct bnge_dev *bd, u64 val,
			       void __iomem *addr)
{
#if BITS_PER_LONG == 32
	spin_lock(&bd->db_lock);
	lo_hi_writeq(val, addr);
	spin_unlock(&bd->db_lock);
#else
	writeq(val, addr);
#endif
}

/* For TX and RX ring doorbells */
static inline void bnge_db_write(struct bnge_dev *bd, struct bnge_db_info *db,
				 u32 idx)
{
	bnge_writeq(bd, db->db_key64 | DB_RING_IDX(db, idx),
		    db->doorbell);
}

bool bnge_aux_registered(struct bnge_dev *bd);
u16 bnge_aux_get_msix(struct bnge_dev *bd);

+4 −0
Original line number Diff line number Diff line
@@ -296,6 +296,10 @@ static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
		goto err_config_uninit;
	}

#if BITS_PER_LONG == 32
	spin_lock_init(&bd->db_lock);
#endif

	rc = bnge_alloc_irqs(bd);
	if (rc) {
		dev_err(&pdev->dev, "Error IRQ allocation rc = %d\n", rc);
+34 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2025 Broadcom */

#ifndef _BNGE_DB_H_
#define _BNGE_DB_H_

/* 64-bit doorbell */
#define DBR_EPOCH_SFT					24
#define DBR_TOGGLE_SFT					25
#define DBR_XID_SFT					32
#define DBR_PATH_L2					(0x1ULL << 56)
#define DBR_VALID					(0x1ULL << 58)
#define DBR_TYPE_SQ					(0x0ULL << 60)
#define DBR_TYPE_SRQ					(0x2ULL << 60)
#define DBR_TYPE_CQ					(0x4ULL << 60)
#define DBR_TYPE_CQ_ARMALL				(0x6ULL << 60)
#define DBR_TYPE_NQ					(0xaULL << 60)
#define DBR_TYPE_NQ_ARM					(0xbULL << 60)
#define DBR_TYPE_NQ_MASK				(0xeULL << 60)

struct bnge_db_info {
	void __iomem		*doorbell;
	u64			db_key64;
	u32			db_ring_mask;
	u32			db_epoch_mask;
	u8			db_epoch_shift;
};

#define DB_EPOCH(db, idx)	(((idx) & (db)->db_epoch_mask) <<	\
				 ((db)->db_epoch_shift))
#define DB_RING_IDX(db, idx)	(((idx) & (db)->db_ring_mask) |		\
				 DB_EPOCH(db, idx))

#endif /* _BNGE_DB_H_ */
+147 −0
Original line number Diff line number Diff line
@@ -757,3 +757,150 @@ int bnge_hwrm_stat_ctx_alloc(struct bnge_net *bn)
	bnge_hwrm_req_drop(bd, req);
	return rc;
}

int hwrm_ring_free_send_msg(struct bnge_net *bn,
			    struct bnge_ring_struct *ring,
			    u32 ring_type, int cmpl_ring_id)
{
	struct hwrm_ring_free_input *req;
	struct bnge_dev *bd = bn->bd;
	int rc;

	rc = bnge_hwrm_req_init(bd, req, HWRM_RING_FREE);
	if (rc)
		goto exit;

	req->cmpl_ring = cpu_to_le16(cmpl_ring_id);
	req->ring_type = ring_type;
	req->ring_id = cpu_to_le16(ring->fw_ring_id);

	bnge_hwrm_req_hold(bd, req);
	rc = bnge_hwrm_req_send(bd, req);
	bnge_hwrm_req_drop(bd, req);
exit:
	if (rc) {
		netdev_err(bd->netdev, "hwrm_ring_free type %d failed. rc:%d\n", ring_type, rc);
		return -EIO;
	}
	return 0;
}

int hwrm_ring_alloc_send_msg(struct bnge_net *bn,
			     struct bnge_ring_struct *ring,
			     u32 ring_type, u32 map_index)
{
	struct bnge_ring_mem_info *rmem = &ring->ring_mem;
	struct bnge_ring_grp_info *grp_info;
	struct hwrm_ring_alloc_output *resp;
	struct hwrm_ring_alloc_input *req;
	struct bnge_dev *bd = bn->bd;
	u16 ring_id, flags = 0;
	int rc;

	rc = bnge_hwrm_req_init(bd, req, HWRM_RING_ALLOC);
	if (rc)
		goto exit;

	req->enables = 0;
	if (rmem->nr_pages > 1) {
		req->page_tbl_addr = cpu_to_le64(rmem->dma_pg_tbl);
		/* Page size is in log2 units */
		req->page_size = BNGE_PAGE_SHIFT;
		req->page_tbl_depth = 1;
	} else {
		req->page_tbl_addr =  cpu_to_le64(rmem->dma_arr[0]);
	}
	req->fbo = 0;
	/* Association of ring index with doorbell index and MSIX number */
	req->logical_id = cpu_to_le16(map_index);

	switch (ring_type) {
	case HWRM_RING_ALLOC_TX: {
		struct bnge_tx_ring_info *txr;

		txr = container_of(ring, struct bnge_tx_ring_info,
				   tx_ring_struct);
		req->ring_type = RING_ALLOC_REQ_RING_TYPE_TX;
		/* Association of transmit ring with completion ring */
		grp_info = &bn->grp_info[ring->grp_idx];
		req->cmpl_ring_id = cpu_to_le16(bnge_cp_ring_for_tx(txr));
		req->length = cpu_to_le32(bn->tx_ring_mask + 1);
		req->stat_ctx_id = cpu_to_le32(grp_info->fw_stats_ctx);
		req->queue_id = cpu_to_le16(ring->queue_id);
		req->flags = cpu_to_le16(flags);
		break;
	}
	case HWRM_RING_ALLOC_RX:
		req->ring_type = RING_ALLOC_REQ_RING_TYPE_RX;
		req->length = cpu_to_le32(bn->rx_ring_mask + 1);

		/* Association of rx ring with stats context */
		grp_info = &bn->grp_info[ring->grp_idx];
		req->rx_buf_size = cpu_to_le16(bn->rx_buf_use_size);
		req->stat_ctx_id = cpu_to_le32(grp_info->fw_stats_ctx);
		req->enables |=
			cpu_to_le32(RING_ALLOC_REQ_ENABLES_RX_BUF_SIZE_VALID);
		if (NET_IP_ALIGN == 2)
			flags = RING_ALLOC_REQ_FLAGS_RX_SOP_PAD;
		req->flags = cpu_to_le16(flags);
		break;
	case HWRM_RING_ALLOC_AGG:
		req->ring_type = RING_ALLOC_REQ_RING_TYPE_RX_AGG;
		/* Association of agg ring with rx ring */
		grp_info = &bn->grp_info[ring->grp_idx];
		req->rx_ring_id = cpu_to_le16(grp_info->rx_fw_ring_id);
		req->rx_buf_size = cpu_to_le16(BNGE_RX_PAGE_SIZE);
		req->stat_ctx_id = cpu_to_le32(grp_info->fw_stats_ctx);
		req->enables |=
			cpu_to_le32(RING_ALLOC_REQ_ENABLES_RX_RING_ID_VALID |
				    RING_ALLOC_REQ_ENABLES_RX_BUF_SIZE_VALID);
		req->length = cpu_to_le32(bn->rx_agg_ring_mask + 1);
		break;
	case HWRM_RING_ALLOC_CMPL:
		req->ring_type = RING_ALLOC_REQ_RING_TYPE_L2_CMPL;
		req->length = cpu_to_le32(bn->cp_ring_mask + 1);
		/* Association of cp ring with nq */
		grp_info = &bn->grp_info[map_index];
		req->nq_ring_id = cpu_to_le16(grp_info->nq_fw_ring_id);
		req->cq_handle = cpu_to_le64(ring->handle);
		req->enables |=
			cpu_to_le32(RING_ALLOC_REQ_ENABLES_NQ_RING_ID_VALID);
		break;
	case HWRM_RING_ALLOC_NQ:
		req->ring_type = RING_ALLOC_REQ_RING_TYPE_NQ;
		req->length = cpu_to_le32(bn->cp_ring_mask + 1);
		req->int_mode = RING_ALLOC_REQ_INT_MODE_MSIX;
		break;
	default:
		netdev_err(bn->netdev, "hwrm alloc invalid ring type %d\n", ring_type);
		return -EINVAL;
	}

	resp = bnge_hwrm_req_hold(bd, req);
	rc = bnge_hwrm_req_send(bd, req);
	ring_id = le16_to_cpu(resp->ring_id);
	bnge_hwrm_req_drop(bd, req);

exit:
	if (rc) {
		netdev_err(bd->netdev, "hwrm_ring_alloc type %d failed. rc:%d\n", ring_type, rc);
		return -EIO;
	}
	ring->fw_ring_id = ring_id;
	return rc;
}

int bnge_hwrm_set_async_event_cr(struct bnge_dev *bd, int idx)
{
	struct hwrm_func_cfg_input *req;
	int rc;

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

	req->fid = cpu_to_le16(0xffff);
	req->enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_ASYNC_EVENT_CR);
	req->async_event_cr = cpu_to_le16(idx);
	return bnge_hwrm_req_send(bd, req);
}
+6 −0
Original line number Diff line number Diff line
@@ -26,4 +26,10 @@ int bnge_hwrm_queue_qportcfg(struct bnge_dev *bd);

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,
			    u32 ring_type, int cmpl_ring_id);
int hwrm_ring_alloc_send_msg(struct bnge_net *bn,
			     struct bnge_ring_struct *ring,
			     u32 ring_type, u32 map_index);
int bnge_hwrm_set_async_event_cr(struct bnge_dev *bd, int idx);
#endif /* _BNGE_HWRM_LIB_H_ */
Loading