diff options
| author | David S. Miller <davem@davemloft.net> | 2017-05-02 15:33:02 -0400 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-05-02 15:33:02 -0400 | 
| commit | 5657f89abb2d8966ac7678b84e3c020b93f340f4 (patch) | |
| tree | e15e2590d068f35aea706abbcca6259d13433326 | |
| parent | 212c7fd614377fef4415d94856a59e9f484aa439 (diff) | |
| parent | 8d3f87d8cd0a16c58ae7e4410938528866c1c0db (diff) | |
Merge branch 'qed-PTP-fixes'
Sudarsana Reddy Kalluru says:
====================
qed*: PTP bug fixes.
The series addresses couple of issues in the PTP implementation.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_ptp.c | 84 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qede/qede.h | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qede/qede_ptp.c | 38 | ||||
| -rw-r--r-- | include/linux/qed/qed_eth_if.h | 23 | 
4 files changed, 105 insertions, 45 deletions
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ptp.c b/drivers/net/ethernet/qlogic/qed/qed_ptp.c index 1871ebfdb793..434a164a76ed 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_ptp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_ptp.c @@ -188,39 +188,73 @@ static int qed_ptp_hw_read_cc(struct qed_dev *cdev, u64 *phc_cycles)  }  /* Filter PTP protocol packets that need to be timestamped */ -static int qed_ptp_hw_cfg_rx_filters(struct qed_dev *cdev, -				     enum qed_ptp_filter_type type) +static int qed_ptp_hw_cfg_filters(struct qed_dev *cdev, +				  enum qed_ptp_filter_type rx_type, +				  enum qed_ptp_hwtstamp_tx_type tx_type)  {  	struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);  	struct qed_ptt *p_ptt = p_hwfn->p_ptp_ptt; -	u32 rule_mask, parm_mask; +	u32 rule_mask, enable_cfg = 0x0; -	switch (type) { -	case QED_PTP_FILTER_L2_IPV4_IPV6: -		parm_mask = 0x6AA; -		rule_mask = 0x3EEE; +	switch (rx_type) { +	case QED_PTP_FILTER_NONE: +		enable_cfg = 0x0; +		rule_mask = 0x3FFF;  		break; -	case QED_PTP_FILTER_L2: -		parm_mask = 0x6BF; -		rule_mask = 0x3EFF; +	case QED_PTP_FILTER_ALL: +		enable_cfg = 0x7; +		rule_mask = 0x3CAA;  		break; -	case QED_PTP_FILTER_IPV4_IPV6: -		parm_mask = 0x7EA; -		rule_mask = 0x3FFE; +	case QED_PTP_FILTER_V1_L4_EVENT: +		enable_cfg = 0x3; +		rule_mask = 0x3FFA;  		break; -	case QED_PTP_FILTER_IPV4: -		parm_mask = 0x7EE; +	case QED_PTP_FILTER_V1_L4_GEN: +		enable_cfg = 0x3;  		rule_mask = 0x3FFE;  		break; +	case QED_PTP_FILTER_V2_L4_EVENT: +		enable_cfg = 0x5; +		rule_mask = 0x3FAA; +		break; +	case QED_PTP_FILTER_V2_L4_GEN: +		enable_cfg = 0x5; +		rule_mask = 0x3FEE; +		break; +	case QED_PTP_FILTER_V2_L2_EVENT: +		enable_cfg = 0x5; +		rule_mask = 0x3CFF; +		break; +	case QED_PTP_FILTER_V2_L2_GEN: +		enable_cfg = 0x5; +		rule_mask = 0x3EFF; +		break; +	case QED_PTP_FILTER_V2_EVENT: +		enable_cfg = 0x5; +		rule_mask = 0x3CAA; +		break; +	case QED_PTP_FILTER_V2_GEN: +		enable_cfg = 0x5; +		rule_mask = 0x3EEE; +		break;  	default: -		DP_INFO(p_hwfn, "Invalid PTP filter type %d\n", type); +		DP_INFO(p_hwfn, "Invalid PTP filter type %d\n", rx_type);  		return -EINVAL;  	} -	qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_PARAM_MASK, parm_mask); +	qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_PARAM_MASK, 0);  	qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_RULE_MASK, rule_mask); +	qed_wr(p_hwfn, p_ptt, NIG_REG_RX_PTP_EN, enable_cfg); -	qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_TO_HOST, 0x1); +	if (tx_type == QED_PTP_HWTSTAMP_TX_OFF) { +		qed_wr(p_hwfn, p_ptt, NIG_REG_TX_PTP_EN, 0x0); +		qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_PARAM_MASK, 0x7FF); +		qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_RULE_MASK, 0x3FFF); +	} else { +		qed_wr(p_hwfn, p_ptt, NIG_REG_TX_PTP_EN, enable_cfg); +		qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_PARAM_MASK, 0); +		qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_RULE_MASK, rule_mask); +	}  	/* Reset possibly old timestamps */  	qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_HOST_BUF_SEQID, @@ -383,17 +417,6 @@ static int qed_ptp_hw_enable(struct qed_dev *cdev)  	return 0;  } -static int qed_ptp_hw_hwtstamp_tx_on(struct qed_dev *cdev) -{ -	struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); -	struct qed_ptt *p_ptt = p_hwfn->p_ptp_ptt; - -	qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_PARAM_MASK, 0x6AA); -	qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_RULE_MASK, 0x3EEE); - -	return 0; -} -  static int qed_ptp_hw_disable(struct qed_dev *cdev)  {  	struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); @@ -419,8 +442,7 @@ static int qed_ptp_hw_disable(struct qed_dev *cdev)  }  const struct qed_eth_ptp_ops qed_ptp_ops_pass = { -	.hwtstamp_tx_on = qed_ptp_hw_hwtstamp_tx_on, -	.cfg_rx_filters = qed_ptp_hw_cfg_rx_filters, +	.cfg_filters = qed_ptp_hw_cfg_filters,  	.read_rx_ts = qed_ptp_hw_read_rx_ts,  	.read_tx_ts = qed_ptp_hw_read_tx_ts,  	.read_cc = qed_ptp_hw_read_cc, diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 766a79d2ed75..9b4f08b6f9b9 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -167,10 +167,11 @@ struct qede_dev {  	u32				dp_module;  	u8				dp_level; -	u32 flags; -#define QEDE_FLAG_IS_VF	BIT(0) +	unsigned long flags; +#define QEDE_FLAG_IS_VF			BIT(0)  #define IS_VF(edev)	(!!((edev)->flags & QEDE_FLAG_IS_VF))  #define QEDE_TX_TIMESTAMPING_EN		BIT(1) +#define QEDE_FLAGS_PTP_TX_IN_PRORGESS	BIT(2)  	const struct qed_eth_ops	*ops;  	struct qede_ptp			*ptp; diff --git a/drivers/net/ethernet/qlogic/qede/qede_ptp.c b/drivers/net/ethernet/qlogic/qede/qede_ptp.c index 6396363a804e..24f06e2ef43e 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ptp.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ptp.c @@ -181,6 +181,7 @@ static void qede_ptp_task(struct work_struct *work)  	skb_tstamp_tx(ptp->tx_skb, &shhwtstamps);  	dev_kfree_skb_any(ptp->tx_skb);  	ptp->tx_skb = NULL; +	clear_bit_unlock(QEDE_FLAGS_PTP_TX_IN_PRORGESS, &edev->flags);  	DP_VERBOSE(edev, QED_MSG_DEBUG,  		   "Tx timestamp, timestamp cycles = %llu, ns = %llu\n", @@ -208,6 +209,8 @@ static u64 qede_ptp_read_cc(const struct cyclecounter *cc)  static int qede_ptp_cfg_filters(struct qede_dev *edev)  { +	enum qed_ptp_hwtstamp_tx_type tx_type = QED_PTP_HWTSTAMP_TX_ON; +	enum qed_ptp_filter_type rx_filter = QED_PTP_FILTER_NONE;  	struct qede_ptp *ptp = edev->ptp;  	if (!ptp) @@ -221,7 +224,12 @@ static int qede_ptp_cfg_filters(struct qede_dev *edev)  	switch (ptp->tx_type) {  	case HWTSTAMP_TX_ON:  		edev->flags |= QEDE_TX_TIMESTAMPING_EN; -		ptp->ops->hwtstamp_tx_on(edev->cdev); +		tx_type = QED_PTP_HWTSTAMP_TX_ON; +		break; + +	case HWTSTAMP_TX_OFF: +		edev->flags &= ~QEDE_TX_TIMESTAMPING_EN; +		tx_type = QED_PTP_HWTSTAMP_TX_OFF;  		break;  	case HWTSTAMP_TX_ONESTEP_SYNC: @@ -232,42 +240,57 @@ static int qede_ptp_cfg_filters(struct qede_dev *edev)  	spin_lock_bh(&ptp->lock);  	switch (ptp->rx_filter) {  	case HWTSTAMP_FILTER_NONE: +		rx_filter = QED_PTP_FILTER_NONE;  		break;  	case HWTSTAMP_FILTER_ALL:  	case HWTSTAMP_FILTER_SOME:  		ptp->rx_filter = HWTSTAMP_FILTER_NONE; +		rx_filter = QED_PTP_FILTER_ALL;  		break;  	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: +		ptp->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; +		rx_filter = QED_PTP_FILTER_V1_L4_EVENT; +		break;  	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:  	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:  		ptp->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;  		/* Initialize PTP detection for UDP/IPv4 events */ -		ptp->ops->cfg_rx_filters(edev->cdev, QED_PTP_FILTER_IPV4); +		rx_filter = QED_PTP_FILTER_V1_L4_GEN;  		break;  	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: +		ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; +		rx_filter = QED_PTP_FILTER_V2_L4_EVENT; +		break;  	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:  	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:  		ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;  		/* Initialize PTP detection for UDP/IPv4 or UDP/IPv6 events */ -		ptp->ops->cfg_rx_filters(edev->cdev, QED_PTP_FILTER_IPV4_IPV6); +		rx_filter = QED_PTP_FILTER_V2_L4_GEN;  		break;  	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: +		ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; +		rx_filter = QED_PTP_FILTER_V2_L2_EVENT; +		break;  	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:  	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:  		ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;  		/* Initialize PTP detection L2 events */ -		ptp->ops->cfg_rx_filters(edev->cdev, QED_PTP_FILTER_L2); +		rx_filter = QED_PTP_FILTER_V2_L2_GEN;  		break;  	case HWTSTAMP_FILTER_PTP_V2_EVENT: +		ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; +		rx_filter = QED_PTP_FILTER_V2_EVENT; +		break;  	case HWTSTAMP_FILTER_PTP_V2_SYNC:  	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:  		ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;  		/* Initialize PTP detection L2, UDP/IPv4 or UDP/IPv6 events */ -		ptp->ops->cfg_rx_filters(edev->cdev, -					 QED_PTP_FILTER_L2_IPV4_IPV6); +		rx_filter = QED_PTP_FILTER_V2_GEN;  		break;  	} +	ptp->ops->cfg_filters(edev->cdev, rx_filter, tx_type); +  	spin_unlock_bh(&ptp->lock);  	return 0; @@ -485,6 +508,9 @@ void qede_ptp_tx_ts(struct qede_dev *edev, struct sk_buff *skb)  	if (!ptp)  		return; +	if (test_and_set_bit_lock(QEDE_FLAGS_PTP_TX_IN_PRORGESS, &edev->flags)) +		return; +  	if (unlikely(!(edev->flags & QEDE_TX_TIMESTAMPING_EN))) {  		DP_NOTICE(edev,  			  "Tx timestamping was not enabled, this packet will not be timestamped\n"); diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h index 15fa7c6e4c6f..d66d16a559e1 100644 --- a/include/linux/qed/qed_eth_if.h +++ b/include/linux/qed/qed_eth_if.h @@ -164,10 +164,21 @@ struct qed_eth_cb_ops {  #define QED_MAX_PHC_DRIFT_PPB   291666666  enum qed_ptp_filter_type { -	QED_PTP_FILTER_L2, -	QED_PTP_FILTER_IPV4, -	QED_PTP_FILTER_IPV4_IPV6, -	QED_PTP_FILTER_L2_IPV4_IPV6 +	QED_PTP_FILTER_NONE, +	QED_PTP_FILTER_ALL, +	QED_PTP_FILTER_V1_L4_EVENT, +	QED_PTP_FILTER_V1_L4_GEN, +	QED_PTP_FILTER_V2_L4_EVENT, +	QED_PTP_FILTER_V2_L4_GEN, +	QED_PTP_FILTER_V2_L2_EVENT, +	QED_PTP_FILTER_V2_L2_GEN, +	QED_PTP_FILTER_V2_EVENT, +	QED_PTP_FILTER_V2_GEN +}; + +enum qed_ptp_hwtstamp_tx_type { +	QED_PTP_HWTSTAMP_TX_OFF, +	QED_PTP_HWTSTAMP_TX_ON,  };  #ifdef CONFIG_DCB @@ -230,8 +241,8 @@ struct qed_eth_dcbnl_ops {  #endif  struct qed_eth_ptp_ops { -	int (*hwtstamp_tx_on)(struct qed_dev *); -	int (*cfg_rx_filters)(struct qed_dev *, enum qed_ptp_filter_type); +	int (*cfg_filters)(struct qed_dev *, enum qed_ptp_filter_type, +			   enum qed_ptp_hwtstamp_tx_type);  	int (*read_rx_ts)(struct qed_dev *, u64 *);  	int (*read_tx_ts)(struct qed_dev *, u64 *);  	int (*read_cc)(struct qed_dev *, u64 *);  | 
