📄 e1000_main.c
字号:
context_desc->cmd_and_length = cpu_to_le32(adapter->txd_cmd | E1000_TXD_CMD_DEXT); i = (i + 1) % adapter->tx_ring.count; adapter->tx_ring.next_to_use = i; return TRUE; } return FALSE;}static inline inte1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb){ struct e1000_desc_ring *tx_ring = &adapter->tx_ring; int len, offset, size, count, i;#ifdef MAX_SKB_FRAGS int f; len = skb->len - skb->data_len;#else len = skb->len;#endif i = (tx_ring->next_to_use + tx_ring->count - 1) % tx_ring->count; count = 0; offset = 0; while(len) { i = (i + 1) % tx_ring->count; size = min(len, adapter->max_data_per_txd); tx_ring->buffer_info[i].length = size; tx_ring->buffer_info[i].dma = pci_map_single(adapter->pdev, skb->data + offset, size, PCI_DMA_TODEVICE); tx_ring->buffer_info[i].time_stamp = jiffies; len -= size; offset += size; count++; }#ifdef MAX_SKB_FRAGS for(f = 0; f < skb_shinfo(skb)->nr_frags; f++) { struct skb_frag_struct *frag; frag = &skb_shinfo(skb)->frags[f]; len = frag->size; offset = 0; while(len) { i = (i + 1) % tx_ring->count; size = min(len, adapter->max_data_per_txd); tx_ring->buffer_info[i].length = size; tx_ring->buffer_info[i].dma = pci_map_page(adapter->pdev, frag->page, frag->page_offset + offset, size, PCI_DMA_TODEVICE); len -= size; offset += size; count++; } }#endif tx_ring->buffer_info[i].skb = skb; return count;}static inline voide1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags){ struct e1000_desc_ring *tx_ring = &adapter->tx_ring; struct e1000_tx_desc *tx_desc = NULL; uint32_t txd_upper, txd_lower; int i; txd_upper = 0; txd_lower = adapter->txd_cmd; if(tx_flags & E1000_TX_FLAGS_CSUM) { txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; txd_upper |= E1000_TXD_POPTS_TXSM << 8; } if(tx_flags & E1000_TX_FLAGS_VLAN) { txd_lower |= E1000_TXD_CMD_VLE; txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); } i = tx_ring->next_to_use; while(count--) { tx_desc = E1000_TX_DESC(*tx_ring, i); tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma); tx_desc->lower.data = cpu_to_le32(txd_lower | tx_ring->buffer_info[i].length); tx_desc->upper.data = cpu_to_le32(txd_upper); i = (i + 1) % tx_ring->count; } tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP); /* 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; E1000_WRITE_REG(&adapter->hw, TDT, i);}#define TXD_USE_COUNT(S, X) (((S) / (X)) + (((S) % (X)) ? 1 : 0))#ifdef IANS#define ANS_XMIT_FULL() do { \ iANSsupport_t *ans = adapter->iANSdata; \ if((ans->iANS_status == IANS_COMMUNICATION_UP) && \ (ans->reporting_mode == IANS_STATUS_REPORTING_ON) && \ (ans_notify)) \ ans_notify(netdev, IANS_IND_XMIT_QUEUE_FULL); \} while (0)#endifstatic inte1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev){ struct e1000_adapter *adapter = netdev->priv; int tx_flags = 0, count;#ifdef MAX_SKB_FRAGS int f;#endif if(!netif_carrier_ok(netdev)) { netif_stop_queue(netdev);#ifdef IANS ANS_XMIT_FULL();#endif return 1; }#ifdef MAX_SKB_FRAGS count = TXD_USE_COUNT(skb->len - skb->data_len, adapter->max_data_per_txd); for(f = 0; f < skb_shinfo(skb)->nr_frags; f++) count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size, adapter->max_data_per_txd); if(skb->ip_summed == CHECKSUM_HW) count++;#else count = TXD_USE_COUNT(skb->len, adapter->max_data_per_txd);#endif if(E1000_DESC_UNUSED(&adapter->tx_ring) < count) { netif_stop_queue(netdev);#ifdef IANS ANS_XMIT_FULL();#endif return 1; } if(e1000_tx_csum(adapter, skb)) tx_flags |= E1000_TX_FLAGS_CSUM;#ifdef IANSif(adapter->iANSdata->iANS_status == IANS_COMMUNICATION_UP) { struct e1000_tx_desc *tx_desc; tx_desc = E1000_TX_DESC(adapter->tx_ring, adapter->tx_ring.next_to_use); if(bd_ans_os_Transmit(adapter, tx_desc, &skb) == BD_ANS_FAILURE) return 1; if(tx_desc->lower.data & E1000_TXD_CMD_VLE) { tx_flags |= E1000_TX_FLAGS_VLAN; tx_flags |= (tx_desc->upper.data & E1000_TX_FLAGS_VLAN_MASK); }}#endif#ifdef NETIF_F_HW_VLAN_TX if(adapter->vlgrp && vlan_tx_tag_present(skb)) { tx_flags |= E1000_TX_FLAGS_VLAN; tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); }#endif count = e1000_tx_map(adapter, skb); e1000_tx_queue(adapter, count, tx_flags); netdev->trans_start = jiffies; return 0;}#ifdef HAVE_TX_TIMEOUT/** * e1000_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure **/static voide1000_tx_timeout(struct net_device *netdev){ struct e1000_adapter *adapter = netdev->priv; e1000_down(adapter);#ifdef IANS if((adapter->iANSdata->iANS_status == IANS_COMMUNICATION_UP) && (adapter->iANSdata->reporting_mode == IANS_STATUS_REPORTING_ON)) { netif_carrier_off(netdev); bd_ans_os_Watchdog(netdev, adapter); netif_carrier_on(netdev); }#endif e1000_up(adapter);}#endif/** * e1000_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 *e1000_get_stats(struct net_device *netdev){ struct e1000_adapter *adapter = netdev->priv; return &adapter->net_stats;}/** * e1000_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 inte1000_change_mtu(struct net_device *netdev, int new_mtu){ struct e1000_adapter *adapter = netdev->priv; int old_mtu = adapter->rx_buffer_len; int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || (max_frame > MAX_JUMBO_FRAME_SIZE)) { E1000_ERR("Invalid MTU setting\n"); return -EINVAL; } if(max_frame <= MAXIMUM_ETHERNET_FRAME_SIZE) { adapter->rx_buffer_len = E1000_RXBUFFER_2048; } else if(adapter->hw.mac_type < e1000_82543) { E1000_ERR("Jumbo Frames not supported on 82542\n"); return -EINVAL; } else if(max_frame <= E1000_RXBUFFER_4096) { adapter->rx_buffer_len = E1000_RXBUFFER_4096; } else if(max_frame <= E1000_RXBUFFER_8192) { adapter->rx_buffer_len = E1000_RXBUFFER_8192; } else { adapter->rx_buffer_len = E1000_RXBUFFER_16384; } if(old_mtu != adapter->rx_buffer_len && netif_running(netdev)) { e1000_down(adapter); e1000_up(adapter); } netdev->mtu = new_mtu; adapter->hw.max_frame_size = max_frame; return 0;}/** * e1000_update_stats - Update the board statistics counters * @adapter: board private structure **/static voide1000_update_stats(struct e1000_adapter *adapter){ struct e1000_hw *hw = &adapter->hw; unsigned long flags; uint16_t phy_tmp;#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF spin_lock_irqsave(&adapter->stats_lock, flags); /* these counters are modified from e1000_adjust_tbi_stats, * called from the interrupt context, so they must only * be written while holding adapter->stats_lock */ adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS); adapter->stats.gprc += E1000_READ_REG(hw, GPRC); adapter->stats.gorcl += E1000_READ_REG(hw, GORCL); adapter->stats.gorch += E1000_READ_REG(hw, GORCH); adapter->stats.bprc += E1000_READ_REG(hw, BPRC); adapter->stats.mprc += E1000_READ_REG(hw, MPRC); adapter->stats.roc += E1000_READ_REG(hw, ROC); adapter->stats.prc64 += E1000_READ_REG(hw, PRC64); adapter->stats.prc127 += E1000_READ_REG(hw, PRC127); adapter->stats.prc255 += E1000_READ_REG(hw, PRC255); adapter->stats.prc511 += E1000_READ_REG(hw, PRC511); adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023); adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522); spin_unlock_irqrestore(&adapter->stats_lock, flags); /* the rest of the counters are only modified here */ adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS); adapter->stats.mpc += E1000_READ_REG(hw, MPC); adapter->stats.scc += E1000_READ_REG(hw, SCC); adapter->stats.ecol += E1000_READ_REG(hw, ECOL); adapter->stats.mcc += E1000_READ_REG(hw, MCC); adapter->stats.latecol += E1000_READ_REG(hw, LATECOL); adapter->stats.dc += E1000_READ_REG(hw, DC); adapter->stats.sec += E1000_READ_REG(hw, SEC); adapter->stats.rlec += E1000_READ_REG(hw, RLEC); adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC); adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC); adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC); adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC); adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC); adapter->stats.gptc += E1000_READ_REG(hw, GPTC); adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL); adapter->stats.gotch += E1000_READ_REG(hw, GOTCH); adapter->stats.rnbc += E1000_READ_REG(hw, RNBC); adapter->stats.ruc += E1000_READ_REG(hw, RUC); adapter->stats.rfc += E1000_READ_REG(hw, RFC); adapter->stats.rjc += E1000_READ_REG(hw, RJC); adapter->stats.torl += E1000_READ_REG(hw, TORL); adapter->stats.torh += E1000_READ_REG(hw, TORH); adapter->stats.totl += E1000_READ_REG(hw, TOTL); adapter->stats.toth += E1000_READ_REG(hw, TOTH); adapter->stats.tpr += E1000_READ_REG(hw, TPR); adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64); adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127); adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255); adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511); adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023); adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522); adapter->stats.mptc += E1000_READ_REG(hw, MPTC); adapter->stats.bptc += E1000_READ_REG(hw, BPTC); /* used for adaptive IFS */ hw->tx_packet_delta = E1000_READ_REG(hw, TPT); adapter->stats.tpt += hw->tx_packet_delta; hw->collision_delta = E1000_READ_REG(hw, COLC); adapter->stats.colc += hw->collision_delta; if(hw->mac_type >= e1000_82543) { adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC); adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC); adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS); adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR); adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC); adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC); } /* Fill out the OS statistics structure */ adapter->net_stats.rx_packets = adapter->stats.gprc; adapter->net_stats.tx_packets = adapter->stats.gptc; adapter->net_stats.rx_bytes = adapter->stats.gorcl; adapter->net_stats.tx_bytes = adapter->stats.gotcl; adapter->net_stats.multicast = adapter->stats.mprc; adapter->net_stats.collisions = adapter->stats.colc; /* Rx Errors */ adapter->net_stats.rx_errors = adapter->stats.rxerrc + adapter->stats.crcerrs + adapter->stats.algnerrc + adapter->stats.rlec + adapter->stats.rnbc + adapter->stats.mpc + adapter->stats.cexterr; adapter->net_stats.rx_dropped = adapter->stats.rnbc; adapter->net_stats.rx_length_errors = adapter->stats.rlec; adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; adapter->net_stats.rx_fifo_errors = adapter->stats.mpc; adapter->net_stats.rx_missed_errors = adapter->stats.mpc; /* Tx Errors */ adapter->net_stats.tx_errors = adapter->stats.ecol + adapter->stats.latecol; adapter->net_stats.tx_aborted_errors = adapter->stats.ecol; adapter->net_stats.tx_window_errors = adapter->stats.latecol; /* Tx Dropped needs to be maintained elsewhere */ /* Phy Stats */ if(hw->media_type == e1000_media_type_copper) { if((adapter->link_speed == SPEED_1000) && (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; adapter->phy_stats.idle_errors += phy_tmp; } if(!e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp)) adapter->phy_stats.receive_errors += phy_tmp; }}/** * e1000_irq_disable - Mask off interrupt generation on the NIC * @adapter: board private structure **/static inline voide1000_irq_disable(struct e1000_adapter *adapter){ atomic_inc(&adapter->irq_sem); E1000_WRITE_REG(&adapter->hw, IMC, ~0); E1000_WRITE_FLUSH(&adapter->hw); synchronize_irq();}/** * e1000_irq_enable - Enable default interrupt generation settings * @adapter: board private structure **/static inline voide1000_irq_enable(struct e1000_adapter *adapter){ if(atomic_dec_and_test(&adapter->irq_sem)) { E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK); E1000_WRITE_FLUSH(&adapter->hw); }}/** * e1000_intr - Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure * @pt_regs: CPU registers structure **/static voide1000_intr(int irq, void *data, struct pt_regs *regs){ struct net_device *netdev = data; struct e1000_adapter *adapter = netdev->priv; uint32_t icr; int i = E1000_MAX_INTR; while(i && (icr = E1000_READ_REG(&adapter->hw, ICR))) { if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { adapter->hw.get_link_status = 1; mod_timer(&adapter->watchdog_timer, jiffies); } /* 26.Jun.2004 - Do not print a message if we get an interrupt in polling mode. Andy Van Maele reports that e1000 adapters can share interrupts with other devices, such as other network cards. Thus, it is not necessarily a problem if we get an interrupt; and printing a message is very expensive. So scrap it. It might be better to keep a counter. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -