Skip to content

Commit fb8d1d7

Browse files
committed
Merge branch 'net-aquantia-PTP-support-for-AQC-devices'
Igor Russkikh says: ==================== net: aquantia: PTP support for AQC devices This patchset introduces PTP feature support in Aquantia AQC atlantic driver. This implementation is a joined effort of aquantia developers: Egor is the main designer and driver/firmware architect on PTP, Sergey and Dmitry are included as co-developers. Dmitry also helped me in the overall patchset preparations. Feature was verified on AQC hardware with testptp tool, linuxptp, gptp and with Motu hardware unit. version3 updates: - Review comments applied: error handling, various fixes version2 updates: - Fixing issues from Andrew's review: replacing self with ptp var name, making ptp_clk_offset a field in the ptp instance. devm_kzalloc advice is actually non applicable, because ptp object gets created/destroyed on each network device close/open and it should not be linked with dev lifecycle. - Rearranging commit authorship, adding Egor as a ptp module main maintainer - Fixing kbuild 32bit division issues ==================== Acked-by: Richard Cochran <[email protected]> Signed-off-by: David S. Miller <[email protected]>
2 parents 337d866 + 4ef511b commit fb8d1d7

24 files changed

+2881
-134
lines changed

MAINTAINERS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,6 +1190,13 @@ Q: http://patchwork.ozlabs.org/project/netdev/list/
11901190
F: drivers/net/ethernet/aquantia/atlantic/
11911191
F: Documentation/networking/device_drivers/aquantia/atlantic.txt
11921192

1193+
AQUANTIA ETHERNET DRIVER PTP SUBSYSTEM
1194+
M: Egor Pomozov <[email protected]>
1195+
1196+
S: Supported
1197+
W: http://www.aquantia.com
1198+
F: drivers/net/ethernet/aquantia/atlantic/aq_ptp*
1199+
11931200
ARC FRAMEBUFFER DRIVER
11941201
M: Jaya Kumar <[email protected]>
11951202
S: Maintained

drivers/net/ethernet/aquantia/atlantic/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ atlantic-objs := aq_main.o \
2424
aq_ethtool.o \
2525
aq_drvinfo.o \
2626
aq_filters.o \
27+
aq_ptp.o \
28+
aq_phy.o \
2729
hw_atl/hw_atl_a0.o \
2830
hw_atl/hw_atl_b0.o \
2931
hw_atl/hw_atl_utils.o \

drivers/net/ethernet/aquantia/atlantic/aq_cfg.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* SPDX-License-Identifier: GPL-2.0-only */
22
/*
33
* aQuantia Corporation Network Driver
4-
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
4+
* Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
55
*/
66

77
/* File aq_cfg.h: Definition of configuration parameters and constants. */
@@ -27,7 +27,7 @@
2727

2828
#define AQ_CFG_INTERRUPT_MODERATION_USEC_MAX (0x1FF * 2)
2929

30-
#define AQ_CFG_IRQ_MASK 0x1FFU
30+
#define AQ_CFG_IRQ_MASK 0x3FFU
3131

3232
#define AQ_CFG_VECS_MAX 8U
3333
#define AQ_CFG_TCS_MAX 8U

drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/*
33
* aQuantia Corporation Network Driver
4-
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
4+
* Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
55
*/
66

77
/* File aq_ethtool.c: Definition of ethertool related functions. */
88

99
#include "aq_ethtool.h"
1010
#include "aq_nic.h"
1111
#include "aq_vec.h"
12+
#include "aq_ptp.h"
1213
#include "aq_filters.h"
1314

