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

📄 ixgb_main.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
		rctl &= ~IXGB_RCTL_UPE;	} else {		rctl &= ~(IXGB_RCTL_UPE | IXGB_RCTL_MPE);	}	if(netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES) {		rctl |= IXGB_RCTL_MPE;		IXGB_WRITE_REG(hw, RCTL, rctl);	} else {		uint8_t mta[netdev->mc_count * IXGB_ETH_LENGTH_OF_ADDRESS];		IXGB_WRITE_REG(hw, RCTL, rctl);		for(i = 0, mc_ptr = netdev->mc_list; mc_ptr;			i++, mc_ptr = mc_ptr->next)			memcpy(&mta[i * IXGB_ETH_LENGTH_OF_ADDRESS],				   mc_ptr->dmi_addr, IXGB_ETH_LENGTH_OF_ADDRESS);		ixgb_mc_addr_list_update(hw, mta, netdev->mc_count, 0);	}}/** * ixgb_watchdog - Timer Call-back * @data: pointer to netdev cast into an unsigned long **/static voidixgb_watchdog(unsigned long data){	struct ixgb_adapter *adapter = (struct ixgb_adapter *)data;	struct net_device *netdev = adapter->netdev;	struct ixgb_desc_ring *txdr = &adapter->tx_ring;	ixgb_check_for_link(&adapter->hw);	if (ixgb_check_for_bad_link(&adapter->hw)) {		/* force the reset path */		netif_stop_queue(netdev);	}	if(adapter->hw.link_up) {		if(!netif_carrier_ok(netdev)) {			printk(KERN_INFO "ixgb: %s NIC Link is Up %d Mbps %s\n",				   netdev->name, 10000, "Full Duplex");			adapter->link_speed = 10000;			adapter->link_duplex = FULL_DUPLEX;			netif_carrier_on(netdev);			netif_wake_queue(netdev);		}	} else {		if(netif_carrier_ok(netdev)) {			adapter->link_speed = 0;			adapter->link_duplex = 0;			printk(KERN_INFO				   "ixgb: %s NIC Link is Down\n",				   netdev->name);			netif_carrier_off(netdev);			netif_stop_queue(netdev);		}	}	ixgb_update_stats(adapter);	if(!netif_carrier_ok(netdev)) {		if(IXGB_DESC_UNUSED(txdr) + 1 < txdr->count) {			/* We've lost link, so the controller stops DMA,			 * but we've got queued Tx work that's never going			 * to get done, so reset controller to flush Tx.			 * (Do the reset outside of interrupt context). */			schedule_work(&adapter->tx_timeout_task);		}	}	/* Force detection of hung controller every watchdog period */	adapter->detect_tx_hung = TRUE;	/* generate an interrupt to force clean up of any stragglers */	IXGB_WRITE_REG(&adapter->hw, ICS, IXGB_INT_TXDW);	/* Reset the timer */	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);}#define IXGB_TX_FLAGS_CSUM		0x00000001#define IXGB_TX_FLAGS_VLAN		0x00000002#define IXGB_TX_FLAGS_TSO		0x00000004static inline intixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb){#ifdef NETIF_F_TSO	struct ixgb_context_desc *context_desc;	unsigned int i;	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;	uint16_t ipcse, tucse, mss;	int err;	if(likely(skb_shinfo(skb)->tso_size)) {		if (skb_header_cloned(skb)) {			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);			if (err)				return err;		}		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));		mss = skb_shinfo(skb)->tso_size;		skb->nh.iph->tot_len = 0;		skb->nh.iph->check = 0;		skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,						      skb->nh.iph->daddr,						      0, IPPROTO_TCP, 0);		ipcss = skb->nh.raw - skb->data;		ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data;		ipcse = skb->h.raw - skb->data - 1;		tucss = skb->h.raw - skb->data;		tucso = (void *)&(skb->h.th->check) - (void *)skb->data;		tucse = 0;		i = adapter->tx_ring.next_to_use;		context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i);		context_desc->ipcss = ipcss;		context_desc->ipcso = ipcso;		context_desc->ipcse = cpu_to_le16(ipcse);		context_desc->tucss = tucss;		context_desc->tucso = tucso;		context_desc->tucse = cpu_to_le16(tucse);		context_desc->mss = cpu_to_le16(mss);		context_desc->hdr_len = hdr_len;		context_desc->status = 0;		context_desc->cmd_type_len = cpu_to_le32(						  IXGB_CONTEXT_DESC_TYPE 						| IXGB_CONTEXT_DESC_CMD_TSE						| IXGB_CONTEXT_DESC_CMD_IP						| IXGB_CONTEXT_DESC_CMD_TCP						| IXGB_CONTEXT_DESC_CMD_IDE						| (skb->len - (hdr_len)));		if(++i == adapter->tx_ring.count) i = 0;		adapter->tx_ring.next_to_use = i;		return 1;	}#endif	return 0;}static inline boolean_tixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb){	struct ixgb_context_desc *context_desc;	unsigned int i;	uint8_t css, cso;	if(likely(skb->ip_summed == CHECKSUM_HW)) {		css = skb->h.raw - skb->data;		cso = (skb->h.raw + skb->csum) - skb->data;		i = adapter->tx_ring.next_to_use;		context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i);		context_desc->tucss = css;		context_desc->tucso = cso;		context_desc->tucse = 0;		/* zero out any previously existing data in one instruction */		*(uint32_t *)&(context_desc->ipcss) = 0;		context_desc->status = 0;		context_desc->hdr_len = 0;		context_desc->mss = 0;		context_desc->cmd_type_len =			cpu_to_le32(IXGB_CONTEXT_DESC_TYPE				    | IXGB_TX_DESC_CMD_IDE);		if(++i == adapter->tx_ring.count) i = 0;		adapter->tx_ring.next_to_use = i;		return TRUE;	}	return FALSE;}#define IXGB_MAX_TXD_PWR	14#define IXGB_MAX_DATA_PER_TXD	(1<<IXGB_MAX_TXD_PWR)static inline intixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,	    unsigned int first){	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;	struct ixgb_buffer *buffer_info;	int len = skb->len;	unsigned int offset = 0, size, count = 0, i;	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;	unsigned int f;	len -= skb->data_len;	i = tx_ring->next_to_use;	while(len) {		buffer_info = &tx_ring->buffer_info[i];		size = min(len, IXGB_MAX_JUMBO_FRAME_SIZE);		buffer_info->length = size;		buffer_info->dma =			pci_map_single(adapter->pdev,				skb->data + offset,				size,				PCI_DMA_TODEVICE);		buffer_info->time_stamp = jiffies;		len -= size;		offset += size;		count++;		if(++i == tx_ring->count) i = 0;	}	for(f = 0; f < nr_frags; f++) {		struct skb_frag_struct *frag;		frag = &skb_shinfo(skb)->frags[f];		len = frag->size;		offset = 0;		while(len) {			buffer_info = &tx_ring->buffer_info[i];			size = min(len, IXGB_MAX_JUMBO_FRAME_SIZE);			buffer_info->length = size;			buffer_info->dma =				pci_map_page(adapter->pdev,					frag->page,					frag->page_offset + offset,					size,					PCI_DMA_TODEVICE);			buffer_info->time_stamp = jiffies;			len -= size;			offset += size;			count++;			if(++i == tx_ring->count) i = 0;		}	}	i = (i == 0) ? tx_ring->count - 1 : i - 1;	tx_ring->buffer_info[i].skb = skb;	tx_ring->buffer_info[first].next_to_watch = i;	return count;}static inline voidixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags){	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;	struct ixgb_tx_desc *tx_desc = NULL;	struct ixgb_buffer *buffer_info;	uint32_t cmd_type_len = adapter->tx_cmd_type;	uint8_t status = 0;	uint8_t popts = 0;	unsigned int i;	if(tx_flags & IXGB_TX_FLAGS_TSO) {		cmd_type_len |= IXGB_TX_DESC_CMD_TSE;		popts |= (IXGB_TX_DESC_POPTS_IXSM | IXGB_TX_DESC_POPTS_TXSM);	}	if(tx_flags & IXGB_TX_FLAGS_CSUM)		popts |= IXGB_TX_DESC_POPTS_TXSM;	if(tx_flags & IXGB_TX_FLAGS_VLAN) {		cmd_type_len |= IXGB_TX_DESC_CMD_VLE;	}	i = tx_ring->next_to_use;	while(count--) {		buffer_info = &tx_ring->buffer_info[i];		tx_desc = IXGB_TX_DESC(*tx_ring, i);		tx_desc->buff_addr = cpu_to_le64(buffer_info->dma);		tx_desc->cmd_type_len =			cpu_to_le32(cmd_type_len | buffer_info->length);		tx_desc->status = status;		tx_desc->popts = popts;		tx_desc->vlan = cpu_to_le16(vlan_id);		if(++i == tx_ring->count) i = 0;	}	tx_desc->cmd_type_len |= cpu_to_le32(IXGB_TX_DESC_CMD_EOP 				| IXGB_TX_DESC_CMD_RS );	/* Force memory writes to complete before letting h/w	 * know there are new descriptors to fetch.  (Only	 * applicable for weak-ordered memory model archs,	 * such as IA-64). */	wmb();	tx_ring->next_to_use = i;	IXGB_WRITE_REG(&adapter->hw, TDT, i);}/* Tx Descriptors needed, worst case */#define TXD_USE_COUNT(S) (((S) >> IXGB_MAX_TXD_PWR) + \			 (((S) & (IXGB_MAX_DATA_PER_TXD - 1)) ? 1 : 0))#define DESC_NEEDED TXD_USE_COUNT(IXGB_MAX_DATA_PER_TXD) + \	MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1static intixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev){	struct ixgb_adapter *adapter = netdev_priv(netdev);	unsigned int first;	unsigned int tx_flags = 0;	unsigned long flags;	int vlan_id = 0;	int tso;	if(skb->len <= 0) {		dev_kfree_skb_any(skb);		return 0;	}	spin_lock_irqsave(&adapter->tx_lock, flags);	if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) {		netif_stop_queue(netdev);		spin_unlock_irqrestore(&adapter->tx_lock, flags);		return 1;	}	spin_unlock_irqrestore(&adapter->tx_lock, flags);	if(adapter->vlgrp && vlan_tx_tag_present(skb)) {		tx_flags |= IXGB_TX_FLAGS_VLAN;		vlan_id = vlan_tx_tag_get(skb);	}	first = adapter->tx_ring.next_to_use;		tso = ixgb_tso(adapter, skb);	if (tso < 0) {		dev_kfree_skb_any(skb);		return NETDEV_TX_OK;	}	if (tso)		tx_flags |= IXGB_TX_FLAGS_TSO;	else if(ixgb_tx_csum(adapter, skb))		tx_flags |= IXGB_TX_FLAGS_CSUM;	ixgb_tx_queue(adapter, ixgb_tx_map(adapter, skb, first), vlan_id,			tx_flags);	netdev->trans_start = jiffies;	return 0;}/** * ixgb_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure **/static voidixgb_tx_timeout(struct net_device *netdev){	struct ixgb_adapter *adapter = netdev_priv(netdev);	/* Do the reset outside of interrupt context */	schedule_work(&adapter->tx_timeout_task);}static voidixgb_tx_timeout_task(struct net_device *netdev){	struct ixgb_adapter *adapter = netdev_priv(netdev);	ixgb_down(adapter, TRUE);	ixgb_up(adapter);}/** * ixgb_get_stats - Get System Network Statistics * @netdev: network interface device structure * * Returns the address of the device statistics structure. * The statistics are actually updated from the timer callback. **/static struct net_device_stats *ixgb_get_stats(struct net_device *netdev){	struct ixgb_adapter *adapter = netdev_priv(netdev);	return &adapter->net_stats;}/** * ixgb_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure * @new_mtu: new value for maximum frame size * * Returns 0 on success, negative on failure **/static intixgb_change_mtu(struct net_device *netdev, int new_mtu){	struct ixgb_adapter *adapter = netdev_priv(netdev);	int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;	int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;	if((max_frame < IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)	   || (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {		IXGB_ERR("Invalid MTU setting\n");		return -EINVAL;	}	if((max_frame <= IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)	   || (max_frame <= IXGB_RXBUFFER_2048)) {		adapter->rx_buffer_len = IXGB_RXBUFFER_2048;	} else if(max_frame <= IXGB_RXBUFFER_4096) {		adapter->rx_buffer_len = IXGB_RXBUFFER_4096;	} else if(max_frame <= IXGB_RXBUFFER_8192) {		adapter->rx_buffer_len = IXGB_RXBUFFER_8192;	} else {		adapter->rx_buffer_len = IXGB_RXBUFFER_16384;	}	netdev->mtu = new_mtu;	if(old_max_frame != max_frame && netif_running(netdev)) {		ixgb_down(adapter, TRUE);		ixgb_up(adapter);	}	return 0;}/** * ixgb_update_stats - Update the board statistics counters. * @adapter: board private structure **/voidixgb_update_stats(struct ixgb_adapter *adapter){	struct net_device *netdev = adapter->netdev;	if((netdev->flags & IFF_PROMISC) || (netdev->flags & IFF_ALLMULTI) ||	   (netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES)) {		u64 multi = IXGB_READ_REG(&adapter->hw, MPRCL);		u32 bcast_l = IXGB_READ_REG(&adapter->hw, BPRCL);		u32 bcast_h = IXGB_READ_REG(&adapter->hw, BPRCH);		u64 bcast = ((u64)bcast_h << 32) | bcast_l; 		multi |= ((u64)IXGB_READ_REG(&adapter->hw, MPRCH) << 32);		/* fix up multicast stats by removing broadcasts */		if(multi >= bcast)			multi -= bcast;				adapter->stats.mprcl += (multi & 0xFFFFFFFF);		adapter->stats.mprch += (multi >> 32);		adapter->stats.bprcl += bcast_l; 		adapter->stats.bprch += bcast_h;	} else {		adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL);		adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH);		adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL);		adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH);	}	adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL);	adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH);	adapter->stats.gprcl += IXGB_READ_REG(&adapter->hw, GPRCL);	adapter->stats.gprch += IXGB_READ_REG(&adapter->hw, GPRCH);	adapter->stats.uprcl += IXGB_READ_REG(&adapter->hw, UPRCL);	adapter->stats.uprch += IXGB_READ_REG(&adapter->hw, UPRCH);	adapter->stats.vprcl += IXGB_READ_REG(&adapter->hw, VPRCL);	adapter->stats.vprch += IXGB_READ_REG(&adapter->hw, VPRCH);	adapter->stats.jprcl += IXGB_READ_REG(&adapter->hw, JPRCL);	adapter->stats.jprch += IXGB_READ_REG(&adapter->hw, JPRCH);	adapter->stats.gorcl += IXGB_READ_REG(&adapter->hw, GORCL);	adapter->stats.gorch += IXGB_READ_REG(&adapter->hw, GORCH);	adapter->stats.torl += IXGB_READ_REG(&adapter->hw, TORL);	adapter->stats.torh += IXGB_READ_REG(&adapter->hw, TORH);	adapter->stats.rnbc += IXGB_READ_REG(&adapter->hw, RNBC);	adapter->stats.ruc += IXGB_READ_REG(&adapter->hw, RUC);	adapter->stats.roc += IXGB_READ_REG(&adapter->hw, ROC);	adapter->stats.rlec += IXGB_READ_REG(&adapter->hw, RLEC);	adapter->stats.crcerrs += IXGB_READ_REG(&adapter->hw, CRCERRS);	adapter->stats.icbc += IXGB_READ_REG(&adapter->hw, ICBC);	adapter->stats.ecbc += IXGB_READ_REG(&adapter->hw, ECBC);	adapter->stats.mpc += IXGB_READ_REG(&adapter->hw, MPC);	adapter->stats.tptl += IXGB_READ_REG(&adapter->hw, TPTL);	adapter->stats.tpth += IXGB_READ_REG(&adapter->hw, TPTH);	adapter->stats.gptcl += IXGB_READ_REG(&adapter->hw, GPTCL);	adapter->stats.gptch += IXGB_READ_REG(&adapter->hw, GPTCH);	adapter->stats.bptcl += IXGB_READ_REG(&adapter->hw, BPTCL);	adapter->stats.bptch += IXGB_READ_REG(&adapter->hw, BPTCH);	adapter->stats.mptcl += IXGB_READ_REG(&adapter->hw, MPTCL);	adapter->stats.mptch += IXGB_READ_REG(&adapter->hw, MPTCH);	adapter->stats.uptcl += IXGB_READ_REG(&adapter->hw, UPTCL);	adapter->stats.uptch += IXGB_READ_REG(&adapter->hw, UPTCH);	adapter->stats.vptcl += IXGB_READ_REG(&adapter->hw, VPTCL);	adapter->stats.vptch += IXGB_READ_REG(&adapter->hw, VPTCH);	adapter->stats.jptcl += IXGB_READ_REG(&adapter->hw, JPTCL);	adapter->stats.jptch += IXGB_READ_REG(&adapter->hw, JPTCH);	adapter->stats.gotcl += IXGB_READ_REG(&adapter->hw, GOTCL);	adapter->stats.gotch += IXGB_READ_REG(&adapter->hw, GOTCH);	adapter->stats.totl += IXGB_READ_REG(&adapter->hw, TOTL);	adapter->stats.toth += IXGB_READ_REG(&adapter->hw, TOTH);	adapter->stats.dc += IXGB_READ_REG(&adapter->hw, DC);	adapter->stats.plt64c += IXGB_READ_REG(&adapter->hw, PLT64C);	adapter->stats.tsctc += IXGB_READ_REG(&adapter->hw, TSCTC);	adapter->stats.tsctfc += IXGB_READ_REG(&adapter->hw, TSCTFC);	adapter->stats.ibic += IXGB_READ_REG(&adapter->hw, IBIC);	adapter->stats.rfc += IXGB_READ_REG(&adapter->hw, RFC);	adapter->stats.lfc += IXGB_READ_REG(&adapter->hw, LFC);	adapter->stats.pfrc += IXGB_READ_REG(&adapter->hw, PFRC);	adapter->stats.pftc += IXGB_READ_REG(&adapter->hw, PFTC);	adapter->stats.mcfrc += IXGB_READ_REG(&adapter->hw, MCFRC);	adapter->stats.mcftc += IXGB_READ_REG(&adapter->hw, MCFTC);	adapter->stats.xonrxc += IXGB_READ_REG(&adapter->hw, XONRXC);	adapter->stats.xontxc += IXGB_READ_REG(&adapter->hw, XONTXC);	adapter->stats.xoffrxc += IXGB_READ_REG(&adapter->hw, XOFFRXC);	adapter->stats.xofftxc += IXGB_READ_REG(&adapter->hw, XOFFTXC);

⌨️ 快捷键说明

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