brintos

brintos / linux-shallow public Read only

0
0
Text · 3.5 KiB · 5b3519f Raw
134 lines · c
1// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause2 3/* Interrupt related logic for Mellanox Gigabit Ethernet driver4 *5 * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES6 */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_STATUS28		 * when the GigE silicon operates on the offending29		 * TX WQE. The write to MLXBF_GIGE_INT_STATUS at the bottom30		 * 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 invokes37		 * this driver's "start_xmit()" method with a packet whose38		 * size < 60 bytes.  The GigE silicon will automatically pad39		 * this small frame up to a minimum-sized frame before it is40		 * sent. The "tx_small_frame" condition is latched into the41		 * MLXBF_GIGE_INT_STATUS register when the GigE silicon42		 * operates on the offending TX WQE. The write to43		 * MLXBF_GIGE_INT_STATUS at the bottom of this routine44		 * 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 to58	 * all the asserted bits in INT_STATUS.  Do not write59	 * '1' back to 'receive packet' bit, since that is60	 * 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 by77	 *       setting MLXBF_GIGE_INT_MASK bit0 upon triggering the interrupt78	 *       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}134