Skip to content

Commit 506c0b3

Browse files
matthew-gerlachRuss Weight
authored andcommitted
net: ethernet: intel: add polling of link status
Add polling for the link statatus in the phy and update the netdev object accordingly. Signed-off-by: Matthew Gerlach <matthew.gerlach@linux.intel.com> Based-on: Martin Hundebøll <mhu@silicom.dk>
1 parent 261da50 commit 506c0b3

1 file changed

Lines changed: 82 additions & 5 deletions

File tree

drivers/net/ethernet/intel/s10hssi.c

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
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

@@ -45,15 +48,29 @@
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

5570
struct s10hssi_drvdata {
5671
struct net_device *netdev;
72+
struct timer_list poll_timer;
73+
struct work_struct poll_workq;
5774
};
5875

5976
struct 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

6887
struct 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+
74124
static 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

301353
static const struct regmap_range regmap_range_10g[] = {
@@ -384,6 +436,8 @@ static const struct s10hssi_ops_params intel_ll_100g_params = {
384436
static 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

389443
static 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

Comments
 (0)