brintos

brintos / linux-shallow public Read only

0
0
Text · 17.5 KiB · 7d54331 Raw
677 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Marvell Octeon CN10K DPI driver3 *4 * Copyright (C) 2024 Marvell.5 *6 */7 8#include <linux/bitfield.h>9#include <linux/compat.h>10#include <linux/delay.h>11#include <linux/miscdevice.h>12#include <linux/module.h>13#include <linux/pci.h>14#include <linux/irq.h>15#include <linux/interrupt.h>16 17#include <uapi/misc/mrvl_cn10k_dpi.h>18 19/* PCI device IDs */20#define PCI_DEVID_MRVL_CN10K_DPI_PF	0xA08021#define PCI_SUBDEVID_MRVL_CN10K_DPI_PF	0xB90022 23/* PCI BAR Number */24#define PCI_DPI_CFG_BAR	025 26/* MSI-X interrupts */27#define DPI_MAX_REQQ_INT	0x2028#define DPI_MAX_CC_INT		0x4029 30/* MBOX MSI-X interrupt vector index */31#define DPI_MBOX_PF_VF_INT_IDX	0x7532 33#define DPI_MAX_IRQS (DPI_MBOX_PF_VF_INT_IDX + 1)34 35#define DPI_MAX_VFS	0x2036 37#define DPI_MAX_ENG_FIFO_SZ	0x2038#define DPI_MAX_ENG_MOLR	0x40039 40#define DPI_DMA_IDS_DMA_NPA_PF_FUNC(x)	FIELD_PREP(GENMASK_ULL(31, 16), x)41#define DPI_DMA_IDS_INST_STRM(x)	FIELD_PREP(GENMASK_ULL(47, 40), x)42#define DPI_DMA_IDS_DMA_STRM(x)		FIELD_PREP(GENMASK_ULL(39, 32), x)43#define DPI_DMA_ENG_EN_MOLR(x)		FIELD_PREP(GENMASK_ULL(41, 32), x)44#define DPI_EBUS_PORTX_CFG_MPS(x)	FIELD_PREP(GENMASK(6, 4), x)45#define DPI_DMA_IDS_DMA_SSO_PF_FUNC(x)	FIELD_PREP(GENMASK(15, 0), x)46#define DPI_DMA_IDS2_INST_AURA(x)	FIELD_PREP(GENMASK(19, 0), x)47#define DPI_DMA_IBUFF_CSIZE_CSIZE(x)	FIELD_PREP(GENMASK(13, 0), x)48#define DPI_EBUS_PORTX_CFG_MRRS(x)	FIELD_PREP(GENMASK(2, 0), x)49#define DPI_ENG_BUF_BLKS(x)		FIELD_PREP(GENMASK(5, 0), x)50#define DPI_DMA_CONTROL_DMA_ENB		GENMASK_ULL(53, 48)51 52#define DPI_DMA_CONTROL_O_MODE		BIT_ULL(14)53#define DPI_DMA_CONTROL_LDWB		BIT_ULL(32)54#define DPI_DMA_CONTROL_WQECSMODE1	BIT_ULL(37)55#define DPI_DMA_CONTROL_ZBWCSEN		BIT_ULL(39)56#define DPI_DMA_CONTROL_WQECSOFF(ofst)	(((u64)ofst) << 40)57#define DPI_DMA_CONTROL_WQECSDIS	BIT_ULL(47)58#define DPI_DMA_CONTROL_PKT_EN		BIT_ULL(56)59#define DPI_DMA_IBUFF_CSIZE_NPA_FREE	BIT(16)60 61#define DPI_CTL_EN			BIT_ULL(0)62#define DPI_DMA_CC_INT			BIT_ULL(0)63#define DPI_DMA_QRST			BIT_ULL(0)64 65#define DPI_REQQ_INT_INSTRFLT		BIT_ULL(0)66#define DPI_REQQ_INT_RDFLT		BIT_ULL(1)67#define DPI_REQQ_INT_WRFLT		BIT_ULL(2)68#define DPI_REQQ_INT_CSFLT		BIT_ULL(3)69#define DPI_REQQ_INT_INST_DBO		BIT_ULL(4)70#define DPI_REQQ_INT_INST_ADDR_NULL	BIT_ULL(5)71#define DPI_REQQ_INT_INST_FILL_INVAL	BIT_ULL(6)72#define DPI_REQQ_INT_INSTR_PSN		BIT_ULL(7)73 74#define DPI_REQQ_INT \75	(DPI_REQQ_INT_INSTRFLT		| \76	DPI_REQQ_INT_RDFLT		| \77	DPI_REQQ_INT_WRFLT		| \78	DPI_REQQ_INT_CSFLT		| \79	DPI_REQQ_INT_INST_DBO		| \80	DPI_REQQ_INT_INST_ADDR_NULL	| \81	DPI_REQQ_INT_INST_FILL_INVAL	| \82	DPI_REQQ_INT_INSTR_PSN)83 84#define DPI_PF_RAS_EBI_DAT_PSN	BIT_ULL(0)85#define DPI_PF_RAS_NCB_DAT_PSN	BIT_ULL(1)86#define DPI_PF_RAS_NCB_CMD_PSN	BIT_ULL(2)87 88#define DPI_PF_RAS_INT \89	(DPI_PF_RAS_EBI_DAT_PSN  | \90	 DPI_PF_RAS_NCB_DAT_PSN  | \91	 DPI_PF_RAS_NCB_CMD_PSN)92 93/* Message fields in word_l of DPI mailbox structure */94#define DPI_MBOX_VFID(msg)		FIELD_GET(GENMASK_ULL(7, 0), msg)95#define DPI_MBOX_CMD(msg)		FIELD_GET(GENMASK_ULL(11, 8), msg)96#define DPI_MBOX_CBUF_SIZE(msg)		FIELD_GET(GENMASK_ULL(27, 12), msg)97#define DPI_MBOX_CBUF_AURA(msg)		FIELD_GET(GENMASK_ULL(47, 28), msg)98#define DPI_MBOX_SSO_PFFUNC(msg)	FIELD_GET(GENMASK_ULL(63, 48), msg)99 100/* Message fields in word_h of DPI mailbox structure */101#define DPI_MBOX_NPA_PFFUNC(msg)	FIELD_GET(GENMASK_ULL(15, 0), msg)102#define DPI_MBOX_WQES_COMPL(msg)	FIELD_GET(GENMASK_ULL(16, 16), msg)103#define DPI_MBOX_WQES_OFFSET(msg)	FIELD_GET(GENMASK_ULL(23, 17), msg)104 105#define DPI_DMAX_IBUFF_CSIZE(x)	(0x0ULL | ((x) << 11))106#define DPI_DMAX_IDS(x)		(0x18ULL | ((x) << 11))107#define DPI_DMAX_IDS2(x)	(0x20ULL | ((x) << 11))108#define DPI_DMAX_QRST(x)	(0x30ULL | ((x) << 11))109 110#define DPI_CTL				0x10010ULL111#define DPI_DMA_CONTROL			0x10018ULL112#define DPI_PF_RAS			0x10308ULL113#define DPI_PF_RAS_ENA_W1C		0x10318ULL114#define DPI_MBOX_VF_PF_INT		0x16300ULL115#define DPI_MBOX_VF_PF_INT_W1S		0x16308ULL116#define DPI_MBOX_VF_PF_INT_ENA_W1C	0x16310ULL117#define DPI_MBOX_VF_PF_INT_ENA_W1S	0x16318ULL118 119#define DPI_DMA_ENGX_EN(x)		(0x10040ULL | ((x) << 3))120#define DPI_ENGX_BUF(x)			(0x100C0ULL | ((x) << 3))121#define DPI_EBUS_PORTX_CFG(x)		(0x10100ULL | ((x) << 3))122#define DPI_DMA_CCX_INT(x)		(0x11000ULL | ((x) << 3))123#define DPI_DMA_CCX_INT_ENA_W1C(x)	(0x11800ULL | ((x) << 3))124#define DPI_REQQX_INT(x)		(0x12C00ULL | ((x) << 5))125#define DPI_REQQX_INT_ENA_W1C(x)	(0x13800ULL | ((x) << 5))126#define DPI_MBOX_PF_VF_DATA0(x)		(0x16000ULL | ((x) << 4))127#define DPI_MBOX_PF_VF_DATA1(x)		(0x16008ULL | ((x) << 4))128 129#define DPI_WCTL_FIF_THR	0x17008ULL130 131#define DPI_EBUS_MAX_PORTS	2132 133#define DPI_EBUS_MRRS_MIN	128134#define DPI_EBUS_MRRS_MAX	1024135#define DPI_EBUS_MPS_MIN	128136#define DPI_EBUS_MPS_MAX	1024137#define DPI_WCTL_FIFO_THRESHOLD	0x30138 139#define DPI_QUEUE_OPEN		0x1140#define DPI_QUEUE_CLOSE		0x2141#define DPI_REG_DUMP		0x3142#define DPI_GET_REG_CFG		0x4143#define DPI_QUEUE_OPEN_V2	0x5144 145enum dpi_mbox_rsp_type {146	DPI_MBOX_TYPE_CMD,147	DPI_MBOX_TYPE_RSP_ACK,148	DPI_MBOX_TYPE_RSP_NACK,149};150 151struct dpivf_config {152	u32 aura;153	u16 csize;154	u16 sso_pf_func;155	u16 npa_pf_func;156};157 158struct dpipf_vf {159	struct dpivf_config vf_config;160	bool setup_done;161	u8 this_vfid;162};163 164/* DPI device mailbox */165struct dpi_mbox {166	struct work_struct work;167	/* lock to serialize mbox requests */168	struct mutex lock;169	struct dpipf *pf;170	u8 __iomem *pf_vf_data_reg;171	u8 __iomem *vf_pf_data_reg;172};173 174struct dpipf {175	struct miscdevice miscdev;176	void __iomem *reg_base;177	struct pci_dev *pdev;178	struct dpipf_vf vf[DPI_MAX_VFS];179	/* Mailbox to talk to VFs */180	struct dpi_mbox *mbox[DPI_MAX_VFS];181};182 183struct dpi_mbox_message {184	uint64_t word_l;185	uint64_t word_h;186};187 188static inline void dpi_reg_write(struct dpipf *dpi, u64 offset, u64 val)189{190	writeq(val, dpi->reg_base + offset);191}192 193static inline u64 dpi_reg_read(struct dpipf *dpi, u64 offset)194{195	return readq(dpi->reg_base + offset);196}197 198static void dpi_wqe_cs_offset(struct dpipf *dpi, u8 offset)199{200	u64 reg;201 202	reg = dpi_reg_read(dpi, DPI_DMA_CONTROL);203	reg &= ~DPI_DMA_CONTROL_WQECSDIS;204	reg |= DPI_DMA_CONTROL_ZBWCSEN | DPI_DMA_CONTROL_WQECSMODE1;205	reg |= DPI_DMA_CONTROL_WQECSOFF(offset);206	dpi_reg_write(dpi, DPI_DMA_CONTROL, reg);207}208 209static int dpi_queue_init(struct dpipf *dpi, struct dpipf_vf *dpivf, u8 vf)210{211	u16 sso_pf_func = dpivf->vf_config.sso_pf_func;212	u16 npa_pf_func = dpivf->vf_config.npa_pf_func;213	u16 csize = dpivf->vf_config.csize;214	u32 aura = dpivf->vf_config.aura;215	unsigned long timeout;216	u64 reg;217 218	dpi_reg_write(dpi, DPI_DMAX_QRST(vf), DPI_DMA_QRST);219 220	/* Wait for a maximum of 3 sec */221	timeout = jiffies + msecs_to_jiffies(3000);222	while (!time_after(jiffies, timeout)) {223		reg = dpi_reg_read(dpi, DPI_DMAX_QRST(vf));224		if (!(reg & DPI_DMA_QRST))225			break;226 227		/* Reset would take time for the request cache to drain */228		usleep_range(500, 1000);229	}230 231	if (reg & DPI_DMA_QRST) {232		dev_err(&dpi->pdev->dev, "Queue reset failed\n");233		return -EBUSY;234	}235 236	dpi_reg_write(dpi, DPI_DMAX_IDS2(vf), 0);237	dpi_reg_write(dpi, DPI_DMAX_IDS(vf), 0);238 239	reg = DPI_DMA_IBUFF_CSIZE_CSIZE(csize) | DPI_DMA_IBUFF_CSIZE_NPA_FREE;240	dpi_reg_write(dpi, DPI_DMAX_IBUFF_CSIZE(vf), reg);241 242	reg = dpi_reg_read(dpi, DPI_DMAX_IDS2(vf));243	reg |= DPI_DMA_IDS2_INST_AURA(aura);244	dpi_reg_write(dpi, DPI_DMAX_IDS2(vf), reg);245 246	reg = dpi_reg_read(dpi, DPI_DMAX_IDS(vf));247	reg |= DPI_DMA_IDS_DMA_NPA_PF_FUNC(npa_pf_func);248	reg |= DPI_DMA_IDS_DMA_SSO_PF_FUNC(sso_pf_func);249	reg |= DPI_DMA_IDS_DMA_STRM(vf + 1);250	reg |= DPI_DMA_IDS_INST_STRM(vf + 1);251	dpi_reg_write(dpi, DPI_DMAX_IDS(vf), reg);252 253	return 0;254}255 256static void dpi_queue_fini(struct dpipf *dpi, u8 vf)257{258	dpi_reg_write(dpi, DPI_DMAX_QRST(vf), DPI_DMA_QRST);259 260	/* Reset IDS and IDS2 registers */261	dpi_reg_write(dpi, DPI_DMAX_IDS2(vf), 0);262	dpi_reg_write(dpi, DPI_DMAX_IDS(vf), 0);263}264 265static irqreturn_t dpi_mbox_intr_handler(int irq, void *data)266{267	struct dpipf *dpi = data;268	u64 reg;269	u32 vf;270 271	reg = dpi_reg_read(dpi, DPI_MBOX_VF_PF_INT);272	if (reg) {273		for (vf = 0; vf < pci_num_vf(dpi->pdev); vf++) {274			if (reg & BIT_ULL(vf))275				schedule_work(&dpi->mbox[vf]->work);276		}277		dpi_reg_write(dpi, DPI_MBOX_VF_PF_INT, reg);278	}279 280	return IRQ_HANDLED;281}282 283static int queue_config(struct dpipf *dpi, struct dpipf_vf *dpivf, struct dpi_mbox_message *msg)284{285	int ret = 0;286 287	switch (DPI_MBOX_CMD(msg->word_l)) {288	case DPI_QUEUE_OPEN:289	case DPI_QUEUE_OPEN_V2:290		dpivf->vf_config.aura = DPI_MBOX_CBUF_AURA(msg->word_l);291		dpivf->vf_config.csize = DPI_MBOX_CMD(msg->word_l) == DPI_QUEUE_OPEN ?292					 DPI_MBOX_CBUF_SIZE(msg->word_l) >> 3 :293					 DPI_MBOX_CBUF_SIZE(msg->word_l);294		dpivf->vf_config.sso_pf_func = DPI_MBOX_SSO_PFFUNC(msg->word_l);295		dpivf->vf_config.npa_pf_func = DPI_MBOX_NPA_PFFUNC(msg->word_h);296		ret = dpi_queue_init(dpi, dpivf, DPI_MBOX_VFID(msg->word_l));297		if (!ret) {298			if (DPI_MBOX_WQES_COMPL(msg->word_h))299				dpi_wqe_cs_offset(dpi, DPI_MBOX_WQES_OFFSET(msg->word_h));300			dpivf->setup_done = true;301		}302		break;303	case DPI_QUEUE_CLOSE:304		memset(&dpivf->vf_config, 0, sizeof(struct dpivf_config));305		dpi_queue_fini(dpi, DPI_MBOX_VFID(msg->word_l));306		dpivf->setup_done = false;307		break;308	default:309		return -EINVAL;310	}311 312	return ret;313}314 315static void dpi_pfvf_mbox_work(struct work_struct *work)316{317	struct dpi_mbox *mbox = container_of(work, struct dpi_mbox, work);318	struct dpi_mbox_message msg;319	struct dpipf_vf *dpivf;320	struct dpipf *dpi;321	int vfid, ret;322 323	dpi = mbox->pf;324	memset(&msg, 0, sizeof(msg));325 326	mutex_lock(&mbox->lock);327	msg.word_l = readq(mbox->vf_pf_data_reg);328	if (msg.word_l == (u64)-1)329		goto exit;330 331	vfid = DPI_MBOX_VFID(msg.word_l);332	if (vfid >= pci_num_vf(dpi->pdev))333		goto exit;334 335	dpivf = &dpi->vf[vfid];336	msg.word_h = readq(mbox->pf_vf_data_reg);337 338	ret = queue_config(dpi, dpivf, &msg);339	if (ret < 0)340		writeq(DPI_MBOX_TYPE_RSP_NACK, mbox->pf_vf_data_reg);341	else342		writeq(DPI_MBOX_TYPE_RSP_ACK, mbox->pf_vf_data_reg);343exit:344	mutex_unlock(&mbox->lock);345}346 347/* Setup registers for a PF mailbox */348static void dpi_setup_mbox_regs(struct dpipf *dpi, int vf)349{350	struct dpi_mbox *mbox = dpi->mbox[vf];351 352	mbox->pf_vf_data_reg = dpi->reg_base + DPI_MBOX_PF_VF_DATA0(vf);353	mbox->vf_pf_data_reg = dpi->reg_base + DPI_MBOX_PF_VF_DATA1(vf);354}355 356static int dpi_pfvf_mbox_setup(struct dpipf *dpi)357{358	int vf;359 360	for (vf = 0; vf < DPI_MAX_VFS; vf++) {361		dpi->mbox[vf] = devm_kzalloc(&dpi->pdev->dev, sizeof(*dpi->mbox[vf]), GFP_KERNEL);362 363		if (!dpi->mbox[vf])364			return -ENOMEM;365 366		mutex_init(&dpi->mbox[vf]->lock);367		INIT_WORK(&dpi->mbox[vf]->work, dpi_pfvf_mbox_work);368		dpi->mbox[vf]->pf = dpi;369		dpi_setup_mbox_regs(dpi, vf);370	}371 372	return 0;373}374 375static void dpi_pfvf_mbox_destroy(struct dpipf *dpi)376{377	unsigned int vf;378 379	for (vf = 0; vf < DPI_MAX_VFS; vf++) {380		if (work_pending(&dpi->mbox[vf]->work))381			cancel_work_sync(&dpi->mbox[vf]->work);382 383		dpi->mbox[vf] = NULL;384	}385}386 387static void dpi_init(struct dpipf *dpi)388{389	unsigned int engine, port;390	u8 mrrs_val, mps_val;391	u64 reg;392 393	for (engine = 0; engine < DPI_MAX_ENGINES; engine++) {394		if (engine == 4 || engine == 5)395			reg = DPI_ENG_BUF_BLKS(16);396		else397			reg = DPI_ENG_BUF_BLKS(8);398 399		dpi_reg_write(dpi, DPI_ENGX_BUF(engine), reg);400	}401 402	reg = DPI_DMA_CONTROL_ZBWCSEN | DPI_DMA_CONTROL_PKT_EN | DPI_DMA_CONTROL_LDWB |403	      DPI_DMA_CONTROL_O_MODE | DPI_DMA_CONTROL_DMA_ENB;404 405	dpi_reg_write(dpi, DPI_DMA_CONTROL, reg);406	dpi_reg_write(dpi, DPI_CTL, DPI_CTL_EN);407 408	mrrs_val = 2; /* 512B */409	mps_val = 1; /* 256B */410 411	for (port = 0; port < DPI_EBUS_MAX_PORTS; port++) {412		reg = dpi_reg_read(dpi, DPI_EBUS_PORTX_CFG(port));413		reg &= ~(DPI_EBUS_PORTX_CFG_MRRS(7) | DPI_EBUS_PORTX_CFG_MPS(7));414		reg |= DPI_EBUS_PORTX_CFG_MPS(mps_val) | DPI_EBUS_PORTX_CFG_MRRS(mrrs_val);415		dpi_reg_write(dpi, DPI_EBUS_PORTX_CFG(port), reg);416	}417 418	dpi_reg_write(dpi, DPI_WCTL_FIF_THR, DPI_WCTL_FIFO_THRESHOLD);419}420 421static void dpi_fini(struct dpipf *dpi)422{423	unsigned int engine;424 425	for (engine = 0; engine < DPI_MAX_ENGINES; engine++)426		dpi_reg_write(dpi, DPI_ENGX_BUF(engine), 0);427 428	dpi_reg_write(dpi, DPI_DMA_CONTROL, 0);429	dpi_reg_write(dpi, DPI_CTL, 0);430}431 432static void dpi_free_irq_vectors(void *pdev)433{434	pci_free_irq_vectors((struct pci_dev *)pdev);435}436 437static int dpi_irq_init(struct dpipf *dpi)438{439	struct pci_dev *pdev = dpi->pdev;440	struct device *dev = &pdev->dev;441	int i, ret;442 443	/* Clear all RAS interrupts */444	dpi_reg_write(dpi, DPI_PF_RAS, DPI_PF_RAS_INT);445 446	/* Clear all RAS interrupt enable bits */447	dpi_reg_write(dpi, DPI_PF_RAS_ENA_W1C, DPI_PF_RAS_INT);448 449	for (i = 0; i < DPI_MAX_REQQ_INT; i++) {450		dpi_reg_write(dpi, DPI_REQQX_INT(i), DPI_REQQ_INT);451		dpi_reg_write(dpi, DPI_REQQX_INT_ENA_W1C(i), DPI_REQQ_INT);452	}453 454	for (i = 0; i < DPI_MAX_CC_INT; i++) {455		dpi_reg_write(dpi, DPI_DMA_CCX_INT(i), DPI_DMA_CC_INT);456		dpi_reg_write(dpi, DPI_DMA_CCX_INT_ENA_W1C(i), DPI_DMA_CC_INT);457	}458 459	ret = pci_alloc_irq_vectors(pdev, DPI_MAX_IRQS, DPI_MAX_IRQS, PCI_IRQ_MSIX);460	if (ret != DPI_MAX_IRQS) {461		dev_err(dev, "DPI: Failed to alloc %d msix irqs\n", DPI_MAX_IRQS);462		return ret;463	}464 465	ret = devm_add_action_or_reset(dev, dpi_free_irq_vectors, pdev);466	if (ret) {467		dev_err(dev, "DPI: Failed to add irq free action\n");468		return ret;469	}470 471	ret = devm_request_irq(dev, pci_irq_vector(pdev, DPI_MBOX_PF_VF_INT_IDX),472			       dpi_mbox_intr_handler, 0, "dpi-mbox", dpi);473	if (ret) {474		dev_err(dev, "DPI: request_irq failed for mbox; err=%d\n", ret);475		return ret;476	}477 478	dpi_reg_write(dpi, DPI_MBOX_VF_PF_INT_ENA_W1S, GENMASK_ULL(31, 0));479 480	return 0;481}482 483static int dpi_mps_mrrs_config(struct dpipf *dpi, void __user *arg)484{485	struct dpi_mps_mrrs_cfg cfg;486	u8 mrrs_val, mps_val;487	u64 reg;488 489	if (copy_from_user(&cfg, arg, sizeof(struct dpi_mps_mrrs_cfg)))490		return -EFAULT;491 492	if (cfg.max_read_req_sz < DPI_EBUS_MRRS_MIN || cfg.max_read_req_sz > DPI_EBUS_MRRS_MAX ||493	    !is_power_of_2(cfg.max_read_req_sz))494		return -EINVAL;495 496	if (cfg.max_payload_sz < DPI_EBUS_MPS_MIN || cfg.max_payload_sz > DPI_EBUS_MPS_MAX ||497	    !is_power_of_2(cfg.max_payload_sz))498		return -EINVAL;499 500	if (cfg.port >= DPI_EBUS_MAX_PORTS)501		return -EINVAL;502 503	 /* Make sure reserved fields are set to 0 */504	if (cfg.reserved)505		return -EINVAL;506 507	mrrs_val = fls(cfg.max_read_req_sz >> 8);508	mps_val = fls(cfg.max_payload_sz >> 8);509 510	reg = dpi_reg_read(dpi, DPI_EBUS_PORTX_CFG(cfg.port));511	reg &= ~(DPI_EBUS_PORTX_CFG_MRRS(0x7) | DPI_EBUS_PORTX_CFG_MPS(0x7));512	reg |= DPI_EBUS_PORTX_CFG_MPS(mps_val) | DPI_EBUS_PORTX_CFG_MRRS(mrrs_val);513	dpi_reg_write(dpi, DPI_EBUS_PORTX_CFG(cfg.port), reg);514 515	return 0;516}517 518static int dpi_engine_config(struct dpipf *dpi, void __user *arg)519{520	struct dpi_engine_cfg cfg;521	unsigned int engine;522	u8 *eng_buf;523	u64 reg;524 525	if (copy_from_user(&cfg, arg, sizeof(struct dpi_engine_cfg)))526		return -EFAULT;527 528	 /* Make sure reserved fields are set to 0 */529	if (cfg.reserved)530		return -EINVAL;531 532	eng_buf = (u8 *)&cfg.fifo_mask;533 534	for (engine = 0; engine < DPI_MAX_ENGINES; engine++) {535		if (eng_buf[engine] > DPI_MAX_ENG_FIFO_SZ)536			return -EINVAL;537		dpi_reg_write(dpi, DPI_ENGX_BUF(engine), eng_buf[engine]);538 539		if (cfg.update_molr) {540			if (cfg.molr[engine] > DPI_MAX_ENG_MOLR)541				return -EINVAL;542			reg = DPI_DMA_ENG_EN_MOLR(cfg.molr[engine]);543			dpi_reg_write(dpi, DPI_DMA_ENGX_EN(engine), reg);544		} else {545			/* Make sure unused fields are set to 0 */546			if (cfg.molr[engine])547				return -EINVAL;548		}549	}550 551	return 0;552}553 554static long dpi_dev_ioctl(struct file *fptr, unsigned int cmd, unsigned long data)555{556	void __user *arg = (void __user *)data;557	struct dpipf *dpi;558	int ret;559 560	dpi = container_of(fptr->private_data, struct dpipf, miscdev);561 562	switch (cmd) {563	case DPI_MPS_MRRS_CFG:564		ret = dpi_mps_mrrs_config(dpi, arg);565		break;566	case DPI_ENGINE_CFG:567		ret = dpi_engine_config(dpi, arg);568		break;569	default:570		ret = -ENOTTY;571		break;572	}573 574	return ret;575}576 577static const struct file_operations dpi_device_fops = {578	.owner = THIS_MODULE,579	.unlocked_ioctl = dpi_dev_ioctl,580	.compat_ioctl = compat_ptr_ioctl,581};582 583static int dpi_probe(struct pci_dev *pdev, const struct pci_device_id *id)584{585	struct device *dev = &pdev->dev;586	struct dpipf *dpi;587	int ret;588 589	dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL);590	if (!dpi)591		return -ENOMEM;592 593	dpi->pdev = pdev;594 595	ret = pcim_enable_device(pdev);596	if (ret) {597		dev_err(dev, "DPI: Failed to enable PCI device\n");598		return ret;599	}600 601	ret = pcim_iomap_regions(pdev, BIT(0) | BIT(4), KBUILD_MODNAME);602	if (ret) {603		dev_err(dev, "DPI: Failed to request MMIO region\n");604		return ret;605	}606 607	dpi->reg_base = pcim_iomap_table(pdev)[PCI_DPI_CFG_BAR];608 609	/* Initialize global PF registers */610	dpi_init(dpi);611 612	/* Setup PF-VF mailbox */613	ret = dpi_pfvf_mbox_setup(dpi);614	if (ret) {615		dev_err(dev, "DPI: Failed to setup pf-vf mbox\n");616		goto err_dpi_fini;617	}618 619	/* Register interrupts */620	ret = dpi_irq_init(dpi);621	if (ret) {622		dev_err(dev, "DPI: Failed to initialize irq vectors\n");623		goto err_dpi_mbox_free;624	}625 626	pci_set_drvdata(pdev, dpi);627	dpi->miscdev.minor = MISC_DYNAMIC_MINOR;628	dpi->miscdev.name = KBUILD_MODNAME;629	dpi->miscdev.fops = &dpi_device_fops;630	dpi->miscdev.parent = dev;631 632	ret = misc_register(&dpi->miscdev);633	if (ret) {634		dev_err(dev, "DPI: Failed to register misc device\n");635		goto err_dpi_mbox_free;636	}637 638	return 0;639 640err_dpi_mbox_free:641	dpi_pfvf_mbox_destroy(dpi);642err_dpi_fini:643	dpi_fini(dpi);644	return ret;645}646 647static void dpi_remove(struct pci_dev *pdev)648{649	struct dpipf *dpi = pci_get_drvdata(pdev);650 651	misc_deregister(&dpi->miscdev);652	pci_sriov_configure_simple(pdev, 0);653	dpi_pfvf_mbox_destroy(dpi);654	dpi_fini(dpi);655	pci_set_drvdata(pdev, NULL);656}657 658static const struct pci_device_id dpi_id_table[] = {659	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_MRVL_CN10K_DPI_PF,660			 PCI_VENDOR_ID_CAVIUM, PCI_SUBDEVID_MRVL_CN10K_DPI_PF) },661	{ 0, }  /* end of table */662};663 664static struct pci_driver dpi_driver = {665	.name = KBUILD_MODNAME,666	.id_table = dpi_id_table,667	.probe = dpi_probe,668	.remove = dpi_remove,669	.sriov_configure = pci_sriov_configure_simple,670};671 672module_pci_driver(dpi_driver);673MODULE_DEVICE_TABLE(pci, dpi_id_table);674MODULE_AUTHOR("Marvell.");675MODULE_DESCRIPTION("Marvell Octeon CN10K DPI Driver");676MODULE_LICENSE("GPL");677