Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH v2 0/2] net: dsa: microchip: add KSZ8563 support
From: David Miller @ 2019-09-01  6:36 UTC (permalink / raw)
  To: razvan.stefanescu
  Cc: woojung.huh, UNGLinuxDriver, andrew, vivien.didelot, f.fainelli,
	netdev, linux-kernel
In-Reply-To: <20190830075202.20740-1-razvan.stefanescu@microchip.com>

From: Razvan Stefanescu <razvan.stefanescu@microchip.com>
Date: Fri, 30 Aug 2019 10:52:00 +0300

> This patchset adds compatibility string for the KSZ8563 switch.

Series applied, thank you.

^ permalink raw reply

* Re: [PATCH v2 net] net: Properly update v4 routes with v6 nexthop
From: David Ahern @ 2019-09-01  2:21 UTC (permalink / raw)
  To: Donald Sharp, netdev, David Miller, sworley
In-Reply-To: <20190831122254.29928-1-sharpd@cumulusnetworks.com>

On 8/31/19 6:22 AM, Donald Sharp wrote:
> When creating a v4 route that uses a v6 nexthop from a nexthop group.
> Allow the kernel to properly send the nexthop as v6 via the RTA_VIA
> attribute.
> 

Dave: I am on PTO with little time through Monday. I will review/test on
Tuesday.

^ permalink raw reply

* Re: [PATCH v2 net 0/3] Fix issues in tc-taprio and tc-cbs
From: David Miller @ 2019-09-01  1:46 UTC (permalink / raw)
  To: olteanv
  Cc: xiyou.wangcong, jiri, vinicius.gomes, vedang.patel,
	leandro.maciel.dorileo, netdev
In-Reply-To: <20190830010723.32096-1-olteanv@gmail.com>

From: Vladimir Oltean <olteanv@gmail.com>
Date: Fri, 30 Aug 2019 04:07:20 +0300

> This series fixes one panic and one WARN_ON found in the tc-taprio
> qdisc, while trying to apply it:
> 
> - On an interface which is not multi-queue
> - On an interface which has no carrier
> 
> The tc-cbs was also visually found to suffer of the same issue as
> tc-taprio, and the fix was only compile-tested in that case.

Series applied, thanks.

^ permalink raw reply

* Re: [PATCH 4.14] tcp: fix tcp_rtx_queue_tail in case of empty retransmit queue
From: Sasha Levin @ 2019-09-01  0:07 UTC (permalink / raw)
  To: Matthieu Baerts
  Cc: Tim Froidcoeur, aprout, cpaasch, davem, edumazet, gregkh,
	jonathan.lemon, jtl, linux-kernel, mkubecek, ncardwell, stable,
	ycheng, netdev
In-Reply-To: <35cd974b-2b31-4f86-d53d-8e9516d4077e@tessares.net>

On Sat, Aug 31, 2019 at 03:14:35PM +0200, Matthieu Baerts wrote:
>Hi Sasha,
>
>Thank you for your reply!
>
>On 31/08/2019 14:20, Sasha Levin wrote:
>> On Sat, Aug 24, 2019 at 08:03:51AM +0200, Tim Froidcoeur wrote:
>>> Commit 8c3088f895a0 ("tcp: be more careful in tcp_fragment()")
>>> triggers following stack trace:
>>>
>>> [25244.848046] kernel BUG at ./include/linux/skbuff.h:1406!
>>> [25244.859335] RIP: 0010:skb_queue_prev+0x9/0xc
>>> [25244.888167] Call Trace:
>>> [25244.889182]  <IRQ>
>>> [25244.890001]  tcp_fragment+0x9c/0x2cf
>>> [25244.891295]  tcp_write_xmit+0x68f/0x988
>>> [25244.892732]  __tcp_push_pending_frames+0x3b/0xa0
>>> [25244.894347]  tcp_data_snd_check+0x2a/0xc8
>>> [25244.895775]  tcp_rcv_established+0x2a8/0x30d
>>> [25244.897282]  tcp_v4_do_rcv+0xb2/0x158
>>> [25244.898666]  tcp_v4_rcv+0x692/0x956
>>> [25244.899959]  ip_local_deliver_finish+0xeb/0x169
>>> [25244.901547]  __netif_receive_skb_core+0x51c/0x582
>>> [25244.903193]  ? inet_gro_receive+0x239/0x247
>>> [25244.904756]  netif_receive_skb_internal+0xab/0xc6
>>> [25244.906395]  napi_gro_receive+0x8a/0xc0
>>> [25244.907760]  receive_buf+0x9a1/0x9cd
>>> [25244.909160]  ? load_balance+0x17a/0x7b7
>>> [25244.910536]  ? vring_unmap_one+0x18/0x61
>>> [25244.911932]  ? detach_buf+0x60/0xfa
>>> [25244.913234]  virtnet_poll+0x128/0x1e1
>>> [25244.914607]  net_rx_action+0x12a/0x2b1
>>> [25244.915953]  __do_softirq+0x11c/0x26b
>>> [25244.917269]  ? handle_irq_event+0x44/0x56
>>> [25244.918695]  irq_exit+0x61/0xa0
>>> [25244.919947]  do_IRQ+0x9d/0xbb
>>> [25244.921065]  common_interrupt+0x85/0x85
>>> [25244.922479]  </IRQ>
>>>
>>> tcp_rtx_queue_tail() (called by tcp_fragment()) can call
>>> tcp_write_queue_prev() on the first packet in the queue, which will
>>> trigger
>>> the BUG in tcp_write_queue_prev(), because there is no previous packet.
>>>
>>> This happens when the retransmit queue is empty, for example in case of a
>>> zero window.
>>>
>>> Patch is needed for 4.4, 4.9 and 4.14 stable branches.
>>
>> There needs to be a better explanation of why it's not needed
>> upstream...
>
>Commit 8c3088f895a0 ("tcp: be more careful in tcp_fragment()") was not a
>simple cherry-pick of the original one from master (b617158dc096)
>because there is a specific TCP rtx queue only since v4.15. For more
>details, please see the commit message of b617158dc096 ("tcp: be more
>careful in tcp_fragment()").
>
>The BUG() is hit due to the specific code added to versions older than
>v4.15. The comment in skb_queue_prev() (include/linux/skbuff.h:1406),
>just before the BUG_ON() somehow suggests to add a check before using
>it, what Tim did.
>
>In master, this code path causing the issue will not be taken because
>the implementation of tcp_rtx_queue_tail() is different:
>
>    tcp_fragment() → tcp_rtx_queue_tail() → tcp_write_queue_prev() →
>skb_queue_prev() → BUG_ON()
>
>Because this patch is specific to versions older than the two last
>stable ones but still linked to the network architecture, who can review
>and approve it? :)

Thanks for the explanation. I've changed the commit message to include
this explanation and queued it for 4.4, 4.9 and 4.14.

--
Thanks,
Sasha

^ permalink raw reply

* Re: KASAN: use-after-free Read in rxrpc_put_peer
From: syzbot @ 2019-08-31 23:28 UTC (permalink / raw)
  To: davem, dhowells, linux-afs, linux-kernel, netdev, syzkaller-bugs
In-Reply-To: <21753.1567081045@warthog.procyon.org.uk>

Hello,

syzbot has tested the proposed patch and the reproducer did not trigger  
crash:

Reported-and-tested-by:  
syzbot+b9be979c55f2bea8ed30@syzkaller.appspotmail.com

Tested on:

commit:         48b9e92a rxrpc: Fix lack of conn cleanup when local endpoi..
git tree:        
git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
kernel config:  https://syzkaller.appspot.com/x/.config?x=230542aa16bfc4b0
dashboard link: https://syzkaller.appspot.com/bug?extid=b9be979c55f2bea8ed30
compiler:       gcc (GCC) 9.0.0 20181231 (experimental)

Note: testing is done by a robot and is best-effort only.

^ permalink raw reply

* [PATCH] iwlwifi: mvm: Move static keyword to the front of declarations
From: Krzysztof Wilczynski @ 2019-08-31 22:01 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, David S. Miller, Sara Sharon,
	Shaul Triebitz, Liad Kaufman, linux-wireless, netdev,
	linux-kernel

Move the static keyword to the front of declarations of
he_if_types_ext_capa_sta and he_iftypes_ext_capa, and
resolve the following compiler warnings that can be seen
when building with warnings enabled (W=1):

drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c:427:1: warning:
  ‘static’ is not at beginning of declaration [-Wold-style-declaration]

drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c:434:1: warning:
  ‘static’ is not at beginning of declaration [-Wold-style-declaration]

Signed-off-by: Krzysztof Wilczynski <kw@linux.com>
---
Related: https://lore.kernel.org/r/20190827233017.GK9987@google.com

 drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index d6499763f0dd..937a843fed56 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -424,14 +424,14 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
 	return ret;
 }
 
-const static u8 he_if_types_ext_capa_sta[] = {
+static const u8 he_if_types_ext_capa_sta[] = {
 	 [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
 	 [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
 	 [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
 	 [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
 };
 
-const static struct wiphy_iftype_ext_capab he_iftypes_ext_capa[] = {
+static const struct wiphy_iftype_ext_capab he_iftypes_ext_capa[] = {
 	{
 		.iftype = NL80211_IFTYPE_STATION,
 		.extended_capabilities = he_if_types_ext_capa_sta,
-- 
2.22.1


^ permalink raw reply related

* Re: [PATCH 2/2] Fix a NULL-ptr-deref bug in ath10k_usb_alloc_urb_from_pipe
From: Guenter Roeck @ 2019-08-31 21:31 UTC (permalink / raw)
  To: Hui Peng
  Cc: kvalo, davem, Mathias Payer, ath10k, linux-wireless, netdev,
	linux-kernel
In-Reply-To: <20190804003101.11541-1-benquike@gmail.com>

Hi,

On Sat, Aug 03, 2019 at 08:31:01PM -0400, Hui Peng wrote:
> The `ar_usb` field of `ath10k_usb_pipe_usb_pipe` objects
> are initialized to point to the containing `ath10k_usb` object
> according to endpoint descriptors read from the device side, as shown
> below in `ath10k_usb_setup_pipe_resources`:
> 
> for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
>         endpoint = &iface_desc->endpoint[i].desc;
> 
>         // get the address from endpoint descriptor
>         pipe_num = ath10k_usb_get_logical_pipe_num(ar_usb,
>                                                 endpoint->bEndpointAddress,
>                                                 &urbcount);
>         ......
>         // select the pipe object
>         pipe = &ar_usb->pipes[pipe_num];
> 
>         // initialize the ar_usb field
>         pipe->ar_usb = ar_usb;
> }
> 
> The driver assumes that the addresses reported in endpoint
> descriptors from device side  to be complete. If a device is
> malicious and does not report complete addresses, it may trigger
> NULL-ptr-deref `ath10k_usb_alloc_urb_from_pipe` and
> `ath10k_usb_free_urb_to_pipe`.
> 
> This patch fixes the bug by preventing potential NULL-ptr-deref.
> 
> Signed-off-by: Hui Peng <benquike@gmail.com>
> Reported-by: Hui Peng <benquike@gmail.com>
> Reported-by: Mathias Payer <mathias.payer@nebelwelt.net>

This patch fixes CVE-2019-15099, which has CVSS scores of 7.5 (CVSS 3.0)
and 7.8 (CVSS 2.0). Yet, I don't find it in the upstream kernel or in Linux
next.

Is the patch going to be applied to the upstream kernel anytime soon ? If
not, is there reason to believe that its severity may not be as high as the
CVSS score indicates ?

Thanks,
Guenter

> ---
>  drivers/net/wireless/ath/ath10k/usb.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c
> index e1420f67f776..14d86627b47f 100644
> --- a/drivers/net/wireless/ath/ath10k/usb.c
> +++ b/drivers/net/wireless/ath/ath10k/usb.c
> @@ -38,6 +38,10 @@ ath10k_usb_alloc_urb_from_pipe(struct ath10k_usb_pipe *pipe)
>  	struct ath10k_urb_context *urb_context = NULL;
>  	unsigned long flags;
>  
> +	/* bail if this pipe is not initialized */
> +	if (!pipe->ar_usb)
> +		return NULL;
> +
>  	spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags);
>  	if (!list_empty(&pipe->urb_list_head)) {
>  		urb_context = list_first_entry(&pipe->urb_list_head,
> @@ -55,6 +59,10 @@ static void ath10k_usb_free_urb_to_pipe(struct ath10k_usb_pipe *pipe,
>  {
>  	unsigned long flags;
>  
> +	/* bail if this pipe is not initialized */
> +	if (!pipe->ar_usb)
> +		return NULL;
> +
>  	spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags);
>  
>  	pipe->urb_cnt++;
> -- 
> 2.22.0
> 

^ permalink raw reply

* Re: [PATCH v3 1/2] net: core: Notify on changes to dev->promiscuity.
From: Ido Schimmel @ 2019-08-31 20:47 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: David Miller, jiri, horatiu.vultur, alexandre.belloni,
	UNGLinuxDriver, allan.nielsen, ivecera, f.fainelli, netdev,
	linux-kernel
In-Reply-To: <20190831193556.GB2647@lunn.ch>

On Sat, Aug 31, 2019 at 09:35:56PM +0200, Andrew Lunn wrote:
> > Also, what happens when I'm running these application without putting
> > the interface in promisc mode? On an offloaded interface I would not be
> > able to even capture packets addressed to my interface's MAC address.
> 
> Sorry for rejoining the discussion late. I've been travelling and i'm
> now 3/4 of the way to Lisbon.

Hi Andrew,

Have fun!

> That statement i don't get. 

What about the other statements?

> If the frame has the MAC address of the interface, it has to be
> delivered to the CPU. 

So every packet that needs to be routed should be delivered to the CPU?
Definitely not.

> And so pcap will see it when running on the interface. I can pretty
> much guarantee every DSA driver does that.

I assume because you currently only consider L2 forwarding.

> But to address the bigger picture. My understanding is that we want to
> model offloading as a mechanism to accelerate what Linux can already
> do. The user should not have to care about these accelerators. The
> interface should work like a normal Linux interface. I can put an IP
> address on it and ping a peer. I can run a dhcp client and get an IP
> address from a dhcp server. I can add the interface to a bridge, and
> packets will get bridged. I as a user should not need to care if this
> is done in software, or accelerated by offloading it. I can add a
> route, and if the accelerate knows about L3, it can accelerate that as
> well. If not, the kernel will route it.

Yep, and this is how it's all working today.

> So if i run wireshark on an interface, i expect the interface will be
> put into promisc mode and i see all packets ingressing the interface.
> What the accelerator needs to do to achieve this, i as a user don't
> care.
> 
> I can follow the argument that i won't necessarily see every
> packet. But that is always true. For many embedded systems, the CPU is
> too slow to receive at line rate, even when we are talking about 1G
> links. Packets do get dropped. And i hope tcpdump users understand
> that.
> 
> For me, having tcpdump use tc trap is just wrong. It breaks the model
> that the user should not care about the accelerator. If anything, i
> think the driver needs to translate cBPF which pcap passes to the
> kernel to whatever internal format the accelerator can process. That
> is just another example of using hardware acceleration.

Look, this again boils down to what promisc mode means with regards to
hardware offload. You want it to mean punt all traffic to the CPU? Fine.
Does not seem like anyone will be switching sides anyway, so lets move
forward. But the current approach is not good. Each driver needs to have
this special case logic and the semantics of promisc mode change not
only with regards to the value of the promisc counter, but also with
regards to the interface's uppers. This is highly fragile and confusing.

The approach taken in v2 makes much more sense. Add a new flag to
accelerators and have the networking stack check it before putting the
interface in promisc mode. Then the only thing drivers need to do is to
instruct the accelerator to trap all traffic to the CPU.

^ permalink raw reply

* Re: [PATCH net 0/5] net: aquantia: fixes on vlan filters and other conditions
From: David Miller @ 2019-08-31 20:36 UTC (permalink / raw)
  To: jakub.kicinski; +Cc: Igor.Russkikh, netdev
In-Reply-To: <20190830232856.6200abd2@cakuba.netronome.com>

From: Jakub Kicinski <jakub.kicinski@netronome.com>
Date: Fri, 30 Aug 2019 23:28:56 -0700

> On Fri, 30 Aug 2019 12:08:28 +0000, Igor Russkikh wrote:
>> Here is a set of various bug fixes related to vlan filter offload and
>> two other rare cases.
> 
> LGTM, Fixes tag should had been first there on patch 4.

Series applied with fixes tag ordering fixed in patch 4.

^ permalink raw reply

* Re: [PATCH net-next 0/4] qed*: Enhancements.
From: David Miller @ 2019-08-31 20:32 UTC (permalink / raw)
  To: skalluru; +Cc: netdev, mkalderon, aelior
In-Reply-To: <20190830074206.8836-1-skalluru@marvell.com>

From: Sudarsana Reddy Kalluru <skalluru@marvell.com>
Date: Fri, 30 Aug 2019 00:42:02 -0700

> The patch series adds couple of enhancements to qed/qede drivers.
>   - Support for dumping the config id attributes via ethtool -w/W.
>   - Support for dumping the GRC data of required memory regions using
>     ethtool -w/W interfaces.
> 
> Patch (1) adds driver APIs for reading the config id attributes.
> Patch (2) adds ethtool support for dumping the config id attributes.
> Patch (3) adds support for configuring the GRC dump config flags.
> Patch (4) adds ethtool support for dumping the grc dump.
> 
> Please consider applying it to net-next.

Series applied, thanks.

^ permalink raw reply

* Re: [PATCH v3 net-next 0/2] Dynamic toggling of vlan_filtering for SJA1105 DSA
From: David Miller @ 2019-08-31 20:21 UTC (permalink / raw)
  To: olteanv; +Cc: f.fainelli, vivien.didelot, andrew, idosch, roopa, nikolay,
	netdev
In-Reply-To: <20190830005325.26526-1-olteanv@gmail.com>

From: Vladimir Oltean <olteanv@gmail.com>
Date: Fri, 30 Aug 2019 03:53:23 +0300

> This patchset addresses a limitation in dsa_8021q where this sequence of
> commands was causing the switch to stop forwarding traffic:
> 
>   ip link add name br0 type bridge vlan_filtering 0
>   ip link set dev swp2 master br0
>   echo 1 > /sys/class/net/br0/bridge/vlan_filtering
>   echo 0 > /sys/class/net/br0/bridge/vlan_filtering
> 
> The issue has to do with the VLAN table manipulations that dsa_8021q
> does without notifying the bridge layer. The solution is to always
> restore the VLANs that the bridge knows about, when disabling tagging.

Series applied, thank you.

^ permalink raw reply

* Re: [PATCH] net: dsa: microchip: fill regmap_config name
From: David Miller @ 2019-08-31 20:19 UTC (permalink / raw)
  To: george.mccollister
  Cc: netdev, woojung.huh, andrew, f.fainelli, Tristram.Ha, marex,
	linux-kernel
In-Reply-To: <20190829141441.70063-1-george.mccollister@gmail.com>

From: George McCollister <george.mccollister@gmail.com>
Date: Thu, 29 Aug 2019 09:14:41 -0500

> Use the register value width as the regmap_config name to prevent the
> following error when the second and third regmap_configs are
> initialized.
>  "debugfs: Directory '${bus-id}' with parent 'regmap' already present!"
> 
> Signed-off-by: George McCollister <george.mccollister@gmail.com>

Applied.

^ permalink raw reply

* [PATCH net-next 08/10] net: dsa: mv88e6xxx: introduce .serdes_irq_enable
From: Vivien Didelot @ 2019-08-31 20:18 UTC (permalink / raw)
  To: netdev; +Cc: davem, Marek Behún, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190831201836.19957-1-vivien.didelot@gmail.com>

Introduce a new .serdes_irq_enable operation to prepare the abstraction
of IRQ enabling from the SERDES IRQ setup code.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
 drivers/net/dsa/mv88e6xxx/chip.c   | 11 +++++
 drivers/net/dsa/mv88e6xxx/chip.h   |  2 +
 drivers/net/dsa/mv88e6xxx/port.c   |  4 +-
 drivers/net/dsa/mv88e6xxx/serdes.c | 73 ++++++++++++------------------
 drivers/net/dsa/mv88e6xxx/serdes.h | 26 +++++++++--
 5 files changed, 66 insertions(+), 50 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 3522b11d5566..258174634bb2 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2934,6 +2934,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6341_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
+	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3184,6 +3185,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
 	.serdes_get_lane = mv88e6352_serdes_get_lane,
 	.serdes_power = mv88e6352_serdes_power,
 	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
+	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
 	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
 	.serdes_irq_free = mv88e6352_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3268,6 +3270,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6390_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
+	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3316,6 +3319,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6390x_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
+	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3364,6 +3368,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6390_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
+	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.avb_ops = &mv88e6390_avb_ops,
@@ -3414,6 +3419,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
 	.serdes_get_lane = mv88e6352_serdes_get_lane,
 	.serdes_power = mv88e6352_serdes_power,
 	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
+	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
 	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
 	.serdes_irq_free = mv88e6352_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3504,6 +3510,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6390_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
+	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3642,6 +3649,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6341_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
+	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3775,6 +3783,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
 	.serdes_get_lane = mv88e6352_serdes_get_lane,
 	.serdes_power = mv88e6352_serdes_power,
 	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
+	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
 	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
 	.serdes_irq_free = mv88e6352_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3830,6 +3839,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6390_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
+	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3882,6 +3892,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6390x_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
+	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 724ce2bf8258..0c7b0f6053d8 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -452,6 +452,8 @@ struct mv88e6xxx_ops {
 					   int port);
 	int (*serdes_irq_setup)(struct mv88e6xxx_chip *chip, int port);
 	void (*serdes_irq_free)(struct mv88e6xxx_chip *chip, int port);
+	int (*serdes_irq_enable)(struct mv88e6xxx_chip *chip, int port, u8 lane,
+				 bool enable);
 
 	/* Statistics from the SERDES interface */
 	int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port);
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index df71c08eda35..04006344adb2 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -434,7 +434,7 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
 	lane = mv88e6xxx_serdes_get_lane(chip, port);
 	if (lane) {
 		if (chip->ports[port].serdes_irq) {
-			err = mv88e6390_serdes_irq_disable(chip, port, lane);
+			err = mv88e6xxx_serdes_irq_disable(chip, port, lane);
 			if (err)
 				return err;
 		}
@@ -469,7 +469,7 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
 			return err;
 
 		if (chip->ports[port].serdes_irq) {
-			err = mv88e6390_serdes_irq_enable(chip, port, lane);
+			err = mv88e6xxx_serdes_irq_enable(chip, port, lane);
 			if (err)
 				return err;
 		}
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index e3ea8cca85b0..3562ef03ae55 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -226,15 +226,15 @@ static irqreturn_t mv88e6352_serdes_thread_fn(int irq, void *dev_id)
 	return ret;
 }
 
-static int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip)
+int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
+				bool enable)
 {
-	return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE,
-				      MV88E6352_SERDES_INT_LINK_CHANGE);
-}
+	u16 val = 0;
 
-static int mv88e6352_serdes_irq_disable(struct mv88e6xxx_chip *chip)
-{
-	return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, 0);
+	if (enable)
+		val |= MV88E6352_SERDES_INT_LINK_CHANGE;
+
+	return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, val);
 }
 
 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
@@ -245,9 +245,11 @@ unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
 int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
 {
 	unsigned int irq;
+	u8 lane;
 	int err;
 
-	if (!mv88e6352_port_has_serdes(chip, port))
+	lane = mv88e6xxx_serdes_get_lane(chip, port);
+	if (!lane)
 		return 0;
 
 	irq = mv88e6xxx_serdes_irq_mapping(chip, port);
@@ -272,15 +274,18 @@ int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
 		return err;
 	}
 
-	return mv88e6352_serdes_irq_enable(chip);
+	return mv88e6xxx_serdes_irq_enable(chip, port, lane);
 }
 
 void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
 {
-	if (!mv88e6352_port_has_serdes(chip, port))
+	u8 lane;
+
+	lane = mv88e6xxx_serdes_get_lane(chip, port);
+	if (!lane)
 		return;
 
-	mv88e6352_serdes_irq_disable(chip);
+	mv88e6xxx_serdes_irq_disable(chip, port, lane);
 
 	/* Freeing the IRQ will trigger irq callbacks. So we cannot
 	 * hold the reg_lock.
@@ -546,51 +551,31 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
 }
 
 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
-					     u8 lane)
-{
-	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
-				      MV88E6390_SGMII_INT_ENABLE,
-				      MV88E6390_SGMII_INT_LINK_DOWN |
-				      MV88E6390_SGMII_INT_LINK_UP);
-}
-
-static int mv88e6390_serdes_irq_disable_sgmii(struct mv88e6xxx_chip *chip,
-					      u8 lane)
+					     u8 lane, bool enable)
 {
-	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
-				      MV88E6390_SGMII_INT_ENABLE, 0);
-}
+	u16 val = 0;
 
-int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
-				u8 lane)
-{
-	u8 cmode = chip->ports[port].cmode;
-	int err = 0;
+	if (enable)
+		val |= MV88E6390_SGMII_INT_LINK_DOWN |
+			MV88E6390_SGMII_INT_LINK_UP;
 
-	switch (cmode) {
-	case MV88E6XXX_PORT_STS_CMODE_SGMII:
-	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
-	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
-		err = mv88e6390_serdes_irq_enable_sgmii(chip, lane);
-	}
-
-	return err;
+	return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
+				      MV88E6390_SGMII_INT_ENABLE, val);
 }
 
-int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
-				 u8 lane)
+int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
+				bool enable)
 {
 	u8 cmode = chip->ports[port].cmode;
-	int err = 0;
 
 	switch (cmode) {
 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
-		err = mv88e6390_serdes_irq_disable_sgmii(chip, lane);
+		return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
 	}
 
-	return err;
+	return 0;
 }
 
 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
@@ -676,7 +661,7 @@ int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
 		return err;
 	}
 
-	return mv88e6390_serdes_irq_enable(chip, port, lane);
+	return mv88e6xxx_serdes_irq_enable(chip, port, lane);
 }
 
 void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
@@ -687,7 +672,7 @@ void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
 	if (!lane)
 		return;
 
-	mv88e6390_serdes_irq_disable(chip, port, lane);
+	mv88e6xxx_serdes_irq_disable(chip, port, lane);
 
 	/* Freeing the IRQ will trigger irq callbacks. So we cannot
 	 * hold the reg_lock.
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index c70023f57090..e2d38b5d4222 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -88,15 +88,15 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
 			   bool on);
 int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port);
 void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port);
+int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
+				bool enable);
+int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
+				bool enable);
 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
 				 int port, uint8_t *data);
 int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
 			       uint64_t *data);
-int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
-				u8 lane);
-int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
-				 u8 lane);
 int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port);
 void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port);
 
@@ -137,4 +137,22 @@ mv88e6xxx_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
 	return chip->info->ops->serdes_irq_mapping(chip, port);
 }
 
+static inline int mv88e6xxx_serdes_irq_enable(struct mv88e6xxx_chip *chip,
+					      int port, u8 lane)
+{
+	if (!chip->info->ops->serdes_irq_enable)
+		return -EOPNOTSUPP;
+
+	return chip->info->ops->serdes_irq_enable(chip, port, lane, true);
+}
+
+static inline int mv88e6xxx_serdes_irq_disable(struct mv88e6xxx_chip *chip,
+					       int port, u8 lane)
+{
+	if (!chip->info->ops->serdes_irq_enable)
+		return -EOPNOTSUPP;
+
+	return chip->info->ops->serdes_irq_enable(chip, port, lane, false);
+}
+
 #endif
-- 
2.23.0


^ permalink raw reply related

* [PATCH net-next 10/10] net: dsa: mv88e6xxx: centralize SERDES IRQ handling
From: Vivien Didelot @ 2019-08-31 20:18 UTC (permalink / raw)
  To: netdev; +Cc: davem, Marek Behún, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190831201836.19957-1-vivien.didelot@gmail.com>

The .serdes_irq_setup are all following the same steps: get the SERDES
lane, get the IRQ mapping, request the IRQ, then enable it. So do
the .serdes_irq_free implementations: get the SERDES lane, disable
the IRQ, then free it.

This patch removes these operations in favor of generic functions.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
 drivers/net/dsa/mv88e6xxx/chip.c   |  96 +++++++++++++------
 drivers/net/dsa/mv88e6xxx/chip.h   |   2 -
 drivers/net/dsa/mv88e6xxx/serdes.c | 142 -----------------------------
 drivers/net/dsa/mv88e6xxx/serdes.h |   4 -
 4 files changed, 69 insertions(+), 175 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index c2061e20bb32..30365a54c31b 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2054,6 +2054,71 @@ static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port)
 	return 0;
 }
 
+static irqreturn_t mv88e6xxx_serdes_irq_thread_fn(int irq, void *dev_id)
+{
+	struct mv88e6xxx_port *mvp = dev_id;
+	struct mv88e6xxx_chip *chip = mvp->chip;
+	irqreturn_t ret = IRQ_NONE;
+	int port = mvp->port;
+	u8 lane;
+
+	mv88e6xxx_reg_lock(chip);
+	lane = mv88e6xxx_serdes_get_lane(chip, port);
+	if (lane)
+		ret = mv88e6xxx_serdes_irq_status(chip, port, lane);
+	mv88e6xxx_reg_unlock(chip);
+
+	return ret;
+}
+
+static int mv88e6xxx_serdes_irq_request(struct mv88e6xxx_chip *chip, int port,
+					u8 lane)
+{
+	struct mv88e6xxx_port *dev_id = &chip->ports[port];
+	unsigned int irq;
+	int err;
+
+	/* Nothing to request if this SERDES port has no IRQ */
+	irq = mv88e6xxx_serdes_irq_mapping(chip, port);
+	if (!irq)
+		return 0;
+
+	/* Requesting the IRQ will trigger IRQ callbacks, so release the lock */
+	mv88e6xxx_reg_unlock(chip);
+	err = request_threaded_irq(irq, NULL, mv88e6xxx_serdes_irq_thread_fn,
+				   IRQF_ONESHOT, "mv88e6xxx-serdes", dev_id);
+	mv88e6xxx_reg_lock(chip);
+	if (err)
+		return err;
+
+	dev_id->serdes_irq = irq;
+
+	return mv88e6xxx_serdes_irq_enable(chip, port, lane);
+}
+
+static int mv88e6xxx_serdes_irq_free(struct mv88e6xxx_chip *chip, int port,
+				     u8 lane)
+{
+	struct mv88e6xxx_port *dev_id = &chip->ports[port];
+	unsigned int irq = dev_id->serdes_irq;
+	int err;
+
+	/* Nothing to free if no IRQ has been requested */
+	if (!irq)
+		return 0;
+
+	err = mv88e6xxx_serdes_irq_disable(chip, port, lane);
+
+	/* Freeing the IRQ will trigger IRQ callbacks, so release the lock */
+	mv88e6xxx_reg_unlock(chip);
+	free_irq(irq, dev_id);
+	mv88e6xxx_reg_lock(chip);
+
+	dev_id->serdes_irq = 0;
+
+	return err;
+}
+
 static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port,
 				  bool on)
 {
@@ -2069,12 +2134,11 @@ static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port,
 		if (err)
 			return err;
 
-		if (chip->info->ops->serdes_irq_setup)
-			err = chip->info->ops->serdes_irq_setup(chip, port);
+		err = mv88e6xxx_serdes_irq_request(chip, port, lane);
 	} else {
-		if (chip->info->ops->serdes_irq_free &&
-		    chip->ports[port].serdes_irq)
-			chip->info->ops->serdes_irq_free(chip, port);
+		err = mv88e6xxx_serdes_irq_free(chip, port, lane);
+		if (err)
+			return err;
 
 		err = mv88e6xxx_serdes_power_down(chip, port, lane);
 	}
@@ -2936,8 +3000,6 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_status = mv88e6390_serdes_irq_status,
-	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
-	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
 	.phylink_validate = mv88e6341_phylink_validate,
 };
@@ -3188,8 +3250,6 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
 	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
 	.serdes_irq_status = mv88e6352_serdes_irq_status,
-	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
-	.serdes_irq_free = mv88e6352_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
 	.phylink_validate = mv88e6352_phylink_validate,
 };
@@ -3274,8 +3334,6 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_status = mv88e6390_serdes_irq_status,
-	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
-	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
 	.phylink_validate = mv88e6390_phylink_validate,
 };
@@ -3324,8 +3382,6 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_status = mv88e6390_serdes_irq_status,
-	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
-	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
 	.phylink_validate = mv88e6390x_phylink_validate,
 };
@@ -3374,8 +3430,6 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_status = mv88e6390_serdes_irq_status,
-	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
-	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.avb_ops = &mv88e6390_avb_ops,
 	.ptp_ops = &mv88e6352_ptp_ops,
 	.phylink_validate = mv88e6390_phylink_validate,
@@ -3426,8 +3480,6 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
 	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
 	.serdes_irq_status = mv88e6352_serdes_irq_status,
-	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
-	.serdes_irq_free = mv88e6352_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
 	.avb_ops = &mv88e6352_avb_ops,
 	.ptp_ops = &mv88e6352_ptp_ops,
@@ -3518,8 +3570,6 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_status = mv88e6390_serdes_irq_status,
-	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
-	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
 	.avb_ops = &mv88e6390_avb_ops,
 	.ptp_ops = &mv88e6352_ptp_ops,
