File Index
Files and directories
Sign in
FILE

hinic3_irq.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c 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.