Commit 5657f89a authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 212c7fd6 8d3f87d8
...@@ -188,39 +188,73 @@ static int qed_ptp_hw_read_cc(struct qed_dev *cdev, u64 *phc_cycles) ...@@ -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 */ /* Filter PTP protocol packets that need to be timestamped */
static int qed_ptp_hw_cfg_rx_filters(struct qed_dev *cdev, static int qed_ptp_hw_cfg_filters(struct qed_dev *cdev,
enum qed_ptp_filter_type type) 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_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
struct qed_ptt *p_ptt = p_hwfn->p_ptp_ptt; struct qed_ptt *p_ptt = p_hwfn->p_ptp_ptt;
u32 rule_mask, parm_mask; u32 rule_mask, enable_cfg = 0x0;
switch (type) { switch (rx_type) {
case QED_PTP_FILTER_L2_IPV4_IPV6: case QED_PTP_FILTER_NONE:
parm_mask = 0x6AA; enable_cfg = 0x0;
rule_mask = 0x3EEE; rule_mask = 0x3FFF;
break; break;
case QED_PTP_FILTER_L2: case QED_PTP_FILTER_ALL:
parm_mask = 0x6BF; enable_cfg = 0x7;
rule_mask = 0x3EFF; rule_mask = 0x3CAA;
break; break;
case QED_PTP_FILTER_IPV4_IPV6: case QED_PTP_FILTER_V1_L4_EVENT:
parm_mask = 0x7EA; enable_cfg = 0x3;
rule_mask = 0x3FFE; rule_mask = 0x3FFA;
break; break;
case QED_PTP_FILTER_IPV4: case QED_PTP_FILTER_V1_L4_GEN:
parm_mask = 0x7EE; enable_cfg = 0x3;
rule_mask = 0x3FFE; rule_mask = 0x3FFE;
break; 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: 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; 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_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 */ /* Reset possibly old timestamps */
qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_HOST_BUF_SEQID, 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) ...@@ -383,17 +417,6 @@ static int qed_ptp_hw_enable(struct qed_dev *cdev)
return 0; 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) static int qed_ptp_hw_disable(struct qed_dev *cdev)
{ {
struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
...@@ -419,8 +442,7 @@ static int qed_ptp_hw_disable(struct qed_dev *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 = { const struct qed_eth_ptp_ops qed_ptp_ops_pass = {
.hwtstamp_tx_on = qed_ptp_hw_hwtstamp_tx_on, .cfg_filters = qed_ptp_hw_cfg_filters,
.cfg_rx_filters = qed_ptp_hw_cfg_rx_filters,
.read_rx_ts = qed_ptp_hw_read_rx_ts, .read_rx_ts = qed_ptp_hw_read_rx_ts,
.read_tx_ts = qed_ptp_hw_read_tx_ts, .read_tx_ts = qed_ptp_hw_read_tx_ts,
.read_cc = qed_ptp_hw_read_cc, .read_cc = qed_ptp_hw_read_cc,
......
...@@ -167,10 +167,11 @@ struct qede_dev { ...@@ -167,10 +167,11 @@ struct qede_dev {
u32 dp_module; u32 dp_module;
u8 dp_level; u8 dp_level;
u32 flags; unsigned long flags;
#define QEDE_FLAG_IS_VF BIT(0) #define QEDE_FLAG_IS_VF BIT(0)
#define IS_VF(edev) (!!((edev)->flags & QEDE_FLAG_IS_VF)) #define IS_VF(edev) (!!((edev)->flags & QEDE_FLAG_IS_VF))
#define QEDE_TX_TIMESTAMPING_EN BIT(1) #define QEDE_TX_TIMESTAMPING_EN BIT(1)
#define QEDE_FLAGS_PTP_TX_IN_PRORGESS BIT(2)
const struct qed_eth_ops *ops; const struct qed_eth_ops *ops;
struct qede_ptp *ptp; struct qede_ptp *ptp;
......
...@@ -181,6 +181,7 @@ static void qede_ptp_task(struct work_struct *work) ...@@ -181,6 +181,7 @@ static void qede_ptp_task(struct work_struct *work)
skb_tstamp_tx(ptp->tx_skb, &shhwtstamps); skb_tstamp_tx(ptp->tx_skb, &shhwtstamps);
dev_kfree_skb_any(ptp->tx_skb); dev_kfree_skb_any(ptp->tx_skb);
ptp->tx_skb = NULL; ptp->tx_skb = NULL;
clear_bit_unlock(QEDE_FLAGS_PTP_TX_IN_PRORGESS, &edev->flags);
DP_VERBOSE(edev, QED_MSG_DEBUG, DP_VERBOSE(edev, QED_MSG_DEBUG,
"Tx timestamp, timestamp cycles = %llu, ns = %llu\n", "Tx timestamp, timestamp cycles = %llu, ns = %llu\n",
...@@ -208,6 +209,8 @@ static u64 qede_ptp_read_cc(const struct cyclecounter *cc) ...@@ -208,6 +209,8 @@ static u64 qede_ptp_read_cc(const struct cyclecounter *cc)
static int qede_ptp_cfg_filters(struct qede_dev *edev) 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; struct qede_ptp *ptp = edev->ptp;
if (!ptp) if (!ptp)
...@@ -221,7 +224,12 @@ static int qede_ptp_cfg_filters(struct qede_dev *edev) ...@@ -221,7 +224,12 @@ static int qede_ptp_cfg_filters(struct qede_dev *edev)
switch (ptp->tx_type) { switch (ptp->tx_type) {
case HWTSTAMP_TX_ON: case HWTSTAMP_TX_ON:
edev->flags |= QEDE_TX_TIMESTAMPING_EN; 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; break;
case HWTSTAMP_TX_ONESTEP_SYNC: case HWTSTAMP_TX_ONESTEP_SYNC:
...@@ -232,42 +240,57 @@ static int qede_ptp_cfg_filters(struct qede_dev *edev) ...@@ -232,42 +240,57 @@ static int qede_ptp_cfg_filters(struct qede_dev *edev)
spin_lock_bh(&ptp->lock); spin_lock_bh(&ptp->lock);
switch (ptp->rx_filter) { switch (ptp->rx_filter) {
case HWTSTAMP_FILTER_NONE: case HWTSTAMP_FILTER_NONE:
rx_filter = QED_PTP_FILTER_NONE;
break; break;
case HWTSTAMP_FILTER_ALL: case HWTSTAMP_FILTER_ALL:
case HWTSTAMP_FILTER_SOME: case HWTSTAMP_FILTER_SOME:
ptp->rx_filter = HWTSTAMP_FILTER_NONE; ptp->rx_filter = HWTSTAMP_FILTER_NONE;
rx_filter = QED_PTP_FILTER_ALL;
break; break;
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 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_SYNC:
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
ptp->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; ptp->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
/* Initialize PTP detection for UDP/IPv4 events */ /* 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; break;
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 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_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
/* Initialize PTP detection for UDP/IPv4 or UDP/IPv6 events */ /* 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; break;
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 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_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
/* Initialize PTP detection L2 events */ /* 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; break;
case HWTSTAMP_FILTER_PTP_V2_EVENT: 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_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; ptp->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
/* Initialize PTP detection L2, UDP/IPv4 or UDP/IPv6 events */ /* Initialize PTP detection L2, UDP/IPv4 or UDP/IPv6 events */
ptp->ops->cfg_rx_filters(edev->cdev, rx_filter = QED_PTP_FILTER_V2_GEN;
QED_PTP_FILTER_L2_IPV4_IPV6);
break; break;
} }
ptp->ops->cfg_filters(edev->cdev, rx_filter, tx_type);
spin_unlock_bh(&ptp->lock); spin_unlock_bh(&ptp->lock);
return 0; return 0;
...@@ -485,6 +508,9 @@ void qede_ptp_tx_ts(struct qede_dev *edev, struct sk_buff *skb) ...@@ -485,6 +508,9 @@ void qede_ptp_tx_ts(struct qede_dev *edev, struct sk_buff *skb)
if (!ptp) if (!ptp)
return; return;
if (test_and_set_bit_lock(QEDE_FLAGS_PTP_TX_IN_PRORGESS, &edev->flags))
return;
if (unlikely(!(edev->flags & QEDE_TX_TIMESTAMPING_EN))) { if (unlikely(!(edev->flags & QEDE_TX_TIMESTAMPING_EN))) {
DP_NOTICE(edev, DP_NOTICE(edev,
"Tx timestamping was not enabled, this packet will not be timestamped\n"); "Tx timestamping was not enabled, this packet will not be timestamped\n");
......
...@@ -164,10 +164,21 @@ struct qed_eth_cb_ops { ...@@ -164,10 +164,21 @@ struct qed_eth_cb_ops {
#define QED_MAX_PHC_DRIFT_PPB 291666666 #define QED_MAX_PHC_DRIFT_PPB 291666666
enum qed_ptp_filter_type { enum qed_ptp_filter_type {
QED_PTP_FILTER_L2, QED_PTP_FILTER_NONE,
QED_PTP_FILTER_IPV4, QED_PTP_FILTER_ALL,
QED_PTP_FILTER_IPV4_IPV6, QED_PTP_FILTER_V1_L4_EVENT,
QED_PTP_FILTER_L2_IPV4_IPV6 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 #ifdef CONFIG_DCB
...@@ -230,8 +241,8 @@ struct qed_eth_dcbnl_ops { ...@@ -230,8 +241,8 @@ struct qed_eth_dcbnl_ops {
#endif #endif
struct qed_eth_ptp_ops { struct qed_eth_ptp_ops {
int (*hwtstamp_tx_on)(struct qed_dev *); int (*cfg_filters)(struct qed_dev *, enum qed_ptp_filter_type,
int (*cfg_rx_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_rx_ts)(struct qed_dev *, u64 *);
int (*read_tx_ts)(struct qed_dev *, u64 *); int (*read_tx_ts)(struct qed_dev *, u64 *);
int (*read_cc)(struct qed_dev *, u64 *); int (*read_cc)(struct qed_dev *, u64 *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment