Re: [PATCH RFC net-next 6/7] net: dsa: mv88e6xxx: provide software node for default settings

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Russell,

On Mon, Mar 27, 2023 at 11:55:00AM +0100, Russell King (Oracle) wrote:
> On Mon, Mar 27, 2023 at 01:28:06PM +0300, Heikki Krogerus wrote:
> > On Fri, Mar 24, 2023 at 05:04:25PM +0000, Russell King (Oracle) wrote:
> > > On Fri, Mar 24, 2023 at 04:49:32PM +0200, Heikki Krogerus wrote:
> > > > Hi Russell,
> > > > 
> > > > On Wed, Mar 22, 2023 at 12:00:21PM +0000, Russell King (Oracle) wrote:
> > > > > +static struct fwnode_handle *mv88e6xxx_create_fixed_swnode(struct fwnode_handle *parent,
> > > > > +							   int speed,
> > > > > +							   int duplex)
> > > > > +{
> > > > > +	struct property_entry fixed_link_props[3] = { };
> > > > > +
> > > > > +	fixed_link_props[0] = PROPERTY_ENTRY_U32("speed", speed);
> > > > > +	if (duplex == DUPLEX_FULL)
> > > > > +		fixed_link_props[1] = PROPERTY_ENTRY_BOOL("full-duplex");
> > > > > +
> > > > > +	return fwnode_create_named_software_node(fixed_link_props, parent,
> > > > > +						 "fixed-link");
> > > > > +}
> > > > > +
> > > > > +static struct fwnode_handle *mv88e6xxx_create_port_swnode(phy_interface_t mode,
> > > > > +							  int speed,
> > > > > +							  int duplex)
> > > > > +{
> > > > > +	struct property_entry port_props[2] = {};
> > > > > +	struct fwnode_handle *fixed_link_fwnode;
> > > > > +	struct fwnode_handle *new_port_fwnode;
> > > > > +
> > > > > +	port_props[0] = PROPERTY_ENTRY_STRING("phy-mode", phy_modes(mode));
> > > > > +	new_port_fwnode = fwnode_create_software_node(port_props, NULL);
> > > > > +	if (IS_ERR(new_port_fwnode))
> > > > > +		return new_port_fwnode;
> > > > > +
> > > > > +	fixed_link_fwnode = mv88e6xxx_create_fixed_swnode(new_port_fwnode,
> > > > > +							  speed, duplex);
> > > > > +	if (IS_ERR(fixed_link_fwnode)) {
> > > > > +		fwnode_remove_software_node(new_port_fwnode);
> > > > > +		return fixed_link_fwnode;
> > > > > +	}
> > > > > +
> > > > > +	return new_port_fwnode;
> > > > > +}
> > > > 
> > > > That new fwnode_create_named_software_node() function looks like a
> > > > conflict waiting to happen - if a driver adds a node to the root level
> > > > (does not have to be root level), all the tests will pass because
> > > > there is only a single device, but when a user later tries the driver
> > > > with two devices, it fails, because the node already exist. But you
> > > > don't need that function at all.
> > > 
> > > I think you're totally failing to explain how this can fail.
> > > 
> > > Let me reiterate what thestructure of the swnodes here is:
> > > 
> > > 	root
> > > 	`- node%d (%d allocated by root IDA)
> > > 	   +- phy-mode property
> > > 	   `- fixed-link
> > > 	      +- speed property
> > > 	      `- optional full-duplex property
> > > 
> > > If we have two different devices creating these nodes, then at the
> > > root level, they will end up having different root names. The
> > > "fixed-link" is a child of this node.
> > 
> > Ah, sorry, the problem is not with this patch, or your use case. The
> > problem is with the PATCH 1/7 of this series where you introduce that
> > new function fwnode_create_named_software_node() which will not be
> > tied to your use case only. In this patch you just use that function.
> > I should have been more clear on that.
> 
> How is this any different from creating two struct device's with the
> same parent and the same name? Or kobject_add() with the same parent
> and name?

But that can not mean we have to take the same risk everywhere. I do
understand that we don't protect developers from doing silly decisions
in kernel, but that does not mean that we should simply accept
interfaces into the kernel that expose these risk if we don't need
them.

> > I really just wanted to show how you can create those nodes by using
> > the API designed for the statically described software nodes. So you
> > don't need that new function. Please check that proposal from my
> > original reply.
> 
> I don't see why I should. This is clearly a case that if one creates
> two named nodes with the same name and same parent, it should fail and
> it's definitely a "well don't do that then" in just the same way that
> one doesn't do it with kobject_add() or any of the other numerous
> interfaces that take names in a space that need to be unique.
> 
> I really don't think there is any issue here to be solved. In fact,
> I think solving it will add additional useless complexity that just
> isn't required - which adds extra code that can be wrong and fail.
> 
> Let's keep this simple. This approach is simple. If one does something
> stupid (like creating two named nodes with the same name and same
> parent) then it will verbosely fail. That is a good thing.

Well, I think the most simplest approach would be to have both the
nodes and the properties as part of that struct mv88e6xxx_chip:

struct mv88e6xxx_chip {
        ...
       struct property_entry port_props[2];
       struct property_entry fixed_link_props[3];

       struct software_node port_swnode;
       struct software_node fixed_link_swnode;
};

That allows you to register both nodes in one go:

static struct fwnode_handle *mv88e6xxx_create_port_swnode(struct mv88e6xxx_chip *chip,
                                                          phy_interface_t mode,
                                                          int speed,
                                                          int duplex)
{
        struct software_node *nodes[3] = {
                &chip->port_swnode,
                &chip->fixed_link_swnode,
        };
        int ret;

        chip->port_props[0] = PROPERTY_ENTRY_STRING("phy-mode", phy_modes(mode));
        chip->port_swnode.properties = chip->port_props;

        chip->fixed_link_props[0] = PROPERTY_ENTRY_U32("speed", speed);
        if (duplex == DUPLEX_FULL)
                chip->fixed_link_props[1] = PROPERTY_ENTRY_BOOL("full-duplex");

        chip->fixed_link_swnode.name = "fixed-link";
        chip->fixed_link_swnode.parent = &chip->port_swnode;
        chip->fixed_link_swnode.properties = chip->fixed_link_props;

        ret = software_node_register_node_group(nodes);
        if (ret)
                return ERR_PTR(ret);

        return software_node_fwnode(&chip->port_swnode);
}

> Internal kernel APIs are not supposed to protect people from being
> stupid.

This is an interesting topic. I used to agree with this
idea/philosophy without much thought, but then after (years of :-)
listening maintainers complaining about how new developers always
repeat the same mistakes over an over again, I've started thinking
about it. To use a bit rough analog, if we give a gun to a monkey, how
can we be surprised if if ends up shooting first its mates and then
its own brains out...

Perhaps this is a more generic subject, a topic for some conference
maybe, but I in any case don't think this is a black and white matter.
A little bit of protection is not only a harmful thing and always only
in the way of flexibility.

At the very least, I don't think we should not use this philosophy as
an argument for doing things in ways that may expose even minute risks
in the cases like this were an alternative approach already exists.

Br,

-- 
heikki



[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]
  Powered by Linux