15+
#include <linux/ptp_clock_kernel.h>
16+
1417
static void aq_ethtool_get_regs(struct net_device *ndev,
1518
struct ethtool_regs *regs, void *p)
1619
{
@@ -377,6 +380,35 @@ static int aq_ethtool_set_wol(struct net_device *ndev,
377380
return err;
378381
}
379382

383+
static int aq_ethtool_get_ts_info(struct net_device *ndev,
384+
struct ethtool_ts_info *info)
385+
{
386+
struct aq_nic_s *aq_nic = netdev_priv(ndev);
387+
388+
ethtool_op_get_ts_info(ndev, info);
389+
390+
if (!aq_nic->aq_ptp)
391+
return 0;
392+
393+
info->so_timestamping |=
394+
SOF_TIMESTAMPING_TX_HARDWARE |
395+
SOF_TIMESTAMPING_RX_HARDWARE |
396+
SOF_TIMESTAMPING_RAW_HARDWARE;
397+
398+
info->tx_types = BIT(HWTSTAMP_TX_OFF) |
399+
BIT(HWTSTAMP_TX_ON);
400+
401+
info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
402+
403+
info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
404+
BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
405+
BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
406+
407+
info->phc_index = ptp_clock_index(aq_ptp_get_ptp_clock(aq_nic->aq_ptp));
408+
409+
return 0;
410+
}
411+
380412
static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed)
381413
{
382414
u32 rate = 0;
@@ -604,4 +636,5 @@ const struct ethtool_ops aq_ethtool_ops = {
604636
.set_link_ksettings = aq_ethtool_set_link_ksettings,
605637
.get_coalesce = aq_ethtool_get_coalesce,
606638
.set_coalesce = aq_ethtool_set_coalesce,
639+
.get_ts_info = aq_ethtool_get_ts_info,
607640
};

drivers/net/ethernet/aquantia/atlantic/aq_filters.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: GPL-2.0-only
2-
/* Copyright (C) 2014-2017 aQuantia Corporation. */
2+
/* Copyright (C) 2014-2019 aQuantia Corporation. */
33

44
/* File aq_filters.c: RX filters related functions. */
55

@@ -89,12 +89,14 @@ static int aq_check_approve_fl3l4(struct aq_nic_s *aq_nic,
8989
struct aq_hw_rx_fltrs_s *rx_fltrs,
9090
struct ethtool_rx_flow_spec *fsp)
9191
{
92+
u32 last_location = AQ_RX_LAST_LOC_FL3L4 -
93+
aq_nic->aq_hw_rx_fltrs.fl3l4.reserved_count;
94+
9295
if (fsp->location < AQ_RX_FIRST_LOC_FL3L4 ||
93-
fsp->location > AQ_RX_LAST_LOC_FL3L4) {
96+
fsp->location > last_location) {
9497
netdev_err(aq_nic->ndev,
9598
"ethtool: location must be in range [%d, %d]",
96-
AQ_RX_FIRST_LOC_FL3L4,
97-
AQ_RX_LAST_LOC_FL3L4);
99+
AQ_RX_FIRST_LOC_FL3L4, last_location);
98100
return -EINVAL;
99101
}
100102
if (rx_fltrs->fl3l4.is_ipv6 && rx_fltrs->fl3l4.active_ipv4) {
@@ -124,12 +126,15 @@ aq_check_approve_fl2(struct aq_nic_s *aq_nic,
124126
struct aq_hw_rx_fltrs_s *rx_fltrs,
125127
struct ethtool_rx_flow_spec *fsp)
126128
{
129+
u32 last_location = AQ_RX_LAST_LOC_FETHERT -
130+
aq_nic->aq_hw_rx_fltrs.fet_reserved_count;
131+
127132
if (fsp->location < AQ_RX_FIRST_LOC_FETHERT ||
128-
fsp->location > AQ_RX_LAST_LOC_FETHERT) {
133+
fsp->location > last_location) {
129134
netdev_err(aq_nic->ndev,
130135
"ethtool: location must be in range [%d, %d]",
131136
AQ_RX_FIRST_LOC_FETHERT,
132-
AQ_RX_LAST_LOC_FETHERT);
137+
last_location);
133138
return -EINVAL;
134139
}
135140

drivers/net/ethernet/aquantia/atlantic/aq_hw.h

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* SPDX-License-Identifier: GPL-2.0-only */
22
/*
33
* aQuantia Corporation Network Driver
4-
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
4+
* Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
55
*/
66

77
/* File aq_hw.h: Declaration of abstract interface for NIC hardware specific
@@ -15,6 +15,9 @@
1515
#include "aq_rss.h"
1616
#include "hw_atl/hw_atl_utils.h"
1717

18+
#define AQ_HW_MAC_COUNTER_HZ 312500000ll
19+
#define AQ_HW_PHY_COUNTER_HZ 160000000ll
20+
1821
#define AQ_RX_FIRST_LOC_FVLANID 0U
1922
#define AQ_RX_LAST_LOC_FVLANID 15U
2023
#define AQ_RX_FIRST_LOC_FETHERT 16U
@@ -94,6 +97,7 @@ struct aq_stats_s {
9497
#define AQ_HW_FLAG_STOPPING 0x00000008U
9598
#define AQ_HW_FLAG_RESETTING 0x00000010U
9699
#define AQ_HW_FLAG_CLOSING 0x00000020U
100+
#define AQ_HW_PTP_AVAILABLE 0x01000000U
97101
#define AQ_HW_LINK_DOWN 0x04000000U
98102
#define AQ_HW_FLAG_ERR_UNPLUG 0x40000000U
99103
#define AQ_HW_FLAG_ERR_HW 0x80000000U
@@ -135,6 +139,8 @@ struct aq_hw_s {
135139
u32 rpc_addr;
136140
u32 rpc_tid;
137141
struct hw_atl_utils_fw_rpc rpc;
142+
s64 ptp_clk_offset;
143+
u16 phy_id;
138144
};
139145

140146
struct aq_ring_s;
@@ -235,6 +241,40 @@ struct aq_hw_ops {
235241
int (*hw_set_offload)(struct aq_hw_s *self,
236242
struct aq_nic_cfg_s *aq_nic_cfg);
237243

244+
int (*hw_tx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode);
245+
246+
int (*hw_rx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode);
247+
248+
int (*hw_ring_hwts_rx_fill)(struct aq_hw_s *self,
249+
struct aq_ring_s *aq_ring);
250+
251+
int (*hw_ring_hwts_rx_receive)(struct aq_hw_s *self,
252+
struct aq_ring_s *ring);
253+
254+
void (*hw_get_ptp_ts)(struct aq_hw_s *self, u64 *stamp);
255+
256+
int (*hw_adj_clock_freq)(struct aq_hw_s *self, s32 delta);
257+
258+
int (*hw_adj_sys_clock)(struct aq_hw_s *self, s64 delta);
259+
260+
int (*hw_set_sys_clock)(struct aq_hw_s *self, u64 time, u64 ts);
261+
262+
int (*hw_ts_to_sys_clock)(struct aq_hw_s *self, u64 ts, u64 *time);
263+
264+
int (*hw_gpio_pulse)(struct aq_hw_s *self, u32 index, u64 start,
265+
u32 period);
266+
267+
int (*hw_extts_gpio_enable)(struct aq_hw_s *self, u32 index,
268+
u32 enable);
269+
270+
int (*hw_get_sync_ts)(struct aq_hw_s *self, u64 *ts);
271+
272+
u16 (*rx_extract_ts)(struct aq_hw_s *self, u8 *p, unsigned int len,
273+
u64 *timestamp);
274+
275+
int (*extract_hwts)(struct aq_hw_s *self, u8 *p, unsigned int len,
276+
u64 *timestamp);
277+
238278
int (*hw_set_fc)(struct aq_hw_s *self, u32 fc, u32 tc);
239279
};
240280

@@ -267,6 +307,12 @@ struct aq_fw_ops {
267307
int (*set_power)(struct aq_hw_s *self, unsigned int power_state,
268308
u8 *mac);
269309

310+
int (*send_fw_request)(struct aq_hw_s *self,
311+
const struct hw_fw_request_iface *fw_req,
312+
size_t size);
313+
314+
void (*enable_ptp)(struct aq_hw_s *self, int enable);
315+
270316
int (*set_eee_rate)(struct aq_hw_s *self, u32 speed);
271317

272318
int (*get_eee_rate)(struct aq_hw_s *self, u32 *rate,

drivers/net/ethernet/aquantia/atlantic/aq_main.c

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/*
33
* aQuantia Corporation Network Driver
4-
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
4+
* Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
55
*/
66

77
/* File aq_main.c: Main file for aQuantia Linux driver. */
@@ -10,10 +10,13 @@
1010
#include "aq_nic.h"
1111
#include "aq_pci_func.h"
1212
#include "aq_ethtool.h"
13+
#include "aq_ptp.h"
1314
#include "aq_filters.h"
1415

1516
#include <linux/netdevice.h>
1617
#include <linux/module.h>
18+
#include <linux/ip.h>
19+
#include <linux/udp.h>
1720

1821
MODULE_LICENSE("GPL v2");
1922
MODULE_VERSION(AQ_CFG_DRV_VERSION);
@@ -93,6 +96,24 @@ static int aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
9396
{
9497
struct aq_nic_s *aq_nic = netdev_priv(ndev);
9598

99+
if (unlikely(aq_utils_obj_test(&aq_nic->flags, AQ_NIC_PTP_DPATH_UP))) {
100+
/* Hardware adds the Timestamp for PTPv2 802.AS1
101+
* and PTPv2 IPv4 UDP.
102+
* We have to push even general 320 port messages to the ptp
103+
* queue explicitly. This is a limitation of current firmware
104+
* and hardware PTP design of the chip. Otherwise ptp stream
105+
* will fail to sync
106+
*/
107+
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) ||
108+
unlikely((ip_hdr(skb)->version == 4) &&
109+
(ip_hdr(skb)->protocol == IPPROTO_UDP) &&
110+
((udp_hdr(skb)->dest == htons(319)) ||
111+
(udp_hdr(skb)->dest == htons(320)))) ||
112+
unlikely(eth_hdr(skb)->h_proto == htons(ETH_P_1588)))
113+
return aq_ptp_xmit(aq_nic, skb);
114+
}
115+
116+
skb_tx_timestamp(skb);
96117
return aq_nic_xmit(aq_nic, skb);
97118
}
98119

