Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1167187f authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'qed-Fix-inifinite-spinning-of-PTP-poll-thread'



Sudarsana Reddy Kalluru says:

====================
qed*: Fix inifinite spinning of PTP poll thread.

The patch series addresses an error scenario in the PTP Tx implementation.

Please consider applying it to net-next.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 36f18439 9adebac3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -157,7 +157,8 @@ static int qed_ptp_hw_read_tx_ts(struct qed_dev *cdev, u64 *timestamp)
	*timestamp = 0;
	val = qed_rd(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_BUF_SEQID);
	if (!(val & QED_TIMESTAMP_MASK)) {
		DP_INFO(p_hwfn, "Invalid Tx timestamp, buf_seqid = %d\n", val);
		DP_VERBOSE(p_hwfn, QED_MSG_DEBUG,
			   "Invalid Tx timestamp, buf_seqid = %08x\n", val);
		return -EINVAL;
	}

+2 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ struct qede_stats_common {
	u64 non_coalesced_pkts;
	u64 coalesced_bytes;
	u64 link_change_count;
	u64 ptp_skip_txts;

	/* port */
	u64 rx_64_byte_packets;
@@ -189,6 +190,7 @@ struct qede_dev {

	const struct qed_eth_ops	*ops;
	struct qede_ptp			*ptp;
	u64				ptp_skip_txts;

	struct qed_dev_eth_info dev_info;
#define QEDE_MAX_RSS_CNT(edev)	((edev)->dev_info.num_queues)
+1 −0
Original line number Diff line number Diff line
@@ -174,6 +174,7 @@ static const struct {
	QEDE_STAT(coalesced_bytes),

	QEDE_STAT(link_change_count),
	QEDE_STAT(ptp_skip_txts),
};

#define QEDE_NUM_STATS	ARRAY_SIZE(qede_stats_arr)
+3 −0
Original line number Diff line number Diff line
@@ -390,6 +390,7 @@ void qede_fill_by_demand_stats(struct qede_dev *edev)
	p_common->brb_discards = stats.common.brb_discards;
	p_common->tx_mac_ctrl_frames = stats.common.tx_mac_ctrl_frames;
	p_common->link_change_count = stats.common.link_change_count;
	p_common->ptp_skip_txts = edev->ptp_skip_txts;

	if (QEDE_IS_BB(edev)) {
		struct qede_stats_bb *p_bb = &edev->stats.bb;
@@ -2232,6 +2233,8 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode,
	if (mode != QEDE_UNLOAD_RECOVERY)
		DP_NOTICE(edev, "Link is down\n");

	edev->ptp_skip_txts = 0;

	DP_INFO(edev, "Ending qede unload\n");
}

+30 −7
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
 * SOFTWARE.
 */
#include "qede_ptp.h"
#define QEDE_PTP_TX_TIMEOUT (2 * HZ)

struct qede_ptp {
	const struct qed_eth_ptp_ops	*ops;
@@ -38,6 +39,7 @@ struct qede_ptp {
	struct timecounter		tc;
	struct ptp_clock		*clock;
	struct work_struct		work;
	unsigned long			ptp_tx_start;
	struct qede_dev			*edev;
	struct sk_buff			*tx_skb;

@@ -160,18 +162,30 @@ static void qede_ptp_task(struct work_struct *work)
	struct qede_dev *edev;
	struct qede_ptp *ptp;
	u64 timestamp, ns;
	bool timedout;
	int rc;

	ptp = container_of(work, struct qede_ptp, work);
	edev = ptp->edev;
	timedout = time_is_before_jiffies(ptp->ptp_tx_start +
					  QEDE_PTP_TX_TIMEOUT);

	/* Read Tx timestamp registers */
	spin_lock_bh(&ptp->lock);
	rc = ptp->ops->read_tx_ts(edev->cdev, &timestamp);
	spin_unlock_bh(&ptp->lock);
	if (rc) {
		/* Reschedule to keep checking for a valid timestamp value */
		if (unlikely(timedout)) {
			DP_INFO(edev, "Tx timestamp is not recorded\n");
			dev_kfree_skb_any(ptp->tx_skb);
			ptp->tx_skb = NULL;
			clear_bit_unlock(QEDE_FLAGS_PTP_TX_IN_PRORGESS,
					 &edev->flags);
			edev->ptp_skip_txts++;
		} else {
			/* Reschedule to keep checking for a valid TS value */
			schedule_work(&ptp->work);
		}
		return;
	}

@@ -514,19 +528,28 @@ 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))
	if (test_and_set_bit_lock(QEDE_FLAGS_PTP_TX_IN_PRORGESS,
				  &edev->flags)) {
		DP_ERR(edev, "Timestamping in progress\n");
		edev->ptp_skip_txts++;
		return;
	}

	if (unlikely(!test_bit(QEDE_FLAGS_TX_TIMESTAMPING_EN, &edev->flags))) {
		DP_NOTICE(edev,
		DP_ERR(edev,
		       "Tx timestamping was not enabled, this packet will not be timestamped\n");
		clear_bit_unlock(QEDE_FLAGS_PTP_TX_IN_PRORGESS, &edev->flags);
		edev->ptp_skip_txts++;
	} else if (unlikely(ptp->tx_skb)) {
		DP_NOTICE(edev,
		DP_ERR(edev,
		       "The device supports only a single outstanding packet to timestamp, this packet will not be timestamped\n");
		clear_bit_unlock(QEDE_FLAGS_PTP_TX_IN_PRORGESS, &edev->flags);
		edev->ptp_skip_txts++;
	} else {
		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
		/* schedule check for Tx timestamp */
		ptp->tx_skb = skb_get(skb);
		ptp->ptp_tx_start = jiffies;
		schedule_work(&ptp->work);
	}
}