@@ -3658,8 +3708,6 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_status = mv88e6390_serdes_irq_status,
-	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
-	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
 	.avb_ops = &mv88e6390_avb_ops,
 	.ptp_ops = &mv88e6352_ptp_ops,
@@ -3793,8 +3841,6 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
 	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
 	.serdes_irq_status = mv88e6352_serdes_irq_status,
-	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
-	.serdes_irq_free = mv88e6352_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
 	.avb_ops = &mv88e6352_avb_ops,
 	.ptp_ops = &mv88e6352_ptp_ops,
@@ -3850,8 +3896,6 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_status = mv88e6390_serdes_irq_status,
-	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
-	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
 	.avb_ops = &mv88e6390_avb_ops,
 	.ptp_ops = &mv88e6352_ptp_ops,
@@ -3904,8 +3948,6 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
 	.serdes_irq_status = mv88e6390_serdes_irq_status,
-	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
-	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
 	.avb_ops = &mv88e6390_avb_ops,
 	.ptp_ops = &mv88e6352_ptp_ops,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 9a73fd1d643b..6bc0a4e4fe7b 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -450,8 +450,6 @@ struct mv88e6xxx_ops {
 	/* SERDES interrupt handling */
 	unsigned int (*serdes_irq_mapping)(struct mv88e6xxx_chip *chip,
 					   int port);
-	int (*serdes_irq_setup)(struct mv88e6xxx_chip *chip, int port);
-	void (*serdes_irq_free)(struct mv88e6xxx_chip *chip, int port);
 	int (*serdes_irq_enable)(struct mv88e6xxx_chip *chip, int port, u8 lane,
 				 bool enable);
 	irqreturn_t (*serdes_irq_status)(struct mv88e6xxx_chip *chip, int port,
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index d37419ba26ab..902feb398746 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -221,19 +221,6 @@ irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
 	return ret;
 }
 
-static irqreturn_t mv88e6352_serdes_thread_fn(int irq, void *dev_id)
-{
-	struct mv88e6xxx_port *port = dev_id;
-	struct mv88e6xxx_chip *chip = port->chip;
-	irqreturn_t ret = IRQ_NONE;
-
-	mv88e6xxx_reg_lock(chip);
-	ret = mv88e6xxx_serdes_irq_status(chip, port->port, 0);
-	mv88e6xxx_reg_unlock(chip);
-
-	return ret;
-}
-
 int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
 				bool enable)
 {
@@ -250,61 +237,6 @@ unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
 	return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ);
 }
 
-int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
-{
-	unsigned int irq;
-	u8 lane;
-	int err;
-
-	lane = mv88e6xxx_serdes_get_lane(chip, port);
-	if (!lane)
-		return 0;
-
-	irq = mv88e6xxx_serdes_irq_mapping(chip, port);
-	if (!irq)
-		return 0;
-
-	chip->ports[port].serdes_irq = irq;
-
-	/* Requesting the IRQ will trigger irq callbacks. So we cannot
-	 * hold the reg_lock.
-	 */
-	mv88e6xxx_reg_unlock(chip);
-	err = request_threaded_irq(chip->ports[port].serdes_irq, NULL,
-				   mv88e6352_serdes_thread_fn,
-				   IRQF_ONESHOT, "mv88e6xxx-serdes",
-				   &chip->ports[port]);
-	mv88e6xxx_reg_lock(chip);
-
-	if (err) {
-		dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n",
-			err);
-		return err;
-	}
-
-	return mv88e6xxx_serdes_irq_enable(chip, port, lane);
-}
-
-void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
-{
-	u8 lane;
-
-	lane = mv88e6xxx_serdes_get_lane(chip, port);
-	if (!lane)
-		return;
-
-	mv88e6xxx_serdes_irq_disable(chip, port, lane);
-
-	/* Freeing the IRQ will trigger irq callbacks. So we cannot
-	 * hold the reg_lock.
-	 */
-	mv88e6xxx_reg_unlock(chip);
-	free_irq(chip->ports[port].serdes_irq, &chip->ports[port]);
-	mv88e6xxx_reg_lock(chip);
-
-	chip->ports[port].serdes_irq = 0;
-}
-
 u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 {
 	u8 cmode = chip->ports[port].cmode;
@@ -622,81 +554,7 @@ irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
 	return ret;
 }
 
-static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
-{
-	struct mv88e6xxx_port *port = dev_id;
-	struct mv88e6xxx_chip *chip = port->chip;
-	irqreturn_t ret = IRQ_NONE;
-	u8 lane;
-
-	mv88e6xxx_reg_lock(chip);
-	lane = mv88e6xxx_serdes_get_lane(chip, port->port);
-	if (!lane)
-		goto out;
-
-	ret = mv88e6xxx_serdes_irq_status(chip, port->port, lane);
-out:
-	mv88e6xxx_reg_unlock(chip);
-
-	return ret;
-}
-
 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
 {
 	return irq_find_mapping(chip->g2_irq.domain, port);
 }
-
-int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
-{
-	unsigned int irq;
-	int err;
-	u8 lane;
-
-	lane = mv88e6xxx_serdes_get_lane(chip, port);
-	if (!lane)
-		return 0;
-
-	irq = mv88e6xxx_serdes_irq_mapping(chip, port);
-	if (!irq)
-		return 0;
-
-	chip->ports[port].serdes_irq = irq;
-
-	/* Requesting the IRQ will trigger irq callbacks. So we cannot
-	 * hold the reg_lock.
-	 */
-	mv88e6xxx_reg_unlock(chip);
-	err = request_threaded_irq(chip->ports[port].serdes_irq, NULL,
-				   mv88e6390_serdes_thread_fn,
-				   IRQF_ONESHOT, "mv88e6xxx-serdes",
-				   &chip->ports[port]);
-	mv88e6xxx_reg_lock(chip);
-
-	if (err) {
-		dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n",
-			err);
-		return err;
-	}
-
-	return mv88e6xxx_serdes_irq_enable(chip, port, lane);
-}
-
-void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
-{
-	u8 lane;
-
-	lane = mv88e6xxx_serdes_get_lane(chip, port);
-	if (!lane)
-		return;
-
-	mv88e6xxx_serdes_irq_disable(chip, port, lane);
-
-	/* Freeing the IRQ will trigger irq callbacks. So we cannot
-	 * hold the reg_lock.
-	 */
-	mv88e6xxx_reg_unlock(chip);
-	free_irq(chip->ports[port].serdes_irq, &chip->ports[port]);
-	mv88e6xxx_reg_lock(chip);
-
-	chip->ports[port].serdes_irq = 0;
-}
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index 52f937347a36..bd8df36ab537 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -86,8 +86,6 @@ int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
 			   bool on);
 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
 			   bool on);
-int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port);
-void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port);
 int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
 				bool enable);
 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
@@ -101,8 +99,6 @@ int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
 				 int port, uint8_t *data);
 int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
 			       uint64_t *data);
-int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port);
-void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port);
 
 /* Return the (first) SERDES lane address a port is using, 0 otherwise. */
 static inline u8 mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
-- 
2.23.0


^ permalink raw reply related

* [PATCH net-next 09/10] net: dsa: mv88e6xxx: introduce .serdes_irq_status
From: Vivien Didelot @ 2019-08-31 20:18 UTC (permalink / raw)
  To: netdev; +Cc: davem, Marek Behún, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190831201836.19957-1-vivien.didelot@gmail.com>

Introduce a new .serdes_irq_status operation to prepare the abstraction
of IRQ thread from the SERDES IRQ setup code.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
 drivers/net/dsa/mv88e6xxx/chip.c   | 11 ++++++
 drivers/net/dsa/mv88e6xxx/chip.h   |  2 +
 drivers/net/dsa/mv88e6xxx/serdes.c | 59 +++++++++++++++++++-----------
 drivers/net/dsa/mv88e6xxx/serdes.h | 13 +++++++
 4 files changed, 64 insertions(+), 21 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 258174634bb2..c2061e20bb32 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2935,6 +2935,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
 	.serdes_get_lane = mv88e6341_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
+	.serdes_irq_status = mv88e6390_serdes_irq_status,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3186,6 +3187,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
 	.serdes_power = mv88e6352_serdes_power,
 	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
+	.serdes_irq_status = mv88e6352_serdes_irq_status,
 	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
 	.serdes_irq_free = mv88e6352_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3271,6 +3273,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
 	.serdes_get_lane = mv88e6390_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
+	.serdes_irq_status = mv88e6390_serdes_irq_status,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3320,6 +3323,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
 	.serdes_get_lane = mv88e6390x_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
+	.serdes_irq_status = mv88e6390_serdes_irq_status,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3369,6 +3373,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
 	.serdes_get_lane = mv88e6390_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
+	.serdes_irq_status = mv88e6390_serdes_irq_status,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.avb_ops = &mv88e6390_avb_ops,
@@ -3420,6 +3425,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
 	.serdes_power = mv88e6352_serdes_power,
 	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
+	.serdes_irq_status = mv88e6352_serdes_irq_status,
 	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
 	.serdes_irq_free = mv88e6352_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3511,6 +3517,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
 	.serdes_get_lane = mv88e6390_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
+	.serdes_irq_status = mv88e6390_serdes_irq_status,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3650,6 +3657,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
 	.serdes_get_lane = mv88e6341_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
+	.serdes_irq_status = mv88e6390_serdes_irq_status,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3784,6 +3792,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
 	.serdes_power = mv88e6352_serdes_power,
 	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
+	.serdes_irq_status = mv88e6352_serdes_irq_status,
 	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
 	.serdes_irq_free = mv88e6352_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3840,6 +3849,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
 	.serdes_get_lane = mv88e6390_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
+	.serdes_irq_status = mv88e6390_serdes_irq_status,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3893,6 +3903,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
 	.serdes_get_lane = mv88e6390x_serdes_get_lane,
 	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_enable = mv88e6390_serdes_irq_enable,
+	.serdes_irq_status = mv88e6390_serdes_irq_status,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 0c7b0f6053d8..9a73fd1d643b 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -454,6 +454,8 @@ struct mv88e6xxx_ops {
 	void (*serdes_irq_free)(struct mv88e6xxx_chip *chip, int port);
 	int (*serdes_irq_enable)(struct mv88e6xxx_chip *chip, int port, u8 lane,
 				 bool enable);
+	irqreturn_t (*serdes_irq_status)(struct mv88e6xxx_chip *chip, int port,
+					 u8 lane);
 
 	/* Statistics from the SERDES interface */
 	int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port);
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 3562ef03ae55..d37419ba26ab 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -202,25 +202,33 @@ static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
 	dsa_port_phylink_mac_change(ds, port, up);
 }
 
-static irqreturn_t mv88e6352_serdes_thread_fn(int irq, void *dev_id)
+irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
+					u8 lane)
 {
-	struct mv88e6xxx_port *port = dev_id;
-	struct mv88e6xxx_chip *chip = port->chip;
 	irqreturn_t ret = IRQ_NONE;
 	u16 status;
 	int err;
 
-	mv88e6xxx_reg_lock(chip);
-
 	err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status);
 	if (err)
-		goto out;
+		return ret;
 
 	if (status & MV88E6352_SERDES_INT_LINK_CHANGE) {
 		ret = IRQ_HANDLED;
-		mv88e6352_serdes_irq_link(chip, port->port);
+		mv88e6352_serdes_irq_link(chip, port);
 	}
-out:
+
+	return ret;
+}
+
+static irqreturn_t mv88e6352_serdes_thread_fn(int irq, void *dev_id)
+{
+	struct mv88e6xxx_port *port = dev_id;
+	struct mv88e6xxx_chip *chip = port->chip;
+	irqreturn_t ret = IRQ_NONE;
+
+	mv88e6xxx_reg_lock(chip);
+	ret = mv88e6xxx_serdes_irq_status(chip, port->port, 0);
 	mv88e6xxx_reg_unlock(chip);
 
 	return ret;
@@ -589,21 +597,13 @@ static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
 	return err;
 }
 
-static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
+irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
+					u8 lane)
 {
-	struct mv88e6xxx_port *port = dev_id;
-	struct mv88e6xxx_chip *chip = port->chip;
+	u8 cmode = chip->ports[port].cmode;
 	irqreturn_t ret = IRQ_NONE;
-	u8 cmode = port->cmode;
 	u16 status;
 	int err;
-	u8 lane;
-
-	mv88e6xxx_reg_lock(chip);
-
-	lane = mv88e6xxx_serdes_get_lane(chip, port->port);
-	if (!lane)
-		goto out;
 
 	switch (cmode) {
 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
@@ -611,13 +611,30 @@ static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
 		err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
 		if (err)
-			goto out;
+			return ret;
 		if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
 			      MV88E6390_SGMII_INT_LINK_UP)) {
 			ret = IRQ_HANDLED;
-			mv88e6390_serdes_irq_link_sgmii(chip, port->port, lane);
+			mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
 		}
 	}
+
+	return ret;
+}
+
+static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
+{
+	struct mv88e6xxx_port *port = dev_id;
+	struct mv88e6xxx_chip *chip = port->chip;
+	irqreturn_t ret = IRQ_NONE;
+	u8 lane;
+
+	mv88e6xxx_reg_lock(chip);
+	lane = mv88e6xxx_serdes_get_lane(chip, port->port);
+	if (!lane)
+		goto out;
+
+	ret = mv88e6xxx_serdes_irq_status(chip, port->port, lane);
 out:
 	mv88e6xxx_reg_unlock(chip);
 
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index e2d38b5d4222..52f937347a36 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -92,6 +92,10 @@ int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
 				bool enable);
 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
 				bool enable);
+irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
+					u8 lane);
+irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
+					u8 lane);
 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
 				 int port, uint8_t *data);
@@ -155,4 +159,13 @@ static inline int mv88e6xxx_serdes_irq_disable(struct mv88e6xxx_chip *chip,
 	return chip->info->ops->serdes_irq_enable(chip, port, lane, false);
 }
 
+static inline irqreturn_t
+mv88e6xxx_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, u8 lane)
+{
+	if (!chip->info->ops->serdes_irq_status)
+		return IRQ_NONE;
+
+	return chip->info->ops->serdes_irq_status(chip, port, lane);
+}
+
 #endif
-- 
2.23.0


^ permalink raw reply related

* [PATCH net-next 05/10] net: dsa: mv88e6xxx: implement mv88e6352_serdes_get_lane
From: Vivien Didelot @ 2019-08-31 20:18 UTC (permalink / raw)
  To: netdev; +Cc: davem, Marek Behún, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190831201836.19957-1-vivien.didelot@gmail.com>

Even though 88E6352 has no dedicated lane for SERDES interfaces, it
uses a similar code as the other .serdes_get_lane implementations to
check the port's CMODE and ensure that SERDES operations are doable.

For consistency, implement mv88e6352_serdes_get_lane for the 88E6352
and similar switches which simply returns an unused 0xff lane address.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
 drivers/net/dsa/mv88e6xxx/chip.c   |  4 ++++
 drivers/net/dsa/mv88e6xxx/serdes.c | 11 ++++++++++-
 drivers/net/dsa/mv88e6xxx/serdes.h |  1 +
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 0ab4ce86eda7..3962e7368ae5 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -3093,6 +3093,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
 	.rmu_disable = mv88e6352_g1_rmu_disable,
 	.vtu_getnext = mv88e6352_g1_vtu_getnext,
 	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
+	.serdes_get_lane = mv88e6352_serdes_get_lane,
 	.serdes_power = mv88e6352_serdes_power,
 	.gpio_ops = &mv88e6352_gpio_ops,
 	.phylink_validate = mv88e6352_phylink_validate,
@@ -3178,6 +3179,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
 	.rmu_disable = mv88e6352_g1_rmu_disable,
 	.vtu_getnext = mv88e6352_g1_vtu_getnext,
 	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
+	.serdes_get_lane = mv88e6352_serdes_get_lane,
 	.serdes_power = mv88e6352_serdes_power,
 	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
@@ -3407,6 +3409,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
 	.rmu_disable = mv88e6352_g1_rmu_disable,
 	.vtu_getnext = mv88e6352_g1_vtu_getnext,
 	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
+	.serdes_get_lane = mv88e6352_serdes_get_lane,
 	.serdes_power = mv88e6352_serdes_power,
 	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
@@ -3767,6 +3770,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
 	.rmu_disable = mv88e6352_g1_rmu_disable,
 	.vtu_getnext = mv88e6352_g1_vtu_getnext,
 	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
+	.serdes_get_lane = mv88e6352_serdes_get_lane,
 	.serdes_power = mv88e6352_serdes_power,
 	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index ce6d97e5caf8..9fb2773a3eb5 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -69,13 +69,22 @@ static int mv88e6352_serdes_power_set(struct mv88e6xxx_chip *chip, bool on)
 	return err;
 }
 
-static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
+u8 mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 {
 	u8 cmode = chip->ports[port].cmode;
+	u8 lane = 0;
 
 	if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) ||
 	    (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) ||
 	    (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
+		lane = 0xff; /* Unused */
+
+	return lane;
+}
+
+static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
+{
+	if (mv88e6xxx_serdes_get_lane(chip, port))
 		return true;
 
 	return false;
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index 4718dcca6b3c..7df27a0de9aa 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -75,6 +75,7 @@
 #define MV88E6390_SGMII_PHY_STATUS_LINK		BIT(10)
 
 u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
+u8 mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
 u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
 u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
-- 
2.23.0


^ permalink raw reply related

* [PATCH net-next 07/10] net: dsa: mv88e6xxx: pass lane to .serdes_power
From: Vivien Didelot @ 2019-08-31 20:18 UTC (permalink / raw)
  To: netdev; +Cc: davem, Marek Behún, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190831201836.19957-1-vivien.didelot@gmail.com>

Now the first step of all .serdes_power implementations is getting
the lane mapping. Since we have an operation for that, call it in
the wrapper and pass the lane down to the .serdes_power operation.

This also allows to avoid querying the SERDES lane twice in
mv88e6xxx_port_set_cmode.

At the same time provide mv88e6xxx_serdes_power_{up,down} helpers
and prefer up/down instead of on/off as in the documentation.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
 drivers/net/dsa/mv88e6xxx/chip.c   |  8 +++++---
 drivers/net/dsa/mv88e6xxx/chip.h   |  3 ++-
 drivers/net/dsa/mv88e6xxx/port.c   |  4 ++--
 drivers/net/dsa/mv88e6xxx/serdes.c | 32 ++++++++++++------------------
 drivers/net/dsa/mv88e6xxx/serdes.h | 24 ++++++++++++++++++++--
 5 files changed, 44 insertions(+), 27 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 3962e7368ae5..3522b11d5566 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2057,13 +2057,15 @@ static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port)
 static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port,
 				  bool on)
 {
+	u8 lane;
 	int err;
 
-	if (!chip->info->ops->serdes_power)
+	lane = mv88e6xxx_serdes_get_lane(chip, port);
+	if (!lane)
 		return 0;
 
 	if (on) {
-		err = chip->info->ops->serdes_power(chip, port, true);
+		err = mv88e6xxx_serdes_power_up(chip, port, lane);
 		if (err)
 			return err;
 
@@ -2074,7 +2076,7 @@ static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port,
 		    chip->ports[port].serdes_irq)
 			chip->info->ops->serdes_irq_free(chip, port);
 
-		err = chip->info->ops->serdes_power(chip, port, false);
+		err = mv88e6xxx_serdes_power_down(chip, port, lane);
 	}
 
 	return err;
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index add0ec5188ec..724ce2bf8258 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -441,7 +441,8 @@ struct mv88e6xxx_ops {
 	int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip);
 
 	/* Power on/off a SERDES interface */
-	int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, bool on);
+	int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, u8 lane,
+			    bool up);
 
 	/* SERDES lane mapping */
 	u8 (*serdes_get_lane)(struct mv88e6xxx_chip *chip, int port);
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 06e2bdf6fa82..df71c08eda35 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -439,7 +439,7 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
 				return err;
 		}
 
-		err = mv88e6390_serdes_power(chip, port, false);
+		err = mv88e6xxx_serdes_power_down(chip, port, lane);
 		if (err)
 			return err;
 	}
@@ -464,7 +464,7 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
 		if (!lane)
 			return -ENODEV;
 
-		err = mv88e6390_serdes_power(chip, port, true);
+		err = mv88e6xxx_serdes_power_up(chip, port, lane);
 		if (err)
 			return err;
 
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index e8ad66987be9..e3ea8cca85b0 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -49,19 +49,17 @@ static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip,
 	return mv88e6xxx_phy_write(chip, lane, reg_c45, val);
 }
 
-int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
+int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
+			   bool up)
 {
 	u16 val, new_val;
 	int err;
 
-	if (!mv88e6xxx_serdes_get_lane(chip, port))
-		return 0;
-
 	err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
 	if (err)
 		return err;
 
-	if (on)
+	if (up)
 		new_val = val & ~BMCR_PDOWN;
 	else
 		new_val = val | BMCR_PDOWN;
@@ -409,9 +407,9 @@ u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 	return lane;
 }
 
-/* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */
+/* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */
 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane,
-				      bool on)
+				      bool up)
 {
 	u16 val, new_val;
 	int err;
@@ -422,7 +420,7 @@ static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane,
 	if (err)
 		return err;
 
-	if (on)
+	if (up)
 		new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET |
 				  MV88E6390_PCS_CONTROL_1_LOOPBACK |
 				  MV88E6390_PCS_CONTROL_1_PDOWN);
@@ -436,9 +434,9 @@ static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane,
 	return err;
 }
 
-/* Set the power on/off for SGMII and 1000Base-X */
+/* Set power up/down for SGMII and 1000Base-X */
 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane,
-					bool on)
+					bool up)
 {
 	u16 val, new_val;
 	int err;
@@ -448,7 +446,7 @@ static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane,
 	if (err)
 		return err;
 
-	if (on)
+	if (up)
 		new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET |
 				  MV88E6390_SGMII_CONTROL_LOOPBACK |
 				  MV88E6390_SGMII_CONTROL_PDOWN);
@@ -462,23 +460,19 @@ static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane,
 	return err;
 }
 
-int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
+int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
+			   bool up)
 {
 	u8 cmode = chip->ports[port].cmode;
-	u8 lane;
-
-	lane = mv88e6xxx_serdes_get_lane(chip, port);
-	if (!lane)
-		return 0;
 
 	switch (cmode) {
 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
 	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
-		return mv88e6390_serdes_power_sgmii(chip, lane, on);
+		return mv88e6390_serdes_power_sgmii(chip, lane, up);
 	case MV88E6XXX_PORT_STS_CMODE_XAUI:
 	case MV88E6XXX_PORT_STS_CMODE_RXAUI:
-		return mv88e6390_serdes_power_10g(chip, lane, on);
+		return mv88e6390_serdes_power_10g(chip, lane, up);
 	}
 
 	return 0;
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index 7df27a0de9aa..c70023f57090 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -82,8 +82,10 @@ unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
 					  int port);
 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
 					  int port);
-int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
-int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
+int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
+			   bool on);
+int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
+			   bool on);
 int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port);
 void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port);
 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
@@ -108,6 +110,24 @@ static inline u8 mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
 	return chip->info->ops->serdes_get_lane(chip, port);
 }
 
+static inline int mv88e6xxx_serdes_power_up(struct mv88e6xxx_chip *chip,
+					    int port, u8 lane)
+{
+	if (!chip->info->ops->serdes_power)
+		return -EOPNOTSUPP;
+
+	return chip->info->ops->serdes_power(chip, port, lane, true);
+}
+
+static inline int mv88e6xxx_serdes_power_down(struct mv88e6xxx_chip *chip,
+					      int port, u8 lane)
+{
+	if (!chip->info->ops->serdes_power)
+		return -EOPNOTSUPP;
+
+	return chip->info->ops->serdes_power(chip, port, lane, false);
+}
+
 static inline unsigned int
 mv88e6xxx_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
 {
-- 
2.23.0


^ permalink raw reply related

* [PATCH net-next 06/10] net: dsa: mv88e6xxx: merge mv88e6352_serdes_power_set
From: Vivien Didelot @ 2019-08-31 20:18 UTC (permalink / raw)
  To: netdev; +Cc: davem, Marek Behún, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190831201836.19957-1-vivien.didelot@gmail.com>

The mv88e6352_serdes_power_set helper is only used at one place, in
mv88e6352_serdes_power. Keep it simple and merge the two functions
together.

Use mv88e6xxx_serdes_get_lane instead of mv88e6352_port_has_serdes
to avoid moving code. No functional changes.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
 drivers/net/dsa/mv88e6xxx/serdes.c | 18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 9fb2773a3eb5..e8ad66987be9 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -49,11 +49,14 @@ static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip,
 	return mv88e6xxx_phy_write(chip, lane, reg_c45, val);
 }
 
-static int mv88e6352_serdes_power_set(struct mv88e6xxx_chip *chip, bool on)
+int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
 {
 	u16 val, new_val;
 	int err;
 
+	if (!mv88e6xxx_serdes_get_lane(chip, port))
+		return 0;
+
 	err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
 	if (err)
 		return err;
@@ -90,19 +93,6 @@ static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
 	return false;
 }
 
-int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
-{
-	int err;
-
-	if (mv88e6352_port_has_serdes(chip, port)) {
-		err = mv88e6352_serdes_power_set(chip, on);
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
 struct mv88e6352_serdes_hw_stat {
 	char string[ETH_GSTRING_LEN];
 	int sizeof_stat;
-- 
2.23.0


^ permalink raw reply related

* [PATCH net-next 04/10] net: dsa: mv88e6xxx: simplify .serdes_get_lane
From: Vivien Didelot @ 2019-08-31 20:18 UTC (permalink / raw)
  To: netdev; +Cc: davem, Marek Behún, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190831201836.19957-1-vivien.didelot@gmail.com>

Because the mapping between a SERDES interface and its lane is static,
we don't need to stick with negative error codes actually and we can
simply return 0 if there is no lane, just like the IRQ mapping.

This way we can keep a simple and intuitive API using unsigned lane
numbers while simplifying the implementations with single return
statements. Last but not least, fix the reverse chrismas tree in
mv88e6390x_serdes_get_lane.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
 drivers/net/dsa/mv88e6xxx/chip.h   |   2 +-
 drivers/net/dsa/mv88e6xxx/port.c   |  13 +--
 drivers/net/dsa/mv88e6xxx/serdes.c | 152 +++++++++++------------------
 drivers/net/dsa/mv88e6xxx/serdes.h |  29 +++---
 4 files changed, 74 insertions(+), 122 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index b116bd7f6109..add0ec5188ec 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -444,7 +444,7 @@ struct mv88e6xxx_ops {
 	int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, bool on);
 
 	/* SERDES lane mapping */
-	int (*serdes_get_lane)(struct mv88e6xxx_chip *chip, int port, u8 *lane);
+	u8 (*serdes_get_lane)(struct mv88e6xxx_chip *chip, int port);
 
 	/* SERDES interrupt handling */
 	unsigned int (*serdes_irq_mapping)(struct mv88e6xxx_chip *chip,
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 4f841335ea32..06e2bdf6fa82 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -431,11 +431,8 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
 	if (cmode == chip->ports[port].cmode)
 		return 0;
 
-	err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
-	if (err && err != -ENODEV)
-		return err;
-
-	if (err != -ENODEV) {
+	lane = mv88e6xxx_serdes_get_lane(chip, port);
+	if (lane) {
 		if (chip->ports[port].serdes_irq) {
 			err = mv88e6390_serdes_irq_disable(chip, port, lane);
 			if (err)
@@ -463,9 +460,9 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
 
 		chip->ports[port].cmode = cmode;
 
-		err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
-		if (err)
-			return err;
+		lane = mv88e6xxx_serdes_get_lane(chip, port);
+		if (!lane)
+			return -ENODEV;
 
 		err = mv88e6390_serdes_power(chip, port, true);
 		if (err)
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 4fb1dca64ef1..ce6d97e5caf8 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -295,149 +295,119 @@ void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
 	chip->ports[port].serdes_irq = 0;
 }
 
-int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane)
+u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 {
 	u8 cmode = chip->ports[port].cmode;
+	u8 lane = 0;
 
-	if (port != 5)
-		return -ENODEV;
-
-	if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
-	    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
-	    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) {
-		*lane = MV88E6341_PORT5_LANE;
-		return 0;
+	switch (port) {
+	case 5:
+		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
+		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
+		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
+			lane = MV88E6341_PORT5_LANE;
+		break;
 	}
 
-	return -ENODEV;
+	return lane;
 }
 
-int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane)
+u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 {
 	u8 cmode = chip->ports[port].cmode;
+	u8 lane = 0;
 
 	switch (port) {
 	case 9:
 		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
-		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) {
-			*lane = MV88E6390_PORT9_LANE0;
-			return 0;
-		}
+		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
+			lane = MV88E6390_PORT9_LANE0;
 		break;
 	case 10:
 		if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 		    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
-		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) {
-			*lane = MV88E6390_PORT10_LANE0;
-			return 0;
-		}
-		break;
-	default:
+		    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
+			lane = MV88E6390_PORT10_LANE0;
 		break;
 	}
 
-	return -ENODEV;
+	return lane;
 }
 
-int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane)
+u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 {
-	u8 cmode_port9, cmode_port10, cmode_port;
-
-	cmode_port9 = chip->ports[9].cmode;
-	cmode_port10 = chip->ports[10].cmode;
-	cmode_port = chip->ports[port].cmode;
+	u8 cmode_port = chip->ports[port].cmode;
+	u8 cmode_port10 = chip->ports[10].cmode;
+	u8 cmode_port9 = chip->ports[9].cmode;
+	u8 lane = 0;
 
 	switch (port) {
 	case 2:
 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
-		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) {
-			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) {
-				*lane = MV88E6390_PORT9_LANE1;
-				return 0;
-			}
-		}
+		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
+			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
+				lane = MV88E6390_PORT9_LANE1;
 		break;
 	case 3:
 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
-		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) {
-			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) {
-				*lane = MV88E6390_PORT9_LANE2;
-				return 0;
-			}
-		}
+		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
+			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
+				lane = MV88E6390_PORT9_LANE2;
 		break;
 	case 4:
 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
-		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) {
-			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) {
-				*lane = MV88E6390_PORT9_LANE3;
-				return 0;
-			}
-		}
+		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
+			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
+				lane = MV88E6390_PORT9_LANE3;
 		break;
 	case 5:
 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
-		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) {
-			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) {
-				*lane = MV88E6390_PORT10_LANE1;
-				return 0;
-			}
-		}
+		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
+			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
+				lane = MV88E6390_PORT10_LANE1;
 		break;
 	case 6:
 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
-		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) {
-			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) {
-				*lane = MV88E6390_PORT10_LANE2;
-				return 0;
-			}
-		}
+		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
+			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
+				lane = MV88E6390_PORT10_LANE2;
 		break;
 	case 7:
 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
-		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) {
-			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) {
-				*lane = MV88E6390_PORT10_LANE3;
-				return 0;
-			}
-		}
+		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
+			if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
+				lane = MV88E6390_PORT10_LANE3;
 		break;
 	case 9:
 		if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
-		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) {
-			*lane = MV88E6390_PORT9_LANE0;
-			return 0;
-		}
+		    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
+			lane = MV88E6390_PORT9_LANE0;
 		break;
 	case 10:
 		if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
-		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) {
-			*lane = MV88E6390_PORT10_LANE0;
-			return 0;
-		}
-		break;
-	default:
+		    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
+			lane = MV88E6390_PORT10_LANE0;
 		break;
 	}
 
-	return -ENODEV;
+	return lane;
 }
 
 /* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */
@@ -497,14 +467,10 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
 {
 	u8 cmode = chip->ports[port].cmode;
 	u8 lane;
-	int err;
 
-	err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
-	if (err) {
-		if (err == -ENODEV)
-			err = 0;
-		return err;
-	}
+	lane = mv88e6xxx_serdes_get_lane(chip, port);
+	if (!lane)
+		return 0;
 
 	switch (cmode) {
 	case MV88E6XXX_PORT_STS_CMODE_SGMII:
@@ -657,8 +623,8 @@ static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
 
 	mv88e6xxx_reg_lock(chip);
 
-	err = mv88e6xxx_serdes_get_lane(chip, port->port, &lane);
-	if (err)
+	lane = mv88e6xxx_serdes_get_lane(chip, port->port);
+	if (!lane)
 		goto out;
 
 	switch (cmode) {
@@ -691,12 +657,9 @@ int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
 	int err;
 	u8 lane;
 
-	err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
-	if (err) {
-		if (err == -ENODEV)
-			err = 0;
-		return err;
-	}
+	lane = mv88e6xxx_serdes_get_lane(chip, port);
+	if (!lane)
+		return 0;
 
 	irq = mv88e6xxx_serdes_irq_mapping(chip, port);
 	if (!irq)
@@ -725,16 +688,11 @@ int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
 
 void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
 {
-	int err;
 	u8 lane;
 
-	err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
-	if (err) {
-		if (err != -ENODEV)
-			dev_err(chip->dev, "Unable to free SERDES irq: %d\n",
-				err);
+	lane = mv88e6xxx_serdes_get_lane(chip, port);
+	if (!lane)
 		return;
-	}
 
 	mv88e6390_serdes_irq_disable(chip, port, lane);
 
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index cb8d287c9388..4718dcca6b3c 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -74,22 +74,9 @@
 #define MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID BIT(11)
 #define MV88E6390_SGMII_PHY_STATUS_LINK		BIT(10)
 
-/* Put the SERDES lane address a port is using into *lane. If a port has
- * multiple lanes, should put the first lane the port is using. If a port does
- * not have a lane, return -ENODEV.
- */
-static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
-					    int port, u8 *lane)
-{
-	if (!chip->info->ops->serdes_get_lane)
-		return -EOPNOTSUPP;
-
-	return chip->info->ops->serdes_get_lane(chip, port, lane);
-}
-
-int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane);
-int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane);
-int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane);
+u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
+u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
+u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
 					  int port);
 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
@@ -110,6 +97,16 @@ int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
 int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port);
 void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port);
 
+/* Return the (first) SERDES lane address a port is using, 0 otherwise. */
+static inline u8 mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
+					   int port)
+{
+	if (!chip->info->ops->serdes_get_lane)
+		return 0;
+
+	return chip->info->ops->serdes_get_lane(chip, port);
+}
+
 static inline unsigned int
 mv88e6xxx_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
 {
-- 
2.23.0


^ permalink raw reply related

* [PATCH net-next 03/10] net: dsa: mv88e6xxx: introduce .serdes_irq_mapping
From: Vivien Didelot @ 2019-08-31 20:18 UTC (permalink / raw)
  To: netdev; +Cc: davem, Marek Behún, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190831201836.19957-1-vivien.didelot@gmail.com>

Introduce a new .serdes_irq_mapping operation to prepare the
abstraction of IRQ mapping from the SERDES IRQ setup code.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
 drivers/net/dsa/mv88e6xxx/chip.c   | 11 +++++++++++
 drivers/net/dsa/mv88e6xxx/chip.h   |  2 ++
 drivers/net/dsa/mv88e6xxx/serdes.c | 26 ++++++++++++++++++++------
 drivers/net/dsa/mv88e6xxx/serdes.h | 12 ++++++++++++
 4 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index c648f9fbfa59..0ab4ce86eda7 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2931,6 +2931,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
 	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6341_serdes_get_lane,
+	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3178,6 +3179,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
 	.vtu_getnext = mv88e6352_g1_vtu_getnext,
 	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 	.serdes_power = mv88e6352_serdes_power,
+	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
 	.serdes_irq_free = mv88e6352_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3261,6 +3263,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
 	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6390_serdes_get_lane,
+	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3308,6 +3311,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
 	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6390x_serdes_get_lane,
+	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3355,6 +3359,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
 	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6390_serdes_get_lane,
+	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.avb_ops = &mv88e6390_avb_ops,
@@ -3403,6 +3408,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
 	.vtu_getnext = mv88e6352_g1_vtu_getnext,
 	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 	.serdes_power = mv88e6352_serdes_power,
+	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
 	.serdes_irq_free = mv88e6352_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3492,6 +3498,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
 	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6390_serdes_get_lane,
+	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3629,6 +3636,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
 	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6341_serdes_get_lane,
+	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3760,6 +3768,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
 	.vtu_getnext = mv88e6352_g1_vtu_getnext,
 	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 	.serdes_power = mv88e6352_serdes_power,
+	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6352_serdes_irq_setup,
 	.serdes_irq_free = mv88e6352_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3814,6 +3823,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
 	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6390_serdes_get_lane,
+	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
@@ -3865,6 +3875,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
 	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
 	.serdes_power = mv88e6390_serdes_power,
 	.serdes_get_lane = mv88e6390x_serdes_get_lane,
+	.serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
 	.serdes_irq_setup = mv88e6390_serdes_irq_setup,
 	.serdes_irq_free = mv88e6390_serdes_irq_free,
 	.gpio_ops = &mv88e6352_gpio_ops,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 2016f51c868b..b116bd7f6109 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -447,6 +447,8 @@ struct mv88e6xxx_ops {
 	int (*serdes_get_lane)(struct mv88e6xxx_chip *chip, int port, u8 *lane);
 
 	/* SERDES interrupt handling */
+	unsigned int (*serdes_irq_mapping)(struct mv88e6xxx_chip *chip,
+					   int port);
 	int (*serdes_irq_setup)(struct mv88e6xxx_chip *chip, int port);
 	void (*serdes_irq_free)(struct mv88e6xxx_chip *chip, int port);
 
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index f65652e6edec..4fb1dca64ef1 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -240,18 +240,25 @@ static int mv88e6352_serdes_irq_disable(struct mv88e6xxx_chip *chip)
 	return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, 0);
 }
 
+unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
+{
+	return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ);
+}
+
 int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
 {
+	unsigned int irq;
 	int err;
 
 	if (!mv88e6352_port_has_serdes(chip, port))
 		return 0;
 
-	chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain,
-							MV88E6352_SERDES_IRQ);
-	if (!chip->ports[port].serdes_irq)
+	irq = mv88e6xxx_serdes_irq_mapping(chip, port);
+	if (!irq)
 		return 0;
 
+	chip->ports[port].serdes_irq = irq;
+
 	/* Requesting the IRQ will trigger irq callbacks. So we cannot
 	 * hold the reg_lock.
 	 */
@@ -673,8 +680,14 @@ static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
 	return ret;
 }
 
+unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
+{
+	return irq_find_mapping(chip->g2_irq.domain, port);
+}
+
 int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
 {
+	unsigned int irq;
 	int err;
 	u8 lane;
 
@@ -685,11 +698,12 @@ int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
 		return err;
 	}
 
-	chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain,
-							port);
-	if (!chip->ports[port].serdes_irq)
+	irq = mv88e6xxx_serdes_irq_mapping(chip, port);
+	if (!irq)
 		return 0;
 
+	chip->ports[port].serdes_irq = irq;
+
 	/* Requesting the IRQ will trigger irq callbacks. So we cannot
 	 * hold the reg_lock.
 	 */
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index c2e6fc3ddf8b..cb8d287c9388 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -90,6 +90,10 @@ static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
 int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane);
 int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane);
 int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane);
+unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
+					  int port);
+unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
+					  int port);
 int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
 int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port);
@@ -106,5 +110,13 @@ int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
 int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port);
 void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port);
 
+static inline unsigned int
+mv88e6xxx_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
+{
+	if (!chip->info->ops->serdes_irq_mapping)
+		return 0;
+
+	return chip->info->ops->serdes_irq_mapping(chip, port);
+}
 
 #endif
-- 
2.23.0


^ permalink raw reply related

* [PATCH net-next 02/10] net: dsa: mv88e6xxx: fix SERDES IRQ mapping
From: Vivien Didelot @ 2019-08-31 20:18 UTC (permalink / raw)
  To: netdev; +Cc: davem, Marek Behún, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190831201836.19957-1-vivien.didelot@gmail.com>

The current mv88e6xxx SERDES code checks for negative error code from
irq_find_mapping, while this function returns an unsigned integer. This
patch removes this dead code and simply returns 0 is no IRQ is found.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
 drivers/net/dsa/mv88e6xxx/chip.h   |  2 +-
 drivers/net/dsa/mv88e6xxx/serdes.c | 14 ++++----------
 2 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 421e8b84bec3..2016f51c868b 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -199,7 +199,7 @@ struct mv88e6xxx_port {
 	u64 vtu_member_violation;
 	u64 vtu_miss_violation;
 	u8 cmode;
-	int serdes_irq;
+	unsigned int serdes_irq;
 };
 
 struct mv88e6xxx_chip {
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 7eb7ed68c91d..f65652e6edec 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -249,11 +249,8 @@ int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
 
 	chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain,
 							MV88E6352_SERDES_IRQ);
-	if (chip->ports[port].serdes_irq < 0) {
-		dev_err(chip->dev, "Unable to map SERDES irq: %d\n",
-			chip->ports[port].serdes_irq);
-		return chip->ports[port].serdes_irq;
-	}
+	if (!chip->ports[port].serdes_irq)
+		return 0;
 
 	/* Requesting the IRQ will trigger irq callbacks. So we cannot
 	 * hold the reg_lock.
@@ -690,11 +687,8 @@ int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
 
 	chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain,
 							port);
-	if (chip->ports[port].serdes_irq < 0) {
-		dev_err(chip->dev, "Unable to map SERDES irq: %d\n",
-			chip->ports[port].serdes_irq);
-		return chip->ports[port].serdes_irq;
-	}
+	if (!chip->ports[port].serdes_irq)
+		return 0;
 
 	/* Requesting the IRQ will trigger irq callbacks. So we cannot
 	 * hold the reg_lock.
-- 
2.23.0


^ permalink raw reply related

* [PATCH net-next 01/10] net: dsa: mv88e6xxx: check errors in mv88e6352_serdes_irq_link
From: Vivien Didelot @ 2019-08-31 20:18 UTC (permalink / raw)
  To: netdev; +Cc: davem, Marek Behún, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190831201836.19957-1-vivien.didelot@gmail.com>

The mv88e6352_serdes_irq_link helper is not checking for any error that
may occur during hardware accesses. Worst, the "up" boolean is set from
the potentially unused "status" variable, if read operations failed.

As done in mv88e6390_serdes_irq_link_sgmii, return right away and do
not call dsa_port_phylink_mac_change if an error occurred.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
 drivers/net/dsa/mv88e6xxx/serdes.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 38c0da2492c0..7eb7ed68c91d 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -186,14 +186,19 @@ static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
 	struct dsa_switch *ds = chip->ds;
 	u16 status;
 	bool up;
+	int err;
 
-	mv88e6352_serdes_read(chip, MII_BMSR, &status);
+	err = mv88e6352_serdes_read(chip, MII_BMSR, &status);
+	if (err)
+		return;
 
 	/* Status must be read twice in order to give the current link
 	 * status. Otherwise the change in link status since the last
 	 * read of the register is returned.
 	 */
-	mv88e6352_serdes_read(chip, MII_BMSR, &status);
+	err = mv88e6352_serdes_read(chip, MII_BMSR, &status);
+	if (err)
+		return;
 
 	up = status & BMSR_LSTATUS;
 
-- 
2.23.0


^ permalink raw reply related

* [PATCH net-next 00/10] net: dsa: mv88e6xxx: centralize SERDES IRQ handling
From: Vivien Didelot @ 2019-08-31 20:18 UTC (permalink / raw)
  To: netdev; +Cc: davem, Marek Behún, f.fainelli, andrew, Vivien Didelot

Following Marek's work on the abstraction of the SERDES lanes mapping, this
series trades the .serdes_irq_setup and .serdes_irq_free callbacks for new
.serdes_irq_mapping, .serdes_irq_enable and .serdes_irq_status operations.

This has the benefit to limit the various SERDES implementations to simple
register accesses only; centralize the IRQ handling and mutex locking logic;
as well as reducing boilerplate in the driver.

Vivien Didelot (10):
  net: dsa: mv88e6xxx: check errors in mv88e6352_serdes_irq_link
  net: dsa: mv88e6xxx: fix SERDES IRQ mapping
  net: dsa: mv88e6xxx: introduce .serdes_irq_mapping
  net: dsa: mv88e6xxx: simplify .serdes_get_lane
  net: dsa: mv88e6xxx: implement mv88e6352_serdes_get_lane
  net: dsa: mv88e6xxx: merge mv88e6352_serdes_power_set
  net: dsa: mv88e6xxx: pass lane to .serdes_power
  net: dsa: mv88e6xxx: introduce .serdes_irq_enable
  net: dsa: mv88e6xxx: introduce .serdes_irq_status
  net: dsa: mv88e6xxx: centralize SERDES IRQ handling

 drivers/net/dsa/mv88e6xxx/chip.c   | 141 ++++++++---
 drivers/net/dsa/mv88e6xxx/chip.h   |  15 +-
 drivers/net/dsa/mv88e6xxx/port.c   |  21 +-
 drivers/net/dsa/mv88e6xxx/serdes.c | 382 ++++++++---------------------
 drivers/net/dsa/mv88e6xxx/serdes.h | 107 ++++++--
 5 files changed, 315 insertions(+), 351 deletions(-)

-- 
2.23.0


^ permalink raw reply

* Re: [PATCH 0/2] pull request for net: batman-adv 2019-08-30
From: David Miller @ 2019-08-31 20:18 UTC (permalink / raw)
  To: sw; +Cc: netdev, b.a.t.m.a.n
In-Reply-To: <20190830072502.16929-1-sw@simonwunderlich.de>

From: Simon Wunderlich <sw@simonwunderlich.de>
Date: Fri, 30 Aug 2019 09:25:00 +0200

> here is another small batman-adv pull request for net.
> 
> Please pull or let me know of any problem!

Pulled, thanks Simon.

^ permalink raw reply

* Re: [PATCH 0/1] pull request for net-next: batman-adv 2019-08-30
From: David Miller @ 2019-08-31 20:15 UTC (permalink / raw)
  To: sw; +Cc: netdev, b.a.t.m.a.n
In-Reply-To: <20190830072736.18535-1-sw@simonwunderlich.de>

From: Simon Wunderlich <sw@simonwunderlich.de>
Date: Fri, 30 Aug 2019 09:27:35 +0200

> here is a small maintenance pull request of batman-adv to go into net-next.
> 
> Please pull or let me know of any problem!

Pulled, but generally speaking MAINTAINERS updates are always legitimate
for 'net'.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox