aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSunil Goutham <sgoutham@cavium.com>2018-01-15 07:44:57 -0500
committerDavid S. Miller <davem@davemloft.net>2018-01-16 14:31:14 -0500
commit4a8755096466d1002236ac7293eae821b6de87ba (patch)
tree8eaf366be7af579511c08ba91d1f991d155f7ec7
parent8c56df372bc1371504bf3cc29fbb3c09967cafff (diff)
net: thunderx: add timestamping support
This adds timestamping support for both receive and transmit paths. On the receive side no filters are supported i.e either all pkts will get a timestamp appended infront of the packet or none. On the transmit side HW doesn't support timestamp insertion but only generates a separate CQE with transmitted packet's timestamp. Also HW supports only one packet at a time for timestamping on the transmit side. Signed-off-by: Sunil Goutham <sgoutham@cavium.com> Signed-off-by: Aleksey Makarov <aleksey.makarov@cavium.com> Acked-by: Philippe Ombredanne <pombredanne@nexb.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/cavium/Kconfig1
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic.h36
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic_main.c56
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic_reg.h1
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c29
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_main.c169
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_queues.c26
-rw-r--r--drivers/net/ethernet/cavium/thunder/thunder_bgx.c29
-rw-r--r--drivers/net/ethernet/cavium/thunder/thunder_bgx.h4
9 files changed, 345 insertions, 6 deletions
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index 96586c0b4490..043e3c11c42b 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -27,6 +27,7 @@ config THUNDER_NIC_PF
27 27
28config THUNDER_NIC_VF 28config THUNDER_NIC_VF
29 tristate "Thunder Virtual function driver" 29 tristate "Thunder Virtual function driver"
30 imply CAVIUM_PTP
30 depends on 64BIT 31 depends on 64BIT
31 ---help--- 32 ---help---
32 This driver supports Thunder's NIC virtual function 33 This driver supports Thunder's NIC virtual function
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index 4a02e618e318..4cacce5d2b16 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -263,6 +263,8 @@ struct nicvf_drv_stats {
263 struct u64_stats_sync syncp; 263 struct u64_stats_sync syncp;
264}; 264};
265 265
266struct cavium_ptp;
267
266struct nicvf { 268struct nicvf {
267 struct nicvf *pnicvf; 269 struct nicvf *pnicvf;
268 struct net_device *netdev; 270 struct net_device *netdev;
@@ -312,6 +314,33 @@ struct nicvf {
312 struct tasklet_struct qs_err_task; 314 struct tasklet_struct qs_err_task;
313 struct work_struct reset_task; 315 struct work_struct reset_task;
314 316
317 /* PTP timestamp */
318 struct cavium_ptp *ptp_clock;
319 /* Inbound timestamping is on */
320 bool hw_rx_tstamp;
321 /* When the packet that requires timestamping is sent, hardware inserts
322 * two entries to the completion queue. First is the regular
323 * CQE_TYPE_SEND entry that signals that the packet was sent.
324 * The second is CQE_TYPE_SEND_PTP that contains the actual timestamp
325 * for that packet.
326 * `ptp_skb` is initialized in the handler for the CQE_TYPE_SEND
327 * entry and is used and zeroed in the handler for the CQE_TYPE_SEND_PTP
328 * entry.
329 * So `ptp_skb` is used to hold the pointer to the packet between
330 * the calls to CQE_TYPE_SEND and CQE_TYPE_SEND_PTP handlers.
331 */
332 struct sk_buff *ptp_skb;
333 /* `tx_ptp_skbs` is set when the hardware is sending a packet that
334 * requires timestamping. Cavium hardware can not process more than one
335 * such packet at once so this is set each time the driver submits
336 * a packet that requires timestamping to the send queue and clears
337 * each time it receives the entry on the completion queue saying
338 * that such packet was sent.
339 * So `tx_ptp_skbs` prevents driver from submitting more than one
340 * packet that requires timestamping to the hardware for transmitting.
341 */
342 atomic_t tx_ptp_skbs;
343
315 /* Interrupt coalescing settings */ 344 /* Interrupt coalescing settings */
316 u32 cq_coalesce_usecs; 345 u32 cq_coalesce_usecs;
317 u32 msg_enable; 346 u32 msg_enable;
@@ -371,6 +400,7 @@ struct nicvf {
371#define NIC_MBOX_MSG_LOOPBACK 0x16 /* Set interface in loopback */ 400#define NIC_MBOX_MSG_LOOPBACK 0x16 /* Set interface in loopback */
372#define NIC_MBOX_MSG_RESET_STAT_COUNTER 0x17 /* Reset statistics counters */ 401#define NIC_MBOX_MSG_RESET_STAT_COUNTER 0x17 /* Reset statistics counters */
373#define NIC_MBOX_MSG_PFC 0x18 /* Pause frame control */ 402#define NIC_MBOX_MSG_PFC 0x18 /* Pause frame control */
403#define NIC_MBOX_MSG_PTP_CFG 0x19 /* HW packet timestamp */
374#define NIC_MBOX_MSG_CFG_DONE 0xF0 /* VF configuration done */ 404#define NIC_MBOX_MSG_CFG_DONE 0xF0 /* VF configuration done */
375#define NIC_MBOX_MSG_SHUTDOWN 0xF1 /* VF is being shutdown */ 405#define NIC_MBOX_MSG_SHUTDOWN 0xF1 /* VF is being shutdown */
376 406
@@ -521,6 +551,11 @@ struct pfc {
521 u8 fc_tx; 551 u8 fc_tx;
522}; 552};
523 553
554struct set_ptp {
555 u8 msg;
556 bool enable;
557};
558
524/* 128 bit shared memory between PF and each VF */ 559/* 128 bit shared memory between PF and each VF */
525union nic_mbx { 560union nic_mbx {
526 struct { u8 msg; } msg; 561 struct { u8 msg; } msg;
@@ -540,6 +575,7 @@ union nic_mbx {
540 struct set_loopback lbk; 575 struct set_loopback lbk;
541 struct reset_stat_cfg reset_stat; 576 struct reset_stat_cfg reset_stat;
542 struct pfc pfc; 577 struct pfc pfc;
578 struct set_ptp ptp;
543}; 579};
544 580
545#define NIC_NODE_ID_MASK 0x03 581#define NIC_NODE_ID_MASK 0x03
diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
index 8f1dd55b3e08..8325577d7442 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -426,13 +426,22 @@ static void nic_init_hw(struct nicpf *nic)
426 /* Enable backpressure */ 426 /* Enable backpressure */
427 nic_reg_write(nic, NIC_PF_BP_CFG, (1ULL << 6) | 0x03); 427 nic_reg_write(nic, NIC_PF_BP_CFG, (1ULL << 6) | 0x03);
428 428
429 /* TNS and TNS bypass modes are present only on 88xx */ 429 /* TNS and TNS bypass modes are present only on 88xx
430 * Also offset of this CSR has changed in 81xx and 83xx.
431 */
430 if (nic->pdev->subsystem_device == PCI_SUBSYS_DEVID_88XX_NIC_PF) { 432 if (nic->pdev->subsystem_device == PCI_SUBSYS_DEVID_88XX_NIC_PF) {
431 /* Disable TNS mode on both interfaces */ 433 /* Disable TNS mode on both interfaces */
432 nic_reg_write(nic, NIC_PF_INTF_0_1_SEND_CFG, 434 nic_reg_write(nic, NIC_PF_INTF_0_1_SEND_CFG,
433 (NIC_TNS_BYPASS_MODE << 7) | BGX0_BLOCK); 435 (NIC_TNS_BYPASS_MODE << 7) |
436 BGX0_BLOCK | (1ULL << 16));
434 nic_reg_write(nic, NIC_PF_INTF_0_1_SEND_CFG | (1 << 8), 437 nic_reg_write(nic, NIC_PF_INTF_0_1_SEND_CFG | (1 << 8),
435 (NIC_TNS_BYPASS_MODE << 7) | BGX1_BLOCK); 438 (NIC_TNS_BYPASS_MODE << 7) |
439 BGX1_BLOCK | (1ULL << 16));
440 } else {
441 /* Configure timestamp generation timeout to 10us */
442 for (i = 0; i < nic->hw->bgx_cnt; i++)
443 nic_reg_write(nic, NIC_PF_INTFX_SEND_CFG | (i << 3),
444 (1ULL << 16));
436 } 445 }
437 446
438 nic_reg_write(nic, NIC_PF_INTF_0_1_BP_CFG, 447 nic_reg_write(nic, NIC_PF_INTF_0_1_BP_CFG,
@@ -880,6 +889,44 @@ static void nic_pause_frame(struct nicpf *nic, int vf, struct pfc *cfg)
880 } 889 }
881} 890}
882 891
892/* Enable or disable HW timestamping by BGX for pkts received on a LMAC */
893static void nic_config_timestamp(struct nicpf *nic, int vf, struct set_ptp *ptp)
894{
895 struct pkind_cfg *pkind;
896 u8 lmac, bgx_idx;
897 u64 pkind_val, pkind_idx;
898
899 if (vf >= nic->num_vf_en)
900 return;
901
902 bgx_idx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
903 lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
904
905 pkind_idx = lmac + bgx_idx * MAX_LMAC_PER_BGX;
906 pkind_val = nic_reg_read(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3));
907 pkind = (struct pkind_cfg *)&pkind_val;
908
909 if (ptp->enable && !pkind->hdr_sl) {
910 /* Skiplen to exclude 8byte timestamp while parsing pkt
911 * If not configured, will result in L2 errors.
912 */
913 pkind->hdr_sl = 4;
914 /* Adjust max packet length allowed */
915 pkind->maxlen += (pkind->hdr_sl * 2);
916 bgx_config_timestamping(nic->node, bgx_idx, lmac, true);
917 nic_reg_write(nic, NIC_PF_RX_ETYPE_0_7 | (1 << 3),
918 (ETYPE_ALG_ENDPARSE << 16) | ETH_P_1588);
919 } else if (!ptp->enable && pkind->hdr_sl) {
920 pkind->maxlen -= (pkind->hdr_sl * 2);
921 pkind->hdr_sl = 0;
922 bgx_config_timestamping(nic->node, bgx_idx, lmac, false);
923 nic_reg_write(nic, NIC_PF_RX_ETYPE_0_7 | (1 << 3),
924 (ETYPE_ALG_SKIP << 16) | ETH_P_8021Q);
925 }
926
927 nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3), pkind_val);
928}
929
883/* Interrupt handler to handle mailbox messages from VFs */ 930/* Interrupt handler to handle mailbox messages from VFs */
884static void nic_handle_mbx_intr(struct nicpf *nic, int vf) 931static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
885{ 932{
@@ -1022,6 +1069,9 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
1022 case NIC_MBOX_MSG_PFC: 1069 case NIC_MBOX_MSG_PFC:
1023 nic_pause_frame(nic, vf, &mbx.pfc); 1070 nic_pause_frame(nic, vf, &mbx.pfc);
1024 goto unlock; 1071 goto unlock;
1072 case NIC_MBOX_MSG_PTP_CFG:
1073 nic_config_timestamp(nic, vf, &mbx.ptp);
1074 break;
1025 default: 1075 default:
1026 dev_err(&nic->pdev->dev, 1076 dev_err(&nic->pdev->dev,
1027 "Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg); 1077 "Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg);
diff --git a/drivers/net/ethernet/cavium/thunder/nic_reg.h b/drivers/net/ethernet/cavium/thunder/nic_reg.h
index 80d46337cf29..a16c48a1ebb2 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_reg.h
+++ b/drivers/net/ethernet/cavium/thunder/nic_reg.h
@@ -99,6 +99,7 @@
99#define NIC_PF_ECC3_DBE_INT_W1S (0x2708) 99#define NIC_PF_ECC3_DBE_INT_W1S (0x2708)
100#define NIC_PF_ECC3_DBE_ENA_W1C (0x2710) 100#define NIC_PF_ECC3_DBE_ENA_W1C (0x2710)
101#define NIC_PF_ECC3_DBE_ENA_W1S (0x2718) 101#define NIC_PF_ECC3_DBE_ENA_W1S (0x2718)
102#define NIC_PF_INTFX_SEND_CFG (0x4000)
102#define NIC_PF_MCAM_0_191_ENA (0x100000) 103#define NIC_PF_MCAM_0_191_ENA (0x100000)
103#define NIC_PF_MCAM_0_191_M_0_5_DATA (0x110000) 104#define NIC_PF_MCAM_0_191_M_0_5_DATA (0x110000)
104#define NIC_PF_MCAM_CTRL (0x120000) 105#define NIC_PF_MCAM_CTRL (0x120000)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
index b9ece9cbf98b..ed9f10bdf41e 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
@@ -9,12 +9,14 @@
9/* ETHTOOL Support for VNIC_VF Device*/ 9/* ETHTOOL Support for VNIC_VF Device*/
10 10
11#include <linux/pci.h> 11#include <linux/pci.h>
12#include <linux/net_tstamp.h>
12 13
13#include "nic_reg.h" 14#include "nic_reg.h"
14#include "nic.h" 15#include "nic.h"
15#include "nicvf_queues.h" 16#include "nicvf_queues.h"
16#include "q_struct.h" 17#include "q_struct.h"
17#include "thunder_bgx.h" 18#include "thunder_bgx.h"
19#include "../common/cavium_ptp.h"
18 20
19#define DRV_NAME "thunder-nicvf" 21#define DRV_NAME "thunder-nicvf"
20#define DRV_VERSION "1.0" 22#define DRV_VERSION "1.0"
@@ -824,6 +826,31 @@ static int nicvf_set_pauseparam(struct net_device *dev,
824 return 0; 826 return 0;
825} 827}
826 828
829static int nicvf_get_ts_info(struct net_device *netdev,
830 struct ethtool_ts_info *info)
831{
832 struct nicvf *nic = netdev_priv(netdev);
833
834 if (!nic->ptp_clock)
835 return ethtool_op_get_ts_info(netdev, info);
836
837 info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
838 SOF_TIMESTAMPING_RX_SOFTWARE |
839 SOF_TIMESTAMPING_SOFTWARE |
840 SOF_TIMESTAMPING_TX_HARDWARE |
841 SOF_TIMESTAMPING_RX_HARDWARE |
842 SOF_TIMESTAMPING_RAW_HARDWARE;
843
844 info->phc_index = cavium_ptp_clock_index(nic->ptp_clock);
845
846 info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
847
848 info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
849 (1 << HWTSTAMP_FILTER_ALL);
850
851 return 0;
852}
853
827static const struct ethtool_ops nicvf_ethtool_ops = { 854static const struct ethtool_ops nicvf_ethtool_ops = {
828 .get_link = nicvf_get_link, 855 .get_link = nicvf_get_link,
829 .get_drvinfo = nicvf_get_drvinfo, 856 .get_drvinfo = nicvf_get_drvinfo,
@@ -847,7 +874,7 @@ static const struct ethtool_ops nicvf_ethtool_ops = {
847 .set_channels = nicvf_set_channels, 874 .set_channels = nicvf_set_channels,
848 .get_pauseparam = nicvf_get_pauseparam, 875 .get_pauseparam = nicvf_get_pauseparam,
849 .set_pauseparam = nicvf_set_pauseparam, 876 .set_pauseparam = nicvf_set_pauseparam,
850 .get_ts_info = ethtool_op_get_ts_info, 877 .get_ts_info = nicvf_get_ts_info,
851 .get_link_ksettings = nicvf_get_link_ksettings, 878 .get_link_ksettings = nicvf_get_link_ksettings,
852}; 879};
853 880
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 21618d0d694f..881af8a120f5 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -20,11 +20,13 @@
20#include <linux/bpf.h> 20#include <linux/bpf.h>
21#include <linux/bpf_trace.h> 21#include <linux/bpf_trace.h>
22#include <linux/filter.h> 22#include <linux/filter.h>
23#include <linux/net_tstamp.h>
23 24
24#include "nic_reg.h" 25#include "nic_reg.h"
25#include "nic.h" 26#include "nic.h"
26#include "nicvf_queues.h" 27#include "nicvf_queues.h"
27#include "thunder_bgx.h" 28#include "thunder_bgx.h"
29#include "../common/cavium_ptp.h"
28 30
29#define DRV_NAME "thunder-nicvf" 31#define DRV_NAME "thunder-nicvf"
30#define DRV_VERSION "1.0" 32#define DRV_VERSION "1.0"
@@ -602,6 +604,44 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog,
602 return false; 604 return false;
603} 605}
604 606
607static void nicvf_snd_ptp_handler(struct net_device *netdev,
608 struct cqe_send_t *cqe_tx)
609{
610 struct nicvf *nic = netdev_priv(netdev);
611 struct skb_shared_hwtstamps ts;
612 u64 ns;
613
614 nic = nic->pnicvf;
615
616 /* Sync for 'ptp_skb' */
617 smp_rmb();
618
619 /* New timestamp request can be queued now */
620 atomic_set(&nic->tx_ptp_skbs, 0);
621
622 /* Check for timestamp requested skb */
623 if (!nic->ptp_skb)
624 return;
625
626 /* Check if timestamping is timedout, which is set to 10us */
627 if (cqe_tx->send_status == CQ_TX_ERROP_TSTMP_TIMEOUT ||
628 cqe_tx->send_status == CQ_TX_ERROP_TSTMP_CONFLICT)
629 goto no_tstamp;
630
631 /* Get the timestamp */
632 memset(&ts, 0, sizeof(ts));
633 ns = cavium_ptp_tstamp2time(nic->ptp_clock, cqe_tx->ptp_timestamp);
634 ts.hwtstamp = ns_to_ktime(ns);
635 skb_tstamp_tx(nic->ptp_skb, &ts);
636
637no_tstamp:
638 /* Free the original skb */
639 dev_kfree_skb_any(nic->ptp_skb);
640 nic->ptp_skb = NULL;
641 /* Sync 'ptp_skb' */
642 smp_wmb();
643}
644
605static void nicvf_snd_pkt_handler(struct net_device *netdev, 645static void nicvf_snd_pkt_handler(struct net_device *netdev,
606 struct cqe_send_t *cqe_tx, 646 struct cqe_send_t *cqe_tx,
607 int budget, int *subdesc_cnt, 647 int budget, int *subdesc_cnt,
@@ -658,7 +698,12 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
658 prefetch(skb); 698 prefetch(skb);
659 (*tx_pkts)++; 699 (*tx_pkts)++;
660 *tx_bytes += skb->len; 700 *tx_bytes += skb->len;
661 napi_consume_skb(skb, budget); 701 /* If timestamp is requested for this skb, don't free it */
702 if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
703 !nic->pnicvf->ptp_skb)
704 nic->pnicvf->ptp_skb = skb;
705 else
706 napi_consume_skb(skb, budget);
662 sq->skbuff[cqe_tx->sqe_ptr] = (u64)NULL; 707 sq->skbuff[cqe_tx->sqe_ptr] = (u64)NULL;
663 } else { 708 } else {
664 /* In case of SW TSO on 88xx, only last segment will have 709 /* In case of SW TSO on 88xx, only last segment will have
@@ -697,6 +742,21 @@ static inline void nicvf_set_rxhash(struct net_device *netdev,
697 skb_set_hash(skb, hash, hash_type); 742 skb_set_hash(skb, hash, hash_type);
698} 743}
699 744
745static inline void nicvf_set_rxtstamp(struct nicvf *nic, struct sk_buff *skb)
746{
747 u64 ns;
748
749 if (!nic->ptp_clock || !nic->hw_rx_tstamp)
750 return;
751
752 /* The first 8 bytes is the timestamp */
753 ns = cavium_ptp_tstamp2time(nic->ptp_clock,
754 be64_to_cpu(*(__be64 *)skb->data));
755 skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(ns);
756
757 __skb_pull(skb, 8);
758}
759
700static void nicvf_rcv_pkt_handler(struct net_device *netdev, 760static void nicvf_rcv_pkt_handler(struct net_device *netdev,
701 struct napi_struct *napi, 761 struct napi_struct *napi,
702 struct cqe_rx_t *cqe_rx, 762 struct cqe_rx_t *cqe_rx,
@@ -748,6 +808,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
748 return; 808 return;
749 } 809 }
750 810
811 nicvf_set_rxtstamp(nic, skb);
751 nicvf_set_rxhash(netdev, cqe_rx, skb); 812 nicvf_set_rxhash(netdev, cqe_rx, skb);
752 813
753 skb_record_rx_queue(skb, rq_idx); 814 skb_record_rx_queue(skb, rq_idx);
@@ -823,10 +884,12 @@ loop:
823 &tx_pkts, &tx_bytes); 884 &tx_pkts, &tx_bytes);
824 tx_done++; 885 tx_done++;
825 break; 886 break;
887 case CQE_TYPE_SEND_PTP:
888 nicvf_snd_ptp_handler(netdev, (void *)cq_desc);
889 break;
826 case CQE_TYPE_INVALID: 890 case CQE_TYPE_INVALID:
827 case CQE_TYPE_RX_SPLIT: 891 case CQE_TYPE_RX_SPLIT:
828 case CQE_TYPE_RX_TCP: 892 case CQE_TYPE_RX_TCP:
829 case CQE_TYPE_SEND_PTP:
830 /* Ignore for now */ 893 /* Ignore for now */
831 break; 894 break;
832 } 895 }
@@ -1322,12 +1385,28 @@ int nicvf_stop(struct net_device *netdev)
1322 1385
1323 nicvf_free_cq_poll(nic); 1386 nicvf_free_cq_poll(nic);
1324 1387
1388 /* Free any pending SKB saved to receive timestamp */
1389 if (nic->ptp_skb) {
1390 dev_kfree_skb_any(nic->ptp_skb);
1391 nic->ptp_skb = NULL;
1392 }
1393
1325 /* Clear multiqset info */ 1394 /* Clear multiqset info */
1326 nic->pnicvf = nic; 1395 nic->pnicvf = nic;
1327 1396
1328 return 0; 1397 return 0;
1329} 1398}
1330 1399
1400static int nicvf_config_hw_rx_tstamp(struct nicvf *nic, bool enable)
1401{
1402 union nic_mbx mbx = {};
1403
1404 mbx.ptp.msg = NIC_MBOX_MSG_PTP_CFG;
1405 mbx.ptp.enable = enable;
1406
1407 return nicvf_send_msg_to_pf(nic, &mbx);
1408}
1409
1331static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu) 1410static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
1332{ 1411{
1333 union nic_mbx mbx = {}; 1412 union nic_mbx mbx = {};
@@ -1397,6 +1476,12 @@ int nicvf_open(struct net_device *netdev)
1397 if (nic->sqs_mode) 1476 if (nic->sqs_mode)
1398 nicvf_get_primary_vf_struct(nic); 1477 nicvf_get_primary_vf_struct(nic);
1399 1478
1479 /* Configure PTP timestamp */
1480 if (nic->ptp_clock)
1481 nicvf_config_hw_rx_tstamp(nic, nic->hw_rx_tstamp);
1482 atomic_set(&nic->tx_ptp_skbs, 0);
1483 nic->ptp_skb = NULL;
1484
1400 /* Configure receive side scaling and MTU */ 1485 /* Configure receive side scaling and MTU */
1401 if (!nic->sqs_mode) { 1486 if (!nic->sqs_mode) {
1402 nicvf_rss_init(nic); 1487 nicvf_rss_init(nic);
@@ -1823,6 +1908,73 @@ static void nicvf_xdp_flush(struct net_device *dev)
1823 return; 1908 return;
1824} 1909}
1825 1910
1911static int nicvf_config_hwtstamp(struct net_device *netdev, struct ifreq *ifr)
1912{
1913 struct hwtstamp_config config;
1914 struct nicvf *nic = netdev_priv(netdev);
1915
1916 if (!nic->ptp_clock)
1917 return -ENODEV;
1918
1919 if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
1920 return -EFAULT;
1921
1922 /* reserved for future extensions */
1923 if (config.flags)
1924 return -EINVAL;
1925
1926 switch (config.tx_type) {
1927 case HWTSTAMP_TX_OFF:
1928 case HWTSTAMP_TX_ON:
1929 break;
1930 default:
1931 return -ERANGE;
1932 }
1933
1934 switch (config.rx_filter) {
1935 case HWTSTAMP_FILTER_NONE:
1936 nic->hw_rx_tstamp = false;
1937 break;
1938 case HWTSTAMP_FILTER_ALL:
1939 case HWTSTAMP_FILTER_SOME:
1940 case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
1941 case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
1942 case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
1943 case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
1944 case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
1945 case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
1946 case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
1947 case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
1948 case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
1949 case HWTSTAMP_FILTER_PTP_V2_EVENT:
1950 case HWTSTAMP_FILTER_PTP_V2_SYNC:
1951 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
1952 nic->hw_rx_tstamp = true;
1953 config.rx_filter = HWTSTAMP_FILTER_ALL;
1954 break;
1955 default:
1956 return -ERANGE;
1957 }
1958
1959 if (netif_running(netdev))
1960 nicvf_config_hw_rx_tstamp(nic, nic->hw_rx_tstamp);
1961
1962 if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
1963 return -EFAULT;
1964
1965 return 0;
1966}
1967
1968static int nicvf_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
1969{
1970 switch (cmd) {
1971 case SIOCSHWTSTAMP:
1972 return nicvf_config_hwtstamp(netdev, req);
1973 default:
1974 return -EOPNOTSUPP;
1975 }
1976}
1977
1826static const struct net_device_ops nicvf_netdev_ops = { 1978static const struct net_device_ops nicvf_netdev_ops = {
1827 .ndo_open = nicvf_open, 1979 .ndo_open = nicvf_open,
1828 .ndo_stop = nicvf_stop, 1980 .ndo_stop = nicvf_stop,
@@ -1836,6 +1988,7 @@ static const struct net_device_ops nicvf_netdev_ops = {
1836 .ndo_bpf = nicvf_xdp, 1988 .ndo_bpf = nicvf_xdp,
1837 .ndo_xdp_xmit = nicvf_xdp_xmit, 1989 .ndo_xdp_xmit = nicvf_xdp_xmit,
1838 .ndo_xdp_flush = nicvf_xdp_flush, 1990 .ndo_xdp_flush = nicvf_xdp_flush,
1991 .ndo_do_ioctl = nicvf_ioctl,
1839}; 1992};
1840 1993
1841static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 1994static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -1845,6 +1998,16 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1845 struct nicvf *nic; 1998 struct nicvf *nic;
1846 int err, qcount; 1999 int err, qcount;
1847 u16 sdevid; 2000 u16 sdevid;
2001 struct cavium_ptp *ptp_clock;
2002
2003 ptp_clock = cavium_ptp_get();
2004 if (IS_ERR(ptp_clock)) {
2005 if (PTR_ERR(ptp_clock) == -ENODEV)
2006 /* In virtualized environment we proceed without ptp */
2007 ptp_clock = NULL;
2008 else
2009 return PTR_ERR(ptp_clock);
2010 }
1848 2011
1849 err = pci_enable_device(pdev); 2012 err = pci_enable_device(pdev);
1850 if (err) { 2013 if (err) {
@@ -1899,6 +2062,7 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1899 */ 2062 */
1900 if (!nic->t88) 2063 if (!nic->t88)
1901 nic->max_queues *= 2; 2064 nic->max_queues *= 2;
2065 nic->ptp_clock = ptp_clock;
1902 2066
1903 /* MAP VF's configuration registers */ 2067 /* MAP VF's configuration registers */
1904 nic->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0); 2068 nic->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0);
@@ -2012,6 +2176,7 @@ static void nicvf_remove(struct pci_dev *pdev)
2012 pci_set_drvdata(pdev, NULL); 2176 pci_set_drvdata(pdev, NULL);
2013 if (nic->drv_stats) 2177 if (nic->drv_stats)
2014 free_percpu(nic->drv_stats); 2178 free_percpu(nic->drv_stats);
2179 cavium_ptp_put(nic->ptp_clock);
2015 free_netdev(netdev); 2180 free_netdev(netdev);
2016 pci_release_regions(pdev); 2181 pci_release_regions(pdev);
2017 pci_disable_device(pdev); 2182 pci_disable_device(pdev);
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index 14e62c6ac342..3eae9ff9b53a 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -982,6 +982,9 @@ void nicvf_qset_config(struct nicvf *nic, bool enable)
982 qs_cfg->be = 1; 982 qs_cfg->be = 1;
983#endif 983#endif
984 qs_cfg->vnic = qs->vnic_id; 984 qs_cfg->vnic = qs->vnic_id;
985 /* Enable Tx timestamping capability */
986 if (nic->ptp_clock)
987 qs_cfg->send_tstmp_ena = 1;
985 } 988 }
986 nicvf_send_msg_to_pf(nic, &mbx); 989 nicvf_send_msg_to_pf(nic, &mbx);
987} 990}
@@ -1389,6 +1392,29 @@ nicvf_sq_add_hdr_subdesc(struct nicvf *nic, struct snd_queue *sq, int qentry,
1389 hdr->inner_l3_offset = skb_network_offset(skb) - 2; 1392 hdr->inner_l3_offset = skb_network_offset(skb) - 2;
1390 this_cpu_inc(nic->pnicvf->drv_stats->tx_tso); 1393 this_cpu_inc(nic->pnicvf->drv_stats->tx_tso);
1391 } 1394 }
1395
1396 /* Check if timestamp is requested */
1397 if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
1398 skb_tx_timestamp(skb);
1399 return;
1400 }
1401
1402 /* Tx timestamping not supported along with TSO, so ignore request */
1403 if (skb_shinfo(skb)->gso_size)
1404 return;
1405
1406 /* HW supports only a single outstanding packet to timestamp */
1407 if (!atomic_add_unless(&nic->pnicvf->tx_ptp_skbs, 1, 1))
1408 return;
1409
1410 /* Mark the SKB for later reference */
1411 skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
1412
1413 /* Finally enable timestamp generation
1414 * Since 'post_cqe' is also set, two CQEs will be posted
1415 * for this packet i.e CQE_TYPE_SEND and CQE_TYPE_SEND_PTP.
1416 */
1417 hdr->tstmp = 1;
1392} 1418}
1393 1419
1394/* SQ GATHER subdescriptor 1420/* SQ GATHER subdescriptor
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 5e5c4d7796b8..0f23999c5bcf 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -245,6 +245,35 @@ void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable)
245} 245}
246EXPORT_SYMBOL(bgx_lmac_rx_tx_enable); 246EXPORT_SYMBOL(bgx_lmac_rx_tx_enable);
247 247
248/* Enables or disables timestamp insertion by BGX for Rx packets */
249void bgx_config_timestamping(int node, int bgx_idx, int lmacid, bool enable)
250{
251 struct bgx *bgx = get_bgx(node, bgx_idx);
252 struct lmac *lmac;
253 u64 csr_offset, cfg;
254
255 if (!bgx)
256 return;
257
258 lmac = &bgx->lmac[lmacid];
259
260 if (lmac->lmac_type == BGX_MODE_SGMII ||
261 lmac->lmac_type == BGX_MODE_QSGMII ||
262 lmac->lmac_type == BGX_MODE_RGMII)
263 csr_offset = BGX_GMP_GMI_RXX_FRM_CTL;
264 else
265 csr_offset = BGX_SMUX_RX_FRM_CTL;
266
267 cfg = bgx_reg_read(bgx, lmacid, csr_offset);
268
269 if (enable)
270 cfg |= BGX_PKT_RX_PTP_EN;
271 else
272 cfg &= ~BGX_PKT_RX_PTP_EN;
273 bgx_reg_write(bgx, lmacid, csr_offset, cfg);
274}
275EXPORT_SYMBOL(bgx_config_timestamping);
276
248void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause) 277void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause)
249{ 278{
250 struct pfc *pfc = (struct pfc *)pause; 279 struct pfc *pfc = (struct pfc *)pause;
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
index 23acdc5ab896..5a7567d31138 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
@@ -122,6 +122,8 @@
122#define SPU_DBG_CTL_AN_NONCE_MCT_DIS BIT_ULL(29) 122#define SPU_DBG_CTL_AN_NONCE_MCT_DIS BIT_ULL(29)
123 123
124#define BGX_SMUX_RX_INT 0x20000 124#define BGX_SMUX_RX_INT 0x20000
125#define BGX_SMUX_RX_FRM_CTL 0x20020
126#define BGX_PKT_RX_PTP_EN BIT_ULL(12)
125#define BGX_SMUX_RX_JABBER 0x20030 127#define BGX_SMUX_RX_JABBER 0x20030
126#define BGX_SMUX_RX_CTL 0x20048 128#define BGX_SMUX_RX_CTL 0x20048
127#define SMU_RX_CTL_STATUS (3ull << 0) 129#define SMU_RX_CTL_STATUS (3ull << 0)
@@ -172,6 +174,7 @@
172#define GMI_PORT_CFG_SPEED_MSB BIT_ULL(8) 174#define GMI_PORT_CFG_SPEED_MSB BIT_ULL(8)
173#define GMI_PORT_CFG_RX_IDLE BIT_ULL(12) 175#define GMI_PORT_CFG_RX_IDLE BIT_ULL(12)
174#define GMI_PORT_CFG_TX_IDLE BIT_ULL(13) 176#define GMI_PORT_CFG_TX_IDLE BIT_ULL(13)
177#define BGX_GMP_GMI_RXX_FRM_CTL 0x38028
175#define BGX_GMP_GMI_RXX_JABBER 0x38038 178#define BGX_GMP_GMI_RXX_JABBER 0x38038
176#define BGX_GMP_GMI_TXX_THRESH 0x38210 179#define BGX_GMP_GMI_TXX_THRESH 0x38210
177#define BGX_GMP_GMI_TXX_APPEND 0x38218 180#define BGX_GMP_GMI_TXX_APPEND 0x38218
@@ -223,6 +226,7 @@ void bgx_set_lmac_mac(int node, int bgx_idx, int lmacid, const u8 *mac);
223void bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status); 226void bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status);
224void bgx_lmac_internal_loopback(int node, int bgx_idx, 227void bgx_lmac_internal_loopback(int node, int bgx_idx,
225 int lmac_idx, bool enable); 228 int lmac_idx, bool enable);
229void bgx_config_timestamping(int node, int bgx_idx, int lmacid, bool enable);
226void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause); 230void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause);
227void bgx_lmac_set_pfc(int node, int bgx_idx, int lmacid, void *pause); 231void bgx_lmac_set_pfc(int node, int bgx_idx, int lmacid, void *pause);
228 232