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>
This commit is contained in:
David S. Miller 2017-05-02 15:33:02 -04:00
commit 5657f89abb
4 changed files with 105 additions and 45 deletions

View File

@ -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;
case QED_PTP_FILTER_ALL:
enable_cfg = 0x7;
rule_mask = 0x3CAA;
break;
case QED_PTP_FILTER_V1_L4_EVENT:
enable_cfg = 0x3;
rule_mask = 0x3FFA;
break;
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_IPV4_IPV6:
parm_mask = 0x7EA;
rule_mask = 0x3FFE;
case QED_PTP_FILTER_V2_EVENT:
enable_cfg = 0x5;
rule_mask = 0x3CAA;
break;
case QED_PTP_FILTER_IPV4:
parm_mask = 0x7EE;
rule_mask = 0x3FFE;
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,

View File

@ -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;

View File

@ -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");

View File

@ -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 *);