blob: 3f9adabecdd3d859b4ff7ba4c6aa7732774c1d26 [file] [log] [blame]
developer5d148cb2023-06-02 13:08:11 +08001From 3e75ca66195dec023ca2e837ff748c317fd7ac26 Mon Sep 17 00:00:00 2001
2From: Sam Shih <sam.shih@mediatek.com>
3Date: Fri, 2 Jun 2023 13:06:00 +0800
4Subject: [PATCH]
5 [backport-networking-drivers][999-1705-add-netlink-support-for-dsa.patch]
6
7---
8 drivers/net/dsa/Makefile | 2 +-
9 drivers/net/dsa/mt7530.c | 24 ++-
10 drivers/net/dsa/mt7530.h | 8 +
11 drivers/net/dsa/mt7530_nl.c | 311 ++++++++++++++++++++++++++++++++++++
12 drivers/net/dsa/mt7530_nl.h | 49 ++++++
13 5 files changed, 386 insertions(+), 8 deletions(-)
14 create mode 100644 drivers/net/dsa/mt7530_nl.c
15 create mode 100644 drivers/net/dsa/mt7530_nl.h
16
17diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
18index 0aa10bc3d..ef563c6c1 100644
19--- a/drivers/net/dsa/Makefile
20+++ b/drivers/net/dsa/Makefile
21@@ -7,7 +7,7 @@ obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdinfo.o
developer2cdaeb12022-10-04 20:25:05 +080022 endif
23 obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
24 obj-$(CONFIG_NET_DSA_MT7530) += mt7530-dsa.o
25-mt7530-dsa-objs := mt7530.o mt7531_phy.o
26+mt7530-dsa-objs := mt7530.o mt7530_nl.o mt7531_phy.o
27 obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
28 obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o
29 obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
developer5d148cb2023-06-02 13:08:11 +080030diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
31index e4c021eeb..63f8a632b 100644
32--- a/drivers/net/dsa/mt7530.c
33+++ b/drivers/net/dsa/mt7530.c
developer2cdaeb12022-10-04 20:25:05 +080034@@ -21,6 +21,7 @@
35 #include <net/dsa.h>
developer5d148cb2023-06-02 13:08:11 +080036
developer2cdaeb12022-10-04 20:25:05 +080037 #include "mt7530.h"
38+#include "mt7530_nl.h"
developer5d148cb2023-06-02 13:08:11 +080039
developer2cdaeb12022-10-04 20:25:05 +080040 /* String, offset, and register size in bytes if different from 4 bytes */
41 static const struct mt7530_mib_desc mt7530_mib[] = {
developer5d148cb2023-06-02 13:08:11 +080042@@ -222,7 +223,7 @@ mt7530_mii_read(struct mt7530_priv *priv, u32 reg)
developer2cdaeb12022-10-04 20:25:05 +080043 return (hi << 16) | (lo & 0xffff);
44 }
developer5d148cb2023-06-02 13:08:11 +080045
developer2cdaeb12022-10-04 20:25:05 +080046-static void
47+void
48 mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val)
49 {
50 struct mii_bus *bus = priv->bus;
developer5d148cb2023-06-02 13:08:11 +080051@@ -255,7 +256,7 @@ _mt7530_read(struct mt7530_dummy_poll *p)
developer2cdaeb12022-10-04 20:25:05 +080052 return val;
53 }
developer5d148cb2023-06-02 13:08:11 +080054
developer2cdaeb12022-10-04 20:25:05 +080055-static u32
56+u32
57 mt7530_read(struct mt7530_priv *priv, u32 reg)
58 {
59 struct mt7530_dummy_poll p;
developer5d148cb2023-06-02 13:08:11 +080060@@ -614,7 +615,7 @@ static int mt7530_phy_write(struct dsa_switch *ds, int port, int regnum,
developer2cdaeb12022-10-04 20:25:05 +080061 return mdiobus_write_nested(priv->bus, port, regnum, val);
62 }
developer5d148cb2023-06-02 13:08:11 +080063
developer2cdaeb12022-10-04 20:25:05 +080064-static int
65+int
66 mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
67 int regnum)
68 {
69@@ -663,7 +664,7 @@ out:
70 return ret;
71 }
developer5d148cb2023-06-02 13:08:11 +080072
developer2cdaeb12022-10-04 20:25:05 +080073-static int
74+int
75 mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
76 int regnum, u32 data)
77 {
78@@ -711,7 +712,7 @@ out:
79 return ret;
80 }
developer5d148cb2023-06-02 13:08:11 +080081
developer2cdaeb12022-10-04 20:25:05 +080082-static int
83+int
84 mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)
85 {
86 struct mii_bus *bus = priv->bus;
87@@ -749,7 +750,7 @@ out:
88 return ret;
89 }
developer5d148cb2023-06-02 13:08:11 +080090
developer2cdaeb12022-10-04 20:25:05 +080091-static int
92+int
93 mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
94 u16 data)
95 {
developer5d148cb2023-06-02 13:08:11 +080096@@ -2691,6 +2692,7 @@ mt7530_probe(struct mdio_device *mdiodev)
developer2cdaeb12022-10-04 20:25:05 +080097 {
98 struct mt7530_priv *priv;
99 struct device_node *dn;
100+ int ret;
developer5d148cb2023-06-02 13:08:11 +0800101
developer2cdaeb12022-10-04 20:25:05 +0800102 dn = mdiodev->dev.of_node;
developer5d148cb2023-06-02 13:08:11 +0800103
104@@ -2766,7 +2768,13 @@ mt7530_probe(struct mdio_device *mdiodev)
developer2cdaeb12022-10-04 20:25:05 +0800105 mutex_init(&priv->reg_mutex);
106 dev_set_drvdata(&mdiodev->dev, priv);
developer5d148cb2023-06-02 13:08:11 +0800107
developer2cdaeb12022-10-04 20:25:05 +0800108- return dsa_register_switch(priv->ds);
109+ ret = dsa_register_switch(priv->ds);
110+ if (ret)
111+ return ret;
112+
113+ mt7530_nl_init(&priv);
114+
115+ return 0;
116 }
developer5d148cb2023-06-02 13:08:11 +0800117
developer2cdaeb12022-10-04 20:25:05 +0800118 static void
developer5d148cb2023-06-02 13:08:11 +0800119@@ -2787,6 +2795,8 @@ mt7530_remove(struct mdio_device *mdiodev)
120
developer2cdaeb12022-10-04 20:25:05 +0800121 dsa_unregister_switch(priv->ds);
122 mutex_destroy(&priv->reg_mutex);
123+
124+ mt7530_nl_exit();
125 }
developer5d148cb2023-06-02 13:08:11 +0800126
developer2cdaeb12022-10-04 20:25:05 +0800127 static struct mdio_driver mt7530_mdio_driver = {
developer5d148cb2023-06-02 13:08:11 +0800128diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
129index 8f1e827ff..130d7e5ec 100644
130--- a/drivers/net/dsa/mt7530.h
131+++ b/drivers/net/dsa/mt7530.h
132@@ -783,4 +783,12 @@ static inline void INIT_MT7530_DUMMY_POLL(struct mt7530_dummy_poll *p,
developer2cdaeb12022-10-04 20:25:05 +0800133 }
developer5d148cb2023-06-02 13:08:11 +0800134
developer2cdaeb12022-10-04 20:25:05 +0800135 int mt7531_phy_setup(struct dsa_switch *ds);
136+u32 mt7530_read(struct mt7530_priv *priv, u32 reg);
137+void mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val);
138+int mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad, int regnum);
139+int mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad, int regnum, u32 data);
140+int mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum);
141+int mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum, u16 data);
142+
143+
144 #endif /* __MT7530_H */
developer5d148cb2023-06-02 13:08:11 +0800145diff --git a/drivers/net/dsa/mt7530_nl.c b/drivers/net/dsa/mt7530_nl.c
146new file mode 100644
147index 000000000..676adef70
developer2cdaeb12022-10-04 20:25:05 +0800148--- /dev/null
developer5d148cb2023-06-02 13:08:11 +0800149+++ b/drivers/net/dsa/mt7530_nl.c
developer2cdaeb12022-10-04 20:25:05 +0800150@@ -0,0 +1,311 @@
151+// SPDX-License-Identifier: GPL-2.0
152+/*
153+ * Copyright (c) 2018 MediaTek Inc.
154+ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
155+ */
156+
157+#include <linux/types.h>
158+#include <linux/kernel.h>
159+#include <linux/module.h>
160+#include <linux/init.h>
161+#include <net/genetlink.h>
162+#include <linux/of_mdio.h>
163+#include <linux/phylink.h>
164+#include <net/dsa.h>
165+
166+#include "mt7530.h"
167+#include "mt7530_nl.h"
168+
169+struct mt7530_nl_cmd_item {
170+ enum mt7530_cmd cmd;
171+ bool require_dev;
172+ int (*process)(struct genl_info *info);
173+ u32 nr_required_attrs;
174+ const enum mt7530_attr *required_attrs;
175+};
176+
177+struct mt7530_priv *sw_priv;
178+
179+static DEFINE_MUTEX(mt7530_devs_lock);
180+
181+void mt7530_put(void)
182+{
183+ mutex_unlock(&mt7530_devs_lock);
184+}
185+
186+void mt7530_lock(void)
187+{
188+ mutex_lock(&mt7530_devs_lock);
189+}
190+
191+static int mt7530_nl_response(struct sk_buff *skb, struct genl_info *info);
192+
193+static const struct nla_policy mt7530_nl_cmd_policy[] = {
194+ [MT7530_ATTR_TYPE_MESG] = { .type = NLA_STRING },
195+ [MT7530_ATTR_TYPE_PHY] = { .type = NLA_S32 },
196+ [MT7530_ATTR_TYPE_REG] = { .type = NLA_S32 },
197+ [MT7530_ATTR_TYPE_VAL] = { .type = NLA_S32 },
198+ [MT7530_ATTR_TYPE_DEV_NAME] = { .type = NLA_S32 },
199+ [MT7530_ATTR_TYPE_DEV_ID] = { .type = NLA_S32 },
200+ [MT7530_ATTR_TYPE_DEVAD] = { .type = NLA_S32 },
201+};
202+
203+static const struct genl_ops mt7530_nl_ops[] = {
204+ {
205+ .cmd = MT7530_CMD_REQUEST,
206+ .doit = mt7530_nl_response,
207+ .flags = GENL_ADMIN_PERM,
208+ }, {
209+ .cmd = MT7530_CMD_READ,
210+ .doit = mt7530_nl_response,
211+ .flags = GENL_ADMIN_PERM,
212+ }, {
213+ .cmd = MT7530_CMD_WRITE,
214+ .doit = mt7530_nl_response,
215+ .flags = GENL_ADMIN_PERM,
216+ },
217+};
218+
219+static struct genl_family mt7530_nl_family = {
220+ .name = MT7530_DSA_GENL_NAME,
221+ .version = MT7530_GENL_VERSION,
222+ .maxattr = MT7530_NR_ATTR_TYPE,
223+ .ops = mt7530_nl_ops,
224+ .n_ops = ARRAY_SIZE(mt7530_nl_ops),
225+ .policy = mt7530_nl_cmd_policy,
226+};
227+
228+static int mt7530_nl_prepare_reply(struct genl_info *info, u8 cmd,
229+ struct sk_buff **skbp)
230+{
231+ struct sk_buff *msg;
232+ void *reply;
233+
234+ if (!info)
235+ return -EINVAL;
236+
237+ msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
238+ if (!msg)
239+ return -ENOMEM;
240+
241+ /* Construct send-back message header */
242+ reply = genlmsg_put(msg, info->snd_portid, info->snd_seq,
243+ &mt7530_nl_family, 0, cmd);
244+ if (!reply) {
245+ nlmsg_free(msg);
246+ return -EINVAL;
247+ }
248+
249+ *skbp = msg;
250+ return 0;
251+}
252+
253+static int mt7530_nl_send_reply(struct sk_buff *skb, struct genl_info *info)
254+{
255+ struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));
256+ void *reply = genlmsg_data(genlhdr);
257+
258+ /* Finalize a generic netlink message (update message header) */
259+ genlmsg_end(skb, reply);
260+
261+ /* reply to a request */
262+ return genlmsg_reply(skb, info);
263+}
264+
265+static s32 mt7530_nl_get_s32(struct genl_info *info, enum mt7530_attr attr,
266+ s32 defval)
267+{
268+ struct nlattr *na;
269+
270+ na = info->attrs[attr];
271+ if (na)
272+ return nla_get_s32(na);
273+
274+ return defval;
275+}
276+
277+static int mt7530_nl_get_u32(struct genl_info *info, enum mt7530_attr attr,
278+ u32 *val)
279+{
280+ struct nlattr *na;
281+
282+ na = info->attrs[attr];
283+ if (na) {
284+ *val = nla_get_u32(na);
285+ return 0;
286+ }
287+
288+ return -1;
289+}
290+
291+static int mt7530_nl_reply_read(struct genl_info *info)
292+{
293+ struct sk_buff *rep_skb = NULL;
294+ s32 phy, devad, reg;
295+ int value;
296+ int ret = 0;
297+
298+ phy = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_PHY, -1);
299+ devad = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_DEVAD, -1);
300+ reg = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_REG, -1);
301+
302+ if (reg < 0)
303+ goto err;
304+
305+ ret = mt7530_nl_prepare_reply(info, MT7530_CMD_READ, &rep_skb);
306+ if (ret < 0)
307+ goto err;
308+
309+ if (phy >= 0) {
310+ if (devad < 0)
311+ value = mt7531_ind_c22_phy_read(sw_priv, phy, reg);
312+ else
313+ value = mt7531_ind_c45_phy_read(sw_priv, phy, devad, reg);
314+ } else
315+ value = mt7530_read(sw_priv, reg);
316+
317+ ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_REG, reg);
318+ if (ret < 0)
319+ goto err;
320+
321+ ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_VAL, value);
322+ if (ret < 0)
323+ goto err;
324+
325+ return mt7530_nl_send_reply(rep_skb, info);
326+
327+err:
328+ if (rep_skb)
329+ nlmsg_free(rep_skb);
330+
331+ return ret;
332+}
333+
334+static int mt7530_nl_reply_write(struct genl_info *info)
335+{
336+ struct sk_buff *rep_skb = NULL;
337+ s32 phy, devad, reg;
338+ u32 value;
339+ int ret = 0;
340+
341+ phy = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_PHY, -1);
342+ devad = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_DEVAD, -1);
343+ reg = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_REG, -1);
344+
345+ if (mt7530_nl_get_u32(info, MT7530_ATTR_TYPE_VAL, &value))
346+ goto err;
347+
348+ if (reg < 0)
349+ goto err;
350+
351+ ret = mt7530_nl_prepare_reply(info, MT7530_CMD_WRITE, &rep_skb);
352+ if (ret < 0)
353+ goto err;
354+
355+ if (phy >= 0) {
356+ if (devad < 0)
357+ mt7531_ind_c22_phy_write(sw_priv, phy, reg, value);
358+ else
359+ mt7531_ind_c45_phy_write(sw_priv, phy, devad, reg, value);
360+ } else
361+ mt7530_write(sw_priv, reg, value);
362+
363+ ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_REG, reg);
364+ if (ret < 0)
365+ goto err;
366+
367+ ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_VAL, value);
368+ if (ret < 0)
369+ goto err;
370+
371+ return mt7530_nl_send_reply(rep_skb, info);
372+
373+err:
374+ if (rep_skb)
375+ nlmsg_free(rep_skb);
376+
377+ return ret;
378+}
379+
380+static const enum mt7530_attr mt7530_nl_cmd_read_attrs[] = {
381+ MT7530_ATTR_TYPE_REG
382+};
383+
384+static const enum mt7530_attr mt7530_nl_cmd_write_attrs[] = {
385+ MT7530_ATTR_TYPE_REG,
386+ MT7530_ATTR_TYPE_VAL
387+};
388+
389+static const struct mt7530_nl_cmd_item mt7530_nl_cmds[] = {
390+ {
391+ .cmd = MT7530_CMD_READ,
392+ .require_dev = true,
393+ .process = mt7530_nl_reply_read,
394+ .required_attrs = mt7530_nl_cmd_read_attrs,
395+ .nr_required_attrs = ARRAY_SIZE(mt7530_nl_cmd_read_attrs),
396+ }, {
397+ .cmd = MT7530_CMD_WRITE,
398+ .require_dev = true,
399+ .process = mt7530_nl_reply_write,
400+ .required_attrs = mt7530_nl_cmd_write_attrs,
401+ .nr_required_attrs = ARRAY_SIZE(mt7530_nl_cmd_write_attrs),
402+ }
403+};
404+
405+static int mt7530_nl_response(struct sk_buff *skb, struct genl_info *info)
406+{
407+ struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
408+ const struct mt7530_nl_cmd_item *cmditem = NULL;
409+ u32 sat_req_attrs = 0;
410+ int i, ret;
411+
412+ for (i = 0; i < ARRAY_SIZE(mt7530_nl_cmds); i++) {
413+ if (hdr->cmd == mt7530_nl_cmds[i].cmd) {
414+ cmditem = &mt7530_nl_cmds[i];
415+ break;
416+ }
417+ }
418+
419+ if (!cmditem) {
420+ pr_info("mt7530-nl: unknown cmd %u\n", hdr->cmd);
421+ return -EINVAL;
422+ }
423+
424+ for (i = 0; i < cmditem->nr_required_attrs; i++) {
425+ if (info->attrs[cmditem->required_attrs[i]])
426+ sat_req_attrs++;
427+ }
428+
429+ if (sat_req_attrs != cmditem->nr_required_attrs) {
430+ pr_info("mt7530-nl: missing required attr(s) for cmd %u\n",
431+ hdr->cmd);
432+ return -EINVAL;
433+ }
434+
435+ ret = cmditem->process(info);
436+
437+ mt7530_put();
438+
439+ return ret;
440+}
441+
442+int mt7530_nl_init(struct mt7530_priv **priv)
443+{
444+ int ret;
445+
446+ pr_info("mt7530-nl: genl_register_family_with_ops \n");
447+
448+ sw_priv = *priv;
449+ ret = genl_register_family(&mt7530_nl_family);
450+ if (ret) {
451+ return ret;
452+ }
453+
454+ return 0;
455+}
456+
457+void mt7530_nl_exit()
458+{
459+ sw_priv = NULL;
460+ genl_unregister_family(&mt7530_nl_family);
461+}
developer5d148cb2023-06-02 13:08:11 +0800462diff --git a/drivers/net/dsa/mt7530_nl.h b/drivers/net/dsa/mt7530_nl.h
463new file mode 100644
464index 000000000..4619288c2
developer2cdaeb12022-10-04 20:25:05 +0800465--- /dev/null
developer5d148cb2023-06-02 13:08:11 +0800466+++ b/drivers/net/dsa/mt7530_nl.h
developer2cdaeb12022-10-04 20:25:05 +0800467@@ -0,0 +1,49 @@
468+/* SPDX-License-Identifier: GPL-2.0-only */
469+/*
470+ * Copyright (c) 2018 MediaTek Inc.
471+ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
472+ */
473+
474+#ifndef _MT753x_NL_H_
475+#define _MT753x_NL_H_
476+
477+#define MT7530_DSA_GENL_NAME "mt753x_dsa"
478+#define MT7530_GENL_VERSION 0x1
479+
480+enum mt7530_cmd {
481+ MT7530_CMD_UNSPEC = 0,
482+ MT7530_CMD_REQUEST,
483+ MT7530_CMD_REPLY,
484+ MT7530_CMD_READ,
485+ MT7530_CMD_WRITE,
486+
487+ __MT7530_CMD_MAX,
488+};
489+
490+enum mt7530_attr {
491+ MT7530_ATTR_TYPE_UNSPEC = 0,
492+ MT7530_ATTR_TYPE_MESG,
493+ MT7530_ATTR_TYPE_PHY,
494+ MT7530_ATTR_TYPE_DEVAD,
495+ MT7530_ATTR_TYPE_REG,
496+ MT7530_ATTR_TYPE_VAL,
497+ MT7530_ATTR_TYPE_DEV_NAME,
498+ MT7530_ATTR_TYPE_DEV_ID,
499+
500+ __MT7530_ATTR_TYPE_MAX,
501+};
502+
503+#define MT7530_NR_ATTR_TYPE (__MT7530_ATTR_TYPE_MAX - 1)
504+
505+struct mt7530_info {
506+ struct mii_bus *bus;
507+ void __iomem *base;
508+ int direct_access;
509+};
510+
511+#ifdef __KERNEL__
512+int mt7530_nl_init(struct mt7530_priv **priv);
513+void mt7530_nl_exit(void);
514+#endif /* __KERNEL__ */
515+
516+#endif /* _MT7530_NL_H_ */
developer5d148cb2023-06-02 13:08:11 +0800517--
5182.34.1
519