@@ -197,6 +218,87 @@ static void aq_ndev_set_multicast_settings(struct net_device *ndev)
197218
(void)aq_nic_set_multicast_list(aq_nic, ndev);
198219
}
199220

221+
static int aq_ndev_config_hwtstamp(struct aq_nic_s *aq_nic,
222+
struct hwtstamp_config *config)
223+
{
224+
if (config->flags)
225+
return -EINVAL;
226+
227+
switch (config->tx_type) {
228+
case HWTSTAMP_TX_OFF:
229+
case HWTSTAMP_TX_ON:
230+
break;
231+
default:
232+
return -ERANGE;
233+
}
234+
235+
switch (config->rx_filter) {
236+
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
237+
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
238+
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
239+
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
240+
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
241+
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
242+
case HWTSTAMP_FILTER_PTP_V2_SYNC:
243+
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
244+
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
245+
break;
246+
case HWTSTAMP_FILTER_PTP_V2_EVENT:
247+
case HWTSTAMP_FILTER_NONE:
248+
break;
249+
default:
250+
return -ERANGE;
251+
}
252+
253+
return aq_ptp_hwtstamp_config_set(aq_nic->aq_ptp, config);
254+
}
255+
256+
static int aq_ndev_hwtstamp_set(struct aq_nic_s *aq_nic, struct ifreq *ifr)
257+
{
258+
struct hwtstamp_config config;
259+
int ret_val;
260+
261+
if (!aq_nic->aq_ptp)
262+
return -EOPNOTSUPP;
263+
264+
if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
265+
return -EFAULT;
266+
267+
ret_val = aq_ndev_config_hwtstamp(aq_nic, &config);
268+
if (ret_val)
269+
return ret_val;
270+
271+
return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
272+
-EFAULT : 0;
273+
}
274+
275+
static int aq_ndev_hwtstamp_get(struct aq_nic_s *aq_nic, struct ifreq *ifr)
276+
{
277+
struct hwtstamp_config config;
278+
279+
if (!aq_nic->aq_ptp)
280+
return -EOPNOTSUPP;
281+
282+
aq_ptp_hwtstamp_config_get(aq_nic->aq_ptp, &config);
283+
return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
284+
-EFAULT : 0;
285+
}
286+
287+
static int aq_ndev_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
288+
{
289+
struct aq_nic_s *aq_nic = netdev_priv(netdev);
290+
291+
switch (cmd) {
292+
case SIOCSHWTSTAMP:
293+
return aq_ndev_hwtstamp_set(aq_nic, ifr);
294+
295+
case SIOCGHWTSTAMP:
296+
return aq_ndev_hwtstamp_get(aq_nic, ifr);
297+
}
298+
299+
return -EOPNOTSUPP;
300+
}
301+
200302
static int aq_ndo_vlan_rx_add_vid(struct net_device *ndev, __be16 proto,
201303
u16 vid)
202304
{
@@ -234,6 +336,7 @@ static const struct net_device_ops aq_ndev_ops = {
234336
.ndo_change_mtu = aq_ndev_change_mtu,
235337
.ndo_set_mac_address = aq_ndev_set_mac_address,
236338
.ndo_set_features = aq_ndev_set_features,
339+
.ndo_do_ioctl = aq_ndev_ioctl,
237340
.ndo_vlan_rx_add_vid = aq_ndo_vlan_rx_add_vid,
238341
.ndo_vlan_rx_kill_vid = aq_ndo_vlan_rx_kill_vid,
239342
};

0 commit comments

Comments
 (0)