Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
forked fromtorvalds/linux

Commit98cd155

Browse files
ffainellidavem330
authored andcommitted
net: dsa: Mock-up driver
This patch adds support for a DSA mock-up driver which essentially doesthe following:- registers/unregisters 4 fixed PHYs to the slave network devices- uses eth0 (configurable) as the master netdev- registers the switch as a fixed MDIO device against the fixed MDIO bus at address 31- includes dynamic debug prints for dsa_switch_ops functions that can be enabled to get call tracesThis is a good way to test modular builds as well as exercise the DSAAPIs without requiring access to real hardware. This does not test thedata-path, although this could be added later on.Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent772c3bd commit98cd155

File tree

5 files changed

+390
-1
lines changed

5 files changed

+390
-1
lines changed

‎drivers/net/dsa/Kconfig‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,12 @@ config NET_DSA_QCA8K
3434
This enables support for the Qualcomm Atheros QCA8K Ethernet
3535
switch chips.
3636

37+
config NET_DSA_LOOP
38+
tristate "DSA mock-up Ethernet switch chip support"
39+
depends on NET_DSA
40+
select FIXED_PHY
41+
---help---
42+
This enables support for a fake mock-up switch chip which
43+
exercises the DSA APIs.
44+
3745
endmenu

‎drivers/net/dsa/Makefile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
22
obj-$(CONFIG_NET_DSA_BCM_SF2)+= bcm-sf2.o
33
bcm-sf2-objs:= bcm_sf2.o bcm_sf2_cfp.o
44
obj-$(CONFIG_NET_DSA_QCA8K)+= qca8k.o
5-
65
obj-y+= b53/
76
obj-y+= mv88e6xxx/
7+
obj-$(CONFIG_NET_DSA_LOOP)+= dsa_loop.o dsa_loop_bdinfo.o

