FILE
hinic3_irq.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c
1// SPDX-License-Identifier: GPL-2.0 2// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. 3 4#include <linux/netdevice.h> 5 6#include "hinic3_hw_comm.h" 7#include "hinic3_hwdev.h" 8#include "hinic3_hwif.h" 9#include "hinic3_nic_dev.h" 10#include "hinic3_rx.h" 11#include "hinic3_tx.h" 12 13static int hinic3_poll(struct napi_struct *napi, int budget) 14{ 15 struct hinic3_irq_cfg *irq_cfg = 16 container_of(napi, struct hinic3_irq_cfg, napi); 17 struct hinic3_nic_dev *nic_dev; 18 bool busy = false; 19 int work_done; 20 21 nic_dev = netdev_priv(irq_cfg->netdev); 22 23 busy |= hinic3_tx_poll(irq_cfg->txq, budget); 24 25 if (unlikely(!budget)) 26 return 0; 27 28 work_done = hinic3_rx_poll(irq_cfg->rxq, budget); 29 busy |= work_done >= budget; 30 31 if (busy) 32 return budget; 33 34 if (likely(napi_complete_done(napi, work_done))) 35 hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, 36 HINIC3_MSIX_ENABLE); 37 38 return work_done; 39} 40 41static void qp_add_napi(struct hinic3_irq_cfg *irq_cfg) 42{ 43 struct hinic3_nic_dev *nic_dev = netdev_priv(irq_cfg->netdev); 44 45 netif_napi_add(nic_dev->netdev, &irq_cfg->napi, hinic3_poll); 46 napi_enable(&irq_cfg->napi); 47} 48 49static void qp_del_napi(struct hinic3_irq_cfg *irq_cfg) 50{ 51 napi_disable(&irq_cfg->napi); 52 netif_napi_del(&irq_cfg->napi); 53} 54 55static irqreturn_t qp_irq(int irq, void *data) 56{ 57 struct hinic3_irq_cfg *irq_cfg = data; 58 struct hinic3_nic_dev *nic_dev; 59 60 nic_dev = netdev_priv(irq_cfg->netdev); 61 hinic3_msix_intr_clear_resend_bit(nic_dev->hwdev, 62 irq_cfg->msix_entry_idx, 1); 63 64 napi_schedule(&irq_cfg->napi); 65 66 return IRQ_HANDLED; 67} 68 69static int hinic3_request_irq(struct hinic3_irq_cfg *irq_cfg, u16 q_id) 70{ 71 struct hinic3_interrupt_info info = {}; 72 struct hinic3_nic_dev *nic_dev; 73 struct net_device *netdev; 74 int err; 75 76 netdev = irq_cfg->netdev; 77 nic_dev = netdev_priv(netdev); 78 qp_add_napi(irq_cfg); 79 80 info.msix_index = irq_cfg->msix_entry_idx; 81 info.interrupt_coalesc_set = 1; 82 info.pending_limit = nic_dev->intr_coalesce[q_id].pending_limit; 83 info.coalesc_timer_cfg = 84 nic_dev->intr_coalesce[q_id].coalesce_timer_cfg; 85 info.resend_timer_cfg = nic_dev->intr_coalesce[q_id].resend_timer_cfg; 86 err = hinic3_set_interrupt_cfg_direct(nic_dev->hwdev, &info); 87 if (err) { 88 netdev_err(netdev, "Failed to set RX interrupt coalescing attribute.\n"); 89 qp_del_napi(irq_cfg); 90 return err; 91 } 92 93 err = request_irq(irq_cfg->irq_id, qp_irq, 0, irq_cfg->irq_name, 94 irq_cfg); 95 if (err) { 96 qp_del_napi(irq_cfg); 97 return err; 98 } 99 100 irq_set_affinity_hint(irq_cfg->irq_id, &irq_cfg->affinity_mask); 101 102 return 0; 103} 104 105static void hinic3_release_irq(struct hinic3_irq_cfg *irq_cfg) 106{ 107 irq_set_affinity_hint(irq_cfg->irq_id, NULL); 108 free_irq(irq_cfg->irq_id, irq_cfg); 109} 110 111int hinic3_qps_irq_init(struct net_device *netdev) 112{ 113 struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 114 struct pci_dev *pdev = nic_dev->pdev; 115 struct hinic3_irq_cfg *irq_cfg; 116 struct msix_entry *msix_entry; 117 u32 local_cpu; 118 u16 q_id; 119 int err; 120 121 for (q_id = 0; q_id < nic_dev->q_params.num_qps; q_id++) { 122 msix_entry = &nic_dev->qps_msix_entries[q_id]; 123 irq_cfg = &nic_dev->q_params.irq_cfg[q_id]; 124 125 irq_cfg->irq_id = msix_entry->vector; 126 irq_cfg->msix_entry_idx = msix_entry->entry; 127 irq_cfg->netdev = netdev; 128 irq_cfg->txq = &nic_dev->txqs[q_id]; 129 irq_cfg->rxq = &nic_dev->rxqs[q_id]; 130 nic_dev->rxqs[q_id].irq_cfg = irq_cfg; 131 132 local_cpu = cpumask_local_spread(q_id, dev_to_node(&pdev->dev)); 133 cpumask_set_cpu(local_cpu, &irq_cfg->affinity_mask); 134 135 snprintf(irq_cfg->irq_name, sizeof(irq_cfg->irq_name), 136 "%s_qp%u", netdev->name, q_id); 137 138 err = hinic3_request_irq(irq_cfg, q_id); 139 if (err) { 140 netdev_err(netdev, "Failed to request Rx irq\n"); 141 goto err_release_irqs; 142 } 143 144 netif_queue_set_napi(irq_cfg->netdev, q_id, 145 NETDEV_QUEUE_TYPE_RX, &irq_cfg->napi); 146 netif_queue_set_napi(irq_cfg->netdev, q_id, 147 NETDEV_QUEUE_TYPE_TX, &irq_cfg->napi); 148 149 hinic3_set_msix_auto_mask_state(nic_dev->hwdev, 150 irq_cfg->msix_entry_idx, 151 HINIC3_SET_MSIX_AUTO_MASK); 152 hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, 153 HINIC3_MSIX_ENABLE); 154 } 155 156 return 0; 157 158err_release_irqs: 159 while (q_id > 0) { 160 q_id--; 161 irq_cfg = &nic_dev->q_params.irq_cfg[q_id]; 162 qp_del_napi(irq_cfg); 163 netif_queue_set_napi(irq_cfg->netdev, q_id, 164 NETDEV_QUEUE_TYPE_RX, NULL); 165 netif_queue_set_napi(irq_cfg->netdev, q_id, 166 NETDEV_QUEUE_TYPE_TX, NULL); 167 hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, 168 HINIC3_MSIX_DISABLE); 169 hinic3_set_msix_auto_mask_state(nic_dev->hwdev, 170 irq_cfg->msix_entry_idx, 171 HINIC3_CLR_MSIX_AUTO_MASK); 172 hinic3_release_irq(irq_cfg); 173 } 174 175 return err; 176} 177 178void hinic3_qps_irq_uninit(struct net_device *netdev) 179{ 180 struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 181 struct hinic3_irq_cfg *irq_cfg; 182 u16 q_id; 183 184 for (q_id = 0; q_id < nic_dev->q_params.num_qps; q_id++) { 185 irq_cfg = &nic_dev->q_params.irq_cfg[q_id]; 186 qp_del_napi(irq_cfg); 187 netif_queue_set_napi(irq_cfg->netdev, q_id, 188 NETDEV_QUEUE_TYPE_RX, NULL); 189 netif_queue_set_napi(irq_cfg->netdev, q_id, 190 NETDEV_QUEUE_TYPE_TX, NULL); 191 hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, 192 HINIC3_MSIX_DISABLE); 193 hinic3_set_msix_auto_mask_state(nic_dev->hwdev, 194 irq_cfg->msix_entry_idx, 195 HINIC3_CLR_MSIX_AUTO_MASK); 196 hinic3_release_irq(irq_cfg); 197 } 198}
~/
Read-only file preview.