Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
0002 
0003 /* Interrupt related logic for Mellanox Gigabit Ethernet driver
0004  *
0005  * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES
0006  */
0007 
0008 #include <linux/interrupt.h>
0009 
0010 #include "mlxbf_gige.h"
0011 #include "mlxbf_gige_regs.h"
0012 
0013 static irqreturn_t mlxbf_gige_error_intr(int irq, void *dev_id)
0014 {
0015     struct mlxbf_gige *priv;
0016     u64 int_status;
0017 
0018     priv = dev_id;
0019 
0020     int_status = readq(priv->base + MLXBF_GIGE_INT_STATUS);
0021 
0022     if (int_status & MLXBF_GIGE_INT_STATUS_HW_ACCESS_ERROR)
0023         priv->stats.hw_access_errors++;
0024 
0025     if (int_status & MLXBF_GIGE_INT_STATUS_TX_CHECKSUM_INPUTS) {
0026         priv->stats.tx_invalid_checksums++;
0027         /* This error condition is latched into MLXBF_GIGE_INT_STATUS
0028          * when the GigE silicon operates on the offending
0029          * TX WQE. The write to MLXBF_GIGE_INT_STATUS at the bottom
0030          * of this routine clears this error condition.
0031          */
0032     }
0033 
0034     if (int_status & MLXBF_GIGE_INT_STATUS_TX_SMALL_FRAME_SIZE) {
0035         priv->stats.tx_small_frames++;
0036         /* This condition happens when the networking stack invokes
0037          * this driver's "start_xmit()" method with a packet whose
0038          * size < 60 bytes.  The GigE silicon will automatically pad
0039          * this small frame up to a minimum-sized frame before it is
0040          * sent. The "tx_small_frame" condition is latched into the
0041          * MLXBF_GIGE_INT_STATUS register when the GigE silicon
0042          * operates on the offending TX WQE. The write to
0043          * MLXBF_GIGE_INT_STATUS at the bottom of this routine
0044          * clears this condition.
0045          */
0046     }
0047 
0048     if (int_status & MLXBF_GIGE_INT_STATUS_TX_PI_CI_EXCEED_WQ_SIZE)
0049         priv->stats.tx_index_errors++;
0050 
0051     if (int_status & MLXBF_GIGE_INT_STATUS_SW_CONFIG_ERROR)
0052         priv->stats.sw_config_errors++;
0053 
0054     if (int_status & MLXBF_GIGE_INT_STATUS_SW_ACCESS_ERROR)
0055         priv->stats.sw_access_errors++;
0056 
0057     /* Clear all error interrupts by writing '1' back to
0058      * all the asserted bits in INT_STATUS.  Do not write
0059      * '1' back to 'receive packet' bit, since that is
0060      * managed separately.
0061      */
0062 
0063     int_status &= ~MLXBF_GIGE_INT_STATUS_RX_RECEIVE_PACKET;
0064 
0065     writeq(int_status, priv->base + MLXBF_GIGE_INT_STATUS);
0066 
0067     return IRQ_HANDLED;
0068 }
0069 
0070 static irqreturn_t mlxbf_gige_rx_intr(int irq, void *dev_id)
0071 {
0072     struct mlxbf_gige *priv;
0073 
0074     priv = dev_id;
0075 
0076     /* NOTE: GigE silicon automatically disables "packet rx" interrupt by
0077      *       setting MLXBF_GIGE_INT_MASK bit0 upon triggering the interrupt
0078      *       to the ARM cores.  Software needs to re-enable "packet rx"
0079      *       interrupts by clearing MLXBF_GIGE_INT_MASK bit0.
0080      */
0081 
0082     napi_schedule(&priv->napi);
0083 
0084     return IRQ_HANDLED;
0085 }
0086 
0087 static irqreturn_t mlxbf_gige_llu_plu_intr(int irq, void *dev_id)
0088 {
0089     return IRQ_HANDLED;
0090 }
0091 
0092 int mlxbf_gige_request_irqs(struct mlxbf_gige *priv)
0093 {
0094     int err;
0095 
0096     err = request_irq(priv->error_irq, mlxbf_gige_error_intr, 0,
0097               "mlxbf_gige_error", priv);
0098     if (err) {
0099         dev_err(priv->dev, "Request error_irq failure\n");
0100         return err;
0101     }
0102 
0103     err = request_irq(priv->rx_irq, mlxbf_gige_rx_intr, 0,
0104               "mlxbf_gige_rx", priv);
0105     if (err) {
0106         dev_err(priv->dev, "Request rx_irq failure\n");
0107         goto free_error_irq;
0108     }
0109 
0110     err = request_irq(priv->llu_plu_irq, mlxbf_gige_llu_plu_intr, 0,
0111               "mlxbf_gige_llu_plu", priv);
0112     if (err) {
0113         dev_err(priv->dev, "Request llu_plu_irq failure\n");
0114         goto free_rx_irq;
0115     }
0116 
0117     return 0;
0118 
0119 free_rx_irq:
0120     free_irq(priv->rx_irq, priv);
0121 
0122 free_error_irq:
0123     free_irq(priv->error_irq, priv);
0124 
0125     return err;
0126 }
0127 
0128 void mlxbf_gige_free_irqs(struct mlxbf_gige *priv)
0129 {
0130     free_irq(priv->error_irq, priv);
0131     free_irq(priv->rx_irq, priv);
0132     free_irq(priv->llu_plu_irq, priv);
0133 }