mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-28 17:41:50 +00:00
Merge branch 'cpsw-allow-vlan-h-w-timestamping'
Ivan Khoronzhuk says: ==================== net: ethernet: ti: cpsw: allow vlan h/w timestamping The patchset adds several improvements and allows vlan h/w ts. Based on net-next/master ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
4fd3e2ac18
4 changed files with 69 additions and 84 deletions
|
@ -283,7 +283,7 @@ struct cpsw_ss_regs {
|
||||||
|
|
||||||
#define CTRL_V2_TS_BITS \
|
#define CTRL_V2_TS_BITS \
|
||||||
(TS_320 | TS_319 | TS_132 | TS_131 | TS_130 | TS_129 |\
|
(TS_320 | TS_319 | TS_132 | TS_131 | TS_130 | TS_129 |\
|
||||||
TS_TTL_NONZERO | TS_ANNEX_D_EN | TS_LTYPE1_EN)
|
TS_TTL_NONZERO | TS_ANNEX_D_EN | TS_LTYPE1_EN | VLAN_LTYPE1_EN)
|
||||||
|
|
||||||
#define CTRL_V2_ALL_TS_MASK (CTRL_V2_TS_BITS | TS_TX_EN | TS_RX_EN)
|
#define CTRL_V2_ALL_TS_MASK (CTRL_V2_TS_BITS | TS_TX_EN | TS_RX_EN)
|
||||||
#define CTRL_V2_TX_TS_BITS (CTRL_V2_TS_BITS | TS_TX_EN)
|
#define CTRL_V2_TX_TS_BITS (CTRL_V2_TS_BITS | TS_TX_EN)
|
||||||
|
@ -293,7 +293,7 @@ struct cpsw_ss_regs {
|
||||||
#define CTRL_V3_TS_BITS \
|
#define CTRL_V3_TS_BITS \
|
||||||
(TS_107 | TS_320 | TS_319 | TS_132 | TS_131 | TS_130 | TS_129 |\
|
(TS_107 | TS_320 | TS_319 | TS_132 | TS_131 | TS_130 | TS_129 |\
|
||||||
TS_TTL_NONZERO | TS_ANNEX_F_EN | TS_ANNEX_D_EN |\
|
TS_TTL_NONZERO | TS_ANNEX_F_EN | TS_ANNEX_D_EN |\
|
||||||
TS_LTYPE1_EN)
|
TS_LTYPE1_EN | VLAN_LTYPE1_EN)
|
||||||
|
|
||||||
#define CTRL_V3_ALL_TS_MASK (CTRL_V3_TS_BITS | TS_TX_EN | TS_RX_EN)
|
#define CTRL_V3_ALL_TS_MASK (CTRL_V3_TS_BITS | TS_TX_EN | TS_RX_EN)
|
||||||
#define CTRL_V3_TX_TS_BITS (CTRL_V3_TS_BITS | TS_TX_EN)
|
#define CTRL_V3_TX_TS_BITS (CTRL_V3_TS_BITS | TS_TX_EN)
|
||||||
|
@ -466,6 +466,8 @@ struct cpsw_priv {
|
||||||
bool mqprio_hw;
|
bool mqprio_hw;
|
||||||
int fifo_bw[CPSW_TC_NUM];
|
int fifo_bw[CPSW_TC_NUM];
|
||||||
int shp_cfg_speed;
|
int shp_cfg_speed;
|
||||||
|
int tx_ts_enabled;
|
||||||
|
int rx_ts_enabled;
|
||||||
u32 emac_port;
|
u32 emac_port;
|
||||||
struct cpsw_common *cpsw;
|
struct cpsw_common *cpsw;
|
||||||
};
|
};
|
||||||
|
@ -905,6 +907,7 @@ static void cpsw_rx_handler(void *token, int len, int status)
|
||||||
struct net_device *ndev = skb->dev;
|
struct net_device *ndev = skb->dev;
|
||||||
int ret = 0, port;
|
int ret = 0, port;
|
||||||
struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
|
struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
|
||||||
|
struct cpsw_priv *priv;
|
||||||
|
|
||||||
if (cpsw->data.dual_emac) {
|
if (cpsw->data.dual_emac) {
|
||||||
port = CPDMA_RX_SOURCE_PORT(status);
|
port = CPDMA_RX_SOURCE_PORT(status);
|
||||||
|
@ -939,7 +942,9 @@ static void cpsw_rx_handler(void *token, int len, int status)
|
||||||
skb_put(skb, len);
|
skb_put(skb, len);
|
||||||
if (status & CPDMA_RX_VLAN_ENCAP)
|
if (status & CPDMA_RX_VLAN_ENCAP)
|
||||||
cpsw_rx_vlan_encap(skb);
|
cpsw_rx_vlan_encap(skb);
|
||||||
cpts_rx_timestamp(cpsw->cpts, skb);
|
priv = netdev_priv(ndev);
|
||||||
|
if (priv->rx_ts_enabled)
|
||||||
|
cpts_rx_timestamp(cpsw->cpts, skb);
|
||||||
skb->protocol = eth_type_trans(skb, ndev);
|
skb->protocol = eth_type_trans(skb, ndev);
|
||||||
netif_receive_skb(skb);
|
netif_receive_skb(skb);
|
||||||
ndev->stats.rx_bytes += len;
|
ndev->stats.rx_bytes += len;
|
||||||
|
@ -2126,7 +2131,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
|
if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
|
||||||
cpts_is_tx_enabled(cpts) && cpts_can_timestamp(cpts, skb))
|
priv->tx_ts_enabled && cpts_can_timestamp(cpts, skb))
|
||||||
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
||||||
|
|
||||||
q_idx = skb_get_queue_mapping(skb);
|
q_idx = skb_get_queue_mapping(skb);
|
||||||
|
@ -2170,13 +2175,13 @@ fail:
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_TI_CPTS)
|
#if IS_ENABLED(CONFIG_TI_CPTS)
|
||||||
|
|
||||||
static void cpsw_hwtstamp_v1(struct cpsw_common *cpsw)
|
static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
|
||||||
{
|
{
|
||||||
|
struct cpsw_common *cpsw = priv->cpsw;
|
||||||
struct cpsw_slave *slave = &cpsw->slaves[cpsw->data.active_slave];
|
struct cpsw_slave *slave = &cpsw->slaves[cpsw->data.active_slave];
|
||||||
u32 ts_en, seq_id;
|
u32 ts_en, seq_id;
|
||||||
|
|
||||||
if (!cpts_is_tx_enabled(cpsw->cpts) &&
|
if (!priv->tx_ts_enabled && !priv->rx_ts_enabled) {
|
||||||
!cpts_is_rx_enabled(cpsw->cpts)) {
|
|
||||||
slave_write(slave, 0, CPSW1_TS_CTL);
|
slave_write(slave, 0, CPSW1_TS_CTL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2184,10 +2189,10 @@ static void cpsw_hwtstamp_v1(struct cpsw_common *cpsw)
|
||||||
seq_id = (30 << CPSW_V1_SEQ_ID_OFS_SHIFT) | ETH_P_1588;
|
seq_id = (30 << CPSW_V1_SEQ_ID_OFS_SHIFT) | ETH_P_1588;
|
||||||
ts_en = EVENT_MSG_BITS << CPSW_V1_MSG_TYPE_OFS;
|
ts_en = EVENT_MSG_BITS << CPSW_V1_MSG_TYPE_OFS;
|
||||||
|
|
||||||
if (cpts_is_tx_enabled(cpsw->cpts))
|
if (priv->tx_ts_enabled)
|
||||||
ts_en |= CPSW_V1_TS_TX_EN;
|
ts_en |= CPSW_V1_TS_TX_EN;
|
||||||
|
|
||||||
if (cpts_is_rx_enabled(cpsw->cpts))
|
if (priv->rx_ts_enabled)
|
||||||
ts_en |= CPSW_V1_TS_RX_EN;
|
ts_en |= CPSW_V1_TS_RX_EN;
|
||||||
|
|
||||||
slave_write(slave, ts_en, CPSW1_TS_CTL);
|
slave_write(slave, ts_en, CPSW1_TS_CTL);
|
||||||
|
@ -2207,20 +2212,20 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
|
||||||
case CPSW_VERSION_2:
|
case CPSW_VERSION_2:
|
||||||
ctrl &= ~CTRL_V2_ALL_TS_MASK;
|
ctrl &= ~CTRL_V2_ALL_TS_MASK;
|
||||||
|
|
||||||
if (cpts_is_tx_enabled(cpsw->cpts))
|
if (priv->tx_ts_enabled)
|
||||||
ctrl |= CTRL_V2_TX_TS_BITS;
|
ctrl |= CTRL_V2_TX_TS_BITS;
|
||||||
|
|
||||||
if (cpts_is_rx_enabled(cpsw->cpts))
|
if (priv->rx_ts_enabled)
|
||||||
ctrl |= CTRL_V2_RX_TS_BITS;
|
ctrl |= CTRL_V2_RX_TS_BITS;
|
||||||
break;
|
break;
|
||||||
case CPSW_VERSION_3:
|
case CPSW_VERSION_3:
|
||||||
default:
|
default:
|
||||||
ctrl &= ~CTRL_V3_ALL_TS_MASK;
|
ctrl &= ~CTRL_V3_ALL_TS_MASK;
|
||||||
|
|
||||||
if (cpts_is_tx_enabled(cpsw->cpts))
|
if (priv->tx_ts_enabled)
|
||||||
ctrl |= CTRL_V3_TX_TS_BITS;
|
ctrl |= CTRL_V3_TX_TS_BITS;
|
||||||
|
|
||||||
if (cpts_is_rx_enabled(cpsw->cpts))
|
if (priv->rx_ts_enabled)
|
||||||
ctrl |= CTRL_V3_RX_TS_BITS;
|
ctrl |= CTRL_V3_RX_TS_BITS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2230,6 +2235,7 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
|
||||||
slave_write(slave, mtype, CPSW2_TS_SEQ_MTYPE);
|
slave_write(slave, mtype, CPSW2_TS_SEQ_MTYPE);
|
||||||
slave_write(slave, ctrl, CPSW2_CONTROL);
|
slave_write(slave, ctrl, CPSW2_CONTROL);
|
||||||
writel_relaxed(ETH_P_1588, &cpsw->regs->ts_ltype);
|
writel_relaxed(ETH_P_1588, &cpsw->regs->ts_ltype);
|
||||||
|
writel_relaxed(ETH_P_8021Q, &cpsw->regs->vlan_ltype);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
|
static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
|
||||||
|
@ -2237,7 +2243,6 @@ static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
|
||||||
struct cpsw_priv *priv = netdev_priv(dev);
|
struct cpsw_priv *priv = netdev_priv(dev);
|
||||||
struct hwtstamp_config cfg;
|
struct hwtstamp_config cfg;
|
||||||
struct cpsw_common *cpsw = priv->cpsw;
|
struct cpsw_common *cpsw = priv->cpsw;
|
||||||
struct cpts *cpts = cpsw->cpts;
|
|
||||||
|
|
||||||
if (cpsw->version != CPSW_VERSION_1 &&
|
if (cpsw->version != CPSW_VERSION_1 &&
|
||||||
cpsw->version != CPSW_VERSION_2 &&
|
cpsw->version != CPSW_VERSION_2 &&
|
||||||
|
@ -2256,7 +2261,7 @@ static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
|
||||||
|
|
||||||
switch (cfg.rx_filter) {
|
switch (cfg.rx_filter) {
|
||||||
case HWTSTAMP_FILTER_NONE:
|
case HWTSTAMP_FILTER_NONE:
|
||||||
cpts_rx_enable(cpts, 0);
|
priv->rx_ts_enabled = 0;
|
||||||
break;
|
break;
|
||||||
case HWTSTAMP_FILTER_ALL:
|
case HWTSTAMP_FILTER_ALL:
|
||||||
case HWTSTAMP_FILTER_NTP_ALL:
|
case HWTSTAMP_FILTER_NTP_ALL:
|
||||||
|
@ -2264,7 +2269,7 @@ static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
|
||||||
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
|
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
|
||||||
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:
|
||||||
cpts_rx_enable(cpts, HWTSTAMP_FILTER_PTP_V1_L4_EVENT);
|
priv->rx_ts_enabled = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
|
||||||
cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
|
cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
|
||||||
break;
|
break;
|
||||||
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
||||||
|
@ -2276,18 +2281,18 @@ static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
|
||||||
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||||
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:
|
||||||
cpts_rx_enable(cpts, HWTSTAMP_FILTER_PTP_V2_EVENT);
|
priv->rx_ts_enabled = HWTSTAMP_FILTER_PTP_V2_EVENT;
|
||||||
cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
|
cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpts_tx_enable(cpts, cfg.tx_type == HWTSTAMP_TX_ON);
|
priv->tx_ts_enabled = cfg.tx_type == HWTSTAMP_TX_ON;
|
||||||
|
|
||||||
switch (cpsw->version) {
|
switch (cpsw->version) {
|
||||||
case CPSW_VERSION_1:
|
case CPSW_VERSION_1:
|
||||||
cpsw_hwtstamp_v1(cpsw);
|
cpsw_hwtstamp_v1(priv);
|
||||||
break;
|
break;
|
||||||
case CPSW_VERSION_2:
|
case CPSW_VERSION_2:
|
||||||
case CPSW_VERSION_3:
|
case CPSW_VERSION_3:
|
||||||
|
@ -2303,7 +2308,7 @@ static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
|
||||||
static int cpsw_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
|
static int cpsw_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
|
||||||
{
|
{
|
||||||
struct cpsw_common *cpsw = ndev_to_cpsw(dev);
|
struct cpsw_common *cpsw = ndev_to_cpsw(dev);
|
||||||
struct cpts *cpts = cpsw->cpts;
|
struct cpsw_priv *priv = netdev_priv(dev);
|
||||||
struct hwtstamp_config cfg;
|
struct hwtstamp_config cfg;
|
||||||
|
|
||||||
if (cpsw->version != CPSW_VERSION_1 &&
|
if (cpsw->version != CPSW_VERSION_1 &&
|
||||||
|
@ -2312,10 +2317,8 @@ static int cpsw_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
cfg.flags = 0;
|
cfg.flags = 0;
|
||||||
cfg.tx_type = cpts_is_tx_enabled(cpts) ?
|
cfg.tx_type = priv->tx_ts_enabled ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
|
||||||
HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
|
cfg.rx_filter = priv->rx_ts_enabled;
|
||||||
cfg.rx_filter = (cpts_is_rx_enabled(cpts) ?
|
|
||||||
cpts->rx_enable : HWTSTAMP_FILTER_NONE);
|
|
||||||
|
|
||||||
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
|
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,25 @@ static int cpts_purge_events(struct cpts *cpts)
|
||||||
return removed ? 0 : -1;
|
return removed ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cpts_purge_txq(struct cpts *cpts)
|
||||||
|
{
|
||||||
|
struct cpts_skb_cb_data *skb_cb;
|
||||||
|
struct sk_buff *skb, *tmp;
|
||||||
|
int removed = 0;
|
||||||
|
|
||||||
|
skb_queue_walk_safe(&cpts->txq, skb, tmp) {
|
||||||
|
skb_cb = (struct cpts_skb_cb_data *)skb->cb;
|
||||||
|
if (time_after(jiffies, skb_cb->tmo)) {
|
||||||
|
__skb_unlink(skb, &cpts->txq);
|
||||||
|
dev_consume_skb_any(skb);
|
||||||
|
++removed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removed)
|
||||||
|
dev_dbg(cpts->dev, "txq cleaned up %d\n", removed);
|
||||||
|
}
|
||||||
|
|
||||||
static bool cpts_match_tx_ts(struct cpts *cpts, struct cpts_event *event)
|
static bool cpts_match_tx_ts(struct cpts *cpts, struct cpts_event *event)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb, *tmp;
|
struct sk_buff *skb, *tmp;
|
||||||
|
@ -119,9 +138,7 @@ static bool cpts_match_tx_ts(struct cpts *cpts, struct cpts_event *event)
|
||||||
|
|
||||||
if (time_after(jiffies, skb_cb->tmo)) {
|
if (time_after(jiffies, skb_cb->tmo)) {
|
||||||
/* timeout any expired skbs over 1s */
|
/* timeout any expired skbs over 1s */
|
||||||
dev_dbg(cpts->dev,
|
dev_dbg(cpts->dev, "expiring tx timestamp from txq\n");
|
||||||
"expiring tx timestamp mtype %u seqid %04x\n",
|
|
||||||
mtype, seqid);
|
|
||||||
__skb_unlink(skb, &cpts->txq);
|
__skb_unlink(skb, &cpts->txq);
|
||||||
dev_consume_skb_any(skb);
|
dev_consume_skb_any(skb);
|
||||||
}
|
}
|
||||||
|
@ -294,8 +311,11 @@ static long cpts_overflow_check(struct ptp_clock_info *ptp)
|
||||||
spin_lock_irqsave(&cpts->lock, flags);
|
spin_lock_irqsave(&cpts->lock, flags);
|
||||||
ts = ns_to_timespec64(timecounter_read(&cpts->tc));
|
ts = ns_to_timespec64(timecounter_read(&cpts->tc));
|
||||||
|
|
||||||
if (!skb_queue_empty(&cpts->txq))
|
if (!skb_queue_empty(&cpts->txq)) {
|
||||||
delay = CPTS_SKB_TX_WORK_TIMEOUT;
|
cpts_purge_txq(cpts);
|
||||||
|
if (!skb_queue_empty(&cpts->txq))
|
||||||
|
delay = CPTS_SKB_TX_WORK_TIMEOUT;
|
||||||
|
}
|
||||||
spin_unlock_irqrestore(&cpts->lock, flags);
|
spin_unlock_irqrestore(&cpts->lock, flags);
|
||||||
|
|
||||||
pr_debug("cpts overflow check at %lld.%09ld\n",
|
pr_debug("cpts overflow check at %lld.%09ld\n",
|
||||||
|
@ -410,8 +430,6 @@ void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
|
||||||
u64 ns;
|
u64 ns;
|
||||||
struct skb_shared_hwtstamps *ssh;
|
struct skb_shared_hwtstamps *ssh;
|
||||||
|
|
||||||
if (!cpts->rx_enable)
|
|
||||||
return;
|
|
||||||
ns = cpts_find_ts(cpts, skb, CPTS_EV_RX);
|
ns = cpts_find_ts(cpts, skb, CPTS_EV_RX);
|
||||||
if (!ns)
|
if (!ns)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -136,26 +136,6 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs,
|
||||||
struct device_node *node);
|
struct device_node *node);
|
||||||
void cpts_release(struct cpts *cpts);
|
void cpts_release(struct cpts *cpts);
|
||||||
|
|
||||||
static inline void cpts_rx_enable(struct cpts *cpts, int enable)
|
|
||||||
{
|
|
||||||
cpts->rx_enable = enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool cpts_is_rx_enabled(struct cpts *cpts)
|
|
||||||
{
|
|
||||||
return !!cpts->rx_enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void cpts_tx_enable(struct cpts *cpts, int enable)
|
|
||||||
{
|
|
||||||
cpts->tx_enable = enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool cpts_is_tx_enabled(struct cpts *cpts)
|
|
||||||
{
|
|
||||||
return !!cpts->tx_enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool cpts_can_timestamp(struct cpts *cpts, struct sk_buff *skb)
|
static inline bool cpts_can_timestamp(struct cpts *cpts, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
unsigned int class = ptp_classify_raw(skb);
|
unsigned int class = ptp_classify_raw(skb);
|
||||||
|
@ -197,24 +177,6 @@ static inline void cpts_unregister(struct cpts *cpts)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void cpts_rx_enable(struct cpts *cpts, int enable)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool cpts_is_rx_enabled(struct cpts *cpts)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void cpts_tx_enable(struct cpts *cpts, int enable)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool cpts_is_tx_enabled(struct cpts *cpts)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool cpts_can_timestamp(struct cpts *cpts, struct sk_buff *skb)
|
static inline bool cpts_can_timestamp(struct cpts *cpts, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -763,6 +763,8 @@ struct gbe_priv {
|
||||||
|
|
||||||
int cpts_registered;
|
int cpts_registered;
|
||||||
struct cpts *cpts;
|
struct cpts *cpts;
|
||||||
|
int rx_ts_enabled;
|
||||||
|
int tx_ts_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gbe_intf {
|
struct gbe_intf {
|
||||||
|
@ -2564,7 +2566,7 @@ static int gbe_txtstamp_mark_pkt(struct gbe_intf *gbe_intf,
|
||||||
struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
|
struct gbe_priv *gbe_dev = gbe_intf->gbe_dev;
|
||||||
|
|
||||||
if (!(skb_shinfo(p_info->skb)->tx_flags & SKBTX_HW_TSTAMP) ||
|
if (!(skb_shinfo(p_info->skb)->tx_flags & SKBTX_HW_TSTAMP) ||
|
||||||
!cpts_is_tx_enabled(gbe_dev->cpts))
|
!gbe_dev->tx_ts_enabled)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* If phy has the txtstamp api, assume it will do it.
|
/* If phy has the txtstamp api, assume it will do it.
|
||||||
|
@ -2598,7 +2600,9 @@ static int gbe_rxtstamp(struct gbe_intf *gbe_intf, struct netcp_packet *p_info)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpts_rx_timestamp(gbe_dev->cpts, p_info->skb);
|
if (gbe_dev->rx_ts_enabled)
|
||||||
|
cpts_rx_timestamp(gbe_dev->cpts, p_info->skb);
|
||||||
|
|
||||||
p_info->rxtstamp_complete = true;
|
p_info->rxtstamp_complete = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2614,10 +2618,8 @@ static int gbe_hwtstamp_get(struct gbe_intf *gbe_intf, struct ifreq *ifr)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
cfg.flags = 0;
|
cfg.flags = 0;
|
||||||
cfg.tx_type = cpts_is_tx_enabled(cpts) ?
|
cfg.tx_type = gbe_dev->tx_ts_enabled ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
|
||||||
HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
|
cfg.rx_filter = gbe_dev->rx_ts_enabled;
|
||||||
cfg.rx_filter = (cpts_is_rx_enabled(cpts) ?
|
|
||||||
cpts->rx_enable : HWTSTAMP_FILTER_NONE);
|
|
||||||
|
|
||||||
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
|
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
|
||||||
}
|
}
|
||||||
|
@ -2628,8 +2630,8 @@ static void gbe_hwtstamp(struct gbe_intf *gbe_intf)
|
||||||
struct gbe_slave *slave = gbe_intf->slave;
|
struct gbe_slave *slave = gbe_intf->slave;
|
||||||
u32 ts_en, seq_id, ctl;
|
u32 ts_en, seq_id, ctl;
|
||||||
|
|
||||||
if (!cpts_is_rx_enabled(gbe_dev->cpts) &&
|
if (!gbe_dev->rx_ts_enabled &&
|
||||||
!cpts_is_tx_enabled(gbe_dev->cpts)) {
|
!gbe_dev->tx_ts_enabled) {
|
||||||
writel(0, GBE_REG_ADDR(slave, port_regs, ts_ctl));
|
writel(0, GBE_REG_ADDR(slave, port_regs, ts_ctl));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2641,10 +2643,10 @@ static void gbe_hwtstamp(struct gbe_intf *gbe_intf)
|
||||||
(slave->ts_ctl.uni ? TS_UNI_EN :
|
(slave->ts_ctl.uni ? TS_UNI_EN :
|
||||||
slave->ts_ctl.maddr_map << TS_CTL_MADDR_SHIFT);
|
slave->ts_ctl.maddr_map << TS_CTL_MADDR_SHIFT);
|
||||||
|
|
||||||
if (cpts_is_tx_enabled(gbe_dev->cpts))
|
if (gbe_dev->tx_ts_enabled)
|
||||||
ts_en |= (TS_TX_ANX_ALL_EN | TS_TX_VLAN_LT1_EN);
|
ts_en |= (TS_TX_ANX_ALL_EN | TS_TX_VLAN_LT1_EN);
|
||||||
|
|
||||||
if (cpts_is_rx_enabled(gbe_dev->cpts))
|
if (gbe_dev->rx_ts_enabled)
|
||||||
ts_en |= (TS_RX_ANX_ALL_EN | TS_RX_VLAN_LT1_EN);
|
ts_en |= (TS_RX_ANX_ALL_EN | TS_RX_VLAN_LT1_EN);
|
||||||
|
|
||||||
writel(ts_en, GBE_REG_ADDR(slave, port_regs, ts_ctl));
|
writel(ts_en, GBE_REG_ADDR(slave, port_regs, ts_ctl));
|
||||||
|
@ -2670,10 +2672,10 @@ static int gbe_hwtstamp_set(struct gbe_intf *gbe_intf, struct ifreq *ifr)
|
||||||
|
|
||||||
switch (cfg.tx_type) {
|
switch (cfg.tx_type) {
|
||||||
case HWTSTAMP_TX_OFF:
|
case HWTSTAMP_TX_OFF:
|
||||||
cpts_tx_enable(cpts, 0);
|
gbe_dev->tx_ts_enabled = 0;
|
||||||
break;
|
break;
|
||||||
case HWTSTAMP_TX_ON:
|
case HWTSTAMP_TX_ON:
|
||||||
cpts_tx_enable(cpts, 1);
|
gbe_dev->tx_ts_enabled = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
|
@ -2681,12 +2683,12 @@ static int gbe_hwtstamp_set(struct gbe_intf *gbe_intf, struct ifreq *ifr)
|
||||||
|
|
||||||
switch (cfg.rx_filter) {
|
switch (cfg.rx_filter) {
|
||||||
case HWTSTAMP_FILTER_NONE:
|
case HWTSTAMP_FILTER_NONE:
|
||||||
cpts_rx_enable(cpts, 0);
|
gbe_dev->rx_ts_enabled = HWTSTAMP_FILTER_NONE;
|
||||||
break;
|
break;
|
||||||
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
|
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
|
||||||
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:
|
||||||
cpts_rx_enable(cpts, HWTSTAMP_FILTER_PTP_V1_L4_EVENT);
|
gbe_dev->rx_ts_enabled = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
|
||||||
cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
|
cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
|
||||||
break;
|
break;
|
||||||
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
||||||
|
@ -2698,7 +2700,7 @@ static int gbe_hwtstamp_set(struct gbe_intf *gbe_intf, struct ifreq *ifr)
|
||||||
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||||
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:
|
||||||
cpts_rx_enable(cpts, HWTSTAMP_FILTER_PTP_V2_EVENT);
|
gbe_dev->rx_ts_enabled = HWTSTAMP_FILTER_PTP_V2_EVENT;
|
||||||
cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
|
cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue