2929 * @wq_cmd_cmplt: waitq to keep the process blocked until cmd completion
3030 * @cmd_lock: Lock to serialize the command interface
3131 * @resp: command response
32+ * @link_info: link related information
3233 * @event_cb: callback for linkchange events
3334 * @cmd_pend: flag set before new command is started
3435 * flag cleared after command response is received
@@ -40,6 +41,7 @@ struct lmac {
4041 wait_queue_head_t wq_cmd_cmplt ;
4142 struct mutex cmd_lock ;
4243 u64 resp ;
44+ struct cgx_link_user_info link_info ;
4345 struct cgx_event_cb event_cb ;
4446 bool cmd_pend ;
4547 struct cgx * cgx ;
@@ -58,6 +60,12 @@ struct cgx {
5860
5961static LIST_HEAD (cgx_list );
6062
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+
6169/* Supported devices */
6270static const struct pci_device_id cgx_id_table [] = {
6371 { PCI_DEVICE (PCI_VENDOR_ID_CAVIUM , PCI_DEVID_OCTEONTX2_CGX ) },
@@ -119,6 +127,24 @@ void *cgx_get_pdata(int cgx_id)
119127}
120128EXPORT_SYMBOL (cgx_get_pdata );
121129
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+
122148static u64 mac2u64 (u8 * mac_addr )
123149{
124150 u64 mac = 0 ;
@@ -160,6 +186,14 @@ u64 cgx_lmac_addr_get(u8 cgx_id, u8 lmac_id)
160186}
161187EXPORT_SYMBOL (cgx_lmac_addr_get );
162188
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+
163197void cgx_lmac_promisc_config (int cgx_id , int lmac_id , bool enable )
164198{
165199 struct cgx * cgx = cgx_get_pdata (cgx_id );
@@ -306,36 +340,79 @@ static inline int cgx_fwi_cmd_generic(u64 req, u64 *resp,
306340 return err ;
307341}
308342
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+
309384/* Hardware event handlers */
310385static inline void cgx_link_change_handler (u64 lstat ,
311386 struct lmac * lmac )
312387{
388+ struct cgx_link_user_info * linfo ;
313389 struct cgx * cgx = lmac -> cgx ;
314390 struct cgx_link_event event ;
315391 struct device * dev ;
392+ int err_type ;
316393
317394 dev = & cgx -> pdev -> dev ;
318395
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 );
323398
324399 event .cgx_id = cgx -> cgx_id ;
325400 event .lmac_id = lmac -> lmac_id ;
326401
402+ /* update the local copy of link status */
403+ lmac -> link_info = event .link_uinfo ;
404+ linfo = & lmac -> link_info ;
405+
327406 if (!lmac -> event_cb .notify_link_chg ) {
328407 dev_dbg (dev , "cgx port %d:%d Link change handler null" ,
329408 cgx -> cgx_id , lmac -> lmac_id );
330- if (event . lstat . err_type != CGX_ERR_NONE ) {
409+ if (err_type != CGX_ERR_NONE ) {
331410 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 );
334412 }
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" ,
336414 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 );
339416 return ;
340417 }
341418
@@ -563,6 +640,8 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
563640 list_add (& cgx -> cgx_list , & cgx_list );
564641 cgx -> cgx_id = cgx_get_cgx_cnt () - 1 ;
565642
643+ cgx_link_usertable_init ();
644+
566645 err = cgx_lmac_init (cgx );
567646 if (err )
568647 goto err_release_lmac ;
0 commit comments