@@ -71,6 +71,7 @@ struct mlxsw_core {
71
71
struct list_head trans_list ;
72
72
spinlock_t trans_list_lock ; /* protects trans_list writes */
73
73
bool use_emad ;
74
+ bool enable_string_tlv ;
74
75
} emad ;
75
76
struct {
76
77
u8 * mapping ; /* lag_id+port_index to local_port mapping */
@@ -323,6 +324,12 @@ static void mlxsw_emad_pack_reg_tlv(char *reg_tlv,
323
324
memcpy (reg_tlv + sizeof (u32 ), payload , reg -> len );
324
325
}
325
326
327
+ static void mlxsw_emad_pack_string_tlv (char * string_tlv )
328
+ {
329
+ mlxsw_emad_string_tlv_type_set (string_tlv , MLXSW_EMAD_TLV_TYPE_STRING );
330
+ mlxsw_emad_string_tlv_len_set (string_tlv , MLXSW_EMAD_STRING_TLV_LEN );
331
+ }
332
+
326
333
static void mlxsw_emad_pack_op_tlv (char * op_tlv ,
327
334
const struct mlxsw_reg_info * reg ,
328
335
enum mlxsw_core_reg_access_type type ,
@@ -364,7 +371,7 @@ static void mlxsw_emad_construct(struct sk_buff *skb,
364
371
const struct mlxsw_reg_info * reg ,
365
372
char * payload ,
366
373
enum mlxsw_core_reg_access_type type ,
367
- u64 tid )
374
+ u64 tid , bool enable_string_tlv )
368
375
{
369
376
char * buf ;
370
377
@@ -374,6 +381,11 @@ static void mlxsw_emad_construct(struct sk_buff *skb,
374
381
buf = skb_push (skb , reg -> len + sizeof (u32 ));
375
382
mlxsw_emad_pack_reg_tlv (buf , reg , payload );
376
383
384
+ if (enable_string_tlv ) {
385
+ buf = skb_push (skb , MLXSW_EMAD_STRING_TLV_LEN * sizeof (u32 ));
386
+ mlxsw_emad_pack_string_tlv (buf );
387
+ }
388
+
377
389
buf = skb_push (skb , MLXSW_EMAD_OP_TLV_LEN * sizeof (u32 ));
378
390
mlxsw_emad_pack_op_tlv (buf , reg , type , tid );
379
391
@@ -418,6 +430,17 @@ static char *mlxsw_emad_op_tlv(const struct sk_buff *skb)
418
430
return ((char * ) (skb -> data + offsets -> op_tlv ));
419
431
}
420
432
433
+ static char * mlxsw_emad_string_tlv (const struct sk_buff * skb )
434
+ {
435
+ struct mlxsw_emad_tlv_offsets * offsets =
436
+ (struct mlxsw_emad_tlv_offsets * ) skb -> cb ;
437
+
438
+ if (!offsets -> string_tlv )
439
+ return NULL ;
440
+
441
+ return ((char * ) (skb -> data + offsets -> string_tlv ));
442
+ }
443
+
421
444
static char * mlxsw_emad_reg_tlv (const struct sk_buff * skb )
422
445
{
423
446
struct mlxsw_emad_tlv_offsets * offsets =
@@ -499,10 +522,31 @@ struct mlxsw_reg_trans {
499
522
const struct mlxsw_reg_info * reg ;
500
523
enum mlxsw_core_reg_access_type type ;
501
524
int err ;
525
+ char * emad_err_string ;
502
526
enum mlxsw_emad_op_tlv_status emad_status ;
503
527
struct rcu_head rcu ;
504
528
};
505
529
530
+ static void mlxsw_emad_process_string_tlv (const struct sk_buff * skb ,
531
+ struct mlxsw_reg_trans * trans )
532
+ {
533
+ char * string_tlv ;
534
+ char * string ;
535
+
536
+ string_tlv = mlxsw_emad_string_tlv (skb );
537
+ if (!string_tlv )
538
+ return ;
539
+
540
+ trans -> emad_err_string = kzalloc (MLXSW_EMAD_STRING_TLV_STRING_LEN ,
541
+ GFP_ATOMIC );
542
+ if (!trans -> emad_err_string )
543
+ return ;
544
+
545
+ string = mlxsw_emad_string_tlv_string_data (string_tlv );
546
+ strlcpy (trans -> emad_err_string , string ,
547
+ MLXSW_EMAD_STRING_TLV_STRING_LEN );
548
+ }
549
+
506
550
#define MLXSW_EMAD_TIMEOUT_DURING_FW_FLASH_MS 3000
507
551
#define MLXSW_EMAD_TIMEOUT_MS 200
508
552
@@ -600,6 +644,8 @@ static void mlxsw_emad_process_response(struct mlxsw_core *mlxsw_core,
600
644
trans -> cb (mlxsw_core ,
601
645
mlxsw_emad_reg_payload (reg_tlv ),
602
646
trans -> reg -> len , trans -> cb_priv );
647
+ } else {
648
+ mlxsw_emad_process_string_tlv (skb , trans );
603
649
}
604
650
mlxsw_emad_trans_finish (trans , err );
605
651
}
@@ -692,14 +738,16 @@ static void mlxsw_emad_fini(struct mlxsw_core *mlxsw_core)
692
738
}
693
739
694
740
static struct sk_buff * mlxsw_emad_alloc (const struct mlxsw_core * mlxsw_core ,
695
- u16 reg_len )
741
+ u16 reg_len , bool enable_string_tlv )
696
742
{
697
743
struct sk_buff * skb ;
698
744
u16 emad_len ;
699
745
700
746
emad_len = (reg_len + sizeof (u32 ) + MLXSW_EMAD_ETH_HDR_LEN +
701
747
(MLXSW_EMAD_OP_TLV_LEN + MLXSW_EMAD_END_TLV_LEN ) *
702
748
sizeof (u32 ) + mlxsw_core -> driver -> txhdr_len );
749
+ if (enable_string_tlv )
750
+ emad_len += MLXSW_EMAD_STRING_TLV_LEN * sizeof (u32 );
703
751
if (emad_len > MLXSW_EMAD_MAX_FRAME_LEN )
704
752
return NULL ;
705
753
@@ -721,14 +769,20 @@ static int mlxsw_emad_reg_access(struct mlxsw_core *mlxsw_core,
721
769
mlxsw_reg_trans_cb_t * cb ,
722
770
unsigned long cb_priv , u64 tid )
723
771
{
772
+ bool enable_string_tlv ;
724
773
struct sk_buff * skb ;
725
774
int err ;
726
775
727
776
dev_dbg (mlxsw_core -> bus_info -> dev , "EMAD reg access (tid=%llx,reg_id=%x(%s),type=%s)\n" ,
728
777
tid , reg -> id , mlxsw_reg_id_str (reg -> id ),
729
778
mlxsw_core_reg_access_type_str (type ));
730
779
731
- skb = mlxsw_emad_alloc (mlxsw_core , reg -> len );
780
+ /* Since this can be changed during emad_reg_access, read it once and
781
+ * use the value all the way.
782
+ */
783
+ enable_string_tlv = mlxsw_core -> emad .enable_string_tlv ;
784
+
785
+ skb = mlxsw_emad_alloc (mlxsw_core , reg -> len , enable_string_tlv );
732
786
if (!skb )
733
787
return - ENOMEM ;
734
788
@@ -745,7 +799,8 @@ static int mlxsw_emad_reg_access(struct mlxsw_core *mlxsw_core,
745
799
trans -> reg = reg ;
746
800
trans -> type = type ;
747
801
748
- mlxsw_emad_construct (skb , reg , payload , type , trans -> tid );
802
+ mlxsw_emad_construct (skb , reg , payload , type , trans -> tid ,
803
+ enable_string_tlv );
749
804
mlxsw_core -> driver -> txhdr_construct (skb , & trans -> tx_info );
750
805
751
806
spin_lock_bh (& mlxsw_core -> emad .trans_list_lock );
@@ -1707,12 +1762,15 @@ static int mlxsw_reg_trans_wait(struct mlxsw_reg_trans *trans)
1707
1762
mlxsw_emad_op_tlv_status_str (trans -> emad_status ));
1708
1763
1709
1764
snprintf (err_string , MLXSW_REG_TRANS_ERR_STRING_SIZE ,
1710
- "(tid=%llx,reg_id=%x(%s)) %s\n" , trans -> tid ,
1765
+ "(tid=%llx,reg_id=%x(%s)) %s (%s) \n" , trans -> tid ,
1711
1766
trans -> reg -> id , mlxsw_reg_id_str (trans -> reg -> id ),
1712
- mlxsw_emad_op_tlv_status_str (trans -> emad_status ));
1767
+ mlxsw_emad_op_tlv_status_str (trans -> emad_status ),
1768
+ trans -> emad_err_string ? trans -> emad_err_string : "" );
1713
1769
1714
1770
trace_devlink_hwerr (priv_to_devlink (mlxsw_core ),
1715
1771
trans -> emad_status , err_string );
1772
+
1773
+ kfree (trans -> emad_err_string );
1716
1774
}
1717
1775
1718
1776
list_del (& trans -> bulk_list );
@@ -2283,6 +2341,12 @@ u32 mlxsw_core_read_frc_l(struct mlxsw_core *mlxsw_core)
2283
2341
}
2284
2342
EXPORT_SYMBOL (mlxsw_core_read_frc_l );
2285
2343
2344
+ void mlxsw_core_emad_string_tlv_enable (struct mlxsw_core * mlxsw_core )
2345
+ {
2346
+ mlxsw_core -> emad .enable_string_tlv = true;
2347
+ }
2348
+ EXPORT_SYMBOL (mlxsw_core_emad_string_tlv_enable );
2349
+
2286
2350
static int __init mlxsw_core_module_init (void )
2287
2351
{
2288
2352
int err ;
0 commit comments