From: Florian Fainelli <florian@openwrt.org>
To: Jason Lin <kernel.jason@gmail.com>
Cc: netdev@vger.kernel.org
Subject: Re: [RFC] net:phy:phylib: phy shares the same interrupt with mac
Date: Tue, 03 Apr 2012 10:49:48 +0200 [thread overview]
Message-ID: <4F7AB9AC.8000708@openwrt.org> (raw)
In-Reply-To: <CAGCDX1nndpdGHZzhh_Y+2OMLZvvUmAqkAsmgHu9hdUXTJFE--Q@mail.gmail.com>
Hi,
Le 04/03/12 04:11, Jason Lin a écrit :
> 1) Add a new definition PHY_MAC if phy shares the same
> interrupt with mac.
> 2) Add do_phy_workqueue(), that mac can invoke this function
> in its ISR when link status changed or other conditions.
>
> Does this seems reasonable?
No, I think this is well handled by the PHY_IGNORE_INTERRUPT case
(documented in Documentation/networking/phy.txt) by doing the following:
- distinguish between MAC and PHY interrupts in your MAC interrupt
handler (most likely you have separate bits for PHY interrupts)
- once you see a PHY interrupt, call the appropriate PHY state machine
callbacks to update the PHY state machine
>
>
> ---------------------------
> drivers/net/phy/phy.c | 27 +++++++++++++++++++++++++++
> drivers/net/phy/phy_device.c | 4 ++--
> include/linux/phy.h | 3 +++
> 3 files changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
> index 7670aac..c8009e9 100644
> --- a/drivers/net/phy/phy.c
> +++ b/drivers/net/phy/phy.c
> @@ -527,6 +527,28 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
> return IRQ_HANDLED;
> }
>
> +/*
> + * do_phy_workqueue - PHY interrupt handler used by MAC
> + * @irq: interrupt line
> + * @phydev: phy_device pointer
> + *
> + * Description: When a PHY use the same interrupt with MAC,
> + * the handler is invoked by MAC, and schedules a work task
> + * to clear the PHY's interrupt.
> + * This handler is invoked only in MAC's ISR.
> + */
> +irqreturn_t do_phy_workqueue(int irq, struct phy_device *phydev) {
> +
> + BUG_ON(!in_interrupt());
> +
> + if (PHY_HALTED == phydev->state)
> + return IRQ_NONE;
> +
> + schedule_work(&phydev->phy_queue);
> + return IRQ_HANDLED;
> +}
> +EXPORT_SYMBOL(do_phy_workqueue);
> +
> /**
> * phy_enable_interrupts - Enable the interrupts from the PHY side
> * @phydev: target phy_device struct
> @@ -589,6 +611,11 @@ int phy_start_interrupts(struct phy_device *phydev)
>
> INIT_WORK(&phydev->phy_queue, phy_change);
>
> + if (phydev->irq == PHY_MAC) {
> + err = phy_enable_interrupts(phydev);
> + return err;
> + }
> +
> atomic_set(&phydev->irq_disable, 0);
> if (request_irq(phydev->irq, phy_interrupt,
> IRQF_SHARED,
> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> index 993c52c..1857097 100644
> --- a/drivers/net/phy/phy_device.c
> +++ b/drivers/net/phy/phy_device.c
> @@ -345,7 +345,7 @@ int phy_connect_direct(struct net_device *dev,
> struct phy_device *phydev,
>
> phy_prepare_link(phydev, handler);
> phy_start_machine(phydev, NULL);
> - if (phydev->irq> 0)
> + if ((phydev->irq> 0) || (phydev->irq == PHY_MAC))
> phy_start_interrupts(phydev);
>
> return 0;
> @@ -399,7 +399,7 @@ EXPORT_SYMBOL(phy_connect);
> */
> void phy_disconnect(struct phy_device *phydev)
> {
> - if (phydev->irq> 0)
> + if ((phydev->irq> 0) || (phydev->irq == PHY_MAC))
> phy_stop_interrupts(phydev);
>
> phy_stop_machine(phydev);
> diff --git a/include/linux/phy.h b/include/linux/phy.h
> index 7da5fa8..155822c 100644
> --- a/include/linux/phy.h
> +++ b/include/linux/phy.h
> @@ -44,9 +44,11 @@
> * Set phydev->irq to PHY_POLL if interrupts are not supported,
> * or not desired for this PHY. Set to PHY_IGNORE_INTERRUPT if
> * the attached driver handles the interrupt
> + * Set to PHY_MAC if using the same interrupt with MAC
> */
> #define PHY_POLL -1
> #define PHY_IGNORE_INTERRUPT -2
> +#define PHY_MAC -3
>
> #define PHY_HAS_INTERRUPT 0x00000001
> #define PHY_HAS_MAGICANEG 0x00000002
> @@ -510,6 +512,7 @@ int phy_ethtool_sset(struct phy_device *phydev,
> struct ethtool_cmd *cmd);
> int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
> int phy_mii_ioctl(struct phy_device *phydev,
> struct ifreq *ifr, int cmd);
> +irqreturn_t do_phy_workqueue(int irq, struct phy_device *phydev);
> int phy_start_interrupts(struct phy_device *phydev);
> void phy_print_status(struct phy_device *phydev);
> void phy_device_free(struct phy_device *phydev);
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2012-04-03 8:51 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-04-03 2:11 [RFC] net:phy:phylib: phy shares the same interrupt with mac Jason Lin
2012-04-03 8:49 ` Florian Fainelli [this message]
2012-04-05 1:30 ` Jason Lin
2012-04-06 2:24 ` Jason Lin
2012-04-06 5:53 ` Jason Lin
2012-07-11 1:32 ` Jason Lin
2012-07-12 20:05 ` Andy Fleming
2012-07-13 2:56 ` Jason Lin
2012-07-13 5:29 ` Jason Lin
2012-07-24 1:58 ` Jason Lin
2012-07-24 10:59 ` Florian Fainelli
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=4F7AB9AC.8000708@openwrt.org \
--to=florian@openwrt.org \
--cc=kernel.jason@gmail.com \
--cc=netdev@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.