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

📄 atl1_main.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (atl1_rcb_128 == hw->rcb_value)		value |= DMA_CTRL_RCB_VALUE;	iowrite32(value, hw->hw_addr + REG_DMA_CTRL);	/* config CMB / SMB */	value = (hw->cmb_tpd > adapter->tpd_ring.count) ?		hw->cmb_tpd : adapter->tpd_ring.count;	value <<= 16;	value |= hw->cmb_rrd;	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);	value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);	iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);	/* --- enable CMB / SMB */	value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;	iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);	value = ioread32(adapter->hw.hw_addr + REG_ISR);	if (unlikely((value & ISR_PHY_LINKDOWN) != 0))		value = 1;	/* config failed */	else		value = 0;	/* clear all interrupt status */	iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);	iowrite32(0, adapter->hw.hw_addr + REG_ISR);	return value;}/* * atl1_pcie_patch - Patch for PCIE module */static void atl1_pcie_patch(struct atl1_adapter *adapter){	u32 value;	/* much vendor magic here */	value = 0x6500;	iowrite32(value, adapter->hw.hw_addr + 0x12FC);	/* pcie flow control mode change */	value = ioread32(adapter->hw.hw_addr + 0x1008);	value |= 0x8000;	iowrite32(value, adapter->hw.hw_addr + 0x1008);}/* * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400 * on PCI Command register is disable. * The function enable this bit. * Brackett, 2006/03/15 */static void atl1_via_workaround(struct atl1_adapter *adapter){	unsigned long value;	value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);	if (value & PCI_COMMAND_INTX_DISABLE)		value &= ~PCI_COMMAND_INTX_DISABLE;	iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);}/* * atl1_irq_enable - Enable default interrupt generation settings * @adapter: board private structure */static void atl1_irq_enable(struct atl1_adapter *adapter){	iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);	ioread32(adapter->hw.hw_addr + REG_IMR);}/* * atl1_irq_disable - Mask off interrupt generation on the NIC * @adapter: board private structure */static void atl1_irq_disable(struct atl1_adapter *adapter){	iowrite32(0, adapter->hw.hw_addr + REG_IMR);	ioread32(adapter->hw.hw_addr + REG_IMR);	synchronize_irq(adapter->pdev->irq);}static void atl1_clear_phy_int(struct atl1_adapter *adapter){	u16 phy_data;	unsigned long flags;	spin_lock_irqsave(&adapter->lock, flags);	atl1_read_phy_reg(&adapter->hw, 19, &phy_data);	spin_unlock_irqrestore(&adapter->lock, flags);}static void atl1_inc_smb(struct atl1_adapter *adapter){	struct stats_msg_block *smb = adapter->smb.smb;	/* Fill out the OS statistics structure */	adapter->soft_stats.rx_packets += smb->rx_ok;	adapter->soft_stats.tx_packets += smb->tx_ok;	adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;	adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;	adapter->soft_stats.multicast += smb->rx_mcast;	adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 +		smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry);	/* Rx Errors */	adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err +		smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov +		smb->rx_rrd_ov + smb->rx_align_err);	adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;	adapter->soft_stats.rx_length_errors += smb->rx_len_err;	adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;	adapter->soft_stats.rx_frame_errors += smb->rx_align_err;	adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +		smb->rx_rxf_ov);	adapter->soft_stats.rx_pause += smb->rx_pause;	adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;	adapter->soft_stats.rx_trunc += smb->rx_sz_ov;	/* Tx Errors */	adapter->soft_stats.tx_errors += (smb->tx_late_col +		smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc);	adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;	adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;	adapter->soft_stats.tx_window_errors += smb->tx_late_col;	adapter->soft_stats.excecol += smb->tx_abort_col;	adapter->soft_stats.deffer += smb->tx_defer;	adapter->soft_stats.scc += smb->tx_1_col;	adapter->soft_stats.mcc += smb->tx_2_col;	adapter->soft_stats.latecol += smb->tx_late_col;	adapter->soft_stats.tx_underun += smb->tx_underrun;	adapter->soft_stats.tx_trunc += smb->tx_trunc;	adapter->soft_stats.tx_pause += smb->tx_pause;	adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets;	adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets;	adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes;	adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes;	adapter->net_stats.multicast = adapter->soft_stats.multicast;	adapter->net_stats.collisions = adapter->soft_stats.collisions;	adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;	adapter->net_stats.rx_over_errors =		adapter->soft_stats.rx_missed_errors;	adapter->net_stats.rx_length_errors =		adapter->soft_stats.rx_length_errors;	adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;	adapter->net_stats.rx_frame_errors =		adapter->soft_stats.rx_frame_errors;	adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;	adapter->net_stats.rx_missed_errors =		adapter->soft_stats.rx_missed_errors;	adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;	adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;	adapter->net_stats.tx_aborted_errors =		adapter->soft_stats.tx_aborted_errors;	adapter->net_stats.tx_window_errors =		adapter->soft_stats.tx_window_errors;	adapter->net_stats.tx_carrier_errors =		adapter->soft_stats.tx_carrier_errors;}/* * atl1_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 *atl1_get_stats(struct net_device *netdev){	struct atl1_adapter *adapter = netdev_priv(netdev);	return &adapter->net_stats;}static void atl1_update_mailbox(struct atl1_adapter *adapter){	unsigned long flags;	u32 tpd_next_to_use;	u32 rfd_next_to_use;	u32 rrd_next_to_clean;	u32 value;	spin_lock_irqsave(&adapter->mb_lock, flags);	tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);	rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);	rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);	value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<		MB_RFD_PROD_INDX_SHIFT) |		((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<		MB_RRD_CONS_INDX_SHIFT) |		((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<		MB_TPD_PROD_INDX_SHIFT);	iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);	spin_unlock_irqrestore(&adapter->mb_lock, flags);}static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,	struct rx_return_desc *rrd, u16 offset){	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;	while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) {		rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0;		if (++rfd_ring->next_to_clean == rfd_ring->count) {			rfd_ring->next_to_clean = 0;		}	}}static void atl1_update_rfd_index(struct atl1_adapter *adapter,	struct rx_return_desc *rrd){	u16 num_buf;	num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) /		adapter->rx_buffer_len;	if (rrd->num_buf == num_buf)		/* clean alloc flag for bad rrd */		atl1_clean_alloc_flag(adapter, rrd, num_buf);}static void atl1_rx_checksum(struct atl1_adapter *adapter,	struct rx_return_desc *rrd, struct sk_buff *skb){	struct pci_dev *pdev = adapter->pdev;	skb->ip_summed = CHECKSUM_NONE;	if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {		if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |					ERR_FLAG_CODE | ERR_FLAG_OV)) {			adapter->hw_csum_err++;			dev_printk(KERN_DEBUG, &pdev->dev,				"rx checksum error\n");			return;		}	}	/* not IPv4 */	if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))		/* checksum is invalid, but it's not an IPv4 pkt, so ok */		return;	/* IPv4 packet */	if (likely(!(rrd->err_flg &		(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {		skb->ip_summed = CHECKSUM_UNNECESSARY;		adapter->hw_csum_good++;		return;	}	/* IPv4, but hardware thinks its checksum is wrong */	dev_printk(KERN_DEBUG, &pdev->dev,		"hw csum wrong, pkt_flag:%x, err_flag:%x\n",		rrd->pkt_flg, rrd->err_flg);	skb->ip_summed = CHECKSUM_COMPLETE;	skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum);	adapter->hw_csum_err++;	return;}/* * atl1_alloc_rx_buffers - Replace used receive buffers * @adapter: address of board private structure */static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter){	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;	struct pci_dev *pdev = adapter->pdev;	struct page *page;	unsigned long offset;	struct atl1_buffer *buffer_info, *next_info;	struct sk_buff *skb;	u16 num_alloc = 0;	u16 rfd_next_to_use, next_next;	struct rx_free_desc *rfd_desc;	next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use);	if (++next_next == rfd_ring->count)		next_next = 0;	buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];	next_info = &rfd_ring->buffer_info[next_next];	while (!buffer_info->alloced && !next_info->alloced) {		if (buffer_info->skb) {			buffer_info->alloced = 1;			goto next;		}		rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);		skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);		if (unlikely(!skb)) {	/* Better luck next round */			adapter->net_stats.rx_dropped++;			break;		}		/*		 * Make buffer alignment 2 beyond a 16 byte boundary		 * this will result in a 16 byte aligned IP header after		 * the 14 byte MAC header is removed		 */		skb_reserve(skb, NET_IP_ALIGN);		buffer_info->alloced = 1;		buffer_info->skb = skb;		buffer_info->length = (u16) adapter->rx_buffer_len;		page = virt_to_page(skb->data);		offset = (unsigned long)skb->data & ~PAGE_MASK;		buffer_info->dma = pci_map_page(pdev, page, offset,						adapter->rx_buffer_len,						PCI_DMA_FROMDEVICE);		rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);		rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);		rfd_desc->coalese = 0;next:		rfd_next_to_use = next_next;		if (unlikely(++next_next == rfd_ring->count))			next_next = 0;		buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];		next_info = &rfd_ring->buffer_info[next_next];		num_alloc++;	}	if (num_alloc) {		/*		 * 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();		atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);	}	return num_alloc;}static void atl1_intr_rx(struct atl1_adapter *adapter){	int i, count;	u16 length;	u16 rrd_next_to_clean;	u32 value;	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;	struct atl1_buffer *buffer_info;	struct rx_return_desc *rrd;	struct sk_buff *skb;	count = 0;	rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);	while (1) {		rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);		i = 1;		if (likely(rrd->xsz.valid)) {	/* packet valid */chk_rrd:			/* check rrd status */			if (likely(rrd->num_buf == 1))				goto rrd_ok;			/* rrd seems to be bad */			if (unlikely(i-- > 0)) {				/* rrd may not be DMAed completely */				dev_printk(KERN_DEBUG, &adapter->pdev->dev,					"incomplete RRD DMA transfer\n");				udelay(1);				goto chk_rrd;			}			/* bad rrd */			dev_printk(KERN_DEBUG, &adapter->pdev->dev,				"bad RRD\n");			/* see if update RFD index */			if (rrd->num_buf > 1)				atl1_update_rfd_index(adapter, rrd);			/* update rrd */			rrd->xsz.valid = 0;			if (++rrd_next_to_clean == rrd_ring->count)				rrd_next_to_clean = 0;			count++;			continue;		} else {	/* current rrd still not be updated */			break;		}rrd_ok:		/* clean alloc flag for bad rrd */		atl1_clean_alloc_flag(adapter, rrd, 0);		buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];		if (++rfd_ring->next_to_clean == rfd_ring->count)			rfd_ring->next_to_clean = 0;		/* update rrd next to clean */		if (++rrd_next_to_clean == rrd_ring->count)			rrd_next_to_clean = 0;		count++;		if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {			if (!(rrd->err_flg &				(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM				| ERR_FLAG_LEN))) {				/* packet error, don't need upstream */				buffer_info->alloced = 0;				rrd->xsz.valid = 0;				continue;			}		}		/* Good Receive */		pci_unmap_page(adapter->pdev, buffer_info->dma,			       buffer_info->length, PCI_DMA_FROMDEVICE);		skb = buffer_info->skb;		length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);		skb_put(skb, length - ETH_FCS_LEN);		/* Receive Checksum Offload */		atl1_rx_checksum(adapter, rrd, skb);		skb->protocol = eth_type_trans(skb, adapter->netdev);		if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) {			u16 vlan_tag = (rrd->vlan_tag >> 4) |					((rrd->vlan_tag & 7) << 13) |					((rrd->vlan_tag & 8) << 9);			vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);		} else			netif_rx(skb);		/* let protocol layer free skb */		buffer_info->skb = NULL;		buffer_info->alloced = 0;		rrd->xsz.valid = 0;		adapter->netdev->last_rx = jiffies;	}	atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);	atl1_alloc_rx_buffers(adapter);	/* update mailbox ? */	if (count) {		u32 tpd_next_to_use;		u32 rfd_next_to_use;		spin_lock(&adapter->mb_lock);

⌨️ 快捷键说明

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