diff options
Diffstat (limited to 'drivers/net/e1000e/netdev.c')
| -rw-r--r-- | drivers/net/e1000e/netdev.c | 520 | 
1 files changed, 269 insertions, 251 deletions
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 0687c6aa4e4..c3105c5087e 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   **/ @@ -167,7 +156,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,  	struct e1000_buffer *buffer_info;  	struct sk_buff *skb;  	unsigned int i; -	unsigned int bufsz = adapter->rx_buffer_len + NET_IP_ALIGN; +	unsigned int bufsz = adapter->rx_buffer_len;  	i = rx_ring->next_to_use;  	buffer_info = &rx_ring->buffer_info[i]; @@ -179,20 +168,13 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,  			goto map_skb;  		} -		skb = netdev_alloc_skb(netdev, bufsz); +		skb = netdev_alloc_skb_ip_align(netdev, bufsz);  		if (!skb) {  			/* Better luck next round */  			adapter->alloc_rx_buff_failed++;  			break;  		} -		/* -		 * Make buffer alignment 2 beyond a 16 byte boundary -		 * this will result in a 16 byte aligned IP header after -		 * the 14 byte MAC header is removed -		 */ -		skb_reserve(skb, NET_IP_ALIGN); -  		buffer_info->skb = skb;  map_skb:  		buffer_info->dma = pci_map_single(pdev, skb->data, @@ -284,21 +266,14 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,  			     cpu_to_le64(ps_page->dma);  		} -		skb = netdev_alloc_skb(netdev, -				       adapter->rx_ps_bsize0 + NET_IP_ALIGN); +		skb = netdev_alloc_skb_ip_align(netdev, +						adapter->rx_ps_bsize0);  		if (!skb) {  			adapter->alloc_rx_buff_failed++;  			break;  		} -		/* -		 * Make buffer alignment 2 beyond a 16 byte boundary -		 * this will result in a 16 byte aligned IP header after -		 * the 14 byte MAC header is removed -		 */ -		skb_reserve(skb, NET_IP_ALIGN); -  		buffer_info->skb = skb;  		buffer_info->dma = pci_map_single(pdev, skb->data,  						  adapter->rx_ps_bsize0, @@ -359,9 +334,7 @@ static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,  	struct e1000_buffer *buffer_info;  	struct sk_buff *skb;  	unsigned int i; -	unsigned int bufsz = 256 - -	                     16 /* for skb_reserve */ - -	                     NET_IP_ALIGN; +	unsigned int bufsz = 256 - 16 /* for skb_reserve */;  	i = rx_ring->next_to_use;  	buffer_info = &rx_ring->buffer_info[i]; @@ -373,19 +346,13 @@ static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,  			goto check_page;  		} -		skb = netdev_alloc_skb(netdev, bufsz); +		skb = netdev_alloc_skb_ip_align(netdev, bufsz);  		if (unlikely(!skb)) {  			/* Better luck next round */  			adapter->alloc_rx_buff_failed++;  			break;  		} -		/* Make buffer alignment 2 beyond a 16 byte boundary -		 * this will result in a 16 byte aligned IP header after -		 * the 14 byte MAC header is removed -		 */ -		skb_reserve(skb, NET_IP_ALIGN); -  		buffer_info->skb = skb;  check_page:  		/* allocate a new page if necessary */ @@ -437,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; @@ -486,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; @@ -513,9 +480,8 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,  		 */  		if (length < copybreak) {  			struct sk_buff *new_skb = -			    netdev_alloc_skb(netdev, length + NET_IP_ALIGN); +			    netdev_alloc_skb_ip_align(netdev, length);  			if (new_skb) { -				skb_reserve(new_skb, NET_IP_ALIGN);  				skb_copy_to_linear_data_offset(new_skb,  							       -NET_IP_ALIGN,  							       (skb->data - @@ -560,33 +526,52 @@ next_desc:  	adapter->total_rx_bytes += total_rx_bytes;  	adapter->total_rx_packets += total_rx_packets; -	adapter->net_stats.rx_bytes += total_rx_bytes; -	adapter->net_stats.rx_packets += total_rx_packets; +	netdev->stats.rx_bytes += total_rx_bytes; +	netdev->stats.rx_packets += total_rx_packets;  	return cleaned;  }  static void e1000_put_txbuf(struct e1000_adapter *adapter,  			     struct e1000_buffer *buffer_info)  { -	buffer_info->dma = 0; +	if (buffer_info->dma) { +		if (buffer_info->mapped_as_page) +			pci_unmap_page(adapter->pdev, buffer_info->dma, +				       buffer_info->length, PCI_DMA_TODEVICE); +		else +			pci_unmap_single(adapter->pdev,	buffer_info->dma, +					 buffer_info->length, +					 PCI_DMA_TODEVICE); +		buffer_info->dma = 0; +	}  	if (buffer_info->skb) { -		skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb, -		              DMA_TO_DEVICE);  		dev_kfree_skb_any(buffer_info->skb);  		buffer_info->skb = NULL;  	}  	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" @@ -595,7 +580,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, @@ -603,7 +593,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);  }  /** @@ -677,21 +672,23 @@ 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); +			       + (adapter->tx_timeout_factor * HZ)) && +		    !(er32(STATUS) & E1000_STATUS_TXOFF)) { +			schedule_work(&adapter->print_hang_task);  			netif_stop_queue(netdev);  		}  	}  	adapter->total_tx_bytes += total_tx_bytes;  	adapter->total_tx_packets += total_tx_packets; -	adapter->net_stats.tx_bytes += total_tx_bytes; -	adapter->net_stats.tx_packets += total_tx_packets; +	netdev->stats.tx_bytes += total_tx_bytes; +	netdev->stats.tx_packets += total_tx_packets;  	return (count < tx_ring->count);  } @@ -705,6 +702,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; @@ -748,8 +746,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;  		} @@ -762,8 +760,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;  		} @@ -871,8 +869,8 @@ next_desc:  	adapter->total_rx_bytes += total_rx_bytes;  	adapter->total_rx_packets += total_rx_packets; -	adapter->net_stats.rx_bytes += total_rx_bytes; -	adapter->net_stats.rx_packets += total_rx_packets; +	netdev->stats.rx_bytes += total_rx_bytes; +	netdev->stats.rx_packets += total_rx_packets;  	return cleaned;  } @@ -1051,8 +1049,8 @@ next_desc:  	adapter->total_rx_bytes += total_rx_bytes;  	adapter->total_rx_packets += total_rx_packets; -	adapter->net_stats.rx_bytes += total_rx_bytes; -	adapter->net_stats.rx_packets += total_rx_packets; +	netdev->stats.rx_bytes += total_rx_bytes; +	netdev->stats.rx_packets += total_rx_packets;  	return cleaned;  } @@ -1199,7 +1197,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 */  	/* @@ -1481,7 +1479,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; @@ -1494,7 +1492,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; @@ -1503,7 +1501,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; @@ -1534,7 +1532,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; @@ -1544,7 +1542,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); @@ -2040,11 +2038,14 @@ static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)  	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&  	    (vid == adapter->mng_vlan_id))  		return; +  	/* add VID to filter table */ -	index = (vid >> 5) & 0x7F; -	vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); -	vfta |= (1 << (vid & 0x1F)); -	e1000e_write_vfta(hw, index, vfta); +	if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { +		index = (vid >> 5) & 0x7F; +		vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); +		vfta |= (1 << (vid & 0x1F)); +		hw->mac.ops.write_vfta(hw, index, vfta); +	}  }  static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) @@ -2069,10 +2070,12 @@ static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)  	}  	/* remove VID from filter table */ -	index = (vid >> 5) & 0x7F; -	vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); -	vfta &= ~(1 << (vid & 0x1F)); -	e1000e_write_vfta(hw, index, vfta); +	if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { +		index = (vid >> 5) & 0x7F; +		vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); +		vfta &= ~(1 << (vid & 0x1F)); +		hw->mac.ops.write_vfta(hw, index, vfta); +	}  }  static void e1000_update_mng_vlan(struct e1000_adapter *adapter) @@ -2464,8 +2467,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); @@ -2507,21 +2508,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 */ @@ -2645,18 +2648,8 @@ static void e1000_configure(struct e1000_adapter *adapter)   **/  void e1000e_power_up_phy(struct e1000_adapter *adapter)  { -	u16 mii_reg = 0; - -	/* Just clear the power down bit to wake the phy back up */ -	if (adapter->hw.phy.media_type == e1000_media_type_copper) { -		/* -		 * According to the manual, the phy will retain its -		 * settings across a power-down/up cycle -		 */ -		e1e_rphy(&adapter->hw, PHY_CONTROL, &mii_reg); -		mii_reg &= ~MII_CR_POWER_DOWN; -		e1e_wphy(&adapter->hw, PHY_CONTROL, mii_reg); -	} +	if (adapter->hw.phy.ops.power_up) +		adapter->hw.phy.ops.power_up(&adapter->hw);  	adapter->hw.mac.ops.setup_link(&adapter->hw);  } @@ -2664,35 +2657,17 @@ void e1000e_power_up_phy(struct e1000_adapter *adapter)  /**   * e1000_power_down_phy - Power down the PHY   * - * Power down the PHY so no link is implied when interface is down - * The PHY cannot be powered down is management or WoL is active + * Power down the PHY so no link is implied when interface is down. + * The PHY cannot be powered down if management or WoL is active.   */  static void e1000_power_down_phy(struct e1000_adapter *adapter)  { -	struct e1000_hw *hw = &adapter->hw; -	u16 mii_reg; -  	/* WoL is enabled */  	if (adapter->wol)  		return; -	/* non-copper PHY? */ -	if (adapter->hw.phy.media_type != e1000_media_type_copper) -		return; - -	/* reset is blocked because of a SoL/IDER session */ -	if (e1000e_check_mng_mode(hw) || e1000_check_reset_block(hw)) -		return; - -	/* manageability (AMT) is enabled */ -	if (er32(MANC) & E1000_MANC_SMBUS_EN) -		return; - -	/* power down the PHY */ -	e1e_rphy(hw, PHY_CONTROL, &mii_reg); -	mii_reg |= MII_CR_POWER_DOWN; -	e1e_wphy(hw, PHY_CONTROL, mii_reg); -	mdelay(1); +	if (adapter->hw.phy.ops.power_down) +		adapter->hw.phy.ops.power_down(&adapter->hw);  }  /** @@ -2769,25 +2744,38 @@ void e1000e_reset(struct e1000_adapter *adapter)  	/*  	 * flow control settings  	 * -	 * The high water mark must be low enough to fit two full frame +	 * The high water mark must be low enough to fit one full frame  	 * (or the size used for early receive) above it in the Rx FIFO.  	 * Set it to the lower of:  	 * - 90% of the Rx FIFO size, and  	 * - the full Rx FIFO size minus the early receive size (for parts  	 *   with ERT support assuming ERT set to E1000_ERT_2048), or -	 * - the full Rx FIFO size minus two full frames +	 * - the full Rx FIFO size minus one full frame  	 */ -	if ((adapter->flags & FLAG_HAS_ERT) && -	    (adapter->netdev->mtu > ETH_DATA_LEN)) -		hwm = min(((pba << 10) * 9 / 10), -			  ((pba << 10) - (E1000_ERT_2048 << 3))); -	else -		hwm = min(((pba << 10) * 9 / 10), -			  ((pba << 10) - (2 * adapter->max_frame_size))); +	if (hw->mac.type == e1000_pchlan) { +		/* +		 * Workaround PCH LOM adapter hangs with certain network +		 * loads.  If hangs persist, try disabling Tx flow control. +		 */ +		if (adapter->netdev->mtu > ETH_DATA_LEN) { +			fc->high_water = 0x3500; +			fc->low_water  = 0x1500; +		} else { +			fc->high_water = 0x5000; +			fc->low_water  = 0x3000; +		} +	} else { +		if ((adapter->flags & FLAG_HAS_ERT) && +		    (adapter->netdev->mtu > ETH_DATA_LEN)) +			hwm = min(((pba << 10) * 9 / 10), +				  ((pba << 10) - (E1000_ERT_2048 << 3))); +		else +			hwm = min(((pba << 10) * 9 / 10), +				  ((pba << 10) - adapter->max_frame_size)); -	fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ -	fc->low_water = (fc->high_water - (2 * adapter->max_frame_size)); -	fc->low_water &= E1000_FCRTL_RTL; /* 8-byte granularity */ +		fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ +		fc->low_water = fc->high_water - 8; +	}  	if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME)  		fc->pause_time = 0xFFFF; @@ -2813,6 +2801,10 @@ void e1000e_reset(struct e1000_adapter *adapter)  	if (mac->ops.init_hw(hw))  		e_err("Hardware Error\n"); +	/* additional part of the flow-control workaround above */ +	if (hw->mac.type == e1000_pchlan) +		ew32(FCRTV_PCH, 0x1000); +  	e1000_update_mng_vlan(adapter);  	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ @@ -2839,6 +2831,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); @@ -2899,6 +2897,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. @@ -2956,7 +2958,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(); @@ -2993,7 +2995,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); @@ -3026,7 +3028,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); @@ -3287,6 +3289,7 @@ static void e1000_update_phy_info(unsigned long data)   **/  void e1000e_update_stats(struct e1000_adapter *adapter)  { +	struct net_device *netdev = adapter->netdev;  	struct e1000_hw *hw = &adapter->hw;  	struct pci_dev *pdev = adapter->pdev;  	u16 phy_data; @@ -3381,8 +3384,8 @@ void e1000e_update_stats(struct e1000_adapter *adapter)  	adapter->stats.tsctfc += er32(TSCTFC);  	/* Fill out the OS statistics structure */ -	adapter->net_stats.multicast = adapter->stats.mprc; -	adapter->net_stats.collisions = adapter->stats.colc; +	netdev->stats.multicast = adapter->stats.mprc; +	netdev->stats.collisions = adapter->stats.colc;  	/* Rx Errors */ @@ -3390,22 +3393,22 @@ void e1000e_update_stats(struct e1000_adapter *adapter)  	 * RLEC on some newer hardware can be incorrect so build  	 * our own version based on RUC and ROC  	 */ -	adapter->net_stats.rx_errors = adapter->stats.rxerrc + +	netdev->stats.rx_errors = adapter->stats.rxerrc +  		adapter->stats.crcerrs + adapter->stats.algnerrc +  		adapter->stats.ruc + adapter->stats.roc +  		adapter->stats.cexterr; -	adapter->net_stats.rx_length_errors = adapter->stats.ruc + +	netdev->stats.rx_length_errors = adapter->stats.ruc +  					      adapter->stats.roc; -	adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; -	adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; -	adapter->net_stats.rx_missed_errors = adapter->stats.mpc; +	netdev->stats.rx_crc_errors = adapter->stats.crcerrs; +	netdev->stats.rx_frame_errors = adapter->stats.algnerrc; +	netdev->stats.rx_missed_errors = adapter->stats.mpc;  	/* Tx Errors */ -	adapter->net_stats.tx_errors = adapter->stats.ecol + +	netdev->stats.tx_errors = adapter->stats.ecol +  				       adapter->stats.latecol; -	adapter->net_stats.tx_aborted_errors = adapter->stats.ecol; -	adapter->net_stats.tx_window_errors = adapter->stats.latecol; -	adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs; +	netdev->stats.tx_aborted_errors = adapter->stats.ecol; +	netdev->stats.tx_window_errors = adapter->stats.latecol; +	netdev->stats.tx_carrier_errors = adapter->stats.tncrs;  	/* Tx Dropped needs to be maintained elsewhere */ @@ -3610,7 +3613,7 @@ static void e1000_watchdog_task(struct work_struct *work)  			case SPEED_100:  				txb2b = 0;  				netdev->tx_queue_len = 100; -				/* maybe add some timeout factor ? */ +				adapter->tx_timeout_factor = 10;  				break;  			} @@ -3759,68 +3762,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) @@ -3892,23 +3891,14 @@ static int e1000_tx_map(struct e1000_adapter *adapter,  			unsigned int mss)  {  	struct e1000_ring *tx_ring = adapter->tx_ring; +	struct pci_dev *pdev = adapter->pdev;  	struct e1000_buffer *buffer_info;  	unsigned int len = skb_headlen(skb); -	unsigned int offset, size, count = 0, i; +	unsigned int offset = 0, size, count = 0, i;  	unsigned int f; -	dma_addr_t *map;  	i = tx_ring->next_to_use; -	if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) { -		dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); -		adapter->tx_dma_failed++; -		return 0; -	} - -	map = skb_shinfo(skb)->dma_maps; -	offset = 0; -  	while (len) {  		buffer_info = &tx_ring->buffer_info[i];  		size = min(len, max_per_txd); @@ -3916,11 +3906,15 @@ static int e1000_tx_map(struct e1000_adapter *adapter,  		buffer_info->length = size;  		buffer_info->time_stamp = jiffies;  		buffer_info->next_to_watch = i; -		buffer_info->dma = skb_shinfo(skb)->dma_head + offset; -		count++; +		buffer_info->dma = pci_map_single(pdev,	skb->data + offset, +						  size,	PCI_DMA_TODEVICE); +		buffer_info->mapped_as_page = false; +		if (pci_dma_mapping_error(pdev, buffer_info->dma)) +			goto dma_error;  		len -= size;  		offset += size; +		count++;  		if (len) {  			i++; @@ -3934,7 +3928,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter,  		frag = &skb_shinfo(skb)->frags[f];  		len = frag->size; -		offset = 0; +		offset = frag->page_offset;  		while (len) {  			i++; @@ -3947,7 +3941,12 @@ static int e1000_tx_map(struct e1000_adapter *adapter,  			buffer_info->length = size;  			buffer_info->time_stamp = jiffies;  			buffer_info->next_to_watch = i; -			buffer_info->dma = map[f] + offset; +			buffer_info->dma = pci_map_page(pdev, frag->page, +							offset, size, +							PCI_DMA_TODEVICE); +			buffer_info->mapped_as_page = true; +			if (pci_dma_mapping_error(pdev, buffer_info->dma)) +				goto dma_error;  			len -= size;  			offset += size; @@ -3959,6 +3958,22 @@ static int e1000_tx_map(struct e1000_adapter *adapter,  	tx_ring->buffer_info[first].next_to_watch = i;  	return count; + +dma_error: +	dev_err(&pdev->dev, "TX DMA map failed\n"); +	buffer_info->dma = 0; +	count--; + +	while (count >= 0) { +		count--; +		i--; +		if (i < 0) +			i += tx_ring->count; +		buffer_info = &tx_ring->buffer_info[i]; +		e1000_put_txbuf(adapter, buffer_info);; +	} + +	return 0;  }  static void e1000_tx_queue(struct e1000_adapter *adapter, @@ -4031,8 +4046,8 @@ static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter,  	u16 length, offset;  	if (vlan_tx_tag_present(skb)) { -		if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) -		    && (adapter->hw.mng_cookie.status & +		if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) && +		    (adapter->hw.mng_cookie.status &  			E1000_MNG_DHCP_COOKIE_STATUS_VLAN)))  			return 0;  	} @@ -4254,10 +4269,8 @@ static void e1000_reset_task(struct work_struct *work)   **/  static struct net_device_stats *e1000_get_stats(struct net_device *netdev)  { -	struct e1000_adapter *adapter = netdev_priv(netdev); -  	/* only return the current stats */ -	return &adapter->net_stats; +	return &netdev->stats;  }  /** @@ -4288,8 +4301,10 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)  	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))  		msleep(1); -	/* e1000e_down has a dependency on max_frame_size */ +	/* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */  	adapter->max_frame_size = max_frame; +	e_info("changing MTU from %d to %d\n", netdev->mtu, new_mtu); +	netdev->mtu = new_mtu;  	if (netif_running(netdev))  		e1000e_down(adapter); @@ -4319,9 +4334,6 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)  		adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN  					 + ETH_FCS_LEN; -	e_info("changing MTU from %d to %d\n", netdev->mtu, new_mtu); -	netdev->mtu = new_mtu; -  	if (netif_running(netdev))  		e1000e_up(adapter);  	else @@ -4346,6 +4358,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; @@ -4453,7 +4467,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; @@ -4470,7 +4484,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;  } @@ -5144,6 +5158,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; @@ -5267,19 +5282,24 @@ 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(); +	if (!(netdev->flags & IFF_UP)) +		e1000_power_down_phy(adapter); + +	unregister_netdev(netdev); +  	/*  	 * Release control of h/w to f/w.  If f/w is AMT enabled, this  	 * would have already happened in close and is redundant.  	 */  	e1000_release_hw_control(adapter); -	unregister_netdev(netdev); - -	if (!e1000_check_reset_block(&adapter->hw)) -		e1000_phy_hw_reset(&adapter->hw); -  	e1000e_reset_interrupt_capability(adapter);  	kfree(adapter->tx_ring);  	kfree(adapter->rx_ring); @@ -5345,6 +5365,7 @@ static struct pci_device_id e1000_pci_tbl[] = {  	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_C), board_ich8lan },  	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M), board_ich8lan },  	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M_AMT), board_ich8lan }, +	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_82567V_3), board_ich8lan },  	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE), board_ich9lan },  	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_G), board_ich9lan }, @@ -5398,12 +5419,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); @@ -5417,7 +5436,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);  |