‎drivers/net/dsa/dsa_loop.c‎

Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
/*
2+
* Distributed Switch Architecture loopback driver
3+
*
4+
* Copyright (C) 2016, Florian Fainelli <f.fainelli@gmail.com>
5+
*
6+
* This program is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License, or
9+
* (at your option) any later version.
10+
*/
11+
12+
#include<linux/platform_device.h>
13+
#include<linux/netdevice.h>
14+
#include<linux/phy.h>
15+
#include<linux/phy_fixed.h>
16+
#include<linux/export.h>
17+
#include<linux/workqueue.h>
18+
#include<linux/module.h>
19+
#include<linux/if_bridge.h>
20+
#include<net/switchdev.h>
21+
#include<net/dsa.h>
22+
23+
#include"dsa_loop.h"
24+
25+
structdsa_loop_vlan {
26+
u16members;
27+
u16untagged;
28+
};
29+
30+
#defineDSA_LOOP_VLANS5
31+
32+
structdsa_loop_priv {
33+
structmii_bus*bus;
34+
unsignedintport_base;
35+
structdsa_loop_vlanvlans[DSA_LOOP_VLANS];
36+
structnet_device*netdev;
37+
u16pvid;
38+
};
39+
40+
staticstructphy_device*phydevs[PHY_MAX_ADDR];
41+
42+
staticenumdsa_tag_protocoldsa_loop_get_protocol(structdsa_switch*ds)
43+
{
44+
dev_dbg(ds->dev,"%s\n",__func__);
45+
46+
returnDSA_TAG_PROTO_NONE;
47+
}
48+
49+
staticintdsa_loop_setup(structdsa_switch*ds)
50+
{
51+
dev_dbg(ds->dev,"%s\n",__func__);
52+
53+
return0;
54+
}
55+
56+
staticintdsa_loop_set_addr(structdsa_switch*ds,u8*addr)
57+
{
58+
dev_dbg(ds->dev,"%s\n",__func__);
59+
60+
return0;
61+
}
62+
63+
staticintdsa_loop_phy_read(structdsa_switch*ds,intport,intregnum)
64+
{
65+
structdsa_loop_priv*ps=ds->priv;
66+
structmii_bus*bus=ps->bus;
67+
68+
dev_dbg(ds->dev,"%s\n",__func__);
69+
70+
returnmdiobus_read_nested(bus,ps->port_base+port,regnum);
71+
}
72+
73+
staticintdsa_loop_phy_write(structdsa_switch*ds,intport,
74+
intregnum,u16value)
75+
{
76+
structdsa_loop_priv*ps=ds->priv;
77+
structmii_bus*bus=ps->bus;
78+
79+
dev_dbg(ds->dev,"%s\n",__func__);
80+
81+
returnmdiobus_write_nested(bus,ps->port_base+port,regnum,value);
82+
}
83+
84+
staticintdsa_loop_port_bridge_join(structdsa_switch*ds,intport,
85+
structnet_device*bridge)
86+
{
87+
dev_dbg(ds->dev,"%s\n",__func__);
88+
89+
return0;
90+
}
91+
92+
staticvoiddsa_loop_port_bridge_leave(structdsa_switch*ds,intport,
93+
structnet_device*bridge)
94+
{
95+
dev_dbg(ds->dev,"%s\n",__func__);
96+
}
97+
98+
staticvoiddsa_loop_port_stp_state_set(structdsa_switch*ds,intport,
99+
u8state)
100+
{
101+
dev_dbg(ds->dev,"%s\n",__func__);
102+
}
103+
104+
staticintdsa_loop_port_vlan_filtering(structdsa_switch*ds,intport,
105+
boolvlan_filtering)
106+
{
107+
dev_dbg(ds->dev,"%s\n",__func__);
108+
109+
return0;
110+
}
111+
112+
staticintdsa_loop_port_vlan_prepare(structdsa_switch*ds,intport,
113+
conststructswitchdev_obj_port_vlan*vlan,
114+
structswitchdev_trans*trans)
115+
{
116+
structdsa_loop_priv*ps=ds->priv;
117+
structmii_bus*bus=ps->bus;
118+
119+
dev_dbg(ds->dev,"%s\n",__func__);
120+
121+
/* Just do a sleeping operation to make lockdep checks effective */
122+
mdiobus_read(bus,ps->port_base+port,MII_BMSR);
123+
124+
if (vlan->vid_end>DSA_LOOP_VLANS)
125+
return-ERANGE;
126+
127+
return0;
128+
}
129+
130+
staticvoiddsa_loop_port_vlan_add(structdsa_switch*ds,intport,
131+
conststructswitchdev_obj_port_vlan*vlan,
132+
structswitchdev_trans*trans)
133+
{
134+
booluntagged=vlan->flags&BRIDGE_VLAN_INFO_UNTAGGED;
135+
boolpvid=vlan->flags&BRIDGE_VLAN_INFO_PVID;
136+
structdsa_loop_priv*ps=ds->priv;
137+
structmii_bus*bus=ps->bus;
138+
structdsa_loop_vlan*vl;
139+
u16vid;
140+
141+
dev_dbg(ds->dev,"%s\n",__func__);
142+
143+
/* Just do a sleeping operation to make lockdep checks effective */
144+
mdiobus_read(bus,ps->port_base+port,MII_BMSR);
145+
146+
for (vid=vlan->vid_begin;vid <=vlan->vid_end;++vid) {
147+
vl=&ps->vlans[vid];
148+
149+
vl->members |=BIT(port);
150+
if (untagged)
151+
vl->untagged |=BIT(port);
152+
else
153+
vl->untagged &= ~BIT(port);
154+
}
155+
156+
if (pvid)
157+
ps->pvid=vid;
158+
}
159+
160+
staticintdsa_loop_port_vlan_del(structdsa_switch*ds,intport,
161+
conststructswitchdev_obj_port_vlan*vlan)
162+
{
163+
booluntagged=vlan->flags&BRIDGE_VLAN_INFO_UNTAGGED;
164+
structdsa_loop_priv*ps=ds->priv;
165+
structmii_bus*bus=ps->bus;
166+
structdsa_loop_vlan*vl;
167+
u16vid,pvid;
168+
169+
dev_dbg(ds->dev,"%s\n",__func__);
170+
171+
/* Just do a sleeping operation to make lockdep checks effective */
172+
mdiobus_read(bus,ps->port_base+port,MII_BMSR);
173+
174+
for (vid=vlan->vid_begin;vid <=vlan->vid_end;++vid) {
175+
vl=&ps->vlans[vid];
176+
177+
vl->members &= ~BIT(port);
178+
if (untagged)
179+
vl->untagged &= ~BIT(port);
180+
181+
if (pvid==vid)
182+
pvid=1;
183+
}
184+
ps->pvid=pvid;
185+
186+
return0;
187+
}
188+
189+
staticintdsa_loop_port_vlan_dump(structdsa_switch*ds,intport,
190+
structswitchdev_obj_port_vlan*vlan,
191+
int (*cb)(structswitchdev_obj*obj))
192+
{
193+
structdsa_loop_priv*ps=ds->priv;
194+
structmii_bus*bus=ps->bus;
195+
structdsa_loop_vlan*vl;
196+
u16vid,vid_start=0;
197+
interr;
198+
199+
dev_dbg(ds->dev,"%s\n",__func__);
200+
201+
/* Just do a sleeping operation to make lockdep checks effective */
202+
mdiobus_read(bus,ps->port_base+port,MII_BMSR);
203+
204+
for (vid=vid_start;vid<DSA_LOOP_VLANS;vid++) {
205+
vl=&ps->vlans[vid];
206+
207+
if (!(vl->members&BIT(port)))
208+
continue;
209+
210+
vlan->vid_begin=vlan->vid_end=vid;
211+
vlan->flags=0;
212+
213+
if (vl->untagged&BIT(port))
214+
vlan->flags |=BRIDGE_VLAN_INFO_UNTAGGED;
215+
if (ps->pvid==vid)
216+
vlan->flags |=BRIDGE_VLAN_INFO_PVID;
217+
218+
err=cb(&vlan->obj);
219+
if (err)
220+
break;
221+
}
222+
223+
returnerr;
224+
}
225+
226+
staticstructdsa_switch_opsdsa_loop_driver= {
227+
.get_tag_protocol=dsa_loop_get_protocol,
228+
.setup=dsa_loop_setup,
229+
.set_addr=dsa_loop_set_addr,
230+
.phy_read=dsa_loop_phy_read,
231+
.phy_write=dsa_loop_phy_write,
232+
.port_bridge_join=dsa_loop_port_bridge_join,
233+
.port_bridge_leave=dsa_loop_port_bridge_leave,
234+
.port_stp_state_set=dsa_loop_port_stp_state_set,
235+
.port_vlan_filtering=dsa_loop_port_vlan_filtering,
236+
.port_vlan_prepare=dsa_loop_port_vlan_prepare,
237+
.port_vlan_add=dsa_loop_port_vlan_add,
238+
.port_vlan_del=dsa_loop_port_vlan_del,
239+
.port_vlan_dump=dsa_loop_port_vlan_dump,
240+
};
241+
242+
staticintdsa_loop_drv_probe(structmdio_device*mdiodev)
243+
{
244+
structdsa_loop_pdata*pdata=mdiodev->dev.platform_data;
245+
structdsa_loop_priv*ps;
246+
structdsa_switch*ds;
247+
248+
if (!pdata)
249+
return-ENODEV;
250+
251+
dev_info(&mdiodev->dev,"%s: 0x%0x\n",
252+
pdata->name,pdata->enabled_ports);
253+
254+
ds=dsa_switch_alloc(&mdiodev->dev,DSA_MAX_PORTS);
255+
if (!ds)
256+
return-ENOMEM;
257+
258+
ps=devm_kzalloc(&mdiodev->dev,sizeof(*ps),GFP_KERNEL);
259+
ps->netdev=dev_get_by_name(&init_net,pdata->netdev);
260+
if (!ps->netdev)
261+
return-EPROBE_DEFER;
262+
263+
pdata->cd.netdev[DSA_LOOP_CPU_PORT]=&ps->netdev->dev;
264+
265+
ds->dev=&mdiodev->dev;
266+
ds->ops=&dsa_loop_driver;
267+
ds->priv=ps;
268+
ps->bus=mdiodev->bus;
269+
270+
dev_set_drvdata(&mdiodev->dev,ds);
271+
272+
returndsa_register_switch(ds,ds->dev);
273+
}
274+
275+
staticvoiddsa_loop_drv_remove(structmdio_device*mdiodev)
276+
{
277+
structdsa_switch*ds=dev_get_drvdata(&mdiodev->dev);
278+
structdsa_loop_priv*ps=ds->priv;
279+
280+
dsa_unregister_switch(ds);
281+
dev_put(ps->netdev);
282+
}
283+
284+
staticstructmdio_driverdsa_loop_drv= {
285+
.mdiodrv.driver= {
286+
.name="dsa-loop",
287+
},
288+
.probe=dsa_loop_drv_probe,
289+
.remove=dsa_loop_drv_remove,
290+
};
291+
292+
#defineNUM_FIXED_PHYS(DSA_LOOP_NUM_PORTS - 2)
293+
294+
staticvoidunregister_fixed_phys(void)
295+
{
296+
unsignedinti;
297+
298+
for (i=0;i<NUM_FIXED_PHYS;i++)
299+
if (phydevs[i])
300+
fixed_phy_unregister(phydevs[i]);
301+
}
302+
303+
staticint__initdsa_loop_init(void)
304+
{
305+
structfixed_phy_statusstatus= {
306+
.link=1,
307+
.speed=SPEED_100,
308+
.duplex=DUPLEX_FULL,
309+
};
310+
unsignedinti;
311+
312+
for (i=0;i<NUM_FIXED_PHYS;i++)
313+
phydevs[i]=fixed_phy_register(PHY_POLL,&status,-1,NULL);
314+
315+
returnmdio_driver_register(&dsa_loop_drv);
316+
}
317+
module_init(dsa_loop_init);
318+
319+
staticvoid__exitdsa_loop_exit(void)
320+
{
321+
mdio_driver_unregister(&dsa_loop_drv);
322+
unregister_fixed_phys();
323+
}
324+
module_exit(dsa_loop_exit);
325+
326+
MODULE_LICENSE("GPL");
327+
MODULE_AUTHOR("Florian Fainelli");
328+
MODULE_DESCRIPTION("DSA loopback driver");

‎drivers/net/dsa/dsa_loop.h‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef__DSA_LOOP_H
2+
#define__DSA_LOOP_H
3+
4+
structdsa_chip_data;
5+
6+
structdsa_loop_pdata {
7+
/* Must be first, such that dsa_register_switch() can access this
8+
* without gory pointer manipulations
9+
*/
10+
structdsa_chip_datacd;
11+
constchar*name;
12+
unsignedintenabled_ports;
13+
constchar*netdev;
14+
};
15+
16+
#defineDSA_LOOP_NUM_PORTS6
17+
#defineDSA_LOOP_CPU_PORT(DSA_LOOP_NUM_PORTS - 1)
18+
19+
#endif/* __DSA_LOOP_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp