diff -Ncr linux-2.4.22-old/drivers/net/e1000/e1000.h linux-2.4.22/drivers/net/e1000/e1000.h *** linux-2.4.22-old/drivers/net/e1000/e1000.h 2003-11-18 17:22:41.000000000 +0900 --- linux-2.4.22/drivers/net/e1000/e1000.h 2003-08-25 20:44:42.000000000 +0900 *************** *** 63,68 **** --- 63,71 ---- #include #include #include + #ifdef NETIF_F_TSO + #include + #endif #include #include #include *************** *** 131,136 **** --- 134,140 ---- uint64_t dma; unsigned long length; unsigned long time_stamp; + unsigned int next_to_watch; }; struct e1000_desc_ring { *************** *** 166,172 **** struct timer_list watchdog_timer; struct timer_list phy_info_timer; struct vlan_group *vlgrp; - char *id_string; uint32_t bd_number; uint32_t rx_buffer_len; uint32_t part_num; --- 170,175 ---- *************** *** 215,223 **** struct e1000_phy_info phy_info; struct e1000_phy_stats phy_stats; uint32_t pci_state[16]; - char ifname[IFNAMSIZ]; }; #endif /* _E1000_H_ */ --- 218,228 ---- struct e1000_phy_info phy_info; struct e1000_phy_stats phy_stats; + uint32_t test_icr; + struct e1000_desc_ring test_tx_ring; + struct e1000_desc_ring test_rx_ring; uint32_t pci_state[16]; }; #endif /* _E1000_H_ */ diff -Ncr linux-2.4.22-old/drivers/net/e1000/e1000_ethtool.c linux-2.4.22/drivers/net/e1000/e1000_ethtool.c *** linux-2.4.22-old/drivers/net/e1000/e1000_ethtool.c 2003-11-18 17:02:21.000000000 +0900 --- linux-2.4.22/drivers/net/e1000/e1000_ethtool.c 2003-08-25 20:44:42.000000000 +0900 *************** *** 40,54 **** extern void e1000_reset(struct e1000_adapter *adapter); extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx); ! static char e1000_gstrings_stats[][ETH_GSTRING_LEN] = { ! "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", ! "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", ! "rx_length_errors", "rx_over_errors", "rx_crc_errors", ! "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", ! "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", ! "tx_heartbeat_errors", "tx_window_errors", }; ! #define E1000_STATS_LEN sizeof(e1000_gstrings_stats) / ETH_GSTRING_LEN static void e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) --- 40,99 ---- extern void e1000_reset(struct e1000_adapter *adapter); extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx); ! struct e1000_stats { ! char stat_string[ETH_GSTRING_LEN]; ! int sizeof_stat; ! int stat_offset; }; ! ! #define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \ ! offsetof(struct e1000_adapter, m) ! static struct e1000_stats e1000_gstrings_stats[] = { ! { "rx_packets", E1000_STAT(net_stats.rx_packets) }, ! { "tx_packets", E1000_STAT(net_stats.tx_packets) }, ! { "rx_bytes", E1000_STAT(net_stats.rx_bytes) }, ! { "tx_bytes", E1000_STAT(net_stats.tx_bytes) }, ! { "rx_errors", E1000_STAT(net_stats.rx_errors) }, ! { "tx_errors", E1000_STAT(net_stats.tx_errors) }, ! { "rx_dropped", E1000_STAT(net_stats.rx_dropped) }, ! { "tx_dropped", E1000_STAT(net_stats.tx_dropped) }, ! { "multicast", E1000_STAT(net_stats.multicast) }, ! { "collisions", E1000_STAT(net_stats.collisions) }, ! { "rx_length_errors", E1000_STAT(net_stats.rx_length_errors) }, ! { "rx_over_errors", E1000_STAT(net_stats.rx_over_errors) }, ! { "rx_crc_errors", E1000_STAT(net_stats.rx_crc_errors) }, ! { "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) }, ! { "rx_fifo_errors", E1000_STAT(net_stats.rx_fifo_errors) }, ! { "rx_missed_errors", E1000_STAT(net_stats.rx_missed_errors) }, ! { "tx_aborted_errors", E1000_STAT(net_stats.tx_aborted_errors) }, ! { "tx_carrier_errors", E1000_STAT(net_stats.tx_carrier_errors) }, ! { "tx_fifo_errors", E1000_STAT(net_stats.tx_fifo_errors) }, ! { "tx_heartbeat_errors", E1000_STAT(net_stats.tx_heartbeat_errors) }, ! { "tx_window_errors", E1000_STAT(net_stats.tx_window_errors) }, ! { "tx_abort_late_coll", E1000_STAT(stats.latecol) }, ! { "tx_deferred_ok", E1000_STAT(stats.dc) }, ! { "tx_single_coll_ok", E1000_STAT(stats.scc) }, ! { "tx_multi_coll_ok", E1000_STAT(stats.mcc) }, ! { "rx_long_length_errors", E1000_STAT(stats.roc) }, ! { "rx_short_length_errors", E1000_STAT(stats.ruc) }, ! { "rx_align_errors", E1000_STAT(stats.algnerrc) }, ! { "tx_tcp_seg_good", E1000_STAT(stats.tsctc) }, ! { "tx_tcp_seg_failed", E1000_STAT(stats.tsctfc) }, ! { "rx_flow_control_xon", E1000_STAT(stats.xonrxc) }, ! { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) }, ! { "tx_flow_control_xon", E1000_STAT(stats.xontxc) }, ! { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) }, ! { "rx_csum_offload_good", E1000_STAT(hw_csum_good) }, ! { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) } ! }; ! #define E1000_STATS_LEN \ ! sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats) ! static char e1000_gstrings_test[][ETH_GSTRING_LEN] = { ! "Register test (offline)", "Eeprom test (offline)", ! "Interrupt test (offline)", "Loopback test (offline)", ! "Link test (on/offline)" ! }; ! #define E1000_TEST_LEN sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN static void e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) *************** *** 154,159 **** --- 199,205 ---- strncpy(drvinfo->fw_version, "N/A", 32); strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32); drvinfo->n_stats = E1000_STATS_LEN; + drvinfo->testinfo_len = E1000_TEST_LEN; #define E1000_REGS_LEN 32 drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t); drvinfo->eedump_len = adapter->hw.eeprom.word_size * 2; *************** *** 164,169 **** --- 210,216 ---- struct ethtool_regs *regs, uint32_t *regs_buff) { struct e1000_hw *hw = &adapter->hw; + uint16_t phy_data; regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; *************** *** 182,187 **** --- 229,290 ---- regs_buff[10] = E1000_READ_REG(hw, TDT); regs_buff[11] = E1000_READ_REG(hw, TIDV); + regs_buff[12] = adapter->hw.phy_type; /* PHY type (IGP=1, M88=0) */ + if(hw->phy_type == e1000_phy_igp) { + e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, + IGP01E1000_PHY_AGC_A); + e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A & + IGP01E1000_PHY_PAGE_SELECT, &phy_data); + regs_buff[13] = (uint32_t)phy_data; /* cable length */ + e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, + IGP01E1000_PHY_AGC_B); + e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_B & + IGP01E1000_PHY_PAGE_SELECT, &phy_data); + regs_buff[14] = (uint32_t)phy_data; /* cable length */ + e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, + IGP01E1000_PHY_AGC_C); + e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_C & + IGP01E1000_PHY_PAGE_SELECT, &phy_data); + regs_buff[15] = (uint32_t)phy_data; /* cable length */ + e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, + IGP01E1000_PHY_AGC_D); + e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_D & + IGP01E1000_PHY_PAGE_SELECT, &phy_data); + regs_buff[16] = (uint32_t)phy_data; /* cable length */ + regs_buff[17] = 0; /* extended 10bt distance (not needed) */ + e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0); + e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS & + IGP01E1000_PHY_PAGE_SELECT, &phy_data); + regs_buff[18] = (uint32_t)phy_data; /* cable polarity */ + e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, + IGP01E1000_PHY_PCS_INIT_REG); + e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG & + IGP01E1000_PHY_PAGE_SELECT, &phy_data); + regs_buff[19] = (uint32_t)phy_data; /* cable polarity */ + regs_buff[20] = 0; /* polarity correction enabled (always) */ + regs_buff[22] = 0; /* phy receive errors (unavailable) */ + regs_buff[23] = regs_buff[18]; /* mdix mode */ + e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0); + } else { + e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); + regs_buff[13] = (uint32_t)phy_data; /* cable length */ + regs_buff[14] = 0; /* Dummy (to align w/ IGP phy reg dump) */ + regs_buff[15] = 0; /* Dummy (to align w/ IGP phy reg dump) */ + regs_buff[16] = 0; /* Dummy (to align w/ IGP phy reg dump) */ + e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + regs_buff[17] = (uint32_t)phy_data; /* extended 10bt distance */ + regs_buff[18] = regs_buff[13]; /* cable polarity */ + regs_buff[19] = 0; /* Dummy (to align w/ IGP phy reg dump) */ + regs_buff[20] = regs_buff[17]; /* polarity correction */ + /* phy receive errors */ + regs_buff[22] = adapter->phy_stats.receive_errors; + regs_buff[23] = regs_buff[13]; /* mdix mode */ + } + regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */ + e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); + regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */ + regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ + return; } *************** *** 219,225 **** uint16_t i; for (i = 0; i < last_word - first_word + 1; i++) if((ret_val = e1000_read_eeprom(hw, first_word + i, 1, ! &eeprom_buff[i]))) break; } geeprom_error: --- 322,328 ---- uint16_t i; for (i = 0; i < last_word - first_word + 1; i++) if((ret_val = e1000_read_eeprom(hw, first_word + i, 1, ! &eeprom_buff[i]))) break; } geeprom_error: *************** *** 249,255 **** first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; eeprom_buff = kmalloc(max_len, GFP_KERNEL); ! if(eeprom_buff == NULL) return -ENOMEM; ptr = (void *)eeprom_buff; --- 352,358 ---- first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; eeprom_buff = kmalloc(max_len, GFP_KERNEL); ! if(!eeprom_buff) return -ENOMEM; ptr = (void *)eeprom_buff; *************** *** 284,289 **** --- 387,1152 ---- return ret_val; } + #define REG_PATTERN_TEST(R, M, W) \ + { \ + uint32_t pat, value; \ + uint32_t test[] = \ + {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \ + for(pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) { \ + E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \ + value = E1000_READ_REG(&adapter->hw, R); \ + if(value != (test[pat] & W & M)) { \ + *data = (adapter->hw.mac_type < e1000_82543) ? \ + E1000_82542_##R : E1000_##R; \ + return 1; \ + } \ + } \ + } + + #define REG_SET_AND_CHECK(R, M, W) \ + { \ + uint32_t value; \ + E1000_WRITE_REG(&adapter->hw, R, W & M); \ + value = E1000_READ_REG(&adapter->hw, R); \ + if ((W & M) != (value & M)) { \ + *data = (adapter->hw.mac_type < e1000_82543) ? \ + E1000_82542_##R : E1000_##R; \ + return 1; \ + } \ + } + + static int + e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) + { + uint32_t value; + uint32_t i; + + /* The status register is Read Only, so a write should fail. + * Some bits that get toggled are ignored. + */ + value = (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833)); + E1000_WRITE_REG(&adapter->hw, STATUS, (0xFFFFFFFF)); + if(value != (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833))) { + *data = 1; + return 1; + } + + REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF); + REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF); + REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF); + REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF); + REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF); + REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF); + REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF); + REG_PATTERN_TEST(RDH, 0x0000FFFF, 0x0000FFFF); + REG_PATTERN_TEST(RDT, 0x0000FFFF, 0x0000FFFF); + REG_PATTERN_TEST(FCRTH, 0x0000FFF8, 0x0000FFF8); + REG_PATTERN_TEST(FCTTV, 0x0000FFFF, 0x0000FFFF); + REG_PATTERN_TEST(TIPG, 0x3FFFFFFF, 0x3FFFFFFF); + REG_PATTERN_TEST(TDBAH, 0xFFFFFFFF, 0xFFFFFFFF); + REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF); + + REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000); + REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0x003FFFFB); + REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000); + + if(adapter->hw.mac_type >= e1000_82543) { + + REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0xFFFFFFFF); + REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF); + REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF); + REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF); + REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF); + + for(i = 0; i < E1000_RAR_ENTRIES; i++) { + REG_PATTERN_TEST(RA + ((i << 1) << 2), 0xFFFFFFFF, + 0xFFFFFFFF); + REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF, + 0xFFFFFFFF); + } + + } else { + + REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x01FFFFFF); + REG_PATTERN_TEST(RDBAL, 0xFFFFF000, 0xFFFFFFFF); + REG_PATTERN_TEST(TXCW, 0x0000FFFF, 0x0000FFFF); + REG_PATTERN_TEST(TDBAL, 0xFFFFF000, 0xFFFFFFFF); + + } + + for(i = 0; i < E1000_MC_TBL_SIZE; i++) + REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF); + + return 0; + } + + static int + e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data) + { + uint16_t temp; + uint16_t checksum = 0; + uint16_t i; + + *data = 0; + /* Read and add up the contents of the EEPROM */ + for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { + if((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) { + *data = 1; + break; + } + checksum += temp; + } + + /* If Checksum is not Correct return error else test passed */ + if((checksum != (uint16_t) EEPROM_SUM) && !(*data)) + *data = 2; + + return *data; + } + + static void + e1000_test_intr(int irq, + void *data, + struct pt_regs *regs) + { + struct net_device *netdev = (struct net_device *) data; + struct e1000_adapter *adapter = netdev->priv; + + adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR); + + return; + } + + static int + e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) + { + struct net_device *netdev = adapter->netdev; + uint32_t icr, mask, i=0; + + *data = 0; + + /* Hook up test interrupt handler just for this test */ + if(request_irq + (netdev->irq, &e1000_test_intr, SA_SHIRQ, netdev->name, netdev)) { + *data = 1; + return -1; + } + + /* Disable all the interrupts */ + E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF); + msec_delay(10); + + /* Interrupts are disabled, so read interrupt cause + * register (icr) twice to verify that there are no interrupts + * pending. icr is clear on read. + */ + icr = E1000_READ_REG(&adapter->hw, ICR); + icr = E1000_READ_REG(&adapter->hw, ICR); + + if(icr != 0) { + /* if icr is non-zero, there is no point + * running other interrupt tests. + */ + *data = 2; + i = 10; + } + + /* Test each interrupt */ + for(; i < 10; i++) { + + /* Interrupt to test */ + mask = 1 << i; + + /* Disable the interrupt to be reported in + * the cause register and then force the same + * interrupt and see if one gets posted. If + * an interrupt was posted to the bus, the + * test failed. + */ + adapter->test_icr = 0; + E1000_WRITE_REG(&adapter->hw, IMC, mask); + E1000_WRITE_REG(&adapter->hw, ICS, mask); + msec_delay(10); + + if(adapter->test_icr & mask) { + *data = 3; + break; + } + + /* Enable the interrupt to be reported in + * the cause register and then force the same + * interrupt and see if one gets posted. If + * an interrupt was not posted to the bus, the + * test failed. + */ + adapter->test_icr = 0; + E1000_WRITE_REG(&adapter->hw, IMS, mask); + E1000_WRITE_REG(&adapter->hw, ICS, mask); + msec_delay(10); + + if(!(adapter->test_icr & mask)) { + *data = 4; + break; + } + + /* Disable the other interrupts to be reported in + * the cause register and then force the other + * interrupts and see if any get posted. If + * an interrupt was posted to the bus, the + * test failed. + */ + adapter->test_icr = 0; + E1000_WRITE_REG(&adapter->hw, IMC, ~mask); + E1000_WRITE_REG(&adapter->hw, ICS, ~mask); + msec_delay(10); + + if(adapter->test_icr) { + *data = 5; + break; + } + } + + /* Disable all the interrupts */ + E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF); + msec_delay(10); + + /* Unhook test interrupt handler */ + free_irq(netdev->irq, netdev); + + return *data; + } + + static void + e1000_free_desc_rings(struct e1000_adapter *adapter) + { + struct e1000_desc_ring *txdr = &adapter->test_tx_ring; + struct e1000_desc_ring *rxdr = &adapter->test_rx_ring; + struct pci_dev *pdev = adapter->pdev; + int i; + + if(txdr->desc && txdr->buffer_info) { + for(i = 0; i < txdr->count; i++) { + if(txdr->buffer_info[i].dma) + pci_unmap_single(pdev, txdr->buffer_info[i].dma, + txdr->buffer_info[i].length, + PCI_DMA_TODEVICE); + if(txdr->buffer_info[i].skb) + dev_kfree_skb(txdr->buffer_info[i].skb); + } + } + + if(rxdr->desc && rxdr->buffer_info) { + for(i = 0; i < rxdr->count; i++) { + if(rxdr->buffer_info[i].dma) + pci_unmap_single(pdev, rxdr->buffer_info[i].dma, + rxdr->buffer_info[i].length, + PCI_DMA_FROMDEVICE); + if(rxdr->buffer_info[i].skb) + dev_kfree_skb(rxdr->buffer_info[i].skb); + } + } + + if(txdr->desc) + pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma); + if(rxdr->desc) + pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma); + + if(txdr->buffer_info) + kfree(txdr->buffer_info); + if(rxdr->buffer_info) + kfree(rxdr->buffer_info); + + return; + } + + static int + e1000_setup_desc_rings(struct e1000_adapter *adapter) + { + struct e1000_desc_ring *txdr = &adapter->test_tx_ring; + struct e1000_desc_ring *rxdr = &adapter->test_rx_ring; + struct pci_dev *pdev = adapter->pdev; + uint32_t rctl; + int size, i, ret_val; + + /* Setup Tx descriptor ring and Tx buffers */ + + txdr->count = 80; + + size = txdr->count * sizeof(struct e1000_buffer); + if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) { + ret_val = 1; + goto err_nomem; + } + memset(txdr->buffer_info, 0, size); + + txdr->size = txdr->count * sizeof(struct e1000_tx_desc); + E1000_ROUNDUP(txdr->size, 4096); + if(!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) { + ret_val = 2; + goto err_nomem; + } + memset(txdr->desc, 0, txdr->size); + txdr->next_to_use = txdr->next_to_clean = 0; + + E1000_WRITE_REG(&adapter->hw, TDBAL, + ((uint64_t) txdr->dma & 0x00000000FFFFFFFF)); + E1000_WRITE_REG(&adapter->hw, TDBAH, ((uint64_t) txdr->dma >> 32)); + E1000_WRITE_REG(&adapter->hw, TDLEN, + txdr->count * sizeof(struct e1000_tx_desc)); + E1000_WRITE_REG(&adapter->hw, TDH, 0); + E1000_WRITE_REG(&adapter->hw, TDT, 0); + E1000_WRITE_REG(&adapter->hw, TCTL, + E1000_TCTL_PSP | E1000_TCTL_EN | + E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | + E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT); + + for(i = 0; i < txdr->count; i++) { + struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i); + struct sk_buff *skb; + unsigned int size = 1024; + + if(!(skb = alloc_skb(size, GFP_KERNEL))) { + ret_val = 3; + goto err_nomem; + } + skb_put(skb, size); + txdr->buffer_info[i].skb = skb; + txdr->buffer_info[i].length = skb->len; + txdr->buffer_info[i].dma = + pci_map_single(pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + tx_desc->buffer_addr = cpu_to_le64(txdr->buffer_info[i].dma); + tx_desc->lower.data = cpu_to_le32(skb->len); + tx_desc->lower.data |= E1000_TXD_CMD_EOP; + tx_desc->lower.data |= E1000_TXD_CMD_IFCS; + tx_desc->lower.data |= E1000_TXD_CMD_RPS; + tx_desc->upper.data = 0; + } + + /* Setup Rx descriptor ring and Rx buffers */ + + rxdr->count = 80; + + size = rxdr->count * sizeof(struct e1000_buffer); + if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) { + ret_val = 4; + goto err_nomem; + } + memset(rxdr->buffer_info, 0, size); + + rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc); + if(!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) { + ret_val = 5; + goto err_nomem; + } + memset(rxdr->desc, 0, rxdr->size); + rxdr->next_to_use = rxdr->next_to_clean = 0; + + rctl = E1000_READ_REG(&adapter->hw, RCTL); + E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN); + E1000_WRITE_REG(&adapter->hw, RDBAL, + ((uint64_t) rxdr->dma & 0xFFFFFFFF)); + E1000_WRITE_REG(&adapter->hw, RDBAH, ((uint64_t) rxdr->dma >> 32)); + E1000_WRITE_REG(&adapter->hw, RDLEN, rxdr->size); + E1000_WRITE_REG(&adapter->hw, RDH, 0); + E1000_WRITE_REG(&adapter->hw, RDT, 0); + rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | + E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | + (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT); + E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + + for(i = 0; i < rxdr->count; i++) { + struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i); + struct sk_buff *skb; + + if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + 2, GFP_KERNEL))) { + ret_val = 6; + goto err_nomem; + } + skb_reserve(skb, 2); + rxdr->buffer_info[i].skb = skb; + rxdr->buffer_info[i].length = E1000_RXBUFFER_2048; + rxdr->buffer_info[i].dma = + pci_map_single(pdev, skb->data, E1000_RXBUFFER_2048, + PCI_DMA_FROMDEVICE); + rx_desc->buffer_addr = cpu_to_le64(rxdr->buffer_info[i].dma); + memset(skb->data, 0x00, skb->len); + } + + return 0; + + err_nomem: + e1000_free_desc_rings(adapter); + return ret_val; + } + + static void + e1000_phy_disable_receiver(struct e1000_adapter *adapter) + { + /* Write out to PHY registers 29 and 30 to disable the Receiver. */ + e1000_write_phy_reg(&adapter->hw, 29, 0x001F); + e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC); + e1000_write_phy_reg(&adapter->hw, 29, 0x001A); + e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0); + + return; + } + + static void + e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter) + { + uint16_t phy_reg; + + /* Because we reset the PHY above, we need to re-force TX_CLK in the + * Extended PHY Specific Control Register to 25MHz clock. This + * value defaults back to a 2.5MHz clock when the PHY is reset. + */ + e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg); + phy_reg |= M88E1000_EPSCR_TX_CLK_25; + e1000_write_phy_reg(&adapter->hw, + M88E1000_EXT_PHY_SPEC_CTRL, phy_reg); + + /* In addition, because of the s/w reset above, we need to enable + * CRS on TX. This must be set for both full and half duplex + * operation. + */ + e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg); + phy_reg |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + e1000_write_phy_reg(&adapter->hw, + M88E1000_PHY_SPEC_CTRL, phy_reg); + } + + static int + e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter) + { + uint32_t ctrl_reg; + uint16_t phy_reg; + + /* Setup the Device Control Register for PHY loopback test. */ + + ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL); + ctrl_reg |= (E1000_CTRL_ILOS | /* Invert Loss-Of-Signal */ + E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ + E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ + E1000_CTRL_SPD_1000 | /* Force Speed to 1000 */ + E1000_CTRL_FD); /* Force Duplex to FULL */ + + E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg); + + /* Read the PHY Specific Control Register (0x10) */ + e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg); + + /* Clear Auto-Crossover bits in PHY Specific Control Register + * (bits 6:5). + */ + phy_reg &= ~M88E1000_PSCR_AUTO_X_MODE; + e1000_write_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, phy_reg); + + /* Perform software reset on the PHY */ + e1000_phy_reset(&adapter->hw); + + /* Have to setup TX_CLK and TX_CRS after software reset */ + e1000_phy_reset_clk_and_crs(adapter); + + e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8100); + + /* Wait for reset to complete. */ + udelay(500); + + /* Have to setup TX_CLK and TX_CRS after software reset */ + e1000_phy_reset_clk_and_crs(adapter); + + /* Write out to PHY registers 29 and 30 to disable the Receiver. */ + e1000_phy_disable_receiver(adapter); + + /* Set the loopback bit in the PHY control register. */ + e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg); + phy_reg |= MII_CR_LOOPBACK; + e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg); + + /* Setup TX_CLK and TX_CRS one more time. */ + e1000_phy_reset_clk_and_crs(adapter); + + /* Check Phy Configuration */ + e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg); + if(phy_reg != 0x4100) + return 9; + + e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg); + if(phy_reg != 0x0070) + return 10; + + e1000_read_phy_reg(&adapter->hw, 29, &phy_reg); + if(phy_reg != 0x001A) + return 11; + + return 0; + } + + static int + e1000_integrated_phy_loopback(struct e1000_adapter *adapter) + { + uint32_t ctrl_reg = 0; + uint32_t stat_reg = 0; + + adapter->hw.autoneg = FALSE; + + if(adapter->hw.phy_type == e1000_phy_m88) { + /* Auto-MDI/MDIX Off */ + e1000_write_phy_reg(&adapter->hw, + M88E1000_PHY_SPEC_CTRL, 0x0808); + /* reset to update Auto-MDI/MDIX */ + e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x9140); + /* autoneg off */ + e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8140); + } + /* force 1000, set loopback */ + e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140); + + /* Now set up the MAC to the same speed/duplex as the PHY. */ + ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL); + ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ + ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ + E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ + E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ + E1000_CTRL_FD); /* Force Duplex to FULL */ + + if(adapter->hw.media_type == e1000_media_type_copper && + adapter->hw.phy_type == e1000_phy_m88) { + ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ + } else { + /* Set the ILOS bit on the fiber Nic is half + * duplex link is detected. */ + stat_reg = E1000_READ_REG(&adapter->hw, STATUS); + if((stat_reg & E1000_STATUS_FD) == 0) + ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU); + } + + E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg); + + /* Disable the receiver on the PHY so when a cable is plugged in, the + * PHY does not begin to autoneg when a cable is reconnected to the NIC. + */ + if(adapter->hw.phy_type == e1000_phy_m88) + e1000_phy_disable_receiver(adapter); + + udelay(500); + + return 0; + } + + static int + e1000_set_phy_loopback(struct e1000_adapter *adapter) + { + uint16_t phy_reg = 0; + uint16_t count = 0; + + switch (adapter->hw.mac_type) { + case e1000_82543: + if(adapter->hw.media_type == e1000_media_type_copper) { + /* Attempt to setup Loopback mode on Non-integrated PHY. + * Some PHY registers get corrupted at random, so + * attempt this 10 times. + */ + while(e1000_nonintegrated_phy_loopback(adapter) && + count++ < 10); + if(count < 11) + return 0; + } + break; + + case e1000_82544: + case e1000_82540: + case e1000_82545: + case e1000_82546: + case e1000_82541: + case e1000_82547: + return e1000_integrated_phy_loopback(adapter); + break; + + default: + /* Default PHY loopback work is to read the MII + * control register and assert bit 14 (loopback mode). + */ + e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg); + phy_reg |= MII_CR_LOOPBACK; + e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg); + return 0; + break; + } + + return 8; + } + + static int + e1000_setup_loopback_test(struct e1000_adapter *adapter) + { + uint32_t rctl; + + if(adapter->hw.media_type == e1000_media_type_fiber) { + if(adapter->hw.mac_type == e1000_82545 || + adapter->hw.mac_type == e1000_82546) + return e1000_set_phy_loopback(adapter); + else { + rctl = E1000_READ_REG(&adapter->hw, RCTL); + rctl |= E1000_RCTL_LBM_TCVR; + E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + return 0; + } + } else if(adapter->hw.media_type == e1000_media_type_copper) + return e1000_set_phy_loopback(adapter); + + return 7; + } + + static void + e1000_loopback_cleanup(struct e1000_adapter *adapter) + { + uint32_t rctl; + uint16_t phy_reg; + + rctl = E1000_READ_REG(&adapter->hw, RCTL); + rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); + E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + + if(adapter->hw.media_type == e1000_media_type_copper || + (adapter->hw.media_type == e1000_media_type_fiber && + (adapter->hw.mac_type == e1000_82545 || + adapter->hw.mac_type == e1000_82546))) { + adapter->hw.autoneg = TRUE; + e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg); + if(phy_reg & MII_CR_LOOPBACK) { + phy_reg &= ~MII_CR_LOOPBACK; + e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg); + e1000_phy_reset(&adapter->hw); + } + } + } + + static void + e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size) + { + memset(skb->data, 0xFF, frame_size); + frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size; + memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1); + memset(&skb->data[frame_size / 2 + 10], 0xBE, 1); + memset(&skb->data[frame_size / 2 + 12], 0xAF, 1); + } + + static int + e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size) + { + frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size; + if(*(skb->data + 3) == 0xFF) { + if((*(skb->data + frame_size / 2 + 10) == 0xBE) && + (*(skb->data + frame_size / 2 + 12) == 0xAF)) { + return 0; + } + } + return 13; + } + + static int + e1000_run_loopback_test(struct e1000_adapter *adapter) + { + struct e1000_desc_ring *txdr = &adapter->test_tx_ring; + struct e1000_desc_ring *rxdr = &adapter->test_rx_ring; + struct pci_dev *pdev = adapter->pdev; + int i; + + E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1); + + for(i = 0; i < 64; i++) { + e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024); + pci_dma_sync_single(pdev, txdr->buffer_info[i].dma, + txdr->buffer_info[i].length, + PCI_DMA_TODEVICE); + } + E1000_WRITE_REG(&adapter->hw, TDT, i); + + msec_delay(200); + + pci_dma_sync_single(pdev, rxdr->buffer_info[0].dma, + rxdr->buffer_info[0].length, PCI_DMA_FROMDEVICE); + + return e1000_check_lbtest_frame(rxdr->buffer_info[0].skb, 1024); + } + + static int + e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data) + { + if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback; + if((*data = e1000_setup_loopback_test(adapter))) goto err_loopback; + *data = e1000_run_loopback_test(adapter); + e1000_loopback_cleanup(adapter); + e1000_free_desc_rings(adapter); + err_loopback: + return *data; + } + + static int + e1000_link_test(struct e1000_adapter *adapter, uint64_t *data) + { + *data = 0; + e1000_check_for_link(&adapter->hw); + + if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) { + *data = 1; + } + return *data; + } + + static int + e1000_ethtool_test(struct e1000_adapter *adapter, + struct ethtool_test *eth_test, uint64_t *data) + { + boolean_t if_running = netif_running(adapter->netdev); + + if(eth_test->flags == ETH_TEST_FL_OFFLINE) { + /* Offline tests */ + + /* Link test performed before hardware reset so autoneg doesn't + * interfere with test result */ + if(e1000_link_test(adapter, &data[4])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + if(if_running) + e1000_down(adapter); + else + e1000_reset(adapter); + + if(e1000_reg_test(adapter, &data[0])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + e1000_reset(adapter); + if(e1000_eeprom_test(adapter, &data[1])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + e1000_reset(adapter); + if(e1000_intr_test(adapter, &data[2])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + e1000_reset(adapter); + if(e1000_loopback_test(adapter, &data[3])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + e1000_reset(adapter); + if(if_running) + e1000_up(adapter); + } else { + /* Online tests */ + if(e1000_link_test(adapter, &data[4])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + /* Offline tests aren't run; pass by default */ + data[0] = 0; + data[1] = 0; + data[2] = 0; + data[3] = 0; + } + return 0; + } + static void e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) { *************** *** 427,434 **** } case ETHTOOL_SSET: { struct ethtool_cmd ecmd; - if(!capable(CAP_NET_ADMIN)) - return -EPERM; if(copy_from_user(&ecmd, addr, sizeof(ecmd))) return -EFAULT; return e1000_ethtool_sset(adapter, &ecmd); --- 1290,1295 ---- *************** *** 443,466 **** case ETHTOOL_GSTRINGS: { struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS }; char *strings = NULL; if(copy_from_user(&gstrings, addr, sizeof(gstrings))) return -EFAULT; switch(gstrings.string_set) { ! case ETH_SS_STATS: gstrings.len = E1000_STATS_LEN; ! strings = *e1000_gstrings_stats; break; default: return -EOPNOTSUPP; } if(copy_to_user(addr, &gstrings, sizeof(gstrings))) ! return -EFAULT; addr += offsetof(struct ethtool_gstrings, data); ! if(copy_to_user(addr, strings, gstrings.len * ETH_GSTRING_LEN)) ! return -EFAULT; ! return 0; } case ETHTOOL_GREGS: { struct ethtool_regs regs = {ETHTOOL_GREGS}; --- 1304,1349 ---- case ETHTOOL_GSTRINGS: { struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS }; char *strings = NULL; + int err = 0; if(copy_from_user(&gstrings, addr, sizeof(gstrings))) return -EFAULT; switch(gstrings.string_set) { ! case ETH_SS_TEST: ! gstrings.len = E1000_TEST_LEN; ! strings = kmalloc(E1000_TEST_LEN * ETH_GSTRING_LEN, ! GFP_KERNEL); ! if(!strings) ! return -ENOMEM; ! memcpy(strings, e1000_gstrings_test, E1000_TEST_LEN * ! ETH_GSTRING_LEN); ! break; ! case ETH_SS_STATS: { ! int i; gstrings.len = E1000_STATS_LEN; ! strings = kmalloc(E1000_STATS_LEN * ETH_GSTRING_LEN, ! GFP_KERNEL); ! if(!strings) ! return -ENOMEM; ! for(i=0; i < E1000_STATS_LEN; i++) { ! memcpy(&strings[i * ETH_GSTRING_LEN], ! e1000_gstrings_stats[i].stat_string, ! ETH_GSTRING_LEN); ! } break; + } default: return -EOPNOTSUPP; } if(copy_to_user(addr, &gstrings, sizeof(gstrings))) ! err = -EFAULT; addr += offsetof(struct ethtool_gstrings, data); ! if(!err && copy_to_user(addr, strings, gstrings.len * ETH_GSTRING_LEN)) ! err = -EFAULT; ! ! kfree(strings); ! return err; } case ETHTOOL_GREGS: { struct ethtool_regs regs = {ETHTOOL_GREGS}; *************** *** 479,486 **** return 0; } case ETHTOOL_NWAY_RST: { - if(!capable(CAP_NET_ADMIN)) - return -EPERM; if(netif_running(netdev)) { e1000_down(adapter); e1000_up(adapter); --- 1362,1367 ---- *************** *** 509,516 **** } case ETHTOOL_SWOL: { struct ethtool_wolinfo wol; - if(!capable(CAP_NET_ADMIN)) - return -EPERM; if(copy_from_user(&wol, addr, sizeof(wol)) != 0) return -EFAULT; return e1000_ethtool_swol(adapter, &wol); --- 1390,1395 ---- *************** *** 522,537 **** void *ptr; int err = 0; eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL); ! if(eeprom_buff == NULL) return -ENOMEM; - if(copy_from_user(&eeprom, addr, sizeof(eeprom))) { - err = -EFAULT; - goto err_geeprom_ioctl; - } - if((err = e1000_ethtool_geeprom(adapter, &eeprom, eeprom_buff))) goto err_geeprom_ioctl; --- 1401,1414 ---- void *ptr; int err = 0; + if(copy_from_user(&eeprom, addr, sizeof(eeprom))) + return -EFAULT; + eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL); ! if(!eeprom_buff) return -ENOMEM; if((err = e1000_ethtool_geeprom(adapter, &eeprom, eeprom_buff))) goto err_geeprom_ioctl; *************** *** 554,562 **** case ETHTOOL_SEEPROM: { struct ethtool_eeprom eeprom; - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if(copy_from_user(&eeprom, addr, sizeof(eeprom))) return -EFAULT; --- 1431,1436 ---- *************** *** 565,582 **** } case ETHTOOL_GSTATS: { struct { ! struct ethtool_stats cmd; uint64_t data[E1000_STATS_LEN]; } stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} }; int i; for(i = 0; i < E1000_STATS_LEN; i++) ! stats.data[i] = ! ((unsigned long *)&adapter->net_stats)[i]; if(copy_to_user(addr, &stats, sizeof(stats))) return -EFAULT; return 0; } default: return -EOPNOTSUPP; } --- 1439,1480 ---- } case ETHTOOL_GSTATS: { struct { ! struct ethtool_stats eth_stats; uint64_t data[E1000_STATS_LEN]; } stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} }; int i; for(i = 0; i < E1000_STATS_LEN; i++) ! stats.data[i] = (e1000_gstrings_stats[i].sizeof_stat == ! sizeof(uint64_t)) ? ! *(uint64_t *)((char *)adapter + ! e1000_gstrings_stats[i].stat_offset) : ! *(uint32_t *)((char *)adapter + ! e1000_gstrings_stats[i].stat_offset); if(copy_to_user(addr, &stats, sizeof(stats))) return -EFAULT; return 0; } + case ETHTOOL_TEST: { + struct { + struct ethtool_test eth_test; + uint64_t data[E1000_TEST_LEN]; + } test = { {ETHTOOL_TEST} }; + int err; + + if(copy_from_user(&test.eth_test, addr, sizeof(test.eth_test))) + return -EFAULT; + + test.eth_test.len = E1000_TEST_LEN; + + if((err = e1000_ethtool_test(adapter, &test.eth_test, + test.data))) + return err; + + if(copy_to_user(addr, &test, sizeof(test)) != 0) + return -EFAULT; + return 0; + } default: return -EOPNOTSUPP; } diff -Ncr linux-2.4.22-old/drivers/net/e1000/e1000_hw.c linux-2.4.22/drivers/net/e1000/e1000_hw.c *** linux-2.4.22-old/drivers/net/e1000/e1000_hw.c 2003-11-18 17:02:21.000000000 +0900 --- linux-2.4.22/drivers/net/e1000/e1000_hw.c 2003-08-25 20:44:42.000000000 +0900 *************** *** 135,140 **** --- 135,175 ---- e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000); e1000_write_phy_reg(hw,0x0000,0x3300); + + + if(hw->mac_type == e1000_82547) { + uint16_t fused, fine, coarse; + + /* Move to analog registers page */ + e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, + IGP01E1000_ANALOG_REGS_PAGE); + + e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused); + + if(!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { + e1000_read_phy_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS, &fused); + + fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK; + coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK; + + if(coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) { + coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10; + fine -= IGP01E1000_ANALOG_FUSE_FINE_1; + } else if(coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH) + fine -= IGP01E1000_ANALOG_FUSE_FINE_10; + + fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | + (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | + (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK); + + e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_CONTROL, fused); + e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS, + IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL); + } + /* Return to first page of registers */ + e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, + IGP01E1000_IEEE_REGS_PAGE); + } } } *************** *** 185,190 **** --- 220,226 ---- break; case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_FIBER: + case E1000_DEV_ID_82546EB_QUAD_COPPER: hw->mac_type = e1000_82546; break; case E1000_DEV_ID_82541EI: *************** *** 258,267 **** msec_delay(5); } ! if(hw->mac_type > e1000_82543) ! E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); ! else ! E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); /* Force a reload from the EEPROM if necessary */ if(hw->mac_type < e1000_82540) { --- 294,313 ---- msec_delay(5); } ! switch(hw->mac_type) { ! case e1000_82544: ! case e1000_82540: ! case e1000_82545: ! case e1000_82546: ! case e1000_82541: ! /* These controllers can't ack the 64-bit write when issuing the ! * reset, so use IO-mapping as a workaround to issue the reset */ ! E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); ! break; ! default: ! E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); ! break; ! } /* Force a reload from the EEPROM if necessary */ if(hw->mac_type < e1000_82540) { *************** *** 288,296 **** /* Configure activity LED after PHY reset */ led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl &= IGP_ACTIVITY_LED_MASK; ! led_ctrl |= IGP_ACTIVITY_LED_ENABLE; ! if(hw->mac_type == e1000_82547) ! led_ctrl |= IGP_LED3_MODE; E1000_WRITE_REG(hw, LEDCTL, led_ctrl); } --- 334,340 ---- /* Configure activity LED after PHY reset */ led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl &= IGP_ACTIVITY_LED_MASK; ! led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); E1000_WRITE_REG(hw, LEDCTL, led_ctrl); } *************** *** 688,694 **** static int32_t e1000_setup_copper_link(struct e1000_hw *hw) { ! uint32_t ctrl, led_ctrl; int32_t ret_val; uint16_t i; uint16_t phy_data; --- 732,739 ---- static int32_t e1000_setup_copper_link(struct e1000_hw *hw) { ! uint32_t ctrl; ! uint32_t led_ctrl; int32_t ret_val; uint16_t i; uint16_t phy_data; *************** *** 737,745 **** /* Configure activity LED after PHY reset */ led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl &= IGP_ACTIVITY_LED_MASK; ! led_ctrl |= IGP_ACTIVITY_LED_ENABLE; ! if(hw->mac_type == e1000_82547) ! led_ctrl |= IGP_LED3_MODE; E1000_WRITE_REG(hw, LEDCTL, led_ctrl); if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { --- 782,788 ---- /* Configure activity LED after PHY reset */ led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl &= IGP_ACTIVITY_LED_MASK; ! led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); E1000_WRITE_REG(hw, LEDCTL, led_ctrl); if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { *************** *** 2252,2258 **** void e1000_phy_hw_reset(struct e1000_hw *hw) { ! uint32_t ctrl, ctrl_ext, led_ctrl; DEBUGFUNC("e1000_phy_hw_reset"); --- 2295,2302 ---- void e1000_phy_hw_reset(struct e1000_hw *hw) { ! uint32_t ctrl, ctrl_ext; ! uint32_t led_ctrl; DEBUGFUNC("e1000_phy_hw_reset"); *************** *** 2293,2301 **** /* Configure activity LED after PHY reset */ led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl &= IGP_ACTIVITY_LED_MASK; ! led_ctrl |= IGP_ACTIVITY_LED_ENABLE; ! if(hw->mac_type == e1000_82547) ! led_ctrl |= IGP_LED3_MODE; E1000_WRITE_REG(hw, LEDCTL, led_ctrl); } } --- 2337,2343 ---- /* Configure activity LED after PHY reset */ led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl &= IGP_ACTIVITY_LED_MASK; ! led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); E1000_WRITE_REG(hw, LEDCTL, led_ctrl); } } *************** *** 3801,3806 **** --- 3843,3849 ---- case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82546EB_COPPER: + case E1000_DEV_ID_82546EB_QUAD_COPPER: case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EP: case E1000_DEV_ID_82547EI: *************** *** 3842,3847 **** --- 3885,3891 ---- case E1000_DEV_ID_82545EM_FIBER: case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_FIBER: + case E1000_DEV_ID_82546EB_QUAD_COPPER: case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EP: case E1000_DEV_ID_82547EI: *************** *** 3896,3901 **** --- 3940,3946 ---- case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82546EB_COPPER: + case E1000_DEV_ID_82546EB_QUAD_COPPER: case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EP: case E1000_DEV_ID_82547EI: *************** *** 3949,3954 **** --- 3994,4000 ---- case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82546EB_COPPER: + case E1000_DEV_ID_82546EB_QUAD_COPPER: case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EP: case E1000_DEV_ID_82547EI: *************** *** 4206,4212 **** status = E1000_READ_REG(hw, STATUS); hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? e1000_bus_type_pcix : e1000_bus_type_pci; ! if(hw->bus_type == e1000_bus_type_pci) { hw->bus_speed = (status & E1000_STATUS_PCI66) ? e1000_bus_speed_66 : e1000_bus_speed_33; } else { --- 4252,4262 ---- status = E1000_READ_REG(hw, STATUS); hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? e1000_bus_type_pcix : e1000_bus_type_pci; ! ! if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) { ! hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ? ! e1000_bus_speed_66 : e1000_bus_speed_120; ! } else if(hw->bus_type == e1000_bus_type_pci) { hw->bus_speed = (status & E1000_STATUS_PCI66) ? e1000_bus_speed_66 : e1000_bus_speed_33; } else { diff -Ncr linux-2.4.22-old/drivers/net/e1000/e1000_hw.h linux-2.4.22/drivers/net/e1000/e1000_hw.h *** linux-2.4.22-old/drivers/net/e1000/e1000_hw.h 2003-11-18 17:22:41.000000000 +0900 --- linux-2.4.22/drivers/net/e1000/e1000_hw.h 2003-08-25 20:44:42.000000000 +0900 *************** *** 99,104 **** --- 99,105 ---- e1000_bus_speed_33, e1000_bus_speed_66, e1000_bus_speed_100, + e1000_bus_speed_120, e1000_bus_speed_133, e1000_bus_speed_reserved } e1000_bus_speed; *************** *** 314,323 **** #define E1000_DEV_ID_82545EM_FIBER 0x1011 #define E1000_DEV_ID_82546EB_COPPER 0x1010 #define E1000_DEV_ID_82546EB_FIBER 0x1012 #define E1000_DEV_ID_82541EI 0x1013 #define E1000_DEV_ID_82541EP 0x1018 #define E1000_DEV_ID_82547EI 0x1019 ! #define NUM_DEV_IDS 19 #define NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 --- 315,325 ---- #define E1000_DEV_ID_82545EM_FIBER 0x1011 #define E1000_DEV_ID_82546EB_COPPER 0x1010 #define E1000_DEV_ID_82546EB_FIBER 0x1012 + #define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D #define E1000_DEV_ID_82541EI 0x1013 #define E1000_DEV_ID_82541EP 0x1018 #define E1000_DEV_ID_82547EI 0x1019 ! #define NUM_DEV_IDS 20 #define NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 *************** *** 601,607 **** #define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ #define E1000_EERD 0x00014 /* EEPROM Read - RW */ #define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ ! #define E1000_FLA 0x0001C /* Flash Access Register - RW */ #define E1000_MDIC 0x00020 /* MDI Control - RW */ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ --- 603,609 ---- #define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ #define E1000_EERD 0x00014 /* EEPROM Read - RW */ #define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ ! #define E1000_FLA 0x0001C /* Flash Access - RW */ #define E1000_MDIC 0x00020 /* MDI Control - RW */ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ *************** *** 730,735 **** --- 732,738 ---- * the registers function in the same manner. */ #define E1000_82542_CTRL E1000_CTRL + #define E1000_82542_CTRL_DUP E1000_CTRL_DUP #define E1000_82542_STATUS E1000_STATUS #define E1000_82542_EECD E1000_EECD #define E1000_82542_EERD E1000_EERD *************** *** 1485,1491 **** #define E1000_COLLISION_DISTANCE 64 #define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE #define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE - #define E1000_GB_HDX_COLLISION_DISTANCE 512 #define E1000_COLD_SHIFT 12 /* The number of Transmit and Receive Descriptors must be a multiple of 8 */ --- 1488,1493 ---- *************** *** 1666,1671 **** --- 1668,1674 ---- #define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ #define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ + #define IGP01E1000_IEEE_REGS_PAGE 0x0000 /* IGP01E1000 Specific Registers */ #define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */ #define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */ *************** *** 1688,1693 **** --- 1691,1697 ---- * speed = 1000 Mbps. */ #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 + #define IGP01E1000_ANALOG_REGS_PAGE 0x20C0 #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ *************** *** 1978,1983 **** --- 1982,2003 ---- #define IGP01E1000_GMII_FLEX_SPD 0x10 /* Enable flexible speed * on Link-Up */ #define IGP01E1000_GMII_SPD 0x20 /* Enable SPD */ + /* IGP01E1000 Analog Register */ + #define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x0011 + #define IGP01E1000_ANALOG_FUSE_STATUS 0x0010 + #define IGP01E1000_ANALOG_FUSE_CONTROL 0x001C + #define IGP01E1000_ANALOG_FUSE_BYPASS 0x001E + + #define IGP01E1000_ANALOG_FUSE_POLY_MASK 0xF000 + #define IGP01E1000_ANALOG_FUSE_FINE_MASK 0x0F80 + #define IGP01E1000_ANALOG_FUSE_COARSE_MASK 0x0070 + #define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED 0x0100 + #define IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL 0x0002 + + #define IGP01E1000_ANALOG_FUSE_COARSE_THRESH 0x0040 + #define IGP01E1000_ANALOG_FUSE_COARSE_10 0x0010 + #define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080 + #define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500 /* Bit definitions for valid PHY IDs. */ #define M88E1000_E_PHY_ID 0x01410C50 diff -Ncr linux-2.4.22-old/drivers/net/e1000/e1000_main.c linux-2.4.22/drivers/net/e1000/e1000_main.c *** linux-2.4.22-old/drivers/net/e1000/e1000_main.c 2003-11-18 17:02:24.000000000 +0900 --- linux-2.4.22/drivers/net/e1000/e1000_main.c 2003-08-25 20:44:42.000000000 +0900 *************** *** 30,96 **** /* Change Log * ! * 5.0.43 3/5/03 ! * o Feature: Added support for 82541 and 82547 hardware. ! * o Feature: Added support for Intel Gigabit PHY (IGP) and a variety of ! * eeproms. ! * o Feature: Added support for TCP Segmentation Offload (TSO). ! * o Feature: Added MII ioctl. ! * o Feature: Added support for statistics reporting through ethtool. ! * o Cleanup: Removed proprietary hooks for ANS. ! * o Cleanup: Miscellaneous code changes to improve CPU utilization. ! * - Replaced "%" with conditionals and "+-" operators. ! * - Implemented dynamic Interrupt Throttle Rate (ITR). ! * - Reduced expensive PCI reads of ICR in interrupt. ! * o Bug fix: Request IRQ after descriptor ring setup to avoid panic in ! * shared interrupt instances. ! * ! * 4.4.18 11/27/02 ! * o Feature: Added user-settable knob for interrupt throttle rate (ITR). ! * o Cleanup: removed large static array allocations. ! * o Cleanup: C99 struct initializer format. ! * o Bug fix: restore VLAN settings when interface is brought up. ! * o Bug fix: return cleanly in probe if error in detecting MAC type. ! * o Bug fix: Wake up on magic packet by default only if enabled in eeprom. ! * o Bug fix: Validate MAC address in set_mac. ! * o Bug fix: Throw away zero-length Tx skbs. ! * o Bug fix: Make ethtool EEPROM acceses work on older versions of ethtool. ! * ! * 4.4.12 10/15/02 */ char e1000_driver_name[] = "e1000"; char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; ! char e1000_driver_version[] = "5.0.43-k1"; char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table * - * Private driver_data field (last one) stores an index into e1000_strings * Wildcard entries (PCI_ANY_ID) should come last * Last entry must be all 0s * * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, ! * Class, Class Mask, String Index } */ static struct pci_device_id e1000_pci_tbl[] __devinitdata = { - /* Intel(R) PRO/1000 Network Connection */ - {0x8086, 0x1000, 0x8086, 0x1000, 0, 0, 0}, - {0x8086, 0x1001, 0x8086, 0x1003, 0, 0, 0}, - {0x8086, 0x1004, 0x8086, 0x1004, 0, 0, 0}, - {0x8086, 0x1008, 0x8086, 0x1107, 0, 0, 0}, - {0x8086, 0x1009, 0x8086, 0x1109, 0, 0, 0}, - {0x8086, 0x100C, 0x8086, 0x1112, 0, 0, 0}, - {0x8086, 0x100E, 0x8086, 0x001E, 0, 0, 0}, - /* Compaq Gigabit Ethernet Server Adapter */ - {0x8086, 0x1000, 0x0E11, PCI_ANY_ID, 0, 0, 1}, - {0x8086, 0x1001, 0x0E11, PCI_ANY_ID, 0, 0, 1}, - {0x8086, 0x1004, 0x0E11, PCI_ANY_ID, 0, 0, 1}, - /* IBM Mobile, Desktop & Server Adapters */ - {0x8086, 0x1000, 0x1014, PCI_ANY_ID, 0, 0, 2}, - {0x8086, 0x1001, 0x1014, PCI_ANY_ID, 0, 0, 2}, - {0x8086, 0x1004, 0x1014, PCI_ANY_ID, 0, 0, 2}, - /* Generic */ {0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, --- 30,67 ---- /* Change Log * ! * 5.1.13 5/28/03 ! * o Bug fix: request_irq() failure resulted in freeing resources twice! ! * [Don Fry (brazilnut@us.ibm.com)] ! * o Bug fix: fix VLAN support on ppc64 [Mark Rakes (mrakes@vivato.net)] ! * o Bug fix: missing Tx cleanup opportunities during interrupt handling. ! * o Bug fix: alloc_etherdev failure didn't cleanup regions in probe. ! * o Cleanup: s/int/unsigned int/ for descriptor ring indexes. ! * ! * 5.1.11 5/6/03 ! * o Feature: Added support for 82546EB (Quad-port) hardware. ! * o Feature: Added support for Diagnostics through Ethtool. ! * o Cleanup: Removed /proc support. ! * o Cleanup: Removed proprietary IDIAG interface. ! * o Bug fix: TSO bug fixes. ! * ! * 5.0.42 3/5/03 */ char e1000_driver_name[] = "e1000"; char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; ! char e1000_driver_version[] = "5.1.13-k1"; char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table * * Wildcard entries (PCI_ANY_ID) should come last * Last entry must be all 0s * * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, ! * Class, Class Mask, private data (not used) } */ static struct pci_device_id e1000_pci_tbl[] __devinitdata = { {0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, *************** *** 106,111 **** --- 77,83 ---- {0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* required last entry */ *************** *** 114,125 **** MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); - static char *e1000_strings[] = { - "Intel(R) PRO/1000 Network Connection", - "HP Gigabit Ethernet Server Adapter", - "IBM Mobile, Desktop & Server Adapters" - }; - /* Local Function Prototypes */ int e1000_up(struct e1000_adapter *adapter); --- 86,91 ---- *************** *** 130,136 **** static int e1000_init_module(void); static void e1000_exit_module(void); static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent); ! static void e1000_remove(struct pci_dev *pdev); static int e1000_sw_init(struct e1000_adapter *adapter); static int e1000_open(struct net_device *netdev); static int e1000_close(struct net_device *netdev); --- 96,102 ---- static int e1000_init_module(void); static void e1000_exit_module(void); static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent); ! static void __devexit e1000_remove(struct pci_dev *pdev); static int e1000_sw_init(struct e1000_adapter *adapter); static int e1000_open(struct net_device *netdev); static int e1000_close(struct net_device *netdev); *************** *** 156,162 **** --- 122,134 ---- static inline void e1000_irq_enable(struct e1000_adapter *adapter); static void e1000_intr(int irq, void *data, struct pt_regs *regs); static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter); + #ifdef CONFIG_E1000_NAPI + static int e1000_clean(struct net_device *netdev, int *budget); + static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter, + int *work_done, int work_to_do); + #else static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter); + #endif static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter); static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, *************** *** 183,198 **** static int e1000_resume(struct pci_dev *pdev); #endif - /* for netdump / net console */ - static void e1000_netpoll (struct net_device *dev); - struct notifier_block e1000_notifier_reboot = { .notifier_call = e1000_notify_reboot, .next = NULL, .priority = 0 }; - /* Exported from other modules */ extern void e1000_check_options(struct e1000_adapter *adapter); --- 155,166 ---- *************** *** 231,238 **** printk(KERN_INFO "%s\n", e1000_copyright); ret = pci_module_init(&e1000_driver); ! if(ret >= 0) register_reboot_notifier(&e1000_notifier_reboot); return ret; } --- 199,207 ---- printk(KERN_INFO "%s\n", e1000_copyright); ret = pci_module_init(&e1000_driver); ! if(ret >= 0) { register_reboot_notifier(&e1000_notifier_reboot); + } return ret; } *************** *** 272,283 **** e1000_alloc_rx_buffers(adapter); if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, ! netdev->name, netdev)) { ! e1000_reset_hw(&adapter->hw); ! e1000_free_tx_resources(adapter); ! e1000_free_rx_resources(adapter); return -1; - } mod_timer(&adapter->watchdog_timer, jiffies); e1000_irq_enable(adapter); --- 241,248 ---- e1000_alloc_rx_buffers(adapter); if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, ! netdev->name, netdev)) return -1; mod_timer(&adapter->watchdog_timer, jiffies); e1000_irq_enable(adapter); *************** *** 421,441 **** netdev->do_ioctl = &e1000_ioctl; netdev->tx_timeout = &e1000_tx_timeout; netdev->watchdog_timeo = 5 * HZ; netdev->vlan_rx_register = e1000_vlan_rx_register; netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid; netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid; - #ifdef HAVE_POLL_CONTROLLER - netdev->poll_controller = e1000_netpoll; - #endif - netdev->irq = pdev->irq; netdev->mem_start = mmio_start; netdev->mem_end = mmio_start + mmio_len; netdev->base_addr = adapter->hw.io_base; adapter->bd_number = cards_found; - adapter->id_string = e1000_strings[ent->driver_data]; /* setup the private structure */ --- 386,405 ---- netdev->do_ioctl = &e1000_ioctl; netdev->tx_timeout = &e1000_tx_timeout; netdev->watchdog_timeo = 5 * HZ; + #ifdef CONFIG_E1000_NAPI + netdev->poll = &e1000_clean; + netdev->weight = 64; + #endif netdev->vlan_rx_register = e1000_vlan_rx_register; netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid; netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid; netdev->irq = pdev->irq; netdev->mem_start = mmio_start; netdev->mem_end = mmio_start + mmio_len; netdev->base_addr = adapter->hw.io_base; adapter->bd_number = cards_found; /* setup the private structure */ *************** *** 452,457 **** --- 416,427 ---- netdev->features = NETIF_F_SG; } + #ifdef NETIF_F_TSO + if((adapter->hw.mac_type >= e1000_82544) && + (adapter->hw.mac_type != e1000_82547)) + netdev->features |= NETIF_F_TSO; + #endif + if(pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; *************** *** 490,504 **** (void (*)(void *))e1000_tx_timeout_task, netdev); register_netdev(netdev); - memcpy(adapter->ifname, netdev->name, IFNAMSIZ); - adapter->ifname[IFNAMSIZ-1] = 0; /* we're going to reset, so assume we have no link for now */ netif_carrier_off(netdev); netif_stop_queue(netdev); ! printk(KERN_INFO "%s: %s\n", netdev->name, adapter->id_string); e1000_check_options(adapter); /* Initial Wake on LAN setting --- 460,473 ---- (void (*)(void *))e1000_tx_timeout_task, netdev); register_netdev(netdev); /* we're going to reset, so assume we have no link for now */ netif_carrier_off(netdev); netif_stop_queue(netdev); ! printk(KERN_INFO "%s: Intel(R) PRO/1000 Network Connection\n", ! netdev->name); e1000_check_options(adapter); /* Initial Wake on LAN setting *************** *** 523,531 **** err_eeprom: iounmap(adapter->hw.hw_addr); err_ioremap: - pci_release_regions(pdev); kfree(netdev); err_alloc_etherdev: return -ENOMEM; } --- 492,500 ---- err_eeprom: iounmap(adapter->hw.hw_addr); err_ioremap: kfree(netdev); err_alloc_etherdev: + pci_release_regions(pdev); return -ENOMEM; } *************** *** 558,564 **** e1000_phy_hw_reset(&adapter->hw); - iounmap(adapter->hw.hw_addr); pci_release_regions(pdev); --- 527,532 ---- *************** *** 821,828 **** e1000_config_collision_dist(&adapter->hw); ! /* Setup Transmit Descriptor Settings for this adapter */ ! adapter->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_IDE; if(adapter->hw.report_tx_early == 1) adapter->txd_cmd |= E1000_TXD_CMD_RS; --- 789,797 ---- e1000_config_collision_dist(&adapter->hw); ! /* Setup Transmit Descriptor Settings for eop descriptor */ ! adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP | ! E1000_TXD_CMD_IFCS; if(adapter->hw.report_tx_early == 1) adapter->txd_cmd |= E1000_TXD_CMD_RS; *************** *** 1000,1034 **** static void e1000_clean_tx_ring(struct e1000_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; unsigned long size; ! int i; /* Free all the Tx ring sk_buffs */ ! for(i = 0; i < adapter->tx_ring.count; i++) { ! if(adapter->tx_ring.buffer_info[i].skb) { pci_unmap_page(pdev, ! adapter->tx_ring.buffer_info[i].dma, ! adapter->tx_ring.buffer_info[i].length, PCI_DMA_TODEVICE); ! dev_kfree_skb(adapter->tx_ring.buffer_info[i].skb); ! adapter->tx_ring.buffer_info[i].skb = NULL; } } ! size = sizeof(struct e1000_buffer) * adapter->tx_ring.count; ! memset(adapter->tx_ring.buffer_info, 0, size); /* Zero out the descriptor ring */ ! memset(adapter->tx_ring.desc, 0, adapter->tx_ring.size); ! adapter->tx_ring.next_to_use = 0; ! adapter->tx_ring.next_to_clean = 0; E1000_WRITE_REG(&adapter->hw, TDH, 0); E1000_WRITE_REG(&adapter->hw, TDT, 0); --- 969,1006 ---- static void e1000_clean_tx_ring(struct e1000_adapter *adapter) { + struct e1000_desc_ring *tx_ring = &adapter->tx_ring; + struct e1000_buffer *buffer_info; struct pci_dev *pdev = adapter->pdev; unsigned long size; ! unsigned int i; /* Free all the Tx ring sk_buffs */ ! for(i = 0; i < tx_ring->count; i++) { ! buffer_info = &tx_ring->buffer_info[i]; ! if(buffer_info->skb) { pci_unmap_page(pdev, ! buffer_info->dma, ! buffer_info->length, PCI_DMA_TODEVICE); ! dev_kfree_skb(buffer_info->skb); ! buffer_info->skb = NULL; } } ! size = sizeof(struct e1000_buffer) * tx_ring->count; ! memset(tx_ring->buffer_info, 0, size); /* Zero out the descriptor ring */ ! memset(tx_ring->desc, 0, tx_ring->size); ! tx_ring->next_to_use = 0; ! tx_ring->next_to_clean = 0; E1000_WRITE_REG(&adapter->hw, TDH, 0); E1000_WRITE_REG(&adapter->hw, TDT, 0); *************** *** 1044,1060 **** static void e1000_free_rx_resources(struct e1000_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; e1000_clean_rx_ring(adapter); ! kfree(adapter->rx_ring.buffer_info); ! adapter->rx_ring.buffer_info = NULL; ! pci_free_consistent(pdev, adapter->rx_ring.size, ! adapter->rx_ring.desc, adapter->rx_ring.dma); ! adapter->rx_ring.desc = NULL; } /** --- 1016,1032 ---- static void e1000_free_rx_resources(struct e1000_adapter *adapter) { + struct e1000_desc_ring *rx_ring = &adapter->rx_ring; struct pci_dev *pdev = adapter->pdev; e1000_clean_rx_ring(adapter); ! kfree(rx_ring->buffer_info); ! rx_ring->buffer_info = NULL; ! pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); ! rx_ring->desc = NULL; } /** *************** *** 1065,1099 **** static void e1000_clean_rx_ring(struct e1000_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; unsigned long size; ! int i; /* Free all the Rx ring sk_buffs */ ! for(i = 0; i < adapter->rx_ring.count; i++) { ! if(adapter->rx_ring.buffer_info[i].skb) { pci_unmap_single(pdev, ! adapter->rx_ring.buffer_info[i].dma, ! adapter->rx_ring.buffer_info[i].length, PCI_DMA_FROMDEVICE); ! dev_kfree_skb(adapter->rx_ring.buffer_info[i].skb); ! adapter->rx_ring.buffer_info[i].skb = NULL; } } ! size = sizeof(struct e1000_buffer) * adapter->rx_ring.count; ! memset(adapter->rx_ring.buffer_info, 0, size); /* Zero out the descriptor ring */ ! memset(adapter->rx_ring.desc, 0, adapter->rx_ring.size); ! adapter->rx_ring.next_to_clean = 0; ! adapter->rx_ring.next_to_use = 0; E1000_WRITE_REG(&adapter->hw, RDH, 0); E1000_WRITE_REG(&adapter->hw, RDT, 0); --- 1037,1074 ---- static void e1000_clean_rx_ring(struct e1000_adapter *adapter) { + struct e1000_desc_ring *rx_ring = &adapter->rx_ring; + struct e1000_buffer *buffer_info; struct pci_dev *pdev = adapter->pdev; unsigned long size; ! unsigned int i; /* Free all the Rx ring sk_buffs */ ! for(i = 0; i < rx_ring->count; i++) { ! buffer_info = &rx_ring->buffer_info[i]; ! if(buffer_info->skb) { pci_unmap_single(pdev, ! buffer_info->dma, ! buffer_info->length, PCI_DMA_FROMDEVICE); ! dev_kfree_skb(buffer_info->skb); ! buffer_info->skb = NULL; } } ! size = sizeof(struct e1000_buffer) * rx_ring->count; ! memset(rx_ring->buffer_info, 0, size); /* Zero out the descriptor ring */ ! memset(rx_ring->desc, 0, rx_ring->size); ! rx_ring->next_to_clean = 0; ! rx_ring->next_to_use = 0; E1000_WRITE_REG(&adapter->hw, RDH, 0); E1000_WRITE_REG(&adapter->hw, RDT, 0); *************** *** 1343,1349 **** struct e1000_adapter *adapter = (struct e1000_adapter *) data; struct net_device *netdev = adapter->netdev; struct e1000_desc_ring *txdr = &adapter->tx_ring; ! int i; e1000_check_for_link(&adapter->hw); --- 1318,1324 ---- struct e1000_adapter *adapter = (struct e1000_adapter *) data; struct net_device *netdev = adapter->netdev; struct e1000_desc_ring *txdr = &adapter->tx_ring; ! unsigned int i; e1000_check_for_link(&adapter->hw); *************** *** 1420,1433 **** #define E1000_TX_FLAGS_CSUM 0x00000001 #define E1000_TX_FLAGS_VLAN 0x00000002 #define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 #define E1000_TX_FLAGS_VLAN_SHIFT 16 static inline boolean_t e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) { struct e1000_context_desc *context_desc; ! int i; uint8_t css, cso; if(skb->ip_summed == CHECKSUM_HW) { --- 1395,1461 ---- #define E1000_TX_FLAGS_CSUM 0x00000001 #define E1000_TX_FLAGS_VLAN 0x00000002 + #define E1000_TX_FLAGS_TSO 0x00000004 #define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 #define E1000_TX_FLAGS_VLAN_SHIFT 16 static inline boolean_t + e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb) + { + #ifdef NETIF_F_TSO + struct e1000_context_desc *context_desc; + unsigned int i; + uint8_t ipcss, ipcso, tucss, tucso, hdr_len; + uint16_t ipcse, tucse, mss; + + if(skb_shinfo(skb)->tso_size) { + 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 = E1000_CONTEXT_DESC(adapter->tx_ring, i); + + context_desc->lower_setup.ip_fields.ipcss = ipcss; + context_desc->lower_setup.ip_fields.ipcso = ipcso; + context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse); + context_desc->upper_setup.tcp_fields.tucss = tucss; + context_desc->upper_setup.tcp_fields.tucso = tucso; + context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse); + context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss); + context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; + context_desc->cmd_and_length = cpu_to_le32( + E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | + E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP | + (skb->len - (hdr_len))); + + if(++i == adapter->tx_ring.count) i = 0; + adapter->tx_ring.next_to_use = i; + + return TRUE; + } + #endif + + return FALSE; + } + + static inline boolean_t e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) { struct e1000_context_desc *context_desc; ! unsigned int i; uint8_t css, cso; if(skb->ip_summed == CHECKSUM_HW) { *************** *** 1441,1448 **** context_desc->upper_setup.tcp_fields.tucso = cso; context_desc->upper_setup.tcp_fields.tucse = 0; context_desc->tcp_seg_setup.data = 0; ! context_desc->cmd_and_length = ! cpu_to_le32(adapter->txd_cmd | E1000_TXD_CMD_DEXT); if(++i == adapter->tx_ring.count) i = 0; adapter->tx_ring.next_to_use = i; --- 1469,1475 ---- context_desc->upper_setup.tcp_fields.tucso = cso; context_desc->upper_setup.tcp_fields.tucse = 0; context_desc->tcp_seg_setup.data = 0; ! context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT); if(++i == adapter->tx_ring.count) i = 0; adapter->tx_ring.next_to_use = i; *************** *** 1457,1481 **** #define E1000_MAX_DATA_PER_TXD (1<tx_ring; ! int len = skb->len, offset = 0, size, count = 0, i; ! int f; len -= skb->data_len; i = tx_ring->next_to_use; while(len) { size = min(len, E1000_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; --- 1484,1522 ---- #define E1000_MAX_DATA_PER_TXD (1<tx_ring; ! struct e1000_buffer *buffer_info; ! int len = skb->len; ! unsigned int offset = 0, size, count = 0, i; ! #ifdef NETIF_F_TSO ! unsigned int tso = skb_shinfo(skb)->tso_size; ! #endif ! 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, E1000_MAX_DATA_PER_TXD); ! #ifdef NETIF_F_TSO ! /* Workaround for premature desc write-backs ! * in TSO mode. Append 4-byte sentinel desc */ ! if(tso && !nr_frags && size == len && size > 4) ! size -= 4; ! #endif ! 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; *************** *** 1483,1489 **** if(++i == tx_ring->count) i = 0; } ! for(f = 0; f < skb_shinfo(skb)->nr_frags; f++) { struct skb_frag_struct *frag; frag = &skb_shinfo(skb)->frags[f]; --- 1524,1530 ---- 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]; *************** *** 1491,1505 **** offset = 0; while(len) { size = min(len, E1000_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); ! tx_ring->buffer_info[i].time_stamp = jiffies; len -= size; offset += size; --- 1532,1553 ---- offset = 0; while(len) { + buffer_info = &tx_ring->buffer_info[i]; size = min(len, E1000_MAX_DATA_PER_TXD); ! #ifdef NETIF_F_TSO ! /* Workaround for premature desc write-backs ! * in TSO mode. Append 4-byte sentinel desc */ ! if(tso && f == (nr_frags-1) && size == len && size > 4) ! size -= 4; ! #endif ! 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; *************** *** 1507,1514 **** if(++i == tx_ring->count) i = 0; } } ! if(--i < 0) i = tx_ring->count - 1; tx_ring->buffer_info[i].skb = skb; return count; } --- 1555,1563 ---- 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; } *************** *** 1518,1528 **** { 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; --- 1567,1581 ---- { struct e1000_desc_ring *tx_ring = &adapter->tx_ring; struct e1000_tx_desc *tx_desc = NULL; ! struct e1000_buffer *buffer_info; ! uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; ! unsigned int i; ! ! if(tx_flags & E1000_TX_FLAGS_TSO) { ! txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | ! E1000_TXD_CMD_TSE; ! txd_upper |= (E1000_TXD_POPTS_IXSM | E1000_TXD_POPTS_TXSM) << 8; ! } if(tx_flags & E1000_TX_FLAGS_CSUM) { txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; *************** *** 1537,1551 **** 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); if(++i == tx_ring->count) i = 0; } ! 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 --- 1590,1605 ---- i = tx_ring->next_to_use; while(count--) { + buffer_info = &tx_ring->buffer_info[i]; tx_desc = E1000_TX_DESC(*tx_ring, i); ! tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); tx_desc->lower.data = ! cpu_to_le32(txd_lower | buffer_info->length); tx_desc->upper.data = cpu_to_le32(txd_upper); if(++i == tx_ring->count) i = 0; } ! tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); /* Force memory writes to complete before letting h/w * know there are new descriptors to fetch. (Only *************** *** 1605,1611 **** e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct e1000_adapter *adapter = netdev->priv; ! int tx_flags = 0; if(skb->len <= 0) { dev_kfree_skb_any(skb); --- 1659,1666 ---- e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct e1000_adapter *adapter = netdev->priv; ! unsigned int first; ! unsigned int tx_flags = 0; if(skb->len <= 0) { dev_kfree_skb_any(skb); *************** *** 1630,1639 **** tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); } ! if(e1000_tx_csum(adapter, skb)) tx_flags |= E1000_TX_FLAGS_CSUM; ! e1000_tx_queue(adapter, e1000_tx_map(adapter, skb), tx_flags); netdev->trans_start = jiffies; --- 1685,1698 ---- tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); } ! first = adapter->tx_ring.next_to_use; ! ! if(e1000_tso(adapter, skb)) ! tx_flags |= E1000_TX_FLAGS_TSO; ! else if(e1000_tx_csum(adapter, skb)) tx_flags |= E1000_TX_FLAGS_CSUM; ! e1000_tx_queue(adapter, e1000_tx_map(adapter, skb, first), tx_flags); netdev->trans_start = jiffies; *************** *** 1865,1870 **** --- 1924,1930 ---- } if((hw->mac_type <= e1000_82546) && + (hw->phy_type == e1000_phy_m88) && !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp)) adapter->phy_stats.receive_errors += phy_tmp; } *************** *** 1911,1917 **** struct net_device *netdev = data; struct e1000_adapter *adapter = netdev->priv; uint32_t icr = E1000_READ_REG(&adapter->hw, ICR); ! int i; if(!icr) return; /* Not our interrupt */ --- 1971,1979 ---- struct net_device *netdev = data; struct e1000_adapter *adapter = netdev->priv; uint32_t icr = E1000_READ_REG(&adapter->hw, ICR); ! #ifndef CONFIG_E1000_NAPI ! unsigned int i; ! #endif if(!icr) return; /* Not our interrupt */ *************** *** 1921,1932 **** mod_timer(&adapter->watchdog_timer, jiffies); } for(i = 0; i < E1000_MAX_INTR; i++) ! if(!e1000_clean_rx_irq(adapter) && !e1000_clean_tx_irq(adapter)) break; } /** * e1000_clean_tx_irq - Reclaim resources after transmit completes --- 1983,2034 ---- mod_timer(&adapter->watchdog_timer, jiffies); } + #ifdef CONFIG_E1000_NAPI + if(netif_rx_schedule_prep(netdev)) { + + /* Disable interrupts and register for poll. The flush + of the posted write is intentionally left out. + */ + + atomic_inc(&adapter->irq_sem); + E1000_WRITE_REG(&adapter->hw, IMC, ~0); + __netif_rx_schedule(netdev); + } + #else for(i = 0; i < E1000_MAX_INTR; i++) ! if(!e1000_clean_rx_irq(adapter) & !e1000_clean_tx_irq(adapter)) break; + #endif + } + + #ifdef CONFIG_E1000_NAPI + /** + * e1000_clean - NAPI Rx polling callback + * @adapter: board private structure + **/ + static int + e1000_clean(struct net_device *netdev, int *budget) + { + struct e1000_adapter *adapter = netdev->priv; + int work_to_do = min(*budget, netdev->quota); + int work_done = 0; + + e1000_clean_tx_irq(adapter); + e1000_clean_rx_irq(adapter, &work_done, work_to_do); + + *budget -= work_done; + netdev->quota -= work_done; + + if(work_done < work_to_do) { + netif_rx_complete(netdev); + e1000_irq_enable(adapter); + } + + return (work_done >= work_to_do); } + #endif /** * e1000_clean_tx_irq - Reclaim resources after transmit completes *************** *** 1939,1977 **** struct e1000_desc_ring *tx_ring = &adapter->tx_ring; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; ! struct e1000_tx_desc *tx_desc; ! int i, cleaned = FALSE; i = tx_ring->next_to_clean; ! tx_desc = E1000_TX_DESC(*tx_ring, i); ! while(tx_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { ! cleaned = TRUE; ! if(tx_ring->buffer_info[i].dma) { ! pci_unmap_page(pdev, ! tx_ring->buffer_info[i].dma, ! tx_ring->buffer_info[i].length, ! PCI_DMA_TODEVICE); ! tx_ring->buffer_info[i].dma = 0; ! } ! if(tx_ring->buffer_info[i].skb) { ! dev_kfree_skb_any(tx_ring->buffer_info[i].skb); ! tx_ring->buffer_info[i].skb = NULL; ! } ! tx_desc->buffer_addr = 0; ! tx_desc->lower.data = 0; ! tx_desc->upper.data = 0; ! if(++i == tx_ring->count) i = 0; ! tx_desc = E1000_TX_DESC(*tx_ring, i); } tx_ring->next_to_clean = i; --- 2041,2088 ---- struct e1000_desc_ring *tx_ring = &adapter->tx_ring; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; ! struct e1000_tx_desc *tx_desc, *eop_desc; ! struct e1000_buffer *buffer_info; ! unsigned int i, eop; ! boolean_t cleaned = FALSE; i = tx_ring->next_to_clean; ! eop = tx_ring->buffer_info[i].next_to_watch; ! eop_desc = E1000_TX_DESC(*tx_ring, eop); ! while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { ! for(cleaned = FALSE; !cleaned; ) { ! tx_desc = E1000_TX_DESC(*tx_ring, i); ! buffer_info = &tx_ring->buffer_info[i]; ! if(buffer_info->dma) { ! pci_unmap_page(pdev, ! buffer_info->dma, ! buffer_info->length, ! PCI_DMA_TODEVICE); ! buffer_info->dma = 0; ! } ! if(buffer_info->skb) { ! dev_kfree_skb_any(buffer_info->skb); ! buffer_info->skb = NULL; ! } ! tx_desc->buffer_addr = 0; ! tx_desc->lower.data = 0; ! tx_desc->upper.data = 0; ! cleaned = (i == eop); ! if(++i == tx_ring->count) i = 0; ! } ! ! eop = tx_ring->buffer_info[i].next_to_watch; ! eop_desc = E1000_TX_DESC(*tx_ring, eop); } tx_ring->next_to_clean = i; *************** *** 1988,2018 **** **/ static boolean_t e1000_clean_rx_irq(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; unsigned long flags; uint32_t length; uint8_t last_byte; ! int i, cleaned = FALSE; i = rx_ring->next_to_clean; rx_desc = E1000_RX_DESC(*rx_ring, i); while(rx_desc->status & E1000_RXD_STAT_DD) { cleaned = TRUE; pci_unmap_single(pdev, ! rx_ring->buffer_info[i].dma, ! rx_ring->buffer_info[i].length, PCI_DMA_FROMDEVICE); ! skb = rx_ring->buffer_info[i].skb; length = le16_to_cpu(rx_desc->length); if(!(rx_desc->status & E1000_RXD_STAT_EOP)) { --- 2099,2144 ---- **/ static boolean_t + #ifdef CONFIG_E1000_NAPI + e1000_clean_rx_irq(struct e1000_adapter *adapter, int *work_done, + int work_to_do) + #else e1000_clean_rx_irq(struct e1000_adapter *adapter) + #endif { 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 e1000_buffer *buffer_info; struct sk_buff *skb; unsigned long flags; uint32_t length; uint8_t last_byte; ! unsigned int i; ! boolean_t cleaned = FALSE; i = rx_ring->next_to_clean; rx_desc = E1000_RX_DESC(*rx_ring, i); while(rx_desc->status & E1000_RXD_STAT_DD) { + buffer_info = &rx_ring->buffer_info[i]; + + #ifdef CONFIG_E1000_NAPI + if(*work_done >= work_to_do) + break; + + (*work_done)++; + #endif cleaned = TRUE; pci_unmap_single(pdev, ! buffer_info->dma, ! buffer_info->length, PCI_DMA_FROMDEVICE); ! skb = buffer_info->skb; length = le16_to_cpu(rx_desc->length); if(!(rx_desc->status & E1000_RXD_STAT_EOP)) { *************** *** 2023,2029 **** dev_kfree_skb_irq(skb); rx_desc->status = 0; ! rx_ring->buffer_info[i].skb = NULL; if(++i == rx_ring->count) i = 0; --- 2149,2155 ---- dev_kfree_skb_irq(skb); rx_desc->status = 0; ! buffer_info->skb = NULL; if(++i == rx_ring->count) i = 0; *************** *** 2051,2057 **** dev_kfree_skb_irq(skb); rx_desc->status = 0; ! rx_ring->buffer_info[i].skb = NULL; if(++i == rx_ring->count) i = 0; --- 2177,2183 ---- dev_kfree_skb_irq(skb); rx_desc->status = 0; ! buffer_info->skb = NULL; if(++i == rx_ring->count) i = 0; *************** *** 2067,2082 **** 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; if(++i == rx_ring->count) i = 0; --- 2193,2219 ---- e1000_rx_checksum(adapter, rx_desc, skb); skb->protocol = eth_type_trans(skb, netdev); + #ifdef CONFIG_E1000_NAPI + if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { + vlan_hwaccel_receive_skb(skb, adapter->vlgrp, + le16_to_cpu(rx_desc->special & + E1000_RXD_SPC_VLAN_MASK)); + } else { + netif_receive_skb(skb); + } + #else /* CONFIG_E1000_NAPI */ if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { vlan_hwaccel_rx(skb, adapter->vlgrp, ! le16_to_cpu(rx_desc->special & ! E1000_RXD_SPC_VLAN_MASK)); } else { netif_rx(skb); } + #endif /* CONFIG_E1000_NAPI */ netdev->last_rx = jiffies; rx_desc->status = 0; ! buffer_info->skb = NULL; if(++i == rx_ring->count) i = 0; *************** *** 2102,2114 **** 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 = 2; ! int i; 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); --- 2239,2253 ---- struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; struct e1000_rx_desc *rx_desc; + struct e1000_buffer *buffer_info; struct sk_buff *skb; int reserve_len = 2; ! unsigned int i; i = rx_ring->next_to_use; + buffer_info = &rx_ring->buffer_info[i]; ! while(!buffer_info->skb) { rx_desc = E1000_RX_DESC(*rx_ring, i); skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len); *************** *** 2126,2140 **** 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 - 1)) == i) { /* Force memory writes to complete before letting h/w --- 2265,2279 ---- skb->dev = netdev; ! buffer_info->skb = skb; ! buffer_info->length = adapter->rx_buffer_len; ! buffer_info->dma = pci_map_single(pdev, skb->data, adapter->rx_buffer_len, PCI_DMA_FROMDEVICE); ! rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); if((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i) { /* Force memory writes to complete before letting h/w *************** *** 2147,2152 **** --- 2286,2292 ---- } if(++i == rx_ring->count) i = 0; + buffer_info = &rx_ring->buffer_info[i]; } rx_ring->next_to_use = i; *************** *** 2525,2531 **** return NOTIFY_DONE; } - static int e1000_suspend(struct pci_dev *pdev, uint32_t state) { --- 2665,2670 ---- *************** *** 2633,2652 **** } #endif - #ifdef HAVE_POLL_CONTROLLER - /* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ - - static void e1000_netpoll (struct net_device *dev) - { - if (!netdump_mode) disable_irq(dev->irq); - e1000_intr (dev->irq, dev, NULL); - if (!netdump_mode) enable_irq(dev->irq); - } - - #endif - /* e1000_main.c */ --- 2772,2775 ---- diff -Ncr linux-2.4.22-old/drivers/net/e1000/e1000_osdep.h linux-2.4.22/drivers/net/e1000/e1000_osdep.h *** linux-2.4.22-old/drivers/net/e1000/e1000_osdep.h 2003-11-18 17:22:41.000000000 +0900 --- linux-2.4.22/drivers/net/e1000/e1000_osdep.h 2003-08-25 20:44:42.000000000 +0900 *************** *** 27,33 **** *******************************************************************************/ ! /* glue for the OS independant part of e1000 * includes register access macros */ --- 27,33 ---- *******************************************************************************/ ! /* glue for the OS independent part of e1000 * includes register access macros */