rtl8367s.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. /*
  2. * This program is free software; you can redistribute it and/or
  3. * modify it under the terms of the GNU General Public License
  4. * as published by the Free Software Foundation; either version 2
  5. * of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/init.h>
  16. #include <linux/device.h>
  17. #include <linux/delay.h>
  18. #include <linux/skbuff.h>
  19. #include <linux/switch.h>
  20. //include from rtl8367c dir
  21. #include "./rtl8367c/include/rtk_switch.h"
  22. #include "./rtl8367c/include/vlan.h"
  23. #include "./rtl8367c/include/stat.h"
  24. #include "./rtl8367c/include/port.h"
  25. #define RTL8367C_SW_CPU_PORT 6
  26. //RTL8367C_PHY_PORT_NUM + ext0 + ext1
  27. #define RTL8367C_NUM_PORTS 7
  28. #define RTL8367C_NUM_VIDS 4096
  29. struct rtl8367_priv {
  30. struct switch_dev swdev;
  31. bool global_vlan_enable;
  32. };
  33. struct rtl8367_mib_counter {
  34. const char *name;
  35. };
  36. struct rtl8367_vlan_info {
  37. unsigned short vid;
  38. unsigned int untag;
  39. unsigned int member;
  40. unsigned char fid;
  41. };
  42. struct rtl8367_priv rtl8367_priv_data;
  43. unsigned int rtl8367c_port_id[RTL8367C_NUM_PORTS]={0,1,2,3,4,EXT_PORT1,EXT_PORT0};
  44. void (*rtl8367_switch_reset_func)(void)=NULL;
  45. static struct rtl8367_mib_counter rtl8367c_mib_counters[] = {
  46. {"ifInOctets"},
  47. {"dot3StatsFCSErrors"},
  48. {"dot3StatsSymbolErrors"},
  49. {"dot3InPauseFrames"},
  50. {"dot3ControlInUnknownOpcodes"},
  51. {"etherStatsFragments"},
  52. {"etherStatsJabbers"},
  53. {"ifInUcastPkts"},
  54. {"etherStatsDropEvents"},
  55. {"etherStatsOctets"},
  56. {"etherStatsUndersizePkts"},
  57. {"etherStatsOversizePkts"},
  58. {"etherStatsPkts64Octets"},
  59. {"etherStatsPkts65to127Octets"},
  60. {"etherStatsPkts128to255Octets"},
  61. {"etherStatsPkts256to511Octets"},
  62. {"etherStatsPkts512to1023Octets"},
  63. {"etherStatsPkts1024toMaxOctets"},
  64. {"etherStatsMcastPkts"},
  65. {"etherStatsBcastPkts"},
  66. {"ifOutOctets"},
  67. {"dot3StatsSingleCollisionFrames"},
  68. {"dot3StatsMultipleCollisionFrames"},
  69. {"dot3StatsDeferredTransmissions"},
  70. {"dot3StatsLateCollisions"},
  71. {"etherStatsCollisions"},
  72. {"dot3StatsExcessiveCollisions"},
  73. {"dot3OutPauseFrames"},
  74. {"dot1dBasePortDelayExceededDiscards"},
  75. {"dot1dTpPortInDiscards"},
  76. {"ifOutUcastPkts"},
  77. {"ifOutMulticastPkts"},
  78. {"ifOutBrocastPkts"},
  79. {"outOampduPkts"},
  80. {"inOampduPkts"},
  81. {"pktgenPkts"},
  82. {"inMldChecksumError"},
  83. {"inIgmpChecksumError"},
  84. {"inMldSpecificQuery"},
  85. {"inMldGeneralQuery"},
  86. {"inIgmpSpecificQuery"},
  87. {"inIgmpGeneralQuery"},
  88. {"inMldLeaves"},
  89. {"inIgmpLeaves"},
  90. {"inIgmpJoinsSuccess"},
  91. {"inIgmpJoinsFail"},
  92. {"inMldJoinsSuccess"},
  93. {"inMldJoinsFail"},
  94. {"inReportSuppressionDrop"},
  95. {"inLeaveSuppressionDrop"},
  96. {"outIgmpReports"},
  97. {"outIgmpLeaves"},
  98. {"outIgmpGeneralQuery"},
  99. {"outIgmpSpecificQuery"},
  100. {"outMldReports"},
  101. {"outMldLeaves"},
  102. {"outMldGeneralQuery"},
  103. {"outMldSpecificQuery"},
  104. {"inKnownMulticastPkts"},
  105. {"ifInMulticastPkts"},
  106. {"ifInBroadcastPkts"},
  107. {"ifOutDiscards"}
  108. };
  109. /*rtl8367c proprietary switch API wrapper */
  110. static inline unsigned int rtl8367c_sw_to_phy_port(int port)
  111. {
  112. return rtl8367c_port_id[port];
  113. }
  114. static inline unsigned int rtl8367c_portmask_phy_to_sw(rtk_portmask_t phy_portmask)
  115. {
  116. int i;
  117. for (i = 0; i < RTL8367C_NUM_PORTS; i++) {
  118. if(RTK_PORTMASK_IS_PORT_SET(phy_portmask,rtl8367c_sw_to_phy_port(i))) {
  119. RTK_PORTMASK_PORT_CLEAR(phy_portmask,rtl8367c_sw_to_phy_port(i));
  120. RTK_PORTMASK_PORT_SET(phy_portmask,i);
  121. }
  122. }
  123. return (unsigned int)phy_portmask.bits[0];
  124. }
  125. static int rtl8367c_reset_mibs(void)
  126. {
  127. return rtk_stat_global_reset();
  128. }
  129. static int rtl8367c_reset_port_mibs(int port)
  130. {
  131. return rtk_stat_port_reset(rtl8367c_sw_to_phy_port(port));
  132. }
  133. static int rtl8367c_get_mibs_num(void)
  134. {
  135. return ARRAY_SIZE(rtl8367c_mib_counters);
  136. }
  137. static const char *rtl8367c_get_mib_name(int idx)
  138. {
  139. return rtl8367c_mib_counters[idx].name;
  140. }
  141. static int rtl8367c_get_port_mib_counter(int idx, int port, unsigned long long *counter)
  142. {
  143. return rtk_stat_port_get(rtl8367c_sw_to_phy_port(port), idx, counter);
  144. }
  145. static int rtl8367c_is_vlan_valid(unsigned int vlan)
  146. {
  147. unsigned max = RTL8367C_NUM_VIDS;
  148. if (vlan == 0 || vlan >= max)
  149. return 0;
  150. return 1;
  151. }
  152. static int rtl8367c_get_vlan( unsigned short vid, struct rtl8367_vlan_info *vlan)
  153. {
  154. rtk_vlan_cfg_t vlan_cfg;
  155. memset(vlan, '\0', sizeof(struct rtl8367_vlan_info));
  156. if (vid >= RTL8367C_NUM_VIDS)
  157. return -EINVAL;
  158. if(rtk_vlan_get(vid,&vlan_cfg))
  159. return -EINVAL;
  160. vlan->vid = vid;
  161. vlan->member = rtl8367c_portmask_phy_to_sw(vlan_cfg.mbr);
  162. vlan->untag = rtl8367c_portmask_phy_to_sw(vlan_cfg.untag);
  163. vlan->fid = vlan_cfg.fid_msti;
  164. return 0;
  165. }
  166. static int rtl8367c_set_vlan( unsigned short vid, u32 mbr, u32 untag, u8 fid)
  167. {
  168. rtk_vlan_cfg_t vlan_cfg;
  169. int i;
  170. memset(&vlan_cfg, 0x00, sizeof(rtk_vlan_cfg_t));
  171. for (i = 0; i < RTL8367C_NUM_PORTS; i++) {
  172. if (mbr & (1 << i)) {
  173. RTK_PORTMASK_PORT_SET(vlan_cfg.mbr, rtl8367c_sw_to_phy_port(i));
  174. if(untag & (1 << i))
  175. RTK_PORTMASK_PORT_SET(vlan_cfg.untag, rtl8367c_sw_to_phy_port(i));
  176. }
  177. }
  178. vlan_cfg.fid_msti=fid;
  179. vlan_cfg.ivl_en = 1;
  180. return rtk_vlan_set(vid, &vlan_cfg);
  181. }
  182. static int rtl8367c_get_pvid( int port, int *pvid)
  183. {
  184. u32 prio=0;
  185. if (port >= RTL8367C_NUM_PORTS)
  186. return -EINVAL;
  187. return rtk_vlan_portPvid_get(rtl8367c_sw_to_phy_port(port),pvid,&prio);
  188. }
  189. static int rtl8367c_set_pvid( int port, int pvid)
  190. {
  191. u32 prio=0;
  192. if (port >= RTL8367C_NUM_PORTS)
  193. return -EINVAL;
  194. return rtk_vlan_portPvid_set(rtl8367c_sw_to_phy_port(port),pvid,prio);
  195. }
  196. static int rtl8367c_get_port_link(int port, int *link, int *speed, int *duplex)
  197. {
  198. if(rtk_port_phyStatus_get(rtl8367c_sw_to_phy_port(port),(rtk_port_linkStatus_t *)link,
  199. (rtk_port_speed_t *)speed,(rtk_port_duplex_t *)duplex))
  200. return -EINVAL;
  201. return 0;
  202. }
  203. /*common rtl8367 swconfig entry API*/
  204. static int
  205. rtl8367_sw_set_vlan_enable(struct switch_dev *dev,
  206. const struct switch_attr *attr,
  207. struct switch_val *val)
  208. {
  209. struct rtl8367_priv *priv = container_of(dev, struct rtl8367_priv, swdev);
  210. priv->global_vlan_enable = val->value.i ;
  211. return 0;
  212. }
  213. static int
  214. rtl8367_sw_get_vlan_enable(struct switch_dev *dev,
  215. const struct switch_attr *attr,
  216. struct switch_val *val)
  217. {
  218. struct rtl8367_priv *priv = container_of(dev, struct rtl8367_priv, swdev);
  219. val->value.i = priv->global_vlan_enable;
  220. return 0;
  221. }
  222. static int rtl8367_sw_reset_mibs(struct switch_dev *dev,
  223. const struct switch_attr *attr,
  224. struct switch_val *val)
  225. {
  226. return rtl8367c_reset_mibs();
  227. }
  228. static int rtl8367_sw_reset_port_mibs(struct switch_dev *dev,
  229. const struct switch_attr *attr,
  230. struct switch_val *val)
  231. {
  232. int port;
  233. port = val->port_vlan;
  234. if (port >= RTL8367C_NUM_PORTS)
  235. return -EINVAL;
  236. return rtl8367c_reset_port_mibs(port);
  237. }
  238. static int rtl8367_sw_get_port_mib(struct switch_dev *dev,
  239. const struct switch_attr *attr,
  240. struct switch_val *val)
  241. {
  242. int i, len = 0;
  243. unsigned long long counter = 0;
  244. static char mib_buf[4096];
  245. if (val->port_vlan >= RTL8367C_NUM_PORTS)
  246. return -EINVAL;
  247. len += snprintf(mib_buf + len, sizeof(mib_buf) - len,
  248. "Port %d MIB counters\n",
  249. val->port_vlan);
  250. for (i = 0; i <rtl8367c_get_mibs_num(); ++i) {
  251. len += snprintf(mib_buf + len, sizeof(mib_buf) - len,
  252. "%-36s: ",rtl8367c_get_mib_name(i));
  253. if (!rtl8367c_get_port_mib_counter(i, val->port_vlan,
  254. &counter))
  255. len += snprintf(mib_buf + len, sizeof(mib_buf) - len,
  256. "%llu\n", counter);
  257. else
  258. len += snprintf(mib_buf + len, sizeof(mib_buf) - len,
  259. "%s\n", "N/A");
  260. }
  261. val->value.s = mib_buf;
  262. val->len = len;
  263. return 0;
  264. }
  265. static int rtl8367_sw_get_vlan_info(struct switch_dev *dev,
  266. const struct switch_attr *attr,
  267. struct switch_val *val)
  268. {
  269. int i;
  270. u32 len = 0;
  271. struct rtl8367_vlan_info vlan;
  272. static char vlan_buf[256];
  273. int err;
  274. if (!rtl8367c_is_vlan_valid(val->port_vlan))
  275. return -EINVAL;
  276. memset(vlan_buf, '\0', sizeof(vlan_buf));
  277. err = rtl8367c_get_vlan(val->port_vlan, &vlan);
  278. if (err)
  279. return err;
  280. len += snprintf(vlan_buf + len, sizeof(vlan_buf) - len,
  281. "VLAN %d: Ports: '", vlan.vid);
  282. for (i = 0; i <RTL8367C_NUM_PORTS; i++) {
  283. if (!(vlan.member & (1 << i)))
  284. continue;
  285. len += snprintf(vlan_buf + len, sizeof(vlan_buf) - len, "%d%s", i,
  286. (vlan.untag & (1 << i)) ? "" : "t");
  287. }
  288. len += snprintf(vlan_buf + len, sizeof(vlan_buf) - len,
  289. "', members=%04x, untag=%04x, fid=%u",
  290. vlan.member, vlan.untag, vlan.fid);
  291. val->value.s = vlan_buf;
  292. val->len = len;
  293. return 0;
  294. }
  295. static int rtl8367_sw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
  296. {
  297. struct switch_port *port;
  298. struct rtl8367_vlan_info vlan;
  299. int i;
  300. if (!rtl8367c_is_vlan_valid(val->port_vlan))
  301. return -EINVAL;
  302. if(rtl8367c_get_vlan(val->port_vlan, &vlan))
  303. return -EINVAL;
  304. port = &val->value.ports[0];
  305. val->len = 0;
  306. for (i = 0; i <RTL8367C_NUM_PORTS ; i++) {
  307. if (!(vlan.member & BIT(i)))
  308. continue;
  309. port->id = i;
  310. port->flags = (vlan.untag & BIT(i)) ?
  311. 0 : BIT(SWITCH_PORT_FLAG_TAGGED);
  312. val->len++;
  313. port++;
  314. }
  315. return 0;
  316. }
  317. static int rtl8367_sw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val)
  318. {
  319. struct switch_port *port;
  320. u32 member = 0;
  321. u32 untag = 0;
  322. u8 fid=0;
  323. int err;
  324. int i;
  325. if (!rtl8367c_is_vlan_valid(val->port_vlan))
  326. return -EINVAL;
  327. port = &val->value.ports[0];
  328. for (i = 0; i < val->len; i++, port++) {
  329. int pvid = 0;
  330. member |= BIT(port->id);
  331. if (!(port->flags & BIT(SWITCH_PORT_FLAG_TAGGED)))
  332. untag |= BIT(port->id);
  333. /*
  334. * To ensure that we have a valid MC entry for this VLAN,
  335. * initialize the port VLAN ID here.
  336. */
  337. err = rtl8367c_get_pvid(port->id, &pvid);
  338. if (err < 0)
  339. return err;
  340. if (pvid == 0) {
  341. err = rtl8367c_set_pvid(port->id, val->port_vlan);
  342. if (err < 0)
  343. return err;
  344. }
  345. }
  346. //pr_info("[%s] vid=%d , mem=%x,untag=%x,fid=%d \n",__func__,val->port_vlan,member,untag,fid);
  347. return rtl8367c_set_vlan(val->port_vlan, member, untag, fid);
  348. }
  349. static int rtl8367_sw_get_port_pvid(struct switch_dev *dev, int port, int *val)
  350. {
  351. return rtl8367c_get_pvid(port, val);
  352. }
  353. static int rtl8367_sw_set_port_pvid(struct switch_dev *dev, int port, int val)
  354. {
  355. return rtl8367c_set_pvid(port, val);
  356. }
  357. static int rtl8367_sw_reset_switch(struct switch_dev *dev)
  358. {
  359. if(rtl8367_switch_reset_func)
  360. (*rtl8367_switch_reset_func)();
  361. else
  362. printk("rest switch is not supported\n");
  363. return 0;
  364. }
  365. static int rtl8367_sw_get_port_link(struct switch_dev *dev, int port,
  366. struct switch_port_link *link)
  367. {
  368. int speed;
  369. if (port >= RTL8367C_NUM_PORTS)
  370. return -EINVAL;
  371. if(rtl8367c_get_port_link(port,(int *)&link->link,(int *)&speed,(int *)&link->duplex))
  372. return -EINVAL;
  373. if (!link->link)
  374. return 0;
  375. switch (speed) {
  376. case 0:
  377. link->speed = SWITCH_PORT_SPEED_10;
  378. break;
  379. case 1:
  380. link->speed = SWITCH_PORT_SPEED_100;
  381. break;
  382. case 2:
  383. link->speed = SWITCH_PORT_SPEED_1000;
  384. break;
  385. default:
  386. link->speed = SWITCH_PORT_SPEED_UNKNOWN;
  387. break;
  388. }
  389. return 0;
  390. }
  391. static struct switch_attr rtl8367_globals[] = {
  392. {
  393. .type = SWITCH_TYPE_INT,
  394. .name = "enable_vlan",
  395. .description = "Enable VLAN mode",
  396. .set = rtl8367_sw_set_vlan_enable,
  397. .get = rtl8367_sw_get_vlan_enable,
  398. .max = 1,
  399. }, {
  400. .type = SWITCH_TYPE_NOVAL,
  401. .name = "reset_mibs",
  402. .description = "Reset all MIB counters",
  403. .set = rtl8367_sw_reset_mibs,
  404. }
  405. };
  406. static struct switch_attr rtl8367_port[] = {
  407. {
  408. .type = SWITCH_TYPE_NOVAL,
  409. .name = "reset_mib",
  410. .description = "Reset single port MIB counters",
  411. .set = rtl8367_sw_reset_port_mibs,
  412. }, {
  413. .type = SWITCH_TYPE_STRING,
  414. .name = "mib",
  415. .description = "Get MIB counters for port",
  416. //.max = 33,
  417. .set = NULL,
  418. .get = rtl8367_sw_get_port_mib,
  419. },
  420. };
  421. static struct switch_attr rtl8367_vlan[] = {
  422. {
  423. .type = SWITCH_TYPE_STRING,
  424. .name = "info",
  425. .description = "Get vlan information",
  426. .max = 1,
  427. .set = NULL,
  428. .get = rtl8367_sw_get_vlan_info,
  429. },
  430. };
  431. static const struct switch_dev_ops rtl8367_sw_ops = {
  432. .attr_global = {
  433. .attr = rtl8367_globals,
  434. .n_attr = ARRAY_SIZE(rtl8367_globals),
  435. },
  436. .attr_port = {
  437. .attr = rtl8367_port,
  438. .n_attr = ARRAY_SIZE(rtl8367_port),
  439. },
  440. .attr_vlan = {
  441. .attr = rtl8367_vlan,
  442. .n_attr = ARRAY_SIZE(rtl8367_vlan),
  443. },
  444. .get_vlan_ports = rtl8367_sw_get_vlan_ports,
  445. .set_vlan_ports = rtl8367_sw_set_vlan_ports,
  446. .get_port_pvid = rtl8367_sw_get_port_pvid,
  447. .set_port_pvid = rtl8367_sw_set_port_pvid,
  448. .reset_switch = rtl8367_sw_reset_switch,
  449. .get_port_link = rtl8367_sw_get_port_link,
  450. };
  451. int rtl8367s_swconfig_init(void (*reset_func)(void))
  452. {
  453. struct rtl8367_priv *priv = &rtl8367_priv_data;
  454. struct switch_dev *dev=&priv->swdev;
  455. int err=0;
  456. rtl8367_switch_reset_func = reset_func ;
  457. memset(priv, 0, sizeof(struct rtl8367_priv));
  458. priv->global_vlan_enable =0;
  459. dev->name = "RTL8367C";
  460. dev->cpu_port = RTL8367C_SW_CPU_PORT;
  461. dev->ports = RTL8367C_NUM_PORTS;
  462. dev->vlans = RTL8367C_NUM_VIDS;
  463. dev->ops = &rtl8367_sw_ops;
  464. dev->alias = "RTL8367C";
  465. err = register_switch(dev, NULL);
  466. pr_info("[%s]\n",__func__);
  467. return err;
  468. }