* RE: linux-next: Fixes tag needs some work in the net tree
From: Voon, Weifeng @ 2019-06-24 1:51 UTC (permalink / raw)
To: Stephen Rothwell, David Miller, Networking
Cc: Linux Next Mailing List, Linux Kernel Mailing List,
Ong, Boon Leong
In-Reply-To: <20190624074716.44b749d3@canb.auug.org.au>
> Hi all,
>
> In commit
>
> d0bb82fd6018 ("net: stmmac: set IC bit when transmitting frames with
> HW timestamp")
>
> Fixes tag
>
> Fixes: f748be531d70 ("net: stmmac: Rework coalesce timer and fix
> multi-queue races")
>
> has these problem(s):
>
> - Subject does not match target commit subject
> Just use
> git log -1 --format='Fixes: %h ("%s")'
>
> Fixes: f748be531d70 ("stmmac: support new GMAC4")
>
> or did you mean
>
> Fixes: 8fce33317023 ("net: stmmac: Rework coalesce timer and fix multi-
> queue races")
>
Sorry for the confusion, what I meant is:
Fixes: 8fce33317023 ("net: stmmac: Rework coalesce timer and fix multi-
queue races")
Regards,
Weifeng
> --
> Cheers,
> Stephen Rothwell
^ permalink raw reply
* Re: [EXT] [PATCH] bnx2x: Prevent ptp_task to be rescheduled indefinitely
From: Guilherme Piccoli @ 2019-06-24 0:50 UTC (permalink / raw)
To: Sudarsana Reddy Kalluru
Cc: GR-everest-linux-l2, netdev@vger.kernel.org, Ariel Elior,
jay.vosburgh@canonical.com
In-Reply-To: <MN2PR18MB2528C51C0A23D9FA7744D883D3E10@MN2PR18MB2528.namprd18.prod.outlook.com>
On Sun, Jun 23, 2019 at 2:13 AM Sudarsana Reddy Kalluru
<skalluru@marvell.com> wrote:
>
> Thanks for uncovering this issue, and the fix.
> With the proposed fix, if HW latches the timestamp after 3 iterations then it would lead to erroneous PTP functionality. When driver receives the next PTP packet, driver sees that timestamp is available in the register and would assign this value (which corresponds to last/skipped ptp packet) to the PTP packet. In general, FW takes around 1ms to 100ms to perform the timestamp and may take more. Hence the promising solution for this issue would be to wait for timestamp for particular period of time. If Tx timestamp is not available for a pre-determined max period, then declare it as an error scenario and terminate the thread.
>
> Just for the reference, similar fix was added for Marvell qede driver recently. Patch details are,
> 9adebac37e7d: (qede: Handle infinite driver spinning for Tx timestamp.)
> https://www.spinics.net/lists/netdev/msg572838.html
>
Thanks a lot for the quick review and good suggestion Sudarsana!
I'll rework the fix based on your reference, and resubmit.
Cheers,
Guilherme
^ permalink raw reply
* Re: [PATCH v2 0/3] fix bugs when enable route_localnet
From: Zhiqiang Liu @ 2019-06-24 1:19 UTC (permalink / raw)
To: David Miller
Cc: luoshijie1, tgraf, dsahern, netdev, wangxiaogang3, mingfangsen,
zhoukang7
In-Reply-To: <20190622.084611.1808368522428755652.davem@davemloft.net>
> From: Zhiqiang Liu <liuzhiqiang26@huawei.com>
> Date: Sat, 22 Jun 2019 16:41:49 +0800
>
>> Friendly ping ...
>
> I'm not applying this patch series without someone reviewing it.
>
Of course, all patches should be reviewd before deciding whether to apply.
In v2, we add a couple of test for enabling route_localnet in selftests suggested
by David Ahern.
In additon, another similar bugfix is added for arp_ignore = 3.
We would appreciate David Ahern or someone could help review the patch series.
^ permalink raw reply
* Re: 6c409a3aee: kernel_selftests.bpf.test_verifier.fail
From: Rong Chen @ 2019-06-24 0:43 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Andreas Steinmetz, Daniel Borkmann, Andrii Nakryiko, Edward Cree,
bpf, Network Development, LKP
In-Reply-To: <CAADnVQ+frnYN6E5zyrNvbnhQ_XgvrEEtghiS7DOKoe6o_ErYRw@mail.gmail.com>
On 6/21/19 11:52 PM, Alexei Starovoitov wrote:
> On Fri, Jun 21, 2019 at 1:36 AM kernel test robot <rong.a.chen@intel.com> wrote:
>> # #340/p direct packet access: test22 (x += pkt_ptr, 3) OK
>> # #341/p direct packet access: test23 (x += pkt_ptr, 4) FAIL
>> # Unexpected success to load!
>> # verification time 17 usec
>> # stack depth 8
>> # processed 18 insns (limit 1000000) max_states_per_insn 0 total_states 1 peak_states 1 mark_read 0
>> # #342/p direct packet access: test24 (x += pkt_ptr, 5) OK
>> # #343/p direct packet access: test25 (marking on <, good access) OK
> ..
>> # #673/p meta access, test9 OK
>> # #674/p meta access, test10 FAIL
>> # Unexpected success to load!
>> # verification time 29 usec
>> # stack depth 8
>> # processed 19 insns (limit 1000000) max_states_per_insn 0 total_states 1 peak_states 1 mark_read 0
>> # #675/p meta access, test11 OK
> Hi Rong,
>
> the patch quoted is not in bpf-next/net-next.
> This patch is work-in-progress that I posted to mailing list
> and pushed into my own git branch on kernel.org.
> It's awesome that build bot does this early testing.
> I really like it.
> Would be great if the bot can add a tag to email subject that it's testing
> this not yet merged patch.
>
> Right now since the email says
> commit: 6c409a3aee945e50c6dd4109689f52
> it felt that this is real commit and my initial reaction
> was that 'ohh something is broken in the merge code'
> which wasn't the case :)
Hi Alexei,
Thanks for the advice, we'll improve the email subject.
Best Regards,
Rong Chen
^ permalink raw reply
* [PATCH v3 net] af_packet: Block execution of tasks waiting for transmit to complete in AF_PACKET
From: Neil Horman @ 2019-06-24 0:46 UTC (permalink / raw)
To: netdev; +Cc: Neil Horman, Matteo Croce, David S. Miller, Willem de Bruijn
In-Reply-To: <20190619202533.4856-1-nhorman@tuxdriver.com>
When an application is run that:
a) Sets its scheduler to be SCHED_FIFO
and
b) Opens a memory mapped AF_PACKET socket, and sends frames with the
MSG_DONTWAIT flag cleared, its possible for the application to hang
forever in the kernel. This occurs because when waiting, the code in
tpacket_snd calls schedule, which under normal circumstances allows
other tasks to run, including ksoftirqd, which in some cases is
responsible for freeing the transmitted skb (which in AF_PACKET calls a
destructor that flips the status bit of the transmitted frame back to
available, allowing the transmitting task to complete).
However, when the calling application is SCHED_FIFO, its priority is
such that the schedule call immediately places the task back on the cpu,
preventing ksoftirqd from freeing the skb, which in turn prevents the
transmitting task from detecting that the transmission is complete.
We can fix this by converting the schedule call to a completion
mechanism. By using a completion queue, we force the calling task, when
it detects there are no more frames to send, to schedule itself off the
cpu until such time as the last transmitted skb is freed, allowing
forward progress to be made.
Tested by myself and the reporter, with good results
Appies to the net tree
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Reported-by: Matteo Croce <mcroce@redhat.com>
CC: "David S. Miller" <davem@davemloft.net>
CC: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Change Notes:
V1->V2:
Enhance the sleep logic to support being interruptible and
allowing for honoring to SK_SNDTIMEO (Willem de Bruijn)
V2->V3:
Rearrage the point at which we wait for the completion queue, to
avoid needing to check for ph/skb being null at the end of the loop.
Also move the complete call to the skb destructor to avoid needing to
modify __packet_set_status. Also gate calling complete on
packet_read_pending returning zero to avoid multiple calls to complete.
(Willem de Bruijn)
Move timeo computation within loop, to re-fetch the socket
timeout since we also use the timeo variable to record the return code
from the wait_for_complete call (Neil Horman)
---
net/packet/af_packet.c | 59 +++++++++++++++++++++++++++++++++++++-----
net/packet/internal.h | 2 ++
2 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index a29d66da7394..5c48bb7a4fa5 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -380,7 +380,6 @@ static void __packet_set_status(struct packet_sock *po, void *frame, int status)
WARN(1, "TPACKET version not supported.\n");
BUG();
}
-
smp_wmb();
}
@@ -1148,6 +1147,14 @@ static void *packet_previous_frame(struct packet_sock *po,
return packet_lookup_frame(po, rb, previous, status);
}
+static void *packet_next_frame(struct packet_sock *po,
+ struct packet_ring_buffer *rb,
+ int status)
+{
+ unsigned int next = rb->head != rb->frame_max ? rb->head+1 : 0;
+ return packet_lookup_frame(po, rb, next, status);
+}
+
static void packet_increment_head(struct packet_ring_buffer *buff)
{
buff->head = buff->head != buff->frame_max ? buff->head+1 : 0;
@@ -2401,6 +2408,9 @@ static void tpacket_destruct_skb(struct sk_buff *skb)
ts = __packet_set_timestamp(po, ph, skb);
__packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts);
+
+ if (po->wait_on_complete && !packet_read_pending(&po->tx_ring))
+ complete(&po->skb_completion);
}
sock_wfree(skb);
@@ -2600,9 +2610,11 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
int len_sum = 0;
int status = TP_STATUS_AVAILABLE;
int hlen, tlen, copylen = 0;
+ long timeo = 0;
mutex_lock(&po->pg_vec_lock);
+
if (likely(saddr == NULL)) {
dev = packet_cached_dev_get(po);
proto = po->num;
@@ -2647,16 +2659,16 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
size_max = dev->mtu + reserve + VLAN_HLEN;
do {
+
ph = packet_current_frame(po, &po->tx_ring,
TP_STATUS_SEND_REQUEST);
- if (unlikely(ph == NULL)) {
- if (need_wait && need_resched())
- schedule();
- continue;
- }
+
+ if (unlikely(ph == NULL))
+ break;
skb = NULL;
tp_len = tpacket_parse_header(po, ph, size_max, &data);
+
if (tp_len < 0)
goto tpacket_error;
@@ -2720,6 +2732,21 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
skb->destructor = tpacket_destruct_skb;
__packet_set_status(po, ph, TP_STATUS_SENDING);
+
+ /*
+ * If we need to wait and we've sent the last frame pending
+ * transmission in the mmaped buffer, flag that we need to wait
+ * on those frames to get freed via tpacket_destruct_skb. This
+ * flag indicates that tpacket_destruct_skb should call complete
+ * when the packet_pending count reaches zero, and that we need
+ * to call wait_on_complete_interruptible_timeout below, to make
+ * sure we pick up the result of that completion
+ */
+ if (need_wait && !packet_next_frame(po, &po->tx_ring, TP_STATUS_SEND_REQUEST)) {
+ po->wait_on_complete = 1;
+ timeo = sock_sndtimeo(&po->sk, msg->msg_flags & MSG_DONTWAIT);
+ }
+
packet_inc_pending(&po->tx_ring);
status = TP_STATUS_SEND_REQUEST;
@@ -2728,6 +2755,11 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
err = net_xmit_errno(err);
if (err && __packet_get_status(po, ph) ==
TP_STATUS_AVAILABLE) {
+ /* re-init completion queue to avoid subsequent fallthrough
+ * on a future thread calling wait_on_complete_interruptible_timeout
+ */
+ po->wait_on_complete = 0;
+ init_completion(&po->skb_completion);
/* skb was destructed already */
skb = NULL;
goto out_status;
@@ -2740,6 +2772,20 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
}
packet_increment_head(&po->tx_ring);
len_sum += tp_len;
+
+ if (po->wait_on_complete) {
+ timeo = wait_for_completion_interruptible_timeout(&po->skb_completion, timeo);
+ po->wait_on_complete = 0;
+ if (!timeo) {
+ /* We timed out, break out and notify userspace */
+ err = -ETIMEDOUT;
+ goto out_status;
+ } else if (timeo == -ERESTARTSYS) {
+ err = -ERESTARTSYS;
+ goto out_status;
+ }
+ }
+
} while (likely((ph != NULL) ||
/* Note: packet_read_pending() might be slow if we have
* to call it as it's per_cpu variable, but in fast-path
@@ -3207,6 +3253,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
sock_init_data(sock, sk);
po = pkt_sk(sk);
+ init_completion(&po->skb_completion);
sk->sk_family = PF_PACKET;
po->num = proto;
po->xmit = dev_queue_xmit;
diff --git a/net/packet/internal.h b/net/packet/internal.h
index 3bb7c5fb3bff..bbb4be2c18e7 100644
--- a/net/packet/internal.h
+++ b/net/packet/internal.h
@@ -128,6 +128,8 @@ struct packet_sock {
unsigned int tp_hdrlen;
unsigned int tp_reserve;
unsigned int tp_tstamp;
+ struct completion skb_completion;
+ unsigned int wait_on_complete;
struct net_device __rcu *cached_dev;
int (*xmit)(struct sk_buff *skb);
struct packet_type prot_hook ____cacheline_aligned_in_smp;
--
2.20.1
^ permalink raw reply related
* RE: [iproute2-next v5] tipc: support interface name when activating UDP bearer
From: Hoang Le @ 2019-06-24 2:15 UTC (permalink / raw)
To: 'David Ahern', jon.maloy, maloy, ying.xue, netdev,
tipc-discussion
In-Reply-To: <d4bef444-f009-5415-f27d-8cfde945ddab@gmail.com>
Thanks David. I will update code change as your comments.
For the item:
> + /* remove from cache */
> + ll_drop_by_index(ifr.ifr_ifindex);
why the call to ll_drop_by_index? doing so means that ifindex is looked
up again.
[Hoang]
> + ifr.ifr_ifindex = ll_name_to_index(ifr.ifr_name);
This function stored an entry ll_cache in hash map table. We have to call this function to prevent memory leaked.
Regards,
Hoang
-----Original Message-----
From: David Ahern <dsahern@gmail.com>
Sent: Saturday, June 22, 2019 5:50 AM
To: Hoang Le <hoang.h.le@dektech.com.au>; dsahern@gmail.com; jon.maloy@ericsson.com; maloy@donjonn.com; ying.xue@windriver.com; netdev@vger.kernel.org; tipc-discussion@lists.sourceforge.net
Subject: Re: [iproute2-next v5] tipc: support interface name when activating UDP bearer
On 6/13/19 2:07 AM, Hoang Le wrote:
> @@ -119,6 +121,74 @@ static int generate_multicast(short af, char *buf, int bufsize)
> return 0;
> }
>
> +static struct ifreq ifr = {};
you don't need to initialize globals, but you could pass a a struct as
the arg to the filter here which is both the addr buffer and the ifindex
of interest.
> +static int nl_dump_addr_filter(struct nlmsghdr *nlh, void *arg)
> +{
> + struct ifaddrmsg *ifa = NLMSG_DATA(nlh);
> + char *r_addr = (char *)arg;
> + int len = nlh->nlmsg_len;
> + struct rtattr *addr_attr;
> +
> + if (ifr.ifr_ifindex != ifa->ifa_index)
> + return 0;
> +
> + if (strlen(r_addr) > 0)
> + return 1;
> +
> + addr_attr = parse_rtattr_one(IFA_ADDRESS, IFA_RTA(ifa),
> + len - NLMSG_LENGTH(sizeof(*ifa)));
> + if (!addr_attr)
> + return 0;
> +
> + if (ifa->ifa_family == AF_INET) {
> + struct sockaddr_in ip4addr;
> + memcpy(&ip4addr.sin_addr, RTA_DATA(addr_attr),
> + sizeof(struct in_addr));
> + if (inet_ntop(AF_INET, &ip4addr.sin_addr, r_addr,
> + INET_ADDRSTRLEN) == NULL)
> + return 0;
> + } else if (ifa->ifa_family == AF_INET6) {
> + struct sockaddr_in6 ip6addr;
> + memcpy(&ip6addr.sin6_addr, RTA_DATA(addr_attr),
> + sizeof(struct in6_addr));
> + if (inet_ntop(AF_INET6, &ip6addr.sin6_addr, r_addr,
> + INET6_ADDRSTRLEN) == NULL)
> + return 0;
> + }
> + return 1;
> +}
> +
> +static int cmd_bearer_validate_and_get_addr(const char *name, char *r_addr)
> +{
> + struct rtnl_handle rth ={ .fd = -1 };
space between '={'
> +
> + memset(&ifr, 0, sizeof(ifr));
> + if (!name || !r_addr || get_ifname(ifr.ifr_name, name))
> + return 0;
> +
> + ifr.ifr_ifindex = ll_name_to_index(ifr.ifr_name);
> + if (!ifr.ifr_ifindex)
> + return 0;
> +
> + /* remove from cache */
> + ll_drop_by_index(ifr.ifr_ifindex);
why the call to ll_drop_by_index? doing so means that ifindex is looked
up again.
> +
> + if (rtnl_open(&rth, 0) < 0)
> + return 0;
> +
> + if (rtnl_addrdump_req(&rth, AF_UNSPEC, 0) < 0) {
If you pass a filter here to set ifa_index, this command on newer
kernels will be much more efficient. See ipaddr_dump_filter.
> + rtnl_close(&rth);
> + return 0;
> + }
> +
> + if (rtnl_dump_filter(&rth, nl_dump_addr_filter, r_addr) < 0) {
> + rtnl_close(&rth);
> + return 0;
> + }
> + rtnl_close(&rth);
> + return 1;
> +}
it would better to have 1 exit with the rtnl_close and return rc based
on above.
^ permalink raw reply
* Re: [PATCH] net: ethernet: ti: cpsw: Fix suspend/resume break
From: Ivan Khoronzhuk @ 2019-06-23 23:31 UTC (permalink / raw)
To: Keerthy
Cc: davem, andrew, ilias.apalodimas, linux-kernel, netdev, linux-omap,
t-kristo, grygorii.strashko, nsekhar
In-Reply-To: <20190622103140.22902-1-j-keerthy@ti.com>
On Sat, Jun 22, 2019 at 04:01:40PM +0530, Keerthy wrote:
Hi Keerty,
>Commit bfe59032bd6127ee190edb30be9381a01765b958 ("net: ethernet:
>ti: cpsw: use cpsw as drv data")changes
>the driver data to struct cpsw_common *cpsw. This is done
>only in probe/remove but the suspend/resume functions are
>still left with struct net_device *ndev. Hence fix both
>suspend & resume also to fetch the updated driver data.
>
>Fixes: bfe59032bd6127ee1 ("net: ethernet: ti: cpsw: use cpsw as drv data")
>Signed-off-by: Keerthy <j-keerthy@ti.com>
>---
> drivers/net/ethernet/ti/cpsw.c | 36 +++++++++++-----------------------
> 1 file changed, 11 insertions(+), 25 deletions(-)
>
>diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
>index 7bdd287074fc..2aeaad15e20e 100644
>--- a/drivers/net/ethernet/ti/cpsw.c
>+++ b/drivers/net/ethernet/ti/cpsw.c
>@@ -2590,20 +2590,12 @@ static int cpsw_remove(struct platform_device *pdev)
> #ifdef CONFIG_PM_SLEEP
> static int cpsw_suspend(struct device *dev)
> {
>- struct net_device *ndev = dev_get_drvdata(dev);
>- struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
>-
>- if (cpsw->data.dual_emac) {
>- int i;
>+ struct cpsw_common *cpsw = dev_get_drvdata(dev);
>+ int i;
>
>- for (i = 0; i < cpsw->data.slaves; i++) {
>- if (netif_running(cpsw->slaves[i].ndev))
>- cpsw_ndo_stop(cpsw->slaves[i].ndev);
>- }
>- } else {
>- if (netif_running(ndev))
>- cpsw_ndo_stop(ndev);
>- }
>+ for (i = 0; i < cpsw->data.slaves; i++)
>+ if (netif_running(cpsw->slaves[i].ndev))
Seems I've missed to add this, but in your fix potential issue in switch mode.
ndev is not necessarily present for slave, you need to check on ndev != null
before using it, if you still remove cpsw->data.dual_emac ofc.
Thanks.
>+ cpsw_ndo_stop(cpsw->slaves[i].ndev);
>
> /* Select sleep pin state */
> pinctrl_pm_select_sleep_state(dev);
>@@ -2613,25 +2605,19 @@ static int cpsw_suspend(struct device *dev)
>
> static int cpsw_resume(struct device *dev)
> {
>- struct net_device *ndev = dev_get_drvdata(dev);
>- struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
>+ struct cpsw_common *cpsw = dev_get_drvdata(dev);
>+ int i;
>
> /* Select default pin state */
> pinctrl_pm_select_default_state(dev);
>
> /* shut up ASSERT_RTNL() warning in netif_set_real_num_tx/rx_queues */
> rtnl_lock();
>- if (cpsw->data.dual_emac) {
>- int i;
>
>- for (i = 0; i < cpsw->data.slaves; i++) {
>- if (netif_running(cpsw->slaves[i].ndev))
>- cpsw_ndo_open(cpsw->slaves[i].ndev);
>- }
>- } else {
>- if (netif_running(ndev))
>- cpsw_ndo_open(ndev);
>- }
>+ for (i = 0; i < cpsw->data.slaves; i++)
>+ if (netif_running(cpsw->slaves[i].ndev))
>+ cpsw_ndo_open(cpsw->slaves[i].ndev);
>+
same here
> rtnl_unlock();
>
> return 0;
>--
>2.17.1
>
--
Regards,
Ivan Khoronzhuk
^ permalink raw reply
* Re: [PATCH net] vxlan: do not destroy fdb if register_netdevice() is failed
From: Taehee Yoo @ 2019-06-24 2:18 UTC (permalink / raw)
To: David Miller; +Cc: Netdev
In-Reply-To: <20190623.110737.1466794521532071350.davem@davemloft.net>
On Mon, 24 Jun 2019 at 03:07, David Miller <davem@davemloft.net> wrote:
>
Hi David,
Thank you for the review!
> From: Taehee Yoo <ap420073@gmail.com>
> Date: Thu, 20 Jun 2019 20:51:08 +0900
>
> > __vxlan_dev_create() destroys FDB using specific pointer which indicates
> > a fdb when error occurs.
> > But that pointer should not be used when register_netdevice() fails because
> > register_netdevice() internally destroys fdb when error occurs.
> >
> > In order to avoid un-registered dev's notification, fdb destroying routine
> > checks dev's register status before notification.
>
> Simply pass do_notify as false in this failure code path of __vxlan_dev_create(),
> thank you.
Failure path of __vxlan_dev_create() can't handle do_notify in that case
because if register_netdevice() fails it internally calls
->ndo_uninit() which is
vxlan_uninit().
vxlan_uninit() internally calls vxlan_fdb_delete_default() and it callls
vxlan_fdb_destroy().
do_notify of vxlan_fdb_destroy() in vxlan_fdb_delete_default() is always true.
So, failure path of __vxlan_dev_create() doesn't have any opportunity to
handle do_notify.
Thank you!
^ permalink raw reply
* linux-next: Fixes tag needs some work in the net tree
From: Stephen Rothwell @ 2019-06-23 21:47 UTC (permalink / raw)
To: David Miller, Networking
Cc: Linux Next Mailing List, Linux Kernel Mailing List, Roland Hii,
Ong Boon Leong, Voon Weifeng
[-- Attachment #1: Type: text/plain, Size: 540 bytes --]
Hi all,
In commit
d0bb82fd6018 ("net: stmmac: set IC bit when transmitting frames with HW timestamp")
Fixes tag
Fixes: f748be531d70 ("net: stmmac: Rework coalesce timer and fix multi-queue races")
has these problem(s):
- Subject does not match target commit subject
Just use
git log -1 --format='Fixes: %h ("%s")'
Fixes: f748be531d70 ("stmmac: support new GMAC4")
or did you mean
Fixes: 8fce33317023 ("net: stmmac: Rework coalesce timer and fix multi-queue races")
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH next 0/3] blackhole device to invalidate dst
From: Mahesh Bandewar (महेश बंडेवार) @ 2019-06-23 23:01 UTC (permalink / raw)
To: David Ahern
Cc: Netdev, Eric Dumazet, David Miller, Michael Chan, Daniel Axtens,
Mahesh Bandewar
In-Reply-To: <5441f3f1-0672-fbb1-e875-7f8ceb68d719@gmail.com>
On Sat, Jun 22, 2019 at 8:35 AM David Ahern <dsahern@gmail.com> wrote:
>
> On 6/21/19 6:45 PM, Mahesh Bandewar wrote:
> > When we invalidate dst or mark it "dead", we assign 'lo' to
> > dst->dev. First of all this assignment is racy and more over,
> > it has MTU implications.
> >
> > The standard dev MTU is 1500 while the Loopback MTU is 64k. TCP
> > code when dereferencing the dst don't check if the dst is valid
> > or not. TCP when dereferencing a dead-dst while negotiating a
> > new connection, may use dst device which is 'lo' instead of
> > using the correct device. Consider the following scenario:
> >
>
> Why doesn't the TCP code (or any code) check if a cached dst is valid?
> That's the whole point of marking it dead - to tell users not to rely on
> it.
Well, I'm not an expert in TCP, but I could guess. Eric, please help
me being honest with my guess.
The code that marks it dead (control path) and the code that need to
check the validity (data-path) need to have some sort of
synchronization and that could be costly in the data-path. Also what
is the worst case scenario? ... that packet is going to get dropped
since the under-lying device or route has issues (minus this corner
case). May be that was the reason.
As I mentioned in the log, we could remove the racy-ness with
barriers or locks but then that would be an additional cost in the
data-path. having a dummy/backhole dev is the cheapest solution with
no changes to the data-path.
^ permalink raw reply
* Re: [PATCH V3 01/10] net: dsa: microchip: Remove ksz_{read,write}24()
From: Andrew Lunn @ 2019-06-24 3:11 UTC (permalink / raw)
To: Marek Vasut; +Cc: netdev, Florian Fainelli, Tristram Ha, Woojung Huh
In-Reply-To: <20190623223508.2713-2-marex@denx.de>
On Mon, Jun 24, 2019 at 12:34:59AM +0200, Marek Vasut wrote:
> These functions and callbacks are never used, remove them.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* Re: [PATCH V3 02/10] net: dsa: microchip: Remove ksz_{get,set}()
From: Andrew Lunn @ 2019-06-24 3:12 UTC (permalink / raw)
To: Marek Vasut; +Cc: netdev, Florian Fainelli, Tristram Ha, Woojung Huh
In-Reply-To: <20190623223508.2713-3-marex@denx.de>
On Mon, Jun 24, 2019 at 12:35:00AM +0200, Marek Vasut wrote:
> These functions and callbacks are never used, remove them.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* Re: linux-next: build failure after merge of the net-next tree
From: Stephen Rothwell @ 2019-06-24 3:12 UTC (permalink / raw)
To: David Miller, Networking
Cc: Linux Next Mailing List, Linux Kernel Mailing List, Yash Shah
In-Reply-To: <20190620191348.335b011d@canb.auug.org.au>
[-- Attachment #1: Type: text/plain, Size: 3521 bytes --]
Hi all,
On Thu, 20 Jun 2019 19:13:48 +1000 Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>
> After merging the net-next tree, today's linux-next build (powerpc
> allyesconfig) failed like this:
>
> drivers/net/ethernet/cadence/macb_main.c:48:16: error: field 'hw' has incomplete type
> struct clk_hw hw;
> ^~
> drivers/net/ethernet/cadence/macb_main.c:4003:21: error: variable 'fu540_c000_ops' has initializer but incomplete type
> static const struct clk_ops fu540_c000_ops = {
> ^~~~~~~
> drivers/net/ethernet/cadence/macb_main.c:4004:3: error: 'const struct clk_ops' has no member named 'recalc_rate'
> .recalc_rate = fu540_macb_tx_recalc_rate,
> ^~~~~~~~~~~
> drivers/net/ethernet/cadence/macb_main.c:4004:17: warning: excess elements in struct initializer
> .recalc_rate = fu540_macb_tx_recalc_rate,
> ^~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/net/ethernet/cadence/macb_main.c:4004:17: note: (near initialization for 'fu540_c000_ops')
> drivers/net/ethernet/cadence/macb_main.c:4005:3: error: 'const struct clk_ops' has no member named 'round_rate'
> .round_rate = fu540_macb_tx_round_rate,
> ^~~~~~~~~~
> drivers/net/ethernet/cadence/macb_main.c:4005:16: warning: excess elements in struct initializer
> .round_rate = fu540_macb_tx_round_rate,
> ^~~~~~~~~~~~~~~~~~~~~~~~
> drivers/net/ethernet/cadence/macb_main.c:4005:16: note: (near initialization for 'fu540_c000_ops')
> drivers/net/ethernet/cadence/macb_main.c:4006:3: error: 'const struct clk_ops' has no member named 'set_rate'
> .set_rate = fu540_macb_tx_set_rate,
> ^~~~~~~~
> drivers/net/ethernet/cadence/macb_main.c:4006:14: warning: excess elements in struct initializer
> .set_rate = fu540_macb_tx_set_rate,
> ^~~~~~~~~~~~~~~~~~~~~~
> drivers/net/ethernet/cadence/macb_main.c:4006:14: note: (near initialization for 'fu540_c000_ops')
> drivers/net/ethernet/cadence/macb_main.c: In function 'fu540_c000_clk_init':
> drivers/net/ethernet/cadence/macb_main.c:4013:23: error: storage size of 'init' isn't known
> struct clk_init_data init;
> ^~~~
> drivers/net/ethernet/cadence/macb_main.c:4032:12: error: implicit declaration of function 'clk_register'; did you mean 'sock_register'? [-Werror=implicit-function-declaration]
> *tx_clk = clk_register(NULL, &mgmt->hw);
> ^~~~~~~~~~~~
> sock_register
> drivers/net/ethernet/cadence/macb_main.c:4013:23: warning: unused variable 'init' [-Wunused-variable]
> struct clk_init_data init;
> ^~~~
> drivers/net/ethernet/cadence/macb_main.c: In function 'macb_probe':
> drivers/net/ethernet/cadence/macb_main.c:4366:2: error: implicit declaration of function 'clk_unregister'; did you mean 'sock_unregister'? [-Werror=implicit-function-declaration]
> clk_unregister(tx_clk);
> ^~~~~~~~~~~~~~
> sock_unregister
> drivers/net/ethernet/cadence/macb_main.c: At top level:
> drivers/net/ethernet/cadence/macb_main.c:4003:29: error: storage size of 'fu540_c000_ops' isn't known
> static const struct clk_ops fu540_c000_ops = {
> ^~~~~~~~~~~~~~
>
> Caused by commit
>
> c218ad559020 ("macb: Add support for SiFive FU540-C000")
>
> CONFIG_COMMON_CLK is not set for this build.
>
> I have reverted that commit for today.
I am still reverting that commit. Has this problem been fixed in some
subtle way?
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH V3 03/10] net: dsa: microchip: Inline ksz_spi.h
From: Andrew Lunn @ 2019-06-24 3:16 UTC (permalink / raw)
To: Marek Vasut; +Cc: netdev, Florian Fainelli, Tristram Ha, Woojung Huh
In-Reply-To: <20190623223508.2713-4-marex@denx.de>
On Mon, Jun 24, 2019 at 12:35:01AM +0200, Marek Vasut wrote:
> The functions in the header file are static, and the header file is
> included from single C file, just inline the code into the C file.
> The bonus is that it's easier to spot further content to clean up.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* Re: [PATCH V3 04/10] net: dsa: microchip: Move ksz_cfg and ksz_port_cfg to ksz9477.c
From: Andrew Lunn @ 2019-06-24 3:17 UTC (permalink / raw)
To: Marek Vasut; +Cc: netdev, Florian Fainelli, Tristram Ha, Woojung Huh
In-Reply-To: <20190623223508.2713-5-marex@denx.de>
On Mon, Jun 24, 2019 at 12:35:02AM +0200, Marek Vasut wrote:
> These functions are only used by the KSZ9477 code, move them from
> the header into that code. Note that these functions will be soon
> replaced by regmap equivalents.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* Re: [PATCH 06/15] ARM: imx: cleanup cppcheck shifting errors
From: Shawn Guo @ 2019-06-24 3:16 UTC (permalink / raw)
To: Phong Tran
Cc: mark.rutland, kstewart, songliubraving, andrew, peterz, nsekhar,
ast, jolsa, netdev, gerg, lorenzo.pieralisi, will,
linux-samsung-soc, daniel, festevam, gregory.clement, allison,
linux, krzk, haojian.zhuang, bgolaszewski, tony, mingo, linux-imx,
yhs, sebastian.hesselbarth, illusionist.neo, jason, liviu.dudau,
s.hauer, acme, lkundrak, robert.jarzmik, dmg, swinslow, namhyung,
tglx, linux-omap, alexander.sverdlin, linux-arm-kernel, info,
gregkh, linux-kernel, alexander.shishkin, hsweeten, kgene, kernel,
sudeep.holla, bpf, kafai, daniel
In-Reply-To: <20190623151313.970-7-tranmanphong@gmail.com>
On Sun, Jun 23, 2019 at 10:13:04PM +0700, Phong Tran wrote:
> [arch/arm/mach-imx/iomux-mx3.h:93]: (error) Shifting signed 32-bit value
> by 31 bits is undefined behaviour
>
> Signed-off-by: Phong Tran <tranmanphong@gmail.com>
Applied, thanks.
^ permalink raw reply
* [PATCH] netfilter: Fix remainder of pseudo-header protocol 0
From: zhe.he @ 2019-06-24 3:17 UTC (permalink / raw)
To: pablo, kadlec, fw, davem, netfilter-devel, coreteam, netdev,
linux-kernel, zhe.he
From: He Zhe <zhe.he@windriver.com>
Since v5.1-rc1, some types of packets do not get unreachable reply with the
following iptables setting. Fox example,
$ iptables -A INPUT -p icmp --icmp-type 8 -j REJECT
$ ping 127.0.0.1 -c 1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
— 127.0.0.1 ping statistics —
1 packets transmitted, 0 received, 100% packet loss, time 0ms
We should have got the following reply from command line, but we did not.
From 127.0.0.1 icmp_seq=1 Destination Port Unreachable
Yi Zhao reported it and narrowed it down to:
7fc38225363d ("netfilter: reject: skip csum verification for protocols that don't support it"),
This is because nf_ip_checksum still expects pseudo-header protocol type 0 for
packets that are of neither TCP or UDP, and thus ICMP packets are mistakenly
treated as TCP/UDP.
This patch corrects the conditions in nf_ip_checksum and all other places that
still call it with protocol 0.
Fixes: 7fc38225363d ("netfilter: reject: skip csum verification for protocols that don't support it")
Reported-by: Yi Zhao <yi.zhao@windriver.com>
Signed-off-by: He Zhe <zhe.he@windriver.com>
---
net/netfilter/nf_conntrack_proto_icmp.c | 2 +-
net/netfilter/nf_nat_proto.c | 2 +-
net/netfilter/utils.c | 5 +++--
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/net/netfilter/nf_conntrack_proto_icmp.c b/net/netfilter/nf_conntrack_proto_icmp.c
index a824367..dd53e2b 100644
--- a/net/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/netfilter/nf_conntrack_proto_icmp.c
@@ -218,7 +218,7 @@ int nf_conntrack_icmpv4_error(struct nf_conn *tmpl,
/* See ip_conntrack_proto_tcp.c */
if (state->net->ct.sysctl_checksum &&
state->hook == NF_INET_PRE_ROUTING &&
- nf_ip_checksum(skb, state->hook, dataoff, 0)) {
+ nf_ip_checksum(skb, state->hook, dataoff, IPPROTO_ICMP)) {
icmp_error_log(skb, state, "bad hw icmp checksum");
return -NF_ACCEPT;
}
diff --git a/net/netfilter/nf_nat_proto.c b/net/netfilter/nf_nat_proto.c
index 07da077..83a24cc 100644
--- a/net/netfilter/nf_nat_proto.c
+++ b/net/netfilter/nf_nat_proto.c
@@ -564,7 +564,7 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb,
if (!skb_make_writable(skb, hdrlen + sizeof(*inside)))
return 0;
- if (nf_ip_checksum(skb, hooknum, hdrlen, 0))
+ if (nf_ip_checksum(skb, hooknum, hdrlen, IPPROTO_ICMP))
return 0;
inside = (void *)skb->data + hdrlen;
diff --git a/net/netfilter/utils.c b/net/netfilter/utils.c
index 06dc555..51b454d 100644
--- a/net/netfilter/utils.c
+++ b/net/netfilter/utils.c
@@ -17,7 +17,8 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
case CHECKSUM_COMPLETE:
if (hook != NF_INET_PRE_ROUTING && hook != NF_INET_LOCAL_IN)
break;
- if ((protocol == 0 && !csum_fold(skb->csum)) ||
+ if ((protocol != IPPROTO_TCP && protocol != IPPROTO_UDP &&
+ !csum_fold(skb->csum)) ||
!csum_tcpudp_magic(iph->saddr, iph->daddr,
skb->len - dataoff, protocol,
skb->csum)) {
@@ -26,7 +27,7 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
}
/* fall through */
case CHECKSUM_NONE:
- if (protocol == 0)
+ if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP)
skb->csum = 0;
else
skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
--
2.7.4
^ permalink raw reply related
* Re: [PATCH V3 05/10] net: dsa: microchip: Use PORT_CTRL_ADDR() instead of indirect function call
From: Andrew Lunn @ 2019-06-24 3:20 UTC (permalink / raw)
To: Marek Vasut; +Cc: netdev, Florian Fainelli, Tristram Ha, Woojung Huh
In-Reply-To: <20190623223508.2713-6-marex@denx.de>
On Mon, Jun 24, 2019 at 12:35:03AM +0200, Marek Vasut wrote:
> The indirect function call to dev->dev_ops->get_port_addr() is expensive
> especially if called for every single register access, and only returns
> the value of PORT_CTRL_ADDR() macro. Use PORT_CTRL_ADDR() macro directly
> instead.
Hi Marek
Rather than change just one instance, it would be better to change
them all. And then remove dev_ops->get_port_addr().
Andrew
^ permalink raw reply
* Re: [PATCH V3 06/10] net: dsa: microchip: Factor out register access opcode generation
From: Andrew Lunn @ 2019-06-24 3:22 UTC (permalink / raw)
To: Marek Vasut; +Cc: netdev, Florian Fainelli, Tristram Ha, Woojung Huh
In-Reply-To: <20190623223508.2713-7-marex@denx.de>
On Mon, Jun 24, 2019 at 12:35:04AM +0200, Marek Vasut wrote:
> Factor out the code which sends out the register read/write opcodes
> to the switch, since the code differs in single bit between read and
> write.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* [PATCH V3 10/10] net: dsa: microchip: Replace ad-hoc bit manipulation with regmap
From: Marek Vasut @ 2019-06-23 22:35 UTC (permalink / raw)
To: netdev; +Cc: Marek Vasut, Andrew Lunn, Florian Fainelli, Tristram Ha,
Woojung Huh
In-Reply-To: <20190623223508.2713-1-marex@denx.de>
Regmap provides bit manipulation functions to set/clear bits, use those
insted of reimplementing them.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Tristram Ha <Tristram.Ha@microchip.com>
Cc: Woojung Huh <Woojung.Huh@microchip.com>
---
V2: New patch
V3: - Rebase on next/master
- Test on KSZ9477EVB
---
drivers/net/dsa/microchip/ksz9477.c | 46 ++++-------------------------
1 file changed, 6 insertions(+), 40 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 7d209fd9f26f..8f13dcc05a10 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -67,60 +67,26 @@ static const struct {
static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
{
- u8 data;
-
- ksz_read8(dev, addr, &data);
- if (set)
- data |= bits;
- else
- data &= ~bits;
- ksz_write8(dev, addr, data);
+ regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
}
static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
bool set)
{
- u32 addr;
- u8 data;
-
- addr = PORT_CTRL_ADDR(port, offset);
- ksz_read8(dev, addr, &data);
-
- if (set)
- data |= bits;
- else
- data &= ~bits;
-
- ksz_write8(dev, addr, data);
+ regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset),
+ bits, set ? bits : 0);
}
static void ksz9477_cfg32(struct ksz_device *dev, u32 addr, u32 bits, bool set)
{
- u32 data;
-
- ksz_read32(dev, addr, &data);
- if (set)
- data |= bits;
- else
- data &= ~bits;
- ksz_write32(dev, addr, data);
+ regmap_update_bits(dev->regmap[2], addr, bits, set ? bits : 0);
}
static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset,
u32 bits, bool set)
{
- u32 addr;
- u32 data;
-
- addr = PORT_CTRL_ADDR(port, offset);
- ksz_read32(dev, addr, &data);
-
- if (set)
- data |= bits;
- else
- data &= ~bits;
-
- ksz_write32(dev, addr, data);
+ regmap_update_bits(dev->regmap[2], PORT_CTRL_ADDR(port, offset),
+ bits, set ? bits : 0);
}
static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev, u32 waiton,
--
2.20.1
^ permalink raw reply related
* [PATCH V3 01/10] net: dsa: microchip: Remove ksz_{read,write}24()
From: Marek Vasut @ 2019-06-23 22:34 UTC (permalink / raw)
To: netdev; +Cc: Marek Vasut, Andrew Lunn, Florian Fainelli, Tristram Ha,
Woojung Huh
In-Reply-To: <20190623223508.2713-1-marex@denx.de>
These functions and callbacks are never used, remove them.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Tristram Ha <Tristram.Ha@microchip.com>
Cc: Woojung Huh <Woojung.Huh@microchip.com>
---
V2: No change
V3: - Rebase on next/master
- Test on KSZ9477EVB
---
drivers/net/dsa/microchip/ksz9477_spi.c | 25 -------------------------
drivers/net/dsa/microchip/ksz_common.h | 22 ----------------------
drivers/net/dsa/microchip/ksz_priv.h | 2 --
3 files changed, 49 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c
index 75178624d3f5..e7118319c192 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -73,37 +73,12 @@ static int ksz_spi_write(struct ksz_device *dev, u32 reg, void *data,
return ksz9477_spi_write_reg(spi, reg, dev->txbuf, len);
}
-static int ksz_spi_read24(struct ksz_device *dev, u32 reg, u32 *val)
-{
- int ret;
-
- *val = 0;
- ret = ksz_spi_read(dev, reg, (u8 *)val, 3);
- if (!ret) {
- *val = be32_to_cpu(*val);
- /* convert to 24bit */
- *val >>= 8;
- }
-
- return ret;
-}
-
-static int ksz_spi_write24(struct ksz_device *dev, u32 reg, u32 value)
-{
- /* make it to big endian 24bit from MSB */
- value <<= 8;
- value = cpu_to_be32(value);
- return ksz_spi_write(dev, reg, &value, 3);
-}
-
static const struct ksz_io_ops ksz9477_spi_ops = {
.read8 = ksz_spi_read8,
.read16 = ksz_spi_read16,
- .read24 = ksz_spi_read24,
.read32 = ksz_spi_read32,
.write8 = ksz_spi_write8,
.write16 = ksz_spi_write16,
- .write24 = ksz_spi_write24,
.write32 = ksz_spi_write32,
.get = ksz_spi_get,
.set = ksz_spi_set,
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 21cd794e18f1..1781539c3a81 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -61,17 +61,6 @@ static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
return ret;
}
-static inline int ksz_read24(struct ksz_device *dev, u32 reg, u32 *val)
-{
- int ret;
-
- mutex_lock(&dev->reg_mutex);
- ret = dev->ops->read24(dev, reg, val);
- mutex_unlock(&dev->reg_mutex);
-
- return ret;
-}
-
static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val)
{
int ret;
@@ -105,17 +94,6 @@ static inline int ksz_write16(struct ksz_device *dev, u32 reg, u16 value)
return ret;
}
-static inline int ksz_write24(struct ksz_device *dev, u32 reg, u32 value)
-{
- int ret;
-
- mutex_lock(&dev->reg_mutex);
- ret = dev->ops->write24(dev, reg, value);
- mutex_unlock(&dev->reg_mutex);
-
- return ret;
-}
-
static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)
{
int ret;
diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h
index c615d2a81dd5..5ef6153bd2cc 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -105,11 +105,9 @@ struct ksz_device {
struct ksz_io_ops {
int (*read8)(struct ksz_device *dev, u32 reg, u8 *value);
int (*read16)(struct ksz_device *dev, u32 reg, u16 *value);
- int (*read24)(struct ksz_device *dev, u32 reg, u32 *value);
int (*read32)(struct ksz_device *dev, u32 reg, u32 *value);
int (*write8)(struct ksz_device *dev, u32 reg, u8 value);
int (*write16)(struct ksz_device *dev, u32 reg, u16 value);
- int (*write24)(struct ksz_device *dev, u32 reg, u32 value);
int (*write32)(struct ksz_device *dev, u32 reg, u32 value);
int (*get)(struct ksz_device *dev, u32 reg, void *data, size_t len);
int (*set)(struct ksz_device *dev, u32 reg, void *data, size_t len);
--
2.20.1
^ permalink raw reply related
* [PATCH V3 06/10] net: dsa: microchip: Factor out register access opcode generation
From: Marek Vasut @ 2019-06-23 22:35 UTC (permalink / raw)
To: netdev; +Cc: Marek Vasut, Andrew Lunn, Florian Fainelli, Tristram Ha,
Woojung Huh
In-Reply-To: <20190623223508.2713-1-marex@denx.de>
Factor out the code which sends out the register read/write opcodes
to the switch, since the code differs in single bit between read and
write.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Tristram Ha <Tristram.Ha@microchip.com>
Cc: Woojung Huh <Woojung.Huh@microchip.com>
---
V2: New patch
V3: - Rebase on next/master
- Test on KSZ9477EVB
---
drivers/net/dsa/microchip/ksz9477_spi.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c
index a34e66eccbcd..49aeb92d36fc 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -25,19 +25,24 @@
/* Enough to read all switch port registers. */
#define SPI_TX_BUF_LEN 0x100
-static int ksz9477_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val,
- unsigned int len)
+static u32 ksz9477_spi_cmd(u32 reg, bool read)
{
u32 txbuf;
- int ret;
txbuf = reg & SPI_ADDR_MASK;
- txbuf |= KS_SPIOP_RD << SPI_ADDR_SHIFT;
+ txbuf |= (read ? KS_SPIOP_RD : KS_SPIOP_WR) << SPI_ADDR_SHIFT;
txbuf <<= SPI_TURNAROUND_SHIFT;
txbuf = cpu_to_be32(txbuf);
- ret = spi_write_then_read(spi, &txbuf, 4, val, len);
- return ret;
+ return txbuf;
+}
+
+static int ksz9477_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val,
+ unsigned int len)
+{
+ u32 txbuf = ksz9477_spi_cmd(reg, true);
+
+ return spi_write_then_read(spi, &txbuf, 4, val, len);
}
static int ksz9477_spi_write_reg(struct spi_device *spi, u32 reg, u8 *val,
@@ -45,10 +50,7 @@ static int ksz9477_spi_write_reg(struct spi_device *spi, u32 reg, u8 *val,
{
u32 *txbuf = (u32 *)val;
- *txbuf = reg & SPI_ADDR_MASK;
- *txbuf |= (KS_SPIOP_WR << SPI_ADDR_SHIFT);
- *txbuf <<= SPI_TURNAROUND_SHIFT;
- *txbuf = cpu_to_be32(*txbuf);
+ *txbuf = ksz9477_spi_cmd(reg, false);
return spi_write(spi, txbuf, 4 + len);
}
--
2.20.1
^ permalink raw reply related
* [PATCH V3 08/10] net: dsa: microchip: Dispose of ksz_io_ops
From: Marek Vasut @ 2019-06-23 22:35 UTC (permalink / raw)
To: netdev; +Cc: Marek Vasut, Andrew Lunn, Florian Fainelli, Tristram Ha,
Woojung Huh
In-Reply-To: <20190623223508.2713-1-marex@denx.de>
Since the driver now uses regmap , get rid of ad-hoc ksz_io_ops
abstraction, which no longer has any meaning. Moreover, since regmap
has it's own locking, get rid of the register access mutex.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Tristram Ha <Tristram.Ha@microchip.com>
Cc: Woojung Huh <Woojung.Huh@microchip.com>
---
V2: Use separate regmaps for 8/16/32bit registers
V3: - Rebase on next/master
- Test on KSZ9477EVB
---
drivers/net/dsa/microchip/ksz9477_spi.c | 57 +------------------------
drivers/net/dsa/microchip/ksz_common.c | 6 +--
drivers/net/dsa/microchip/ksz_common.h | 50 ++++++----------------
drivers/net/dsa/microchip/ksz_priv.h | 16 +------
4 files changed, 17 insertions(+), 112 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c
index 77e3cb100eae..8c8bf3237013 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -46,67 +46,12 @@ static const struct regmap_config ksz9477_regmap_config[] = {
KSZ_REGMAP_COMMON(32),
};
-static int ksz_spi_read8(struct ksz_device *dev, u32 reg, u8 *val)
-{
- unsigned int value;
- int ret = regmap_read(dev->regmap, reg, &value);
-
- *val = value;
- return ret;
-}
-
-static int ksz_spi_read16(struct ksz_device *dev, u32 reg, u16 *val)
-{
- int ret = regmap_bulk_read(dev->regmap, reg, val, 2);
-
- if (!ret)
- *val = be16_to_cpu(*val);
-
- return ret;
-}
-
-static int ksz_spi_read32(struct ksz_device *dev, u32 reg, u32 *val)
-{
- int ret = regmap_bulk_read(dev->regmap, reg, val, 4);
-
- if (!ret)
- *val = be32_to_cpu(*val);
-
- return ret;
-}
-
-static int ksz_spi_write8(struct ksz_device *dev, u32 reg, u8 value)
-{
- return regmap_write(dev->regmap, reg, value);
-}
-
-static int ksz_spi_write16(struct ksz_device *dev, u32 reg, u16 value)
-{
- value = cpu_to_be16(value);
- return regmap_bulk_write(dev->regmap, reg, &value, 2);
-}
-
-static int ksz_spi_write32(struct ksz_device *dev, u32 reg, u32 value)
-{
- value = cpu_to_be32(value);
- return regmap_bulk_write(dev->regmap, reg, &value, 4);
-}
-
-static const struct ksz_io_ops ksz9477_spi_ops = {
- .read8 = ksz_spi_read8,
- .read16 = ksz_spi_read16,
- .read32 = ksz_spi_read32,
- .write8 = ksz_spi_write8,
- .write16 = ksz_spi_write16,
- .write32 = ksz_spi_write32,
-};
-
static int ksz9477_spi_probe(struct spi_device *spi)
{
struct ksz_device *dev;
int i, ret;
- dev = ksz_switch_alloc(&spi->dev, &ksz9477_spi_ops, spi);
+ dev = ksz_switch_alloc(&spi->dev, spi);
if (!dev)
return -ENOMEM;
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 978c59aa8efb..a3d2d67894bd 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -396,9 +396,7 @@ void ksz_disable_port(struct dsa_switch *ds, int port)
}
EXPORT_SYMBOL_GPL(ksz_disable_port);
-struct ksz_device *ksz_switch_alloc(struct device *base,
- const struct ksz_io_ops *ops,
- void *priv)
+struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
{
struct dsa_switch *ds;
struct ksz_device *swdev;
@@ -416,7 +414,6 @@ struct ksz_device *ksz_switch_alloc(struct device *base,
swdev->ds = ds;
swdev->priv = priv;
- swdev->ops = ops;
return swdev;
}
@@ -442,7 +439,6 @@ int ksz_switch_register(struct ksz_device *dev,
}
mutex_init(&dev->dev_mutex);
- mutex_init(&dev->reg_mutex);
mutex_init(&dev->stats_mutex);
mutex_init(&dev->alu_mutex);
mutex_init(&dev->vlan_mutex);
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index fe576a00facf..c3871ed9b097 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -7,6 +7,8 @@
#ifndef __KSZ_COMMON_H
#define __KSZ_COMMON_H
+#include <linux/regmap.h>
+
void ksz_port_cleanup(struct ksz_device *dev, int port);
void ksz_update_port_member(struct ksz_device *dev, int port);
void ksz_init_mib_timer(struct ksz_device *dev);
@@ -41,68 +43,44 @@ void ksz_disable_port(struct dsa_switch *ds, int port);
static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val)
{
- int ret;
-
- mutex_lock(&dev->reg_mutex);
- ret = dev->ops->read8(dev, reg, val);
- mutex_unlock(&dev->reg_mutex);
+ unsigned int value;
+ int ret = regmap_read(dev->regmap[0], reg, &value);
+ *val = value;
return ret;
}
static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
{
- int ret;
-
- mutex_lock(&dev->reg_mutex);
- ret = dev->ops->read16(dev, reg, val);
- mutex_unlock(&dev->reg_mutex);
+ unsigned int value;
+ int ret = regmap_read(dev->regmap[1], reg, &value);
+ *val = value;
return ret;
}
static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val)
{
- int ret;
-
- mutex_lock(&dev->reg_mutex);
- ret = dev->ops->read32(dev, reg, val);
- mutex_unlock(&dev->reg_mutex);
+ unsigned int value;
+ int ret = regmap_read(dev->regmap[2], reg, &value);
+ *val = value;
return ret;
}
static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value)
{
- int ret;
-
- mutex_lock(&dev->reg_mutex);
- ret = dev->ops->write8(dev, reg, value);
- mutex_unlock(&dev->reg_mutex);
-
- return ret;
+ return regmap_write(dev->regmap[0], reg, value);
}
static inline int ksz_write16(struct ksz_device *dev, u32 reg, u16 value)
{
- int ret;
-
- mutex_lock(&dev->reg_mutex);
- ret = dev->ops->write16(dev, reg, value);
- mutex_unlock(&dev->reg_mutex);
-
- return ret;
+ return regmap_write(dev->regmap[1], reg, value);
}
static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)
{
- int ret;
-
- mutex_lock(&dev->reg_mutex);
- ret = dev->ops->write32(dev, reg, value);
- mutex_unlock(&dev->reg_mutex);
-
- return ret;
+ return regmap_write(dev->regmap[2], reg, value);
}
static inline void ksz_pread8(struct ksz_device *dev, int port, int offset,
diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h
index 5ccc633fc766..beacf0e40f42 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -14,8 +14,6 @@
#include <linux/etherdevice.h>
#include <net/dsa.h>
-struct ksz_io_ops;
-
struct vlan_table {
u32 table[3];
};
@@ -49,11 +47,9 @@ struct ksz_device {
const char *name;
struct mutex dev_mutex; /* device access */
- struct mutex reg_mutex; /* register access */
struct mutex stats_mutex; /* status access */
struct mutex alu_mutex; /* ALU access */
struct mutex vlan_mutex; /* vlan access */
- const struct ksz_io_ops *ops;
const struct ksz_dev_ops *dev_ops;
struct device *dev;
@@ -101,15 +97,6 @@ struct ksz_device {
u16 port_mask;
};
-struct ksz_io_ops {
- int (*read8)(struct ksz_device *dev, u32 reg, u8 *value);
- int (*read16)(struct ksz_device *dev, u32 reg, u16 *value);
- int (*read32)(struct ksz_device *dev, u32 reg, u32 *value);
- int (*write8)(struct ksz_device *dev, u32 reg, u8 value);
- int (*write16)(struct ksz_device *dev, u32 reg, u16 value);
- int (*write32)(struct ksz_device *dev, u32 reg, u32 value);
-};
-
struct alu_struct {
/* entry 1 */
u8 is_static:1;
@@ -158,8 +145,7 @@ struct ksz_dev_ops {
void (*exit)(struct ksz_device *dev);
};
-struct ksz_device *ksz_switch_alloc(struct device *base,
- const struct ksz_io_ops *ops, void *priv);
+struct ksz_device *ksz_switch_alloc(struct device *base, void *priv);
int ksz_switch_register(struct ksz_device *dev,
const struct ksz_dev_ops *ops);
void ksz_switch_remove(struct ksz_device *dev);
--
2.20.1
^ permalink raw reply related
* [PATCH V3 09/10] net: dsa: microchip: Factor out regmap config generation into common header
From: Marek Vasut @ 2019-06-23 22:35 UTC (permalink / raw)
To: netdev; +Cc: Marek Vasut, Andrew Lunn, Florian Fainelli, Tristram Ha,
Woojung Huh
In-Reply-To: <20190623223508.2713-1-marex@denx.de>
The regmap config tables are rather similar for various generations of
the KSZ8xxx/KSZ9xxx switches. Introduce a macro which allows generating
those tables without duplication. Note that $regalign parameter is not
used right now, but will be used in KSZ87xx series switches.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Tristram Ha <Tristram.Ha@microchip.com>
Cc: Woojung Huh <Woojung.Huh@microchip.com>
---
V2: New patch
V3: - Rebase on next/master
- Test on KSZ9477EVB
- Increase regmap max register, to cover all switch registers
- Make register swabbing configurable, to allow handling switches
with only 16bit registers as well as switches with some 32bit ones
---
drivers/net/dsa/microchip/ksz9477_spi.c | 29 +++-------------------
drivers/net/dsa/microchip/ksz_common.h | 32 +++++++++++++++++++++++++
2 files changed, 35 insertions(+), 26 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c
index 8c8bf3237013..5a9e27b337a8 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -14,37 +14,14 @@
#include <linux/spi/spi.h>
#include "ksz_priv.h"
+#include "ksz_common.h"
#define SPI_ADDR_SHIFT 24
#define SPI_ADDR_ALIGN 3
#define SPI_TURNAROUND_SHIFT 5
-/* SPI frame opcodes */
-#define KS_SPIOP_RD 3
-#define KS_SPIOP_WR 2
-
-#define KS_SPIOP_FLAG_MASK(opcode) \
- cpu_to_be32((opcode) << (SPI_ADDR_SHIFT + SPI_TURNAROUND_SHIFT))
-
-#define KSZ_REGMAP_COMMON(width) \
- { \
- .val_bits = (width), \
- .reg_stride = (width) / 8, \
- .reg_bits = SPI_ADDR_SHIFT + SPI_ADDR_ALIGN, \
- .pad_bits = SPI_TURNAROUND_SHIFT, \
- .max_register = BIT(SPI_ADDR_SHIFT) - 1, \
- .cache_type = REGCACHE_NONE, \
- .read_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_RD), \
- .write_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_WR), \
- .reg_format_endian = REGMAP_ENDIAN_BIG, \
- .val_format_endian = REGMAP_ENDIAN_BIG \
- }
-
-static const struct regmap_config ksz9477_regmap_config[] = {
- KSZ_REGMAP_COMMON(8),
- KSZ_REGMAP_COMMON(16),
- KSZ_REGMAP_COMMON(32),
-};
+KSZ_REGMAP_TABLE(ksz9477, 32, SPI_ADDR_SHIFT,
+ SPI_TURNAROUND_SHIFT, SPI_ADDR_ALIGN);
static int ksz9477_spi_probe(struct spi_device *spi)
{
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index c3871ed9b097..78b5ab7db403 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -133,4 +133,36 @@ static inline u32 ksz_pread32_poll(struct ksz_poll_ctx *ctx)
return data;
}
+/* Regmap tables generation */
+#define KSZ_SPI_OP_RD 3
+#define KSZ_SPI_OP_WR 2
+
+#define KSZ_SPI_OP_FLAG_MASK(opcode, swp, regbits, regpad) \
+ cpu_to_be##swp((opcode) << ((regbits) + (regpad)))
+
+#define KSZ_REGMAP_ENTRY(width, swp, regbits, regpad, regalign) \
+ { \
+ .val_bits = (width), \
+ .reg_stride = (width) / 8, \
+ .reg_bits = (regbits) + (regalign), \
+ .pad_bits = (regpad), \
+ .max_register = BIT(regbits) - 1, \
+ .cache_type = REGCACHE_NONE, \
+ .read_flag_mask = \
+ KSZ_SPI_OP_FLAG_MASK(KSZ_SPI_OP_RD, swp, \
+ regbits, regpad), \
+ .write_flag_mask = \
+ KSZ_SPI_OP_FLAG_MASK(KSZ_SPI_OP_WR, swp, \
+ regbits, regpad), \
+ .reg_format_endian = REGMAP_ENDIAN_BIG, \
+ .val_format_endian = REGMAP_ENDIAN_BIG \
+ }
+
+#define KSZ_REGMAP_TABLE(ksz, swp, regbits, regpad, regalign) \
+ static const struct regmap_config ksz##_regmap_config[] = { \
+ KSZ_REGMAP_ENTRY(8, swp, (regbits), (regpad), (regalign)), \
+ KSZ_REGMAP_ENTRY(16, swp, (regbits), (regpad), (regalign)), \
+ KSZ_REGMAP_ENTRY(32, swp, (regbits), (regpad), (regalign)), \
+ }
+
#endif
--
2.20.1
^ permalink raw reply related
* [PATCH V3 07/10] net: dsa: microchip: Initial SPI regmap support
From: Marek Vasut @ 2019-06-23 22:35 UTC (permalink / raw)
To: netdev; +Cc: Marek Vasut, Andrew Lunn, Florian Fainelli, Tristram Ha,
Woojung Huh
In-Reply-To: <20190623223508.2713-1-marex@denx.de>
Add basic SPI regmap support into the driver.
Previous patches unconver that ksz_spi_write() is always ever called
with len = 1, 2 or 4. We can thus drop the if (len > SPI_TX_BUF_LEN)
check and we can also drop the allocation of the txbuf which is part
of the driver data and wastes 256 bytes for no reason. Regmap covers
the whole thing now.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Tristram Ha <Tristram.Ha@microchip.com>
Cc: Woojung Huh <Woojung.Huh@microchip.com>
---
V2: - Squash with "net: dsa: microchip: Remove dev->txbuf"
- Use separate regmaps for 8/16/32bit registers
- Increase the regmap size to 0xd00 to cover the entire register area
V3: - Rebase on next/master
- Test on KSZ9477EVB
- Increase regmap max register, to cover all switch registers
- Correct regmap reg_bits value to match the hardware
- Use cpu_to_be32() instead of cpu_to_le16() in register masks, since
the KSZ9477 has some 32bit registers.
---
drivers/net/dsa/microchip/Kconfig | 1 +
drivers/net/dsa/microchip/ksz9477_spi.c | 114 +++++++++++-------------
drivers/net/dsa/microchip/ksz_priv.h | 3 +-
3 files changed, 52 insertions(+), 66 deletions(-)
diff --git a/drivers/net/dsa/microchip/Kconfig b/drivers/net/dsa/microchip/Kconfig
index 2c3a6751bdaf..56790d544eb2 100644
--- a/drivers/net/dsa/microchip/Kconfig
+++ b/drivers/net/dsa/microchip/Kconfig
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
config NET_DSA_MICROCHIP_KSZ_COMMON
+ select REGMAP_SPI
tristate
menuconfig NET_DSA_MICROCHIP_KSZ9477
diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c
index 49aeb92d36fc..77e3cb100eae 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -10,78 +10,54 @@
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include "ksz_priv.h"
-/* SPI frame opcodes */
-#define KS_SPIOP_RD 3
-#define KS_SPIOP_WR 2
-
#define SPI_ADDR_SHIFT 24
-#define SPI_ADDR_MASK (BIT(SPI_ADDR_SHIFT) - 1)
+#define SPI_ADDR_ALIGN 3
#define SPI_TURNAROUND_SHIFT 5
-/* Enough to read all switch port registers. */
-#define SPI_TX_BUF_LEN 0x100
-
-static u32 ksz9477_spi_cmd(u32 reg, bool read)
-{
- u32 txbuf;
-
- txbuf = reg & SPI_ADDR_MASK;
- txbuf |= (read ? KS_SPIOP_RD : KS_SPIOP_WR) << SPI_ADDR_SHIFT;
- txbuf <<= SPI_TURNAROUND_SHIFT;
- txbuf = cpu_to_be32(txbuf);
-
- return txbuf;
-}
-
-static int ksz9477_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val,
- unsigned int len)
-{
- u32 txbuf = ksz9477_spi_cmd(reg, true);
-
- return spi_write_then_read(spi, &txbuf, 4, val, len);
-}
-
-static int ksz9477_spi_write_reg(struct spi_device *spi, u32 reg, u8 *val,
- unsigned int len)
-{
- u32 *txbuf = (u32 *)val;
-
- *txbuf = ksz9477_spi_cmd(reg, false);
-
- return spi_write(spi, txbuf, 4 + len);
-}
-
-static int ksz_spi_read(struct ksz_device *dev, u32 reg, u8 *data,
- unsigned int len)
-{
- struct spi_device *spi = dev->priv;
-
- return ksz9477_spi_read_reg(spi, reg, data, len);
-}
-
-static int ksz_spi_write(struct ksz_device *dev, u32 reg, void *data,
- unsigned int len)
-{
- struct spi_device *spi = dev->priv;
+/* SPI frame opcodes */
+#define KS_SPIOP_RD 3
+#define KS_SPIOP_WR 2
- if (len > SPI_TX_BUF_LEN)
- len = SPI_TX_BUF_LEN;
- memcpy(&dev->txbuf[4], data, len);
- return ksz9477_spi_write_reg(spi, reg, dev->txbuf, len);
-}
+#define KS_SPIOP_FLAG_MASK(opcode) \
+ cpu_to_be32((opcode) << (SPI_ADDR_SHIFT + SPI_TURNAROUND_SHIFT))
+
+#define KSZ_REGMAP_COMMON(width) \
+ { \
+ .val_bits = (width), \
+ .reg_stride = (width) / 8, \
+ .reg_bits = SPI_ADDR_SHIFT + SPI_ADDR_ALIGN, \
+ .pad_bits = SPI_TURNAROUND_SHIFT, \
+ .max_register = BIT(SPI_ADDR_SHIFT) - 1, \
+ .cache_type = REGCACHE_NONE, \
+ .read_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_RD), \
+ .write_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_WR), \
+ .reg_format_endian = REGMAP_ENDIAN_BIG, \
+ .val_format_endian = REGMAP_ENDIAN_BIG \
+ }
+
+static const struct regmap_config ksz9477_regmap_config[] = {
+ KSZ_REGMAP_COMMON(8),
+ KSZ_REGMAP_COMMON(16),
+ KSZ_REGMAP_COMMON(32),
+};
static int ksz_spi_read8(struct ksz_device *dev, u32 reg, u8 *val)
{
- return ksz_spi_read(dev, reg, val, 1);
+ unsigned int value;
+ int ret = regmap_read(dev->regmap, reg, &value);
+
+ *val = value;
+ return ret;
}
static int ksz_spi_read16(struct ksz_device *dev, u32 reg, u16 *val)
{
- int ret = ksz_spi_read(dev, reg, (u8 *)val, 2);
+ int ret = regmap_bulk_read(dev->regmap, reg, val, 2);
if (!ret)
*val = be16_to_cpu(*val);
@@ -91,7 +67,7 @@ static int ksz_spi_read16(struct ksz_device *dev, u32 reg, u16 *val)
static int ksz_spi_read32(struct ksz_device *dev, u32 reg, u32 *val)
{
- int ret = ksz_spi_read(dev, reg, (u8 *)val, 4);
+ int ret = regmap_bulk_read(dev->regmap, reg, val, 4);
if (!ret)
*val = be32_to_cpu(*val);
@@ -101,19 +77,19 @@ static int ksz_spi_read32(struct ksz_device *dev, u32 reg, u32 *val)
static int ksz_spi_write8(struct ksz_device *dev, u32 reg, u8 value)
{
- return ksz_spi_write(dev, reg, &value, 1);
+ return regmap_write(dev->regmap, reg, value);
}
static int ksz_spi_write16(struct ksz_device *dev, u32 reg, u16 value)
{
value = cpu_to_be16(value);
- return ksz_spi_write(dev, reg, &value, 2);
+ return regmap_bulk_write(dev->regmap, reg, &value, 2);
}
static int ksz_spi_write32(struct ksz_device *dev, u32 reg, u32 value)
{
value = cpu_to_be32(value);
- return ksz_spi_write(dev, reg, &value, 4);
+ return regmap_bulk_write(dev->regmap, reg, &value, 4);
}
static const struct ksz_io_ops ksz9477_spi_ops = {
@@ -128,17 +104,27 @@ static const struct ksz_io_ops ksz9477_spi_ops = {
static int ksz9477_spi_probe(struct spi_device *spi)
{
struct ksz_device *dev;
- int ret;
+ int i, ret;
dev = ksz_switch_alloc(&spi->dev, &ksz9477_spi_ops, spi);
if (!dev)
return -ENOMEM;
+ for (i = 0; i < ARRAY_SIZE(ksz9477_regmap_config); i++) {
+ dev->regmap[i] = devm_regmap_init_spi(spi,
+ &ksz9477_regmap_config[i]);
+ if (IS_ERR(dev->regmap[i])) {
+ ret = PTR_ERR(dev->regmap[i]);
+ dev_err(&spi->dev,
+ "Failed to initialize regmap%i: %d\n",
+ ksz9477_regmap_config[i].val_bits, ret);
+ return ret;
+ }
+ }
+
if (spi->dev.platform_data)
dev->pdata = spi->dev.platform_data;
- dev->txbuf = devm_kzalloc(dev->dev, 4 + SPI_TX_BUF_LEN, GFP_KERNEL);
-
ret = ksz9477_switch_register(dev);
/* Main DSA driver may not be started yet. */
diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h
index d3ddf98156bb..5ccc633fc766 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -57,6 +57,7 @@ struct ksz_device {
const struct ksz_dev_ops *dev_ops;
struct device *dev;
+ struct regmap *regmap[3];
void *priv;
@@ -82,8 +83,6 @@ struct ksz_device {
struct vlan_table *vlan_cache;
- u8 *txbuf;
-
struct ksz_port *ports;
struct timer_list mib_read_timer;
struct work_struct mib_read;
--
2.20.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox