Skip to content

Commit 98ba810

Browse files
committed
Merge branch 'sfc-ptp'
Edward Cree says: ==================== sfc: add support for PTP over IPv6 and 802.3 Most recent cards (8000 series and newer) had enough hardware support for this, but it was not enabled in the driver. The transmission of PTP packets over these protocols was already added in commit bd4a269 ("sfc: use hardware tx timestamps for more than PTP"), but receiving them was already unsupported so synchronization didn't happen. These patches add support for timestamping received packets over IPv6/UPD and IEEE802.3. v2: fixed weird indentation in efx_ptp_init_filter v3: fixed bug caused by usage of htons in PTP_EVENT_PORT definition. It was used in more places, where htons was used too, so using it 2 times leave it again in host order. I didn't detected it in my tests because it only affected if timestamping through the MC, but the model I used do it through the MAC. Detected by kernel test robot <lkp@intel.com> v4: removed `inline` specifiers from 2 local functions v5: restored deleted comment with useful explanation about packets reordering. Deleted useless whitespaces. ==================== Reviewed-by: Edward Cree <ecree.xilinx@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 13248b9 + e4616f6 commit 98ba810

File tree

2 files changed

+111
-39
lines changed

2 files changed

+111
-39
lines changed

drivers/net/ethernet/sfc/filter.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <linux/types.h>
1111
#include <linux/if_ether.h>
12+
#include <linux/in6.h>
1213
#include <asm/byteorder.h>
1314

1415
/**
@@ -223,6 +224,27 @@ efx_filter_set_ipv4_local(struct efx_filter_spec *spec, u8 proto,
223224
return 0;
224225
}
225226

227+
/**
228+
* efx_filter_set_ipv6_local - specify IPv6 host, transport protocol and port
229+
* @spec: Specification to initialise
230+
* @proto: Transport layer protocol number
231+
* @host: Local host address (network byte order)
232+
* @port: Local port (network byte order)
233+
*/
234+
static inline int
235+
efx_filter_set_ipv6_local(struct efx_filter_spec *spec, u8 proto,
236+
const struct in6_addr *host, __be16 port)
237+
{
238+
spec->match_flags |=
239+
EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
240+
EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
241+
spec->ether_type = htons(ETH_P_IPV6);
242+
spec->ip_proto = proto;
243+
memcpy(spec->loc_host, host, sizeof(spec->loc_host));
244+
spec->loc_port = port;
245+
return 0;
246+
}
247+
226248
/**
227249
* efx_filter_set_ipv4_full - specify IPv4 hosts, transport protocol and ports
228250
* @spec: Specification to initialise

drivers/net/ethernet/sfc/ptp.c

Lines changed: 89 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,14 @@
118118

119119
#define PTP_MIN_LENGTH 63
120120

121-
#define PTP_ADDRESS 0xe0000181 /* 224.0.1.129 */
121+
#define PTP_RXFILTERS_LEN 5
122+
123+
#define PTP_ADDR_IPV4 0xe0000181 /* 224.0.1.129 */
124+
#define PTP_ADDR_IPV6 {0xff, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
125+
0, 0x01, 0x81} /* ff0e::181 */
122126
#define PTP_EVENT_PORT 319
123127
#define PTP_GENERAL_PORT 320
128+
#define PTP_ADDR_ETHER {0x01, 0x1b, 0x19, 0, 0, 0} /* 01-1B-19-00-00-00 */
124129

125130
/* Annoyingly the format of the version numbers are different between
126131
* versions 1 and 2 so it isn't possible to simply look for 1 or 2.
@@ -224,9 +229,8 @@ struct efx_ptp_timeset {
224229
* @work: Work task
225230
* @reset_required: A serious error has occurred and the PTP task needs to be
226231
* reset (disable, enable).
227-
* @rxfilter_event: Receive filter when operating
228-
* @rxfilter_general: Receive filter when operating
229-
* @rxfilter_installed: Receive filter installed
232+
* @rxfilters: Receive filters when operating
233+
* @rxfilters_count: Num of installed rxfilters, should be == PTP_RXFILTERS_LEN
230234
* @config: Current timestamp configuration
231235
* @enabled: PTP operation enabled
232236
* @mode: Mode in which PTP operating (PTP version)
@@ -295,9 +299,8 @@ struct efx_ptp_data {
295299
struct workqueue_struct *workwq;
296300
struct work_struct work;
297301
bool reset_required;
298-
u32 rxfilter_event;
299-
u32 rxfilter_general;
300-
bool rxfilter_installed;
302+
u32 rxfilters[PTP_RXFILTERS_LEN];
303+
size_t rxfilters_count;
301304
struct hwtstamp_config config;
302305
bool enabled;
303306
unsigned int mode;
@@ -1290,61 +1293,108 @@ static void efx_ptp_remove_multicast_filters(struct efx_nic *efx)
12901293
{
12911294
struct efx_ptp_data *ptp = efx->ptp_data;
12921295

1293-
if (ptp->rxfilter_installed) {
1294-
efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED,
1295-
ptp->rxfilter_general);
1296+
while (ptp->rxfilters_count) {
1297+
ptp->rxfilters_count--;
12961298
efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED,
1297-
ptp->rxfilter_event);
1298-
ptp->rxfilter_installed = false;
1299+
ptp->rxfilters[ptp->rxfilters_count]);
12991300
}
13001301
}
13011302

1302-
static int efx_ptp_insert_multicast_filters(struct efx_nic *efx)
1303+
static void efx_ptp_init_filter(struct efx_nic *efx,
1304+
struct efx_filter_spec *rxfilter)
1305+
{
1306+
struct efx_channel *channel = efx->ptp_data->channel;
1307+
struct efx_rx_queue *queue = efx_channel_get_rx_queue(channel);
1308+
1309+
efx_filter_init_rx(rxfilter, EFX_FILTER_PRI_REQUIRED, 0,
1310+
efx_rx_queue_index(queue));
1311+
}
1312+
1313+
static int efx_ptp_insert_filter(struct efx_nic *efx,
1314+
struct efx_filter_spec *rxfilter)
13031315
{
13041316
struct efx_ptp_data *ptp = efx->ptp_data;
1317+
1318+
int rc = efx_filter_insert_filter(efx, rxfilter, true);
1319+
if (rc < 0)
1320+
return rc;
1321+
ptp->rxfilters[ptp->rxfilters_count] = rc;
1322+
ptp->rxfilters_count++;
1323+
return 0;
1324+
}
1325+
1326+
static int efx_ptp_insert_ipv4_filter(struct efx_nic *efx, u16 port)
1327+
{
13051328
struct efx_filter_spec rxfilter;
1329+
1330+
efx_ptp_init_filter(efx, &rxfilter);
1331+
efx_filter_set_ipv4_local(&rxfilter, IPPROTO_UDP, htonl(PTP_ADDR_IPV4),
1332+
htons(port));
1333+
return efx_ptp_insert_filter(efx, &rxfilter);
1334+
}
1335+
1336+
static int efx_ptp_insert_ipv6_filter(struct efx_nic *efx, u16 port)
1337+
{
1338+
const struct in6_addr addr = {{PTP_ADDR_IPV6}};
1339+
struct efx_filter_spec rxfilter;
1340+
1341+
efx_ptp_init_filter(efx, &rxfilter);
1342+
efx_filter_set_ipv6_local(&rxfilter, IPPROTO_UDP, &addr, htons(port));
1343+
return efx_ptp_insert_filter(efx, &rxfilter);
1344+
}
1345+
1346+
static int efx_ptp_insert_eth_filter(struct efx_nic *efx)
1347+
{
1348+
const u8 addr[ETH_ALEN] = PTP_ADDR_ETHER;
1349+
struct efx_filter_spec rxfilter;
1350+
1351+
efx_ptp_init_filter(efx, &rxfilter);
1352+
efx_filter_set_eth_local(&rxfilter, EFX_FILTER_VID_UNSPEC, addr);
1353+
rxfilter.match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
1354+
rxfilter.ether_type = htons(ETH_P_1588);
1355+
return efx_ptp_insert_filter(efx, &rxfilter);
1356+
}
1357+
1358+
static int efx_ptp_insert_multicast_filters(struct efx_nic *efx)
1359+
{
1360+
struct efx_ptp_data *ptp = efx->ptp_data;
13061361
int rc;
13071362

1308-
if (!ptp->channel || ptp->rxfilter_installed)
1363+
if (!ptp->channel || ptp->rxfilters_count)
13091364
return 0;
13101365

13111366
/* Must filter on both event and general ports to ensure
13121367
* that there is no packet re-ordering.
13131368
*/
1314-
efx_filter_init_rx(&rxfilter, EFX_FILTER_PRI_REQUIRED, 0,
1315-
efx_rx_queue_index(
1316-
efx_channel_get_rx_queue(ptp->channel)));
1317-
rc = efx_filter_set_ipv4_local(&rxfilter, IPPROTO_UDP,
1318-
htonl(PTP_ADDRESS),
1319-
htons(PTP_EVENT_PORT));
1320-
if (rc != 0)
1321-
return rc;
1322-
1323-
rc = efx_filter_insert_filter(efx, &rxfilter, true);
1369+
rc = efx_ptp_insert_ipv4_filter(efx, PTP_EVENT_PORT);
13241370
if (rc < 0)
1325-
return rc;
1326-
ptp->rxfilter_event = rc;
1327-
1328-
efx_filter_init_rx(&rxfilter, EFX_FILTER_PRI_REQUIRED, 0,
1329-
efx_rx_queue_index(
1330-
efx_channel_get_rx_queue(ptp->channel)));
1331-
rc = efx_filter_set_ipv4_local(&rxfilter, IPPROTO_UDP,
1332-
htonl(PTP_ADDRESS),
1333-
htons(PTP_GENERAL_PORT));
1334-
if (rc != 0)
13351371
goto fail;
13361372

1337-
rc = efx_filter_insert_filter(efx, &rxfilter, true);
1373+
rc = efx_ptp_insert_ipv4_filter(efx, PTP_GENERAL_PORT);
13381374
if (rc < 0)
13391375
goto fail;
1340-
ptp->rxfilter_general = rc;
13411376

1342-
ptp->rxfilter_installed = true;
1377+
/* if the NIC supports hw timestamps by the MAC, we can support
1378+
* PTP over IPv6 and Ethernet
1379+
*/
1380+
if (efx_ptp_use_mac_tx_timestamps(efx)) {
1381+
rc = efx_ptp_insert_ipv6_filter(efx, PTP_EVENT_PORT);
1382+
if (rc < 0)
1383+
goto fail;
1384+
1385+
rc = efx_ptp_insert_ipv6_filter(efx, PTP_GENERAL_PORT);
1386+
if (rc < 0)
1387+
goto fail;
1388+
1389+
rc = efx_ptp_insert_eth_filter(efx);
1390+
if (rc < 0)
1391+
goto fail;
1392+
}
1393+
13431394
return 0;
13441395

13451396
fail:
1346-
efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED,
1347-
ptp->rxfilter_event);
1397+
efx_ptp_remove_multicast_filters(efx);
13481398
return rc;
13491399
}
13501400

0 commit comments

Comments
 (0)