Hi,

On Sun Mar 8, 2026 at 12:39 PM CET, vladimir.oltean wrote:
> Consumer drivers shouldn't dereference struct phy, not even to get to
> its attributes.
>
> We have phy_get_bus_width() as a precedent for getting the bus_width
> attribute, so let's add phy_get_max_link_rate() and use it in DRM and
> CAN drivers.
>
> In CAN drivers, the transceiver is acquired through devm_phy_optional_get()
> and NULL is given by the API as a non-error case, so the PHY API should
> also tolerate NULL coming back to it. This means we can further simplify
> the call sites that test for the NULL quality of the transceiver.

Thanks for adding this.

>
> Signed-off-by: Vladimir Oltean <[email protected]>
> ---
> Cc: Andrzej Hajda <[email protected]>
> Cc: Neil Armstrong <[email protected]>
> Cc: Robert Foss <[email protected]>
> Cc: Laurent Pinchart <[email protected]>
> Cc: Jonas Karlman <[email protected]>
> Cc: Jernej Skrabec <[email protected]>
> Cc: Maarten Lankhorst <[email protected]>
> Cc: Maxime Ripard <[email protected]>
> Cc: Thomas Zimmermann <[email protected]>
> Cc: David Airlie <[email protected]>
> Cc: Simona Vetter <[email protected]>
> Cc: Andy Yan <[email protected]>
> Cc: Marc Kleine-Budde <[email protected]>
> Cc: Vincent Mailhol <[email protected]>
> Cc: Nicolas Ferre <[email protected]>
> Cc: Alexandre Belloni <[email protected]>
> Cc: Claudiu Beznea <[email protected]>
> Cc: Markus Schneider-Pargmann <[email protected]>
> Cc: Geert Uytterhoeven <[email protected]>
> Cc: Magnus Damm <[email protected]>
>
> v1->v2: make phy_get_bus_width() NULL-tolerant to simplify CAN callers
> ---
>  drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 4 ++--
>  drivers/gpu/drm/bridge/synopsys/dw-dp.c             | 2 +-
>  drivers/net/can/at91_can.c                          | 3 +--
>  drivers/net/can/flexcan/flexcan-core.c              | 3 +--
>  drivers/net/can/m_can/m_can_platform.c              | 3 +--

For m_can:
Acked-by: Markus Schneider-Pargmann <[email protected]>

Best
Markus

