rtl8366.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  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-core.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. /**
  33. * rtl8366_obtain_mc() - retrieve or allocate a VLAN member configuration
  34. * @smi: the Realtek SMI device instance
  35. * @vid: the VLAN ID to look up or allocate
  36. * @vlanmc: the pointer will be assigned to a pointer to a valid member config
  37. * if successful
  38. * @return: index of a new member config or negative error number
  39. */
  40. static int rtl8366_obtain_mc(struct realtek_smi *smi, int vid,
  41. struct rtl8366_vlan_mc *vlanmc)
  42. {
  43. struct rtl8366_vlan_4k vlan4k;
  44. int ret;
  45. int i;
  46. /* Try to find an existing member config entry for this VID */
  47. for (i = 0; i < smi->num_vlan_mc; i++) {
  48. ret = smi->ops->get_vlan_mc(smi, i, vlanmc);
  49. if (ret) {
  50. dev_err(smi->dev, "error searching for VLAN MC %d for VID %d\n",
  51. i, vid);
  52. return ret;
  53. }
  54. if (vid == vlanmc->vid)
  55. return i;
  56. }
  57. /* We have no MC entry for this VID, try to find an empty one */
  58. for (i = 0; i < smi->num_vlan_mc; i++) {
  59. ret = smi->ops->get_vlan_mc(smi, i, vlanmc);
  60. if (ret) {
  61. dev_err(smi->dev, "error searching for VLAN MC %d for VID %d\n",
  62. i, vid);
  63. return ret;
  64. }
  65. if (vlanmc->vid == 0 && vlanmc->member == 0) {
  66. /* Update the entry from the 4K table */
  67. ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
  68. if (ret) {
  69. dev_err(smi->dev, "error looking for 4K VLAN MC %d for VID %d\n",
  70. i, vid);
  71. return ret;
  72. }
  73. vlanmc->vid = vid;
  74. vlanmc->member = vlan4k.member;
  75. vlanmc->untag = vlan4k.untag;
  76. vlanmc->fid = vlan4k.fid;
  77. ret = smi->ops->set_vlan_mc(smi, i, vlanmc);
  78. if (ret) {
  79. dev_err(smi->dev, "unable to set/update VLAN MC %d for VID %d\n",
  80. i, vid);
  81. return ret;
  82. }
  83. dev_dbg(smi->dev, "created new MC at index %d for VID %d\n",
  84. i, vid);
  85. return i;
  86. }
  87. }
  88. /* MC table is full, try to find an unused entry and replace it */
  89. for (i = 0; i < smi->num_vlan_mc; i++) {
  90. int used;
  91. ret = rtl8366_mc_is_used(smi, i, &used);
  92. if (ret)
  93. return ret;
  94. if (!used) {
  95. /* Update the entry from the 4K table */
  96. ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
  97. if (ret)
  98. return ret;
  99. vlanmc->vid = vid;
  100. vlanmc->member = vlan4k.member;
  101. vlanmc->untag = vlan4k.untag;
  102. vlanmc->fid = vlan4k.fid;
  103. ret = smi->ops->set_vlan_mc(smi, i, vlanmc);
  104. if (ret) {
  105. dev_err(smi->dev, "unable to set/update VLAN MC %d for VID %d\n",
  106. i, vid);
  107. return ret;
  108. }
  109. dev_dbg(smi->dev, "recycled MC at index %i for VID %d\n",
  110. i, vid);
  111. return i;
  112. }
  113. }
  114. dev_err(smi->dev, "all VLAN member configurations are in use\n");
  115. return -ENOSPC;
  116. }
  117. int rtl8366_set_vlan(struct realtek_smi *smi, int vid, u32 member,
  118. u32 untag, u32 fid)
  119. {
  120. struct rtl8366_vlan_mc vlanmc;
  121. struct rtl8366_vlan_4k vlan4k;
  122. int mc;
  123. int ret;
  124. if (!smi->ops->is_vlan_valid(smi, vid))
  125. return -EINVAL;
  126. dev_dbg(smi->dev,
  127. "setting VLAN%d 4k members: 0x%02x, untagged: 0x%02x\n",
  128. vid, member, untag);
  129. /* Update the 4K table */
  130. ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
  131. if (ret)
  132. return ret;
  133. vlan4k.member |= member;
  134. vlan4k.untag |= untag;
  135. vlan4k.fid = fid;
  136. ret = smi->ops->set_vlan_4k(smi, &vlan4k);
  137. if (ret)
  138. return ret;
  139. dev_dbg(smi->dev,
  140. "resulting VLAN%d 4k members: 0x%02x, untagged: 0x%02x\n",
  141. vid, vlan4k.member, vlan4k.untag);
  142. /* Find or allocate a member config for this VID */
  143. ret = rtl8366_obtain_mc(smi, vid, &vlanmc);
  144. if (ret < 0)
  145. return ret;
  146. mc = ret;
  147. /* Update the MC entry */
  148. vlanmc.member |= member;
  149. vlanmc.untag |= untag;
  150. vlanmc.fid = fid;
  151. /* Commit updates to the MC entry */
  152. ret = smi->ops->set_vlan_mc(smi, mc, &vlanmc);
  153. if (ret)
  154. dev_err(smi->dev, "failed to commit changes to VLAN MC index %d for VID %d\n",
  155. mc, vid);
  156. else
  157. dev_dbg(smi->dev,
  158. "resulting VLAN%d MC members: 0x%02x, untagged: 0x%02x\n",
  159. vid, vlanmc.member, vlanmc.untag);
  160. return ret;
  161. }
  162. EXPORT_SYMBOL_GPL(rtl8366_set_vlan);
  163. int rtl8366_set_pvid(struct realtek_smi *smi, unsigned int port,
  164. unsigned int vid)
  165. {
  166. struct rtl8366_vlan_mc vlanmc;
  167. int mc;
  168. int ret;
  169. if (!smi->ops->is_vlan_valid(smi, vid))
  170. return -EINVAL;
  171. /* Find or allocate a member config for this VID */
  172. ret = rtl8366_obtain_mc(smi, vid, &vlanmc);
  173. if (ret < 0)
  174. return ret;
  175. mc = ret;
  176. ret = smi->ops->set_mc_index(smi, port, mc);
  177. if (ret) {
  178. dev_err(smi->dev, "set PVID: failed to set MC index %d for port %d\n",
  179. mc, port);
  180. return ret;
  181. }
  182. dev_dbg(smi->dev, "set PVID: the PVID for port %d set to %d using existing MC index %d\n",
  183. port, vid, mc);
  184. return 0;
  185. }
  186. EXPORT_SYMBOL_GPL(rtl8366_set_pvid);
  187. int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable)
  188. {
  189. int ret;
  190. /* To enable 4k VLAN, ordinary VLAN must be enabled first,
  191. * but if we disable 4k VLAN it is fine to leave ordinary
  192. * VLAN enabled.
  193. */
  194. if (enable) {
  195. /* Make sure VLAN is ON */
  196. ret = smi->ops->enable_vlan(smi, true);
  197. if (ret)
  198. return ret;
  199. smi->vlan_enabled = true;
  200. }
  201. ret = smi->ops->enable_vlan4k(smi, enable);
  202. if (ret)
  203. return ret;
  204. smi->vlan4k_enabled = enable;
  205. return 0;
  206. }
  207. EXPORT_SYMBOL_GPL(rtl8366_enable_vlan4k);
  208. int rtl8366_enable_vlan(struct realtek_smi *smi, bool enable)
  209. {
  210. int ret;
  211. ret = smi->ops->enable_vlan(smi, enable);
  212. if (ret)
  213. return ret;
  214. smi->vlan_enabled = enable;
  215. /* If we turn VLAN off, make sure that we turn off
  216. * 4k VLAN as well, if that happened to be on.
  217. */
  218. if (!enable) {
  219. smi->vlan4k_enabled = false;
  220. ret = smi->ops->enable_vlan4k(smi, false);
  221. }
  222. return ret;
  223. }
  224. EXPORT_SYMBOL_GPL(rtl8366_enable_vlan);
  225. int rtl8366_reset_vlan(struct realtek_smi *smi)
  226. {
  227. struct rtl8366_vlan_mc vlanmc;
  228. int ret;
  229. int i;
  230. rtl8366_enable_vlan(smi, false);
  231. rtl8366_enable_vlan4k(smi, false);
  232. /* Clear the 16 VLAN member configurations */
  233. vlanmc.vid = 0;
  234. vlanmc.priority = 0;
  235. vlanmc.member = 0;
  236. vlanmc.untag = 0;
  237. vlanmc.fid = 0;
  238. for (i = 0; i < smi->num_vlan_mc; i++) {
  239. ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
  240. if (ret)
  241. return ret;
  242. }
  243. return 0;
  244. }
  245. EXPORT_SYMBOL_GPL(rtl8366_reset_vlan);
  246. int rtl8366_init_vlan(struct realtek_smi *smi)
  247. {
  248. int port;
  249. int ret;
  250. ret = rtl8366_reset_vlan(smi);
  251. if (ret)
  252. return ret;
  253. /* Loop over the available ports, for each port, associate
  254. * it with the VLAN (port+1)
  255. */
  256. for (port = 0; port < smi->num_ports; port++) {
  257. u32 mask;
  258. if (port == smi->cpu_port)
  259. /* For the CPU port, make all ports members of this
  260. * VLAN.
  261. */
  262. mask = GENMASK(smi->num_ports - 1, 0);
  263. else
  264. /* For all other ports, enable itself plus the
  265. * CPU port.
  266. */
  267. mask = BIT(port) | BIT(smi->cpu_port);
  268. /* For each port, set the port as member of VLAN (port+1)
  269. * and untagged, except for the CPU port: the CPU port (5) is
  270. * member of VLAN 6 and so are ALL the other ports as well.
  271. * Use filter 0 (no filter).
  272. */
  273. dev_info(smi->dev, "VLAN%d port mask for port %d, %08x\n",
  274. (port + 1), port, mask);
  275. ret = rtl8366_set_vlan(smi, (port + 1), mask, mask, 0);
  276. if (ret)
  277. return ret;
  278. dev_info(smi->dev, "VLAN%d port %d, PVID set to %d\n",
  279. (port + 1), port, (port + 1));
  280. ret = rtl8366_set_pvid(smi, port, (port + 1));
  281. if (ret)
  282. return ret;
  283. }
  284. return rtl8366_enable_vlan(smi, true);
  285. }
  286. EXPORT_SYMBOL_GPL(rtl8366_init_vlan);
  287. int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
  288. {
  289. struct realtek_smi *smi = ds->priv;
  290. struct rtl8366_vlan_4k vlan4k;
  291. int ret;
  292. /* Use VLAN nr port + 1 since VLAN0 is not valid */
  293. if (!smi->ops->is_vlan_valid(smi, port + 1))
  294. return -EINVAL;
  295. dev_info(smi->dev, "%s filtering on port %d\n",
  296. vlan_filtering ? "enable" : "disable",
  297. port);
  298. /* TODO:
  299. * The hardware support filter ID (FID) 0..7, I have no clue how to
  300. * support this in the driver when the callback only says on/off.
  301. */
  302. ret = smi->ops->get_vlan_4k(smi, port + 1, &vlan4k);
  303. if (ret)
  304. return ret;
  305. /* Just set the filter to FID 1 for now then */
  306. ret = rtl8366_set_vlan(smi, port + 1,
  307. vlan4k.member,
  308. vlan4k.untag,
  309. 1);
  310. if (ret)
  311. return ret;
  312. return 0;
  313. }
  314. EXPORT_SYMBOL_GPL(rtl8366_vlan_filtering);
  315. int rtl8366_vlan_prepare(struct dsa_switch *ds, int port,
  316. const struct switchdev_obj_port_vlan *vlan)
  317. {
  318. struct realtek_smi *smi = ds->priv;
  319. u16 vid;
  320. int ret;
  321. for (vid = vlan->vid_begin; vid < vlan->vid_end; vid++)
  322. if (!smi->ops->is_vlan_valid(smi, vid))
  323. return -EINVAL;
  324. dev_info(smi->dev, "prepare VLANs %04x..%04x\n",
  325. vlan->vid_begin, vlan->vid_end);
  326. /* Enable VLAN in the hardware
  327. * FIXME: what's with this 4k business?
  328. * Just rtl8366_enable_vlan() seems inconclusive.
  329. */
  330. ret = rtl8366_enable_vlan4k(smi, true);
  331. if (ret)
  332. return ret;
  333. return 0;
  334. }
  335. EXPORT_SYMBOL_GPL(rtl8366_vlan_prepare);
  336. void rtl8366_vlan_add(struct dsa_switch *ds, int port,
  337. const struct switchdev_obj_port_vlan *vlan)
  338. {
  339. bool untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
  340. bool pvid = !!(vlan->flags & BRIDGE_VLAN_INFO_PVID);
  341. struct realtek_smi *smi = ds->priv;
  342. u32 member = 0;
  343. u32 untag = 0;
  344. u16 vid;
  345. int ret;
  346. for (vid = vlan->vid_begin; vid < vlan->vid_end; vid++)
  347. if (!smi->ops->is_vlan_valid(smi, vid))
  348. return;
  349. dev_info(smi->dev, "add VLAN %d on port %d, %s, %s\n",
  350. vlan->vid_begin,
  351. port,
  352. untagged ? "untagged" : "tagged",
  353. pvid ? " PVID" : "no PVID");
  354. if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
  355. dev_err(smi->dev, "port is DSA or CPU port\n");
  356. for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
  357. member |= BIT(port);
  358. if (untagged)
  359. untag |= BIT(port);
  360. ret = rtl8366_set_vlan(smi, vid, member, untag, 0);
  361. if (ret)
  362. dev_err(smi->dev,
  363. "failed to set up VLAN %04x",
  364. vid);
  365. if (!pvid)
  366. continue;
  367. ret = rtl8366_set_pvid(smi, port, vid);
  368. if (ret)
  369. dev_err(smi->dev,
  370. "failed to set PVID on port %d to VLAN %04x",
  371. port, vid);
  372. if (!ret)
  373. dev_dbg(smi->dev, "VLAN add: added VLAN %d with PVID on port %d\n",
  374. vid, port);
  375. }
  376. }
  377. EXPORT_SYMBOL_GPL(rtl8366_vlan_add);
  378. int rtl8366_vlan_del(struct dsa_switch *ds, int port,
  379. const struct switchdev_obj_port_vlan *vlan)
  380. {
  381. struct realtek_smi *smi = ds->priv;
  382. u16 vid;
  383. int ret;
  384. dev_info(smi->dev, "del VLAN on port %d\n", port);
  385. for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
  386. int i;
  387. dev_info(smi->dev, "del VLAN %04x\n", vid);
  388. for (i = 0; i < smi->num_vlan_mc; i++) {
  389. struct rtl8366_vlan_mc vlanmc;
  390. ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
  391. if (ret)
  392. return ret;
  393. if (vid == vlanmc.vid) {
  394. /* Remove this port from the VLAN */
  395. vlanmc.member &= ~BIT(port);
  396. vlanmc.untag &= ~BIT(port);
  397. /*
  398. * If no ports are members of this VLAN
  399. * anymore then clear the whole member
  400. * config so it can be reused.
  401. */
  402. if (!vlanmc.member && vlanmc.untag) {
  403. vlanmc.vid = 0;
  404. vlanmc.priority = 0;
  405. vlanmc.fid = 0;
  406. }
  407. ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
  408. if (ret) {
  409. dev_err(smi->dev,
  410. "failed to remove VLAN %04x\n",
  411. vid);
  412. return ret;
  413. }
  414. break;
  415. }
  416. }
  417. }
  418. return 0;
  419. }
  420. EXPORT_SYMBOL_GPL(rtl8366_vlan_del);
  421. void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
  422. uint8_t *data)
  423. {
  424. struct realtek_smi *smi = ds->priv;
  425. struct rtl8366_mib_counter *mib;
  426. int i;
  427. if (port >= smi->num_ports)
  428. return;
  429. for (i = 0; i < smi->num_mib_counters; i++) {
  430. mib = &smi->mib_counters[i];
  431. strncpy(data + i * ETH_GSTRING_LEN,
  432. mib->name, ETH_GSTRING_LEN);
  433. }
  434. }
  435. EXPORT_SYMBOL_GPL(rtl8366_get_strings);
  436. int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset)
  437. {
  438. struct realtek_smi *smi = ds->priv;
  439. /* We only support SS_STATS */
  440. if (sset != ETH_SS_STATS)
  441. return 0;
  442. if (port >= smi->num_ports)
  443. return -EINVAL;
  444. return smi->num_mib_counters;
  445. }
  446. EXPORT_SYMBOL_GPL(rtl8366_get_sset_count);
  447. void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
  448. {
  449. struct realtek_smi *smi = ds->priv;
  450. int i;
  451. int ret;
  452. if (port >= smi->num_ports)
  453. return;
  454. for (i = 0; i < smi->num_mib_counters; i++) {
  455. struct rtl8366_mib_counter *mib;
  456. u64 mibvalue = 0;
  457. mib = &smi->mib_counters[i];
  458. ret = smi->ops->get_mib_counter(smi, port, mib, &mibvalue);
  459. if (ret) {
  460. dev_err(smi->dev, "error reading MIB counter %s\n",
  461. mib->name);
  462. }
  463. data[i] = mibvalue;
  464. }
  465. }
  466. EXPORT_SYMBOL_GPL(rtl8366_get_ethtool_stats);