drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c
Extension
.c
Size
6506 bytes
Lines
269
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (err) {
			wx_err(wx, "request_irq failed for MSIX interrupt %s Error: %d\n",
			       q_vector->name, err);
			goto free_queue_irqs;
		}
	}

	return 0;

free_queue_irqs:
	while (vector) {
		vector--;
		free_irq(wx->msix_q_entries[vector].vector,
			 wx->q_vector[vector]);
	}
	return err;
}

static int txgbe_request_link_irq(struct txgbe *txgbe)
{
	txgbe->link_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_LINK);
	return request_threaded_irq(txgbe->link_irq, NULL,
				    txgbe_link_irq_handler,
				    IRQF_ONESHOT, "txgbe-link-irq", txgbe);
}

static int txgbe_request_gpio_irq(struct txgbe *txgbe)
{
	txgbe->gpio_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_GPIO);
	return request_threaded_irq(txgbe->gpio_irq, NULL,
				    txgbe_gpio_irq_handler_aml,
				    IRQF_ONESHOT, "txgbe-gpio-irq", txgbe);
}

static const struct irq_chip txgbe_irq_chip = {
	.name = "txgbe-misc-irq",
};

static int txgbe_misc_irq_domain_map(struct irq_domain *d,
				     unsigned int irq,
				     irq_hw_number_t hwirq)
{
	struct txgbe *txgbe = d->host_data;

	irq_set_chip_data(irq, txgbe);
	irq_set_chip(irq, &txgbe->misc.chip);
	irq_set_nested_thread(irq, true);
	irq_set_noprobe(irq);

	return 0;
}

static const struct irq_domain_ops txgbe_misc_irq_domain_ops = {
	.map = txgbe_misc_irq_domain_map,
};

static irqreturn_t txgbe_misc_irq_handle(int irq, void *data)
{
	struct wx_q_vector *q_vector;
	struct txgbe *txgbe = data;
	struct wx *wx = txgbe->wx;
	u32 eicr;

	if (wx->pdev->msix_enabled) {
		eicr = wx_misc_isb(wx, WX_ISB_MISC);
		txgbe->eicr = eicr;
		if (eicr & TXGBE_PX_MISC_IC_VF_MBOX) {
			wx_msg_task(txgbe->wx);
			wx_intr_enable(wx, TXGBE_INTR_MISC(wx));
		}
		return IRQ_WAKE_THREAD;
	}

	eicr = wx_misc_isb(wx, WX_ISB_VEC0);
	if (!eicr) {
		/* shared interrupt alert!
		 * the interrupt that we masked before the ICR read.
		 */
		if (!test_bit(WX_STATE_DOWN, wx->state))
			txgbe_irq_enable(wx, true);
		return IRQ_NONE;        /* Not our interrupt */
	}
	wx->isb_mem[WX_ISB_VEC0] = 0;
	if (!(wx->pdev->msi_enabled))
		wr32(wx, WX_PX_INTA, 1);

	/* would disable interrupts here but it is auto disabled */
	q_vector = wx->q_vector[0];
	napi_schedule_irqoff(&q_vector->napi);

Annotation

Implementation Notes