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

📄 ixgbe_main.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (cleaned_count >= IXGBE_RX_BUFFER_WRITE) {			ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count);			cleaned_count = 0;		}		/* use prefetched values */		rx_desc = next_rxd;		rx_buffer_info = next_buffer;		staterr = le32_to_cpu(rx_desc->wb.upper.status_error);		is_vlan = (staterr & IXGBE_RXD_STAT_VP);		vlan_tag = le16_to_cpu(rx_desc->wb.upper.vlan);	}	rx_ring->next_to_clean = i;	cleaned_count = IXGBE_DESC_UNUSED(rx_ring);	if (cleaned_count)		ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count);	return cleaned;}#define IXGBE_MAX_INTR 10/** * ixgbe_configure_msix - Configure MSI-X hardware * @adapter: board private structure * * ixgbe_configure_msix sets up the hardware to properly generate MSI-X * interrupts. **/static void ixgbe_configure_msix(struct ixgbe_adapter *adapter){	int i, vector = 0;	for (i = 0; i < adapter->num_tx_queues; i++) {		ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(i),			       IXGBE_MSIX_VECTOR(vector));		writel(EITR_INTS_PER_SEC_TO_REG(adapter->tx_eitr),		       adapter->hw.hw_addr + adapter->tx_ring[i].itr_register);		vector++;	}	for (i = 0; i < adapter->num_rx_queues; i++) {		ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(i),			       IXGBE_MSIX_VECTOR(vector));		writel(EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr),		       adapter->hw.hw_addr + adapter->rx_ring[i].itr_register);		vector++;	}	vector = adapter->num_tx_queues + adapter->num_rx_queues;	ixgbe_set_ivar(adapter, IXGBE_IVAR_OTHER_CAUSES_INDEX,		       IXGBE_MSIX_VECTOR(vector));	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(vector), 1950);}static irqreturn_t ixgbe_msix_lsc(int irq, void *data){	struct net_device *netdev = data;	struct ixgbe_adapter *adapter = netdev_priv(netdev);	struct ixgbe_hw *hw = &adapter->hw;	u32 eicr = IXGBE_READ_REG(hw, IXGBE_EICR);	if (eicr & IXGBE_EICR_LSC) {		adapter->lsc_int++;		if (!test_bit(__IXGBE_DOWN, &adapter->state))			mod_timer(&adapter->watchdog_timer, jiffies);	}	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);	return IRQ_HANDLED;}static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data){	struct ixgbe_ring *txr = data;	struct ixgbe_adapter *adapter = txr->adapter;	ixgbe_clean_tx_irq(adapter, txr);	return IRQ_HANDLED;}static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data){	struct ixgbe_ring *rxr = data;	struct ixgbe_adapter *adapter = rxr->adapter;	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rxr->eims_value);	netif_rx_schedule(adapter->netdev, &adapter->napi);	return IRQ_HANDLED;}static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget){	struct ixgbe_adapter *adapter = container_of(napi,					struct ixgbe_adapter, napi);	struct net_device *netdev = adapter->netdev;	int work_done = 0;	struct ixgbe_ring *rxr = adapter->rx_ring;	/* Keep link state information with original netdev */	if (!netif_carrier_ok(netdev))		goto quit_polling;	ixgbe_clean_rx_irq(adapter, rxr, &work_done, budget);	/* If no Tx and not enough Rx work done, exit the polling mode */	if ((work_done < budget) || !netif_running(netdev)) {quit_polling:		netif_rx_complete(netdev, napi);		if (!test_bit(__IXGBE_DOWN, &adapter->state))			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS,					rxr->eims_value);	}	return work_done;}/** * ixgbe_setup_msix - Initialize MSI-X interrupts * * ixgbe_setup_msix allocates MSI-X vectors and requests * interrutps from the kernel. **/static int ixgbe_setup_msix(struct ixgbe_adapter *adapter){	struct net_device *netdev = adapter->netdev;	int i, int_vector = 0, err = 0;	int max_msix_count;	/* +1 for the LSC interrupt */	max_msix_count = adapter->num_rx_queues + adapter->num_tx_queues + 1;	adapter->msix_entries = kcalloc(max_msix_count,					sizeof(struct msix_entry), GFP_KERNEL);	if (!adapter->msix_entries)		return -ENOMEM;	for (i = 0; i < max_msix_count; i++)		adapter->msix_entries[i].entry = i;	err = pci_enable_msix(adapter->pdev, adapter->msix_entries,			      max_msix_count);	if (err)		goto out;	for (i = 0; i < adapter->num_tx_queues; i++) {		sprintf(adapter->tx_ring[i].name, "%s-tx%d", netdev->name, i);		err = request_irq(adapter->msix_entries[int_vector].vector,				  &ixgbe_msix_clean_tx,				  0,				  adapter->tx_ring[i].name,				  &(adapter->tx_ring[i]));		if (err) {			DPRINTK(PROBE, ERR,				"request_irq failed for MSIX interrupt "				"Error: %d\n", err);			goto release_irqs;		}		adapter->tx_ring[i].eims_value =		    (1 << IXGBE_MSIX_VECTOR(int_vector));		adapter->tx_ring[i].itr_register = IXGBE_EITR(int_vector);		int_vector++;	}	for (i = 0; i < adapter->num_rx_queues; i++) {		if (strlen(netdev->name) < (IFNAMSIZ - 5))			sprintf(adapter->rx_ring[i].name,				"%s-rx%d", netdev->name, i);		else			memcpy(adapter->rx_ring[i].name,			       netdev->name, IFNAMSIZ);		err = request_irq(adapter->msix_entries[int_vector].vector,				  &ixgbe_msix_clean_rx, 0,				  adapter->rx_ring[i].name,				  &(adapter->rx_ring[i]));		if (err) {			DPRINTK(PROBE, ERR,				"request_irq failed for MSIX interrupt "				"Error: %d\n", err);			goto release_irqs;		}		adapter->rx_ring[i].eims_value =		    (1 << IXGBE_MSIX_VECTOR(int_vector));		adapter->rx_ring[i].itr_register = IXGBE_EITR(int_vector);		int_vector++;	}	sprintf(adapter->lsc_name, "%s-lsc", netdev->name);	err = request_irq(adapter->msix_entries[int_vector].vector,			  &ixgbe_msix_lsc, 0, adapter->lsc_name, netdev);	if (err) {		DPRINTK(PROBE, ERR,			"request_irq for msix_lsc failed: %d\n", err);		goto release_irqs;	}	/* FIXME: implement netif_napi_remove() instead */	adapter->napi.poll = ixgbe_clean_rxonly;	adapter->flags |= IXGBE_FLAG_MSIX_ENABLED;	return 0;release_irqs:	int_vector--;	for (; int_vector >= adapter->num_tx_queues; int_vector--)		free_irq(adapter->msix_entries[int_vector].vector,			 &(adapter->rx_ring[int_vector -					    adapter->num_tx_queues]));	for (; int_vector >= 0; int_vector--)		free_irq(adapter->msix_entries[int_vector].vector,			 &(adapter->tx_ring[int_vector]));out:	kfree(adapter->msix_entries);	adapter->msix_entries = NULL;	adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;	return err;}/** * ixgbe_intr - Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure * @pt_regs: CPU registers structure **/static irqreturn_t ixgbe_intr(int irq, void *data){	struct net_device *netdev = data;	struct ixgbe_adapter *adapter = netdev_priv(netdev);	struct ixgbe_hw *hw = &adapter->hw;	u32 eicr;	eicr = IXGBE_READ_REG(hw, IXGBE_EICR);	if (!eicr)		return IRQ_NONE;	/* Not our interrupt */	if (eicr & IXGBE_EICR_LSC) {		adapter->lsc_int++;		if (!test_bit(__IXGBE_DOWN, &adapter->state))			mod_timer(&adapter->watchdog_timer, jiffies);	}	if (netif_rx_schedule_prep(netdev, &adapter->napi)) {		/* Disable interrupts and register for poll. The flush of the		 * posted write is intentionally left out. */		atomic_inc(&adapter->irq_sem);		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);		__netif_rx_schedule(netdev, &adapter->napi);	}	return IRQ_HANDLED;}/** * ixgbe_request_irq - initialize interrupts * @adapter: board private structure * * Attempts to configure interrupts using the best available * capabilities of the hardware and kernel. **/static int ixgbe_request_irq(struct ixgbe_adapter *adapter, u32 *num_rx_queues){	struct net_device *netdev = adapter->netdev;	int flags, err;	irqreturn_t(*handler) (int, void *) = &ixgbe_intr;	flags = IRQF_SHARED;	err = ixgbe_setup_msix(adapter);	if (!err)		goto request_done;	/*	 * if we can't do MSI-X, fall through and try MSI	 * No need to reallocate memory since we're decreasing the number of	 * queues. We just won't use the other ones, also it is freed correctly	 * on ixgbe_remove.	 */	*num_rx_queues = 1;	/* do MSI */	err = pci_enable_msi(adapter->pdev);	if (!err) {		adapter->flags |= IXGBE_FLAG_MSI_ENABLED;		flags &= ~IRQF_SHARED;		handler = &ixgbe_intr;	}	err = request_irq(adapter->pdev->irq, handler, flags,			  netdev->name, netdev);	if (err)		DPRINTK(PROBE, ERR, "request_irq failed, Error %d\n", err);request_done:	return err;}static void ixgbe_free_irq(struct ixgbe_adapter *adapter){	struct net_device *netdev = adapter->netdev;	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {		int i;		for (i = 0; i < adapter->num_tx_queues; i++)			free_irq(adapter->msix_entries[i].vector,				 &(adapter->tx_ring[i]));		for (i = 0; i < adapter->num_rx_queues; i++)			free_irq(adapter->msix_entries[i +						adapter->num_tx_queues].vector,				&(adapter->rx_ring[i]));		i = adapter->num_rx_queues + adapter->num_tx_queues;		free_irq(adapter->msix_entries[i].vector, netdev);		pci_disable_msix(adapter->pdev);		kfree(adapter->msix_entries);		adapter->msix_entries = NULL;		adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;		return;	}	free_irq(adapter->pdev->irq, netdev);	if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {		pci_disable_msi(adapter->pdev);		adapter->flags &= ~IXGBE_FLAG_MSI_ENABLED;	}}/** * ixgbe_irq_disable - Mask off interrupt generation on the NIC * @adapter: board private structure **/static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter){	atomic_inc(&adapter->irq_sem);	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);	IXGBE_WRITE_FLUSH(&adapter->hw);	synchronize_irq(adapter->pdev->irq);}/** * ixgbe_irq_enable - Enable default interrupt generation settings * @adapter: board private structure **/static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter){	if (atomic_dec_and_test(&adapter->irq_sem)) {		if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC,					(IXGBE_EIMS_ENABLE_MASK &					 ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC)));		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS,				IXGBE_EIMS_ENABLE_MASK);		IXGBE_WRITE_FLUSH(&adapter->hw);	}}/** * ixgbe_configure_msi_and_legacy - Initialize PIN (INTA...) and MSI interrupts * **/static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter){	int i;	struct ixgbe_hw *hw = &adapter->hw;	if (adapter->rx_eitr)		IXGBE_WRITE_REG(hw, IXGBE_EITR(0),				EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr));	/* for re-triggering the interrupt in non-NAPI mode */	adapter->rx_ring[0].eims_value = (1 << IXGBE_MSIX_VECTOR(0));	adapter->tx_ring[0].eims_value = (1 << IXGBE_MSIX_VECTOR(0));	ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(0), 0);	for (i = 0; i < adapter->num_tx_queues; i++)		ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(i), i);}/** * ixgbe_configure_tx - Configure 8254x Transmit Unit after Reset * @adapter: board private structure * * Configure the Tx unit of the MAC after a reset. **/static void ixgbe_configure_tx(struct ixgbe_adapter *adapter){	u64 tdba;	struct ixgbe_hw *hw = &adapter->hw;	u32 i, tdlen;	/* Setup the HW Tx Head and Tail descriptor pointers */	for (i = 0; i < adapter->num_tx_queues; i++) {		tdba = adapter->tx_ring[i].dma;		tdlen = adapter->tx_ring[i].count *		    sizeof(union ixgbe_adv_tx_desc);		IXGBE_WRITE_REG(hw, IXGBE_TDBAL(i), (tdba & DMA_32BIT_MASK));		IXGBE_WRITE_REG(hw, IXGBE_TDBAH(i), (tdba >> 32));		IXGBE_WRITE_REG(hw, IXGBE_TDLEN(i), tdlen);		IXGBE_WRITE_REG(hw, IXGBE_TDH(i), 0);		IXGBE_WRITE_REG(hw, IXGBE_TDT(i), 0);		adapter->tx_ring[i].head = IXGBE_TDH(i);		adapter->tx_ring[i].tail = IXGBE_TDT(i);	}	IXGBE_WRITE_REG(hw, IXGBE_TIPG, IXGBE_TIPG_FIBER_DEFAULT);}#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \			(((S) & (PAGE_SIZE - 1)) ? 1 : 0))#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT			2/** * ixgbe_configure_rx - Configure 8254x Receive Unit after Reset * @adapter: board private structure * * Configure the Rx unit of the MAC after a reset. **/static void ixgbe_configure_rx(struct ixgbe_adapter *adapter){	u64 rdba;	struct ixgbe_hw *hw = &adapter->hw;	struct net_device *netdev = adapter->netdev;	int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;	u32 rdlen, rxctrl, rxcsum;	u32 random[10];	u32 reta, mrqc;	int i;	u32 fctrl, hlreg0;	u32 srrctl;	u32 pages;	/* Decide whether to use packet split mode or not */	if (netdev->mtu > ETH_DATA_LEN)		adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED;	else		adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED;	/* Set the RX buffer length according to the mode */	if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {		adapter->rx_buf_len = IXGBE_RX_HDR_SIZE;	} else {		if (netdev->mtu <= ETH_DATA_LEN)			adapter->rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE;		else			adapter->rx_buf_len = ALIGN(max_frame, 1024);	}	fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);	fctrl |= IXGBE_FCTRL_BAM;	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);	hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);	if (adapter->netdev->mtu <= ETH_DATA_LEN)		hlreg0 &= ~IXGBE_HLREG0_JUMBOEN;	else		hlreg0 |= IXGBE_HLREG0_JUMBOEN;	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);	pages = PAGE_USE_COUNT(adapter->netdev->mtu);	srrctl = IXGBE_READ_REG(&adapter->hw, IXGBE_SRRCTL(0));	srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;	srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;	if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {		srrctl |= PAGE_SIZE >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;		srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;		srrctl |= ((IXGBE_RX_HDR_SIZE <<

⌨️ 快捷键说明

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