29
29
* @wq_cmd_cmplt: waitq to keep the process blocked until cmd completion
30
30
* @cmd_lock: Lock to serialize the command interface
31
31
* @resp: command response
32
+ * @link_info: link related information
32
33
* @event_cb: callback for linkchange events
33
34
* @cmd_pend: flag set before new command is started
34
35
* flag cleared after command response is received
@@ -40,6 +41,7 @@ struct lmac {
40
41
wait_queue_head_t wq_cmd_cmplt ;
41
42
struct mutex cmd_lock ;
42
43
u64 resp ;
44
+ struct cgx_link_user_info link_info ;
43
45
struct cgx_event_cb event_cb ;
44
46
bool cmd_pend ;
45
47
struct cgx * cgx ;
@@ -58,6 +60,12 @@ struct cgx {
58
60
59
61
static LIST_HEAD (cgx_list );
60
62
63
+ /* Convert firmware speed encoding to user format(Mbps) */
64
+ static u32 cgx_speed_mbps [CGX_LINK_SPEED_MAX ];
65
+
66
+ /* Convert firmware lmac type encoding to string */
67
+ static char * cgx_lmactype_string [LMAC_MODE_MAX ];
68
+
61
69
/* Supported devices */
62
70
static const struct pci_device_id cgx_id_table [] = {
63
71
{ PCI_DEVICE (PCI_VENDOR_ID_CAVIUM , PCI_DEVID_OCTEONTX2_CGX ) },
@@ -119,6 +127,24 @@ void *cgx_get_pdata(int cgx_id)
119
127
}
120
128
EXPORT_SYMBOL (cgx_get_pdata );
121
129
130
+ /* Ensure the required lock for event queue(where asynchronous events are
131
+ * posted) is acquired before calling this API. Else an asynchronous event(with
132
+ * latest link status) can reach the destination before this function returns
133
+ * and could make the link status appear wrong.
134
+ */
135
+ int cgx_get_link_info (void * cgxd , int lmac_id ,
136
+ struct cgx_link_user_info * linfo )
137
+ {
138
+ struct lmac * lmac = lmac_pdata (lmac_id , cgxd );
139
+
140
+ if (!lmac )
141
+ return - ENODEV ;
142
+
143
+ * linfo = lmac -> link_info ;
144
+ return 0 ;
145
+ }
146
+ EXPORT_SYMBOL (cgx_get_link_info );
147
+
122
148
static u64 mac2u64 (u8 * mac_addr )
123
149
{
124
150
u64 mac = 0 ;
@@ -160,6 +186,14 @@ u64 cgx_lmac_addr_get(u8 cgx_id, u8 lmac_id)
160
186
}
161
187
EXPORT_SYMBOL (cgx_lmac_addr_get );
162
188
189
+ static inline u8 cgx_get_lmac_type (struct cgx * cgx , int lmac_id )
190
+ {
191
+ u64 cfg ;
192
+
193
+ cfg = cgx_read (cgx , lmac_id , CGXX_CMRX_CFG );
194
+ return (cfg >> CGX_LMAC_TYPE_SHIFT ) & CGX_LMAC_TYPE_MASK ;
195
+ }
196
+
163
197
void cgx_lmac_promisc_config (int cgx_id , int lmac_id , bool enable )
164
198
{
165
199
struct cgx * cgx = cgx_get_pdata (cgx_id );
@@ -306,36 +340,79 @@ static inline int cgx_fwi_cmd_generic(u64 req, u64 *resp,
306
340
return err ;
307
341
}
308
342
343
+ static inline void cgx_link_usertable_init (void )
344
+ {
345
+ cgx_speed_mbps [CGX_LINK_NONE ] = 0 ;
346
+ cgx_speed_mbps [CGX_LINK_10M ] = 10 ;
347
+ cgx_speed_mbps [CGX_LINK_100M ] = 100 ;
348
+ cgx_speed_mbps [CGX_LINK_1G ] = 1000 ;
349
+ cgx_speed_mbps [CGX_LINK_2HG ] = 2500 ;
350
+ cgx_speed_mbps [CGX_LINK_5G ] = 5000 ;
351
+ cgx_speed_mbps [CGX_LINK_10G ] = 10000 ;
352
+ cgx_speed_mbps [CGX_LINK_20G ] = 20000 ;
353
+ cgx_speed_mbps [CGX_LINK_25G ] = 25000 ;
354
+ cgx_speed_mbps [CGX_LINK_40G ] = 40000 ;
355
+ cgx_speed_mbps [CGX_LINK_50G ] = 50000 ;
356
+ cgx_speed_mbps [CGX_LINK_100G ] = 100000 ;
357
+
358
+ cgx_lmactype_string [LMAC_MODE_SGMII ] = "SGMII" ;
359
+ cgx_lmactype_string [LMAC_MODE_XAUI ] = "XAUI" ;
360
+ cgx_lmactype_string [LMAC_MODE_RXAUI ] = "RXAUI" ;
361
+ cgx_lmactype_string [LMAC_MODE_10G_R ] = "10G_R" ;
362
+ cgx_lmactype_string [LMAC_MODE_40G_R ] = "40G_R" ;
363
+ cgx_lmactype_string [LMAC_MODE_QSGMII ] = "QSGMII" ;
364
+ cgx_lmactype_string [LMAC_MODE_25G_R ] = "25G_R" ;
365
+ cgx_lmactype_string [LMAC_MODE_50G_R ] = "50G_R" ;
366
+ cgx_lmactype_string [LMAC_MODE_100G_R ] = "100G_R" ;
367
+ cgx_lmactype_string [LMAC_MODE_USXGMII ] = "USXGMII" ;
368
+ }
369
+
370
+ static inline void link_status_user_format (u64 lstat ,
371
+ struct cgx_link_user_info * linfo ,
372
+ struct cgx * cgx , u8 lmac_id )
373
+ {
374
+ char * lmac_string ;
375
+
376
+ linfo -> link_up = FIELD_GET (RESP_LINKSTAT_UP , lstat );
377
+ linfo -> full_duplex = FIELD_GET (RESP_LINKSTAT_FDUPLEX , lstat );
378
+ linfo -> speed = cgx_speed_mbps [FIELD_GET (RESP_LINKSTAT_SPEED , lstat )];
379
+ linfo -> lmac_type_id = cgx_get_lmac_type (cgx , lmac_id );
380
+ lmac_string = cgx_lmactype_string [linfo -> lmac_type_id ];
381
+ strncpy (linfo -> lmac_type , lmac_string , LMACTYPE_STR_LEN - 1 );
382
+ }
383
+
309
384
/* Hardware event handlers */
310
385
static inline void cgx_link_change_handler (u64 lstat ,
311
386
struct lmac * lmac )
312
387
{
388
+ struct cgx_link_user_info * linfo ;
313
389
struct cgx * cgx = lmac -> cgx ;
314
390
struct cgx_link_event event ;
315
391
struct device * dev ;
392
+ int err_type ;
316
393
317
394
dev = & cgx -> pdev -> dev ;
318
395
319
- event .lstat .link_up = FIELD_GET (RESP_LINKSTAT_UP , lstat );
320
- event .lstat .full_duplex = FIELD_GET (RESP_LINKSTAT_FDUPLEX , lstat );
321
- event .lstat .speed = FIELD_GET (RESP_LINKSTAT_SPEED , lstat );
322
- event .lstat .err_type = FIELD_GET (RESP_LINKSTAT_ERRTYPE , lstat );
396
+ link_status_user_format (lstat , & event .link_uinfo , cgx , lmac -> lmac_id );
397
+ err_type = FIELD_GET (RESP_LINKSTAT_ERRTYPE , lstat );
323
398
324
399
event .cgx_id = cgx -> cgx_id ;
325
400
event .lmac_id = lmac -> lmac_id ;
326
401
402
+ /* update the local copy of link status */
403
+ lmac -> link_info = event .link_uinfo ;
404
+ linfo = & lmac -> link_info ;
405
+
327
406
if (!lmac -> event_cb .notify_link_chg ) {
328
407
dev_dbg (dev , "cgx port %d:%d Link change handler null" ,
329
408
cgx -> cgx_id , lmac -> lmac_id );
330
- if (event . lstat . err_type != CGX_ERR_NONE ) {
409
+ if (err_type != CGX_ERR_NONE ) {
331
410
dev_err (dev , "cgx port %d:%d Link error %d\n" ,
332
- cgx -> cgx_id , lmac -> lmac_id ,
333
- event .lstat .err_type );
411
+ cgx -> cgx_id , lmac -> lmac_id , err_type );
334
412
}
335
- dev_info (dev , "cgx port %d:%d Link status %s, speed %x \n" ,
413
+ dev_info (dev , "cgx port %d:%d Link is %s %d Mbps \n" ,
336
414
cgx -> cgx_id , lmac -> lmac_id ,
337
- event .lstat .link_up ? "UP" : "DOWN" ,
338
- event .lstat .speed );
415
+ linfo -> link_up ? "UP" : "DOWN" , linfo -> speed );
339
416
return ;
340
417
}
341
418
@@ -563,6 +640,8 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
563
640
list_add (& cgx -> cgx_list , & cgx_list );
564
641
cgx -> cgx_id = cgx_get_cgx_cnt () - 1 ;
565
642
643
+ cgx_link_usertable_init ();
644
+
566
645
err = cgx_lmac_init (cgx );
567
646
if (err )
568
647
goto err_release_lmac ;
0 commit comments