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

mlxbf_gige_intr.c (3534B)


      1// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
      2
      3/* Interrupt related logic for Mellanox Gigabit Ethernet driver
      4 *
      5 * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES
      6 */
      7
      8#include <linux/interrupt.h>
      9
     10#include "mlxbf_gige.h"
     11#include "mlxbf_gige_regs.h"
     12
     13static irqreturn_t mlxbf_gige_error_intr(int irq, void *dev_id)
     14{
     15	struct mlxbf_gige *priv;
     16	u64 int_status;
     17
     18	priv = dev_id;
     19
     20	int_status = readq(priv->base + MLXBF_GIGE_INT_STATUS);
     21
     22	if (int_status & MLXBF_GIGE_INT_STATUS_HW_ACCESS_ERROR)
     23		priv->stats.hw_access_errors++;
     24
     25	if (int_status & MLXBF_GIGE_INT_STATUS_TX_CHECKSUM_INPUTS) {
     26		priv->stats.tx_invalid_checksums++;
     27		/* This error condition is latched into MLXBF_GIGE_INT_STATUS
     28		 * when the GigE silicon operates on the offending
     29		 * TX WQE. The write to MLXBF_GIGE_INT_STATUS at the bottom
     30		 * of this routine clears this error condition.
     31		 */
     32	}
     33
     34	if (int_status & MLXBF_GIGE_INT_STATUS_TX_SMALL_FRAME_SIZE) {
     35		priv->stats.tx_small_frames++;
     36		/* This condition happens when the networking stack invokes
     37		 * this driver's "start_xmit()" method with a packet whose
     38		 * size < 60 bytes.  The GigE silicon will automatically pad
     39		 * this small frame up to a minimum-sized frame before it is
     40		 * sent. The "tx_small_frame" condition is latched into the
     41		 * MLXBF_GIGE_INT_STATUS register when the GigE silicon
     42		 * operates on the offending TX WQE. The write to
     43		 * MLXBF_GIGE_INT_STATUS at the bottom of this routine
     44		 * clears this condition.
     45		 */
     46	}
     47
     48	if (int_status & MLXBF_GIGE_INT_STATUS_TX_PI_CI_EXCEED_WQ_SIZE)
     49		priv->stats.tx_index_errors++;
     50
     51	if (int_status & MLXBF_GIGE_INT_STATUS_SW_CONFIG_ERROR)
     52		priv->stats.sw_config_errors++;
     53
     54	if (int_status & MLXBF_GIGE_INT_STATUS_SW_ACCESS_ERROR)
     55		priv->stats.sw_access_errors++;
     56
     57	/* Clear all error interrupts by writing '1' back to
     58	 * all the asserted bits in INT_STATUS.  Do not write
     59	 * '1' back to 'receive packet' bit, since that is
     60	 * managed separately.
     61	 */
     62
     63	int_status &= ~MLXBF_GIGE_INT_STATUS_RX_RECEIVE_PACKET;
     64
     65	writeq(int_status, priv->base + MLXBF_GIGE_INT_STATUS);
     66
     67	return IRQ_HANDLED;
     68}
     69
     70static irqreturn_t mlxbf_gige_rx_intr(int irq, void *dev_id)
     71{
     72	struct mlxbf_gige *priv;
     73
     74	priv = dev_id;
     75
     76	/* NOTE: GigE silicon automatically disables "packet rx" interrupt by
     77	 *       setting MLXBF_GIGE_INT_MASK bit0 upon triggering the interrupt
     78	 *       to the ARM cores.  Software needs to re-enable "packet rx"
     79	 *       interrupts by clearing MLXBF_GIGE_INT_MASK bit0.
     80	 */
     81
     82	napi_schedule(&priv->napi);
     83
     84	return IRQ_HANDLED;
     85}
     86
     87static irqreturn_t mlxbf_gige_llu_plu_intr(int irq, void *dev_id)
     88{
     89	return IRQ_HANDLED;
     90}
     91
     92int mlxbf_gige_request_irqs(struct mlxbf_gige *priv)
     93{
     94	int err;
     95
     96	err = request_irq(priv->error_irq, mlxbf_gige_error_intr, 0,
     97			  "mlxbf_gige_error", priv);
     98	if (err) {
     99		dev_err(priv->dev, "Request error_irq failure\n");
    100		return err;
    101	}
    102
    103	err = request_irq(priv->rx_irq, mlxbf_gige_rx_intr, 0,
    104			  "mlxbf_gige_rx", priv);
    105	if (err) {
    106		dev_err(priv->dev, "Request rx_irq failure\n");
    107		goto free_error_irq;
    108	}
    109
    110	err = request_irq(priv->llu_plu_irq, mlxbf_gige_llu_plu_intr, 0,
    111			  "mlxbf_gige_llu_plu", priv);
    112	if (err) {
    113		dev_err(priv->dev, "Request llu_plu_irq failure\n");
    114		goto free_rx_irq;
    115	}
    116
    117	return 0;
    118
    119free_rx_irq:
    120	free_irq(priv->rx_irq, priv);
    121
    122free_error_irq:
    123	free_irq(priv->error_irq, priv);
    124
    125	return err;
    126}
    127
    128void mlxbf_gige_free_irqs(struct mlxbf_gige *priv)
    129{
    130	free_irq(priv->error_irq, priv);
    131	free_irq(priv->rx_irq, priv);
    132	free_irq(priv->llu_plu_irq, priv);
    133}