diff options
Diffstat (limited to 'drivers/net/ethernet/intel/igb')
| -rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_i210.c | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igb/igb_ethtool.c | 8 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 156 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igb/igb_ptp.c | 192 | 
4 files changed, 302 insertions, 57 deletions
| diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c index 9265901455cd..b9b9d35494d2 100644 --- a/drivers/net/ethernet/intel/igb/e1000_i210.c +++ b/drivers/net/ethernet/intel/igb/e1000_i210.c @@ -792,7 +792,6 @@ s32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data)   **/  s32 igb_init_nvm_params_i210(struct e1000_hw *hw)  { -	s32 ret_val = 0;  	struct e1000_nvm_info *nvm = &hw->nvm;  	nvm->ops.acquire = igb_acquire_nvm_i210; @@ -813,7 +812,7 @@ s32 igb_init_nvm_params_i210(struct e1000_hw *hw)  		nvm->ops.validate = NULL;  		nvm->ops.update   = NULL;  	} -	return ret_val; +	return 0;  }  /** diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index fb1029352c3e..51a2dcaf553d 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -864,7 +864,9 @@ static void igb_get_drvinfo(struct net_device *netdev,  }  static void igb_get_ringparam(struct net_device *netdev, -			      struct ethtool_ringparam *ring) +			      struct ethtool_ringparam *ring, +			      struct kernel_ethtool_ringparam *kernel_ring, +			      struct netlink_ext_ack *extack)  {  	struct igb_adapter *adapter = netdev_priv(netdev); @@ -875,7 +877,9 @@ static void igb_get_ringparam(struct net_device *netdev,  }  static int igb_set_ringparam(struct net_device *netdev, -			     struct ethtool_ringparam *ring) +			     struct ethtool_ringparam *ring, +			     struct kernel_ethtool_ringparam *kernel_ring, +			     struct netlink_ext_ack *extack)  {  	struct igb_adapter *adapter = netdev_priv(netdev);  	struct igb_ring *temp_ring; diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 446894dde182..38ba92022cd4 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2927,7 +2927,7 @@ static int igb_xdp_xmit_back(struct igb_adapter *adapter, struct xdp_buff *xdp)  	nq = txring_txq(tx_ring);  	__netif_tx_lock(nq, cpu);  	/* Avoid transmit queue timeout since we share it with the slow path */ -	nq->trans_start = jiffies; +	txq_trans_cond_update(nq);  	ret = igb_xmit_xdp_ring(adapter, tx_ring, xdpf);  	__netif_tx_unlock(nq); @@ -2961,7 +2961,7 @@ static int igb_xdp_xmit(struct net_device *dev, int n,  	__netif_tx_lock(nq, cpu);  	/* Avoid transmit queue timeout since we share it with the slow path */ -	nq->trans_start = jiffies; +	txq_trans_cond_update(nq);  	for (i = 0; i < n; i++) {  		struct xdp_frame *xdpf = frames[i]; @@ -6739,12 +6739,119 @@ void igb_update_stats(struct igb_adapter *adapter)  	}  } -static void igb_tsync_interrupt(struct igb_adapter *adapter) +static void igb_perout(struct igb_adapter *adapter, int tsintr_tt)  { +	int pin = ptp_find_pin(adapter->ptp_clock, PTP_PF_PEROUT, tsintr_tt); +	struct e1000_hw *hw = &adapter->hw; +	struct timespec64 ts; +	u32 tsauxc; + +	if (pin < 0 || pin >= IGB_N_PEROUT) +		return; + +	spin_lock(&adapter->tmreg_lock); + +	if (hw->mac.type == e1000_82580 || +	    hw->mac.type == e1000_i354 || +	    hw->mac.type == e1000_i350) { +		s64 ns = timespec64_to_ns(&adapter->perout[pin].period); +		u32 systiml, systimh, level_mask, level, rem; +		u64 systim, now; + +		/* read systim registers in sequence */ +		rd32(E1000_SYSTIMR); +		systiml = rd32(E1000_SYSTIML); +		systimh = rd32(E1000_SYSTIMH); +		systim = (((u64)(systimh & 0xFF)) << 32) | ((u64)systiml); +		now = timecounter_cyc2time(&adapter->tc, systim); + +		if (pin < 2) { +			level_mask = (tsintr_tt == 1) ? 0x80000 : 0x40000; +			level = (rd32(E1000_CTRL) & level_mask) ? 1 : 0; +		} else { +			level_mask = (tsintr_tt == 1) ? 0x80 : 0x40; +			level = (rd32(E1000_CTRL_EXT) & level_mask) ? 1 : 0; +		} + +		div_u64_rem(now, ns, &rem); +		systim = systim + (ns - rem); + +		/* synchronize pin level with rising/falling edges */ +		div_u64_rem(now, ns << 1, &rem); +		if (rem < ns) { +			/* first half of period */ +			if (level == 0) { +				/* output is already low, skip this period */ +				systim += ns; +				pr_notice("igb: periodic output on %s missed falling edge\n", +					  adapter->sdp_config[pin].name); +			} +		} else { +			/* second half of period */ +			if (level == 1) { +				/* output is already high, skip this period */ +				systim += ns; +				pr_notice("igb: periodic output on %s missed rising edge\n", +					  adapter->sdp_config[pin].name); +			} +		} + +		/* for this chip family tv_sec is the upper part of the binary value, +		 * so not seconds +		 */ +		ts.tv_nsec = (u32)systim; +		ts.tv_sec  = ((u32)(systim >> 32)) & 0xFF; +	} else { +		ts = timespec64_add(adapter->perout[pin].start, +				    adapter->perout[pin].period); +	} + +	/* u32 conversion of tv_sec is safe until y2106 */ +	wr32((tsintr_tt == 1) ? E1000_TRGTTIML1 : E1000_TRGTTIML0, ts.tv_nsec); +	wr32((tsintr_tt == 1) ? E1000_TRGTTIMH1 : E1000_TRGTTIMH0, (u32)ts.tv_sec); +	tsauxc = rd32(E1000_TSAUXC); +	tsauxc |= TSAUXC_EN_TT0; +	wr32(E1000_TSAUXC, tsauxc); +	adapter->perout[pin].start = ts; + +	spin_unlock(&adapter->tmreg_lock); +} + +static void igb_extts(struct igb_adapter *adapter, int tsintr_tt) +{ +	int pin = ptp_find_pin(adapter->ptp_clock, PTP_PF_EXTTS, tsintr_tt); +	int auxstmpl = (tsintr_tt == 1) ? E1000_AUXSTMPL1 : E1000_AUXSTMPL0; +	int auxstmph = (tsintr_tt == 1) ? E1000_AUXSTMPH1 : E1000_AUXSTMPH0;  	struct e1000_hw *hw = &adapter->hw;  	struct ptp_clock_event event;  	struct timespec64 ts; -	u32 ack = 0, tsauxc, sec, nsec, tsicr = rd32(E1000_TSICR); + +	if (pin < 0 || pin >= IGB_N_EXTTS) +		return; + +	if (hw->mac.type == e1000_82580 || +	    hw->mac.type == e1000_i354 || +	    hw->mac.type == e1000_i350) { +		s64 ns = rd32(auxstmpl); + +		ns += ((s64)(rd32(auxstmph) & 0xFF)) << 32; +		ts = ns_to_timespec64(ns); +	} else { +		ts.tv_nsec = rd32(auxstmpl); +		ts.tv_sec  = rd32(auxstmph); +	} + +	event.type = PTP_CLOCK_EXTTS; +	event.index = tsintr_tt; +	event.timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec; +	ptp_clock_event(adapter->ptp_clock, &event); +} + +static void igb_tsync_interrupt(struct igb_adapter *adapter) +{ +	struct e1000_hw *hw = &adapter->hw; +	u32 ack = 0, tsicr = rd32(E1000_TSICR); +	struct ptp_clock_event event;  	if (tsicr & TSINTR_SYS_WRAP) {  		event.type = PTP_CLOCK_PPS; @@ -6760,51 +6867,22 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter)  	}  	if (tsicr & TSINTR_TT0) { -		spin_lock(&adapter->tmreg_lock); -		ts = timespec64_add(adapter->perout[0].start, -				    adapter->perout[0].period); -		/* u32 conversion of tv_sec is safe until y2106 */ -		wr32(E1000_TRGTTIML0, ts.tv_nsec); -		wr32(E1000_TRGTTIMH0, (u32)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); +		igb_perout(adapter, 0);  		ack |= TSINTR_TT0;  	}  	if (tsicr & TSINTR_TT1) { -		spin_lock(&adapter->tmreg_lock); -		ts = timespec64_add(adapter->perout[1].start, -				    adapter->perout[1].period); -		wr32(E1000_TRGTTIML1, ts.tv_nsec); -		wr32(E1000_TRGTTIMH1, (u32)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); +		igb_perout(adapter, 1);  		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); +		igb_extts(adapter, 0);  		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); +		igb_extts(adapter, 1);  		ack |= TSINTR_AUTT1;  	} @@ -8367,7 +8445,7 @@ static struct sk_buff *igb_build_skb(struct igb_ring *rx_ring,  	net_prefetch(xdp->data_meta);  	/* build an skb around the page buffer */ -	skb = build_skb(xdp->data_hard_start, truesize); +	skb = napi_build_skb(xdp->data_hard_start, truesize);  	if (unlikely(!skb))  		return NULL; @@ -8422,7 +8500,7 @@ static struct sk_buff *igb_run_xdp(struct igb_adapter *adapter,  		result = IGB_XDP_REDIR;  		break;  	default: -		bpf_warn_invalid_xdp_action(act); +		bpf_warn_invalid_xdp_action(adapter->netdev, xdp_prog, act);  		fallthrough;  	case XDP_ABORTED:  out_failure: diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index 0011b15e678c..6580fcddb4be 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -69,6 +69,7 @@  #define IGB_NBITS_82580			40  static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter); +static void igb_ptp_sdp_init(struct igb_adapter *adapter);  /* SYSTIM read access for the 82576 */  static u64 igb_ptp_read_82576(const struct cyclecounter *cc) @@ -507,6 +508,158 @@ static void igb_pin_perout(struct igb_adapter *igb, int chan, int pin, int freq)  	wr32(E1000_CTRL_EXT, ctrl_ext);  } +static int igb_ptp_feature_enable_82580(struct ptp_clock_info *ptp, +					struct ptp_clock_request *rq, int on) +{ +	struct igb_adapter *igb = +		container_of(ptp, struct igb_adapter, ptp_caps); +	u32 tsauxc, tsim, tsauxc_mask, tsim_mask, trgttiml, trgttimh, systiml, +		systimh, level_mask, level, rem; +	struct e1000_hw *hw = &igb->hw; +	struct timespec64 ts, start; +	unsigned long flags; +	u64 systim, now; +	int pin = -1; +	s64 ns; + +	switch (rq->type) { +	case PTP_CLK_REQ_EXTTS: +		/* Reject requests with unsupported flags */ +		if (rq->extts.flags & ~(PTP_ENABLE_FEATURE | +					PTP_RISING_EDGE | +					PTP_FALLING_EDGE | +					PTP_STRICT_FLAGS)) +			return -EOPNOTSUPP; + +		if (on) { +			pin = ptp_find_pin(igb->ptp_clock, PTP_PF_EXTTS, +					   rq->extts.index); +			if (pin < 0) +				return -EBUSY; +		} +		if (rq->extts.index == 1) { +			tsauxc_mask = TSAUXC_EN_TS1; +			tsim_mask = TSINTR_AUTT1; +		} else { +			tsauxc_mask = TSAUXC_EN_TS0; +			tsim_mask = TSINTR_AUTT0; +		} +		spin_lock_irqsave(&igb->tmreg_lock, flags); +		tsauxc = rd32(E1000_TSAUXC); +		tsim = rd32(E1000_TSIM); +		if (on) { +			igb_pin_extts(igb, rq->extts.index, pin); +			tsauxc |= tsauxc_mask; +			tsim |= tsim_mask; +		} else { +			tsauxc &= ~tsauxc_mask; +			tsim &= ~tsim_mask; +		} +		wr32(E1000_TSAUXC, tsauxc); +		wr32(E1000_TSIM, tsim); +		spin_unlock_irqrestore(&igb->tmreg_lock, flags); +		return 0; + +	case PTP_CLK_REQ_PEROUT: +		/* Reject requests with unsupported flags */ +		if (rq->perout.flags) +			return -EOPNOTSUPP; + +		if (on) { +			pin = ptp_find_pin(igb->ptp_clock, PTP_PF_PEROUT, +					   rq->perout.index); +			if (pin < 0) +				return -EBUSY; +		} +		ts.tv_sec = rq->perout.period.sec; +		ts.tv_nsec = rq->perout.period.nsec; +		ns = timespec64_to_ns(&ts); +		ns = ns >> 1; +		if (on && ns < 8LL) +			return -EINVAL; +		ts = ns_to_timespec64(ns); +		if (rq->perout.index == 1) { +			tsauxc_mask = TSAUXC_EN_TT1; +			tsim_mask = TSINTR_TT1; +			trgttiml = E1000_TRGTTIML1; +			trgttimh = E1000_TRGTTIMH1; +		} else { +			tsauxc_mask = TSAUXC_EN_TT0; +			tsim_mask = TSINTR_TT0; +			trgttiml = E1000_TRGTTIML0; +			trgttimh = E1000_TRGTTIMH0; +		} +		spin_lock_irqsave(&igb->tmreg_lock, flags); +		tsauxc = rd32(E1000_TSAUXC); +		tsim = rd32(E1000_TSIM); +		if (rq->perout.index == 1) { +			tsauxc &= ~(TSAUXC_EN_TT1 | TSAUXC_EN_CLK1 | TSAUXC_ST1); +			tsim &= ~TSINTR_TT1; +		} else { +			tsauxc &= ~(TSAUXC_EN_TT0 | TSAUXC_EN_CLK0 | TSAUXC_ST0); +			tsim &= ~TSINTR_TT0; +		} +		if (on) { +			int i = rq->perout.index; + +			/* read systim registers in sequence */ +			rd32(E1000_SYSTIMR); +			systiml = rd32(E1000_SYSTIML); +			systimh = rd32(E1000_SYSTIMH); +			systim = (((u64)(systimh & 0xFF)) << 32) | ((u64)systiml); +			now = timecounter_cyc2time(&igb->tc, systim); + +			if (pin < 2) { +				level_mask = (i == 1) ? 0x80000 : 0x40000; +				level = (rd32(E1000_CTRL) & level_mask) ? 1 : 0; +			} else { +				level_mask = (i == 1) ? 0x80 : 0x40; +				level = (rd32(E1000_CTRL_EXT) & level_mask) ? 1 : 0; +			} + +			div_u64_rem(now, ns, &rem); +			systim = systim + (ns - rem); + +			/* synchronize pin level with rising/falling edges */ +			div_u64_rem(now, ns << 1, &rem); +			if (rem < ns) { +				/* first half of period */ +				if (level == 0) { +					/* output is already low, skip this period */ +					systim += ns; +				} +			} else { +				/* second half of period */ +				if (level == 1) { +					/* output is already high, skip this period */ +					systim += ns; +				} +			} + +			start = ns_to_timespec64(systim + (ns - rem)); +			igb_pin_perout(igb, i, pin, 0); +			igb->perout[i].start.tv_sec = start.tv_sec; +			igb->perout[i].start.tv_nsec = start.tv_nsec; +			igb->perout[i].period.tv_sec = ts.tv_sec; +			igb->perout[i].period.tv_nsec = ts.tv_nsec; + +			wr32(trgttiml, (u32)systim); +			wr32(trgttimh, ((u32)(systim >> 32)) & 0xFF); +			tsauxc |= tsauxc_mask; +			tsim |= tsim_mask; +		} +		wr32(E1000_TSAUXC, tsauxc); +		wr32(E1000_TSIM, tsim); +		spin_unlock_irqrestore(&igb->tmreg_lock, flags); +		return 0; + +	case PTP_CLK_REQ_PPS: +		return -EOPNOTSUPP; +	} + +	return -EOPNOTSUPP; +} +  static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp,  				       struct ptp_clock_request *rq, int on)  { @@ -1015,10 +1168,6 @@ static int igb_ptp_set_timestamp_mode(struct igb_adapter *adapter,  	bool is_l2 = false;  	u32 regval; -	/* reserved for future extensions */ -	if (config->flags) -		return -EINVAL; -  	switch (config->tx_type) {  	case HWTSTAMP_TX_OFF:  		tsync_tx_ctl = 0; @@ -1192,7 +1341,6 @@ void igb_ptp_init(struct igb_adapter *adapter)  {  	struct e1000_hw *hw = &adapter->hw;  	struct net_device *netdev = adapter->netdev; -	int i;  	switch (hw->mac.type) {  	case e1000_82576: @@ -1215,16 +1363,21 @@ void igb_ptp_init(struct igb_adapter *adapter)  	case e1000_82580:  	case e1000_i354:  	case e1000_i350: +		igb_ptp_sdp_init(adapter);  		snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);  		adapter->ptp_caps.owner = THIS_MODULE;  		adapter->ptp_caps.max_adj = 62499999; -		adapter->ptp_caps.n_ext_ts = 0; +		adapter->ptp_caps.n_ext_ts = IGB_N_EXTTS; +		adapter->ptp_caps.n_per_out = IGB_N_PEROUT; +		adapter->ptp_caps.n_pins = IGB_N_SDP;  		adapter->ptp_caps.pps = 0; +		adapter->ptp_caps.pin_config = adapter->sdp_config;  		adapter->ptp_caps.adjfine = igb_ptp_adjfine_82580;  		adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576;  		adapter->ptp_caps.gettimex64 = igb_ptp_gettimex_82580;  		adapter->ptp_caps.settime64 = igb_ptp_settime_82576; -		adapter->ptp_caps.enable = igb_ptp_feature_enable; +		adapter->ptp_caps.enable = igb_ptp_feature_enable_82580; +		adapter->ptp_caps.verify = igb_ptp_verify_pin;  		adapter->cc.read = igb_ptp_read_82580;  		adapter->cc.mask = CYCLECOUNTER_MASK(IGB_NBITS_82580);  		adapter->cc.mult = 1; @@ -1233,13 +1386,7 @@ void igb_ptp_init(struct igb_adapter *adapter)  		break;  	case e1000_i210:  	case e1000_i211: -		for (i = 0; i < IGB_N_SDP; i++) { -			struct ptp_pin_desc *ppd = &adapter->sdp_config[i]; - -			snprintf(ppd->name, sizeof(ppd->name), "SDP%d", i); -			ppd->index = i; -			ppd->func = PTP_PF_NONE; -		} +		igb_ptp_sdp_init(adapter);  		snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);  		adapter->ptp_caps.owner = THIS_MODULE;  		adapter->ptp_caps.max_adj = 62499999; @@ -1285,6 +1432,23 @@ void igb_ptp_init(struct igb_adapter *adapter)  }  /** + * igb_ptp_sdp_init - utility function which inits the SDP config structs + * @adapter: Board private structure. + **/ +void igb_ptp_sdp_init(struct igb_adapter *adapter) +{ +	int i; + +	for (i = 0; i < IGB_N_SDP; i++) { +		struct ptp_pin_desc *ppd = &adapter->sdp_config[i]; + +		snprintf(ppd->name, sizeof(ppd->name), "SDP%d", i); +		ppd->index = i; +		ppd->func = PTP_PF_NONE; +	} +} + +/**   * igb_ptp_suspend - Disable PTP work items and prepare for suspend   * @adapter: Board private structure   * |