@@ -149,12 +149,307 @@ static void hinic_get_channels(struct net_device *netdev,
149
149
channels -> combined_count = 0 ;
150
150
}
151
151
152
+ static int hinic_get_rss_hash_opts (struct hinic_dev * nic_dev ,
153
+ struct ethtool_rxnfc * cmd )
154
+ {
155
+ struct hinic_rss_type rss_type = { 0 };
156
+ int err ;
157
+
158
+ cmd -> data = 0 ;
159
+
160
+ if (!(nic_dev -> flags & HINIC_RSS_ENABLE ))
161
+ return 0 ;
162
+
163
+ err = hinic_get_rss_type (nic_dev , nic_dev -> rss_tmpl_idx ,
164
+ & rss_type );
165
+ if (err )
166
+ return err ;
167
+
168
+ cmd -> data = RXH_IP_SRC | RXH_IP_DST ;
169
+ switch (cmd -> flow_type ) {
170
+ case TCP_V4_FLOW :
171
+ if (rss_type .tcp_ipv4 )
172
+ cmd -> data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 ;
173
+ break ;
174
+ case TCP_V6_FLOW :
175
+ if (rss_type .tcp_ipv6 )
176
+ cmd -> data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 ;
177
+ break ;
178
+ case UDP_V4_FLOW :
179
+ if (rss_type .udp_ipv4 )
180
+ cmd -> data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 ;
181
+ break ;
182
+ case UDP_V6_FLOW :
183
+ if (rss_type .udp_ipv6 )
184
+ cmd -> data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 ;
185
+ break ;
186
+ case IPV4_FLOW :
187
+ case IPV6_FLOW :
188
+ break ;
189
+ default :
190
+ cmd -> data = 0 ;
191
+ return - EINVAL ;
192
+ }
193
+
194
+ return 0 ;
195
+ }
196
+
197
+ static int set_l4_rss_hash_ops (struct ethtool_rxnfc * cmd ,
198
+ struct hinic_rss_type * rss_type )
199
+ {
200
+ u8 rss_l4_en = 0 ;
201
+
202
+ switch (cmd -> data & (RXH_L4_B_0_1 | RXH_L4_B_2_3 )) {
203
+ case 0 :
204
+ rss_l4_en = 0 ;
205
+ break ;
206
+ case (RXH_L4_B_0_1 | RXH_L4_B_2_3 ):
207
+ rss_l4_en = 1 ;
208
+ break ;
209
+ default :
210
+ return - EINVAL ;
211
+ }
212
+
213
+ switch (cmd -> flow_type ) {
214
+ case TCP_V4_FLOW :
215
+ rss_type -> tcp_ipv4 = rss_l4_en ;
216
+ break ;
217
+ case TCP_V6_FLOW :
218
+ rss_type -> tcp_ipv6 = rss_l4_en ;
219
+ break ;
220
+ case UDP_V4_FLOW :
221
+ rss_type -> udp_ipv4 = rss_l4_en ;
222
+ break ;
223
+ case UDP_V6_FLOW :
224
+ rss_type -> udp_ipv6 = rss_l4_en ;
225
+ break ;
226
+ default :
227
+ return - EINVAL ;
228
+ }
229
+
230
+ return 0 ;
231
+ }
232
+
233
+ static int hinic_set_rss_hash_opts (struct hinic_dev * nic_dev ,
234
+ struct ethtool_rxnfc * cmd )
235
+ {
236
+ struct hinic_rss_type * rss_type = & nic_dev -> rss_type ;
237
+ int err ;
238
+
239
+ if (!(nic_dev -> flags & HINIC_RSS_ENABLE )) {
240
+ cmd -> data = 0 ;
241
+ return - EOPNOTSUPP ;
242
+ }
243
+
244
+ /* RSS does not support anything other than hashing
245
+ * to queues on src and dst IPs and ports
246
+ */
247
+ if (cmd -> data & ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 |
248
+ RXH_L4_B_2_3 ))
249
+ return - EINVAL ;
250
+
251
+ /* We need at least the IP SRC and DEST fields for hashing */
252
+ if (!(cmd -> data & RXH_IP_SRC ) || !(cmd -> data & RXH_IP_DST ))
253
+ return - EINVAL ;
254
+
255
+ err = hinic_get_rss_type (nic_dev ,
256
+ nic_dev -> rss_tmpl_idx , rss_type );
257
+ if (err )
258
+ return - EFAULT ;
259
+
260
+ switch (cmd -> flow_type ) {
261
+ case TCP_V4_FLOW :
262
+ case TCP_V6_FLOW :
263
+ case UDP_V4_FLOW :
264
+ case UDP_V6_FLOW :
265
+ err = set_l4_rss_hash_ops (cmd , rss_type );
266
+ if (err )
267
+ return err ;
268
+ break ;
269
+ case IPV4_FLOW :
270
+ rss_type -> ipv4 = 1 ;
271
+ break ;
272
+ case IPV6_FLOW :
273
+ rss_type -> ipv6 = 1 ;
274
+ break ;
275
+ default :
276
+ return - EINVAL ;
277
+ }
278
+
279
+ err = hinic_set_rss_type (nic_dev , nic_dev -> rss_tmpl_idx ,
280
+ * rss_type );
281
+ if (err )
282
+ return - EFAULT ;
283
+
284
+ return 0 ;
285
+ }
286
+
287
+ static int __set_rss_rxfh (struct net_device * netdev ,
288
+ const u32 * indir , const u8 * key )
289
+ {
290
+ struct hinic_dev * nic_dev = netdev_priv (netdev );
291
+ int err ;
292
+
293
+ if (indir ) {
294
+ if (!nic_dev -> rss_indir_user ) {
295
+ nic_dev -> rss_indir_user =
296
+ kzalloc (sizeof (u32 ) * HINIC_RSS_INDIR_SIZE ,
297
+ GFP_KERNEL );
298
+ if (!nic_dev -> rss_indir_user )
299
+ return - ENOMEM ;
300
+ }
301
+
302
+ memcpy (nic_dev -> rss_indir_user , indir ,
303
+ sizeof (u32 ) * HINIC_RSS_INDIR_SIZE );
304
+
305
+ err = hinic_rss_set_indir_tbl (nic_dev ,
306
+ nic_dev -> rss_tmpl_idx , indir );
307
+ if (err )
308
+ return - EFAULT ;
309
+ }
310
+
311
+ if (key ) {
312
+ if (!nic_dev -> rss_hkey_user ) {
313
+ nic_dev -> rss_hkey_user =
314
+ kzalloc (HINIC_RSS_KEY_SIZE * 2 , GFP_KERNEL );
315
+
316
+ if (!nic_dev -> rss_hkey_user )
317
+ return - ENOMEM ;
318
+ }
319
+
320
+ memcpy (nic_dev -> rss_hkey_user , key , HINIC_RSS_KEY_SIZE );
321
+
322
+ err = hinic_rss_set_template_tbl (nic_dev ,
323
+ nic_dev -> rss_tmpl_idx , key );
324
+ if (err )
325
+ return - EFAULT ;
326
+ }
327
+
328
+ return 0 ;
329
+ }
330
+
331
+ static int hinic_get_rxnfc (struct net_device * netdev ,
332
+ struct ethtool_rxnfc * cmd , u32 * rule_locs )
333
+ {
334
+ struct hinic_dev * nic_dev = netdev_priv (netdev );
335
+ int err = 0 ;
336
+
337
+ switch (cmd -> cmd ) {
338
+ case ETHTOOL_GRXRINGS :
339
+ cmd -> data = nic_dev -> num_qps ;
340
+ break ;
341
+ case ETHTOOL_GRXFH :
342
+ err = hinic_get_rss_hash_opts (nic_dev , cmd );
343
+ break ;
344
+ default :
345
+ err = - EOPNOTSUPP ;
346
+ break ;
347
+ }
348
+
349
+ return err ;
350
+ }
351
+
352
+ static int hinic_set_rxnfc (struct net_device * netdev , struct ethtool_rxnfc * cmd )
353
+ {
354
+ struct hinic_dev * nic_dev = netdev_priv (netdev );
355
+ int err = 0 ;
356
+
357
+ switch (cmd -> cmd ) {
358
+ case ETHTOOL_SRXFH :
359
+ err = hinic_set_rss_hash_opts (nic_dev , cmd );
360
+ break ;
361
+ default :
362
+ err = - EOPNOTSUPP ;
363
+ break ;
364
+ }
365
+
366
+ return err ;
367
+ }
368
+
369
+ static int hinic_get_rxfh (struct net_device * netdev ,
370
+ u32 * indir , u8 * key , u8 * hfunc )
371
+ {
372
+ struct hinic_dev * nic_dev = netdev_priv (netdev );
373
+ u8 hash_engine_type = 0 ;
374
+ int err = 0 ;
375
+
376
+ if (!(nic_dev -> flags & HINIC_RSS_ENABLE ))
377
+ return - EOPNOTSUPP ;
378
+
379
+ if (hfunc ) {
380
+ err = hinic_rss_get_hash_engine (nic_dev ,
381
+ nic_dev -> rss_tmpl_idx ,
382
+ & hash_engine_type );
383
+ if (err )
384
+ return - EFAULT ;
385
+
386
+ * hfunc = hash_engine_type ? ETH_RSS_HASH_TOP : ETH_RSS_HASH_XOR ;
387
+ }
388
+
389
+ if (indir ) {
390
+ err = hinic_rss_get_indir_tbl (nic_dev ,
391
+ nic_dev -> rss_tmpl_idx , indir );
392
+ if (err )
393
+ return - EFAULT ;
394
+ }
395
+
396
+ if (key )
397
+ err = hinic_rss_get_template_tbl (nic_dev ,
398
+ nic_dev -> rss_tmpl_idx , key );
399
+
400
+ return err ;
401
+ }
402
+
403
+ static int hinic_set_rxfh (struct net_device * netdev , const u32 * indir ,
404
+ const u8 * key , const u8 hfunc )
405
+ {
406
+ struct hinic_dev * nic_dev = netdev_priv (netdev );
407
+ int err = 0 ;
408
+
409
+ if (!(nic_dev -> flags & HINIC_RSS_ENABLE ))
410
+ return - EOPNOTSUPP ;
411
+
412
+ if (hfunc != ETH_RSS_HASH_NO_CHANGE ) {
413
+ if (hfunc != ETH_RSS_HASH_TOP && hfunc != ETH_RSS_HASH_XOR )
414
+ return - EOPNOTSUPP ;
415
+
416
+ nic_dev -> rss_hash_engine = (hfunc == ETH_RSS_HASH_XOR ) ?
417
+ HINIC_RSS_HASH_ENGINE_TYPE_XOR :
418
+ HINIC_RSS_HASH_ENGINE_TYPE_TOEP ;
419
+ err = hinic_rss_set_hash_engine
420
+ (nic_dev , nic_dev -> rss_tmpl_idx ,
421
+ nic_dev -> rss_hash_engine );
422
+ if (err )
423
+ return - EFAULT ;
424
+ }
425
+
426
+ err = __set_rss_rxfh (netdev , indir , key );
427
+
428
+ return err ;
429
+ }
430
+
431
+ static u32 hinic_get_rxfh_key_size (struct net_device * netdev )
432
+ {
433
+ return HINIC_RSS_KEY_SIZE ;
434
+ }
435
+
436
+ static u32 hinic_get_rxfh_indir_size (struct net_device * netdev )
437
+ {
438
+ return HINIC_RSS_INDIR_SIZE ;
439
+ }
440
+
152
441
static const struct ethtool_ops hinic_ethtool_ops = {
153
442
.get_link_ksettings = hinic_get_link_ksettings ,
154
443
.get_drvinfo = hinic_get_drvinfo ,
155
444
.get_link = ethtool_op_get_link ,
156
445
.get_ringparam = hinic_get_ringparam ,
157
446
.get_channels = hinic_get_channels ,
447
+ .get_rxnfc = hinic_get_rxnfc ,
448
+ .set_rxnfc = hinic_set_rxnfc ,
449
+ .get_rxfh_key_size = hinic_get_rxfh_key_size ,
450
+ .get_rxfh_indir_size = hinic_get_rxfh_indir_size ,
451
+ .get_rxfh = hinic_get_rxfh ,
452
+ .set_rxfh = hinic_set_rxfh ,
158
453
};
159
454
160
455
void hinic_set_ethtool_ops (struct net_device * netdev )
0 commit comments