Now that the current timestamp is saved in a variable lets add the ETHTOOL_MSG_TS_SET ethtool netlink socket to make it selectable.
Unified · Split
| @@ -227,6 +227,7 @@ Userspace to kernel: · 226 unmodified lines | ||
| 227 | 227 | ``ETHTOOL_MSG_MM_SET`` set MAC merge layer parameters |
| 228 | 228 | ``ETHTOOL_MSG_TS_GET`` get current timestamping |
| 229 | 229 | ``ETHTOOL_MSG_TS_LIST_GET`` list available timestampings |
| 230 | + ``ETHTOOL_MSG_TS_SET`` set current timestamping | |
| 230 | 231 | ===================================== ================================= |
| 231 | 232 | |
| 232 | 233 | Kernel to userspace: |
| @@ -2038,6 +2039,21 @@ Kernel response contents: · 1805 unmodified lines | ||
| 2038 | 2039 | |
| 2039 | 2040 | This command lists all the possible timestamp layer available. |
| 2040 | 2041 | |
| 2042 | +TS_SET | |
| 2043 | +====== | |
| 2044 | + | |
| 2045 | +Modify the selected timestamping. | |
| 2046 | + | |
| 2047 | +Request contents: | |
| 2048 | + | |
| 2049 | + ======================= ====== =================== | |
| 2050 | + ``ETHTOOL_A_TS_HEADER`` nested reply header | |
| 2051 | + ``ETHTOOL_A_TS_LAYER`` u32 timestamping | |
| 2052 | + ======================= ====== =================== | |
| 2053 | + | |
| 2054 | +This command set the timestamping with one that should be listed by the | |
| 2055 | +TSLIST_GET command. | |
| 2056 | + | |
| 2041 | 2057 | Request translation |
| 2042 | 2058 | =================== |
| 2043 | 2059 | |
| @@ -2146,4 +2162,5 @@ are netlink only. · 102 unmodified lines | ||
| 2146 | 2162 | n/a ``ETHTOOL_MSG_MM_SET`` |
| 2147 | 2163 | n/a ``ETHTOOL_MSG_TS_GET`` |
| 2148 | 2164 | n/a ``ETHTOOL_MSG_TS_LIST_GET`` |
| 2165 | + n/a ``ETHTOOL_MSG_TS_SET`` | |
| 2149 | 2166 | =================================== ===================================== |
| @@ -59,6 +59,7 @@ enum { · 58 unmodified lines | ||
| 59 | 59 | ETHTOOL_MSG_MM_SET, |
| 60 | 60 | ETHTOOL_MSG_TS_GET, |
| 61 | 61 | ETHTOOL_MSG_TS_LIST_GET, |
| 62 | + ETHTOOL_MSG_TS_SET, | |
| 62 | 63 | |
| 63 | 64 | /* add new constants above here */ |
| 64 | 65 | __ETHTOOL_MSG_USER_CNT, |
| @@ -308,6 +308,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { · 307 unmodified lines | ||
| 308 | 308 | [ETHTOOL_MSG_MM_SET] = ðnl_mm_request_ops, |
| 309 | 309 | [ETHTOOL_MSG_TS_GET] = ðnl_ts_request_ops, |
| 310 | 310 | [ETHTOOL_MSG_TS_LIST_GET] = ðnl_ts_list_request_ops, |
| 311 | + [ETHTOOL_MSG_TS_SET] = ðnl_ts_request_ops, | |
| 311 | 312 | }; |
| 312 | 313 | |
| 313 | 314 | static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) |
| @@ -1148,6 +1149,13 @@ static const struct genl_ops ethtool_genl_ops[] = { · 834 unmodified lines | ||
| 1148 | 1149 | .policy = ethnl_ts_get_policy, |
| 1149 | 1150 | .maxattr = ARRAY_SIZE(ethnl_ts_get_policy) - 1, |
| 1150 | 1151 | }, |
| 1152 | + { | |
| 1153 | + .cmd = ETHTOOL_MSG_TS_SET, | |
| 1154 | + .flags = GENL_UNS_ADMIN_PERM, | |
| 1155 | + .doit = ethnl_default_set_doit, | |
| 1156 | + .policy = ethnl_ts_set_policy, | |
| 1157 | + .maxattr = ARRAY_SIZE(ethnl_ts_set_policy) - 1, | |
| 1158 | + }, | |
| 1151 | 1159 | }; |
| 1152 | 1160 | |
| 1153 | 1161 | static const struct genl_multicast_group ethtool_nl_mcgrps[] = { |
| @@ -444,6 +444,7 @@ extern const struct nla_policy ethnl_plca_get_status_policy[ETHTOOL_A_PLCA_HEADE · 443 unmodified lines | ||
| 444 | 444 | extern const struct nla_policy ethnl_mm_get_policy[ETHTOOL_A_MM_HEADER + 1]; |
| 445 | 445 | extern const struct nla_policy ethnl_mm_set_policy[ETHTOOL_A_MM_MAX + 1]; |
| 446 | 446 | extern const struct nla_policy ethnl_ts_get_policy[ETHTOOL_A_TS_HEADER + 1]; |
| 447 | +extern const struct nla_policy ethnl_ts_set_policy[ETHTOOL_A_TS_MAX + 1]; | |
| 447 | 448 | |
| 448 | 449 | int ethnl_set_features(struct sk_buff *skb, struct genl_info *info); |
| 449 | 450 | int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info); |
| @@ -59,6 +59,102 @@ static int ts_fill_reply(struct sk_buff *skb, · 58 unmodified lines | ||
| 59 | 59 | return nla_put_u32(skb, ETHTOOL_A_TS_LAYER, data->ts_layer); |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | +/* TS_SET */ | |
| 63 | +const struct nla_policy ethnl_ts_set_policy[] = { | |
| 64 | + [ETHTOOL_A_TS_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy), | |
| 65 | + [ETHTOOL_A_TS_LAYER] = NLA_POLICY_RANGE(NLA_U32, 0, | |
| 66 | + __TIMESTAMPING_COUNT - 1) | |
| 67 | +}; | |
| 68 | + | |
| 69 | +static int ethnl_set_ts_validate(struct ethnl_req_info *req_info, | |
| 70 | + struct genl_info *info) | |
| 71 | +{ | |
| 72 | + struct nlattr **tb = info->attrs; | |
| 73 | + const struct net_device_ops *ops = req_info->dev->netdev_ops; | |
| 74 | + | |
| 75 | + if (!ops->ndo_hwtstamp_set) | |
| 76 | + return -EOPNOTSUPP; | |
| 77 | + | |
| 78 | + if (!tb[ETHTOOL_A_TS_LAYER]) | |
| 79 | + return 0; | |
| 80 | + | |
| 81 | + return 1; | |
| 82 | +} | |
| 83 | + | |
| 84 | +static int ethnl_set_ts(struct ethnl_req_info *req_info, struct genl_info *info) | |
| 85 | +{ | |
| 86 | + struct net_device *dev = req_info->dev; | |
| 87 | + const struct ethtool_ops *ops = dev->ethtool_ops; | |
| 88 | + struct kernel_hwtstamp_config config = {0}; | |
| 89 | + struct nlattr **tb = info->attrs; | |
| 90 | + enum timestamping_layer ts_layer; | |
| 91 | + bool mod = false; | |
| 92 | + int ret; | |
| 93 | + | |
| 94 | + ts_layer = dev->ts_layer; | |
| 95 | + ethnl_update_u32(&ts_layer, tb[ETHTOOL_A_TS_LAYER], &mod); | |
| 96 | + | |
| 97 | + if (!mod) | |
| 98 | + return 0; | |
| 99 | + | |
| 100 | + if (ts_layer == SOFTWARE_TIMESTAMPING) { | |
| 101 | + struct ethtool_ts_info ts_info = {0}; | |
| 102 | + | |
| 103 | + if (!ops->get_ts_info) { | |
| 104 | + NL_SET_ERR_MSG_ATTR(info->extack, | |
| 105 | + tb[ETHTOOL_A_TS_LAYER], | |
| 106 | + "this net device cannot support timestamping"); | |
| 107 | + return -EINVAL; | |
| 108 | + } | |
| 109 | + | |
| 110 | + ops->get_ts_info(dev, &ts_info); | |
| 111 | + if ((ts_info.so_timestamping & | |
| 112 | + SOF_TIMESTAMPING_SOFTWARE_MASK) != | |
| 113 | + SOF_TIMESTAMPING_SOFTWARE_MASK) { | |
| 114 | + NL_SET_ERR_MSG_ATTR(info->extack, | |
| 115 | + tb[ETHTOOL_A_TS_LAYER], | |
| 116 | + "this net device cannot support software timestamping"); | |
| 117 | + return -EINVAL; | |
| 118 | + } | |
| 119 | + } else if (ts_layer == MAC_TIMESTAMPING) { | |
| 120 | + struct ethtool_ts_info ts_info = {0}; | |
| 121 | + | |
| 122 | + if (!ops->get_ts_info) { | |
| 123 | + NL_SET_ERR_MSG_ATTR(info->extack, | |
| 124 | + tb[ETHTOOL_A_TS_LAYER], | |
| 125 | + "this net device cannot support timestamping"); | |
| 126 | + return -EINVAL; | |
| 127 | + } | |
| 128 | + | |
| 129 | + ops->get_ts_info(dev, &ts_info); | |
| 130 | + if ((ts_info.so_timestamping & | |
| 131 | + SOF_TIMESTAMPING_HARDWARE_MASK) != | |
| 132 | + SOF_TIMESTAMPING_HARDWARE_MASK) { | |
| 133 | + NL_SET_ERR_MSG_ATTR(info->extack, | |
| 134 | + tb[ETHTOOL_A_TS_LAYER], | |
| 135 | + "this net device cannot support hardware timestamping"); | |
| 136 | + return -EINVAL; | |
| 137 | + } | |
| 138 | + } else if (ts_layer == PHY_TIMESTAMPING && !phy_has_tsinfo(dev->phydev)) { | |
| 139 | + NL_SET_ERR_MSG_ATTR(info->extack, tb[ETHTOOL_A_TS_LAYER], | |
| 140 | + "this phy device cannot support timestamping"); | |
| 141 | + return -EINVAL; | |
| 142 | + } | |
| 143 | + | |
| 144 | + /* Disable time stamping in the current layer. */ | |
| 145 | + if (netif_device_present(dev) && | |
| 146 | + (dev->ts_layer == PHY_TIMESTAMPING || | |
| 147 | + dev->ts_layer == MAC_TIMESTAMPING)) { | |
| 148 | + ret = dev_set_hwtstamp_phylib(dev, &config, info->extack); | |
| 149 | + if (ret < 0) | |
| 150 | + return ret; | |
| 151 | + } | |
| 152 | + | |
| 153 | + dev->ts_layer = ts_layer; | |
| 154 | + | |
| 155 | + return 1; | |
| 156 | +} | |
| 157 | + | |
| 62 | 158 | const struct ethnl_request_ops ethnl_ts_request_ops = { |
| 63 | 159 | .request_cmd = ETHTOOL_MSG_TS_GET, |
| 64 | 160 | .reply_cmd = ETHTOOL_MSG_TS_GET_REPLY, |
| @@ -69,6 +165,9 @@ const struct ethnl_request_ops ethnl_ts_request_ops = { · 4 unmodified lines | ||
| 69 | 165 | .prepare_data = ts_prepare_data, |
| 70 | 166 | .reply_size = ts_reply_size, |
| 71 | 167 | .fill_reply = ts_fill_reply, |
| 168 | + | |
| 169 | + .set_validate = ethnl_set_ts_validate, | |
| 170 | + .set = ethnl_set_ts, | |
| 72 | 171 | }; |
| 73 | 172 | |
| 74 | 173 | /* TS_LIST_GET */ |