blob: 8853324ec41f95181e6e3d844b4a1991c4cea72a [file] [log] [blame]
developer2cdaeb12022-10-04 20:25:05 +08001Index: linux-5.4.203/drivers/net/dsa/Makefile
2===================================================================
3--- linux-5.4.203.orig/drivers/net/dsa/Makefile
4+++ linux-5.4.203/drivers/net/dsa/Makefile
5@@ -7,7 +7,7 @@ obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdi
6 endif
7 obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
8 obj-$(CONFIG_NET_DSA_MT7530) += mt7530-dsa.o
9-mt7530-dsa-objs := mt7530.o mt7531_phy.o
10+mt7530-dsa-objs := mt7530.o mt7530_nl.o mt7531_phy.o
11 obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
12 obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o
13 obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
14Index: linux-5.4.203/drivers/net/dsa/mt7530.c
15===================================================================
16--- linux-5.4.203.orig/drivers/net/dsa/mt7530.c
17+++ linux-5.4.203/drivers/net/dsa/mt7530.c
18@@ -21,6 +21,7 @@
19 #include <net/dsa.h>
20
21 #include "mt7530.h"
22+#include "mt7530_nl.h"
23
24 /* String, offset, and register size in bytes if different from 4 bytes */
25 static const struct mt7530_mib_desc mt7530_mib[] = {
26@@ -222,7 +223,7 @@ mt7530_mii_read(struct mt7530_priv *priv
27 return (hi << 16) | (lo & 0xffff);
28 }
29
30-static void
31+void
32 mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val)
33 {
34 struct mii_bus *bus = priv->bus;
35@@ -255,7 +256,7 @@ _mt7530_read(struct mt7530_dummy_poll *p
36 return val;
37 }
38
39-static u32
40+u32
41 mt7530_read(struct mt7530_priv *priv, u32 reg)
42 {
43 struct mt7530_dummy_poll p;
44@@ -614,7 +615,7 @@ static int mt7530_phy_write(struct dsa_s
45 return mdiobus_write_nested(priv->bus, port, regnum, val);
46 }
47
48-static int
49+int
50 mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
51 int regnum)
52 {
53@@ -663,7 +664,7 @@ out:
54 return ret;
55 }
56
57-static int
58+int
59 mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
60 int regnum, u32 data)
61 {
62@@ -711,7 +712,7 @@ out:
63 return ret;
64 }
65
66-static int
67+int
68 mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)
69 {
70 struct mii_bus *bus = priv->bus;
71@@ -749,7 +750,7 @@ out:
72 return ret;
73 }
74
75-static int
76+int
77 mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
78 u16 data)
79 {
80@@ -2690,6 +2691,7 @@ mt7530_probe(struct mdio_device *mdiodev
81 {
82 struct mt7530_priv *priv;
83 struct device_node *dn;
84+ int ret;
85
86 dn = mdiodev->dev.of_node;
87
88@@ -2765,7 +2767,13 @@ mt7530_probe(struct mdio_device *mdiodev
89 mutex_init(&priv->reg_mutex);
90 dev_set_drvdata(&mdiodev->dev, priv);
91
92- return dsa_register_switch(priv->ds);
93+ ret = dsa_register_switch(priv->ds);
94+ if (ret)
95+ return ret;
96+
97+ mt7530_nl_init(&priv);
98+
99+ return 0;
100 }
101
102 static void
103@@ -2786,6 +2794,8 @@ mt7530_remove(struct mdio_device *mdiode
104
105 dsa_unregister_switch(priv->ds);
106 mutex_destroy(&priv->reg_mutex);
107+
108+ mt7530_nl_exit();
109 }
110
111 static struct mdio_driver mt7530_mdio_driver = {
112Index: linux-5.4.203/drivers/net/dsa/mt7530.h
113===================================================================
114--- linux-5.4.203.orig/drivers/net/dsa/mt7530.h
115+++ linux-5.4.203/drivers/net/dsa/mt7530.h
116@@ -783,4 +783,12 @@ static inline void INIT_MT7530_DUMMY_POL
117 }
118
119 int mt7531_phy_setup(struct dsa_switch *ds);
120+u32 mt7530_read(struct mt7530_priv *priv, u32 reg);
121+void mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val);
122+int mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad, int regnum);
123+int mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad, int regnum, u32 data);
124+int mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum);
125+int mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum, u16 data);
126+
127+
128 #endif /* __MT7530_H */
129Index: linux-5.4.203/drivers/net/dsa/mt7530_nl.c
130===================================================================
131--- /dev/null
132+++ linux-5.4.203/drivers/net/dsa/mt7530_nl.c
133@@ -0,0 +1,311 @@
134+// SPDX-License-Identifier: GPL-2.0
135+/*
136+ * Copyright (c) 2018 MediaTek Inc.
137+ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
138+ */
139+
140+#include <linux/types.h>
141+#include <linux/kernel.h>
142+#include <linux/module.h>
143+#include <linux/init.h>
144+#include <net/genetlink.h>
145+#include <linux/of_mdio.h>
146+#include <linux/phylink.h>
147+#include <net/dsa.h>
148+
149+#include "mt7530.h"
150+#include "mt7530_nl.h"
151+
152+struct mt7530_nl_cmd_item {
153+ enum mt7530_cmd cmd;
154+ bool require_dev;
155+ int (*process)(struct genl_info *info);
156+ u32 nr_required_attrs;
157+ const enum mt7530_attr *required_attrs;
158+};
159+
160+struct mt7530_priv *sw_priv;
161+
162+static DEFINE_MUTEX(mt7530_devs_lock);
163+
164+void mt7530_put(void)
165+{
166+ mutex_unlock(&mt7530_devs_lock);
167+}
168+
169+void mt7530_lock(void)
170+{
171+ mutex_lock(&mt7530_devs_lock);
172+}
173+
174+static int mt7530_nl_response(struct sk_buff *skb, struct genl_info *info);
175+
176+static const struct nla_policy mt7530_nl_cmd_policy[] = {
177+ [MT7530_ATTR_TYPE_MESG] = { .type = NLA_STRING },
178+ [MT7530_ATTR_TYPE_PHY] = { .type = NLA_S32 },
179+ [MT7530_ATTR_TYPE_REG] = { .type = NLA_S32 },
180+ [MT7530_ATTR_TYPE_VAL] = { .type = NLA_S32 },
181+ [MT7530_ATTR_TYPE_DEV_NAME] = { .type = NLA_S32 },
182+ [MT7530_ATTR_TYPE_DEV_ID] = { .type = NLA_S32 },
183+ [MT7530_ATTR_TYPE_DEVAD] = { .type = NLA_S32 },
184+};
185+
186+static const struct genl_ops mt7530_nl_ops[] = {
187+ {
188+ .cmd = MT7530_CMD_REQUEST,
189+ .doit = mt7530_nl_response,
190+ .flags = GENL_ADMIN_PERM,
191+ }, {
192+ .cmd = MT7530_CMD_READ,
193+ .doit = mt7530_nl_response,
194+ .flags = GENL_ADMIN_PERM,
195+ }, {
196+ .cmd = MT7530_CMD_WRITE,
197+ .doit = mt7530_nl_response,
198+ .flags = GENL_ADMIN_PERM,
199+ },
200+};
201+
202+static struct genl_family mt7530_nl_family = {
203+ .name = MT7530_DSA_GENL_NAME,
204+ .version = MT7530_GENL_VERSION,
205+ .maxattr = MT7530_NR_ATTR_TYPE,
206+ .ops = mt7530_nl_ops,
207+ .n_ops = ARRAY_SIZE(mt7530_nl_ops),
208+ .policy = mt7530_nl_cmd_policy,
209+};
210+
211+static int mt7530_nl_prepare_reply(struct genl_info *info, u8 cmd,
212+ struct sk_buff **skbp)
213+{
214+ struct sk_buff *msg;
215+ void *reply;
216+
217+ if (!info)
218+ return -EINVAL;
219+
220+ msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
221+ if (!msg)
222+ return -ENOMEM;
223+
224+ /* Construct send-back message header */
225+ reply = genlmsg_put(msg, info->snd_portid, info->snd_seq,
226+ &mt7530_nl_family, 0, cmd);
227+ if (!reply) {
228+ nlmsg_free(msg);
229+ return -EINVAL;
230+ }
231+
232+ *skbp = msg;
233+ return 0;
234+}
235+
236+static int mt7530_nl_send_reply(struct sk_buff *skb, struct genl_info *info)
237+{
238+ struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));
239+ void *reply = genlmsg_data(genlhdr);
240+
241+ /* Finalize a generic netlink message (update message header) */
242+ genlmsg_end(skb, reply);
243+
244+ /* reply to a request */
245+ return genlmsg_reply(skb, info);
246+}
247+
248+static s32 mt7530_nl_get_s32(struct genl_info *info, enum mt7530_attr attr,
249+ s32 defval)
250+{
251+ struct nlattr *na;
252+
253+ na = info->attrs[attr];
254+ if (na)
255+ return nla_get_s32(na);
256+
257+ return defval;
258+}
259+
260+static int mt7530_nl_get_u32(struct genl_info *info, enum mt7530_attr attr,
261+ u32 *val)
262+{
263+ struct nlattr *na;
264+
265+ na = info->attrs[attr];
266+ if (na) {
267+ *val = nla_get_u32(na);
268+ return 0;
269+ }
270+
271+ return -1;
272+}
273+
274+static int mt7530_nl_reply_read(struct genl_info *info)
275+{
276+ struct sk_buff *rep_skb = NULL;
277+ s32 phy, devad, reg;
278+ int value;
279+ int ret = 0;
280+
281+ phy = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_PHY, -1);
282+ devad = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_DEVAD, -1);
283+ reg = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_REG, -1);
284+
285+ if (reg < 0)
286+ goto err;
287+
288+ ret = mt7530_nl_prepare_reply(info, MT7530_CMD_READ, &rep_skb);
289+ if (ret < 0)
290+ goto err;
291+
292+ if (phy >= 0) {
293+ if (devad < 0)
294+ value = mt7531_ind_c22_phy_read(sw_priv, phy, reg);
295+ else
296+ value = mt7531_ind_c45_phy_read(sw_priv, phy, devad, reg);
297+ } else
298+ value = mt7530_read(sw_priv, reg);
299+
300+ ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_REG, reg);
301+ if (ret < 0)
302+ goto err;
303+
304+ ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_VAL, value);
305+ if (ret < 0)
306+ goto err;
307+
308+ return mt7530_nl_send_reply(rep_skb, info);
309+
310+err:
311+ if (rep_skb)
312+ nlmsg_free(rep_skb);
313+
314+ return ret;
315+}
316+
317+static int mt7530_nl_reply_write(struct genl_info *info)
318+{
319+ struct sk_buff *rep_skb = NULL;
320+ s32 phy, devad, reg;
321+ u32 value;
322+ int ret = 0;
323+
324+ phy = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_PHY, -1);
325+ devad = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_DEVAD, -1);
326+ reg = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_REG, -1);
327+
328+ if (mt7530_nl_get_u32(info, MT7530_ATTR_TYPE_VAL, &value))
329+ goto err;
330+
331+ if (reg < 0)
332+ goto err;
333+
334+ ret = mt7530_nl_prepare_reply(info, MT7530_CMD_WRITE, &rep_skb);
335+ if (ret < 0)
336+ goto err;
337+
338+ if (phy >= 0) {
339+ if (devad < 0)
340+ mt7531_ind_c22_phy_write(sw_priv, phy, reg, value);
341+ else
342+ mt7531_ind_c45_phy_write(sw_priv, phy, devad, reg, value);
343+ } else
344+ mt7530_write(sw_priv, reg, value);
345+
346+ ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_REG, reg);
347+ if (ret < 0)
348+ goto err;
349+
350+ ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_VAL, value);
351+ if (ret < 0)
352+ goto err;
353+
354+ return mt7530_nl_send_reply(rep_skb, info);
355+
356+err:
357+ if (rep_skb)
358+ nlmsg_free(rep_skb);
359+
360+ return ret;
361+}
362+
363+static const enum mt7530_attr mt7530_nl_cmd_read_attrs[] = {
364+ MT7530_ATTR_TYPE_REG
365+};
366+
367+static const enum mt7530_attr mt7530_nl_cmd_write_attrs[] = {
368+ MT7530_ATTR_TYPE_REG,
369+ MT7530_ATTR_TYPE_VAL
370+};
371+
372+static const struct mt7530_nl_cmd_item mt7530_nl_cmds[] = {
373+ {
374+ .cmd = MT7530_CMD_READ,
375+ .require_dev = true,
376+ .process = mt7530_nl_reply_read,
377+ .required_attrs = mt7530_nl_cmd_read_attrs,
378+ .nr_required_attrs = ARRAY_SIZE(mt7530_nl_cmd_read_attrs),
379+ }, {
380+ .cmd = MT7530_CMD_WRITE,
381+ .require_dev = true,
382+ .process = mt7530_nl_reply_write,
383+ .required_attrs = mt7530_nl_cmd_write_attrs,
384+ .nr_required_attrs = ARRAY_SIZE(mt7530_nl_cmd_write_attrs),
385+ }
386+};
387+
388+static int mt7530_nl_response(struct sk_buff *skb, struct genl_info *info)
389+{
390+ struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
391+ const struct mt7530_nl_cmd_item *cmditem = NULL;
392+ u32 sat_req_attrs = 0;
393+ int i, ret;
394+
395+ for (i = 0; i < ARRAY_SIZE(mt7530_nl_cmds); i++) {
396+ if (hdr->cmd == mt7530_nl_cmds[i].cmd) {
397+ cmditem = &mt7530_nl_cmds[i];
398+ break;
399+ }
400+ }
401+
402+ if (!cmditem) {
403+ pr_info("mt7530-nl: unknown cmd %u\n", hdr->cmd);
404+ return -EINVAL;
405+ }
406+
407+ for (i = 0; i < cmditem->nr_required_attrs; i++) {
408+ if (info->attrs[cmditem->required_attrs[i]])
409+ sat_req_attrs++;
410+ }
411+
412+ if (sat_req_attrs != cmditem->nr_required_attrs) {
413+ pr_info("mt7530-nl: missing required attr(s) for cmd %u\n",
414+ hdr->cmd);
415+ return -EINVAL;
416+ }
417+
418+ ret = cmditem->process(info);
419+
420+ mt7530_put();
421+
422+ return ret;
423+}
424+
425+int mt7530_nl_init(struct mt7530_priv **priv)
426+{
427+ int ret;
428+
429+ pr_info("mt7530-nl: genl_register_family_with_ops \n");
430+
431+ sw_priv = *priv;
432+ ret = genl_register_family(&mt7530_nl_family);
433+ if (ret) {
434+ return ret;
435+ }
436+
437+ return 0;
438+}
439+
440+void mt7530_nl_exit()
441+{
442+ sw_priv = NULL;
443+ genl_unregister_family(&mt7530_nl_family);
444+}
445Index: linux-5.4.203/drivers/net/dsa/mt7530_nl.h
446===================================================================
447--- /dev/null
448+++ linux-5.4.203/drivers/net/dsa/mt7530_nl.h
449@@ -0,0 +1,49 @@
450+/* SPDX-License-Identifier: GPL-2.0-only */
451+/*
452+ * Copyright (c) 2018 MediaTek Inc.
453+ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
454+ */
455+
456+#ifndef _MT753x_NL_H_
457+#define _MT753x_NL_H_
458+
459+#define MT7530_DSA_GENL_NAME "mt753x_dsa"
460+#define MT7530_GENL_VERSION 0x1
461+
462+enum mt7530_cmd {
463+ MT7530_CMD_UNSPEC = 0,
464+ MT7530_CMD_REQUEST,
465+ MT7530_CMD_REPLY,
466+ MT7530_CMD_READ,
467+ MT7530_CMD_WRITE,
468+
469+ __MT7530_CMD_MAX,
470+};
471+
472+enum mt7530_attr {
473+ MT7530_ATTR_TYPE_UNSPEC = 0,
474+ MT7530_ATTR_TYPE_MESG,
475+ MT7530_ATTR_TYPE_PHY,
476+ MT7530_ATTR_TYPE_DEVAD,
477+ MT7530_ATTR_TYPE_REG,
478+ MT7530_ATTR_TYPE_VAL,
479+ MT7530_ATTR_TYPE_DEV_NAME,
480+ MT7530_ATTR_TYPE_DEV_ID,
481+
482+ __MT7530_ATTR_TYPE_MAX,
483+};
484+
485+#define MT7530_NR_ATTR_TYPE (__MT7530_ATTR_TYPE_MAX - 1)
486+
487+struct mt7530_info {
488+ struct mii_bus *bus;
489+ void __iomem *base;
490+ int direct_access;
491+};
492+
493+#ifdef __KERNEL__
494+int mt7530_nl_init(struct mt7530_priv **priv);
495+void mt7530_nl_exit(void);
496+#endif /* __KERNEL__ */
497+
498+#endif /* _MT7530_NL_H_ */