OpenWrt – Blame information for rev 3
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | --- a/drivers/net/dsa/mt7530.c |
2 | +++ b/drivers/net/dsa/mt7530.c |
||
3 | @@ -670,6 +670,9 @@ static int |
||
4 | mt7530_cpu_port_enable(struct mt7530_priv *priv, |
||
5 | int port) |
||
6 | { |
||
7 | + u8 port_mask = 0; |
||
8 | + int i; |
||
9 | + |
||
10 | /* Enable Mediatek header mode on the cpu port */ |
||
11 | mt7530_write(priv, MT7530_PVC_P(port), |
||
12 | PORT_SPEC_TAG); |
||
13 | @@ -686,8 +689,12 @@ mt7530_cpu_port_enable(struct mt7530_pri |
||
14 | /* CPU port gets connected to all user ports of |
||
15 | * the switch |
||
16 | */ |
||
17 | + for (i = 0; i < MT7530_NUM_PORTS; i++) |
||
18 | + if ((priv->ds->enabled_port_mask & BIT(i)) && |
||
19 | + (dsa_port_upstream_port(priv->ds, i) == port)) |
||
20 | + port_mask |= BIT(i); |
||
21 | mt7530_write(priv, MT7530_PCR_P(port), |
||
22 | - PCR_MATRIX(priv->ds->enabled_port_mask)); |
||
23 | + PCR_MATRIX(port_mask)); |
||
24 | |||
25 | return 0; |
||
26 | } |
||
27 | @@ -697,6 +704,7 @@ mt7530_port_enable(struct dsa_switch *ds |
||
28 | struct phy_device *phy) |
||
29 | { |
||
30 | struct mt7530_priv *priv = ds->priv; |
||
31 | + u8 upstream = dsa_port_upstream_port(ds, port); |
||
32 | |||
33 | mutex_lock(&priv->reg_mutex); |
||
34 | |||
35 | @@ -707,7 +715,7 @@ mt7530_port_enable(struct dsa_switch *ds |
||
36 | * restore the port matrix if the port is the member of a certain |
||
37 | * bridge. |
||
38 | */ |
||
39 | - priv->ports[port].pm |= PCR_MATRIX(BIT(MT7530_CPU_PORT)); |
||
40 | + priv->ports[port].pm |= PCR_MATRIX(BIT(upstream)); |
||
41 | priv->ports[port].enable = true; |
||
42 | mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, |
||
43 | priv->ports[port].pm); |
||
44 | @@ -770,7 +778,8 @@ mt7530_port_bridge_join(struct dsa_switc |
||
45 | struct net_device *bridge) |
||
46 | { |
||
47 | struct mt7530_priv *priv = ds->priv; |
||
48 | - u32 port_bitmap = BIT(MT7530_CPU_PORT); |
||
49 | + u8 upstream = dsa_port_upstream_port(ds, port); |
||
50 | + u32 port_bitmap = BIT(upstream); |
||
51 | int i; |
||
52 | |||
53 | mutex_lock(&priv->reg_mutex); |
||
54 | @@ -808,6 +817,7 @@ mt7530_port_bridge_leave(struct dsa_swit |
||
55 | struct net_device *bridge) |
||
56 | { |
||
57 | struct mt7530_priv *priv = ds->priv; |
||
58 | + u8 upstream = dsa_port_upstream_port(ds, port); |
||
59 | int i; |
||
60 | |||
61 | mutex_lock(&priv->reg_mutex); |
||
62 | @@ -832,8 +842,8 @@ mt7530_port_bridge_leave(struct dsa_swit |
||
63 | */ |
||
64 | if (priv->ports[port].enable) |
||
65 | mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, |
||
66 | - PCR_MATRIX(BIT(MT7530_CPU_PORT))); |
||
67 | - priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT)); |
||
68 | + PCR_MATRIX(BIT(upstream))); |
||
69 | + priv->ports[port].pm = PCR_MATRIX(BIT(upstream)); |
||
70 | |||
71 | mutex_unlock(&priv->reg_mutex); |
||
72 | } |
||
73 | @@ -908,15 +918,7 @@ err: |
||
74 | static enum dsa_tag_protocol |
||
75 | mtk_get_tag_protocol(struct dsa_switch *ds) |
||
76 | { |
||
77 | - struct mt7530_priv *priv = ds->priv; |
||
78 | - |
||
79 | - if (!dsa_is_cpu_port(ds, MT7530_CPU_PORT)) { |
||
80 | - dev_warn(priv->dev, |
||
81 | - "port not matched with tagging CPU port\n"); |
||
82 | - return DSA_TAG_PROTO_NONE; |
||
83 | - } else { |
||
84 | - return DSA_TAG_PROTO_MTK; |
||
85 | - } |
||
86 | + return DSA_TAG_PROTO_MTK; |
||
87 | } |
||
88 | |||
89 | static int |
||
90 | @@ -989,7 +991,7 @@ mt7530_setup(struct dsa_switch *ds) |
||
91 | |||
92 | /* Enable Port 6 only; P5 as GMAC5 which currently is not supported */ |
||
93 | val = mt7530_read(priv, MT7530_MHWTRAP); |
||
94 | - val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; |
||
95 | + val &= ~MHWTRAP_P5_DIS & ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; |
||
96 | val |= MHWTRAP_MANUAL; |
||
97 | if (!dsa_is_cpu_port(ds, 5)) { |
||
98 | val |= MHWTRAP_P5_DIS; |
||
99 | --- a/include/net/dsa.h |
||
100 | +++ b/include/net/dsa.h |
||
101 | @@ -185,6 +185,10 @@ struct dsa_port { |
||
102 | u8 stp_state; |
||
103 | struct net_device *bridge_dev; |
||
104 | struct devlink_port devlink_port; |
||
105 | + |
||
106 | + struct net_device *ethernet; |
||
107 | + int upstream; |
||
108 | + |
||
109 | /* |
||
110 | * Original copy of the master netdev ethtool_ops |
||
111 | */ |
||
112 | @@ -266,6 +270,11 @@ static inline bool dsa_is_normal_port(st |
||
113 | return !dsa_is_cpu_port(ds, p) && !dsa_is_dsa_port(ds, p); |
||
114 | } |
||
115 | |||
116 | +static inline bool dsa_is_upstream_port(struct dsa_switch *ds, int p) |
||
117 | +{ |
||
118 | + return dsa_is_cpu_port(ds, p) || dsa_is_dsa_port(ds, p); |
||
119 | +} |
||
120 | + |
||
121 | static inline u8 dsa_upstream_port(struct dsa_switch *ds) |
||
122 | { |
||
123 | struct dsa_switch_tree *dst = ds->dst; |
||
124 | @@ -282,6 +291,18 @@ static inline u8 dsa_upstream_port(struc |
||
125 | return ds->rtable[dst->cpu_dp->ds->index]; |
||
126 | } |
||
127 | |||
128 | +static inline u8 dsa_port_upstream_port(struct dsa_switch *ds, int port) |
||
129 | +{ |
||
130 | + /* |
||
131 | + * If this port has a specific upstream cpu port, use it, |
||
132 | + * otherwise use the switch default. |
||
133 | + */ |
||
134 | + if (ds->ports[port].upstream) |
||
135 | + return ds->ports[port].upstream; |
||
136 | + else |
||
137 | + return dsa_upstream_port(ds); |
||
138 | +} |
||
139 | + |
||
140 | typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid, |
||
141 | bool is_static, void *data); |
||
142 | struct dsa_switch_ops { |
||
143 | --- a/net/dsa/dsa2.c |
||
144 | +++ b/net/dsa/dsa2.c |
||
145 | @@ -253,6 +253,8 @@ static int dsa_cpu_port_apply(struct dsa |
||
146 | memset(&port->devlink_port, 0, sizeof(port->devlink_port)); |
||
147 | err = devlink_port_register(ds->devlink, &port->devlink_port, |
||
148 | port->index); |
||
149 | + if (port->netdev) |
||
150 | + port->netdev->dsa_ptr = ds->dst; |
||
151 | return err; |
||
152 | } |
||
153 | |||
154 | @@ -262,6 +264,12 @@ static void dsa_cpu_port_unapply(struct |
||
155 | dsa_cpu_dsa_destroy(port); |
||
156 | port->ds->cpu_port_mask &= ~BIT(port->index); |
||
157 | |||
158 | + if (port->netdev) |
||
159 | + port->netdev->dsa_ptr = NULL; |
||
160 | + if (port->ethernet) { |
||
161 | + dev_put(port->ethernet); |
||
162 | + port->ethernet = NULL; |
||
163 | + } |
||
164 | } |
||
165 | |||
166 | static int dsa_user_port_apply(struct dsa_port *port) |
||
167 | @@ -505,10 +513,9 @@ static int dsa_cpu_parse(struct dsa_port |
||
168 | dev_put(ethernet_dev); |
||
169 | } |
||
170 | |||
171 | - if (!dst->cpu_dp) { |
||
172 | + if (!dst->cpu_dp) |
||
173 | dst->cpu_dp = port; |
||
174 | - dst->cpu_dp->netdev = ethernet_dev; |
||
175 | - } |
||
176 | + port->netdev = ethernet_dev; |
||
177 | |||
178 | /* Initialize cpu_port_mask now for drv->setup() |
||
179 | * to have access to a correct value, just like what |
||
180 | @@ -526,6 +533,29 @@ static int dsa_cpu_parse(struct dsa_port |
||
181 | |||
182 | dst->rcv = dst->tag_ops->rcv; |
||
183 | |||
184 | + dev_hold(ethernet_dev); |
||
185 | + ds->ports[index].ethernet = ethernet_dev; |
||
186 | + ds->cpu_port_mask |= BIT(index); |
||
187 | + |
||
188 | + return 0; |
||
189 | +} |
||
190 | + |
||
191 | +static int dsa_user_parse(struct dsa_port *port, u32 index, |
||
192 | + struct dsa_switch *ds) |
||
193 | +{ |
||
194 | + struct device_node *cpu_port; |
||
195 | + const unsigned int *cpu_port_reg; |
||
196 | + int cpu_port_index; |
||
197 | + |
||
198 | + cpu_port = of_parse_phandle(port->dn, "cpu", 0); |
||
199 | + if (cpu_port) { |
||
200 | + cpu_port_reg = of_get_property(cpu_port, "reg", NULL); |
||
201 | + if (!cpu_port_reg) |
||
202 | + return -EINVAL; |
||
203 | + cpu_port_index = be32_to_cpup(cpu_port_reg); |
||
204 | + ds->ports[index].upstream = cpu_port_index; |
||
205 | + } |
||
206 | + |
||
207 | return 0; |
||
208 | } |
||
209 | |||
210 | @@ -533,7 +563,7 @@ static int dsa_ds_parse(struct dsa_switc |
||
211 | { |
||
212 | struct dsa_port *port; |
||
213 | u32 index; |
||
214 | - int err; |
||
215 | + int err = 0; |
||
216 | |||
217 | for (index = 0; index < ds->num_ports; index++) { |
||
218 | port = &ds->ports[index]; |
||
219 | @@ -546,6 +576,9 @@ static int dsa_ds_parse(struct dsa_switc |
||
220 | if (err) |
||
221 | return err; |
||
222 | } else { |
||
223 | + err = dsa_user_parse(port, index, ds); |
||
224 | + if (err) |
||
225 | + return err; |
||
226 | /* Initialize enabled_port_mask now for drv->setup() |
||
227 | * to have access to a correct value, just like what |
||
228 | * net/dsa/dsa.c::dsa_switch_setup_one does. |
||
229 | --- a/net/dsa/dsa_priv.h |
||
230 | +++ b/net/dsa/dsa_priv.h |
||
231 | @@ -91,6 +91,8 @@ struct dsa_slave_priv { |
||
232 | |||
233 | /* TC context */ |
||
234 | struct list_head mall_tc_list; |
||
235 | + |
||
236 | + struct net_device *master; |
||
237 | }; |
||
238 | |||
239 | /* dsa.c */ |
||
240 | @@ -177,6 +179,9 @@ extern const struct dsa_device_ops trail |
||
241 | |||
242 | static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p) |
||
243 | { |
||
244 | + if (p->master) |
||
245 | + return p->master; |
||
246 | + |
||
247 | return p->dp->cpu_dp->netdev; |
||
248 | } |
||
249 | |||
250 | --- a/net/dsa/slave.c |
||
251 | +++ b/net/dsa/slave.c |
||
3 | office | 252 | @@ -1263,7 +1263,7 @@ int dsa_slave_create(struct dsa_port *po |
1 | office | 253 | int ret; |
254 | |||
255 | cpu_dp = ds->dst->cpu_dp; |
||
256 | - master = cpu_dp->netdev; |
||
257 | + master = ds->ports[port->upstream].ethernet; |
||
258 | |||
259 | if (!ds->num_tx_queues) |
||
260 | ds->num_tx_queues = 1; |
||
3 | office | 261 | @@ -1301,6 +1301,7 @@ int dsa_slave_create(struct dsa_port *po |
1 | office | 262 | p->dp = port; |
263 | INIT_LIST_HEAD(&p->mall_tc_list); |
||
264 | p->xmit = dst->tag_ops->xmit; |
||
265 | + p->master = master; |
||
266 | |||
267 | p->old_pause = -1; |
||
268 | p->old_link = -1; |