|
118 | 118 |
|
119 | 119 | #define PTP_MIN_LENGTH 63 |
120 | 120 |
|
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 */ |
122 | 126 | #define PTP_EVENT_PORT 319 |
123 | 127 | #define PTP_GENERAL_PORT 320 |
| 128 | +#define PTP_ADDR_ETHER {0x01, 0x1b, 0x19, 0, 0, 0} /* 01-1B-19-00-00-00 */ |
124 | 129 |
|
125 | 130 | /* Annoyingly the format of the version numbers are different between |
126 | 131 | * versions 1 and 2 so it isn't possible to simply look for 1 or 2. |
@@ -224,9 +229,8 @@ struct efx_ptp_timeset { |
224 | 229 | * @work: Work task |
225 | 230 | * @reset_required: A serious error has occurred and the PTP task needs to be |
226 | 231 | * 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 |
230 | 234 | * @config: Current timestamp configuration |
231 | 235 | * @enabled: PTP operation enabled |
232 | 236 | * @mode: Mode in which PTP operating (PTP version) |
@@ -295,9 +299,8 @@ struct efx_ptp_data { |
295 | 299 | struct workqueue_struct *workwq; |
296 | 300 | struct work_struct work; |
297 | 301 | 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; |
301 | 304 | struct hwtstamp_config config; |
302 | 305 | bool enabled; |
303 | 306 | unsigned int mode; |
@@ -1290,61 +1293,108 @@ static void efx_ptp_remove_multicast_filters(struct efx_nic *efx) |
1290 | 1293 | { |
1291 | 1294 | struct efx_ptp_data *ptp = efx->ptp_data; |
1292 | 1295 |
|
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--; |
1296 | 1298 | 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]); |
1299 | 1300 | } |
1300 | 1301 | } |
1301 | 1302 |
|
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) |
1303 | 1315 | { |
1304 | 1316 | 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 | +{ |
1305 | 1328 | 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; |
1306 | 1361 | int rc; |
1307 | 1362 |
|
1308 | | - if (!ptp->channel || ptp->rxfilter_installed) |
| 1363 | + if (!ptp->channel || ptp->rxfilters_count) |
1309 | 1364 | return 0; |
1310 | 1365 |
|
1311 | 1366 | /* Must filter on both event and general ports to ensure |
1312 | 1367 | * that there is no packet re-ordering. |
1313 | 1368 | */ |
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); |
1324 | 1370 | 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) |
1335 | 1371 | goto fail; |
1336 | 1372 |
|
1337 | | - rc = efx_filter_insert_filter(efx, &rxfilter, true); |
| 1373 | + rc = efx_ptp_insert_ipv4_filter(efx, PTP_GENERAL_PORT); |
1338 | 1374 | if (rc < 0) |
1339 | 1375 | goto fail; |
1340 | | - ptp->rxfilter_general = rc; |
1341 | 1376 |
|
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 | + |
1343 | 1394 | return 0; |
1344 | 1395 |
|
1345 | 1396 | fail: |
1346 | | - efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, |
1347 | | - ptp->rxfilter_event); |
| 1397 | + efx_ptp_remove_multicast_filters(efx); |
1348 | 1398 | return rc; |
1349 | 1399 | } |
1350 | 1400 |
|
|
0 commit comments