rtl8366.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  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. if (!smi->ops->is_vlan_valid(smi, port))
  255. return -EINVAL;
  256. dev_info(smi->dev, "%s filtering on port %d\n",
  257. vlan_filtering ? "enable" : "disable",
  258. port);
  259. /* TODO:
  260. * The hardware support filter ID (FID) 0..7, I have no clue how to
  261. * support this in the driver when the callback only says on/off.
  262. */
  263. ret = smi->ops->get_vlan_4k(smi, port, &vlan4k);
  264. if (ret)
  265. return ret;
  266. /* Just set the filter to FID 1 for now then */
  267. ret = rtl8366_set_vlan(smi, port,
  268. vlan4k.member,
  269. vlan4k.untag,
  270. 1);
  271. if (ret)
  272. return ret;
  273. return 0;
  274. }
  275. EXPORT_SYMBOL_GPL(rtl8366_vlan_filtering);
  276. int rtl8366_vlan_prepare(struct dsa_switch *ds, int port,
  277. const struct switchdev_obj_port_vlan *vlan)
  278. {
  279. struct realtek_smi *smi = ds->priv;
  280. int ret;
  281. if (!smi->ops->is_vlan_valid(smi, port))
  282. return -EINVAL;
  283. dev_info(smi->dev, "prepare VLANs %04x..%04x\n",
  284. vlan->vid_begin, vlan->vid_end);
  285. /* Enable VLAN in the hardware
  286. * FIXME: what's with this 4k business?
  287. * Just rtl8366_enable_vlan() seems inconclusive.
  288. */
  289. ret = rtl8366_enable_vlan4k(smi, true);
  290. if (ret)
  291. return ret;
  292. return 0;
  293. }
  294. EXPORT_SYMBOL_GPL(rtl8366_vlan_prepare);
  295. void rtl8366_vlan_add(struct dsa_switch *ds, int port,
  296. const struct switchdev_obj_port_vlan *vlan)
  297. {
  298. bool untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
  299. bool pvid = !!(vlan->flags & BRIDGE_VLAN_INFO_PVID);
  300. struct realtek_smi *smi = ds->priv;
  301. u32 member = 0;
  302. u32 untag = 0;
  303. u16 vid;
  304. int ret;
  305. if (!smi->ops->is_vlan_valid(smi, port))
  306. return;
  307. dev_info(smi->dev, "add VLAN on port %d, %s, %s\n",
  308. port,
  309. untagged ? "untagged" : "tagged",
  310. pvid ? " PVID" : "no PVID");
  311. if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
  312. dev_err(smi->dev, "port is DSA or CPU port\n");
  313. for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
  314. int pvid_val = 0;
  315. dev_info(smi->dev, "add VLAN %04x\n", vid);
  316. member |= BIT(port);
  317. if (untagged)
  318. untag |= BIT(port);
  319. /* To ensure that we have a valid MC entry for this VLAN,
  320. * initialize the port VLAN ID here.
  321. */
  322. ret = rtl8366_get_pvid(smi, port, &pvid_val);
  323. if (ret < 0) {
  324. dev_err(smi->dev, "could not lookup PVID for port %d\n",
  325. port);
  326. return;
  327. }
  328. if (pvid_val == 0) {
  329. ret = rtl8366_set_pvid(smi, port, vid);
  330. if (ret < 0)
  331. return;
  332. }
  333. }
  334. ret = rtl8366_set_vlan(smi, port, member, untag, 0);
  335. if (ret)
  336. dev_err(smi->dev,
  337. "failed to set up VLAN %04x",
  338. vid);
  339. }
  340. EXPORT_SYMBOL_GPL(rtl8366_vlan_add);
  341. int rtl8366_vlan_del(struct dsa_switch *ds, int port,
  342. const struct switchdev_obj_port_vlan *vlan)
  343. {
  344. struct realtek_smi *smi = ds->priv;
  345. u16 vid;
  346. int ret;
  347. dev_info(smi->dev, "del VLAN on port %d\n", port);
  348. for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
  349. int i;
  350. dev_info(smi->dev, "del VLAN %04x\n", vid);
  351. for (i = 0; i < smi->num_vlan_mc; i++) {
  352. struct rtl8366_vlan_mc vlanmc;
  353. ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
  354. if (ret)
  355. return ret;
  356. if (vid == vlanmc.vid) {
  357. /* clear VLAN member configurations */
  358. vlanmc.vid = 0;
  359. vlanmc.priority = 0;
  360. vlanmc.member = 0;
  361. vlanmc.untag = 0;
  362. vlanmc.fid = 0;
  363. ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
  364. if (ret) {
  365. dev_err(smi->dev,
  366. "failed to remove VLAN %04x\n",
  367. vid);
  368. return ret;
  369. }
  370. break;
  371. }
  372. }
  373. }
  374. return 0;
  375. }
  376. EXPORT_SYMBOL_GPL(rtl8366_vlan_del);
  377. void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
  378. uint8_t *data)
  379. {
  380. struct realtek_smi *smi = ds->priv;
  381. struct rtl8366_mib_counter *mib;
  382. int i;
  383. if (port >= smi->num_ports)
  384. return;
  385. for (i = 0; i < smi->num_mib_counters; i++) {
  386. mib = &smi->mib_counters[i];
  387. strncpy(data + i * ETH_GSTRING_LEN,
  388. mib->name, ETH_GSTRING_LEN);
  389. }
  390. }
  391. EXPORT_SYMBOL_GPL(rtl8366_get_strings);
  392. int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset)
  393. {
  394. struct realtek_smi *smi = ds->priv;
  395. /* We only support SS_STATS */
  396. if (sset != ETH_SS_STATS)
  397. return 0;
  398. if (port >= smi->num_ports)
  399. return -EINVAL;
  400. return smi->num_mib_counters;
  401. }
  402. EXPORT_SYMBOL_GPL(rtl8366_get_sset_count);
  403. void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
  404. {
  405. struct realtek_smi *smi = ds->priv;
  406. int i;
  407. int ret;
  408. if (port >= smi->num_ports)
  409. return;
  410. for (i = 0; i < smi->num_mib_counters; i++) {
  411. struct rtl8366_mib_counter *mib;
  412. u64 mibvalue = 0;
  413. mib = &smi->mib_counters[i];
  414. ret = smi->ops->get_mib_counter(smi, port, mib, &mibvalue);
  415. if (ret) {
  416. dev_err(smi->dev, "error reading MIB counter %s\n",
  417. mib->name);
  418. }
  419. data[i] = mibvalue;
  420. }
  421. }
  422. EXPORT_SYMBOL_GPL(rtl8366_get_ethtool_stats);