static int raw_open(struct transport *t, const char *name, struct fdarray *fda, enum timestamp_type ts_type) { struct raw *raw = container_of(t, struct raw, t); int efd, gfd; mac_to_addr(&raw->ptp_addr, ptp_dst_mac); mac_to_addr(&raw->p2p_addr, p2p_dst_mac); if (sk_interface_macaddr(name, &raw->src_addr)) goto no_mac; efd = open_socket(name, 1); if (efd < 0) goto no_event; gfd = open_socket(name, 0); if (gfd < 0) goto no_general; if (sk_timestamping_init(efd, name, ts_type, TRANS_IEEE_802_3)) goto no_timestamping; if (sk_general_init(gfd)) goto no_timestamping; fda->fd[FD_EVENT] = efd; fda->fd[FD_GENERAL] = gfd; return 0; no_timestamping: close(gfd); no_general: close(efd); no_event: no_mac: return -1; }
int sk_timestamping_init(int fd, const char *device, enum timestamp_type type, enum transport_type transport) { int err, filter1, filter2 = 0, flags, one_step; switch (type) { case TS_SOFTWARE: flags = SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE; break; case TS_HARDWARE: case TS_ONESTEP: flags = SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; break; case TS_LEGACY_HW: flags = SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_SYS_HARDWARE; break; default: return -1; } if (type != TS_SOFTWARE) { filter1 = HWTSTAMP_FILTER_PTP_V2_EVENT; one_step = type == TS_ONESTEP ? 1 : 0; 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, one_step); if (err) { pr_info("driver rejected most general HWTSTAMP filter"); err = hwts_init(fd, device, filter2, one_step); if (err) { pr_err("ioctl SIOCSHWTSTAMP failed: %m"); return err; } } } if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, &flags, sizeof(flags)) < 0) { pr_err("ioctl SO_TIMESTAMPING failed: %m"); return -1; } flags = 1; if (setsockopt(fd, SOL_SOCKET, SO_SELECT_ERR_QUEUE, &flags, sizeof(flags)) < 0) { pr_warning("%s: SO_SELECT_ERR_QUEUE: %m", device); sk_events = 0; sk_revents = POLLERR; } /* Enable the sk_check_fupsync option, perhaps. */ if (sk_general_init(fd)) { return -1; } return 0; }