Skip to content

Commit

Permalink
Merge branch 'qed-Fix-inifinite-spinning-of-PTP-poll-thread'
Browse files Browse the repository at this point in the history
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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed May 29, 2019
2 parents 36f1843 + 9adebac commit 1167187
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 8 deletions.
3 changes: 2 additions & 1 deletion drivers/net/ethernet/qlogic/qed/qed_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/qlogic/qede/qede.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/qlogic/qede/qede_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/qlogic/qede/qede_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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");
}

Expand Down
37 changes: 30 additions & 7 deletions drivers/net/ethernet/qlogic/qede/qede_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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 */
schedule_work(&ptp->work);
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;
}

Expand Down Expand Up @@ -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,
"Tx timestamping was not enabled, this packet will not be timestamped\n");
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,
"The device supports only a single outstanding packet to timestamp, this packet will not be timestamped\n");
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);
}
}
Expand Down

0 comments on commit 1167187

Please sign in to comment.