Re: [PATCH net-next v3 06/10] net: dsa: Migrate to device_find_class()
From: Greg KH
Date: Thu Jan 19 2017 - 09:41:03 EST
On Mon, Jan 16, 2017 at 12:01:02PM -0800, Florian Fainelli wrote:
> On 01/15/2017 11:16 AM, Andrew Lunn wrote:
> >>> What exactly is the relationship between these devices (a ascii-art tree
> >>> or sysfs tree output might be nice) so I can try to understand what is
> >>> going on here.
> >
> > Hi Greg, Florian
> >
> > A few diagrams and trees which might help understand what is going on.
> >
> > The first diagram comes from the 2008 patch which added all this code:
> >
> > +-----------+ +-----------+
> > | | RGMII | |
> > | +-------+ +------ 1000baseT MDI ("WAN")
> > | | | 6-port +------ 1000baseT MDI ("LAN1")
> > | CPU | | ethernet +------ 1000baseT MDI ("LAN2")
> > | |MIImgmt| switch +------ 1000baseT MDI ("LAN3")
> > | +-------+ w/5 PHYs +------ 1000baseT MDI ("LAN4")
> > | | | |
> > +-----------+ +-----------+
> >
> > We have an ethernet switch and a host CPU. The switch is connected to
> > the CPU in two different ways. RGMII allows us to get Ethernet frames
> > from the CPU into the switch. MIImgmt, is the management bus normally
> > used for Ethernet PHYs, but Marvell switches also use it for Managing
> > switches.
> >
> > The diagram above is the simplest setup. You can have multiple
> > Ethernet switches, connected together via switch ports. Each switch
> > has its own MIImgmt connect to the CPU, but there is only one RGMII
> > link.
> >
> > When this code was designed back in 2008, it was decided to represent
> > this is a platform device, and it has a platform_data, which i have
> > slightly edited to keep it simple:
> >
> > struct dsa_platform_data {
> > /*
> > * Reference to a Linux network interface that connects
> > * to the root switch chip of the tree.
> > */
> > struct device *netdev;
This I think is the oddest thing, why do you need to have the "root
switch" here? You seem to have dropped the next value in this
structure:
struct net_device *of_netdev;
Isn't that the "real" net_device you need/want to get to here?
Or, when you set netdev, can't you also point to the "real" net_device
you want to later get to?
> > /*
> > * Info structs describing each of the switch chips
> > * connected via this network interface.
> > */
> > int nr_chips;
> > struct dsa_chip_data *chip;
> > };
> >
> > This netdev is the CPU side of the RGMII interface.
> >
> > Each switch has a dsa_chip_data, again edited:
> >
> > struct dsa_chip_data {
> > /*
> > * How to access the switch configuration registers.
> > */
> > struct device *host_dev;
> > int sw_addr;
> > ...
> > }
If each switch only has one dsa_chip_data, can't you point directly from
that structure back to the dsa_platform_device? Or is that what this
"host_dev" pointer is pointing to?
> > The host_dev is the CPU side of the MIImgmt, and we have the address
> > the switch is using on the bus.
"cpu side" means what? What 'struct device' is this? The host
controller? The platform device? Something else?
> > During probe of this platform device, we need to get from the
> > struct device *netdev to a struct net_device *dev.
Wait, what exactly is this "struct device *"? Who created it?
And why are you using a platform device? Shouldn't this be a custom
bus? I know people like to abuse platform devices, is that the case
here, or is it really driven only by a device tree representation?
Shouldn't you have a bus for RGMII devices? Is that the real problem
here, you don't have a representation for your RGMII "bus" with a
controller to bundle everything under (like a USB host controller, it
bridges from one bus to another).
> > So the code looks in the device net class to find the device
> >
> > | | | |-- f1074000.ethernet
> > | | | | |-- deferred_probe
> > | | | | |-- driver -> ../../../../../bus/platform/drivers/mvneta
> > | | | | |-- driver_override
> > | | | | |-- modalias
> > | | | | |-- net
> > | | | | | `-- eth1
> > | | | | | |-- addr_assign_type
> > | | | | | |-- address
> > | | | | | |-- addr_len
> > | | | | | |-- broadcast
> > | | | | | |-- carrier
> > | | | | | |-- carrier_changes
> > | | | | | |-- deferred_probe
> > | | | | | |-- device -> ../../../f1074000.ethernet
> >
> > and then use container_of() to get the net_device.
What 'struct device *' are you passing to container_of() here? The one
representing eth1? What call is this? And where are you trying to go
from there, to a peer? Why?
> > Similarly, the code needs to get from struct device *host_dev to a struct mii_bus *.
> >
> > | | | |-- f1072004.mdio
> > | | | | |-- deferred_probe
> > | | | | |-- driver -> ../../../../../bus/platform/drivers/orion-mdio
> > | | | | |-- driver_override
> > | | | | |-- mdio_bus
> > | | | | | `-- f1072004.mdio-mi
> > | | | | | |-- deferred_probe
> > | | | | | |-- device -> ../../../f1072004.mdio
Ok, this looks like the "peer" you want to get to from eth1, you want
f1072004.mdio-mi, right?
If so, why is eth1 not below f1072004.mdio-mi in the heirachy already?
Why is it up attached to the parent device, making this a "flat"
heirachy?
That's what is confusing about your functions, you are just walking all
of the "child" devices of a specific struct device, trying to find the
first random one that happens to belong to a specific 'bus' because you
are related to it.
Which is wrong, eth1 should be a child of your bus device, that way you
"know" how to get to it (it's your parent!).
So, I'm still confused, and still think this is all wrong, but feel free
to prove me wrong about this :)
thanks,
greg k-h