cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nitrox_isr.c (11373B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/pci.h>
      3#include <linux/printk.h>
      4#include <linux/slab.h>
      5
      6#include "nitrox_dev.h"
      7#include "nitrox_csr.h"
      8#include "nitrox_common.h"
      9#include "nitrox_hal.h"
     10#include "nitrox_isr.h"
     11#include "nitrox_mbx.h"
     12
     13/*
     14 * One vector for each type of ring
     15 *  - NPS packet ring, AQMQ ring and ZQMQ ring
     16 */
     17#define NR_RING_VECTORS 3
     18#define NR_NON_RING_VECTORS 1
     19/* base entry for packet ring/port */
     20#define PKT_RING_MSIX_BASE 0
     21#define NON_RING_MSIX_BASE 192
     22
     23/**
     24 * nps_pkt_slc_isr - IRQ handler for NPS solicit port
     25 * @irq: irq number
     26 * @data: argument
     27 */
     28static irqreturn_t nps_pkt_slc_isr(int irq, void *data)
     29{
     30	struct nitrox_q_vector *qvec = data;
     31	union nps_pkt_slc_cnts slc_cnts;
     32	struct nitrox_cmdq *cmdq = qvec->cmdq;
     33
     34	slc_cnts.value = readq(cmdq->compl_cnt_csr_addr);
     35	/* New packet on SLC output port */
     36	if (slc_cnts.s.slc_int)
     37		tasklet_hi_schedule(&qvec->resp_tasklet);
     38
     39	return IRQ_HANDLED;
     40}
     41
     42static void clear_nps_core_err_intr(struct nitrox_device *ndev)
     43{
     44	u64 value;
     45
     46	/* Write 1 to clear */
     47	value = nitrox_read_csr(ndev, NPS_CORE_INT);
     48	nitrox_write_csr(ndev, NPS_CORE_INT, value);
     49
     50	dev_err_ratelimited(DEV(ndev), "NSP_CORE_INT  0x%016llx\n", value);
     51}
     52
     53static void clear_nps_pkt_err_intr(struct nitrox_device *ndev)
     54{
     55	union nps_pkt_int pkt_int;
     56	unsigned long value, offset;
     57	int i;
     58
     59	pkt_int.value = nitrox_read_csr(ndev, NPS_PKT_INT);
     60	dev_err_ratelimited(DEV(ndev), "NPS_PKT_INT  0x%016llx\n",
     61			    pkt_int.value);
     62
     63	if (pkt_int.s.slc_err) {
     64		offset = NPS_PKT_SLC_ERR_TYPE;
     65		value = nitrox_read_csr(ndev, offset);
     66		nitrox_write_csr(ndev, offset, value);
     67		dev_err_ratelimited(DEV(ndev),
     68				    "NPS_PKT_SLC_ERR_TYPE  0x%016lx\n", value);
     69
     70		offset = NPS_PKT_SLC_RERR_LO;
     71		value = nitrox_read_csr(ndev, offset);
     72		nitrox_write_csr(ndev, offset, value);
     73		/* enable the solicit ports */
     74		for_each_set_bit(i, &value, BITS_PER_LONG)
     75			enable_pkt_solicit_port(ndev, i);
     76
     77		dev_err_ratelimited(DEV(ndev),
     78				    "NPS_PKT_SLC_RERR_LO  0x%016lx\n", value);
     79
     80		offset = NPS_PKT_SLC_RERR_HI;
     81		value = nitrox_read_csr(ndev, offset);
     82		nitrox_write_csr(ndev, offset, value);
     83		dev_err_ratelimited(DEV(ndev),
     84				    "NPS_PKT_SLC_RERR_HI  0x%016lx\n", value);
     85	}
     86
     87	if (pkt_int.s.in_err) {
     88		offset = NPS_PKT_IN_ERR_TYPE;
     89		value = nitrox_read_csr(ndev, offset);
     90		nitrox_write_csr(ndev, offset, value);
     91		dev_err_ratelimited(DEV(ndev),
     92				    "NPS_PKT_IN_ERR_TYPE  0x%016lx\n", value);
     93		offset = NPS_PKT_IN_RERR_LO;
     94		value = nitrox_read_csr(ndev, offset);
     95		nitrox_write_csr(ndev, offset, value);
     96		/* enable the input ring */
     97		for_each_set_bit(i, &value, BITS_PER_LONG)
     98			enable_pkt_input_ring(ndev, i);
     99
    100		dev_err_ratelimited(DEV(ndev),
    101				    "NPS_PKT_IN_RERR_LO  0x%016lx\n", value);
    102
    103		offset = NPS_PKT_IN_RERR_HI;
    104		value = nitrox_read_csr(ndev, offset);
    105		nitrox_write_csr(ndev, offset, value);
    106		dev_err_ratelimited(DEV(ndev),
    107				    "NPS_PKT_IN_RERR_HI  0x%016lx\n", value);
    108	}
    109}
    110
    111static void clear_pom_err_intr(struct nitrox_device *ndev)
    112{
    113	u64 value;
    114
    115	value = nitrox_read_csr(ndev, POM_INT);
    116	nitrox_write_csr(ndev, POM_INT, value);
    117	dev_err_ratelimited(DEV(ndev), "POM_INT  0x%016llx\n", value);
    118}
    119
    120static void clear_pem_err_intr(struct nitrox_device *ndev)
    121{
    122	u64 value;
    123
    124	value = nitrox_read_csr(ndev, PEM0_INT);
    125	nitrox_write_csr(ndev, PEM0_INT, value);
    126	dev_err_ratelimited(DEV(ndev), "PEM(0)_INT  0x%016llx\n", value);
    127}
    128
    129static void clear_lbc_err_intr(struct nitrox_device *ndev)
    130{
    131	union lbc_int lbc_int;
    132	u64 value, offset;
    133	int i;
    134
    135	lbc_int.value = nitrox_read_csr(ndev, LBC_INT);
    136	dev_err_ratelimited(DEV(ndev), "LBC_INT  0x%016llx\n", lbc_int.value);
    137
    138	if (lbc_int.s.dma_rd_err) {
    139		for (i = 0; i < NR_CLUSTERS; i++) {
    140			offset = EFL_CORE_VF_ERR_INT0X(i);
    141			value = nitrox_read_csr(ndev, offset);
    142			nitrox_write_csr(ndev, offset, value);
    143			offset = EFL_CORE_VF_ERR_INT1X(i);
    144			value = nitrox_read_csr(ndev, offset);
    145			nitrox_write_csr(ndev, offset, value);
    146		}
    147	}
    148
    149	if (lbc_int.s.cam_soft_err) {
    150		dev_err_ratelimited(DEV(ndev), "CAM_SOFT_ERR, invalidating LBC\n");
    151		invalidate_lbc(ndev);
    152	}
    153
    154	if (lbc_int.s.pref_dat_len_mismatch_err) {
    155		offset = LBC_PLM_VF1_64_INT;
    156		value = nitrox_read_csr(ndev, offset);
    157		nitrox_write_csr(ndev, offset, value);
    158		offset = LBC_PLM_VF65_128_INT;
    159		value = nitrox_read_csr(ndev, offset);
    160		nitrox_write_csr(ndev, offset, value);
    161	}
    162
    163	if (lbc_int.s.rd_dat_len_mismatch_err) {
    164		offset = LBC_ELM_VF1_64_INT;
    165		value = nitrox_read_csr(ndev, offset);
    166		nitrox_write_csr(ndev, offset, value);
    167		offset = LBC_ELM_VF65_128_INT;
    168		value = nitrox_read_csr(ndev, offset);
    169		nitrox_write_csr(ndev, offset, value);
    170	}
    171	nitrox_write_csr(ndev, LBC_INT, lbc_int.value);
    172}
    173
    174static void clear_efl_err_intr(struct nitrox_device *ndev)
    175{
    176	int i;
    177
    178	for (i = 0; i < NR_CLUSTERS; i++) {
    179		union efl_core_int core_int;
    180		u64 value, offset;
    181
    182		offset = EFL_CORE_INTX(i);
    183		core_int.value = nitrox_read_csr(ndev, offset);
    184		nitrox_write_csr(ndev, offset, core_int.value);
    185		dev_err_ratelimited(DEV(ndev), "ELF_CORE(%d)_INT  0x%016llx\n",
    186				    i, core_int.value);
    187		if (core_int.s.se_err) {
    188			offset = EFL_CORE_SE_ERR_INTX(i);
    189			value = nitrox_read_csr(ndev, offset);
    190			nitrox_write_csr(ndev, offset, value);
    191		}
    192	}
    193}
    194
    195static void clear_bmi_err_intr(struct nitrox_device *ndev)
    196{
    197	u64 value;
    198
    199	value = nitrox_read_csr(ndev, BMI_INT);
    200	nitrox_write_csr(ndev, BMI_INT, value);
    201	dev_err_ratelimited(DEV(ndev), "BMI_INT  0x%016llx\n", value);
    202}
    203
    204static void nps_core_int_tasklet(unsigned long data)
    205{
    206	struct nitrox_q_vector *qvec = (void *)(uintptr_t)(data);
    207	struct nitrox_device *ndev = qvec->ndev;
    208
    209	/* if pf mode do queue recovery */
    210	if (ndev->mode == __NDEV_MODE_PF) {
    211	} else {
    212		/**
    213		 * if VF(s) enabled communicate the error information
    214		 * to VF(s)
    215		 */
    216	}
    217}
    218
    219/*
    220 * nps_core_int_isr - interrupt handler for NITROX errors and
    221 *   mailbox communication
    222 */
    223static irqreturn_t nps_core_int_isr(int irq, void *data)
    224{
    225	struct nitrox_q_vector *qvec = data;
    226	struct nitrox_device *ndev = qvec->ndev;
    227	union nps_core_int_active core_int;
    228
    229	core_int.value = nitrox_read_csr(ndev, NPS_CORE_INT_ACTIVE);
    230
    231	if (core_int.s.nps_core)
    232		clear_nps_core_err_intr(ndev);
    233
    234	if (core_int.s.nps_pkt)
    235		clear_nps_pkt_err_intr(ndev);
    236
    237	if (core_int.s.pom)
    238		clear_pom_err_intr(ndev);
    239
    240	if (core_int.s.pem)
    241		clear_pem_err_intr(ndev);
    242
    243	if (core_int.s.lbc)
    244		clear_lbc_err_intr(ndev);
    245
    246	if (core_int.s.efl)
    247		clear_efl_err_intr(ndev);
    248
    249	if (core_int.s.bmi)
    250		clear_bmi_err_intr(ndev);
    251
    252	/* Mailbox interrupt */
    253	if (core_int.s.mbox)
    254		nitrox_pf2vf_mbox_handler(ndev);
    255
    256	/* If more work callback the ISR, set resend */
    257	core_int.s.resend = 1;
    258	nitrox_write_csr(ndev, NPS_CORE_INT_ACTIVE, core_int.value);
    259
    260	return IRQ_HANDLED;
    261}
    262
    263void nitrox_unregister_interrupts(struct nitrox_device *ndev)
    264{
    265	struct pci_dev *pdev = ndev->pdev;
    266	int i;
    267
    268	for (i = 0; i < ndev->num_vecs; i++) {
    269		struct nitrox_q_vector *qvec;
    270		int vec;
    271
    272		qvec = ndev->qvec + i;
    273		if (!qvec->valid)
    274			continue;
    275
    276		/* get the vector number */
    277		vec = pci_irq_vector(pdev, i);
    278		irq_set_affinity_hint(vec, NULL);
    279		free_irq(vec, qvec);
    280
    281		tasklet_disable(&qvec->resp_tasklet);
    282		tasklet_kill(&qvec->resp_tasklet);
    283		qvec->valid = false;
    284	}
    285	kfree(ndev->qvec);
    286	ndev->qvec = NULL;
    287	pci_free_irq_vectors(pdev);
    288}
    289
    290int nitrox_register_interrupts(struct nitrox_device *ndev)
    291{
    292	struct pci_dev *pdev = ndev->pdev;
    293	struct nitrox_q_vector *qvec;
    294	int nr_vecs, vec, cpu;
    295	int ret, i;
    296
    297	/*
    298	 * PF MSI-X vectors
    299	 *
    300	 * Entry 0: NPS PKT ring 0
    301	 * Entry 1: AQMQ ring 0
    302	 * Entry 2: ZQM ring 0
    303	 * Entry 3: NPS PKT ring 1
    304	 * Entry 4: AQMQ ring 1
    305	 * Entry 5: ZQM ring 1
    306	 * ....
    307	 * Entry 192: NPS_CORE_INT_ACTIVE
    308	 */
    309	nr_vecs = pci_msix_vec_count(pdev);
    310	if (nr_vecs < 0) {
    311		dev_err(DEV(ndev), "Error in getting vec count %d\n", nr_vecs);
    312		return nr_vecs;
    313	}
    314
    315	/* Enable MSI-X */
    316	ret = pci_alloc_irq_vectors(pdev, nr_vecs, nr_vecs, PCI_IRQ_MSIX);
    317	if (ret < 0) {
    318		dev_err(DEV(ndev), "msix vectors %d alloc failed\n", nr_vecs);
    319		return ret;
    320	}
    321	ndev->num_vecs = nr_vecs;
    322
    323	ndev->qvec = kcalloc(nr_vecs, sizeof(*qvec), GFP_KERNEL);
    324	if (!ndev->qvec) {
    325		pci_free_irq_vectors(pdev);
    326		return -ENOMEM;
    327	}
    328
    329	/* request irqs for packet rings/ports */
    330	for (i = PKT_RING_MSIX_BASE; i < (nr_vecs - 1); i += NR_RING_VECTORS) {
    331		qvec = &ndev->qvec[i];
    332
    333		qvec->ring = i / NR_RING_VECTORS;
    334		if (qvec->ring >= ndev->nr_queues)
    335			break;
    336
    337		qvec->cmdq = &ndev->pkt_inq[qvec->ring];
    338		snprintf(qvec->name, IRQ_NAMESZ, "nitrox-pkt%d", qvec->ring);
    339		/* get the vector number */
    340		vec = pci_irq_vector(pdev, i);
    341		ret = request_irq(vec, nps_pkt_slc_isr, 0, qvec->name, qvec);
    342		if (ret) {
    343			dev_err(DEV(ndev), "irq failed for pkt ring/port%d\n",
    344				qvec->ring);
    345			goto irq_fail;
    346		}
    347		cpu = qvec->ring % num_online_cpus();
    348		irq_set_affinity_hint(vec, get_cpu_mask(cpu));
    349
    350		tasklet_init(&qvec->resp_tasklet, pkt_slc_resp_tasklet,
    351			     (unsigned long)qvec);
    352		qvec->valid = true;
    353	}
    354
    355	/* request irqs for non ring vectors */
    356	i = NON_RING_MSIX_BASE;
    357	qvec = &ndev->qvec[i];
    358	qvec->ndev = ndev;
    359
    360	snprintf(qvec->name, IRQ_NAMESZ, "nitrox-core-int%d", i);
    361	/* get the vector number */
    362	vec = pci_irq_vector(pdev, i);
    363	ret = request_irq(vec, nps_core_int_isr, 0, qvec->name, qvec);
    364	if (ret) {
    365		dev_err(DEV(ndev), "irq failed for nitrox-core-int%d\n", i);
    366		goto irq_fail;
    367	}
    368	cpu = num_online_cpus();
    369	irq_set_affinity_hint(vec, get_cpu_mask(cpu));
    370
    371	tasklet_init(&qvec->resp_tasklet, nps_core_int_tasklet,
    372		     (unsigned long)qvec);
    373	qvec->valid = true;
    374
    375	return 0;
    376
    377irq_fail:
    378	nitrox_unregister_interrupts(ndev);
    379	return ret;
    380}
    381
    382void nitrox_sriov_unregister_interrupts(struct nitrox_device *ndev)
    383{
    384	struct pci_dev *pdev = ndev->pdev;
    385	int i;
    386
    387	for (i = 0; i < ndev->num_vecs; i++) {
    388		struct nitrox_q_vector *qvec;
    389		int vec;
    390
    391		qvec = ndev->qvec + i;
    392		if (!qvec->valid)
    393			continue;
    394
    395		vec = ndev->iov.msix.vector;
    396		irq_set_affinity_hint(vec, NULL);
    397		free_irq(vec, qvec);
    398
    399		tasklet_disable(&qvec->resp_tasklet);
    400		tasklet_kill(&qvec->resp_tasklet);
    401		qvec->valid = false;
    402	}
    403	kfree(ndev->qvec);
    404	ndev->qvec = NULL;
    405	pci_disable_msix(pdev);
    406}
    407
    408int nitrox_sriov_register_interupts(struct nitrox_device *ndev)
    409{
    410	struct pci_dev *pdev = ndev->pdev;
    411	struct nitrox_q_vector *qvec;
    412	int vec, cpu;
    413	int ret;
    414
    415	/**
    416	 * only non ring vectors i.e Entry 192 is available
    417	 * for PF in SR-IOV mode.
    418	 */
    419	ndev->iov.msix.entry = NON_RING_MSIX_BASE;
    420	ret = pci_enable_msix_exact(pdev, &ndev->iov.msix, NR_NON_RING_VECTORS);
    421	if (ret) {
    422		dev_err(DEV(ndev), "failed to allocate nps-core-int%d\n",
    423			NON_RING_MSIX_BASE);
    424		return ret;
    425	}
    426
    427	qvec = kcalloc(NR_NON_RING_VECTORS, sizeof(*qvec), GFP_KERNEL);
    428	if (!qvec) {
    429		pci_disable_msix(pdev);
    430		return -ENOMEM;
    431	}
    432	qvec->ndev = ndev;
    433
    434	ndev->qvec = qvec;
    435	ndev->num_vecs = NR_NON_RING_VECTORS;
    436	snprintf(qvec->name, IRQ_NAMESZ, "nitrox-core-int%d",
    437		 NON_RING_MSIX_BASE);
    438
    439	vec = ndev->iov.msix.vector;
    440	ret = request_irq(vec, nps_core_int_isr, 0, qvec->name, qvec);
    441	if (ret) {
    442		dev_err(DEV(ndev), "irq failed for nitrox-core-int%d\n",
    443			NON_RING_MSIX_BASE);
    444		goto iov_irq_fail;
    445	}
    446	cpu = num_online_cpus();
    447	irq_set_affinity_hint(vec, get_cpu_mask(cpu));
    448
    449	tasklet_init(&qvec->resp_tasklet, nps_core_int_tasklet,
    450		     (unsigned long)qvec);
    451	qvec->valid = true;
    452
    453	return 0;
    454
    455iov_irq_fail:
    456	nitrox_sriov_unregister_interrupts(ndev);
    457	return ret;
    458}