@@ -96,9 +96,46 @@ static int pse_reply_size(const struct ethnl_req_info *req_base,
9696 /* _C33_PSE_EXT_SUBSTATE */
9797 len += nla_total_size (sizeof (u32 ));
9898 }
99+ if (st -> c33_avail_pw_limit > 0 )
100+ /* _C33_AVAIL_PSE_PW_LIMIT */
101+ len += nla_total_size (sizeof (u32 ));
102+ if (st -> c33_pw_limit_nb_ranges > 0 )
103+ /* _C33_PSE_PW_LIMIT_RANGES */
104+ len += st -> c33_pw_limit_nb_ranges *
105+ (nla_total_size (0 ) +
106+ nla_total_size (sizeof (u32 )) * 2 );
107+
99108 return len ;
100109}
101110
111+ static int pse_put_pw_limit_ranges (struct sk_buff * skb ,
112+ const struct pse_control_status * st )
113+ {
114+ const struct ethtool_c33_pse_pw_limit_range * pw_limit_ranges ;
115+ int i ;
116+
117+ pw_limit_ranges = st -> c33_pw_limit_ranges ;
118+ for (i = 0 ; i < st -> c33_pw_limit_nb_ranges ; i ++ ) {
119+ struct nlattr * nest ;
120+
121+ nest = nla_nest_start (skb , ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES );
122+ if (!nest )
123+ return - EMSGSIZE ;
124+
125+ if (nla_put_u32 (skb , ETHTOOL_A_C33_PSE_PW_LIMIT_MIN ,
126+ pw_limit_ranges -> min ) ||
127+ nla_put_u32 (skb , ETHTOOL_A_C33_PSE_PW_LIMIT_MAX ,
128+ pw_limit_ranges -> max )) {
129+ nla_nest_cancel (skb , nest );
130+ return - EMSGSIZE ;
131+ }
132+ nla_nest_end (skb , nest );
133+ pw_limit_ranges ++ ;
134+ }
135+
136+ return 0 ;
137+ }
138+
102139static int pse_fill_reply (struct sk_buff * skb ,
103140 const struct ethnl_req_info * req_base ,
104141 const struct ethnl_reply_data * reply_base )
@@ -147,9 +184,25 @@ static int pse_fill_reply(struct sk_buff *skb,
147184 return - EMSGSIZE ;
148185 }
149186
187+ if (st -> c33_avail_pw_limit > 0 &&
188+ nla_put_u32 (skb , ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT ,
189+ st -> c33_avail_pw_limit ))
190+ return - EMSGSIZE ;
191+
192+ if (st -> c33_pw_limit_nb_ranges > 0 &&
193+ pse_put_pw_limit_ranges (skb , st ))
194+ return - EMSGSIZE ;
195+
150196 return 0 ;
151197}
152198
199+ static void pse_cleanup_data (struct ethnl_reply_data * reply_base )
200+ {
201+ const struct pse_reply_data * data = PSE_REPDATA (reply_base );
202+
203+ kfree (data -> status .c33_pw_limit_ranges );
204+ }
205+
153206/* PSE_SET */
154207
155208const struct nla_policy ethnl_pse_set_policy [ETHTOOL_A_PSE_MAX + 1 ] = {
@@ -160,6 +213,7 @@ const struct nla_policy ethnl_pse_set_policy[ETHTOOL_A_PSE_MAX + 1] = {
160213 [ETHTOOL_A_C33_PSE_ADMIN_CONTROL ] =
161214 NLA_POLICY_RANGE (NLA_U32 , ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED ,
162215 ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED ),
216+ [ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT ] = { .type = NLA_U32 },
163217};
164218
165219static int
@@ -202,19 +256,39 @@ static int
202256ethnl_set_pse (struct ethnl_req_info * req_info , struct genl_info * info )
203257{
204258 struct net_device * dev = req_info -> dev ;
205- struct pse_control_config config = {};
206259 struct nlattr * * tb = info -> attrs ;
207260 struct phy_device * phydev ;
261+ int ret = 0 ;
208262
209263 phydev = dev -> phydev ;
264+
265+ if (tb [ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT ]) {
266+ unsigned int pw_limit ;
267+
268+ pw_limit = nla_get_u32 (tb [ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT ]);
269+ ret = pse_ethtool_set_pw_limit (phydev -> psec , info -> extack ,
270+ pw_limit );
271+ if (ret )
272+ return ret ;
273+ }
274+
210275 /* These values are already validated by the ethnl_pse_set_policy */
211- if (pse_has_podl (phydev -> psec ))
212- config .podl_admin_control = nla_get_u32 (tb [ETHTOOL_A_PODL_PSE_ADMIN_CONTROL ]);
213- if (pse_has_c33 (phydev -> psec ))
214- config .c33_admin_control = nla_get_u32 (tb [ETHTOOL_A_C33_PSE_ADMIN_CONTROL ]);
276+ if (tb [ETHTOOL_A_PODL_PSE_ADMIN_CONTROL ] ||
277+ tb [ETHTOOL_A_C33_PSE_ADMIN_CONTROL ]) {
278+ struct pse_control_config config = {};
279+
280+ if (pse_has_podl (phydev -> psec ))
281+ config .podl_admin_control = nla_get_u32 (tb [ETHTOOL_A_PODL_PSE_ADMIN_CONTROL ]);
282+ if (pse_has_c33 (phydev -> psec ))
283+ config .c33_admin_control = nla_get_u32 (tb [ETHTOOL_A_C33_PSE_ADMIN_CONTROL ]);
284+
285+ ret = pse_ethtool_set_config (phydev -> psec , info -> extack ,
286+ & config );
287+ if (ret )
288+ return ret ;
289+ }
215290
216- /* Return errno directly - PSE has no notification */
217- return pse_ethtool_set_config (phydev -> psec , info -> extack , & config );
291+ return ret ;
218292}
219293
220294const struct ethnl_request_ops ethnl_pse_request_ops = {
@@ -227,6 +301,7 @@ const struct ethnl_request_ops ethnl_pse_request_ops = {
227301 .prepare_data = pse_prepare_data ,
228302 .reply_size = pse_reply_size ,
229303 .fill_reply = pse_fill_reply ,
304+ .cleanup_data = pse_cleanup_data ,
230305
231306 .set_validate = ethnl_set_pse_validate ,
232307 .set = ethnl_set_pse ,
0 commit comments