diff options
| author | Chris Zankel <[email protected]> | 2015-04-14 03:51:35 +0000 | 
|---|---|---|
| committer | Chris Zankel <[email protected]> | 2015-04-14 03:51:35 +0000 | 
| commit | 7ead5b7e4a3cf4a16579a8f164022345b93fe972 (patch) | |
| tree | 0a9b9497f53d1593c9e2ac197b2e686ea74a9975 /drivers/net/ethernet/intel/igb/igb_main.c | |
| parent | 834a316eeebcb75316c0a7d9088fa638c52dc584 (diff) | |
| parent | 39a8804455fb23f09157341d3ba7db6d7ae6ee76 (diff) | |
Merge tag 'v4.0' into for_next
Linux 4.0
Diffstat (limited to 'drivers/net/ethernet/intel/igb/igb_main.c')
| -rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 157 | 
1 files changed, 104 insertions, 53 deletions
| diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index ff59897a9463..f366b3b96d03 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -5035,9 +5035,9 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,  	skb_tx_timestamp(skb); -	if (vlan_tx_tag_present(skb)) { +	if (skb_vlan_tag_present(skb)) {  		tx_flags |= IGB_TX_FLAGS_VLAN; -		tx_flags |= (vlan_tx_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT); +		tx_flags |= (skb_vlan_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT);  	}  	/* record initial flags and protocol */ @@ -5384,6 +5384,80 @@ void igb_update_stats(struct igb_adapter *adapter,  	}  } +static void igb_tsync_interrupt(struct igb_adapter *adapter) +{ +	struct e1000_hw *hw = &adapter->hw; +	struct ptp_clock_event event; +	struct timespec ts; +	u32 ack = 0, tsauxc, sec, nsec, tsicr = rd32(E1000_TSICR); + +	if (tsicr & TSINTR_SYS_WRAP) { +		event.type = PTP_CLOCK_PPS; +		if (adapter->ptp_caps.pps) +			ptp_clock_event(adapter->ptp_clock, &event); +		else +			dev_err(&adapter->pdev->dev, "unexpected SYS WRAP"); +		ack |= TSINTR_SYS_WRAP; +	} + +	if (tsicr & E1000_TSICR_TXTS) { +		/* retrieve hardware timestamp */ +		schedule_work(&adapter->ptp_tx_work); +		ack |= E1000_TSICR_TXTS; +	} + +	if (tsicr & TSINTR_TT0) { +		spin_lock(&adapter->tmreg_lock); +		ts = timespec_add(adapter->perout[0].start, +				  adapter->perout[0].period); +		wr32(E1000_TRGTTIML0, ts.tv_nsec); +		wr32(E1000_TRGTTIMH0, ts.tv_sec); +		tsauxc = rd32(E1000_TSAUXC); +		tsauxc |= TSAUXC_EN_TT0; +		wr32(E1000_TSAUXC, tsauxc); +		adapter->perout[0].start = ts; +		spin_unlock(&adapter->tmreg_lock); +		ack |= TSINTR_TT0; +	} + +	if (tsicr & TSINTR_TT1) { +		spin_lock(&adapter->tmreg_lock); +		ts = timespec_add(adapter->perout[1].start, +				  adapter->perout[1].period); +		wr32(E1000_TRGTTIML1, ts.tv_nsec); +		wr32(E1000_TRGTTIMH1, ts.tv_sec); +		tsauxc = rd32(E1000_TSAUXC); +		tsauxc |= TSAUXC_EN_TT1; +		wr32(E1000_TSAUXC, tsauxc); +		adapter->perout[1].start = ts; +		spin_unlock(&adapter->tmreg_lock); +		ack |= TSINTR_TT1; +	} + +	if (tsicr & TSINTR_AUTT0) { +		nsec = rd32(E1000_AUXSTMPL0); +		sec  = rd32(E1000_AUXSTMPH0); +		event.type = PTP_CLOCK_EXTTS; +		event.index = 0; +		event.timestamp = sec * 1000000000ULL + nsec; +		ptp_clock_event(adapter->ptp_clock, &event); +		ack |= TSINTR_AUTT0; +	} + +	if (tsicr & TSINTR_AUTT1) { +		nsec = rd32(E1000_AUXSTMPL1); +		sec  = rd32(E1000_AUXSTMPH1); +		event.type = PTP_CLOCK_EXTTS; +		event.index = 1; +		event.timestamp = sec * 1000000000ULL + nsec; +		ptp_clock_event(adapter->ptp_clock, &event); +		ack |= TSINTR_AUTT1; +	} + +	/* acknowledge the interrupts */ +	wr32(E1000_TSICR, ack); +} +  static irqreturn_t igb_msix_other(int irq, void *data)  {  	struct igb_adapter *adapter = data; @@ -5415,16 +5489,8 @@ static irqreturn_t igb_msix_other(int irq, void *data)  			mod_timer(&adapter->watchdog_timer, jiffies + 1);  	} -	if (icr & E1000_ICR_TS) { -		u32 tsicr = rd32(E1000_TSICR); - -		if (tsicr & E1000_TSICR_TXTS) { -			/* acknowledge the interrupt */ -			wr32(E1000_TSICR, E1000_TSICR_TXTS); -			/* retrieve hardware timestamp */ -			schedule_work(&adapter->ptp_tx_work); -		} -	} +	if (icr & E1000_ICR_TS) +		igb_tsync_interrupt(adapter);  	wr32(E1000_EIMS, adapter->eims_other); @@ -6011,8 +6077,12 @@ static void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf)  	adapter->vf_data[vf].flags |= IGB_VF_FLAG_CTS;  	/* reply to reset with ack and vf mac address */ -	msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK; -	memcpy(addr, vf_mac, ETH_ALEN); +	if (!is_zero_ether_addr(vf_mac)) { +		msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK; +		memcpy(addr, vf_mac, ETH_ALEN); +	} else { +		msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_NACK; +	}  	igb_write_mbx(hw, msgbuf, 3, vf);  } @@ -6203,16 +6273,8 @@ static irqreturn_t igb_intr_msi(int irq, void *data)  			mod_timer(&adapter->watchdog_timer, jiffies + 1);  	} -	if (icr & E1000_ICR_TS) { -		u32 tsicr = rd32(E1000_TSICR); - -		if (tsicr & E1000_TSICR_TXTS) { -			/* acknowledge the interrupt */ -			wr32(E1000_TSICR, E1000_TSICR_TXTS); -			/* retrieve hardware timestamp */ -			schedule_work(&adapter->ptp_tx_work); -		} -	} +	if (icr & E1000_ICR_TS) +		igb_tsync_interrupt(adapter);  	napi_schedule(&q_vector->napi); @@ -6257,16 +6319,8 @@ static irqreturn_t igb_intr(int irq, void *data)  			mod_timer(&adapter->watchdog_timer, jiffies + 1);  	} -	if (icr & E1000_ICR_TS) { -		u32 tsicr = rd32(E1000_TSICR); - -		if (tsicr & E1000_TSICR_TXTS) { -			/* acknowledge the interrupt */ -			wr32(E1000_TSICR, E1000_TSICR_TXTS); -			/* retrieve hardware timestamp */ -			schedule_work(&adapter->ptp_tx_work); -		} -	} +	if (icr & E1000_ICR_TS) +		igb_tsync_interrupt(adapter);  	napi_schedule(&q_vector->napi); @@ -6527,15 +6581,17 @@ static void igb_reuse_rx_page(struct igb_ring *rx_ring,  					 DMA_FROM_DEVICE);  } +static inline bool igb_page_is_reserved(struct page *page) +{ +	return (page_to_nid(page) != numa_mem_id()) || page->pfmemalloc; +} +  static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer,  				  struct page *page,  				  unsigned int truesize)  {  	/* avoid re-using remote pages */ -	if (unlikely(page_to_nid(page) != numa_node_id())) -		return false; - -	if (unlikely(page->pfmemalloc)) +	if (unlikely(igb_page_is_reserved(page)))  		return false;  #if (PAGE_SIZE < 8192) @@ -6545,22 +6601,19 @@ static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer,  	/* flip page offset to other buffer */  	rx_buffer->page_offset ^= IGB_RX_BUFSZ; - -	/* Even if we own the page, we are not allowed to use atomic_set() -	 * This would break get_page_unless_zero() users. -	 */ -	atomic_inc(&page->_count);  #else  	/* move offset up to the next cache line */  	rx_buffer->page_offset += truesize;  	if (rx_buffer->page_offset > (PAGE_SIZE - IGB_RX_BUFSZ))  		return false; - -	/* bump ref count on page before it is given to the stack */ -	get_page(page);  #endif +	/* Even if we own the page, we are not allowed to use atomic_set() +	 * This would break get_page_unless_zero() users. +	 */ +	atomic_inc(&page->_count); +  	return true;  } @@ -6603,13 +6656,12 @@ static bool igb_add_rx_frag(struct igb_ring *rx_ring,  		memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long))); -		/* we can reuse buffer as-is, just make sure it is local */ -		if (likely((page_to_nid(page) == numa_node_id()) && -			   !page->pfmemalloc)) +		/* page is not reserved, we can reuse buffer as-is */ +		if (likely(!igb_page_is_reserved(page)))  			return true;  		/* this page cannot be reused so discard it */ -		put_page(page); +		__free_page(page);  		return false;  	} @@ -6627,7 +6679,6 @@ static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring,  	struct page *page;  	rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; -  	page = rx_buffer->page;  	prefetchw(page); @@ -7042,8 +7093,8 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)  			i -= rx_ring->count;  		} -		/* clear the hdr_addr for the next_to_use descriptor */ -		rx_desc->read.hdr_addr = 0; +		/* clear the status bits for the next_to_use descriptor */ +		rx_desc->wb.upper.status_error = 0;  		cleaned_count--;  	} while (cleaned_count); |