27
27
#include <linux/platform_data/b53.h>
28
28
#include <linux/phy.h>
29
29
#include <linux/etherdevice.h>
30
+ #include <linux/if_bridge.h>
30
31
#include <net/dsa.h>
31
32
#include <net/switchdev.h>
32
33
@@ -339,12 +340,12 @@ static int b53_set_jumbo(struct b53_device *dev, bool enable, bool allow_10_100)
339
340
return b53_write16 (dev , B53_JUMBO_PAGE , dev -> jumbo_size_reg , max_size );
340
341
}
341
342
342
- static int b53_flush_arl (struct b53_device * dev )
343
+ static int b53_flush_arl (struct b53_device * dev , u8 mask )
343
344
{
344
345
unsigned int i ;
345
346
346
347
b53_write8 (dev , B53_CTRL_PAGE , B53_FAST_AGE_CTRL ,
347
- FAST_AGE_DONE | FAST_AGE_DYNAMIC | FAST_AGE_STATIC );
348
+ FAST_AGE_DONE | FAST_AGE_DYNAMIC | mask );
348
349
349
350
for (i = 0 ; i < 10 ; i ++ ) {
350
351
u8 fast_age_ctrl ;
@@ -365,14 +366,52 @@ static int b53_flush_arl(struct b53_device *dev)
365
366
return 0 ;
366
367
}
367
368
369
+ static int b53_fast_age_port (struct b53_device * dev , int port )
370
+ {
371
+ b53_write8 (dev , B53_CTRL_PAGE , B53_FAST_AGE_PORT_CTRL , port );
372
+
373
+ return b53_flush_arl (dev , FAST_AGE_PORT );
374
+ }
375
+
376
+ static void b53_imp_vlan_setup (struct dsa_switch * ds , int cpu_port )
377
+ {
378
+ struct b53_device * dev = ds_to_priv (ds );
379
+ unsigned int i ;
380
+ u16 pvlan ;
381
+
382
+ /* Enable the IMP port to be in the same VLAN as the other ports
383
+ * on a per-port basis such that we only have Port i and IMP in
384
+ * the same VLAN.
385
+ */
386
+ b53_for_each_port (dev , i ) {
387
+ b53_read16 (dev , B53_PVLAN_PAGE , B53_PVLAN_PORT_MASK (i ), & pvlan );
388
+ pvlan |= BIT (cpu_port );
389
+ b53_write16 (dev , B53_PVLAN_PAGE , B53_PVLAN_PORT_MASK (i ), pvlan );
390
+ }
391
+ }
392
+
368
393
static int b53_enable_port (struct dsa_switch * ds , int port ,
369
394
struct phy_device * phy )
370
395
{
371
396
struct b53_device * dev = ds_to_priv (ds );
397
+ unsigned int cpu_port = dev -> cpu_port ;
398
+ u16 pvlan ;
372
399
373
400
/* Clear the Rx and Tx disable bits and set to no spanning tree */
374
401
b53_write8 (dev , B53_CTRL_PAGE , B53_PORT_CTRL (port ), 0 );
375
402
403
+ /* Set this port, and only this one to be in the default VLAN,
404
+ * if member of a bridge, restore its membership prior to
405
+ * bringing down this port.
406
+ */
407
+ b53_read16 (dev , B53_PVLAN_PAGE , B53_PVLAN_PORT_MASK (port ), & pvlan );
408
+ pvlan &= ~0x1ff ;
409
+ pvlan |= BIT (port );
410
+ pvlan |= dev -> ports [port ].vlan_ctl_mask ;
411
+ b53_write16 (dev , B53_PVLAN_PAGE , B53_PVLAN_PORT_MASK (port ), pvlan );
412
+
413
+ b53_imp_vlan_setup (ds , cpu_port );
414
+
376
415
return 0 ;
377
416
}
378
417
@@ -482,7 +521,7 @@ static int b53_switch_reset(struct b53_device *dev)
482
521
483
522
b53_enable_mib (dev );
484
523
485
- return b53_flush_arl (dev );
524
+ return b53_flush_arl (dev , FAST_AGE_STATIC );
486
525
}
487
526
488
527
static int b53_phy_read16 (struct dsa_switch * ds , int addr , int reg )
@@ -1019,6 +1058,120 @@ static int b53_fdb_dump(struct dsa_switch *ds, int port,
1019
1058
return 0 ;
1020
1059
}
1021
1060
1061
+ static int b53_br_join (struct dsa_switch * ds , int port ,
1062
+ struct net_device * bridge )
1063
+ {
1064
+ struct b53_device * dev = ds_to_priv (ds );
1065
+ u16 pvlan , reg ;
1066
+ unsigned int i ;
1067
+
1068
+ dev -> ports [port ].bridge_dev = bridge ;
1069
+ b53_read16 (dev , B53_PVLAN_PAGE , B53_PVLAN_PORT_MASK (port ), & pvlan );
1070
+
1071
+ b53_for_each_port (dev , i ) {
1072
+ if (dev -> ports [i ].bridge_dev != bridge )
1073
+ continue ;
1074
+
1075
+ /* Add this local port to the remote port VLAN control
1076
+ * membership and update the remote port bitmask
1077
+ */
1078
+ b53_read16 (dev , B53_PVLAN_PAGE , B53_PVLAN_PORT_MASK (i ), & reg );
1079
+ reg |= BIT (port );
1080
+ b53_write16 (dev , B53_PVLAN_PAGE , B53_PVLAN_PORT_MASK (i ), reg );
1081
+ dev -> ports [i ].vlan_ctl_mask = reg ;
1082
+
1083
+ pvlan |= BIT (i );
1084
+ }
1085
+
1086
+ /* Configure the local port VLAN control membership to include
1087
+ * remote ports and update the local port bitmask
1088
+ */
1089
+ b53_write16 (dev , B53_PVLAN_PAGE , B53_PVLAN_PORT_MASK (port ), pvlan );
1090
+ dev -> ports [port ].vlan_ctl_mask = pvlan ;
1091
+
1092
+ return 0 ;
1093
+ }
1094
+
1095
+ static void b53_br_leave (struct dsa_switch * ds , int port )
1096
+ {
1097
+ struct b53_device * dev = ds_to_priv (ds );
1098
+ struct net_device * bridge = dev -> ports [port ].bridge_dev ;
1099
+ unsigned int i ;
1100
+ u16 pvlan , reg ;
1101
+
1102
+ b53_read16 (dev , B53_PVLAN_PAGE , B53_PVLAN_PORT_MASK (port ), & pvlan );
1103
+
1104
+ b53_for_each_port (dev , i ) {
1105
+ /* Don't touch the remaining ports */
1106
+ if (dev -> ports [i ].bridge_dev != bridge )
1107
+ continue ;
1108
+
1109
+ b53_read16 (dev , B53_PVLAN_PAGE , B53_PVLAN_PORT_MASK (i ), & reg );
1110
+ reg &= ~BIT (port );
1111
+ b53_write16 (dev , B53_PVLAN_PAGE , B53_PVLAN_PORT_MASK (i ), reg );
1112
+ dev -> ports [port ].vlan_ctl_mask = reg ;
1113
+
1114
+ /* Prevent self removal to preserve isolation */
1115
+ if (port != i )
1116
+ pvlan &= ~BIT (i );
1117
+ }
1118
+
1119
+ b53_write16 (dev , B53_PVLAN_PAGE , B53_PVLAN_PORT_MASK (port ), pvlan );
1120
+ dev -> ports [port ].vlan_ctl_mask = pvlan ;
1121
+ dev -> ports [port ].bridge_dev = NULL ;
1122
+ }
1123
+
1124
+ static void b53_br_set_stp_state (struct dsa_switch * ds , int port ,
1125
+ u8 state )
1126
+ {
1127
+ struct b53_device * dev = ds_to_priv (ds );
1128
+ u8 hw_state , cur_hw_state ;
1129
+ u8 reg ;
1130
+
1131
+ b53_read8 (dev , B53_CTRL_PAGE , B53_PORT_CTRL (port ), & reg );
1132
+ cur_hw_state = reg & PORT_CTRL_STP_STATE_MASK ;
1133
+
1134
+ switch (state ) {
1135
+ case BR_STATE_DISABLED :
1136
+ hw_state = PORT_CTRL_DIS_STATE ;
1137
+ break ;
1138
+ case BR_STATE_LISTENING :
1139
+ hw_state = PORT_CTRL_LISTEN_STATE ;
1140
+ break ;
1141
+ case BR_STATE_LEARNING :
1142
+ hw_state = PORT_CTRL_LEARN_STATE ;
1143
+ break ;
1144
+ case BR_STATE_FORWARDING :
1145
+ hw_state = PORT_CTRL_FWD_STATE ;
1146
+ break ;
1147
+ case BR_STATE_BLOCKING :
1148
+ hw_state = PORT_CTRL_BLOCK_STATE ;
1149
+ break ;
1150
+ default :
1151
+ dev_err (ds -> dev , "invalid STP state: %d\n" , state );
1152
+ return ;
1153
+ }
1154
+
1155
+ /* Fast-age ARL entries if we are moving a port from Learning or
1156
+ * Forwarding (cur_hw_state) state to Disabled, Blocking or Listening
1157
+ * state (hw_state)
1158
+ */
1159
+ if (cur_hw_state != hw_state ) {
1160
+ if (cur_hw_state >= PORT_CTRL_LEARN_STATE &&
1161
+ hw_state <= PORT_CTRL_LISTEN_STATE ) {
1162
+ if (b53_fast_age_port (dev , port )) {
1163
+ dev_err (ds -> dev , "fast ageing failed\n" );
1164
+ return ;
1165
+ }
1166
+ }
1167
+ }
1168
+
1169
+ b53_read8 (dev , B53_CTRL_PAGE , B53_PORT_CTRL (port ), & reg );
1170
+ reg &= ~PORT_CTRL_STP_STATE_MASK ;
1171
+ reg |= hw_state ;
1172
+ b53_write8 (dev , B53_CTRL_PAGE , B53_PORT_CTRL (port ), reg );
1173
+ }
1174
+
1022
1175
static struct dsa_switch_driver b53_switch_ops = {
1023
1176
.tag_protocol = DSA_TAG_PROTO_NONE ,
1024
1177
.setup = b53_setup ,
@@ -1031,6 +1184,9 @@ static struct dsa_switch_driver b53_switch_ops = {
1031
1184
.adjust_link = b53_adjust_link ,
1032
1185
.port_enable = b53_enable_port ,
1033
1186
.port_disable = b53_disable_port ,
1187
+ .port_bridge_join = b53_br_join ,
1188
+ .port_bridge_leave = b53_br_leave ,
1189
+ .port_stp_state_set = b53_br_set_stp_state ,
1034
1190
.port_fdb_prepare = b53_fdb_prepare ,
1035
1191
.port_fdb_dump = b53_fdb_dump ,
1036
1192
.port_fdb_add = b53_fdb_add ,
0 commit comments