3131#define MB_BASE_OFF 0x28
3232
3333#define PHY_BASE_OFF 0x2000
34+ #define PHY_RX_LOCKED_OFF 0x480
35+ #define PHY_RX_LOCKED_DATA (BIT(0) | BIT(1))
36+
3437#define PHY_RX_SER_LOOP_BACK 0x4e1
3538#define PHY_MAX_OFF 0x541
3639
4548#define ILL_100G_RX_STATS_CLR 0x945
4649
4750#define ILL_100G_PHY_BASE_OFF 0x300
48- #define ILL_100G_PHY_MAX_OFF 0x3ff
51+ #define ILL_100G_RX_PCS_ALN_OFF 0x326
52+ #define ILL_100G_RX_RCS_ALIGNED BIT(0)
53+
4954#define ILL_100G_LPBK_OFF 0x313
5055#define ILL_100G_LPBK_EN_VAL 0xffff
5156
57+ #define ILL_100G_PHY_MAX_OFF 0x3ff
58+
59+ #define ILL_100G_TX_FEC_OFF 0xc00
60+ #define ILL_100G_TX_FEC_MAX_OFF 0xc07
61+
62+ #define ILL_100G_RX_FEC_OFF 0xd00
63+ #define ILL_100G_RX_FEC_ST 0xd06
64+ #define ILL_100G_RX_FEC_ST_ALN BIT(4)
65+ #define ILL_100G_RX_FEC_MAX_OFF 0xd08
66+
5267#define STATS_CLR_INT_US 1
5368#define STATS_CLR_INT_TIMEOUT_US 1000
5469
5570struct s10hssi_drvdata {
5671 struct net_device * netdev ;
72+ struct timer_list poll_timer ;
73+ struct work_struct poll_workq ;
5774};
5875
5976struct s10hssi_ops_params {
@@ -63,14 +80,47 @@ struct s10hssi_ops_params {
6380 u32 rx_clr_off ;
6481 u32 lpbk_off ;
6582 u32 lpbk_en_val ;
83+ u32 link_off ;
84+ u32 link_mask ;
6685};
6786
6887struct s10hssi_netdata {
6988 struct dfl_device * dfl_dev ;
7089 struct regmap * regmap ;
71- const struct s10hssi_ops_params * ops_params ;
90+ struct s10hssi_ops_params * ops_params ;
91+ u32 link_status ;
7292};
7393
94+ static void poll_work (struct work_struct * arg )
95+ {
96+ struct s10hssi_netdata * npriv ;
97+ struct s10hssi_drvdata * priv ;
98+ u32 link_status = 0 ;
99+
100+ priv = container_of (arg , struct s10hssi_drvdata , poll_workq );
101+ npriv = netdev_priv (priv -> netdev );
102+
103+ regmap_read (npriv -> regmap , npriv -> ops_params -> link_off , & link_status );
104+ link_status &= npriv -> ops_params -> link_mask ;
105+ if (link_status != npriv -> link_status ) {
106+ npriv -> link_status = link_status ;
107+ dev_dbg (& priv -> netdev -> dev , "link state: %u\n" , link_status );
108+
109+ if (link_status == npriv -> ops_params -> link_mask )
110+ netif_carrier_on (priv -> netdev );
111+ else
112+ netif_carrier_off (priv -> netdev );
113+ }
114+ }
115+
116+ static void poll_timerf (struct timer_list * timer_arg )
117+ {
118+ struct s10hssi_drvdata * priv = from_timer (priv , timer_arg , poll_timer );
119+
120+ schedule_work (& priv -> poll_workq );
121+ mod_timer (& priv -> poll_timer , jiffies + msecs_to_jiffies (1000 ));
122+ }
123+
74124static int netdev_change_mtu (struct net_device * netdev , int new_mtu )
75125{
76126 netdev -> mtu = new_mtu ;
@@ -296,6 +346,8 @@ static const struct s10hssi_ops_params s10hssi_params = {
296346 .rx_clr_off = ILL_10G_RX_STATS_CLR ,
297347 .lpbk_off = PHY_BASE_OFF + PHY_RX_SER_LOOP_BACK ,
298348 .lpbk_en_val = 1 ,
349+ .link_off = PHY_BASE_OFF + PHY_RX_LOCKED_OFF ,
350+ .link_mask = PHY_RX_LOCKED_DATA ,
299351};
300352
301353static const struct regmap_range regmap_range_10g [] = {
@@ -384,6 +436,8 @@ static const struct s10hssi_ops_params intel_ll_100g_params = {
384436static const struct regmap_range regmap_range_100g [] = {
385437 regmap_reg_range (ILL_100G_PHY_BASE_OFF , ILL_100G_PHY_MAX_OFF ),
386438 regmap_reg_range (ILL_100G_BASE_OFF , ILL_100G_MAX_OFF ),
439+ regmap_reg_range (ILL_100G_TX_FEC_OFF , ILL_100G_TX_FEC_MAX_OFF ),
440+ regmap_reg_range (ILL_100G_RX_FEC_OFF , ILL_100G_RX_FEC_MAX_OFF ),
387441};
388442
389443static const struct regmap_access_table access_table_100g = {
@@ -448,16 +502,30 @@ static int s10hssi_mac_probe(struct dfl_device *dfl_dev)
448502
449503 if (pcs_speed == CAP_RATE_10G ) {
450504 dev_info (dev , "%s found 10G\n" , __func__ );
451- npriv -> ops_params = & s10hssi_params ;
505+ npriv -> ops_params = ( struct s10hssi_ops_params * ) & s10hssi_params ;
452506 cfg .wr_table = & access_table_10g ;
453507 cfg .rd_table = & access_table_10g ;
454508 cfg .max_register = PHY_BASE_OFF + PHY_MAX_OFF ;
455509 } else if (pcs_speed == CAP_RATE_100G ) {
456510 dev_info (dev , "%s found 100G\n" , __func__ );
457- npriv -> ops_params = & intel_ll_100g_params ;
511+ npriv -> ops_params = devm_kmalloc (dev , sizeof (* npriv -> ops_params ), GFP_KERNEL );
512+ if (!npriv -> ops_params )
513+ return - ENOMEM ;
514+
515+ * npriv -> ops_params = intel_ll_100g_params ;
516+ if (FIELD_GET (CAP_CONTAINS_FEC , val )) {
517+ dev_info (dev , "%s contains FEC\n" , __func__ );
518+ npriv -> ops_params -> link_off = ILL_100G_RX_FEC_ST ;
519+ npriv -> ops_params -> link_mask = ILL_100G_RX_FEC_ST_ALN ;
520+ } else {
521+ dev_info (dev , "%s no FEC\n" , __func__ );
522+ npriv -> ops_params -> link_off = ILL_100G_RX_PCS_ALN_OFF ;
523+ npriv -> ops_params -> link_mask = ILL_100G_RX_RCS_ALIGNED ;
524+ }
525+
458526 cfg .wr_table = & access_table_100g ;
459527 cfg .rd_table = & access_table_100g ;
460- cfg .max_register = ILL_100G_MAX_OFF ;
528+ cfg .max_register = ILL_100G_RX_FEC_MAX_OFF ;
461529 } else {
462530 dev_err (dev , "%s unsupported pcs data rate 0x%llx\n" ,
463531 __func__ , pcs_speed );
@@ -490,6 +558,13 @@ static int s10hssi_mac_probe(struct dfl_device *dfl_dev)
490558 dev_err (& dfl_dev -> dev , "failed to register %s: %d" ,
491559 priv -> netdev -> name , ret );
492560
561+ dev_info (& dfl_dev -> dev , "setting carrier off\n" );
562+ netif_carrier_off (priv -> netdev );
563+
564+ INIT_WORK (& priv -> poll_workq , poll_work );
565+ timer_setup (& priv -> poll_timer , poll_timerf , 0 );
566+ mod_timer (& priv -> poll_timer , jiffies + msecs_to_jiffies (1000 ));
567+
493568 return ret ;
494569}
495570
@@ -498,6 +573,8 @@ static void s10hssi_mac_remove(struct dfl_device *dfl_dev)
498573 struct s10hssi_drvdata * priv = dev_get_drvdata (& dfl_dev -> dev );
499574
500575 unregister_netdev (priv -> netdev );
576+
577+ del_timer_sync (& priv -> poll_timer );
501578}
502579
503580#define FME_FEATURE_ID_LL_10G_MAC 0xf
0 commit comments