Commit 313aa13a authored by Íñigo Huguet's avatar Íñigo Huguet Committed by David S. Miller

sfc: allow more flexible way of adding filters for PTP

In preparation for the support of PTP over IPv6/UDP and Ethernet in next
patches, allow a more flexible way of adding and removing RX filters for
PTP. Right now, only 2 filters are allowed, which are the ones needed
for PTP over IPv4/UDP.
Signed-off-by: default avatarÍñigo Huguet <ihuguet@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 13248b97
...@@ -118,6 +118,8 @@ ...@@ -118,6 +118,8 @@
#define PTP_MIN_LENGTH 63 #define PTP_MIN_LENGTH 63
#define PTP_RXFILTERS_LEN 2
#define PTP_ADDRESS 0xe0000181 /* 224.0.1.129 */ #define PTP_ADDRESS 0xe0000181 /* 224.0.1.129 */
#define PTP_EVENT_PORT 319 #define PTP_EVENT_PORT 319
#define PTP_GENERAL_PORT 320 #define PTP_GENERAL_PORT 320
...@@ -224,9 +226,8 @@ struct efx_ptp_timeset { ...@@ -224,9 +226,8 @@ struct efx_ptp_timeset {
* @work: Work task * @work: Work task
* @reset_required: A serious error has occurred and the PTP task needs to be * @reset_required: A serious error has occurred and the PTP task needs to be
* reset (disable, enable). * reset (disable, enable).
* @rxfilter_event: Receive filter when operating * @rxfilters: Receive filters when operating
* @rxfilter_general: Receive filter when operating * @rxfilters_count: Num of installed rxfilters, should be == PTP_RXFILTERS_LEN
* @rxfilter_installed: Receive filter installed
* @config: Current timestamp configuration * @config: Current timestamp configuration
* @enabled: PTP operation enabled * @enabled: PTP operation enabled
* @mode: Mode in which PTP operating (PTP version) * @mode: Mode in which PTP operating (PTP version)
...@@ -295,9 +296,8 @@ struct efx_ptp_data { ...@@ -295,9 +296,8 @@ struct efx_ptp_data {
struct workqueue_struct *workwq; struct workqueue_struct *workwq;
struct work_struct work; struct work_struct work;
bool reset_required; bool reset_required;
u32 rxfilter_event; u32 rxfilters[PTP_RXFILTERS_LEN];
u32 rxfilter_general; size_t rxfilters_count;
bool rxfilter_installed;
struct hwtstamp_config config; struct hwtstamp_config config;
bool enabled; bool enabled;
unsigned int mode; unsigned int mode;
...@@ -1290,61 +1290,57 @@ static void efx_ptp_remove_multicast_filters(struct efx_nic *efx) ...@@ -1290,61 +1290,57 @@ static void efx_ptp_remove_multicast_filters(struct efx_nic *efx)
{ {
struct efx_ptp_data *ptp = efx->ptp_data; struct efx_ptp_data *ptp = efx->ptp_data;
if (ptp->rxfilter_installed) { while (ptp->rxfilters_count) {
efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, ptp->rxfilters_count--;
ptp->rxfilter_general);
efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED,
ptp->rxfilter_event); ptp->rxfilters[ptp->rxfilters_count]);
ptp->rxfilter_installed = false;
} }
} }
static int efx_ptp_insert_multicast_filters(struct efx_nic *efx) static int efx_ptp_insert_ipv4_filter(struct efx_nic *efx, u16 port)
{ {
struct efx_ptp_data *ptp = efx->ptp_data; struct efx_ptp_data *ptp = efx->ptp_data;
struct efx_filter_spec rxfilter; struct efx_filter_spec rxfilter;
int rc; int rc;
if (!ptp->channel || ptp->rxfilter_installed)
return 0;
/* Must filter on both event and general ports to ensure
* that there is no packet re-ordering.
*/
efx_filter_init_rx(&rxfilter, EFX_FILTER_PRI_REQUIRED, 0, efx_filter_init_rx(&rxfilter, EFX_FILTER_PRI_REQUIRED, 0,
efx_rx_queue_index( efx_rx_queue_index(
efx_channel_get_rx_queue(ptp->channel))); efx_channel_get_rx_queue(ptp->channel)));
rc = efx_filter_set_ipv4_local(&rxfilter, IPPROTO_UDP,
htonl(PTP_ADDRESS), efx_filter_set_ipv4_local(&rxfilter, IPPROTO_UDP, htonl(PTP_ADDRESS),
htons(PTP_EVENT_PORT)); htons(port));
if (rc != 0)
return rc;
rc = efx_filter_insert_filter(efx, &rxfilter, true); rc = efx_filter_insert_filter(efx, &rxfilter, true);
if (rc < 0) if (rc < 0)
return rc; return rc;
ptp->rxfilter_event = rc; ptp->rxfilters[ptp->rxfilters_count] = rc;
ptp->rxfilters_count++;
return 0;
}
efx_filter_init_rx(&rxfilter, EFX_FILTER_PRI_REQUIRED, 0, static int efx_ptp_insert_multicast_filters(struct efx_nic *efx)
efx_rx_queue_index( {
efx_channel_get_rx_queue(ptp->channel))); struct efx_ptp_data *ptp = efx->ptp_data;
rc = efx_filter_set_ipv4_local(&rxfilter, IPPROTO_UDP, int rc;
htonl(PTP_ADDRESS),
htons(PTP_GENERAL_PORT)); if (!ptp->channel || ptp->rxfilters_count)
if (rc != 0) return 0;
/* Must filter on both event and general ports to ensure
* that there is no packet re-ordering.
*/
rc = efx_ptp_insert_ipv4_filter(efx, PTP_EVENT_PORT);
if (rc < 0)
goto fail; goto fail;
rc = efx_filter_insert_filter(efx, &rxfilter, true); rc = efx_ptp_insert_ipv4_filter(efx, PTP_GENERAL_PORT);
if (rc < 0) if (rc < 0)
goto fail; goto fail;
ptp->rxfilter_general = rc;
ptp->rxfilter_installed = true;
return 0; return 0;
fail: fail:
efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, efx_ptp_remove_multicast_filters(efx);
ptp->rxfilter_event);
return rc; return rc;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment