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

📄 netdev.c

📁 DELL755 Intel 网卡驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 e1000_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;}/** * e1000_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 e1000_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");			e1000_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-rx0", 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-tx0", 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_alloc_queues - Allocate memory for all rings * @adapter: board private structure to initialize **/static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter){	adapter->tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);	if (!adapter->tx_ring)		goto err;	adapter->rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);	if (!adapter->rx_ring)		goto err;	return 0;err:	e_err("Unable to allocate memory for queues\n");	kfree(adapter->rx_ring);	kfree(adapter->tx_ring);	return -ENOMEM;}/** * 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;	int err;#ifdef CONFIG_E1000E_MSIX	if (adapter->msix_entries) {		err = e1000_request_msix(adapter);		if (!err)			return err;		/* fall back to MSI */		e1000_reset_interrupt_capability(adapter);		adapter->int_mode = E1000E_INT_MODE_MSI;		e1000_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 */		e1000_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	int irq_flags = IRQF_SHARED;	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++;#endif		/* Other Causes interrupt vector */		free_irq(adapter->msix_entries[vector].vector, netdev);		return;	}#endif /* CONFIG_E1000E_MSIX */	free_irq(adapter->pdev->irq, netdev);#ifndef CONFIG_E1000E_MSIX	if (adapter->flags & FLAG_MSI_ENABLED) {		pci_disable_msi(adapter->pdev);		adapter->flags &= ~FLAG_MSI_ENABLED;	}#endif}/** * e1000_irq_disable - Mask off interrupt generation on the NIC **/static void e1000_irq_disable(struct e1000_adapter *adapter){	struct e1000_hw *hw = &adapter->hw;	ew32(IMC, ~0);#ifdef CONFIG_E1000E_MSIX	if (adapter->msix_entries) {		ew32(EIAC_82574, 0);	}#endif /* CONFIG_E1000E_MSIX */	e1e_flush();	synchronize_irq(adapter->pdev->irq);}/** * e1000_irq_enable - Enable default interrupt generation settings **/static void e1000_irq_enable(struct e1000_adapter *adapter){	struct e1000_hw *hw = &adapter->hw;#ifdef CONFIG_E1000E_MSIX	if (adapter->msix_entries) {		ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574);		ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC);	} else {		ew32(IMS, IMS_ENABLE_MASK);	}#else	ew32(IMS, IMS_ENABLE_MASK);#endif /* CONFIG_E1000E_MSIX */}/** * e1000_get_hw_control - get control of the h/w from f/w * @adapter: address of board private structure * * e1000_get_hw_control sets {CTRL_EXT|SWSM}:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means that * the driver is loaded. For AMT version (only with 82573) * of the f/w this means that the network i/f is open. **/static void e1000_get_hw_control(struct e1000_adapter *adapter){	struct e1000_hw *hw = &adapter->hw;	u32 ctrl_ext;	u32 swsm;	/* Let firmware know the driver has taken over */	if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) {		swsm = er32(SWSM);		ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD);	} else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) {		ctrl_ext = er32(CTRL_EXT);		ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);	}}/** * e1000_release_hw_control - release control of the h/w to f/w * @adapter: address of board private structure * * e1000_release_hw_control resets {CTRL_EXT|SWSM}:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means that the * driver is no longer loaded. For AMT version (only with 82573) i * of the f/w this means that the network i/f is closed. * **/static void e1000_release_hw_control(struct e1000_adapter *adapter){	struct e1000_hw *hw = &adapter->hw;	u32 ctrl_ext;	u32 swsm;	/* Let firmware taken over control of h/w */	if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) {		swsm = er32(SWSM);		ew32(SWSM, swsm & ~E1000_SWSM_DRV_LOAD);	} else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) {		ctrl_ext = er32(CTRL_EXT);		ew32(CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);	}}#ifdef CONFIG_E1000E_NAPI/** * e1000_poll - NAPI Rx polling callback * @napi: struct associated with this polling callback * @budget: amount of packets driver is allowed to process this poll **/static int e1000_poll(struct napi_struct *napi, int budget){	struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter,						     napi);	struct net_device *netdev = adapter->netdev;	int tx_clean_complete = 1, work_done = 0;#ifdef CONFIG_E1000E_MSIX	struct e1000_hw *hw = &adapter->hw;	if (adapter->msix_entries &&	    !(adapter->rx_ring->ims_val & adapter->tx_ring->ims_val))		goto clean_rx;#endif	/*	 * e1000_poll is called per-cpu.  This lock protects	 * tx_ring from being cleaned by multiple cpus	 * simultaneously.  A failure obtaining the lock means	 * tx_ring is currently being cleaned anyway.	 */	if (spin_trylock(&adapter->tx_queue_lo

⌨️ 快捷键说明

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