@@ -59,6 +59,102 @@ static int ts_fill_reply(struct sk_buff *skb,
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 = {
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 */
0 commit comments