rtl8366.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Realtek SMI library helpers for the RTL8366x variants
  3. * RTL8366RB and RTL8366S
  4. *
  5. * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
  6. * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
  7. * Copyright (C) 2010 Antti Seppälä <a.seppala@gmail.com>
  8. * Copyright (C) 2010 Roman Yeryomin <roman@advem.lv>
  9. * Copyright (C) 2011 Colin Leitner <colin.leitner@googlemail.com>
  10. */
  11. #include <linux/if_bridge.h>
  12. #include <net/dsa.h>
  13. #include "realtek-smi.h"
  14. int rtl8366_mc_is_used(struct realtek_smi *smi, int mc_index, int *used)
  15. {
  16. int ret;
  17. int i;
  18. *used = 0;
  19. for (i = 0; i < smi->num_ports; i++) {
  20. int index = 0;
  21. ret = smi->ops->get_mc_index(smi, i, &index);
  22. if (ret)
  23. return ret;
  24. if (mc_index == index) {
  25. *used = 1;
  26. break;
  27. }
  28. }
  29. return 0;
  30. }
  31. EXPORT_SYMBOL_GPL(rtl8366_mc_is_used);
  32. int rtl8366_set_vlan(struct realtek_smi *smi, int vid, u32 member,
  33. u32 untag, u32 fid)
  34. {
  35. struct rtl8366_vlan_4k vlan4k;
  36. int ret;
  37. int i;
  38. /* Update the 4K table */
  39. ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
  40. if (ret)
  41. return ret;
  42. vlan4k.member = member;
  43. vlan4k.untag = untag;
  44. vlan4k.fid = fid;
  45. ret = smi->ops->set_vlan_4k(smi, &vlan4k);
  46. if (ret)
  47. return ret;
  48. /* Try to find an existing MC entry for this VID */
  49. for (i = 0; i < smi->num_vlan_mc; i++) {
  50. struct rtl8366_vlan_mc vlanmc;
  51. ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
  52. if (ret)
  53. return ret;
  54. if (vid == vlanmc.vid) {
  55. /* update the MC entry */
  56. vlanmc.member = member;
  57. vlanmc.untag = untag;
  58. vlanmc.fid = fid;
  59. ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
  60. break;
  61. }
  62. }
  63. return ret;
  64. }
  65. EXPORT_SYMBOL_GPL(rtl8366_set_vlan);
  66. int rtl8366_get_pvid(struct realtek_smi *smi, int port, int *val)
  67. {
  68. struct rtl8366_vlan_mc vlanmc;
  69. int ret;
  70. int index;
  71. ret = smi->ops->get_mc_index(smi, port, &index);
  72. if (ret)
  73. return ret;
  74. ret = smi->ops->get_vlan_mc(smi, index, &vlanmc);
  75. if (ret)
  76. return ret;
  77. *val = vlanmc.vid;
  78. return 0;
  79. }
  80. EXPORT_SYMBOL_GPL(rtl8366_get_pvid);
  81. int rtl8366_set_pvid(struct realtek_smi *smi, unsigned int port,
  82. unsigned int vid)
  83. {
  84. struct rtl8366_vlan_mc vlanmc;
  85. struct rtl8366_vlan_4k vlan4k;
  86. int ret;
  87. int i;
  88. /* Try to find an existing MC entry for this VID */
  89. for (i = 0; i < smi->num_vlan_mc; i++) {
  90. ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
  91. if (ret)
  92. return ret;
  93. if (vid == vlanmc.vid) {
  94. ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
  95. if (ret)
  96. return ret;
  97. ret = smi->ops->set_mc_index(smi, port, i);
  98. return ret;
  99. }
  100. }
  101. /* We have no MC entry for this VID, try to find an empty one */
  102. for (i = 0; i < smi->num_vlan_mc; i++) {
  103. ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
  104. if (ret)
  105. return ret;
  106. if (vlanmc.vid == 0 && vlanmc.member == 0) {
  107. /* Update the entry from the 4K table */
  108. ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
  109. if (ret)
  110. return ret;
  111. vlanmc.vid = vid;
  112. vlanmc.member = vlan4k.member;
  113. vlanmc.untag = vlan4k.untag;
  114. vlanmc.fid = vlan4k.fid;
  115. ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
  116. if (ret)
  117. return ret;
  118. ret = smi->ops->set_mc_index(smi, port, i);
  119. return ret;
  120. }
  121. }
  122. /* MC table is full, try to find an unused entry and replace it */
  123. for (i = 0; i < smi->num_vlan_mc; i++) {
  124. int used;
  125. ret = rtl8366_mc_is_used(smi, i, &used);
  126. if (ret)
  127. return ret;
  128. if (!used) {
  129. /* Update the entry from the 4K table */
  130. ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
  131. if (ret)
  132. return ret;
  133. vlanmc.vid = vid;
  134. vlanmc.member = vlan4k.member;
  135. vlanmc.untag = vlan4k.untag;
  136. vlanmc.fid = vlan4k.fid;
  137. ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
  138. if (ret)
  139. return ret;
  140. ret = smi->ops->set_mc_index(smi, port, i);
  141. return ret;
  142. }
  143. }
  144. dev_err(smi->dev,
  145. "all VLAN member configurations are in use\n");
  146. return -ENOSPC;
  147. }
  148. EXPORT_SYMBOL_GPL(rtl8366_set_pvid);
  149. int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable)
  150. {
  151. int ret;
  152. /* To enable 4k VLAN, ordinary VLAN must be enabled first,
  153. * but if we disable 4k VLAN it is fine to leave ordinary
  154. * VLAN enabled.
  155. */
  156. if (enable) {
  157. /* Make sure VLAN is ON */
  158. ret = smi->ops->enable_vlan(smi, true);
  159. if (ret)
  160. return ret;
  161. smi->vlan_enabled = true;
  162. }
  163. ret = smi->ops->enable_vlan4k(smi, enable);
  164. if (ret)
  165. return ret;
  166. smi->vlan4k_enabled = enable;
  167. return 0;
  168. }
  169. EXPORT_SYMBOL_GPL(rtl8366_enable_vlan4k);
  170. int rtl8366_enable_vlan(struct realtek_smi *smi, bool enable)
  171. {
  172. int ret;
  173. ret = smi->ops->enable_vlan(smi, enable);
  174. if (ret)
  175. return ret;
  176. smi->vlan_enabled = enable;
  177. /* If we turn VLAN off, make sure that we turn off
  178. * 4k VLAN as well, if that happened to be on.
  179. */
  180. if (!enable) {
  181. smi->vlan4k_enabled = false;
  182. ret = smi->ops->enable_vlan4k(smi, false);
  183. }
  184. return ret;
  185. }
  186. EXPORT_SYMBOL_GPL(rtl8366_enable_vlan);
  187. int rtl8366_reset_vlan(struct realtek_smi *smi)
  188. {
  189. struct rtl8366_vlan_mc vlanmc;
  190. int ret;
  191. int i;
  192. rtl8366_enable_vlan(smi, false);
  193. rtl8366_enable_vlan4k(smi, false);
  194. /* Clear the 16 VLAN member configurations */
  195. vlanmc.vid = 0;
  196. vlanmc.priority = 0;
  197. vlanmc.member = 0;
  198. vlanmc.untag = 0;
  199. vlanmc.fid = 0;
  200. for (i = 0; i < smi->num_vlan_mc; i++) {
  201. ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
  202. if (ret)
  203. return ret;
  204. }
  205. return 0;
  206. }
  207. EXPORT_SYMBOL_GPL(rtl8366_reset_vlan);
  208. int rtl8366_init_vlan(struct realtek_smi *smi)
  209. {
  210. int port;
  211. int ret;
  212. ret = rtl8366_reset_vlan(smi);
  213. if (ret)
  214. return ret;
  215. /* Loop over the available ports, for each port, associate
  216. * it with the VLAN (port+1)
  217. */
  218. for (port = 0; port < smi->num_ports; port++) {
  219. u32 mask;
  220. if (port == smi->cpu_port)
  221. /* For the CPU port, make all ports members of this
  222. * VLAN.
  223. */
  224. mask = GENMASK(smi->num_ports - 1, 0);
  225. else
  226. /* For all other ports, enable itself plus the
  227. * CPU port.
  228. */
  229. mask = BIT(port) | BIT(smi->cpu_port);
  230. /* For each port, set the port as member of VLAN (port+1)
  231. * and untagged, except for the CPU port: the CPU port (5) is
  232. * member of VLAN 6 and so are ALL the other ports as well.
  233. * Use filter 0 (no filter).
  234. */
  235. dev_info(smi->dev, "VLAN%d port mask for port %d, %08x\n",
  236. (port + 1), port, mask);
  237. ret = rtl8366_set_vlan(smi, (port + 1), mask, mask, 0);
  238. if (ret)
  239. return ret;
  240. dev_info(smi->dev, "VLAN%d port %d, PVID set to %d\n",
  241. (port + 1), port, (port + 1));
  242. ret = rtl8366_set_pvid(smi, port, (port + 1));
  243. if (ret)
  244. return ret;
  245. }
  246. return rtl8366_enable_vlan(smi, true);
  247. }
  248. EXPORT_SYMBOL_GPL(rtl8366_init_vlan);
  249. int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
  250. {
  251. struct realtek_smi *smi = ds->priv;
  252. struct rtl8366_vlan_4k vlan4k;
  253. int ret;
  254. /* Use VLAN nr port + 1 since VLAN0 is not valid */
  255. if (!smi->ops->is_vlan_valid(smi, port + 1))
  256. return -EINVAL;
  257. dev_info(smi->dev, "%s filtering on port %d\n",
  258. vlan_filtering ? "enable" : "disable",
  259. port);
  260. /* TODO:
  261. * The hardware support filter ID (FID) 0..7, I have no clue how to
  262. * support this in the driver when the callback only says on/off.
  263. */
  264. ret = smi->ops->get_vlan_4k(smi, port + 1, &vlan4k);
  265. if (ret)
  266. return ret;
  267. /* Just set the filter to FID 1 for now then */
  268. ret = rtl8366_set_vlan(smi, port + 1,
  269. vlan4k.member,
  270. vlan4k.untag,
  271. 1);
  272. if (ret)
  273. return ret;
  274. return 0;
  275. }
  276. EXPORT_SYMBOL_GPL(rtl8366_vlan_filtering);
  277. int rtl8366_vlan_prepare(struct dsa_switch *ds, int port,
  278. const struct switchdev_obj_port_vlan *vlan)
  279. {
  280. struct realtek_smi *smi = ds->priv;
  281. u16 vid;
  282. int ret;
  283. for (vid = vlan->vid_begin; vid < vlan->vid_end; vid++)
  284. if (!smi->ops->is_vlan_valid(smi, vid))
  285. return -EINVAL;
  286. dev_info(smi->dev, "prepare VLANs %04x..%04x\n",
  287. vlan->vid_begin, vlan->vid_end);
  288. /* Enable VLAN in the hardware
  289. * FIXME: what's with this 4k business?
  290. * Just rtl8366_enable_vlan() seems inconclusive.
  291. */
  292. ret = rtl8366_enable_vlan4k(smi, true);
  293. if (ret)
  294. return ret;
  295. return 0;
  296. }
  297. EXPORT_SYMBOL_GPL(rtl8366_vlan_prepare);
  298. void rtl8366_vlan_add(struct dsa_switch *ds, int port,
  299. const struct switchdev_obj_port_vlan *vlan)
  300. {
  301. bool untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
  302. bool pvid = !!(vlan->flags & BRIDGE_VLAN_INFO_PVID);
  303. struct realtek_smi *smi = ds->priv;
  304. u32 member = 0;
  305. u32 untag = 0;
  306. u16 vid;
  307. int ret;
  308. for (vid = vlan->vid_begin; vid < vlan->vid_end; vid++)
  309. if (!smi->ops->is_vlan_valid(smi, vid))
  310. return;
  311. dev_info(smi->dev, "add VLAN on port %d, %s, %s\n",
  312. port,
  313. untagged ? "untagged" : "tagged",
  314. pvid ? " PVID" : "no PVID");
  315. if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
  316. dev_err(smi->dev, "port is DSA or CPU port\n");
  317. for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
  318. int pvid_val = 0;
  319. dev_info(smi->dev, "add VLAN %04x\n", vid);
  320. member |= BIT(port);
  321. if (untagged)
  322. untag |= BIT(port);
  323. /* To ensure that we have a valid MC entry for this VLAN,
  324. * initialize the port VLAN ID here.
  325. */
  326. ret = rtl8366_get_pvid(smi, port, &pvid_val);
  327. if (ret < 0) {
  328. dev_err(smi->dev, "could not lookup PVID for port %d\n",
  329. port);
  330. return;
  331. }
  332. if (pvid_val == 0) {
  333. ret = rtl8366_set_pvid(smi, port, vid);
  334. if (ret < 0)
  335. return;
  336. }
  337. }
  338. ret = rtl8366_set_vlan(smi, port, member, untag, 0);
  339. if (ret)
  340. dev_err(smi->dev,
  341. "failed to set up VLAN %04x",
  342. vid);
  343. }
  344. EXPORT_SYMBOL_GPL(rtl8366_vlan_add);
  345. int rtl8366_vlan_del(struct dsa_switch *ds, int port,
  346. const struct switchdev_obj_port_vlan *vlan)
  347. {
  348. struct realtek_smi *smi = ds->priv;
  349. u16 vid;
  350. int ret;
  351. dev_info(smi->dev, "del VLAN on port %d\n", port);
  352. for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
  353. int i;
  354. dev_info(smi->dev, "del VLAN %04x\n", vid);
  355. for (i = 0; i < smi->num_vlan_mc; i++) {
  356. struct rtl8366_vlan_mc vlanmc;
  357. ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
  358. if (ret)
  359. return ret;
  360. if (vid == vlanmc.vid) {
  361. /* clear VLAN member configurations */
  362. vlanmc.vid = 0;
  363. vlanmc.priority = 0;
  364. vlanmc.member = 0;
  365. vlanmc.untag = 0;
  366. vlanmc.fid = 0;
  367. ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
  368. if (ret) {
  369. dev_err(smi->dev,
  370. "failed to remove VLAN %04x\n",
  371. vid);
  372. return ret;
  373. }
  374. break;
  375. }
  376. }
  377. }
  378. return 0;
  379. }
  380. EXPORT_SYMBOL_GPL(rtl8366_vlan_del);
  381. void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
  382. uint8_t *data)
  383. {
  384. struct realtek_smi *smi = ds->priv;
  385. struct rtl8366_mib_counter *mib;
  386. int i;
  387. if (port >= smi->num_ports)
  388. return;
  389. for (i = 0; i < smi->num_mib_counters; i++) {
  390. mib = &smi->mib_counters[i];
  391. strncpy(data + i * ETH_GSTRING_LEN,
  392. mib->name, ETH_GSTRING_LEN);
  393. }
  394. }
  395. EXPORT_SYMBOL_GPL(rtl8366_get_strings);
  396. int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset)
  397. {
  398. struct realtek_smi *smi = ds->priv;
  399. /* We only support SS_STATS */
  400. if (sset != ETH_SS_STATS)
  401. return 0;
  402. if (port >= smi->num_ports)
  403. return -EINVAL;
  404. return smi->num_mib_counters;
  405. }
  406. EXPORT_SYMBOL_GPL(rtl8366_get_sset_count);
  407. void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
  408. {
  409. struct realtek_smi *smi = ds->priv;
  410. int i;
  411. int ret;
  412. if (port >= smi->num_ports)
  413. return;
  414. for (i = 0; i < smi->num_mib_counters; i++) {
  415. struct rtl8366_mib_counter *mib;
  416. u64 mibvalue = 0;
  417. mib = &smi->mib_counters[i];
  418. ret = smi->ops->get_mib_counter(smi, port, mib, &mibvalue);
  419. if (ret) {
  420. dev_err(smi->dev, "error reading MIB counter %s\n",
  421. mib->name);
  422. }
  423. data[i] = mibvalue;
  424. }
  425. }
  426. EXPORT_SYMBOL_GPL(rtl8366_get_ethtool_stats);