From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
stable@vger.kernel.org, Brad Mouring <brad.mouring@ni.com>,
"David S. Miller" <davem@davemloft.net>
Subject: [PATCH 4.15 15/47] net: phy: Tell caller result of phy_change()
Date: Thu, 29 Mar 2018 19:59:56 +0200 [thread overview]
Message-ID: <20180329175730.206175888@linuxfoundation.org> (raw)
In-Reply-To: <20180329175729.225211114@linuxfoundation.org>
4.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Brad Mouring <brad.mouring@ni.com>
[ Upstream commit a2c054a896b8ac794ddcfc7c92e2dc7ec4ed4ed5 ]
In 664fcf123a30e (net: phy: Threaded interrupts allow some simplification)
the phy_interrupt system was changed to use a traditional threaded
interrupt scheme instead of a workqueue approach.
With this change, the phy status check moved into phy_change, which
did not report back to the caller whether or not the interrupt was
handled. This means that, in the case of a shared phy interrupt,
only the first phydev's interrupt registers are checked (since
phy_interrupt() would always return IRQ_HANDLED). This leads to
interrupt storms when it is a secondary device that's actually the
interrupt source.
Signed-off-by: Brad Mouring <brad.mouring@ni.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/phy/phy.c | 173 ++++++++++++++++++++++++--------------------------
include/linux/phy.h | 1
2 files changed, 86 insertions(+), 88 deletions(-)
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -615,6 +615,91 @@ static void phy_error(struct phy_device
}
/**
+ * phy_disable_interrupts - Disable the PHY interrupts from the PHY side
+ * @phydev: target phy_device struct
+ */
+static int phy_disable_interrupts(struct phy_device *phydev)
+{
+ int err;
+
+ /* Disable PHY interrupts */
+ err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
+ if (err)
+ goto phy_err;
+
+ /* Clear the interrupt */
+ err = phy_clear_interrupt(phydev);
+ if (err)
+ goto phy_err;
+
+ return 0;
+
+phy_err:
+ phy_error(phydev);
+
+ return err;
+}
+
+/**
+ * phy_change - Called by the phy_interrupt to handle PHY changes
+ * @phydev: phy_device struct that interrupted
+ */
+static irqreturn_t phy_change(struct phy_device *phydev)
+{
+ if (phy_interrupt_is_valid(phydev)) {
+ if (phydev->drv->did_interrupt &&
+ !phydev->drv->did_interrupt(phydev))
+ goto ignore;
+
+ if (phy_disable_interrupts(phydev))
+ goto phy_err;
+ }
+
+ mutex_lock(&phydev->lock);
+ if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
+ phydev->state = PHY_CHANGELINK;
+ mutex_unlock(&phydev->lock);
+
+ if (phy_interrupt_is_valid(phydev)) {
+ atomic_dec(&phydev->irq_disable);
+ enable_irq(phydev->irq);
+
+ /* Reenable interrupts */
+ if (PHY_HALTED != phydev->state &&
+ phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED))
+ goto irq_enable_err;
+ }
+
+ /* reschedule state queue work to run as soon as possible */
+ phy_trigger_machine(phydev, true);
+ return IRQ_HANDLED;
+
+ignore:
+ atomic_dec(&phydev->irq_disable);
+ enable_irq(phydev->irq);
+ return IRQ_NONE;
+
+irq_enable_err:
+ disable_irq(phydev->irq);
+ atomic_inc(&phydev->irq_disable);
+phy_err:
+ phy_error(phydev);
+ return IRQ_NONE;
+}
+
+/**
+ * phy_change_work - Scheduled by the phy_mac_interrupt to handle PHY changes
+ * @work: work_struct that describes the work to be done
+ */
+void phy_change_work(struct work_struct *work)
+{
+ struct phy_device *phydev =
+ container_of(work, struct phy_device, phy_queue);
+
+ phy_change(phydev);
+}
+
+/**
* phy_interrupt - PHY interrupt handler
* @irq: interrupt line
* @phy_dat: phy_device pointer
@@ -632,9 +717,7 @@ static irqreturn_t phy_interrupt(int irq
disable_irq_nosync(irq);
atomic_inc(&phydev->irq_disable);
- phy_change(phydev);
-
- return IRQ_HANDLED;
+ return phy_change(phydev);
}
/**
@@ -652,32 +735,6 @@ static int phy_enable_interrupts(struct
}
/**
- * phy_disable_interrupts - Disable the PHY interrupts from the PHY side
- * @phydev: target phy_device struct
- */
-static int phy_disable_interrupts(struct phy_device *phydev)
-{
- int err;
-
- /* Disable PHY interrupts */
- err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
- if (err)
- goto phy_err;
-
- /* Clear the interrupt */
- err = phy_clear_interrupt(phydev);
- if (err)
- goto phy_err;
-
- return 0;
-
-phy_err:
- phy_error(phydev);
-
- return err;
-}
-
-/**
* phy_start_interrupts - request and enable interrupts for a PHY device
* @phydev: target phy_device struct
*
@@ -728,64 +785,6 @@ int phy_stop_interrupts(struct phy_devic
EXPORT_SYMBOL(phy_stop_interrupts);
/**
- * phy_change - Called by the phy_interrupt to handle PHY changes
- * @phydev: phy_device struct that interrupted
- */
-void phy_change(struct phy_device *phydev)
-{
- if (phy_interrupt_is_valid(phydev)) {
- if (phydev->drv->did_interrupt &&
- !phydev->drv->did_interrupt(phydev))
- goto ignore;
-
- if (phy_disable_interrupts(phydev))
- goto phy_err;
- }
-
- mutex_lock(&phydev->lock);
- if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
- phydev->state = PHY_CHANGELINK;
- mutex_unlock(&phydev->lock);
-
- if (phy_interrupt_is_valid(phydev)) {
- atomic_dec(&phydev->irq_disable);
- enable_irq(phydev->irq);
-
- /* Reenable interrupts */
- if (PHY_HALTED != phydev->state &&
- phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED))
- goto irq_enable_err;
- }
-
- /* reschedule state queue work to run as soon as possible */
- phy_trigger_machine(phydev, true);
- return;
-
-ignore:
- atomic_dec(&phydev->irq_disable);
- enable_irq(phydev->irq);
- return;
-
-irq_enable_err:
- disable_irq(phydev->irq);
- atomic_inc(&phydev->irq_disable);
-phy_err:
- phy_error(phydev);
-}
-
-/**
- * phy_change_work - Scheduled by the phy_mac_interrupt to handle PHY changes
- * @work: work_struct that describes the work to be done
- */
-void phy_change_work(struct work_struct *work)
-{
- struct phy_device *phydev =
- container_of(work, struct phy_device, phy_queue);
-
- phy_change(phydev);
-}
-
-/**
* phy_stop - Bring down the PHY link, and stop checking the status
* @phydev: target phy_device struct
*/
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -897,7 +897,6 @@ int phy_driver_register(struct phy_drive
int phy_drivers_register(struct phy_driver *new_driver, int n,
struct module *owner);
void phy_state_machine(struct work_struct *work);
-void phy_change(struct phy_device *phydev);
void phy_change_work(struct work_struct *work);
void phy_mac_interrupt(struct phy_device *phydev, int new_link);
void phy_start_machine(struct phy_device *phydev);
next prev parent reply other threads:[~2018-03-29 18:03 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-03-29 17:59 [PATCH 4.15 00/47] 4.15.15-stable review Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 01/47] net: dsa: Fix dsa_is_user_port() test inversion Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 02/47] openvswitch: meter: fix the incorrect calculation of max delta_t Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 03/47] qed: Fix MPA unalign flow in case header is split across two packets Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 04/47] tcp: purge write queue upon aborting the connection Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 05/47] qed: Fix non TCP packets should be dropped on iWARP ll2 connection Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 06/47] sysfs: symlink: export sysfs_create_link_nowarn() Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 07/47] net: phy: relax error checking when creating sysfs link netdev->phydev Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 08/47] devlink: Remove redundant free on error path Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 09/47] macvlan: filter out unsupported feature flags Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 10/47] net: ipv6: keep sk status consistent after datagram connect failure Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 11/47] ipv6: old_dport should be a __be16 in __ip6_datagram_connect() Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 12/47] ipv6: sr: fix NULL pointer dereference when setting encap source address Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 13/47] ipv6: sr: fix scheduling in RCU when creating seg6 lwtunnel state Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 14/47] mlxsw: spectrum_buffers: Set a minimum quota for CPU port traffic Greg Kroah-Hartman
2018-03-29 17:59 ` Greg Kroah-Hartman [this message]
2018-03-29 17:59 ` [PATCH 4.15 16/47] ipv6: Reflect MTU changes on PMTU of exceptions for MTU-less routes Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 17/47] net sched actions: return explicit error when tunnel_key mode is not specified Greg Kroah-Hartman
2018-03-29 17:59 ` [PATCH 4.15 18/47] ppp: avoid loop in xmit recursion detection code Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 19/47] rhashtable: Fix rhlist duplicates insertion Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 20/47] test_rhashtable: add test case for rhltable with duplicate objects Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 21/47] kcm: lock lower socket in kcm_attach Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 22/47] sch_netem: fix skb leak in netem_enqueue() Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 23/47] ieee802154: 6lowpan: fix possible NULL deref in lowpan_device_event() Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 24/47] net: use skb_to_full_sk() in skb_update_prio() Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 25/47] net: Fix hlist corruptions in inet_evict_bucket() Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 26/47] s390/qeth: free netdevice when removing a card Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 27/47] s390/qeth: when thread completes, wake up all waiters Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 28/47] s390/qeth: lock read device while queueing next buffer Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 29/47] s390/qeth: on channel error, reject further cmd requests Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 30/47] soc/fsl/qbman: fix issue in qman_delete_cgr_safe() Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 31/47] dpaa_eth: fix error in dpaa_remove() Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 32/47] dpaa_eth: remove duplicate initialization Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 33/47] dpaa_eth: increment the RX dropped counter when needed Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 34/47] dpaa_eth: remove duplicate increment of the tx_errors counter Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 35/47] dccp: check sk for closed state in dccp_sendmsg() Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 36/47] ipv6: fix access to non-linear packet in ndisc_fill_redirect_hdr_option() Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 37/47] l2tp: do not accept arbitrary sockets Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 38/47] net: ethernet: arc: Fix a potential memory leak if an optional regulator is deferred Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 40/47] net: fec: Fix unbalanced PM runtime calls Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 41/47] net/iucv: Free memory obtained by kzalloc Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 42/47] netlink: avoid a double skb free in genlmsg_mcast() Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 43/47] net: Only honor ifindex in IP_PKTINFO if non-0 Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 44/47] net: systemport: Rewrite __bcm_sysport_tx_reclaim() Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 45/47] qede: Fix qedr link update Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 46/47] skbuff: Fix not waking applications when errors are enqueued Greg Kroah-Hartman
2018-03-29 18:00 ` [PATCH 4.15 47/47] team: Fix double free in error path Greg Kroah-Hartman
2018-03-29 23:09 ` [PATCH 4.15 00/47] 4.15.15-stable review Shuah Khan
2018-03-30 9:02 ` Greg Kroah-Hartman
2018-03-30 8:11 ` Naresh Kamboju
2018-03-30 9:08 ` Greg Kroah-Hartman
2018-03-30 15:20 ` Guenter Roeck
2018-03-31 7:22 ` Greg Kroah-Hartman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180329175730.206175888@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=brad.mouring@ni.com \
--cc=davem@davemloft.net \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).