0343-net-ethernet-qualcomm-Add-netdevice-support-for-QCOM.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. From 5dc80c468c668d855d76b323f09bbadb95cc3147 Mon Sep 17 00:00:00 2001
  2. From: Suruchi Agarwal <[email protected]>
  3. Date: Thu, 21 Mar 2024 16:14:46 -0700
  4. Subject: [PATCH] net: ethernet: qualcomm: Add netdevice support for QCOM
  5. IPQ9574 chipset.
  6. Add EDMA ports and netdevice operations for QCOM IPQ9574 chipset.
  7. Change-Id: I08b2eff52b4ef0d6d428c1c416f5580ef010973f
  8. Co-developed-by: Pavithra R <[email protected]>
  9. Signed-off-by: Pavithra R <[email protected]>
  10. Signed-off-by: Suruchi Agarwal <[email protected]>
  11. ---
  12. drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +-
  13. drivers/net/ethernet/qualcomm/ppe/edma.h | 3 +
  14. drivers/net/ethernet/qualcomm/ppe/edma_port.c | 270 ++++++++++++++++++
  15. drivers/net/ethernet/qualcomm/ppe/edma_port.h | 31 ++
  16. drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 19 ++
  17. 5 files changed, 324 insertions(+), 1 deletion(-)
  18. create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_port.c
  19. create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_port.h
  20. --- a/drivers/net/ethernet/qualcomm/ppe/Makefile
  21. +++ b/drivers/net/ethernet/qualcomm/ppe/Makefile
  22. @@ -7,4 +7,4 @@ obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o
  23. qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o
  24. #EDMA
  25. -qcom-ppe-objs += edma.o
  26. +qcom-ppe-objs += edma.o edma_port.o
  27. --- a/drivers/net/ethernet/qualcomm/ppe/edma.h
  28. +++ b/drivers/net/ethernet/qualcomm/ppe/edma.h
  29. @@ -26,6 +26,9 @@
  30. /* Number of PPE queue priorities supported per ARM core. */
  31. #define EDMA_PRI_MAX_PER_CORE 8
  32. +/* Interface ID start. */
  33. +#define EDMA_START_IFNUM 1
  34. +
  35. /**
  36. * enum ppe_queue_class_type - PPE queue class type
  37. * @PPE_QUEUE_CLASS_PRIORITY: Queue offset configured from internal priority
  38. --- /dev/null
  39. +++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.c
  40. @@ -0,0 +1,270 @@
  41. +// SPDX-License-Identifier: GPL-2.0-only
  42. + /* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
  43. + */
  44. +
  45. +/* EDMA port initialization, configuration and netdevice ops handling */
  46. +
  47. +#include <linux/etherdevice.h>
  48. +#include <linux/net.h>
  49. +#include <linux/netdevice.h>
  50. +#include <linux/of_net.h>
  51. +#include <linux/phylink.h>
  52. +#include <linux/printk.h>
  53. +
  54. +#include "edma.h"
  55. +#include "edma_port.h"
  56. +#include "ppe_regs.h"
  57. +
  58. +/* Number of netdev queues. */
  59. +#define EDMA_NETDEV_QUEUE_NUM 4
  60. +
  61. +static u16 __maybe_unused edma_port_select_queue(__maybe_unused struct net_device *netdev,
  62. + __maybe_unused struct sk_buff *skb,
  63. + __maybe_unused struct net_device *sb_dev)
  64. +{
  65. + int cpu = get_cpu();
  66. +
  67. + put_cpu();
  68. +
  69. + return cpu;
  70. +}
  71. +
  72. +static int edma_port_open(struct net_device *netdev)
  73. +{
  74. + struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
  75. + struct ppe_port *ppe_port;
  76. +
  77. + if (!port_priv)
  78. + return -EINVAL;
  79. +
  80. + /* Inform the Linux Networking stack about the hardware capability of
  81. + * checksum offloading and other features. Each port is
  82. + * responsible to maintain the feature set it supports.
  83. + */
  84. + netdev->features |= EDMA_NETDEV_FEATURES;
  85. + netdev->hw_features |= EDMA_NETDEV_FEATURES;
  86. + netdev->vlan_features |= EDMA_NETDEV_FEATURES;
  87. + netdev->wanted_features |= EDMA_NETDEV_FEATURES;
  88. +
  89. + ppe_port = port_priv->ppe_port;
  90. +
  91. + if (ppe_port->phylink)
  92. + phylink_start(ppe_port->phylink);
  93. +
  94. + netif_start_queue(netdev);
  95. +
  96. + return 0;
  97. +}
  98. +
  99. +static int edma_port_close(struct net_device *netdev)
  100. +{
  101. + struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
  102. + struct ppe_port *ppe_port;
  103. +
  104. + if (!port_priv)
  105. + return -EINVAL;
  106. +
  107. + netif_stop_queue(netdev);
  108. +
  109. + ppe_port = port_priv->ppe_port;
  110. +
  111. + /* Phylink close. */
  112. + if (ppe_port->phylink)
  113. + phylink_stop(ppe_port->phylink);
  114. +
  115. + return 0;
  116. +}
  117. +
  118. +static int edma_port_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
  119. +{
  120. + struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
  121. + struct ppe_port *ppe_port;
  122. + int ret = -EINVAL;
  123. +
  124. + if (!port_priv)
  125. + return -EINVAL;
  126. +
  127. + ppe_port = port_priv->ppe_port;
  128. + if (ppe_port->phylink)
  129. + return phylink_mii_ioctl(ppe_port->phylink, ifr, cmd);
  130. +
  131. + return ret;
  132. +}
  133. +
  134. +static int edma_port_change_mtu(struct net_device *netdev, int mtu)
  135. +{
  136. + struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
  137. +
  138. + if (!port_priv)
  139. + return -EINVAL;
  140. +
  141. + netdev->mtu = mtu;
  142. +
  143. + return ppe_port_set_maxframe(port_priv->ppe_port, mtu);
  144. +}
  145. +
  146. +static netdev_features_t edma_port_feature_check(__maybe_unused struct sk_buff *skb,
  147. + __maybe_unused struct net_device *netdev,
  148. + netdev_features_t features)
  149. +{
  150. + return features;
  151. +}
  152. +
  153. +static void edma_port_get_stats64(struct net_device *netdev,
  154. + struct rtnl_link_stats64 *stats)
  155. +{
  156. + struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
  157. +
  158. + if (!port_priv)
  159. + return;
  160. +
  161. + ppe_port_get_stats64(port_priv->ppe_port, stats);
  162. +}
  163. +
  164. +static int edma_port_set_mac_address(struct net_device *netdev, void *macaddr)
  165. +{
  166. + struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
  167. + struct sockaddr *addr = (struct sockaddr *)macaddr;
  168. + int ret;
  169. +
  170. + if (!port_priv)
  171. + return -EINVAL;
  172. +
  173. + netdev_dbg(netdev, "AddrFamily: %d, %0x:%0x:%0x:%0x:%0x:%0x\n",
  174. + addr->sa_family, addr->sa_data[0], addr->sa_data[1],
  175. + addr->sa_data[2], addr->sa_data[3], addr->sa_data[4],
  176. + addr->sa_data[5]);
  177. +
  178. + ret = eth_prepare_mac_addr_change(netdev, addr);
  179. + if (ret)
  180. + return ret;
  181. +
  182. + if (ppe_port_set_mac_address(port_priv->ppe_port, (u8 *)addr)) {
  183. + netdev_err(netdev, "set mac address failed for dev: %s\n", netdev->name);
  184. + return -EINVAL;
  185. + }
  186. +
  187. + eth_commit_mac_addr_change(netdev, addr);
  188. +
  189. + return 0;
  190. +}
  191. +
  192. +static const struct net_device_ops edma_port_netdev_ops = {
  193. + .ndo_open = edma_port_open,
  194. + .ndo_stop = edma_port_close,
  195. + .ndo_get_stats64 = edma_port_get_stats64,
  196. + .ndo_set_mac_address = edma_port_set_mac_address,
  197. + .ndo_validate_addr = eth_validate_addr,
  198. + .ndo_change_mtu = edma_port_change_mtu,
  199. + .ndo_eth_ioctl = edma_port_ioctl,
  200. + .ndo_features_check = edma_port_feature_check,
  201. + .ndo_select_queue = edma_port_select_queue,
  202. +};
  203. +
  204. +/**
  205. + * edma_port_destroy - EDMA port destroy.
  206. + * @port: PPE port
  207. + *
  208. + * Unregister and free the netdevice.
  209. + */
  210. +void edma_port_destroy(struct ppe_port *port)
  211. +{
  212. + int port_id = port->port_id;
  213. + struct net_device *netdev = edma_ctx->netdev_arr[port_id - 1];
  214. +
  215. + unregister_netdev(netdev);
  216. + free_netdev(netdev);
  217. + ppe_port_phylink_destroy(port);
  218. + edma_ctx->netdev_arr[port_id - 1] = NULL;
  219. +}
  220. +
  221. +/**
  222. + * edma_port_setup - EDMA port Setup.
  223. + * @port: PPE port
  224. + *
  225. + * Initialize and register the netdevice.
  226. + *
  227. + * Return 0 on success, negative error code on failure.
  228. + */
  229. +int edma_port_setup(struct ppe_port *port)
  230. +{
  231. + struct ppe_device *ppe_dev = edma_ctx->ppe_dev;
  232. + struct device_node *np = port->np;
  233. + struct edma_port_priv *port_priv;
  234. + int port_id = port->port_id;
  235. + struct net_device *netdev;
  236. + u8 mac_addr[ETH_ALEN];
  237. + int ret = 0;
  238. + u8 *maddr;
  239. +
  240. + netdev = alloc_etherdev_mqs(sizeof(struct edma_port_priv),
  241. + EDMA_NETDEV_QUEUE_NUM, EDMA_NETDEV_QUEUE_NUM);
  242. + if (!netdev) {
  243. + pr_err("alloc_etherdev() failed\n");
  244. + return -ENOMEM;
  245. + }
  246. +
  247. + SET_NETDEV_DEV(netdev, ppe_dev->dev);
  248. + netdev->dev.of_node = np;
  249. +
  250. + /* max_mtu is set to 1500 in ether_setup(). */
  251. + netdev->max_mtu = ETH_MAX_MTU;
  252. +
  253. + port_priv = netdev_priv(netdev);
  254. + memset((void *)port_priv, 0, sizeof(struct edma_port_priv));
  255. +
  256. + port_priv->ppe_port = port;
  257. + port_priv->netdev = netdev;
  258. + netdev->watchdog_timeo = 5 * HZ;
  259. + netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
  260. + netdev->netdev_ops = &edma_port_netdev_ops;
  261. + netdev->gso_max_segs = GSO_MAX_SEGS;
  262. +
  263. + maddr = mac_addr;
  264. + if (of_get_mac_address(np, maddr))
  265. + maddr = NULL;
  266. +
  267. + if (maddr && is_valid_ether_addr(maddr)) {
  268. + eth_hw_addr_set(netdev, maddr);
  269. + } else {
  270. + eth_hw_addr_random(netdev);
  271. + netdev_info(netdev, "GMAC%d Using random MAC address - %pM\n",
  272. + port_id, netdev->dev_addr);
  273. + }
  274. +
  275. + netdev_dbg(netdev, "Configuring the port %s(qcom-id:%d)\n",
  276. + netdev->name, port_id);
  277. +
  278. + /* We expect 'port_id' to correspond to ports numbers on SoC.
  279. + * These begin from '1' and hence we subtract
  280. + * one when using it as an array index.
  281. + */
  282. + edma_ctx->netdev_arr[port_id - 1] = netdev;
  283. +
  284. + /* Setup phylink. */
  285. + ret = ppe_port_phylink_setup(port, netdev);
  286. + if (ret) {
  287. + netdev_dbg(netdev, "EDMA port phylink setup for netdevice %s\n",
  288. + netdev->name);
  289. + goto port_phylink_setup_fail;
  290. + }
  291. +
  292. + /* Register the network interface. */
  293. + ret = register_netdev(netdev);
  294. + if (ret) {
  295. + netdev_dbg(netdev, "Error registering netdevice %s\n",
  296. + netdev->name);
  297. + goto register_netdev_fail;
  298. + }
  299. +
  300. + netdev_dbg(netdev, "Setup EDMA port GMAC%d done\n", port_id);
  301. + return ret;
  302. +
  303. +register_netdev_fail:
  304. + ppe_port_phylink_destroy(port);
  305. +port_phylink_setup_fail:
  306. + free_netdev(netdev);
  307. + edma_ctx->netdev_arr[port_id - 1] = NULL;
  308. +
  309. + return ret;
  310. +}
  311. --- /dev/null
  312. +++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.h
  313. @@ -0,0 +1,31 @@
  314. +/* SPDX-License-Identifier: GPL-2.0-only
  315. + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
  316. + */
  317. +
  318. +#ifndef __EDMA_PORTS__
  319. +#define __EDMA_PORTS__
  320. +
  321. +#include "ppe_port.h"
  322. +
  323. +#define EDMA_NETDEV_FEATURES (NETIF_F_FRAGLIST \
  324. + | NETIF_F_SG \
  325. + | NETIF_F_RXCSUM \
  326. + | NETIF_F_HW_CSUM \
  327. + | NETIF_F_TSO \
  328. + | NETIF_F_TSO6)
  329. +
  330. +/**
  331. + * struct edma_port_priv - EDMA port priv structure.
  332. + * @ppe_port: Pointer to PPE port
  333. + * @netdev: Corresponding netdevice
  334. + * @flags: Feature flags
  335. + */
  336. +struct edma_port_priv {
  337. + struct ppe_port *ppe_port;
  338. + struct net_device *netdev;
  339. + unsigned long flags;
  340. +};
  341. +
  342. +void edma_port_destroy(struct ppe_port *port);
  343. +int edma_port_setup(struct ppe_port *port);
  344. +#endif
  345. --- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.c
  346. +++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c
  347. @@ -13,6 +13,7 @@
  348. #include <linux/regmap.h>
  349. #include <linux/rtnetlink.h>
  350. +#include "edma_port.h"
  351. #include "ppe.h"
  352. #include "ppe_port.h"
  353. #include "ppe_regs.h"
  354. @@ -1277,12 +1278,26 @@ int ppe_port_mac_init(struct ppe_device
  355. goto err_port_node;
  356. }
  357. + ret = edma_port_setup(&ppe_ports->port[i]);
  358. + if (ret) {
  359. + dev_err(ppe_dev->dev, "QCOM EDMA port setup failed\n");
  360. + i--;
  361. + goto err_port_setup;
  362. + }
  363. +
  364. i++;
  365. }
  366. of_node_put(ports_node);
  367. return 0;
  368. +err_port_setup:
  369. + /* Destroy edma ports created till now */
  370. + while (i >= 0) {
  371. + edma_port_destroy(&ppe_ports->port[i]);
  372. + i--;
  373. + }
  374. +
  375. err_port_clk:
  376. for (j = 0; j < i; j++)
  377. ppe_port_clock_deinit(&ppe_ports->port[j]);
  378. @@ -1307,6 +1322,10 @@ void ppe_port_mac_deinit(struct ppe_devi
  379. for (i = 0; i < ppe_dev->ports->num; i++) {
  380. ppe_port = &ppe_dev->ports->port[i];
  381. +
  382. + /* Destroy all phylinks and edma ports */
  383. + edma_port_destroy(ppe_port);
  384. +
  385. ppe_port_clock_deinit(ppe_port);
  386. }
  387. }