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.
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.
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/device.h>
18 #include <linux/delay.h>
19 #include <linux/skbuff.h>
20 #include <linux/switch.h>
22 //include from rtl8367c dir
23 #include "./rtl8367c/include/rtk_switch.h"
24 #include "./rtl8367c/include/vlan.h"
25 #include "./rtl8367c/include/stat.h"
26 #include "./rtl8367c/include/port.h"
28 #define RTL8367C_SW_CPU_PORT 6
30 //RTL8367C_PHY_PORT_NUM + ext0 + ext1
31 #define RTL8367C_NUM_PORTS 7
32 #define RTL8367C_NUM_VIDS 4096
35 struct switch_dev swdev
;
36 bool global_vlan_enable
;
39 struct rtl8367_mib_counter
{
43 struct rtl8367_vlan_info
{
50 struct rtl8367_priv rtl8367_priv_data
;
52 unsigned int rtl8367c_port_id
[RTL8367C_NUM_PORTS
]={0,1,2,3,4,EXT_PORT1
,EXT_PORT0
};
54 void (*rtl8367_switch_reset_func
)(void)=NULL
;
56 static struct rtl8367_mib_counter rtl8367c_mib_counters
[] = {
58 {"dot3StatsFCSErrors"},
59 {"dot3StatsSymbolErrors"},
60 {"dot3InPauseFrames"},
61 {"dot3ControlInUnknownOpcodes"},
62 {"etherStatsFragments"},
63 {"etherStatsJabbers"},
65 {"etherStatsDropEvents"},
67 {"etherStatsUndersizePkts"},
68 {"etherStatsOversizePkts"},
69 {"etherStatsPkts64Octets"},
70 {"etherStatsPkts65to127Octets"},
71 {"etherStatsPkts128to255Octets"},
72 {"etherStatsPkts256to511Octets"},
73 {"etherStatsPkts512to1023Octets"},
74 {"etherStatsPkts1024toMaxOctets"},
75 {"etherStatsMcastPkts"},
76 {"etherStatsBcastPkts"},
78 {"dot3StatsSingleCollisionFrames"},
79 {"dot3StatsMultipleCollisionFrames"},
80 {"dot3StatsDeferredTransmissions"},
81 {"dot3StatsLateCollisions"},
82 {"etherStatsCollisions"},
83 {"dot3StatsExcessiveCollisions"},
84 {"dot3OutPauseFrames"},
85 {"dot1dBasePortDelayExceededDiscards"},
86 {"dot1dTpPortInDiscards"},
88 {"ifOutMulticastPkts"},
93 {"inMldChecksumError"},
94 {"inIgmpChecksumError"},
95 {"inMldSpecificQuery"},
96 {"inMldGeneralQuery"},
97 {"inIgmpSpecificQuery"},
98 {"inIgmpGeneralQuery"},
101 {"inIgmpJoinsSuccess"},
103 {"inMldJoinsSuccess"},
105 {"inReportSuppressionDrop"},
106 {"inLeaveSuppressionDrop"},
109 {"outIgmpGeneralQuery"},
110 {"outIgmpSpecificQuery"},
113 {"outMldGeneralQuery"},
114 {"outMldSpecificQuery"},
115 {"inKnownMulticastPkts"},
116 {"ifInMulticastPkts"},
117 {"ifInBroadcastPkts"},
121 /*rtl8367c proprietary switch API wrapper */
122 static inline unsigned int rtl8367c_sw_to_phy_port(int port
)
124 return rtl8367c_port_id
[port
];
127 static inline unsigned int rtl8367c_portmask_phy_to_sw(rtk_portmask_t phy_portmask
)
130 for (i
= 0; i
< RTL8367C_NUM_PORTS
; i
++) {
131 if(RTK_PORTMASK_IS_PORT_SET(phy_portmask
,rtl8367c_sw_to_phy_port(i
))) {
132 RTK_PORTMASK_PORT_CLEAR(phy_portmask
,rtl8367c_sw_to_phy_port(i
));
133 RTK_PORTMASK_PORT_SET(phy_portmask
,i
);
137 return (unsigned int)phy_portmask
.bits
[0];
140 static int rtl8367c_reset_mibs(void)
142 return rtk_stat_global_reset();
145 static int rtl8367c_reset_port_mibs(int port
)
148 return rtk_stat_port_reset(rtl8367c_sw_to_phy_port(port
));
151 static int rtl8367c_get_mibs_num(void)
153 return ARRAY_SIZE(rtl8367c_mib_counters
);
156 static const char *rtl8367c_get_mib_name(int idx
)
159 return rtl8367c_mib_counters
[idx
].name
;
162 static int rtl8367c_get_port_mib_counter(int idx
, int port
, unsigned long long *counter
)
164 return rtk_stat_port_get(rtl8367c_sw_to_phy_port(port
), idx
, counter
);
167 static int rtl8367c_is_vlan_valid(unsigned int vlan
)
169 unsigned max
= RTL8367C_NUM_VIDS
;
171 if (vlan
== 0 || vlan
>= max
)
177 static int rtl8367c_get_vlan( unsigned short vid
, struct rtl8367_vlan_info
*vlan
)
179 rtk_vlan_cfg_t vlan_cfg
;
181 memset(vlan
, '\0', sizeof(struct rtl8367_vlan_info
));
183 if (vid
>= RTL8367C_NUM_VIDS
)
186 if(rtk_vlan_get(vid
,&vlan_cfg
))
190 vlan
->member
= rtl8367c_portmask_phy_to_sw(vlan_cfg
.mbr
);
191 vlan
->untag
= rtl8367c_portmask_phy_to_sw(vlan_cfg
.untag
);
192 vlan
->fid
= vlan_cfg
.fid_msti
;
197 static int rtl8367c_set_vlan( unsigned short vid
, u32 mbr
, u32 untag
, u8 fid
)
199 rtk_vlan_cfg_t vlan_cfg
;
202 memset(&vlan_cfg
, 0x00, sizeof(rtk_vlan_cfg_t
));
204 for (i
= 0; i
< RTL8367C_NUM_PORTS
; i
++) {
205 if (mbr
& (1 << i
)) {
206 RTK_PORTMASK_PORT_SET(vlan_cfg
.mbr
, rtl8367c_sw_to_phy_port(i
));
208 RTK_PORTMASK_PORT_SET(vlan_cfg
.untag
, rtl8367c_sw_to_phy_port(i
));
211 vlan_cfg
.fid_msti
=fid
;
213 return rtk_vlan_set(vid
, &vlan_cfg
);
217 static int rtl8367c_get_pvid( int port
, int *pvid
)
221 if (port
>= RTL8367C_NUM_PORTS
)
224 return rtk_vlan_portPvid_get(rtl8367c_sw_to_phy_port(port
),pvid
,&prio
);
228 static int rtl8367c_set_pvid( int port
, int pvid
)
232 if (port
>= RTL8367C_NUM_PORTS
)
235 return rtk_vlan_portPvid_set(rtl8367c_sw_to_phy_port(port
),pvid
,prio
);
238 static int rtl8367c_get_port_link(int port
, int *link
, int *speed
, int *duplex
)
241 if(rtk_port_phyStatus_get(rtl8367c_sw_to_phy_port(port
),(rtk_port_linkStatus_t
*)link
,
242 (rtk_port_speed_t
*)speed
,(rtk_port_duplex_t
*)duplex
))
248 /*common rtl8367 swconfig entry API*/
251 rtl8367_sw_set_vlan_enable(struct switch_dev
*dev
,
252 const struct switch_attr
*attr
,
253 struct switch_val
*val
)
255 struct rtl8367_priv
*priv
= container_of(dev
, struct rtl8367_priv
, swdev
);
257 priv
->global_vlan_enable
= val
->value
.i
;
263 rtl8367_sw_get_vlan_enable(struct switch_dev
*dev
,
264 const struct switch_attr
*attr
,
265 struct switch_val
*val
)
267 struct rtl8367_priv
*priv
= container_of(dev
, struct rtl8367_priv
, swdev
);
269 val
->value
.i
= priv
->global_vlan_enable
;
274 static int rtl8367_sw_reset_mibs(struct switch_dev
*dev
,
275 const struct switch_attr
*attr
,
276 struct switch_val
*val
)
278 return rtl8367c_reset_mibs();
282 static int rtl8367_sw_reset_port_mibs(struct switch_dev
*dev
,
283 const struct switch_attr
*attr
,
284 struct switch_val
*val
)
288 port
= val
->port_vlan
;
289 if (port
>= RTL8367C_NUM_PORTS
)
292 return rtl8367c_reset_port_mibs(port
);
295 static int rtl8367_sw_get_port_mib(struct switch_dev
*dev
,
296 const struct switch_attr
*attr
,
297 struct switch_val
*val
)
300 unsigned long long counter
= 0;
301 static char mib_buf
[4096];
303 if (val
->port_vlan
>= RTL8367C_NUM_PORTS
)
306 len
+= snprintf(mib_buf
+ len
, sizeof(mib_buf
) - len
,
307 "Port %d MIB counters\n",
310 for (i
= 0; i
<rtl8367c_get_mibs_num(); ++i
) {
311 len
+= snprintf(mib_buf
+ len
, sizeof(mib_buf
) - len
,
312 "%-36s: ",rtl8367c_get_mib_name(i
));
313 if (!rtl8367c_get_port_mib_counter(i
, val
->port_vlan
,
315 len
+= snprintf(mib_buf
+ len
, sizeof(mib_buf
) - len
,
318 len
+= snprintf(mib_buf
+ len
, sizeof(mib_buf
) - len
,
322 val
->value
.s
= mib_buf
;
328 static int rtl8367_sw_get_vlan_info(struct switch_dev
*dev
,
329 const struct switch_attr
*attr
,
330 struct switch_val
*val
)
334 struct rtl8367_vlan_info vlan
;
335 static char vlan_buf
[256];
338 if (!rtl8367c_is_vlan_valid(val
->port_vlan
))
341 memset(vlan_buf
, '\0', sizeof(vlan_buf
));
343 err
= rtl8367c_get_vlan(val
->port_vlan
, &vlan
);
347 len
+= snprintf(vlan_buf
+ len
, sizeof(vlan_buf
) - len
,
348 "VLAN %d: Ports: '", vlan
.vid
);
350 for (i
= 0; i
<RTL8367C_NUM_PORTS
; i
++) {
351 if (!(vlan
.member
& (1 << i
)))
354 len
+= snprintf(vlan_buf
+ len
, sizeof(vlan_buf
) - len
, "%d%s", i
,
355 (vlan
.untag
& (1 << i
)) ? "" : "t");
358 len
+= snprintf(vlan_buf
+ len
, sizeof(vlan_buf
) - len
,
359 "', members=%04x, untag=%04x, fid=%u",
360 vlan
.member
, vlan
.untag
, vlan
.fid
);
362 val
->value
.s
= vlan_buf
;
369 static int rtl8367_sw_get_vlan_ports(struct switch_dev
*dev
, struct switch_val
*val
)
371 struct switch_port
*port
;
372 struct rtl8367_vlan_info vlan
;
375 if (!rtl8367c_is_vlan_valid(val
->port_vlan
))
378 if(rtl8367c_get_vlan(val
->port_vlan
, &vlan
))
381 port
= &val
->value
.ports
[0];
383 for (i
= 0; i
<RTL8367C_NUM_PORTS
; i
++) {
384 if (!(vlan
.member
& BIT(i
)))
388 port
->flags
= (vlan
.untag
& BIT(i
)) ?
389 0 : BIT(SWITCH_PORT_FLAG_TAGGED
);
397 static int rtl8367_sw_set_vlan_ports(struct switch_dev
*dev
, struct switch_val
*val
)
399 struct switch_port
*port
;
406 if (!rtl8367c_is_vlan_valid(val
->port_vlan
))
409 port
= &val
->value
.ports
[0];
410 for (i
= 0; i
< val
->len
; i
++, port
++) {
412 member
|= BIT(port
->id
);
414 if (!(port
->flags
& BIT(SWITCH_PORT_FLAG_TAGGED
)))
415 untag
|= BIT(port
->id
);
418 * To ensure that we have a valid MC entry for this VLAN,
419 * initialize the port VLAN ID here.
421 err
= rtl8367c_get_pvid(port
->id
, &pvid
);
425 err
= rtl8367c_set_pvid(port
->id
, val
->port_vlan
);
431 //pr_info("[%s] vid=%d , mem=%x,untag=%x,fid=%d \n",__func__,val->port_vlan,member,untag,fid);
433 return rtl8367c_set_vlan(val
->port_vlan
, member
, untag
, fid
);
438 static int rtl8367_sw_get_port_pvid(struct switch_dev
*dev
, int port
, int *val
)
440 return rtl8367c_get_pvid(port
, val
);
444 static int rtl8367_sw_set_port_pvid(struct switch_dev
*dev
, int port
, int val
)
446 return rtl8367c_set_pvid(port
, val
);
450 static int rtl8367_sw_reset_switch(struct switch_dev
*dev
)
452 if(rtl8367_switch_reset_func
)
453 (*rtl8367_switch_reset_func
)();
455 printk("rest switch is not supported\n");
460 static int rtl8367_sw_get_port_link(struct switch_dev
*dev
, int port
,
461 struct switch_port_link
*link
)
465 if (port
>= RTL8367C_NUM_PORTS
)
468 if(rtl8367c_get_port_link(port
,(int *)&link
->link
,(int *)&speed
,(int *)&link
->duplex
))
476 link
->speed
= SWITCH_PORT_SPEED_10
;
479 link
->speed
= SWITCH_PORT_SPEED_100
;
482 link
->speed
= SWITCH_PORT_SPEED_1000
;
485 link
->speed
= SWITCH_PORT_SPEED_UNKNOWN
;
493 static struct switch_attr rtl8367_globals
[] = {
495 .type
= SWITCH_TYPE_INT
,
496 .name
= "enable_vlan",
497 .description
= "Enable VLAN mode",
498 .set
= rtl8367_sw_set_vlan_enable
,
499 .get
= rtl8367_sw_get_vlan_enable
,
502 .type
= SWITCH_TYPE_NOVAL
,
503 .name
= "reset_mibs",
504 .description
= "Reset all MIB counters",
505 .set
= rtl8367_sw_reset_mibs
,
509 static struct switch_attr rtl8367_port
[] = {
511 .type
= SWITCH_TYPE_NOVAL
,
513 .description
= "Reset single port MIB counters",
514 .set
= rtl8367_sw_reset_port_mibs
,
516 .type
= SWITCH_TYPE_STRING
,
518 .description
= "Get MIB counters for port",
521 .get
= rtl8367_sw_get_port_mib
,
525 static struct switch_attr rtl8367_vlan
[] = {
527 .type
= SWITCH_TYPE_STRING
,
529 .description
= "Get vlan information",
532 .get
= rtl8367_sw_get_vlan_info
,
536 static const struct switch_dev_ops rtl8367_sw_ops
= {
538 .attr
= rtl8367_globals
,
539 .n_attr
= ARRAY_SIZE(rtl8367_globals
),
542 .attr
= rtl8367_port
,
543 .n_attr
= ARRAY_SIZE(rtl8367_port
),
546 .attr
= rtl8367_vlan
,
547 .n_attr
= ARRAY_SIZE(rtl8367_vlan
),
550 .get_vlan_ports
= rtl8367_sw_get_vlan_ports
,
551 .set_vlan_ports
= rtl8367_sw_set_vlan_ports
,
552 .get_port_pvid
= rtl8367_sw_get_port_pvid
,
553 .set_port_pvid
= rtl8367_sw_set_port_pvid
,
554 .reset_switch
= rtl8367_sw_reset_switch
,
555 .get_port_link
= rtl8367_sw_get_port_link
,
558 int rtl8367s_swconfig_init(void (*reset_func
)(void))
560 struct rtl8367_priv
*priv
= &rtl8367_priv_data
;
561 struct switch_dev
*dev
=&priv
->swdev
;
564 rtl8367_switch_reset_func
= reset_func
;
566 memset(priv
, 0, sizeof(struct rtl8367_priv
));
567 priv
->global_vlan_enable
=0;
569 dev
->name
= "RTL8367C";
570 dev
->cpu_port
= RTL8367C_SW_CPU_PORT
;
571 dev
->ports
= RTL8367C_NUM_PORTS
;
572 dev
->vlans
= RTL8367C_NUM_VIDS
;
573 dev
->ops
= &rtl8367_sw_ops
;
574 dev
->alias
= "RTL8367C";
575 err
= register_switch(dev
, NULL
);
577 pr_info("[%s]\n",__func__
);