📄 e1000_main.c
字号:
skb = rx_ring->buffer_info[i].skb; length = le16_to_cpu(rx_desc->length); if(!(rx_desc->status & E1000_RXD_STAT_EOP)) { /* All receives must fit into a single buffer */ E1000_DBG("Receive packet consumed multiple buffers\n"); dev_kfree_skb_irq(skb); rx_desc->status = 0; rx_ring->buffer_info[i].skb = NULL; i = (i + 1) % rx_ring->count; rx_desc = E1000_RX_DESC(*rx_ring, i); continue; } if(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) { last_byte = *(skb->data + length - 1); if(TBI_ACCEPT(&adapter->hw, rx_desc->status, rx_desc->errors, length, last_byte)) { spin_lock_irqsave(&adapter->stats_lock, flags); e1000_tbi_adjust_stats(&adapter->hw, &adapter->stats, length, skb->data); spin_unlock_irqrestore(&adapter->stats_lock, flags); length--; } else { dev_kfree_skb_irq(skb); rx_desc->status = 0; rx_ring->buffer_info[i].skb = NULL; i = (i + 1) % rx_ring->count; rx_desc = E1000_RX_DESC(*rx_ring, i); continue; } } /* Good Receive */ skb_put(skb, length - ETHERNET_FCS_SIZE); /* Receive Checksum Offload */ e1000_rx_checksum(adapter, rx_desc, skb); skb->protocol = eth_type_trans(skb, netdev); if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { vlan_hwaccel_rx(skb, adapter->vlgrp, (rx_desc->special & E1000_RXD_SPC_VLAN_MASK)); } else { netif_rx(skb); } netdev->last_rx = jiffies; rx_desc->status = 0; rx_ring->buffer_info[i].skb = NULL; i = (i + 1) % rx_ring->count; rx_desc = E1000_RX_DESC(*rx_ring, i); } rx_ring->next_to_clean = i; e1000_alloc_rx_buffers(adapter);}/** * e1000_alloc_rx_buffers - Replace used receive buffers * @data: address of board private structure **/static voide1000_alloc_rx_buffers(struct e1000_adapter *adapter){ struct e1000_desc_ring *rx_ring = &adapter->rx_ring; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; struct e1000_rx_desc *rx_desc; struct sk_buff *skb; int reserve_len; int i; reserve_len = 2; i = rx_ring->next_to_use; while(!rx_ring->buffer_info[i].skb) { rx_desc = E1000_RX_DESC(*rx_ring, i); skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len); if(!skb) { /* Better luck next round */ 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, reserve_len); skb->dev = netdev; rx_ring->buffer_info[i].skb = skb; rx_ring->buffer_info[i].length = adapter->rx_buffer_len; rx_ring->buffer_info[i].dma = pci_map_single(pdev, skb->data, adapter->rx_buffer_len, PCI_DMA_FROMDEVICE); rx_desc->buffer_addr = cpu_to_le64(rx_ring->buffer_info[i].dma); if(!(i % E1000_RX_BUFFER_WRITE)) { /* 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(); E1000_WRITE_REG(&adapter->hw, RDT, i); } i = (i + 1) % rx_ring->count; } rx_ring->next_to_use = i;}/** * e1000_ioctl - * @netdev: * @ifreq: * @cmd: **/static inte1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd){ switch (cmd) { case SIOCETHTOOL: return e1000_ethtool_ioctl(netdev, ifr); default: return -EOPNOTSUPP; }}/** * e1000_rx_checksum - Receive Checksum Offload for 82543 * @adapter: board private structure * @rx_desc: receive descriptor * @sk_buff: socket buffer with received data **/static inline voide1000_rx_checksum(struct e1000_adapter *adapter, struct e1000_rx_desc *rx_desc, struct sk_buff *skb){ /* 82543 or newer only */ if((adapter->hw.mac_type < e1000_82543) || /* Ignore Checksum bit is set */ (rx_desc->status & E1000_RXD_STAT_IXSM) || /* TCP Checksum has not been calculated */ (!(rx_desc->status & E1000_RXD_STAT_TCPCS))) { skb->ip_summed = CHECKSUM_NONE; return; } /* At this point we know the hardware did the TCP checksum */ /* now look at the TCP checksum error bit */ if(rx_desc->errors & E1000_RXD_ERR_TCPE) { /* let the stack verify checksum errors */ skb->ip_summed = CHECKSUM_NONE; adapter->hw_csum_err++; } else { /* TCP checksum is good */ skb->ip_summed = CHECKSUM_UNNECESSARY; adapter->hw_csum_good++; }}voide1000_pci_set_mwi(struct e1000_hw *hw){ struct e1000_adapter *adapter = hw->back; pci_set_mwi(adapter->pdev);}voide1000_pci_clear_mwi(struct e1000_hw *hw){ struct e1000_adapter *adapter = hw->back; pci_clear_mwi(adapter->pdev);}voide1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value){ struct e1000_adapter *adapter = hw->back; pci_read_config_word(adapter->pdev, reg, value);}voide1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value){ struct e1000_adapter *adapter = hw->back; pci_write_config_word(adapter->pdev, reg, *value);}uint32_te1000_io_read(struct e1000_hw *hw, uint32_t port){ return inl(port);}voide1000_io_write(struct e1000_hw *hw, uint32_t port, uint32_t value){ outl(value, port);}static voide1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp){ struct e1000_adapter *adapter = netdev->priv; uint32_t ctrl, rctl; e1000_irq_disable(adapter); adapter->vlgrp = grp; if(grp) { /* enable VLAN tag insert/strip */ E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE); ctrl = E1000_READ_REG(&adapter->hw, CTRL); ctrl |= E1000_CTRL_VME; E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); /* enable VLAN receive filtering */ rctl = E1000_READ_REG(&adapter->hw, RCTL); rctl |= E1000_RCTL_VFE; rctl &= ~E1000_RCTL_CFIEN; E1000_WRITE_REG(&adapter->hw, RCTL, rctl); } else { /* disable VLAN tag insert/strip */ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ctrl &= ~E1000_CTRL_VME; E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); /* disable VLAN filtering */ rctl = E1000_READ_REG(&adapter->hw, RCTL); rctl &= ~E1000_RCTL_VFE; E1000_WRITE_REG(&adapter->hw, RCTL, rctl); } e1000_irq_enable(adapter);}static voide1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid){ struct e1000_adapter *adapter = netdev->priv; uint32_t vfta, index; /* add VID to filter table */ index = (vid >> 5) & 0x7F; vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); vfta |= (1 << (vid & 0x1F)); e1000_write_vfta(&adapter->hw, index, vfta);}static voide1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid){ struct e1000_adapter *adapter = netdev->priv; uint32_t vfta, index; e1000_irq_disable(adapter); if(adapter->vlgrp) adapter->vlgrp->vlan_devices[vid] = NULL; e1000_irq_enable(adapter); /* remove VID from filter table*/ index = (vid >> 5) & 0x7F; vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); vfta &= ~(1 << (vid & 0x1F)); e1000_write_vfta(&adapter->hw, index, vfta);}static inte1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p){ struct pci_dev *pdev = NULL; switch(event) { case SYS_DOWN: case SYS_HALT: case SYS_POWER_OFF: pci_for_each_dev(pdev) { if(pci_dev_driver(pdev) == &e1000_driver) e1000_suspend(pdev, 3); } } return NOTIFY_DONE;}static inte1000_notify_netdev(struct notifier_block *nb, unsigned long event, void *p){ struct e1000_adapter *adapter; struct net_device *netdev = p; if(netdev == NULL) return NOTIFY_DONE; switch(event) { case NETDEV_CHANGENAME: if(netdev->open == e1000_open) { adapter = netdev->priv; /* rename the proc nodes the easy way */ e1000_proc_dev_free(adapter); memcpy(adapter->ifname, netdev->name, IFNAMSIZ); adapter->ifname[IFNAMSIZ-1] = 0; e1000_proc_dev_setup(adapter); } break; } return NOTIFY_DONE;}static inte1000_suspend(struct pci_dev *pdev, uint32_t state){ struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev->priv; uint32_t ctrl, ctrl_ext, rctl, manc; netif_device_detach(netdev); if(netif_running(netdev)) e1000_down(adapter); if(adapter->wol) { e1000_setup_rctl(adapter); e1000_set_multi(netdev); /* turn on all-multi mode if wake on multicast is enabled */ if(adapter->wol & E1000_WUFC_MC) { rctl = E1000_READ_REG(&adapter->hw, RCTL); rctl |= E1000_RCTL_MPE; E1000_WRITE_REG(&adapter->hw, RCTL, rctl); } if(adapter->hw.mac_type >= e1000_82540) { ctrl = E1000_READ_REG(&adapter->hw, CTRL); /* advertise wake from D3Cold */ #define E1000_CTRL_ADVD3WUC 0x00100000 /* phy power management enable */ #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 ctrl |= E1000_CTRL_ADVD3WUC | E1000_CTRL_EN_PHY_PWR_MGMT; E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); } if(adapter->hw.media_type == e1000_media_type_fiber) { /* keep the laser running in D3 */ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext); } E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN); E1000_WRITE_REG(&adapter->hw, WUFC, adapter->wol); pci_enable_wake(pdev, 3, 1); pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */ } else { E1000_WRITE_REG(&adapter->hw, WUC, 0); E1000_WRITE_REG(&adapter->hw, WUFC, 0); pci_enable_wake(pdev, 3, 0); pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */ } pci_save_state(pdev, adapter->pci_state); if(adapter->hw.mac_type >= e1000_82540) { manc = E1000_READ_REG(&adapter->hw, MANC); if(manc & E1000_MANC_SMBUS_EN) { manc |= E1000_MANC_ARP_EN; E1000_WRITE_REG(&adapter->hw, MANC, manc); state = 0; } } state = (state > 0) ? 3 : 0; pci_set_power_state(pdev, state); return 0;}#ifdef CONFIG_PMstatic inte1000_resume(struct pci_dev *pdev){ struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev->priv; uint32_t manc; pci_set_power_state(pdev, 0); pci_restore_state(pdev, adapter->pci_state); pci_enable_wake(pdev, 3, 0); pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */ e1000_reset(adapter); E1000_WRITE_REG(&adapter->hw, WUS, ~0); if(netif_running(netdev)) e1000_up(adapter); netif_device_attach(netdev); if(adapter->hw.mac_type >= e1000_82540) { manc = E1000_READ_REG(&adapter->hw, MANC); manc &= ~(E1000_MANC_ARP_EN); E1000_WRITE_REG(&adapter->hw, MANC, manc); } return 0;}#endif/* e1000_main.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -