⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netdev.c

📁 Intel 82546系列lan driver源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (likely(adapter->itr_setting & 3))		e1000_set_itr(adapter);#endif /* CONFIG_E1000E_NAPI */	return IRQ_HANDLED;}/** * e1000_intr - Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure **/static irqreturn_t e1000_intr(int irq, void *data){	struct net_device *netdev = data;	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;#ifndef CONFIG_E1000E_NAPI	int i;	int rx_cleaned, tx_cleaned_complete;#endif	u32 rctl, icr = er32(ICR);	if (!icr)		return IRQ_NONE;  /* Not our interrupt */#ifdef CONFIG_E1000E_NAPI	/*	 * IMS will not auto-mask if INT_ASSERTED is not set, and if it is	 * not set, then the adapter didn't send an interrupt	 */	if (!(icr & E1000_ICR_INT_ASSERTED))		return IRQ_NONE;#endif /* CONFIG_E1000E_NAPI */	/*	 * Interrupt Auto-Mask...upon reading ICR,	 * interrupts are masked.  No need for the	 * IMC write	 */	if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {		hw->mac.get_link_status = 1;		/*		 * ICH8 workaround-- Call gig speed drop workaround on cable		 * disconnect (LSC) before accessing any PHY registers		 */		if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&		    (!(er32(STATUS) & E1000_STATUS_LU)))			schedule_work(&adapter->downshift_task);		/*		 * 80003ES2LAN workaround--		 * For packet buffer work-around on link down event;		 * disable receives here in the ISR and		 * reset adapter in watchdog		 */		if (netif_carrier_ok(netdev) &&		    (adapter->flags & FLAG_RX_NEEDS_RESTART)) {			/* disable receives */			rctl = er32(RCTL);			ew32(RCTL, rctl & ~E1000_RCTL_EN);			adapter->flags |= FLAG_RX_RESTART_NOW;		}		/* guard against interrupt when we're going down */		if (!test_bit(__E1000_DOWN, &adapter->state))			mod_timer(&adapter->watchdog_timer, jiffies + 1);	}#ifdef CONFIG_E1000E_NAPI	if (netif_rx_schedule_prep(netdev, &adapter->napi)) {		adapter->total_tx_bytes = 0;		adapter->total_tx_packets = 0;		adapter->total_rx_bytes = 0;		adapter->total_rx_packets = 0;		__netif_rx_schedule(netdev, &adapter->napi);	}#else	adapter->total_tx_bytes = 0;	adapter->total_rx_bytes = 0;	adapter->total_tx_packets = 0;	adapter->total_rx_packets = 0;	for (i = 0; i < E1000_MAX_INTR; i++) {		rx_cleaned = adapter->clean_rx(adapter);		tx_cleaned_complete = e1000_clean_tx_irq(adapter);		if (!rx_cleaned && tx_cleaned_complete)			break;	}	if (likely(adapter->itr_setting & 3))		e1000_set_itr(adapter);#endif /* CONFIG_E1000E_NAPI */	return IRQ_HANDLED;}#ifdef CONFIG_E1000E_MSIXstatic irqreturn_t e1000_msix_other(int irq, void *data){	struct net_device *netdev = data;	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	u32 icr = er32(ICR);	if (!(icr & E1000_ICR_INT_ASSERTED)) {		ew32(IMS, E1000_IMS_OTHER);		return IRQ_NONE;	}	if (icr & adapter->eiac_mask)		ew32(ICS, (icr & adapter->eiac_mask));	if (icr & E1000_ICR_OTHER) {		if (!(icr & E1000_ICR_LSC))			goto no_link_interrupt;		hw->mac.get_link_status = 1;		/* guard against interrupt when we're going down */		if (!test_bit(__E1000_DOWN, &adapter->state))			mod_timer(&adapter->watchdog_timer, jiffies + 1);	}no_link_interrupt:	ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER);	return IRQ_HANDLED;}#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLERstatic irqreturn_t e1000_intr_msix_tx(int irq, void *data){	struct net_device *netdev = data;	struct e1000_adapter *adapter = netdev_priv(netdev);	struct e1000_hw *hw = &adapter->hw;	struct e1000_ring *tx_ring = adapter->tx_ring;	adapter->total_tx_bytes = 0;	adapter->total_tx_packets = 0;	if (!e1000_clean_tx_irq(adapter))		/* Ring was not completely cleaned, so fire another interrupt */		ew32(ICS, tx_ring->ims_val);	return IRQ_HANDLED;}#endif  /* CONFIG_E1000E_SEPARATE_TX_HANDLER */static irqreturn_t e1000_intr_msix_rx(int irq, void *data){	struct net_device *netdev = data;	struct e1000_adapter *adapter = netdev_priv(netdev);#ifndef CONFIG_E1000E_NAPI	int i;	struct e1000_hw *hw = &adapter->hw;#endif	/* Write the ITR value calculated at the end of the	 * previous interrupt.	 */	if (adapter->rx_ring->set_itr) {		writel(1000000000 / (adapter->rx_ring->itr_val * 256),		       adapter->hw.hw_addr + adapter->rx_ring->itr_register);		adapter->rx_ring->set_itr = 0;	}#ifdef CONFIG_E1000E_NAPI	if (netif_rx_schedule_prep(netdev, &adapter->napi)) {		adapter->total_rx_bytes = 0;		adapter->total_rx_packets = 0;#ifndef CONFIG_E1000E_SEPARATE_TX_HANDLER		adapter->total_tx_bytes = 0;		adapter->total_tx_packets = 0;#endif /* CONFIG_E1000E_SEPARATE_TX_HANDLER */		__netif_rx_schedule(netdev, &adapter->napi);	}#else	adapter->total_rx_bytes = 0;	adapter->total_rx_packets = 0;#ifndef CONFIG_E1000E_SEPARATE_TX_HANDLER	adapter->total_tx_bytes = 0;	adapter->total_tx_packets = 0;#endif	for (i = 0; i < E1000_MAX_INTR; i++) {		int rx_cleaned = adapter->clean_rx(adapter);#ifndef CONFIG_E1000E_SEPARATE_TX_HANDLER		int tx_cleaned_complete = e1000_clean_tx_irq(adapter);		if (!rx_cleaned && tx_cleaned_complete)#else		if (!rx_cleaned)#endif			goto out;	}	/* If we got here, the ring was not completely cleaned,	 * so fire another interrupt.	 */	ew32(ICS, adapter->rx_ring->ims_val);out:#endif /* CONFIG_E1000E_NAPI */	return IRQ_HANDLED;}/** * e1000_configure_msix - Configure MSI-X hardware * * e1000_configure_msix sets up the hardware to properly * generate MSI-X interrupts. **/static void e1000_configure_msix(struct e1000_adapter *adapter){	struct e1000_hw *hw = &adapter->hw;	struct e1000_ring *rx_ring = adapter->rx_ring;	struct e1000_ring *tx_ring = adapter->tx_ring;	int vector = 0;	u32 ctrl_ext, ivar = 0;	adapter->eiac_mask = 0;	/* Workaround issue with spurious interrupts on 82574 in MSI-X mode */	if (hw->mac.type == e1000_82574) {		u32 rfctl = er32(RFCTL);		rfctl |= E1000_RFCTL_ACK_DIS;		ew32(RFCTL, rfctl);	}#define E1000_IVAR_INT_ALLOC_VALID	0x8	/* Configure Rx vector */	rx_ring->ims_val = E1000_IMS_RXQ0;	adapter->eiac_mask |= rx_ring->ims_val;	if (rx_ring->itr_val)		writel(1000000000 / (rx_ring->itr_val * 256),		       hw->hw_addr + rx_ring->itr_register);	else		writel(1, hw->hw_addr + rx_ring->itr_register);	ivar = E1000_IVAR_INT_ALLOC_VALID | vector;	/* Configure Tx vector */	tx_ring->ims_val = E1000_IMS_TXQ0;#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLER	vector++;	if (tx_ring->itr_val)		writel(1000000000 / (tx_ring->itr_val * 256),		       hw->hw_addr + tx_ring->itr_register);	else		writel(1, hw->hw_addr + tx_ring->itr_register);#else	rx_ring->ims_val |= tx_ring->ims_val;#endif	adapter->eiac_mask |= tx_ring->ims_val;	ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 8);	/* set vector for Other Causes, e.g. link changes */	vector++;	ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 16);	if (rx_ring->itr_val)		writel(1000000000 / (rx_ring->itr_val * 256),		       hw->hw_addr + E1000_EITR_82574(vector));	else		writel(1, hw->hw_addr + E1000_EITR_82574(vector));	/* Cause Tx interrupts on every write back */	ivar |= (1 << 31);	ew32(IVAR, ivar);	/* enable MSI-X PBA support */	ctrl_ext = er32(CTRL_EXT);	ctrl_ext |= E1000_CTRL_EXT_PBA_CLR;	/* Auto-Mask Other interrupts upon ICR read */	ew32(IAM, ~E1000_EIAC_MASK_82574 | E1000_IMS_OTHER);	ctrl_ext |= E1000_CTRL_EXT_EIAME;	ew32(CTRL_EXT, ctrl_ext);	e1e_flush();}void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter){	if (adapter->msix_entries) {		pci_disable_msix(adapter->pdev);		kfree(adapter->msix_entries);		adapter->msix_entries = NULL;	} else if (adapter->flags & FLAG_MSI_ENABLED) {		pci_disable_msi(adapter->pdev);		adapter->flags &= ~FLAG_MSI_ENABLED;	}	return;}/** * e1000e_set_interrupt_capability - set MSI or MSI-X if supported * * Attempt to configure interrupts using the best available * capabilities of the hardware and kernel. **/void e1000e_set_interrupt_capability(struct e1000_adapter *adapter){	int err;	int numvecs, i;	switch (adapter->int_mode) {	case E1000E_INT_MODE_MSIX:		if (adapter->flags & FLAG_HAS_MSIX) {#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLER			numvecs = 3; /* RxQ0, TxQ0 and other */#else			numvecs = 2; /* RxQ0/TxQ0 and other */#endif			adapter->msix_entries = kcalloc(numvecs,						      sizeof(struct msix_entry),						      GFP_KERNEL);			if (adapter->msix_entries) {				for (i = 0; i < numvecs; i++)					adapter->msix_entries[i].entry = i;				err = pci_enable_msix(adapter->pdev,						      adapter->msix_entries,						      numvecs);				if (err == 0)					return;			}			/* MSI-X failed, so fall through and try MSI */			e_err("Failed to initialize MSI-X interrupts.  "			      "Falling back to MSI interrupts.\n");			e1000e_reset_interrupt_capability(adapter);		}		adapter->int_mode = E1000E_INT_MODE_MSI;		/* Fall through */	case E1000E_INT_MODE_MSI:		if (!pci_enable_msi(adapter->pdev)) {			adapter->flags |= FLAG_MSI_ENABLED;		} else {			adapter->int_mode = E1000E_INT_MODE_LEGACY;			e_err("Failed to initialize MSI interrupts.  Falling "			      "back to legacy interrupts.\n");		}		/* Fall through */	case E1000E_INT_MODE_LEGACY:		/* Don't do anything; this is the system default */		break;	}	return;}/** * e1000_request_msix - Initialize MSI-X interrupts * * e1000_request_msix allocates MSI-X vectors and requests interrupts from the * kernel. **/static int e1000_request_msix(struct e1000_adapter *adapter){	struct net_device *netdev = adapter->netdev;	int err = 0, vector = 0;	if (strlen(netdev->name) < (IFNAMSIZ - 5))#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLER		sprintf(adapter->rx_ring->name, "%s-rx-0", netdev->name);#else		sprintf(adapter->rx_ring->name, "%s-Q0", netdev->name);#endif	else		memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ);	err = request_irq(adapter->msix_entries[vector].vector,			  &e1000_intr_msix_rx, 0, adapter->rx_ring->name,			  netdev);	if (err)		goto out;	adapter->rx_ring->itr_register = E1000_EITR_82574(vector);	adapter->rx_ring->itr_val = adapter->itr;	vector++;#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLER	if (strlen(netdev->name) < (IFNAMSIZ - 5))		sprintf(adapter->tx_ring->name, "%s-tx-0", netdev->name);	else		memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ);	err = request_irq(adapter->msix_entries[vector].vector,			  &e1000_intr_msix_tx, 0, adapter->tx_ring->name,			  netdev);	if (err)		goto out;	adapter->tx_ring->itr_register = E1000_EITR_82574(vector);	adapter->tx_ring->itr_val = adapter->itr;	vector++;#endif /* CONFIG_E1000E_SEPARATE_TX_HANDLER */	err = request_irq(adapter->msix_entries[vector].vector,			  &e1000_msix_other, 0, netdev->name, netdev);	if (err)		goto out;	e1000_configure_msix(adapter);	return 0;out:	return err;}#endif /* CONFIG_E1000E_MSIX *//** * e1000_request_irq - initialize interrupts * * Attempts to configure interrupts using the best available * capabilities of the hardware and kernel. **/static int e1000_request_irq(struct e1000_adapter *adapter){	struct net_device *netdev = adapter->netdev;#ifndef CONFIG_E1000E_MSIX	int irq_flags = IRQF_SHARED;#endif	int err;#ifdef CONFIG_E1000E_MSIX	if (adapter->msix_entries) {		err = e1000_request_msix(adapter);		if (!err)			return err;		/* fall back to MSI */		e1000e_reset_interrupt_capability(adapter);		adapter->int_mode = E1000E_INT_MODE_MSI;		e1000e_set_interrupt_capability(adapter);	}	if (adapter->flags & FLAG_MSI_ENABLED) {		err = request_irq(adapter->pdev->irq, &e1000_intr_msi, 0,				  netdev->name, netdev);		if (!err)			return err;		/* fall back to legacy interrupt */		e1000e_reset_interrupt_capability(adapter);		adapter->int_mode = E1000E_INT_MODE_LEGACY;	}	err = request_irq(adapter->pdev->irq, &e1000_intr, IRQF_SHARED,			  netdev->name, netdev);	if (err)		e_err("Unable to allocate interrupt, Error: %d\n", err);#else	if (!(adapter->flags & FLAG_MSI_TEST_FAILED)) {		err = pci_enable_msi(adapter->pdev);		if (!err) {			adapter->flags |= FLAG_MSI_ENABLED;			irq_flags = 0;		}	}	err = request_irq(adapter->pdev->irq,			  ((adapter->flags & FLAG_MSI_ENABLED) ?				&e1000_intr_msi : &e1000_intr),			  irq_flags, netdev->name, netdev);	if (err) {		if (adapter->flags & FLAG_MSI_ENABLED) {			pci_disable_msi(adapter->pdev);			adapter->flags &= ~FLAG_MSI_ENABLED;		}		e_err("Unable to allocate interrupt, Error: %d\n", err);	}#endif /* CONFIG_E1000E_MSIX */	return err;}static void e1000_free_irq(struct e1000_adapter *adapter){	struct net_device *netdev = adapter->netdev;#ifdef CONFIG_E1000E_MSIX	if (adapter->msix_entries) {		int vector = 0;		free_irq(adapter->msix_entries[vector].vector, netdev);		vector++;#ifdef CONFIG_E1000E_SEPARATE_TX_HANDLER		free_irq(adapter->msix_entries[vector].vector, netdev);		vector++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -