From fdf6491193e411087ae77bcbc6468e3e1cff99ed Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 20 Feb 2023 17:24:00 +0100 Subject: netfilter: ctnetlink: make event listener tracking global pernet tracking doesn't work correctly because other netns might have set NETLINK_LISTEN_ALL_NSID on its event socket. In this case its expected that events originating in other net namespaces are also received. Making pernet-tracking work while also honoring NETLINK_LISTEN_ALL_NSID requires much more intrusive changes both in netlink and nfnetlink, f.e. adding a 'setsockopt' callback that lets nfnetlink know that the event socket entered (or left) ALL_NSID mode. Move to global tracking instead: if there is an event socket anywhere on the system, all net namespaces which have conntrack enabled and use autobind mode will allocate the ecache extension. netlink_has_listeners() returns false only if the given group has no subscribers in any net namespace, the 'net' argument passed to nfnetlink_has_listeners is only used to derive the protocol (nfnetlink), it has no other effect. For proper NETLINK_LISTEN_ALL_NSID-aware pernet tracking of event listeners a new netlink_has_net_listeners() is also needed. Fixes: 90d1daa45849 ("netfilter: conntrack: add nf_conntrack_events autodetect mode") Reported-by: Bryce Kahle Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter.h | 5 +++++ include/net/netns/conntrack.h | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index d8817d381c14..bef8db9d6c08 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -488,4 +488,9 @@ extern const struct nfnl_ct_hook __rcu *nfnl_ct_hook; */ DECLARE_PER_CPU(bool, nf_skb_duplicated); +/** + * Contains bitmask of ctnetlink event subscribers, if any. + * Can't be pernet due to NETLINK_LISTEN_ALL_NSID setsockopt flag. + */ +extern u8 nf_ctnetlink_has_listener; #endif /*__LINUX_NETFILTER_H*/ diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index e1290c159184..1f463b3957c7 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h @@ -95,7 +95,6 @@ struct nf_ip_net { struct netns_ct { #ifdef CONFIG_NF_CONNTRACK_EVENTS - u8 ctnetlink_has_listener; bool ecache_dwork_pending; #endif u8 sysctl_log_invalid; /* Log invalid packets */ -- cgit v1.2.3 From b6478b8c93304fa0483e4657779b44634a1711c7 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Wed, 22 Feb 2023 06:50:41 +0100 Subject: net: phy: c45: add genphy_c45_an_config_eee_aneg() function Add new genphy_c45_an_config_eee_aneg() function and replace some of genphy_c45_write_eee_adv() calls. This will be needed by the next patch. Signed-off-by: Oleksij Rempel Reviewed-by: Russell King (Oracle) Signed-off-by: Paolo Abeni --- drivers/net/phy/phy-c45.c | 11 ++++++++++- drivers/net/phy/phy_device.c | 2 +- include/linux/phy.h | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index f23cce2c5199..784868e818a7 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -262,7 +262,7 @@ int genphy_c45_an_config_aneg(struct phy_device *phydev) linkmode_and(phydev->advertising, phydev->advertising, phydev->supported); - ret = genphy_c45_write_eee_adv(phydev, phydev->supported_eee); + ret = genphy_c45_an_config_eee_aneg(phydev); if (ret < 0) return ret; else if (ret) @@ -858,6 +858,15 @@ int genphy_c45_read_eee_abilities(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(genphy_c45_read_eee_abilities); +/** + * genphy_c45_an_config_eee_aneg - configure EEE advertisement + * @phydev: target phy_device struct + */ +int genphy_c45_an_config_eee_aneg(struct phy_device *phydev) +{ + return genphy_c45_write_eee_adv(phydev, phydev->supported_eee); +} + /** * genphy_c45_pma_read_abilities - read supported link modes from PMA * @phydev: target phy_device struct diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 71becceb8764..570a5803f9c2 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -2231,7 +2231,7 @@ int __genphy_config_aneg(struct phy_device *phydev, bool changed) { int err; - err = genphy_c45_write_eee_adv(phydev, phydev->supported_eee); + err = genphy_c45_an_config_eee_aneg(phydev); if (err < 0) return err; else if (err) diff --git a/include/linux/phy.h b/include/linux/phy.h index 727bff531a14..19d83e112beb 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1765,6 +1765,7 @@ int genphy_c45_ethtool_get_eee(struct phy_device *phydev, int genphy_c45_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data); int genphy_c45_write_eee_adv(struct phy_device *phydev, unsigned long *adv); +int genphy_c45_an_config_eee_aneg(struct phy_device *phydev); /* Generic C45 PHY driver */ extern struct phy_driver genphy_c45_driver; -- cgit v1.2.3 From 3eeca4e199cee2066c65b872391cecee5cbbbb81 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Wed, 22 Feb 2023 06:50:42 +0100 Subject: net: phy: do not force EEE support With following patches: commit 9b01c885be36 ("net: phy: c22: migrate to genphy_c45_write_eee_adv()") commit 5827b168125d ("net: phy: c45: migrate to genphy_c45_write_eee_adv()") we set the advertisement to potentially supported values. This behavior may introduce new regressions on systems where EEE was disabled by default (BIOS or boot loader configuration or by other ways.) At same time, with this patches, we would overwrite EEE advertisement configuration made over ethtool. To avoid this issues, we need to cache initial and ethtool advertisement configuration and store it for later use. Fixes: 9b01c885be36 ("net: phy: c22: migrate to genphy_c45_write_eee_adv()") Fixes: 5827b168125d ("net: phy: c45: migrate to genphy_c45_write_eee_adv()") Fixes: 022c3f87f88e ("net: phy: add genphy_c45_ethtool_get/set_eee() support") Signed-off-by: Oleksij Rempel Reviewed-by: Russell King (Oracle) Signed-off-by: Paolo Abeni --- drivers/net/phy/phy-c45.c | 24 +++++++++++++++++------- drivers/net/phy/phy_device.c | 19 +++++++++++++++++++ include/linux/phy.h | 5 +++++ 3 files changed, 41 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 784868e818a7..8717c122e2f3 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -721,8 +721,7 @@ int genphy_c45_write_eee_adv(struct phy_device *phydev, unsigned long *adv) * @phydev: target phy_device struct * @adv: the linkmode advertisement status */ -static int genphy_c45_read_eee_adv(struct phy_device *phydev, - unsigned long *adv) +int genphy_c45_read_eee_adv(struct phy_device *phydev, unsigned long *adv) { int val; @@ -864,7 +863,13 @@ EXPORT_SYMBOL_GPL(genphy_c45_read_eee_abilities); */ int genphy_c45_an_config_eee_aneg(struct phy_device *phydev) { - return genphy_c45_write_eee_adv(phydev, phydev->supported_eee); + if (!phydev->eee_enabled) { + __ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {}; + + return genphy_c45_write_eee_adv(phydev, adv); + } + + return genphy_c45_write_eee_adv(phydev, phydev->advertising_eee); } /** @@ -1430,17 +1435,22 @@ EXPORT_SYMBOL(genphy_c45_ethtool_get_eee); int genphy_c45_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data) { - __ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {}; int ret; if (data->eee_enabled) { if (data->advertised) - adv[0] = data->advertised; + ethtool_convert_legacy_u32_to_link_mode(phydev->advertising_eee, + data->advertised); else - linkmode_copy(adv, phydev->supported_eee); + linkmode_copy(phydev->advertising_eee, + phydev->supported_eee); + + phydev->eee_enabled = true; + } else { + phydev->eee_enabled = false; } - ret = genphy_c45_write_eee_adv(phydev, adv); + ret = genphy_c45_an_config_eee_aneg(phydev); if (ret < 0) return ret; if (ret > 0) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 570a5803f9c2..3f8a64fb9d71 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -3141,6 +3141,25 @@ static int phy_probe(struct device *dev) of_set_phy_supported(phydev); phy_advertise_supported(phydev); + /* Get PHY default EEE advertising modes and handle them as potentially + * safe initial configuration. + */ + err = genphy_c45_read_eee_adv(phydev, phydev->advertising_eee); + if (err) + return err; + + /* There is no "enabled" flag. If PHY is advertising, assume it is + * kind of enabled. + */ + phydev->eee_enabled = !linkmode_empty(phydev->advertising_eee); + + /* Some PHYs may advertise, by default, not support EEE modes. So, + * we need to clean them. + */ + if (phydev->eee_enabled) + linkmode_and(phydev->advertising_eee, phydev->supported_eee, + phydev->advertising_eee); + /* Get the EEE modes we want to prohibit. We will ask * the PHY stop advertising these mode later on */ diff --git a/include/linux/phy.h b/include/linux/phy.h index 19d83e112beb..36bf0bbc8efa 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -575,6 +575,8 @@ struct macsec_ops; * @advertising: Currently advertised linkmodes * @adv_old: Saved advertised while power saving for WoL * @supported_eee: supported PHY EEE linkmodes + * @advertising_eee: Currently advertised EEE linkmodes + * @eee_enabled: Flag indicating whether the EEE feature is enabled * @lp_advertising: Current link partner advertised linkmodes * @host_interfaces: PHY interface modes supported by host * @eee_broken_modes: Energy efficient ethernet modes which should be prohibited @@ -681,6 +683,8 @@ struct phy_device { __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old); /* used for eee validation */ __ETHTOOL_DECLARE_LINK_MODE_MASK(supported_eee); + __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising_eee); + bool eee_enabled; /* Host supported PHY interface types. Should be ignored if empty. */ DECLARE_PHY_INTERFACE_MASK(host_interfaces); @@ -1766,6 +1770,7 @@ int genphy_c45_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data); int genphy_c45_write_eee_adv(struct phy_device *phydev, unsigned long *adv); int genphy_c45_an_config_eee_aneg(struct phy_device *phydev); +int genphy_c45_read_eee_adv(struct phy_device *phydev, unsigned long *adv); /* Generic C45 PHY driver */ extern struct phy_driver genphy_c45_driver; -- cgit v1.2.3 From 68ba44639537de6f91fe32783766322d41848127 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Wed, 22 Feb 2023 12:07:21 -0500 Subject: sctp: add a refcnt in sctp_stream_priorities to avoid a nested loop With this refcnt added in sctp_stream_priorities, we don't need to traverse all streams to check if the prio is used by other streams when freeing one stream's prio in sctp_sched_prio_free_sid(). This can avoid a nested loop (up to 65535 * 65535), which may cause a stuck as Ying reported: watchdog: BUG: soft lockup - CPU#23 stuck for 26s! [ksoftirqd/23:136] Call Trace: sctp_sched_prio_free_sid+0xab/0x100 [sctp] sctp_stream_free_ext+0x64/0xa0 [sctp] sctp_stream_free+0x31/0x50 [sctp] sctp_association_free+0xa5/0x200 [sctp] Note that it doesn't need to use refcount_t type for this counter, as its accessing is always protected under the sock lock. v1->v2: - add a check in sctp_sched_prio_set to avoid the possible prio_head refcnt overflow. Fixes: 9ed7bfc79542 ("sctp: fix memory leak in sctp_stream_outq_migrate()") Reported-by: Ying Xu Acked-by: Marcelo Ricardo Leitner Signed-off-by: Xin Long Link: https://lore.kernel.org/r/825eb0c905cb864991eba335f4a2b780e543f06b.1677085641.git.lucien.xin@gmail.com Signed-off-by: Jakub Kicinski --- include/net/sctp/structs.h | 1 + net/sctp/stream_sched_prio.c | 52 ++++++++++++++++++-------------------------- 2 files changed, 22 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index afa3781e3ca2..e1f6e7fc2b11 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1412,6 +1412,7 @@ struct sctp_stream_priorities { /* The next stream in line */ struct sctp_stream_out_ext *next; __u16 prio; + __u16 users; }; struct sctp_stream_out_ext { diff --git a/net/sctp/stream_sched_prio.c b/net/sctp/stream_sched_prio.c index 42d4800f263d..4d4d9da331f4 100644 --- a/net/sctp/stream_sched_prio.c +++ b/net/sctp/stream_sched_prio.c @@ -25,6 +25,18 @@ static void sctp_sched_prio_unsched_all(struct sctp_stream *stream); +static struct sctp_stream_priorities *sctp_sched_prio_head_get(struct sctp_stream_priorities *p) +{ + p->users++; + return p; +} + +static void sctp_sched_prio_head_put(struct sctp_stream_priorities *p) +{ + if (p && --p->users == 0) + kfree(p); +} + static struct sctp_stream_priorities *sctp_sched_prio_new_head( struct sctp_stream *stream, int prio, gfp_t gfp) { @@ -38,6 +50,7 @@ static struct sctp_stream_priorities *sctp_sched_prio_new_head( INIT_LIST_HEAD(&p->active); p->next = NULL; p->prio = prio; + p->users = 1; return p; } @@ -53,7 +66,7 @@ static struct sctp_stream_priorities *sctp_sched_prio_get_head( */ list_for_each_entry(p, &stream->prio_list, prio_sched) { if (p->prio == prio) - return p; + return sctp_sched_prio_head_get(p); if (p->prio > prio) break; } @@ -70,7 +83,7 @@ static struct sctp_stream_priorities *sctp_sched_prio_get_head( */ break; if (p->prio == prio) - return p; + return sctp_sched_prio_head_get(p); } /* If not even there, allocate a new one. */ @@ -154,32 +167,21 @@ static int sctp_sched_prio_set(struct sctp_stream *stream, __u16 sid, struct sctp_stream_out_ext *soute = sout->ext; struct sctp_stream_priorities *prio_head, *old; bool reschedule = false; - int i; + + old = soute->prio_head; + if (old && old->prio == prio) + return 0; prio_head = sctp_sched_prio_get_head(stream, prio, gfp); if (!prio_head) return -ENOMEM; reschedule = sctp_sched_prio_unsched(soute); - old = soute->prio_head; soute->prio_head = prio_head; if (reschedule) sctp_sched_prio_sched(stream, soute); - if (!old) - /* Happens when we set the priority for the first time */ - return 0; - - for (i = 0; i < stream->outcnt; i++) { - soute = SCTP_SO(stream, i)->ext; - if (soute && soute->prio_head == old) - /* It's still in use, nothing else to do here. */ - return 0; - } - - /* No hits, we are good to free it. */ - kfree(old); - + sctp_sched_prio_head_put(old); return 0; } @@ -206,20 +208,8 @@ static int sctp_sched_prio_init_sid(struct sctp_stream *stream, __u16 sid, static void sctp_sched_prio_free_sid(struct sctp_stream *stream, __u16 sid) { - struct sctp_stream_priorities *prio = SCTP_SO(stream, sid)->ext->prio_head; - int i; - - if (!prio) - return; - + sctp_sched_prio_head_put(SCTP_SO(stream, sid)->ext->prio_head); SCTP_SO(stream, sid)->ext->prio_head = NULL; - for (i = 0; i < stream->outcnt; i++) { - if (SCTP_SO(stream, i)->ext && - SCTP_SO(stream, i)->ext->prio_head == prio) - return; - } - - kfree(prio); } static void sctp_sched_prio_enqueue(struct sctp_outq *q, -- cgit v1.2.3 From 1862de92c81c2a74ff05819aca20b0b83192c83b Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Thu, 23 Feb 2023 09:26:56 +0200 Subject: netdev-genl: fix repeated typo oflloading -> offloading Fix a repeated copy/paste typo. Fixes: d3d854fd6a1d ("netdev-genl: create a simple family for netdev stuff") Signed-off-by: Tariq Toukan Acked-by: Lorenzo Bianconi Signed-off-by: David S. Miller --- Documentation/netlink/specs/netdev.yaml | 2 +- include/uapi/linux/netdev.h | 2 +- tools/include/uapi/linux/netdev.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml index b4dcdae54ffd..cffef09729f1 100644 --- a/Documentation/netlink/specs/netdev.yaml +++ b/Documentation/netlink/specs/netdev.yaml @@ -28,7 +28,7 @@ definitions: - name: hw-offload doc: - This feature informs if netdev supports XDP hw oflloading. + This feature informs if netdev supports XDP hw offloading. - name: rx-sg doc: diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h index 9ee459872600..588391447bfb 100644 --- a/include/uapi/linux/netdev.h +++ b/include/uapi/linux/netdev.h @@ -19,7 +19,7 @@ * @NETDEV_XDP_ACT_XSK_ZEROCOPY: This feature informs if netdev supports AF_XDP * in zero copy mode. * @NETDEV_XDP_ACT_HW_OFFLOAD: This feature informs if netdev supports XDP hw - * oflloading. + * offloading. * @NETDEV_XDP_ACT_RX_SG: This feature informs if netdev implements non-linear * XDP buffer support in the driver napi callback. * @NETDEV_XDP_ACT_NDO_XMIT_SG: This feature informs if netdev implements diff --git a/tools/include/uapi/linux/netdev.h b/tools/include/uapi/linux/netdev.h index 9ee459872600..588391447bfb 100644 --- a/tools/include/uapi/linux/netdev.h +++ b/tools/include/uapi/linux/netdev.h @@ -19,7 +19,7 @@ * @NETDEV_XDP_ACT_XSK_ZEROCOPY: This feature informs if netdev supports AF_XDP * in zero copy mode. * @NETDEV_XDP_ACT_HW_OFFLOAD: This feature informs if netdev supports XDP hw - * oflloading. + * offloading. * @NETDEV_XDP_ACT_RX_SG: This feature informs if netdev implements non-linear * XDP buffer support in the driver napi callback. * @NETDEV_XDP_ACT_NDO_XMIT_SG: This feature informs if netdev implements -- cgit v1.2.3 From 0322ef49c1ac6f0e2ef37b146c0bf8440873072c Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 24 Feb 2023 17:52:33 +0200 Subject: net: dsa: seville: ignore mscc-miim read errors from Lynx PCS During the refactoring in the commit below, vsc9953_mdio_read() was replaced with mscc_miim_read(), which has one extra step: it checks for the MSCC_MIIM_DATA_ERROR bits before returning the result. On T1040RDB, there are 8 QSGMII PCSes belonging to the switch, and they are organized in 2 groups. First group responds to MDIO addresses 4-7 because QSGMIIACR1[MDEV_PORT] is 1, and the second group responds to MDIO addresses 8-11 because QSGMIIBCR1[MDEV_PORT] is 2. I have double checked that these values are correctly set in the SERDES, as well as PCCR1[QSGMA_CFG] and PCCR1[QSGMB_CFG] are both 0b01. mscc_miim_read: phyad 8 reg 0x1 MIIM_DATA 0x2d mscc_miim_read: phyad 8 reg 0x5 MIIM_DATA 0x5801 mscc_miim_read: phyad 8 reg 0x1 MIIM_DATA 0x2d mscc_miim_read: phyad 8 reg 0x5 MIIM_DATA 0x5801 mscc_miim_read: phyad 9 reg 0x1 MIIM_DATA 0x2d mscc_miim_read: phyad 9 reg 0x5 MIIM_DATA 0x5801 mscc_miim_read: phyad 9 reg 0x1 MIIM_DATA 0x2d mscc_miim_read: phyad 9 reg 0x5 MIIM_DATA 0x5801 mscc_miim_read: phyad 10 reg 0x1 MIIM_DATA 0x2d mscc_miim_read: phyad 10 reg 0x5 MIIM_DATA 0x5801 mscc_miim_read: phyad 10 reg 0x1 MIIM_DATA 0x2d mscc_miim_read: phyad 10 reg 0x5 MIIM_DATA 0x5801 mscc_miim_read: phyad 11 reg 0x1 MIIM_DATA 0x2d mscc_miim_read: phyad 11 reg 0x5 MIIM_DATA 0x5801 mscc_miim_read: phyad 11 reg 0x1 MIIM_DATA 0x2d mscc_miim_read: phyad 11 reg 0x5 MIIM_DATA 0x5801 mscc_miim_read: phyad 4 reg 0x1 MIIM_DATA 0x3002d, ERROR mscc_miim_read: phyad 4 reg 0x5 MIIM_DATA 0x3da01, ERROR mscc_miim_read: phyad 5 reg 0x1 MIIM_DATA 0x3002d, ERROR mscc_miim_read: phyad 5 reg 0x5 MIIM_DATA 0x35801, ERROR mscc_miim_read: phyad 5 reg 0x1 MIIM_DATA 0x3002d, ERROR mscc_miim_read: phyad 5 reg 0x5 MIIM_DATA 0x35801, ERROR mscc_miim_read: phyad 6 reg 0x1 MIIM_DATA 0x3002d, ERROR mscc_miim_read: phyad 6 reg 0x5 MIIM_DATA 0x35801, ERROR mscc_miim_read: phyad 6 reg 0x1 MIIM_DATA 0x3002d, ERROR mscc_miim_read: phyad 6 reg 0x5 MIIM_DATA 0x35801, ERROR mscc_miim_read: phyad 7 reg 0x1 MIIM_DATA 0x3002d, ERROR mscc_miim_read: phyad 7 reg 0x5 MIIM_DATA 0x35801, ERROR mscc_miim_read: phyad 7 reg 0x1 MIIM_DATA 0x3002d, ERROR mscc_miim_read: phyad 7 reg 0x5 MIIM_DATA 0x35801, ERROR As can be seen, the data in MIIM_DATA is still valid despite having the MSCC_MIIM_DATA_ERROR bits set. The driver as introduced in commit 84705fc16552 ("net: dsa: felix: introduce support for Seville VSC9953 switch") was ignoring these bits, perhaps deliberately (although unbeknownst to me). This is an old IP and the hardware team cannot seem to be able to help me track down a plausible reason for these failures. I'll keep investigating, but in the meantime, this is a direct regression which must be restored to a working state. The only thing I can do is keep ignoring the errors as before. Fixes: b99658452355 ("net: dsa: ocelot: felix: utilize shared mscc-miim driver for indirect MDIO access") Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/seville_vsc9953.c | 4 ++-- drivers/net/mdio/mdio-mscc-miim.c | 9 ++++++--- include/linux/mdio/mdio-mscc-miim.h | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index 287b64b788db..563ad338da25 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -893,8 +893,8 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot) rc = mscc_miim_setup(dev, &bus, "VSC9953 internal MDIO bus", ocelot->targets[GCB], - ocelot->map[GCB][GCB_MIIM_MII_STATUS & REG_MASK]); - + ocelot->map[GCB][GCB_MIIM_MII_STATUS & REG_MASK], + true); if (rc) { dev_err(dev, "failed to setup MDIO bus\n"); return rc; diff --git a/drivers/net/mdio/mdio-mscc-miim.c b/drivers/net/mdio/mdio-mscc-miim.c index c87e991d1a17..1a1b95ae95fa 100644 --- a/drivers/net/mdio/mdio-mscc-miim.c +++ b/drivers/net/mdio/mdio-mscc-miim.c @@ -52,6 +52,7 @@ struct mscc_miim_info { struct mscc_miim_dev { struct regmap *regs; int mii_status_offset; + bool ignore_read_errors; struct regmap *phy_regs; const struct mscc_miim_info *info; struct clk *clk; @@ -135,7 +136,7 @@ static int mscc_miim_read(struct mii_bus *bus, int mii_id, int regnum) goto out; } - if (val & MSCC_MIIM_DATA_ERROR) { + if (!miim->ignore_read_errors && !!(val & MSCC_MIIM_DATA_ERROR)) { ret = -EIO; goto out; } @@ -212,7 +213,8 @@ static const struct regmap_config mscc_miim_phy_regmap_config = { }; int mscc_miim_setup(struct device *dev, struct mii_bus **pbus, const char *name, - struct regmap *mii_regmap, int status_offset) + struct regmap *mii_regmap, int status_offset, + bool ignore_read_errors) { struct mscc_miim_dev *miim; struct mii_bus *bus; @@ -234,6 +236,7 @@ int mscc_miim_setup(struct device *dev, struct mii_bus **pbus, const char *name, miim->regs = mii_regmap; miim->mii_status_offset = status_offset; + miim->ignore_read_errors = ignore_read_errors; *pbus = bus; @@ -285,7 +288,7 @@ static int mscc_miim_probe(struct platform_device *pdev) return dev_err_probe(dev, PTR_ERR(phy_regmap), "Unable to create phy register regmap\n"); - ret = mscc_miim_setup(dev, &bus, "mscc_miim", mii_regmap, 0); + ret = mscc_miim_setup(dev, &bus, "mscc_miim", mii_regmap, 0, false); if (ret < 0) { dev_err(dev, "Unable to setup the MDIO bus\n"); return ret; diff --git a/include/linux/mdio/mdio-mscc-miim.h b/include/linux/mdio/mdio-mscc-miim.h index 5b4ed2c3cbb9..1ce699740af6 100644 --- a/include/linux/mdio/mdio-mscc-miim.h +++ b/include/linux/mdio/mdio-mscc-miim.h @@ -14,6 +14,6 @@ int mscc_miim_setup(struct device *device, struct mii_bus **bus, const char *name, struct regmap *mii_regmap, - int status_offset); + int status_offset, bool ignore_read_errors); #endif -- cgit v1.2.3