[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <0cca4621-13da-3fa2-cdd9-6a969162c49b@gmail.com>
Date: Thu, 23 May 2019 14:30:30 -0700
From: Florian Fainelli <f.fainelli@...il.com>
To: Vladimir Oltean <olteanv@...il.com>,
Ioana Ciornei <ioana.ciornei@....com>,
"linux@...linux.org.uk" <linux@...linux.org.uk>,
"andrew@...n.ch" <andrew@...n.ch>,
"hkallweit1@...il.com" <hkallweit1@...il.com>,
"maxime.chevallier@...tlin.com" <maxime.chevallier@...tlin.com>
Cc: "netdev@...r.kernel.org" <netdev@...r.kernel.org>,
"davem@...emloft.net" <davem@...emloft.net>
Subject: Re: [RFC PATCH net-next 5/9] net: phylink: Add phylink_create_raw
On 5/23/19 1:32 PM, Vladimir Oltean wrote:
> On 5/23/19 5:32 PM, Florian Fainelli wrote:
>>
>> On 5/23/2019 5:10 AM, Ioana Ciornei wrote:
>>>
>>>> Subject: Re: [RFC PATCH net-next 5/9] net: phylink: Add
>>>> phylink_create_raw
>>>>
>>>>
>>>>
>>>> On 5/22/2019 7:25 PM, Florian Fainelli wrote:
>>>>>
>>>>>
>>>>> On 5/22/2019 6:20 PM, Ioana Ciornei wrote:
>>>>>> This adds a new entry point to PHYLINK that does not require a
>>>>>> net_device structure.
>>>>>>
>>>>>> The main intended use are DSA ports that do not have net devices
>>>>>> registered for them (mainly because doing so would be redundant - see
>>>>>> Documentation/networking/dsa/dsa.rst for details). So far DSA has
>>>>>> been using PHYLIB fixed PHYs for these ports, driven manually with
>>>>>> genphy instead of starting a full PHY state machine, but this does
>>>>>> not scale well when there are actual PHYs that need a driver on those
>>>>>> ports, or when a fixed-link is requested in DT that has a speed
>>>>>> unsupported by the fixed PHY C22 emulation (such as SGMII-2500).
>>>>>>
>>>>>> The proposed solution comes in the form of a notifier chain owned by
>>>>>> the PHYLINK instance, and the passing of phylink_notifier_info
>>>>>> structures back to the driver through a blocking notifier call.
>>>>>>
>>>>>> The event API exposed by the new notifier mechanism is a 1:1 mapping
>>>>>> to the existing PHYLINK mac_ops, plus the PHYLINK fixed-link
>>>>>> callback.
>>>>>>
>>>>>> Both the standard phylink_create() function, as well as its raw
>>>>>> variant, call the same underlying function which initializes either
>>>>>> the netdev field or the notifier block of the PHYLINK instance.
>>>>>>
>>>>>> All PHYLINK driver callbacks have been extended to call the notifier
>>>>>> chain in case the instance is a raw one.
>>>>>>
>>>>>> Signed-off-by: Ioana Ciornei <ioana.ciornei@....com>
>>>>>> Signed-off-by: Vladimir Oltean <olteanv@...il.com>
>>>>>> ---
>>>>>
>>>>> [snip]
>>>>>
>>>>>> + struct phylink_notifier_info info = {
>>>>>> + .link_an_mode = pl->link_an_mode,
>>>>>> + /* Discard const pointer */
>>>>>> + .state = (struct phylink_link_state *)state,
>>>>>> + };
>>>>>> +
>>>>>> netdev_dbg(pl->netdev,
>>>>>> "%s: mode=%s/%s/%s/%s adv=%*pb pause=%02x link=%u
>>>> an=%u\n",
>>>>>> __func__, phylink_an_mode_str(pl->link_an_mode),
>>>>>> @@ -299,7 +317,12 @@ static void phylink_mac_config(struct phylink
>>>>>> *pl,
>>>>>> __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising,
>>>>>> state->pause, state->link, state->an_enabled);
>>>>>
>>>>> Don't you need to guard that netdev_dbg() with an if (pl->ops) to
>>>>> avoid de-referencing a NULL net_device?
>>>>>
>>>
>>>
>>> The netdev_* print will not dereference a NULL net_device since it
>>> has explicit checks agains this.
>>> Instead it will just print (net/core/dev.c, __netdev_printk):
>>>
>>> printk("%s(NULL net_device): %pV", level, vaf);
>>>
>>>
>>>>> Another possibility could be to change the signature of the
>>>>> phylink_mac_ops to take an opaque pointer and in the case where we
>>>>> called phylink_create() and passed down a net_device pointer, we
>>>>> somehow remember that for doing any operation that requires a
>>>>> net_device (printing, setting carrier). We lose strict typing in doing
>>>>> that, but we'd have fewer places to patch for a blocking notifier
>>>>> call.
>>>>>
>>>>
>>>> Or even make those functions part of phylink_mac_ops such that the
>>>> caller
>>>> could pass an .carrier_ok callback which is netif_carrier_ok() for a
>>>> net_device,
>>>> else it's NULL, same with printing functions if desired...
>>>> --
>>>> Florian
>>>
>>>
>>> Let me see if I understood this correctly. I presume that any API
>>> that we add should not break any current PHYLINK users.
>>>
>>> You suggest to change the prototype of the phylink_mac_ops from
>>>
>>> void (*validate)(struct net_device *ndev, unsigned long *supported,
>>> struct phylink_link_state *state);
>>>
>>> to something that takes a void pointer:
>>>
>>> void (*validate)(void *dev, unsigned long *supported,
>>> struct phylink_link_state *state);
>>
>> That is what I am suggesting, but I am also suggesting passing all
>> netdev specific calls that must be made as callbacks as well, so
>> something like:
>>
>> bool (*carrier_ok)(const void *dev)
>> void (*carrier_set)(const void *dev, bool on)
>> void (*print)(const void *dev, const char *fmt)
>>
>> as new members of phylink_mac_ops.
>>
>>>
>>> This would imply that the any function in PHYLINK would have to
>>> somehow differentiate if the dev provided is indeed a net_device or
>>> another structure in order to make the decision if netif_carrier_off
>>> should be called or not (this is so we do not break any drivers using
>>> PHYLINK). I cannot see how this judgement can be made.
>>
>> You don't have to make the judgement you can just do:
>>
>> if (pl->ops->carrier_set)
>> pl->ops->carrier_set(dev,
>>
>> where dev was this opaque pointer passed to phylink_create() the first
>> time it was created. Like I wrote, we lose strong typing doing that, but
>> we don't have to update all code paths for if (pl->ops) else notifier.
>>
>
> Hi Florian,
>
> Have you thought this through?
Not to the point of seeing the problems you are highlighting.
> What about the totally random stuff, such as this portion from 2/9:
>
>> @@ -1187,8 +1190,10 @@ int phy_attach_direct(struct net_device *dev,
>> struct phy_device *phydev,
>> * our own module->refcnt here, otherwise we would not be able to
>> * unload later on.
>> */
>> + if (dev)
>> + ndev_owner = dev->dev.parent->driver->owner;
>> if (ndev_owner != bus->owner && !try_module_get(bus->owner)) {
>> - dev_err(&dev->dev, "failed to get the bus module\n");
>> + phydev_err(phydev, "failed to get the bus module\n");
>> return -EIO;
>> }
>
> Which is in PHYLIB by the way.
> Do you just add a pl->ops->owns_mdio_bus() callback? What if that code
> goes away in the future? Do you remove it? This is code that all users
> of phylink_create_raw will have to implement.
>
> IMO the whole point is to change as little as possible from PHYLINK's
> surface, and nothing from PHYLIB's. What you're suggesting is to change
> everything, *including* phylib. And PHYLINK's print callback can't be
> used in PHYLIB unless struct phylink is made public.
>
> And if you want to replace "struct net_device *ndev" with "const void
> *dev", how will you even assign the phydev->attached_dev->phydev
> backlink? Another callback?
>
> As for carrier state - realistically I don't see how any raw PHYLINK
> user would implement it any other way except keep a variable for it.
> Hence just let PHYLINK do it once.
>
> I fail to see how this is cleaner.
Fine, it's not.
--
Florian
Powered by blists - more mailing lists