Skip to content

Commit 72e9df2

Browse files
eth: qsfp: introduce polling mode qsfp presence detection
1 parent f16857d commit 72e9df2

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// SPDX-License-Identifier: GPL
2+
3+
/* Intel(R) QSFP Memory controller poller api
4+
*
5+
* Copyright (C) 2023 Intel Corporation. All rights reserved.
6+
*
7+
* Contributors:
8+
* Preetam Narayan
9+
*/
10+
11+
#include "intel_fpga_eth_main.h"
12+
#include <linux/platform_device.h>
13+
#include <linux/of_platform.h>
14+
15+
16+
static struct platform_device *
17+
qsfp_lane_mapper(intel_fpga_xtile_eth_private *priv) {
18+
19+
struct platform_device *pdev;
20+
struct platform_device *pdev_qsfp;
21+
struct device_node *dev_qsfp;
22+
23+
pdev = container_of(priv->device, struct platform_device, dev);
24+
25+
/* QSFP has four lanes, each lane is considered one port and
26+
* corresponds to linux network interface
27+
*/
28+
if (priv->qsfp_lane >= 0 && priv->qsfp_lane <=3)
29+
dev_qsfp = of_parse_phandle(pdev->dev.of_node, "qsfp0", 0);
30+
else
31+
dev_qsfp = of_parse_phandle(pdev->dev.of_node, "qsfp1", 0);
32+
33+
pdev_qsfp = of_find_device_by_node(dev_qsfp);
34+
35+
return pdev_qsfp;
36+
}
37+
38+
static void
39+
qsfp_addr_space_mapper(intel_fpga_xtile_eth_private *priv,
40+
struct platform_device *pdev_qsfp) {
41+
42+
struct resource *qsfp_ctrl_res;
43+
44+
qsfp_ctrl_res =
45+
platform_get_resource_byname(pdev_qsfp,
46+
IORESOURCE_MEM,
47+
"qsfp-mem-ctrl");
48+
49+
priv->qsfp_reg = devm_ioremap(&pdev_qsfp->dev,
50+
qsfp_ctrl_res->start,
51+
resource_size(qsfp_ctrl_res));
52+
}
53+
54+
void qsfp_link_status(struct work_struct *work) {
55+
56+
bool is_link_stable;
57+
struct delayed_work *dwork;
58+
bool is_next_iter_fine = false;
59+
intel_fpga_xtile_eth_private *priv;
60+
static bool is_prev_iter_fine = true;
61+
62+
dwork = to_delayed_work(work);
63+
priv = container_of(dwork, intel_fpga_xtile_eth_private, dwork);
64+
65+
priv->cable_unplugged =
66+
priv->qsfp_reg->status_reg.qsfp_stat_bits.mod_presence;
67+
68+
is_link_stable =
69+
hssi_ethport_is_stable(priv->pdev_hssi, priv->chan, false);
70+
71+
is_next_iter_fine =
72+
(is_link_stable == true) && (priv->cable_unplugged == false);
73+
74+
/* If the link is not stable to perform the networking function then
75+
* necessary defence need to be taken
76+
*/
77+
if (is_prev_iter_fine == is_next_iter_fine)
78+
/* This is for the 1st iteration where it is assumed link is up
79+
* because on ndo_open system has been prior initalized
80+
*/
81+
goto reshed;
82+
83+
else if (is_next_iter_fine == true) {
84+
if ( priv->qsfp_ops->qsfp_link_up )
85+
priv->qsfp_ops->qsfp_link_up(priv);
86+
}
87+
else {
88+
if ( priv->qsfp_ops->qsfp_link_down )
89+
priv->qsfp_ops->qsfp_link_down(priv);
90+
}
91+
92+
is_prev_iter_fine = is_next_iter_fine;
93+
94+
reshed:
95+
schedule_delayed_work(&priv->dwork, msecs_to_jiffies(QSFP_POLL_TIMEOUT));
96+
}
97+
98+
99+
static void
100+
init_worker_thread(intel_fpga_xtile_eth_private *priv) {
101+
102+
INIT_DELAYED_WORK(&priv->dwork, qsfp_link_status);
103+
qsfp_link_status(&priv->dwork.work);
104+
}
105+
106+
void init_qsfp_ctrl_space(intel_fpga_xtile_eth_private *priv) {
107+
108+
struct platform_device *pdev_qsfp;
109+
110+
pdev_qsfp = qsfp_lane_mapper(priv);
111+
qsfp_addr_space_mapper(priv, pdev_qsfp);
112+
113+
init_worker_thread(priv);
114+
}
115+
116+
static void
117+
release_worker_thread(intel_fpga_xtile_eth_private *priv) {
118+
cancel_delayed_work_sync(&priv->dwork);
119+
}
120+
121+
void deinit_qsfp_ctrl_space(intel_fpga_xtile_eth_private *priv) {
122+
release_worker_thread(priv);
123+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
#ifndef __INTEL_FPGA_ETH_QSFP_H__
3+
#define __INTEL_FPGA_ETH_QSFP_H__
4+
5+
#include "intel_fpga_eth_hssi_itf.h"
6+
7+
#define QSFP_POLL_TIMEOUT 1
8+
9+
struct qsfp_reg_space {
10+
11+
u8 ns_area0[27];
12+
union status_reg {
13+
struct {
14+
u32 mod_presence:1;
15+
u32 qsfp_intr:1;
16+
u32 reserved:30;
17+
u32 reserved2;
18+
}qsfp_stat_bits;
19+
u64 qsfp_stat;
20+
}status_reg;
21+
};
22+
23+
#endif

0 commit comments

Comments
 (0)