/drivers/net/dsa/mv88e6xxx/global1_vtu.c

https://github.com/srikard/linux · C · 690 lines · 474 code · 160 blank · 56 comment · 86 complexity · c9395c1a2a9ba8b8c6463ec783051a23 MD5 · raw file

  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support
  4. *
  5. * Copyright (c) 2008 Marvell Semiconductor
  6. * Copyright (c) 2015 CMC Electronics, Inc.
  7. * Copyright (c) 2017 Savoir-faire Linux, Inc.
  8. */
  9. #include <linux/bitfield.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/irqdomain.h>
  12. #include "chip.h"
  13. #include "global1.h"
  14. /* Offset 0x02: VTU FID Register */
  15. static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
  16. struct mv88e6xxx_vtu_entry *entry)
  17. {
  18. u16 val;
  19. int err;
  20. err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
  21. if (err)
  22. return err;
  23. entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
  24. return 0;
  25. }
  26. static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
  27. struct mv88e6xxx_vtu_entry *entry)
  28. {
  29. u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK;
  30. return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val);
  31. }
  32. /* Offset 0x03: VTU SID Register */
  33. static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip,
  34. struct mv88e6xxx_vtu_entry *entry)
  35. {
  36. u16 val;
  37. int err;
  38. err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val);
  39. if (err)
  40. return err;
  41. entry->sid = val & MV88E6352_G1_VTU_SID_MASK;
  42. return 0;
  43. }
  44. static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip,
  45. struct mv88e6xxx_vtu_entry *entry)
  46. {
  47. u16 val = entry->sid & MV88E6352_G1_VTU_SID_MASK;
  48. return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val);
  49. }
  50. /* Offset 0x05: VTU Operation Register */
  51. static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
  52. {
  53. int bit = __bf_shf(MV88E6XXX_G1_VTU_OP_BUSY);
  54. return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_VTU_OP, bit, 0);
  55. }
  56. static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
  57. {
  58. int err;
  59. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP,
  60. MV88E6XXX_G1_VTU_OP_BUSY | op);
  61. if (err)
  62. return err;
  63. return mv88e6xxx_g1_vtu_op_wait(chip);
  64. }
  65. /* Offset 0x06: VTU VID Register */
  66. static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
  67. struct mv88e6xxx_vtu_entry *entry)
  68. {
  69. u16 val;
  70. int err;
  71. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val);
  72. if (err)
  73. return err;
  74. entry->vid = val & 0xfff;
  75. if (val & MV88E6390_G1_VTU_VID_PAGE)
  76. entry->vid |= 0x1000;
  77. entry->valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID);
  78. return 0;
  79. }
  80. static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
  81. struct mv88e6xxx_vtu_entry *entry)
  82. {
  83. u16 val = entry->vid & 0xfff;
  84. if (entry->vid & 0x1000)
  85. val |= MV88E6390_G1_VTU_VID_PAGE;
  86. if (entry->valid)
  87. val |= MV88E6XXX_G1_VTU_VID_VALID;
  88. return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val);
  89. }
  90. /* Offset 0x07: VTU/STU Data Register 1
  91. * Offset 0x08: VTU/STU Data Register 2
  92. * Offset 0x09: VTU/STU Data Register 3
  93. */
  94. static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
  95. u16 *regs)
  96. {
  97. int i;
  98. /* Read all 3 VTU/STU Data registers */
  99. for (i = 0; i < 3; ++i) {
  100. u16 *reg = &regs[i];
  101. int err;
  102. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
  103. if (err)
  104. return err;
  105. }
  106. return 0;
  107. }
  108. static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
  109. struct mv88e6xxx_vtu_entry *entry)
  110. {
  111. u16 regs[3];
  112. int err;
  113. int i;
  114. err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
  115. if (err)
  116. return err;
  117. /* Extract MemberTag data */
  118. for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
  119. unsigned int member_offset = (i % 4) * 4;
  120. entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
  121. }
  122. return 0;
  123. }
  124. static int mv88e6185_g1_stu_data_read(struct mv88e6xxx_chip *chip,
  125. struct mv88e6xxx_vtu_entry *entry)
  126. {
  127. u16 regs[3];
  128. int err;
  129. int i;
  130. err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
  131. if (err)
  132. return err;
  133. /* Extract PortState data */
  134. for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
  135. unsigned int state_offset = (i % 4) * 4 + 2;
  136. entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
  137. }
  138. return 0;
  139. }
  140. static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
  141. struct mv88e6xxx_vtu_entry *entry)
  142. {
  143. u16 regs[3] = { 0 };
  144. int i;
  145. /* Insert MemberTag and PortState data */
  146. for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
  147. unsigned int member_offset = (i % 4) * 4;
  148. unsigned int state_offset = member_offset + 2;
  149. regs[i / 4] |= (entry->member[i] & 0x3) << member_offset;
  150. regs[i / 4] |= (entry->state[i] & 0x3) << state_offset;
  151. }
  152. /* Write all 3 VTU/STU Data registers */
  153. for (i = 0; i < 3; ++i) {
  154. u16 reg = regs[i];
  155. int err;
  156. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
  157. if (err)
  158. return err;
  159. }
  160. return 0;
  161. }
  162. static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
  163. {
  164. u16 regs[2];
  165. int i;
  166. /* Read the 2 VTU/STU Data registers */
  167. for (i = 0; i < 2; ++i) {
  168. u16 *reg = &regs[i];
  169. int err;
  170. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
  171. if (err)
  172. return err;
  173. }
  174. /* Extract data */
  175. for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
  176. unsigned int offset = (i % 8) * 2;
  177. data[i] = (regs[i / 8] >> offset) & 0x3;
  178. }
  179. return 0;
  180. }
  181. static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
  182. {
  183. u16 regs[2] = { 0 };
  184. int i;
  185. /* Insert data */
  186. for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
  187. unsigned int offset = (i % 8) * 2;
  188. regs[i / 8] |= (data[i] & 0x3) << offset;
  189. }
  190. /* Write the 2 VTU/STU Data registers */
  191. for (i = 0; i < 2; ++i) {
  192. u16 reg = regs[i];
  193. int err;
  194. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
  195. if (err)
  196. return err;
  197. }
  198. return 0;
  199. }
  200. /* VLAN Translation Unit Operations */
  201. static int mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip *chip,
  202. struct mv88e6xxx_vtu_entry *entry)
  203. {
  204. int err;
  205. err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
  206. if (err)
  207. return err;
  208. err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
  209. if (err)
  210. return err;
  211. err = mv88e6xxx_g1_vtu_sid_read(chip, entry);
  212. if (err)
  213. return err;
  214. return mv88e6xxx_g1_vtu_vid_read(chip, entry);
  215. }
  216. static int mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip *chip,
  217. struct mv88e6xxx_vtu_entry *vtu)
  218. {
  219. struct mv88e6xxx_vtu_entry stu;
  220. int err;
  221. err = mv88e6xxx_g1_vtu_sid_read(chip, vtu);
  222. if (err)
  223. return err;
  224. stu.sid = vtu->sid - 1;
  225. err = mv88e6xxx_g1_vtu_stu_getnext(chip, &stu);
  226. if (err)
  227. return err;
  228. if (stu.sid != vtu->sid || !stu.valid)
  229. return -EINVAL;
  230. return 0;
  231. }
  232. static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
  233. struct mv88e6xxx_vtu_entry *entry)
  234. {
  235. int err;
  236. err = mv88e6xxx_g1_vtu_op_wait(chip);
  237. if (err)
  238. return err;
  239. /* To get the next higher active VID, the VTU GetNext operation can be
  240. * started again without setting the VID registers since it already
  241. * contains the last VID.
  242. *
  243. * To save a few hardware accesses and abstract this to the caller,
  244. * write the VID only once, when the entry is given as invalid.
  245. */
  246. if (!entry->valid) {
  247. err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
  248. if (err)
  249. return err;
  250. }
  251. err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
  252. if (err)
  253. return err;
  254. return mv88e6xxx_g1_vtu_vid_read(chip, entry);
  255. }
  256. int mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
  257. struct mv88e6xxx_vtu_entry *entry)
  258. {
  259. u16 val;
  260. int err;
  261. err = mv88e6xxx_g1_vtu_getnext(chip, entry);
  262. if (err)
  263. return err;
  264. if (entry->valid) {
  265. err = mv88e6185_g1_vtu_data_read(chip, entry);
  266. if (err)
  267. return err;
  268. /* VTU DBNum[3:0] are located in VTU Operation 3:0
  269. * VTU DBNum[5:4] are located in VTU Operation 9:8
  270. */
  271. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
  272. if (err)
  273. return err;
  274. entry->fid = val & 0x000f;
  275. entry->fid |= (val & 0x0300) >> 4;
  276. }
  277. return 0;
  278. }
  279. int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
  280. struct mv88e6xxx_vtu_entry *entry)
  281. {
  282. u16 val;
  283. int err;
  284. err = mv88e6xxx_g1_vtu_getnext(chip, entry);
  285. if (err)
  286. return err;
  287. if (entry->valid) {
  288. err = mv88e6185_g1_vtu_data_read(chip, entry);
  289. if (err)
  290. return err;
  291. err = mv88e6185_g1_stu_data_read(chip, entry);
  292. if (err)
  293. return err;
  294. /* VTU DBNum[3:0] are located in VTU Operation 3:0
  295. * VTU DBNum[7:4] are located in VTU Operation 11:8
  296. */
  297. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
  298. if (err)
  299. return err;
  300. entry->fid = val & 0x000f;
  301. entry->fid |= (val & 0x0f00) >> 4;
  302. }
  303. return 0;
  304. }
  305. int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
  306. struct mv88e6xxx_vtu_entry *entry)
  307. {
  308. int err;
  309. /* Fetch VLAN MemberTag data from the VTU */
  310. err = mv88e6xxx_g1_vtu_getnext(chip, entry);
  311. if (err)
  312. return err;
  313. if (entry->valid) {
  314. err = mv88e6185_g1_vtu_data_read(chip, entry);
  315. if (err)
  316. return err;
  317. err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
  318. if (err)
  319. return err;
  320. /* Fetch VLAN PortState data from the STU */
  321. err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
  322. if (err)
  323. return err;
  324. err = mv88e6185_g1_stu_data_read(chip, entry);
  325. if (err)
  326. return err;
  327. }
  328. return 0;
  329. }
  330. int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
  331. struct mv88e6xxx_vtu_entry *entry)
  332. {
  333. int err;
  334. /* Fetch VLAN MemberTag data from the VTU */
  335. err = mv88e6xxx_g1_vtu_getnext(chip, entry);
  336. if (err)
  337. return err;
  338. if (entry->valid) {
  339. err = mv88e6390_g1_vtu_data_read(chip, entry->member);
  340. if (err)
  341. return err;
  342. /* Fetch VLAN PortState data from the STU */
  343. err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
  344. if (err)
  345. return err;
  346. err = mv88e6390_g1_vtu_data_read(chip, entry->state);
  347. if (err)
  348. return err;
  349. err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
  350. if (err)
  351. return err;
  352. }
  353. return 0;
  354. }
  355. int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
  356. struct mv88e6xxx_vtu_entry *entry)
  357. {
  358. u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
  359. int err;
  360. err = mv88e6xxx_g1_vtu_op_wait(chip);
  361. if (err)
  362. return err;
  363. err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
  364. if (err)
  365. return err;
  366. if (entry->valid) {
  367. err = mv88e6185_g1_vtu_data_write(chip, entry);
  368. if (err)
  369. return err;
  370. /* VTU DBNum[3:0] are located in VTU Operation 3:0
  371. * VTU DBNum[5:4] are located in VTU Operation 9:8
  372. */
  373. op |= entry->fid & 0x000f;
  374. op |= (entry->fid & 0x0030) << 4;
  375. }
  376. return mv88e6xxx_g1_vtu_op(chip, op);
  377. }
  378. int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
  379. struct mv88e6xxx_vtu_entry *entry)
  380. {
  381. u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
  382. int err;
  383. err = mv88e6xxx_g1_vtu_op_wait(chip);
  384. if (err)
  385. return err;
  386. err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
  387. if (err)
  388. return err;
  389. if (entry->valid) {
  390. err = mv88e6185_g1_vtu_data_write(chip, entry);
  391. if (err)
  392. return err;
  393. /* VTU DBNum[3:0] are located in VTU Operation 3:0
  394. * VTU DBNum[7:4] are located in VTU Operation 11:8
  395. */
  396. op |= entry->fid & 0x000f;
  397. op |= (entry->fid & 0x00f0) << 4;
  398. }
  399. return mv88e6xxx_g1_vtu_op(chip, op);
  400. }
  401. int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
  402. struct mv88e6xxx_vtu_entry *entry)
  403. {
  404. int err;
  405. err = mv88e6xxx_g1_vtu_op_wait(chip);
  406. if (err)
  407. return err;
  408. err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
  409. if (err)
  410. return err;
  411. if (entry->valid) {
  412. /* Write MemberTag and PortState data */
  413. err = mv88e6185_g1_vtu_data_write(chip, entry);
  414. if (err)
  415. return err;
  416. err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
  417. if (err)
  418. return err;
  419. /* Load STU entry */
  420. err = mv88e6xxx_g1_vtu_op(chip,
  421. MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
  422. if (err)
  423. return err;
  424. err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
  425. if (err)
  426. return err;
  427. }
  428. /* Load/Purge VTU entry */
  429. return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
  430. }
  431. int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
  432. struct mv88e6xxx_vtu_entry *entry)
  433. {
  434. int err;
  435. err = mv88e6xxx_g1_vtu_op_wait(chip);
  436. if (err)
  437. return err;
  438. err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
  439. if (err)
  440. return err;
  441. if (entry->valid) {
  442. /* Write PortState data */
  443. err = mv88e6390_g1_vtu_data_write(chip, entry->state);
  444. if (err)
  445. return err;
  446. err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
  447. if (err)
  448. return err;
  449. /* Load STU entry */
  450. err = mv88e6xxx_g1_vtu_op(chip,
  451. MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
  452. if (err)
  453. return err;
  454. /* Write MemberTag data */
  455. err = mv88e6390_g1_vtu_data_write(chip, entry->member);
  456. if (err)
  457. return err;
  458. err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
  459. if (err)
  460. return err;
  461. }
  462. /* Load/Purge VTU entry */
  463. return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
  464. }
  465. int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
  466. {
  467. int err;
  468. err = mv88e6xxx_g1_vtu_op_wait(chip);
  469. if (err)
  470. return err;
  471. return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
  472. }
  473. static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
  474. {
  475. struct mv88e6xxx_chip *chip = dev_id;
  476. struct mv88e6xxx_vtu_entry entry;
  477. int spid;
  478. int err;
  479. u16 val;
  480. mv88e6xxx_reg_lock(chip);
  481. err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
  482. if (err)
  483. goto out;
  484. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
  485. if (err)
  486. goto out;
  487. err = mv88e6xxx_g1_vtu_vid_read(chip, &entry);
  488. if (err)
  489. goto out;
  490. spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
  491. if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
  492. dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n",
  493. entry.vid, spid);
  494. chip->ports[spid].vtu_member_violation++;
  495. }
  496. if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
  497. dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n",
  498. entry.vid, spid);
  499. chip->ports[spid].vtu_miss_violation++;
  500. }
  501. mv88e6xxx_reg_unlock(chip);
  502. return IRQ_HANDLED;
  503. out:
  504. mv88e6xxx_reg_unlock(chip);
  505. dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
  506. err);
  507. return IRQ_HANDLED;
  508. }
  509. int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
  510. {
  511. int err;
  512. chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
  513. MV88E6XXX_G1_STS_IRQ_VTU_PROB);
  514. if (chip->vtu_prob_irq < 0)
  515. return chip->vtu_prob_irq;
  516. snprintf(chip->vtu_prob_irq_name, sizeof(chip->vtu_prob_irq_name),
  517. "mv88e6xxx-%s-g1-vtu-prob", dev_name(chip->dev));
  518. err = request_threaded_irq(chip->vtu_prob_irq, NULL,
  519. mv88e6xxx_g1_vtu_prob_irq_thread_fn,
  520. IRQF_ONESHOT, chip->vtu_prob_irq_name,
  521. chip);
  522. if (err)
  523. irq_dispose_mapping(chip->vtu_prob_irq);
  524. return err;
  525. }
  526. void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
  527. {
  528. free_irq(chip->vtu_prob_irq, chip);
  529. irq_dispose_mapping(chip->vtu_prob_irq);
  530. }