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.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Acked-by: Markus Schneider-Pargmann <msp@baylibre.com> # m_can
---
Cc: Andrzej Hajda <andrzej.hajda@intel.com>
Cc: Neil Armstrong <neil.armstrong@linaro.org>
Cc: Robert Foss <rfoss@kernel.org>
Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
Cc: Jonas Karlman <jonas@kwiboo.se>
Cc: Jernej Skrabec <jernej.skrabec@gmail.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: David Airlie <airlied@gmail.com>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Andy Yan <andy.yan@rock-chips.com>
Cc: Marc Kleine-Budde <mkl@pengutronix.de>
Cc: Vincent Mailhol <mailhol@kernel.org>
Cc: Nicolas Ferre <nicolas.ferre@microchip.com>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Claudiu Beznea <claudiu.beznea@tuxon.dev>
Cc: Markus Schneider-Pargmann <msp@baylibre.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Magnus Damm <magnus.damm@gmail.com>
v3->v6: none
v2->v3: collect tag
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 +--
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(-)
@@ -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
@@ -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));
@@ -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;
@@ -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);
@@ -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;
@@ -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);
@@ -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
@@ -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 */