diff options
Diffstat (limited to 'drivers/net/e1000e/netdev.c')
-rw-r--r-- | drivers/net/e1000e/netdev.c | 251 |
1 files changed, 138 insertions, 113 deletions
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 376924804f3..11a527484e1 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2008 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -65,17 +65,6 @@ static const struct e1000_info *e1000_info_tbl[] = { [board_pchlan] = &e1000_pch_info, }; -#ifdef DEBUG -/** - * e1000_get_hw_dev_name - return device name string - * used by hardware layer to print debugging information - **/ -char *e1000e_get_hw_dev_name(struct e1000_hw *hw) -{ - return hw->adapter->netdev->name; -} -#endif - /** * e1000_desc_unused - calculate if we have unused descriptors **/ @@ -415,6 +404,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, { struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; + struct e1000_hw *hw = &adapter->hw; struct e1000_ring *rx_ring = adapter->rx_ring; struct e1000_rx_desc *rx_desc, *next_rxd; struct e1000_buffer *buffer_info, *next_buffer; @@ -464,8 +454,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, * packet, also make sure the frame isn't just CRC only */ if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) { /* All receives must fit into a single buffer */ - e_dbg("%s: Receive packet consumed multiple buffers\n", - netdev->name); + e_dbg("Receive packet consumed multiple buffers\n"); /* recycle */ buffer_info->skb = skb; goto next_desc; @@ -555,15 +544,27 @@ static void e1000_put_txbuf(struct e1000_adapter *adapter, buffer_info->time_stamp = 0; } -static void e1000_print_tx_hang(struct e1000_adapter *adapter) +static void e1000_print_hw_hang(struct work_struct *work) { + struct e1000_adapter *adapter = container_of(work, + struct e1000_adapter, + print_hang_task); struct e1000_ring *tx_ring = adapter->tx_ring; unsigned int i = tx_ring->next_to_clean; unsigned int eop = tx_ring->buffer_info[i].next_to_watch; struct e1000_tx_desc *eop_desc = E1000_TX_DESC(*tx_ring, eop); + struct e1000_hw *hw = &adapter->hw; + u16 phy_status, phy_1000t_status, phy_ext_status; + u16 pci_status; + + e1e_rphy(hw, PHY_STATUS, &phy_status); + e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status); + e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status); + + pci_read_config_word(adapter->pdev, PCI_STATUS, &pci_status); - /* detected Tx unit hang */ - e_err("Detected Tx Unit Hang:\n" + /* detected Hardware unit hang */ + e_err("Detected Hardware Unit Hang:\n" " TDH <%x>\n" " TDT <%x>\n" " next_to_use <%x>\n" @@ -572,7 +573,12 @@ static void e1000_print_tx_hang(struct e1000_adapter *adapter) " time_stamp <%lx>\n" " next_to_watch <%x>\n" " jiffies <%lx>\n" - " next_to_watch.status <%x>\n", + " next_to_watch.status <%x>\n" + "MAC Status <%x>\n" + "PHY Status <%x>\n" + "PHY 1000BASE-T Status <%x>\n" + "PHY Extended Status <%x>\n" + "PCI Status <%x>\n", readl(adapter->hw.hw_addr + tx_ring->head), readl(adapter->hw.hw_addr + tx_ring->tail), tx_ring->next_to_use, @@ -580,7 +586,12 @@ static void e1000_print_tx_hang(struct e1000_adapter *adapter) tx_ring->buffer_info[eop].time_stamp, eop, jiffies, - eop_desc->upper.fields.status); + eop_desc->upper.fields.status, + er32(STATUS), + phy_status, + phy_1000t_status, + phy_ext_status, + pci_status); } /** @@ -654,14 +665,16 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) } if (adapter->detect_tx_hung) { - /* Detect a transmit hang in hardware, this serializes the - * check with the clearing of time_stamp and movement of i */ + /* + * Detect a transmit hang in hardware, this serializes the + * check with the clearing of time_stamp and movement of i + */ adapter->detect_tx_hung = 0; if (tx_ring->buffer_info[i].time_stamp && time_after(jiffies, tx_ring->buffer_info[i].time_stamp + (adapter->tx_timeout_factor * HZ)) && !(er32(STATUS) & E1000_STATUS_TXOFF)) { - e1000_print_tx_hang(adapter); + schedule_work(&adapter->print_hang_task); netif_stop_queue(netdev); } } @@ -682,6 +695,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, int *work_done, int work_to_do) { + struct e1000_hw *hw = &adapter->hw; union e1000_rx_desc_packet_split *rx_desc, *next_rxd; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; @@ -725,8 +739,8 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, buffer_info->dma = 0; if (!(staterr & E1000_RXD_STAT_EOP)) { - e_dbg("%s: Packet Split buffers didn't pick up the " - "full packet\n", netdev->name); + e_dbg("Packet Split buffers didn't pick up the full " + "packet\n"); dev_kfree_skb_irq(skb); goto next_desc; } @@ -739,8 +753,8 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, length = le16_to_cpu(rx_desc->wb.middle.length0); if (!length) { - e_dbg("%s: Last part of the packet spanning multiple " - "descriptors\n", netdev->name); + e_dbg("Last part of the packet spanning multiple " + "descriptors\n"); dev_kfree_skb_irq(skb); goto next_desc; } @@ -1176,7 +1190,7 @@ static irqreturn_t e1000_intr(int irq, void *data) struct e1000_hw *hw = &adapter->hw; u32 rctl, icr = er32(ICR); - if (!icr) + if (!icr || test_bit(__E1000_DOWN, &adapter->state)) return IRQ_NONE; /* Not our interrupt */ /* @@ -1458,7 +1472,7 @@ static int e1000_request_msix(struct e1000_adapter *adapter) else memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ); err = request_irq(adapter->msix_entries[vector].vector, - &e1000_intr_msix_rx, 0, adapter->rx_ring->name, + e1000_intr_msix_rx, 0, adapter->rx_ring->name, netdev); if (err) goto out; @@ -1471,7 +1485,7 @@ static int e1000_request_msix(struct e1000_adapter *adapter) else memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ); err = request_irq(adapter->msix_entries[vector].vector, - &e1000_intr_msix_tx, 0, adapter->tx_ring->name, + e1000_intr_msix_tx, 0, adapter->tx_ring->name, netdev); if (err) goto out; @@ -1480,7 +1494,7 @@ static int e1000_request_msix(struct e1000_adapter *adapter) vector++; err = request_irq(adapter->msix_entries[vector].vector, - &e1000_msix_other, 0, netdev->name, netdev); + e1000_msix_other, 0, netdev->name, netdev); if (err) goto out; @@ -1511,7 +1525,7 @@ static int e1000_request_irq(struct e1000_adapter *adapter) e1000e_set_interrupt_capability(adapter); } if (adapter->flags & FLAG_MSI_ENABLED) { - err = request_irq(adapter->pdev->irq, &e1000_intr_msi, 0, + err = request_irq(adapter->pdev->irq, e1000_intr_msi, 0, netdev->name, netdev); if (!err) return err; @@ -1521,7 +1535,7 @@ static int e1000_request_irq(struct e1000_adapter *adapter) adapter->int_mode = E1000E_INT_MODE_LEGACY; } - err = request_irq(adapter->pdev->irq, &e1000_intr, IRQF_SHARED, + err = request_irq(adapter->pdev->irq, e1000_intr, IRQF_SHARED, netdev->name, netdev); if (err) e_err("Unable to allocate interrupt, Error: %d\n", err); @@ -2441,8 +2455,6 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) ew32(ITR, 1000000000 / (adapter->itr * 256)); ctrl_ext = er32(CTRL_EXT); - /* Reset delay timers after every interrupt */ - ctrl_ext |= E1000_CTRL_EXT_INT_TIMER_CLR; /* Auto-Mask interrupts upon ICR access */ ctrl_ext |= E1000_CTRL_EXT_IAME; ew32(IAM, 0xffffffff); @@ -2484,21 +2496,23 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) * packet size is equal or larger than the specified value (in 8 byte * units), e.g. using jumbo frames when setting to E1000_ERT_2048 */ - if ((adapter->flags & FLAG_HAS_ERT) && - (adapter->netdev->mtu > ETH_DATA_LEN)) { - u32 rxdctl = er32(RXDCTL(0)); - ew32(RXDCTL(0), rxdctl | 0x3); - ew32(ERT, E1000_ERT_2048 | (1 << 13)); - /* - * With jumbo frames and early-receive enabled, excessive - * C4->C2 latencies result in dropped transactions. - */ - pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, - e1000e_driver_name, 55); - } else { - pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, - e1000e_driver_name, - PM_QOS_DEFAULT_VALUE); + if (adapter->flags & FLAG_HAS_ERT) { + if (adapter->netdev->mtu > ETH_DATA_LEN) { + u32 rxdctl = er32(RXDCTL(0)); + ew32(RXDCTL(0), rxdctl | 0x3); + ew32(ERT, E1000_ERT_2048 | (1 << 13)); + /* + * With jumbo frames and early-receive enabled, + * excessive C-state transition latencies result in + * dropped transactions. + */ + pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, + adapter->netdev->name, 55); + } else { + pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, + adapter->netdev->name, + PM_QOS_DEFAULT_VALUE); + } } /* Enable Receives */ @@ -2816,6 +2830,12 @@ int e1000e_up(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; + /* DMA latency requirement to workaround early-receive/jumbo issue */ + if (adapter->flags & FLAG_HAS_ERT) + pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, + adapter->netdev->name, + PM_QOS_DEFAULT_VALUE); + /* hardware has been reset, we need to reload some things */ e1000_configure(adapter); @@ -2876,6 +2896,10 @@ void e1000e_down(struct e1000_adapter *adapter) e1000_clean_tx_ring(adapter); e1000_clean_rx_ring(adapter); + if (adapter->flags & FLAG_HAS_ERT) + pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, + adapter->netdev->name); + /* * TODO: for power management, we could drop the link and * pci_disable_device here. @@ -2933,7 +2957,7 @@ static irqreturn_t e1000_intr_msi_test(int irq, void *data) struct e1000_hw *hw = &adapter->hw; u32 icr = er32(ICR); - e_dbg("%s: icr is %08X\n", netdev->name, icr); + e_dbg("icr is %08X\n", icr); if (icr & E1000_ICR_RXSEQ) { adapter->flags &= ~FLAG_MSI_TEST_FAILED; wmb(); @@ -2970,7 +2994,7 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) if (err) goto msi_test_failed; - err = request_irq(adapter->pdev->irq, &e1000_intr_msi_test, 0, + err = request_irq(adapter->pdev->irq, e1000_intr_msi_test, 0, netdev->name, netdev); if (err) { pci_disable_msi(adapter->pdev); @@ -3003,7 +3027,7 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) goto msi_test_failed; /* okay so the test worked, restore settings */ - e_dbg("%s: MSI interrupt test succeeded!\n", netdev->name); + e_dbg("MSI interrupt test succeeded!\n"); msi_test_failed: e1000e_set_interrupt_capability(adapter); e1000_request_irq(adapter); @@ -3737,68 +3761,64 @@ static int e1000_tso(struct e1000_adapter *adapter, u8 ipcss, ipcso, tucss, tucso, hdr_len; int err; - if (skb_is_gso(skb)) { - if (skb_header_cloned(skb)) { - err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); - if (err) - return err; - } + if (!skb_is_gso(skb)) + return 0; - hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - mss = skb_shinfo(skb)->gso_size; - if (skb->protocol == htons(ETH_P_IP)) { - struct iphdr *iph = ip_hdr(skb); - iph->tot_len = 0; - iph->check = 0; - tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, - iph->daddr, 0, - IPPROTO_TCP, - 0); - cmd_length = E1000_TXD_CMD_IP; - ipcse = skb_transport_offset(skb) - 1; - } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) { - ipv6_hdr(skb)->payload_len = 0; - tcp_hdr(skb)->check = - ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); - ipcse = 0; - } - ipcss = skb_network_offset(skb); - ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data; - tucss = skb_transport_offset(skb); - tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data; - tucse = 0; + if (skb_header_cloned(skb)) { + err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); + if (err) + return err; + } - cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | - E1000_TXD_CMD_TCP | (skb->len - (hdr_len))); + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + mss = skb_shinfo(skb)->gso_size; + if (skb->protocol == htons(ETH_P_IP)) { + struct iphdr *iph = ip_hdr(skb); + iph->tot_len = 0; + iph->check = 0; + tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, + 0, IPPROTO_TCP, 0); + cmd_length = E1000_TXD_CMD_IP; + ipcse = skb_transport_offset(skb) - 1; + } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) { + ipv6_hdr(skb)->payload_len = 0; + tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, + &ipv6_hdr(skb)->daddr, + 0, IPPROTO_TCP, 0); + ipcse = 0; + } + ipcss = skb_network_offset(skb); + ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data; + tucss = skb_transport_offset(skb); + tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data; + tucse = 0; - i = tx_ring->next_to_use; - context_desc = E1000_CONTEXT_DESC(*tx_ring, i); - buffer_info = &tx_ring->buffer_info[i]; + cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | + E1000_TXD_CMD_TCP | (skb->len - (hdr_len))); - 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(cmd_length); + i = tx_ring->next_to_use; + context_desc = E1000_CONTEXT_DESC(*tx_ring, i); + buffer_info = &tx_ring->buffer_info[i]; - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = 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(cmd_length); - i++; - if (i == tx_ring->count) - i = 0; - tx_ring->next_to_use = i; + buffer_info->time_stamp = jiffies; + buffer_info->next_to_watch = i; - return 1; - } + i++; + if (i == tx_ring->count) + i = 0; + tx_ring->next_to_use = i; - return 0; + return 1; } static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) @@ -4322,6 +4342,8 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, data->phy_id = adapter->hw.phy.addr; break; case SIOCGMIIREG: + e1000_phy_read_status(adapter); + switch (data->reg_num & 0x1F) { case MII_BMCR: data->val_out = adapter->phy_regs.bmcr; @@ -4429,7 +4451,7 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) e1e_wphy(&adapter->hw, BM_WUC, E1000_WUC_PME_EN); /* activate PHY wakeup */ - retval = hw->phy.ops.acquire_phy(hw); + retval = hw->phy.ops.acquire(hw); if (retval) { e_err("Could not acquire PHY\n"); return retval; @@ -4446,7 +4468,7 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) if (retval) e_err("Could not set PHY Host Wakeup bit\n"); out: - hw->phy.ops.release_phy(hw); + hw->phy.ops.release(hw); return retval; } @@ -5120,6 +5142,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task); INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround); INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task); + INIT_WORK(&adapter->print_hang_task, e1000_print_hw_hang); /* Initialize link parameters. User can change them with ethtool */ adapter->hw.mac.autoneg = 1; @@ -5243,6 +5266,11 @@ static void __devexit e1000_remove(struct pci_dev *pdev) del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->phy_info_timer); + cancel_work_sync(&adapter->reset_task); + cancel_work_sync(&adapter->watchdog_task); + cancel_work_sync(&adapter->downshift_task); + cancel_work_sync(&adapter->update_phy_task); + cancel_work_sync(&adapter->print_hang_task); flush_scheduled_work(); /* @@ -5374,12 +5402,10 @@ static int __init e1000_init_module(void) int ret; printk(KERN_INFO "%s: Intel(R) PRO/1000 Network Driver - %s\n", e1000e_driver_name, e1000e_driver_version); - printk(KERN_INFO "%s: Copyright (c) 1999-2008 Intel Corporation.\n", + printk(KERN_INFO "%s: Copyright (c) 1999 - 2009 Intel Corporation.\n", e1000e_driver_name); ret = pci_register_driver(&e1000_driver); - pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, e1000e_driver_name, - PM_QOS_DEFAULT_VALUE); - + return ret; } module_init(e1000_init_module); @@ -5393,7 +5419,6 @@ module_init(e1000_init_module); static void __exit e1000_exit_module(void) { pci_unregister_driver(&e1000_driver); - pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, e1000e_driver_name); } module_exit(e1000_exit_module); |