Try two different HWTSTAMP options.

Start with the most general HWTSTAMP option. If that fails, fall back
to the option that best fits the interface's transport.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Acked-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Jiri Benc <jbenc@redhat.com>
master
Richard Cochran 2012-10-25 20:55:28 +02:00
parent 8dde0d31b6
commit 870873c7a7
1 changed files with 31 additions and 9 deletions

40
sk.c
View File

@ -36,7 +36,7 @@ int sk_tx_retries = 2, sk_prefer_layer2 = 0;
/* private methods */ /* private methods */
static int hwts_init(int fd, char *device) static int hwts_init(int fd, char *device, int rx_filter)
{ {
struct ifreq ifreq; struct ifreq ifreq;
struct hwtstamp_config cfg, req; struct hwtstamp_config cfg, req;
@ -49,13 +49,11 @@ static int hwts_init(int fd, char *device)
ifreq.ifr_data = (void *) &cfg; ifreq.ifr_data = (void *) &cfg;
cfg.tx_type = HWTSTAMP_TX_ON; cfg.tx_type = HWTSTAMP_TX_ON;
cfg.rx_filter = sk_prefer_layer2 ? cfg.rx_filter = rx_filter;
HWTSTAMP_FILTER_PTP_V2_L2_EVENT : HWTSTAMP_FILTER_PTP_V2_EVENT;
req = cfg; req = cfg;
err = ioctl(fd, SIOCSHWTSTAMP, &ifreq); err = ioctl(fd, SIOCSHWTSTAMP, &ifreq);
if (err < 0) if (err < 0)
pr_err("ioctl SIOCSHWTSTAMP failed: %m"); return err;
if (memcmp(&cfg, &req, sizeof(cfg))) { if (memcmp(&cfg, &req, sizeof(cfg))) {
@ -70,7 +68,7 @@ static int hwts_init(int fd, char *device)
} }
} }
return err ? errno : 0; return 0;
} }
/* public methods */ /* public methods */
@ -226,7 +224,7 @@ int sk_receive(int fd, void *buf, int buflen,
int sk_timestamping_init(int fd, char *device, enum timestamp_type type, int sk_timestamping_init(int fd, char *device, enum timestamp_type type,
enum transport_type transport) enum transport_type transport)
{ {
int flags; int err, filter1, filter2, flags;
switch (type) { switch (type) {
case TS_SOFTWARE: case TS_SOFTWARE:
@ -248,8 +246,32 @@ int sk_timestamping_init(int fd, char *device, enum timestamp_type type,
return -1; return -1;
} }
if (type != TS_SOFTWARE && hwts_init(fd, device)) if (type != TS_SOFTWARE) {
return -1; filter1 = HWTSTAMP_FILTER_PTP_V2_EVENT;
switch (transport) {
case TRANS_UDP_IPV4:
case TRANS_UDP_IPV6:
filter2 = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
break;
case TRANS_IEEE_802_3:
filter2 = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
break;
case TRANS_DEVICENET:
case TRANS_CONTROLNET:
case TRANS_PROFINET:
case TRANS_UDS:
return -1;
}
err = hwts_init(fd, device, filter1);
if (err) {
pr_info("driver rejected most general HWTSTAMP filter");
err = hwts_init(fd, device, filter2);
if (err) {
pr_err("ioctl SIOCSHWTSTAMP failed: %m");
return err;
}
}
}
if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
&flags, sizeof(flags)) < 0) { &flags, sizeof(flags)) < 0) {