Commit 1d131151 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'marvell-cn10k'



Geetha sowjanya says:

====================
Add Marvell CN10K support

The current admin function (AF) driver and the netdev driver supports
OcteonTx2 silicon variants. The same OcteonTx2's
Resource Virtualization Unit (RVU) is carried forward to the next-gen
silicon ie OcteonTx3, with some changes and feature enhancements.

This patch set adds support for OcteonTx3 (CN10K) silicon and gets
the drivers to the same level as OcteonTx2. No new OcteonTx3 specific
features are added.

Changes cover below HW level differences
- PCIe BAR address changes wrt shared mailbox memory region
- Receive buffer freeing to HW
- Transmit packet's descriptor submission to HW
- Programmable HW interface identifiers (channels)
- Increased MTU support
- A Serdes MAC block (RPM) configuration

v5-v6
Rebased on top of latest net-next branch.

v4-v5
Fixed sparse warnings.

v3-v4
Fixed compiler warnings.

v2-v3
Reposting as a single thread.
Rebased on top latest net-next branch.

v1-v2
Fixed check-patch reported issues.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents cc6216ba 3ad3f8f9
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -10719,6 +10719,8 @@ M: Sunil Goutham <sgoutham@marvell.com>
M:	Linu Cherian <lcherian@marvell.com>
M:	Geetha sowjanya <gakula@marvell.com>
M:	Jerin Jacob <jerinj@marvell.com>
M:	hariprasad <hkelam@marvell.com>
M:	Subbaraya Sundeep <sbhatta@marvell.com>
L:	netdev@vger.kernel.org
S:	Supported
F:	Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst
+5 −5
Original line number Diff line number Diff line
@@ -4,10 +4,10 @@
#

ccflags-y += -I$(src)
obj-$(CONFIG_OCTEONTX2_MBOX) += octeontx2_mbox.o
obj-$(CONFIG_OCTEONTX2_AF) += octeontx2_af.o
obj-$(CONFIG_OCTEONTX2_MBOX) += rvu_mbox.o
obj-$(CONFIG_OCTEONTX2_AF) += rvu_af.o

octeontx2_mbox-y := mbox.o rvu_trace.o
octeontx2_af-y := cgx.o rvu.o rvu_cgx.o rvu_npa.o rvu_nix.o \
rvu_mbox-y := mbox.o rvu_trace.o
rvu_af-y := cgx.o rvu.o rvu_cgx.o rvu_npa.o rvu_nix.o \
		  rvu_reg.o rvu_npc.o rvu_debugfs.o ptp.o rvu_npc_fs.o \
		  rvu_cpt.o rvu_devlink.o
		  rvu_cpt.o rvu_devlink.o rpm.o rvu_cn10k.o
+226 −87
Original line number Diff line number Diff line
@@ -21,47 +21,11 @@
#include <linux/of_net.h>

#include "cgx.h"
#include "rvu.h"
#include "lmac_common.h"

#define DRV_NAME	"octeontx2-cgx"
#define DRV_STRING      "Marvell OcteonTX2 CGX/MAC Driver"

/**
 * struct lmac
 * @wq_cmd_cmplt:	waitq to keep the process blocked until cmd completion
 * @cmd_lock:		Lock to serialize the command interface
 * @resp:		command response
 * @link_info:		link related information
 * @event_cb:		callback for linkchange events
 * @event_cb_lock:	lock for serializing callback with unregister
 * @cmd_pend:		flag set before new command is started
 *			flag cleared after command response is received
 * @cgx:		parent cgx port
 * @lmac_id:		lmac port id
 * @name:		lmac port name
 */
struct lmac {
	wait_queue_head_t wq_cmd_cmplt;
	struct mutex cmd_lock;
	u64 resp;
	struct cgx_link_user_info link_info;
	struct cgx_event_cb event_cb;
	spinlock_t event_cb_lock;
	bool cmd_pend;
	struct cgx *cgx;
	u8 lmac_id;
	char *name;
};

struct cgx {
	void __iomem		*reg_base;
	struct pci_dev		*pdev;
	u8			cgx_id;
	u8			lmac_count;
	struct lmac		*lmac_idmap[MAX_LMAC_PER_CGX];
	struct			work_struct cgx_cmd_work;
	struct			workqueue_struct *cgx_cmd_workq;
	struct list_head	cgx_list;
};
#define DRV_NAME	"Marvell-CGX/RPM"
#define DRV_STRING      "Marvell CGX/RPM Driver"

static LIST_HEAD(cgx_list);

@@ -77,22 +41,45 @@ static int cgx_fwi_link_change(struct cgx *cgx, int lmac_id, bool en);
/* Supported devices */
static const struct pci_device_id cgx_id_table[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_CGX) },
	{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM) },
	{ 0, }  /* end of table */
};

MODULE_DEVICE_TABLE(pci, cgx_id_table);

static void cgx_write(struct cgx *cgx, u64 lmac, u64 offset, u64 val)
static bool is_dev_rpm(void *cgxd)
{
	struct cgx *cgx = cgxd;

	return (cgx->pdev->device == PCI_DEVID_CN10K_RPM);
}

bool is_lmac_valid(struct cgx *cgx, int lmac_id)
{
	return cgx && test_bit(lmac_id, &cgx->lmac_bmap);
}

struct mac_ops *get_mac_ops(void *cgxd)
{
	writeq(val, cgx->reg_base + (lmac << 18) + offset);
	if (!cgxd)
		return cgxd;

	return ((struct cgx *)cgxd)->mac_ops;
}

static u64 cgx_read(struct cgx *cgx, u64 lmac, u64 offset)
void cgx_write(struct cgx *cgx, u64 lmac, u64 offset, u64 val)
{
	return readq(cgx->reg_base + (lmac << 18) + offset);
	writeq(val, cgx->reg_base + (lmac << cgx->mac_ops->lmac_offset) +
	       offset);
}

static inline struct lmac *lmac_pdata(u8 lmac_id, struct cgx *cgx)
u64 cgx_read(struct cgx *cgx, u64 lmac, u64 offset)
{
	return readq(cgx->reg_base + (lmac << cgx->mac_ops->lmac_offset) +
		     offset);
}

struct lmac *lmac_pdata(u8 lmac_id, struct cgx *cgx)
{
	if (!cgx || lmac_id >= MAX_LMAC_PER_CGX)
		return NULL;
@@ -136,6 +123,20 @@ void *cgx_get_pdata(int cgx_id)
	return NULL;
}

void cgx_lmac_write(int cgx_id, int lmac_id, u64 offset, u64 val)
{
	struct cgx *cgx_dev = cgx_get_pdata(cgx_id);

	cgx_write(cgx_dev, lmac_id, offset, val);
}

u64 cgx_lmac_read(int cgx_id, int lmac_id, u64 offset)
{
	struct cgx *cgx_dev = cgx_get_pdata(cgx_id);

	return cgx_read(cgx_dev, lmac_id, offset);
}

int cgx_get_cgxid(void *cgxd)
{
	struct cgx *cgx = cgxd;
@@ -186,8 +187,10 @@ static u64 mac2u64 (u8 *mac_addr)
int cgx_lmac_addr_set(u8 cgx_id, u8 lmac_id, u8 *mac_addr)
{
	struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
	struct mac_ops *mac_ops;
	u64 cfg;

	mac_ops = cgx_dev->mac_ops;
	/* copy 6bytes from macaddr */
	/* memcpy(&cfg, mac_addr, 6); */

@@ -206,8 +209,11 @@ int cgx_lmac_addr_set(u8 cgx_id, u8 lmac_id, u8 *mac_addr)
u64 cgx_lmac_addr_get(u8 cgx_id, u8 lmac_id)
{
	struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
	struct mac_ops *mac_ops;
	u64 cfg;

	mac_ops = cgx_dev->mac_ops;

	cfg = cgx_read(cgx_dev, 0, CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8);
	return cfg & CGX_RX_DMAC_ADR_MASK;
}
@@ -216,15 +222,16 @@ int cgx_set_pkind(void *cgxd, u8 lmac_id, int pkind)
{
	struct cgx *cgx = cgxd;

	if (!cgx || lmac_id >= cgx->lmac_count)
	if (!is_lmac_valid(cgx, lmac_id))
		return -ENODEV;

	cgx_write(cgx, lmac_id, CGXX_CMRX_RX_ID_MAP, (pkind & 0x3F));
	return 0;
}

static inline u8 cgx_get_lmac_type(struct cgx *cgx, int lmac_id)
static u8 cgx_get_lmac_type(void *cgxd, int lmac_id)
{
	struct cgx *cgx = cgxd;
	u64 cfg;

	cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_CFG);
@@ -238,10 +245,10 @@ int cgx_lmac_internal_loopback(void *cgxd, int lmac_id, bool enable)
	u8 lmac_type;
	u64 cfg;

	if (!cgx || lmac_id >= cgx->lmac_count)
	if (!is_lmac_valid(cgx, lmac_id))
		return -ENODEV;

	lmac_type = cgx_get_lmac_type(cgx, lmac_id);
	lmac_type = cgx->mac_ops->get_lmac_type(cgx, lmac_id);
	if (lmac_type == LMAC_MODE_SGMII || lmac_type == LMAC_MODE_QSGMII) {
		cfg = cgx_read(cgx, lmac_id, CGXX_GMP_PCS_MRX_CTL);
		if (enable)
@@ -263,11 +270,13 @@ int cgx_lmac_internal_loopback(void *cgxd, int lmac_id, bool enable)
void cgx_lmac_promisc_config(int cgx_id, int lmac_id, bool enable)
{
	struct cgx *cgx = cgx_get_pdata(cgx_id);
	struct mac_ops *mac_ops;
	u64 cfg = 0;

	if (!cgx)
		return;

	mac_ops = cgx->mac_ops;
	if (enable) {
		/* Enable promiscuous mode on LMAC */
		cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_RX_DMAC_CTL0);
@@ -325,7 +334,7 @@ int cgx_get_rx_stats(void *cgxd, int lmac_id, int idx, u64 *rx_stat)
{
	struct cgx *cgx = cgxd;

	if (!cgx || lmac_id >= cgx->lmac_count)
	if (!is_lmac_valid(cgx, lmac_id))
		return -ENODEV;
	*rx_stat =  cgx_read(cgx, lmac_id, CGXX_CMRX_RX_STAT0 + (idx * 8));
	return 0;
@@ -335,12 +344,17 @@ int cgx_get_tx_stats(void *cgxd, int lmac_id, int idx, u64 *tx_stat)
{
	struct cgx *cgx = cgxd;

	if (!cgx || lmac_id >= cgx->lmac_count)
	if (!is_lmac_valid(cgx, lmac_id))
		return -ENODEV;
	*tx_stat = cgx_read(cgx, lmac_id, CGXX_CMRX_TX_STAT0 + (idx * 8));
	return 0;
}

u64 cgx_features_get(void *cgxd)
{
	return ((struct cgx *)cgxd)->hw_features;
}

static int cgx_set_fec_stats_count(struct cgx_link_user_info *linfo)
{
	if (!linfo->fec)
@@ -400,7 +414,7 @@ int cgx_lmac_rx_tx_enable(void *cgxd, int lmac_id, bool enable)
	struct cgx *cgx = cgxd;
	u64 cfg;

	if (!cgx || lmac_id >= cgx->lmac_count)
	if (!is_lmac_valid(cgx, lmac_id))
		return -ENODEV;

	cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_CFG);
@@ -417,7 +431,7 @@ int cgx_lmac_tx_enable(void *cgxd, int lmac_id, bool enable)
	struct cgx *cgx = cgxd;
	u64 cfg, last;

	if (!cgx || lmac_id >= cgx->lmac_count)
	if (!is_lmac_valid(cgx, lmac_id))
		return -ENODEV;

	cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_CFG);
@@ -432,13 +446,16 @@ int cgx_lmac_tx_enable(void *cgxd, int lmac_id, bool enable)
	return !!(last & DATA_PKT_TX_EN);
}

int cgx_lmac_get_pause_frm(void *cgxd, int lmac_id,
static int cgx_lmac_get_pause_frm_status(void *cgxd, int lmac_id,
					 u8 *tx_pause, u8 *rx_pause)
{
	struct cgx *cgx = cgxd;
	u64 cfg;

	if (!cgx || lmac_id >= cgx->lmac_count)
	if (is_dev_rpm(cgx))
		return 0;

	if (!is_lmac_valid(cgx, lmac_id))
		return -ENODEV;

	cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_RX_FRM_CTL);
@@ -449,13 +466,16 @@ int cgx_lmac_get_pause_frm(void *cgxd, int lmac_id,
	return 0;
}

int cgx_lmac_set_pause_frm(void *cgxd, int lmac_id,
static int cgx_lmac_enadis_pause_frm(void *cgxd, int lmac_id,
				     u8 tx_pause, u8 rx_pause)
{
	struct cgx *cgx = cgxd;
	u64 cfg;

	if (!cgx || lmac_id >= cgx->lmac_count)
	if (is_dev_rpm(cgx))
		return 0;

	if (!is_lmac_valid(cgx, lmac_id))
		return -ENODEV;

	cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_RX_FRM_CTL);
@@ -479,11 +499,12 @@ int cgx_lmac_set_pause_frm(void *cgxd, int lmac_id,
	return 0;
}

static void cgx_lmac_pause_frm_config(struct cgx *cgx, int lmac_id, bool enable)
static void cgx_lmac_pause_frm_config(void *cgxd, int lmac_id, bool enable)
{
	struct cgx *cgx = cgxd;
	u64 cfg;

	if (!cgx || lmac_id >= cgx->lmac_count)
	if (!is_lmac_valid(cgx, lmac_id))
		return;
	if (enable) {
		/* Enable receive pause frames */
@@ -541,6 +562,9 @@ void cgx_lmac_ptp_config(void *cgxd, int lmac_id, bool enable)
	if (!cgx)
		return;

	if (is_dev_rpm(cgx))
		return;

	if (enable) {
		/* Enable inbound PTP timestamping */
		cfg = cgx_read(cgx, lmac_id, CGXX_GMP_GMI_RXX_FRM_CTL);
@@ -563,7 +587,7 @@ void cgx_lmac_ptp_config(void *cgxd, int lmac_id, bool enable)
}

/* CGX Firmware interface low level support */
static int cgx_fwi_cmd_send(u64 req, u64 *resp, struct lmac *lmac)
int cgx_fwi_cmd_send(u64 req, u64 *resp, struct lmac *lmac)
{
	struct cgx *cgx = lmac->cgx;
	struct device *dev;
@@ -611,8 +635,7 @@ static int cgx_fwi_cmd_send(u64 req, u64 *resp, struct lmac *lmac)
	return err;
}

static inline int cgx_fwi_cmd_generic(u64 req, u64 *resp,
				      struct cgx *cgx, int lmac_id)
int cgx_fwi_cmd_generic(u64 req, u64 *resp, struct cgx *cgx, int lmac_id)
{
	struct lmac *lmac;
	int err;
@@ -885,12 +908,16 @@ static inline bool cgx_event_is_linkevent(u64 event)

static irqreturn_t cgx_fwi_event_handler(int irq, void *data)
{
	u64 event, offset, clear_bit;
	struct lmac *lmac = data;
	struct cgx *cgx;
	u64 event;

	cgx = lmac->cgx;

	/* Clear SW_INT for RPM and CMR_INT for CGX */
	offset     = cgx->mac_ops->int_register;
	clear_bit  = cgx->mac_ops->int_ena_bit;

	event = cgx_read(cgx, lmac->lmac_id, CGX_EVENT_REG);

	if (!FIELD_GET(EVTREG_ACK, event))
@@ -926,7 +953,7 @@ static irqreturn_t cgx_fwi_event_handler(int irq, void *data)
	 * Ack the interrupt register as well.
	 */
	cgx_write(lmac->cgx, lmac->lmac_id, CGX_EVENT_REG, 0);
	cgx_write(lmac->cgx, lmac->lmac_id, CGXX_CMRX_INT, FW_CGX_INT);
	cgx_write(lmac->cgx, lmac->lmac_id, offset, clear_bit);

	return IRQ_HANDLED;
}
@@ -970,14 +997,16 @@ int cgx_get_fwdata_base(u64 *base)
{
	u64 req = 0, resp;
	struct cgx *cgx;
	int first_lmac;
	int err;

	cgx = list_first_entry_or_null(&cgx_list, struct cgx, cgx_list);
	if (!cgx)
		return -ENXIO;

	first_lmac = find_first_bit(&cgx->lmac_bmap, MAX_LMAC_PER_CGX);
	req = FIELD_SET(CMDREG_ID, CGX_CMD_GET_FWD_BASE, req);
	err = cgx_fwi_cmd_generic(req, &resp, cgx, 0);
	err = cgx_fwi_cmd_generic(req, &resp, cgx, first_lmac);
	if (!err)
		*base = FIELD_GET(RESP_FWD_BASE, resp);

@@ -1056,10 +1085,11 @@ static int cgx_fwi_link_change(struct cgx *cgx, int lmac_id, bool enable)

static inline int cgx_fwi_read_version(u64 *resp, struct cgx *cgx)
{
	int first_lmac = find_first_bit(&cgx->lmac_bmap, MAX_LMAC_PER_CGX);
	u64 req = 0;

	req = FIELD_SET(CMDREG_ID, CGX_CMD_GET_FW_VER, req);
	return cgx_fwi_cmd_generic(req, resp, cgx, 0);
	return cgx_fwi_cmd_generic(req, resp, cgx, first_lmac);
}

static int cgx_lmac_verify_fwi_version(struct cgx *cgx)
@@ -1092,8 +1122,8 @@ static void cgx_lmac_linkup_work(struct work_struct *work)
	struct device *dev = &cgx->pdev->dev;
	int i, err;

	/* Do Link up for all the lmacs */
	for (i = 0; i < cgx->lmac_count; i++) {
	/* Do Link up for all the enabled lmacs */
	for_each_set_bit(i, &cgx->lmac_bmap, MAX_LMAC_PER_CGX) {
		err = cgx_fwi_link_change(cgx, i, true);
		if (err)
			dev_info(dev, "cgx port %d:%d Link up command failed\n",
@@ -1113,12 +1143,77 @@ int cgx_lmac_linkup_start(void *cgxd)
	return 0;
}

static void cgx_lmac_get_fifolen(struct cgx *cgx)
{
	u64 cfg;

	cfg = cgx_read(cgx, 0, CGX_CONST);
	cgx->mac_ops->fifo_len = FIELD_GET(CGX_CONST_RXFIFO_SIZE, cfg);
}

static int cgx_configure_interrupt(struct cgx *cgx, struct lmac *lmac,
				   int cnt, bool req_free)
{
	struct mac_ops *mac_ops = cgx->mac_ops;
	u64 offset, ena_bit;
	unsigned int irq;
	int err;

	irq      = pci_irq_vector(cgx->pdev, mac_ops->lmac_fwi +
				  cnt * mac_ops->irq_offset);
	offset   = mac_ops->int_set_reg;
	ena_bit  = mac_ops->int_ena_bit;

	if (req_free) {
		free_irq(irq, lmac);
		return 0;
	}

	err = request_irq(irq, cgx_fwi_event_handler, 0, lmac->name, lmac);
	if (err)
		return err;

	/* Enable interrupt */
	cgx_write(cgx, lmac->lmac_id, offset, ena_bit);
	return 0;
}

int cgx_get_nr_lmacs(void *cgxd)
{
	struct cgx *cgx = cgxd;

	return cgx_read(cgx, 0, CGXX_CMRX_RX_LMACS) & 0x7ULL;
}

u8 cgx_get_lmacid(void *cgxd, u8 lmac_index)
{
	struct cgx *cgx = cgxd;

	return cgx->lmac_idmap[lmac_index]->lmac_id;
}

unsigned long cgx_get_lmac_bmap(void *cgxd)
{
	struct cgx *cgx = cgxd;

	return cgx->lmac_bmap;
}

static int cgx_lmac_init(struct cgx *cgx)
{
	struct lmac *lmac;
	u64 lmac_list;
	int i, err;

	cgx->lmac_count = cgx_read(cgx, 0, CGXX_CMRX_RX_LMACS) & 0x7;
	cgx_lmac_get_fifolen(cgx);

	cgx->lmac_count = cgx->mac_ops->get_nr_lmacs(cgx);
	/* lmac_list specifies which lmacs are enabled
	 * when bit n is set to 1, LMAC[n] is enabled
	 */
	if (cgx->mac_ops->non_contiguous_serdes_lane)
		lmac_list = cgx_read(cgx, 0, CGXX_CMRX_RX_LMACS) & 0xFULL;

	if (cgx->lmac_count > MAX_LMAC_PER_CGX)
		cgx->lmac_count = MAX_LMAC_PER_CGX;

@@ -1132,24 +1227,25 @@ static int cgx_lmac_init(struct cgx *cgx)
			goto err_lmac_free;
		}
		sprintf(lmac->name, "cgx_fwi_%d_%d", cgx->cgx_id, i);
		if (cgx->mac_ops->non_contiguous_serdes_lane) {
			lmac->lmac_id = __ffs64(lmac_list);
			lmac_list   &= ~BIT_ULL(lmac->lmac_id);
		} else {
			lmac->lmac_id = i;
		}

		lmac->cgx = cgx;
		init_waitqueue_head(&lmac->wq_cmd_cmplt);
		mutex_init(&lmac->cmd_lock);
		spin_lock_init(&lmac->event_cb_lock);
		err = request_irq(pci_irq_vector(cgx->pdev,
						 CGX_LMAC_FWI + i * 9),
				   cgx_fwi_event_handler, 0, lmac->name, lmac);
		err = cgx_configure_interrupt(cgx, lmac, lmac->lmac_id, false);
		if (err)
			goto err_irq;

		/* Enable interrupt */
		cgx_write(cgx, lmac->lmac_id, CGXX_CMRX_INT_ENA_W1S,
			  FW_CGX_INT);

		/* Add reference */
		cgx->lmac_idmap[i] = lmac;
		cgx_lmac_pause_frm_config(cgx, i, true);
		cgx->lmac_idmap[lmac->lmac_id] = lmac;
		cgx->mac_ops->mac_pause_frm_config(cgx, lmac->lmac_id, true);
		set_bit(lmac->lmac_id, &cgx->lmac_bmap);
	}

	return cgx_lmac_verify_fwi_version(cgx);
@@ -1173,12 +1269,12 @@ static int cgx_lmac_exit(struct cgx *cgx)
	}

	/* Free all lmac related resources */
	for (i = 0; i < cgx->lmac_count; i++) {
		cgx_lmac_pause_frm_config(cgx, i, false);
	for_each_set_bit(i, &cgx->lmac_bmap, MAX_LMAC_PER_CGX) {
		lmac = cgx->lmac_idmap[i];
		if (!lmac)
			continue;
		free_irq(pci_irq_vector(cgx->pdev, CGX_LMAC_FWI + i * 9), lmac);
		cgx->mac_ops->mac_pause_frm_config(cgx, lmac->lmac_id, false);
		cgx_configure_interrupt(cgx, lmac, lmac->lmac_id, true);
		kfree(lmac->name);
		kfree(lmac);
	}
@@ -1186,6 +1282,37 @@ static int cgx_lmac_exit(struct cgx *cgx)
	return 0;
}

static void cgx_populate_features(struct cgx *cgx)
{
	if (is_dev_rpm(cgx))
		cgx->hw_features =  (RVU_MAC_RPM | RVU_LMAC_FEAT_FC);
	else
		cgx->hw_features = (RVU_LMAC_FEAT_FC | RVU_LMAC_FEAT_PTP);
}

static struct mac_ops	cgx_mac_ops    = {
	.name		=       "cgx",
	.csr_offset	=       0,
	.lmac_offset    =       18,
	.int_register	=       CGXX_CMRX_INT,
	.int_set_reg	=       CGXX_CMRX_INT_ENA_W1S,
	.irq_offset	=       9,
	.int_ena_bit    =       FW_CGX_INT,
	.lmac_fwi	=	CGX_LMAC_FWI,
	.non_contiguous_serdes_lane = false,
	.rx_stats_cnt   =       9,
	.tx_stats_cnt   =       18,
	.get_nr_lmacs	=	cgx_get_nr_lmacs,
	.get_lmac_type  =       cgx_get_lmac_type,
	.mac_lmac_intl_lbk =    cgx_lmac_internal_loopback,
	.mac_get_rx_stats  =	cgx_get_rx_stats,
	.mac_get_tx_stats  =	cgx_get_tx_stats,
	.mac_enadis_rx_pause_fwding =	cgx_lmac_enadis_rx_pause_fwding,
	.mac_get_pause_frm_status =	cgx_lmac_get_pause_frm_status,
	.mac_enadis_pause_frm =		cgx_lmac_enadis_pause_frm,
	.mac_pause_frm_config =		cgx_lmac_pause_frm_config,
};

static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
	struct device *dev = &pdev->dev;
@@ -1199,6 +1326,12 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)

	pci_set_drvdata(pdev, cgx);

	/* Use mac_ops to get MAC specific features */
	if (pdev->device == PCI_DEVID_CN10K_RPM)
		cgx->mac_ops = rpm_get_mac_ops();
	else
		cgx->mac_ops = &cgx_mac_ops;

	err = pci_enable_device(pdev);
	if (err) {
		dev_err(dev, "Failed to enable PCI device\n");
@@ -1220,7 +1353,7 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
		goto err_release_regions;
	}

	nvec = CGX_NVEC;
	nvec = pci_msix_vec_count(cgx->pdev);
	err = pci_alloc_irq_vectors(pdev, nvec, nvec, PCI_IRQ_MSIX);
	if (err < 0 || err != nvec) {
		dev_err(dev, "Request for %d msix vectors failed, err %d\n",
@@ -1244,6 +1377,10 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)

	cgx_link_usertable_init();

	cgx_populate_features(cgx);

	mutex_init(&cgx->lock);

	err = cgx_lmac_init(cgx);
	if (err)
		goto err_release_lmac;
@@ -1267,8 +1404,10 @@ static void cgx_remove(struct pci_dev *pdev)
{
	struct cgx *cgx = pci_get_drvdata(pdev);

	if (cgx) {
		cgx_lmac_exit(cgx);
		list_del(&cgx->cgx_list);
	}
	pci_free_irq_vectors(pdev);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
+11 −4
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@

#include "mbox.h"
#include "cgx_fw_if.h"
#include "rpm.h"

 /* PCI device IDs */
#define	PCI_DEVID_OCTEONTX2_CGX		0xA059
@@ -42,12 +43,12 @@
#define CGXX_CMRX_RX_ID_MAP		0x060
#define CGXX_CMRX_RX_STAT0		0x070
#define CGXX_CMRX_RX_LMACS		0x128
#define CGXX_CMRX_RX_DMAC_CTL0		0x1F8
#define CGXX_CMRX_RX_DMAC_CTL0		(0x1F8 + mac_ops->csr_offset)
#define CGX_DMAC_CTL0_CAM_ENABLE	BIT_ULL(3)
#define CGX_DMAC_CAM_ACCEPT		BIT_ULL(3)
#define CGX_DMAC_MCAST_MODE		BIT_ULL(1)
#define CGX_DMAC_BCAST_MODE		BIT_ULL(0)
#define CGXX_CMRX_RX_DMAC_CAM0		0x200
#define CGXX_CMRX_RX_DMAC_CAM0		(0x200 + mac_ops->csr_offset)
#define CGX_DMAC_CAM_ADDR_ENABLE	BIT_ULL(48)
#define CGXX_CMRX_RX_DMAC_CAM1		0x400
#define CGX_RX_DMAC_ADR_MASK		GENMASK_ULL(47, 0)
@@ -55,6 +56,7 @@
#define CGXX_SCRATCH0_REG		0x1050
#define CGXX_SCRATCH1_REG		0x1058
#define CGX_CONST			0x2000
#define CGX_CONST_RXFIFO_SIZE	        GENMASK_ULL(23, 0)
#define CGXX_SPUX_CONTROL1		0x10000
#define CGXX_SPUX_LNX_FEC_CORR_BLOCKS	0x10700
#define CGXX_SPUX_LNX_FEC_UNCORR_BLOCKS	0x10800
@@ -86,7 +88,6 @@
#define CGX_CMD_TIMEOUT			2200 /* msecs */
#define DEFAULT_PAUSE_TIME		0x7FF

#define CGX_NVEC			37
#define CGX_LMAC_FWI			0

enum  cgx_nix_stat_type {
@@ -157,5 +158,11 @@ int cgx_get_fec_stats(void *cgxd, int lmac_id, struct cgx_fec_stats_rsp *rsp);
int cgx_get_phy_fec_stats(void *cgxd, int lmac_id);
int cgx_set_link_mode(void *cgxd, struct cgx_set_link_mode_args args,
		      int cgx_id, int lmac_id);

u64 cgx_features_get(void *cgxd);
struct mac_ops *get_mac_ops(void *cgxd);
int cgx_get_nr_lmacs(void *cgxd);
u8 cgx_get_lmacid(void *cgxd, u8 lmac_index);
unsigned long cgx_get_lmac_bmap(void *cgxd);
void cgx_lmac_write(int cgx_id, int lmac_id, u64 offset, u64 val);
u64 cgx_lmac_read(int cgx_id, int lmac_id, u64 offset);
#endif /* CGX_H */
+1 −0
Original line number Diff line number Diff line
@@ -204,6 +204,7 @@ enum cgx_cmd_own {
 * CGX_STAT_SUCCESS
 */
#define RESP_FWD_BASE		GENMASK_ULL(56, 9)
#define RESP_LINKSTAT_LMAC_TYPE                GENMASK_ULL(35, 28)

/* Response to cmd ID - CGX_CMD_LINK_BRING_UP/DOWN, event ID CGX_EVT_LINK_CHANGE
 * status can be either CGX_STAT_FAIL or CGX_STAT_SUCCESS
Loading