>  drivers/net/can/rcar/rcar_canfd.c                   | 3 +--
>  drivers/phy/phy-core.c                              | 9 +++++++++
>  include/linux/phy/phy.h                             | 6 ++++++
>  8 files changed, 22 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c 
> b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
> index a8b6ae58cb0a..ed7ed82ddb64 100644
> --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
> +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
> @@ -1300,7 +1300,7 @@ static u32 cdns_mhdp_get_training_interval_us(struct 
> cdns_mhdp_device *mhdp,
>  
>  static void cdns_mhdp_fill_host_caps(struct cdns_mhdp_device *mhdp)
>  {
> -     unsigned int link_rate;
> +     u32 link_rate;
>  
>       /* Get source capabilities based on PHY attributes */
>  
> @@ -1308,7 +1308,7 @@ static void cdns_mhdp_fill_host_caps(struct 
> cdns_mhdp_device *mhdp)
>       if (!mhdp->host.lanes_cnt)
>               mhdp->host.lanes_cnt = 4;
>  
> -     link_rate = mhdp->phy->attrs.max_link_rate;
> +     link_rate = phy_get_max_link_rate(mhdp->phy);
>       if (!link_rate)
>               link_rate = drm_dp_bw_code_to_link_rate(DP_LINK_BW_8_1);
>       else
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c 
> b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> index 4ab6922dd79c..79c72ee8e263 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> @@ -536,7 +536,7 @@ static int dw_dp_link_parse(struct dw_dp *dp, struct 
> drm_connector *connector)
>  
>       link->revision = link->dpcd[DP_DPCD_REV];
>       link->rate = min_t(u32, min(dp->plat_data.max_link_rate,
> -                                 dp->phy->attrs.max_link_rate * 100),
> +                                 phy_get_max_link_rate(dp->phy) * 100),
>                          drm_dp_max_link_rate(link->dpcd));
>       link->lanes = min_t(u8, phy_get_bus_width(dp->phy),
>                           drm_dp_max_lane_count(link->dpcd));
> diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
> index 58da323f14d7..7749da0a58f6 100644
> --- a/drivers/net/can/at91_can.c
> +++ b/drivers/net/can/at91_can.c
> @@ -1125,8 +1125,7 @@ static int at91_can_probe(struct platform_device *pdev)
>  
>       can_rx_offload_add_timestamp(dev, &priv->offload);
>  
> -     if (transceiver)
> -             priv->can.bitrate_max = transceiver->attrs.max_link_rate;
> +     priv->can.bitrate_max = phy_get_max_link_rate(transceiver);
>  
>       if (at91_is_sam9263(priv))
>               dev->sysfs_groups[0] = &at91_sysfs_attr_group;
> diff --git a/drivers/net/can/flexcan/flexcan-core.c 
> b/drivers/net/can/flexcan/flexcan-core.c
> index f5d22c61503f..093e48b8da58 100644
> --- a/drivers/net/can/flexcan/flexcan-core.c
> +++ b/drivers/net/can/flexcan/flexcan-core.c
> @@ -2210,8 +2210,7 @@ static int flexcan_probe(struct platform_device *pdev)
>       priv->reg_xceiver = reg_xceiver;
>       priv->transceiver = transceiver;
>  
> -     if (transceiver)
> -             priv->can.bitrate_max = transceiver->attrs.max_link_rate;
> +     priv->can.bitrate_max = phy_get_max_link_rate(transceiver);
>  
>       if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
>               priv->irq_boff = platform_get_irq(pdev, 1);
> diff --git a/drivers/net/can/m_can/m_can_platform.c 
> b/drivers/net/can/m_can/m_can_platform.c
> index 56da411878af..2a0f163a683a 100644
> --- a/drivers/net/can/m_can/m_can_platform.c
> +++ b/drivers/net/can/m_can/m_can_platform.c
> @@ -131,8 +131,7 @@ static int m_can_plat_probe(struct platform_device *pdev)
>               goto probe_fail;
>       }
>  
> -     if (transceiver)
> -             mcan_class->can.bitrate_max = transceiver->attrs.max_link_rate;
> +     mcan_class->can.bitrate_max = phy_get_max_link_rate(transceiver);
>  
>       priv->base = addr;
>       priv->mram_base = mram_addr;
> diff --git a/drivers/net/can/rcar/rcar_canfd.c 
> b/drivers/net/can/rcar/rcar_canfd.c
> index eaf8cac78038..9062db48d477 100644
> --- a/drivers/net/can/rcar/rcar_canfd.c
> +++ b/drivers/net/can/rcar/rcar_canfd.c
> @@ -1884,8 +1884,7 @@ static int rcar_canfd_channel_probe(struct 
> rcar_canfd_global *gpriv, u32 ch,
>       priv->transceiver = transceiver;
>       priv->channel = ch;
>       priv->gpriv = gpriv;
> -     if (transceiver)
> -             priv->can.bitrate_max = transceiver->attrs.max_link_rate;
> +     priv->can.bitrate_max = phy_get_max_link_rate(transceiver);
>       priv->can.clock.freq = fcan_freq;
>       dev_info(dev, "can_clk rate is %u\n", priv->can.clock.freq);
>  
> diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
> index 0d0be494cfd7..737a760d97d1 100644
> --- a/drivers/phy/phy-core.c
> +++ b/drivers/phy/phy-core.c
> @@ -647,6 +647,15 @@ void phy_set_bus_width(struct phy *phy, int bus_width)
>  }
>  EXPORT_SYMBOL_GPL(phy_set_bus_width);
>  
> +u32 phy_get_max_link_rate(struct phy *phy)
> +{
> +     if (!phy)
> +             return 0;
> +
> +     return phy->attrs.max_link_rate;
> +}
> +EXPORT_SYMBOL_GPL(phy_get_max_link_rate);
> +
>  /**
>   * _of_phy_get() - lookup and obtain a reference to a phy by phandle
>   * @np: device_node for which to get the phy
> diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
> index a7e2432ca1ae..34b656084caf 100644
> --- a/include/linux/phy/phy.h
> +++ b/include/linux/phy/phy.h
> @@ -57,6 +57,7 @@ int phy_notify_disconnect(struct phy *phy, int port);
>  int phy_notify_state(struct phy *phy, union phy_notify state);
>  int phy_get_bus_width(struct phy *phy);
>  void phy_set_bus_width(struct phy *phy, int bus_width);
> +u32 phy_get_max_link_rate(struct phy *phy);
>  #else
>  static inline struct phy *phy_get(struct device *dev, const char *string)
>  {
> @@ -256,6 +257,11 @@ static inline int phy_get_bus_width(struct phy *phy)
>  static inline void phy_set_bus_width(struct phy *phy, int bus_width)
>  {
>  }
> +
> +static inline u32 phy_get_max_link_rate(struct phy *phy)
> +{
> +     return 0;
> +}
>  #endif /* IS_ENABLED(CONFIG_GENERIC_PHY) */
>  
>  #endif /* __PHY_CONSUMER_H */

Attachment: signature.asc
Description: PGP signature

Reply via email to