[PATCH net-next v7 02/12] net: phylink: introduce internal phylink PCS handling
Christian Marangi
ansuelsmth at gmail.com
Mon Jun 15 07:17:07 PDT 2026
On Mon, Jun 15, 2026 at 03:31:20PM +0200, Maxime Chevallier wrote:
> Hi Christian,
>
> On 6/15/26 14:29, Christian Marangi wrote:
> > Introduce internal handling of PCS for phylink. This is an alternative
> > way to .mac_select_pcs that moves the selection logic of the PCS entirely
> > to phylink with the usage of the supported_interface value in the PCS
> > struct.
> >
> > MAC should now provide a callback to fill the available PCS in
> > phylink_config in .fill_available_pcs and fill the .num_possible_pcs with
> > the number of elements in the array. MAC should also define a new bitmap,
> > pcs_interfaces, in phylink_config to define for what interface mode a
> > dedicated PCS is required.
> >
> > On phylink_create(), an array of PCS pointer is allocated of size
> > .num_possible_pcs from phylink_config and .fill_available_pcs from
> > phylink_config is called passing as args the just allocated array and
> > the number of possible element in it.
> >
> > MAC will fill this passed array with all the available PCS.
> >
> > This array is then parsed and a linked list of PCS is created based on
> > the allocated PCS array filled by MAC via .fill_available_pcs().
> >
> > Every PCS in phylink PCS list gets then linked to the phylink instance
> > by setting the phylink value in phylink_pcs struct to the phylink instance.
> > Also the supported_interface value in phylink struct is updated with
> > the new supported_interface from the provided PCS.
> >
> > On phylink_destroy(), every PCS in phylink PCS list is unlinked from the
> > phylink instance by setting the phylink value in phylink_pcs struct to NULL
> > and removed from the PCS list.
> >
> > phylink_validate_mac_and_pcs(), phylink_major_config() and
> > phylink_inband_caps() are updated to support this new implementation
> > with the PCS list stored in phylink.
> >
> > They will make use of phylink_validate_pcs_interface() that will loop
> > for every PCS in the phylink PCS available list and find one that supports
> > the passed interface.
> >
> > phylink_validate_pcs_interface() applies the same logic of .mac_select_pcs
> > where if a supported_interface value is not set for the PCS struct, then
> > it's assumed every interface is supported.
> >
> > A MAC is required to implement either a .mac_select_pcs or make use of
> > the PCS list implementation. Implementing both will result in a fail
> > on phylink_create().
> >
> > A MAC defining .num_possible_pcs in phylink_config MUST also define a
> > .fill_available_pcs or phylink_create() will fail with an negative error.
> >
> > phylink value in phylink_pcs struct with this implementation is used to
> > track from PCS side when it's attached to a phylink instance. PCS driver
> > will make use of this information to correctly detach from a phylink
> > instance if needed.
> >
> > phylink_pcs_change() is also changed to verify that the PCS that triggered
> > a link change is the one that is currently used by the phylink instance.
> >
> > The .mac_select_pcs implementation is not changed but it's expected that
> > every MAC driver migrates to the new implementation to later deprecate
> > and remove .mac_select_pcs.
> >
> > Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
> > ---
>
> [...]
>
> > @@ -1872,10 +1993,28 @@ struct phylink *phylink_create(struct phylink_config *config,
> > mutex_init(&pl->phydev_mutex);
> > mutex_init(&pl->state_mutex);
> > INIT_WORK(&pl->resolve, phylink_resolve);
> > + INIT_LIST_HEAD(&pl->pcs_list);
> > +
> > + /* Fill the PCS list with available PCS from phylink config */
> > + ret = phylink_fill_available_pcs(pl, config);
> > + if (ret < 0) {
> > + kfree(pl);
> > + return ERR_PTR(ret);
> > + }
> > +
> > + /* Link available PCS to phylink */
> > + list_for_each_entry(pcs, &pl->pcs_list, list)
> > + pcs->phylink = pl;
> >
> > phy_interface_copy(pl->supported_interfaces,
> > config->supported_interfaces);
> >
> > + /* Update supported interfaces */
> > + list_for_each_entry(pcs, &pl->pcs_list, list)
> > + phy_interface_or(pl->supported_interfaces,
> > + pl->supported_interfaces,
> > + pcs->supported_interfaces);
> > +
>
> I'm not entirely sure about that, we may need to restrict the supported_interfaces
> from the MAC.
>
> As an example, take mvpp2. We have 2 PCSs, one for BaseX/SGMII, one for BaseR. But
> if we don't have a comphy (generic PHY) device, then we can't use all the
> combination of modes our PCSs can provide :
>
> https://elixir.bootlin.com/linux/v7.1-rc7/source/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c#L7074
>
> These aren't external PCS IPs, but from what I understand you'd like to
> handle these the same way as purely external PCSs, right ?
>
> I'd say the MAC driver utltimately has the knowledge of all possible interfaces.
>
> The way I see it, it's probably safer to let the MAC give a wide range of interfaces,
> and filter that down with what the PCSs can provide (i.e. turn that or into an and,
> while handling the case where the pcs supported interfaces is empty).
>
> What do you think ?
>
The idea is that supported_interface is a mask of every possible interface
from MAC and PCS. Then it's phylink_validate_mac_and_pcs that actually use
that mask and validates it on both MAC and PCS.
This is why the OR was used instead of AND. The idea is to have the PCS as
external standalone entry (even if they are internal to the MAC). So each
entry should have they own set of supported mask.
The previous patch and this try to address this problem where phylink is
actually clueless of what is actually supported exactly because it's has
been given MAC too much freedom of modelling limitation internally.
I feel limitation should be handled by their dedicated function with
.pcs_validate and .mac_get_caps.
Just my idea on this, if needed it's totally ok to simplify this and let
MAC entirely handle the mask. (but I feel the current idea of phylink code
was to have a generic mask in supported_interfaces and then verify MAC and
PCS in phylink_validate_mac_and_pcs())
But by thinking on it more, following your case of mvpp2, with this new
PCS:
- You need a PCS for the .get_state.
- And such PCS will have the supported interface set 1000baseX and
2500BaseX (as that is what is actually supported in HW)
Either some magic is done in .pcs_validate to deny changing the interface
that was initially configured or this gets limited at the
supported_interface configured by the MAC.
I need to check if this might be problematic for the other driver where
this is being used on OpenWrt but maybe changing the logic to an AND might
be sensible for these kind of case.
(for the other it shouldn't change anything)
--
Ansuel
More information about the linux-arm-kernel
mailing list