* Re: [PATCH v4 2/3] Bluetooth: cmtp: fix possible might sleep error in cmtp_session
From: AL Yu-Chen Cho @ 2017-06-12 8:44 UTC (permalink / raw)
To: Jeffy Chen, linux-bluetooth
Cc: Brian Norris, Douglas Anderson, Johan Hedberg, Peter Hurley,
Johan Hedberg, netdev, linux-kernel, David S. Miller,
Marcel Holtmann, Gustavo Padovan
In-Reply-To: <1487033725-7208-2-git-send-email-jeffy.chen@rock-chips.com>
On Tue, 2017-02-14 at 08:55 +0800, Jeffy Chen wrote:
> It looks like cmtp_session has same pattern as the issue reported in
> old rfcomm:
>
> while (1) {
> set_current_state(TASK_INTERRUPTIBLE);
> if (condition)
> break;
> // may call might_sleep here
> schedule();
> }
> __set_current_state(TASK_RUNNING);
>
> Which fixed at:
> dfb2fae Bluetooth: Fix nested sleeps
>
> So let's fix it at the same way, also follow the suggestion of:
> https://lwn.net/Articles/628628/
>
> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
> Reviewed-by: Brian Norris <briannorris@chromium.org>
> Remove unnecessary memory barrier before wake_up_* functions.
Reviewed-by: AL Yu-Chen Cho <acho@suse.com>
>
> ---
>
> Changes in v3:
> Add brian's Reviewed-by.
>
> Changes in v2: None
>
> net/bluetooth/cmtp/core.c | 17 ++++++++++-------
> 1 file changed, 10 insertions(+), 7 deletions(-)
>
> diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c
> index 9e59b66..1152ce3 100644
> --- a/net/bluetooth/cmtp/core.c
> +++ b/net/bluetooth/cmtp/core.c
> @@ -280,16 +280,16 @@ static int cmtp_session(void *arg)
> struct cmtp_session *session = arg;
> struct sock *sk = session->sock->sk;
> struct sk_buff *skb;
> - wait_queue_t wait;
> + DEFINE_WAIT_FUNC(wait, woken_wake_function);
>
> BT_DBG("session %p", session);
>
> set_user_nice(current, -15);
>
> - init_waitqueue_entry(&wait, current);
> add_wait_queue(sk_sleep(sk), &wait);
> while (1) {
> - set_current_state(TASK_INTERRUPTIBLE);
> + /* Ensure session->terminate is updated */
> + smp_mb__before_atomic();
>
> if (atomic_read(&session->terminate))
> break;
> @@ -306,9 +306,8 @@ static int cmtp_session(void *arg)
>
> cmtp_process_transmit(session);
>
> - schedule();
> + wait_woken(&wait, TASK_INTERRUPTIBLE,
> MAX_SCHEDULE_TIMEOUT);
> }
> - __set_current_state(TASK_RUNNING);
> remove_wait_queue(sk_sleep(sk), &wait);
>
> down_write(&cmtp_session_sem);
> @@ -393,7 +392,7 @@ int cmtp_add_connection(struct cmtp_connadd_req
> *req, struct socket *sock)
> err = cmtp_attach_device(session);
> if (err < 0) {
> atomic_inc(&session->terminate);
> - wake_up_process(session->task);
> + wake_up_interruptible(sk_sleep(session-
> >sock->sk));
> up_write(&cmtp_session_sem);
> return err;
> }
> @@ -431,7 +430,11 @@ int cmtp_del_connection(struct cmtp_conndel_req
> *req)
>
> /* Stop session thread */
> atomic_inc(&session->terminate);
> - wake_up_process(session->task);
> +
> + /* Ensure session->terminate is updated */
> + smp_mb__after_atomic();
> +
> + wake_up_interruptible(sk_sleep(session->sock->sk));
> } else
> err = -ENOENT;
>
^ permalink raw reply
* Re: [PATCH v4 3/3] Bluetooth: hidp: fix possible might sleep error in hidp_session_thread
From: AL Yu-Chen Cho @ 2017-06-12 8:44 UTC (permalink / raw)
To: Jeffy Chen, linux-bluetooth
Cc: Brian Norris, Douglas Anderson, Johan Hedberg, Peter Hurley,
Johan Hedberg, netdev, linux-kernel, David S. Miller,
Marcel Holtmann, Gustavo Padovan
In-Reply-To: <1487033725-7208-3-git-send-email-jeffy.chen@rock-chips.com>
On Tue, 2017-02-14 at 08:55 +0800, Jeffy Chen wrote:
> It looks like hidp_session_thread has same pattern as the issue
> reported in
> old rfcomm:
>
> while (1) {
> set_current_state(TASK_INTERRUPTIBLE);
> if (condition)
> break;
> // may call might_sleep here
> schedule();
> }
> __set_current_state(TASK_RUNNING);
>
> Which fixed at:
> dfb2fae Bluetooth: Fix nested sleeps
>
> So let's fix it at the same way, also follow the suggestion of:
> https://lwn.net/Articles/628628/
>
> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
> 1/ Fix could not wake up by wake attempts on original wait queues.
> 2/ Remove unnecessary memory barrier before wake_up_* functions.
>
> 1/ Make hidp_session_wake_function static.
> 2/ Remove unnecessary default_wake_function.
>
Tested-by: AL Yu-Chen Cho <acho@suse.com>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
> net/bluetooth/hidp/core.c | 33 ++++++++++++++++++++++-----------
> 1 file changed, 22 insertions(+), 11 deletions(-)
>
> diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
> index 0bec458..1fc0764 100644
> --- a/net/bluetooth/hidp/core.c
> +++ b/net/bluetooth/hidp/core.c
> @@ -36,6 +36,7 @@
> #define VERSION "1.2"
>
> static DECLARE_RWSEM(hidp_session_sem);
> +static DECLARE_WAIT_QUEUE_HEAD(hidp_session_wq);
> static LIST_HEAD(hidp_session_list);
>
> static unsigned char hidp_keycode[256] = {
> @@ -1068,12 +1069,12 @@ static int hidp_session_start_sync(struct
> hidp_session *session)
> * Wake up session thread and notify it to stop. This is
> asynchronous and
> * returns immediately. Call this whenever a runtime error occurs
> and you want
> * the session to stop.
> - * Note: wake_up_process() performs any necessary memory-barriers
> for us.
> + * Note: wake_up_interruptible() performs any necessary memory-
> barriers for us.
> */
> static void hidp_session_terminate(struct hidp_session *session)
> {
> atomic_inc(&session->terminate);
> - wake_up_process(session->task);
> + wake_up_interruptible(&hidp_session_wq);
> }
>
> /*
> @@ -1180,7 +1181,9 @@ static void hidp_session_run(struct
> hidp_session *session)
> struct sock *ctrl_sk = session->ctrl_sock->sk;
> struct sock *intr_sk = session->intr_sock->sk;
> struct sk_buff *skb;
> + DEFINE_WAIT_FUNC(wait, woken_wake_function);
>
> + add_wait_queue(&hidp_session_wq, &wait);
> for (;;) {
> /*
> * This thread can be woken up two ways:
> @@ -1188,12 +1191,10 @@ static void hidp_session_run(struct
> hidp_session *session)
> * session->terminate flag and wakes this thread
> up.
> * - Via modifying the socket state of
> ctrl/intr_sock. This
> * thread is woken up by ->sk_state_changed().
> - *
> - * Note: set_current_state() performs any necessary
> - * memory-barriers for us.
> */
> - set_current_state(TASK_INTERRUPTIBLE);
>
> + /* Ensure session->terminate is updated */
> + smp_mb__before_atomic();
> if (atomic_read(&session->terminate))
> break;
>
> @@ -1227,11 +1228,22 @@ static void hidp_session_run(struct
> hidp_session *session)
> hidp_process_transmit(session, &session-
> >ctrl_transmit,
> session->ctrl_sock);
>
> - schedule();
> + wait_woken(&wait, TASK_INTERRUPTIBLE,
> MAX_SCHEDULE_TIMEOUT);
> }
> + remove_wait_queue(&hidp_session_wq, &wait);
>
> atomic_inc(&session->terminate);
> - set_current_state(TASK_RUNNING);
> +
> + /* Ensure session->terminate is updated */
> + smp_mb__after_atomic();
> +}
> +
> +static int hidp_session_wake_function(wait_queue_t *wait,
> + unsigned int mode,
> + int sync, void *key)
> +{
> + wake_up_interruptible(&hidp_session_wq);
> + return false;
> }
>
> /*
> @@ -1244,7 +1256,8 @@ static void hidp_session_run(struct
> hidp_session *session)
> static int hidp_session_thread(void *arg)
> {
> struct hidp_session *session = arg;
> - wait_queue_t ctrl_wait, intr_wait;
> + DEFINE_WAIT_FUNC(ctrl_wait, hidp_session_wake_function);
> + DEFINE_WAIT_FUNC(intr_wait, hidp_session_wake_function);
>
> BT_DBG("session %p", session);
>
> @@ -1254,8 +1267,6 @@ static int hidp_session_thread(void *arg)
> set_user_nice(current, -15);
> hidp_set_timer(session);
>
> - init_waitqueue_entry(&ctrl_wait, current);
> - init_waitqueue_entry(&intr_wait, current);
> add_wait_queue(sk_sleep(session->ctrl_sock->sk),
> &ctrl_wait);
> add_wait_queue(sk_sleep(session->intr_sock->sk),
> &intr_wait);
> /* This memory barrier is paired with wq_has_sleeper(). See
^ permalink raw reply
* Re: [PATCH nf-next] netns: add and use net_ns_barrier
From: Pablo Neira Ayuso @ 2017-06-12 8:47 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: Florian Westphal, netfilter-devel, netdev
In-Reply-To: <87y3tcj3n7.fsf@xmission.com>
On Wed, May 31, 2017 at 01:13:32PM -0500, Eric W. Biederman wrote:
> Florian Westphal <fw@strlen.de> writes:
>
> > Quoting Joe Stringer:
> > If a user loads nf_conntrack_ftp, sends FTP traffic through a network
> > namespace, destroys that namespace then unloads the FTP helper module,
> > then the kernel will crash.
> >
> > Events that lead to the crash:
> > 1. conntrack is created with ftp helper in netns x
> > 2. This netns is destroyed
> > 3. netns destruction is scheduled
> > 4. netns destruction wq starts, removes netns from global list
> > 5. ftp helper is unloaded, which resets all helpers of the conntracks
> > via for_each_net()
> >
> > but because netns is already gone from list the for_each_net() loop
> > doesn't include it, therefore all of these conntracks are unaffected.
> >
> > 6. helper module unload finishes
> > 7. netns wq invokes destructor for rmmod'ed helper
> >
> > CC: "Eric W. Biederman" <ebiederm@xmission.com>
> > Reported-by: Joe Stringer <joe@ovn.org>
> > Signed-off-by: Florian Westphal <fw@strlen.de>
> > ---
> > Eric, I'd like an explicit (n)ack from you for this one.
>
> This doesn't look too scary but I have the impression we have addressed
> this elsewhere with a different solution.
Eric, so you hold your nose there and I take this ;-)
Or let me know if you want a different path.
Thanks !
^ permalink raw reply
* [PATCH net-next v3 0/3] udp: reduce cache pressure
From: Paolo Abeni @ 2017-06-12 9:23 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller, Eric Dumazet
In the most common use case, many skb fields are not used by recvmsg(), and
the few ones actually accessed lays on cold cachelines, which leads to several
cache miss per packet.
This patch series attempts to reduce such misses with different strategies:
* caching the interesting fields in the scratched space
* avoid accessing at all uninteresting fields
* prefetching
Tested using the udp_sink program by Jesper[1] as the receiver, an h/w l4 rx
hash on the ingress nic, so that the number of ingress nic rx queues hit by the
udp traffic could be controlled via ethtool -L.
The udp_sink program was bound to the first idle cpu, to get more
stable numbers.
On a single numa node receiver:
nic rx queues vanilla patched kernel delta
1 1850 kpps 1850 kpps 0%
2 2370 kpps 2700 kpps 13.9%
16 2000 kpps 2220 kpps 11%
[1] https://github.com/netoptimizer/network-testing/blob/master/src/udp_sink.c
v1 -> v2:
- replaced secpath_reset() with skb_release_head_state()
- changed udp_dev_scratch fields types to u{32,16} variant,
replaced bitfield with bool
v2 -> v3:
- no changes, tested against apachebench for performances regression
Paolo Abeni (3):
net: factor out a helper to decrement the skb refcount
udp: avoid a cache miss on dequeue
udp: try to avoid 2 cache miss on dequeue
include/linux/skbuff.h | 15 +++++++
net/core/datagram.c | 4 +-
net/core/skbuff.c | 38 ++++++++++------
net/ipv4/udp.c | 120 ++++++++++++++++++++++++++++++++++++++++++++-----
4 files changed, 148 insertions(+), 29 deletions(-)
--
2.9.4
^ permalink raw reply
* [PATCH net-next v3 1/3] net: factor out a helper to decrement the skb refcount
From: Paolo Abeni @ 2017-06-12 9:23 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller, Eric Dumazet
In-Reply-To: <cover.1497026892.git.pabeni@redhat.com>
The same code is replicated in 3 different places; move it to a
common helper.
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Acked-by: Eric Dumazet <edumazet@google.com>
---
include/linux/skbuff.h | 13 +++++++++++++
net/core/datagram.c | 4 +---
net/core/skbuff.c | 14 ++++----------
3 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index d460a4c..decce36 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -867,6 +867,19 @@ static inline unsigned int skb_napi_id(const struct sk_buff *skb)
#endif
}
+/* decrement the reference count and return true if we can free the skb */
+static inline bool skb_unref(struct sk_buff *skb)
+{
+ if (unlikely(!skb))
+ return false;
+ if (likely(atomic_read(&skb->users) == 1))
+ smp_rmb();
+ else if (likely(!atomic_dec_and_test(&skb->users)))
+ return false;
+
+ return true;
+}
+
void kfree_skb(struct sk_buff *skb);
void kfree_skb_list(struct sk_buff *segs);
void skb_tx_error(struct sk_buff *skb);
diff --git a/net/core/datagram.c b/net/core/datagram.c
index bc46118..e5311a7 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -330,9 +330,7 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len)
{
bool slow;
- if (likely(atomic_read(&skb->users) == 1))
- smp_rmb();
- else if (likely(!atomic_dec_and_test(&skb->users))) {
+ if (!skb_unref(skb)) {
sk_peek_offset_bwd(sk, len);
return;
}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index e508c1e..747263c 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -694,12 +694,9 @@ EXPORT_SYMBOL(__kfree_skb);
*/
void kfree_skb(struct sk_buff *skb)
{
- if (unlikely(!skb))
- return;
- if (likely(atomic_read(&skb->users) == 1))
- smp_rmb();
- else if (likely(!atomic_dec_and_test(&skb->users)))
+ if (!skb_unref(skb))
return;
+
trace_kfree_skb(skb, __builtin_return_address(0));
__kfree_skb(skb);
}
@@ -746,12 +743,9 @@ EXPORT_SYMBOL(skb_tx_error);
*/
void consume_skb(struct sk_buff *skb)
{
- if (unlikely(!skb))
- return;
- if (likely(atomic_read(&skb->users) == 1))
- smp_rmb();
- else if (likely(!atomic_dec_and_test(&skb->users)))
+ if (!skb_unref(skb))
return;
+
trace_consume_skb(skb);
__kfree_skb(skb);
}
--
2.9.4
^ permalink raw reply related
* [PATCH net-next v3 2/3] udp: avoid a cache miss on dequeue
From: Paolo Abeni @ 2017-06-12 9:23 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller, Eric Dumazet
In-Reply-To: <cover.1497026892.git.pabeni@redhat.com>
Since UDP no more uses sk->destructor, we can clear completely
the skb head state before enqueuing. Amend and use
skb_release_head_state() for that.
All head states share a single cacheline, which is not
normally used/accesses on dequeue. We can avoid entirely accessing
such cacheline implementing and using in the UDP code a specialized
skb free helper which ignores the skb head state.
This saves a cacheline miss at skb deallocation time.
v1 -> v2:
replaced secpath_reset() with skb_release_head_state()
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Acked-by: Eric Dumazet <edumazet@google.com>
---
include/linux/skbuff.h | 2 ++
net/core/skbuff.c | 24 ++++++++++++++++++++----
net/ipv4/udp.c | 6 +++++-
3 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index decce36..d66d4fe 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -880,10 +880,12 @@ static inline bool skb_unref(struct sk_buff *skb)
return true;
}
+void skb_release_head_state(struct sk_buff *skb);
void kfree_skb(struct sk_buff *skb);
void kfree_skb_list(struct sk_buff *segs);
void skb_tx_error(struct sk_buff *skb);
void consume_skb(struct sk_buff *skb);
+void consume_stateless_skb(struct sk_buff *skb);
void __kfree_skb(struct sk_buff *skb);
extern struct kmem_cache *skbuff_head_cache;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 747263c..3046027 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -643,12 +643,10 @@ static void kfree_skbmem(struct sk_buff *skb)
kmem_cache_free(skbuff_fclone_cache, fclones);
}
-static void skb_release_head_state(struct sk_buff *skb)
+void skb_release_head_state(struct sk_buff *skb)
{
skb_dst_drop(skb);
-#ifdef CONFIG_XFRM
- secpath_put(skb->sp);
-#endif
+ secpath_reset(skb);
if (skb->destructor) {
WARN_ON(in_irq());
skb->destructor(skb);
@@ -751,6 +749,24 @@ void consume_skb(struct sk_buff *skb)
}
EXPORT_SYMBOL(consume_skb);
+/**
+ * consume_stateless_skb - free an skbuff, assuming it is stateless
+ * @skb: buffer to free
+ *
+ * Works like consume_skb(), but this variant assumes that all the head
+ * states have been already dropped.
+ */
+void consume_stateless_skb(struct sk_buff *skb)
+{
+ if (!skb_unref(skb))
+ return;
+
+ trace_consume_skb(skb);
+ if (likely(skb->head))
+ skb_release_data(skb);
+ kfree_skbmem(skb);
+}
+
void __kfree_skb_flush(void)
{
struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index fdcb743..d8b265f 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1359,7 +1359,8 @@ void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len)
sk_peek_offset_bwd(sk, len);
unlock_sock_fast(sk, slow);
}
- consume_skb(skb);
+
+ consume_stateless_skb(skb);
}
EXPORT_SYMBOL_GPL(skb_consume_udp);
@@ -1739,6 +1740,9 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
sk_mark_napi_id_once(sk, skb);
}
+ /* clear all pending head states while they are hot in the cache */
+ skb_release_head_state(skb);
+
rc = __udp_enqueue_schedule_skb(sk, skb);
if (rc < 0) {
int is_udplite = IS_UDPLITE(sk);
--
2.9.4
^ permalink raw reply related
* [PATCH net-next v3 3/3] udp: try to avoid 2 cache miss on dequeue
From: Paolo Abeni @ 2017-06-12 9:23 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller, Eric Dumazet
In-Reply-To: <cover.1497026892.git.pabeni@redhat.com>
when udp_recvmsg() is executed, on x86_64 and other archs, most skb
fields are on cold cachelines.
If the skb are linear and the kernel don't need to compute the udp
csum, only a handful of skb fields are required by udp_recvmsg().
Since we already use skb->dev_scratch to cache hot data, and
there are 32 bits unused on 64 bit archs, use such field to cache
as much data as we can, and try to prefetch on dequeue the relevant
fields that are left out.
This can save up to 2 cache miss per packet.
v1 -> v2:
- changed udp_dev_scratch fields types to u{32,16} variant,
replaced bitfiled with bool
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Acked-by: Eric Dumazet <edumazet@google.com>
---
net/ipv4/udp.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 103 insertions(+), 11 deletions(-)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index d8b265f..2bc638c 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1163,6 +1163,83 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset,
return ret;
}
+/* Copy as much information as possible into skb->dev_scratch to avoid
+ * possibly multiple cache miss on dequeue();
+ */
+#if BITS_PER_LONG == 64
+
+/* we can store multiple info here: truesize, len and the bit needed to
+ * compute skb_csum_unnecessary will be on cold cache lines at recvmsg
+ * time.
+ * skb->len can be stored on 16 bits since the udp header has been already
+ * validated and pulled.
+ */
+struct udp_dev_scratch {
+ u32 truesize;
+ u16 len;
+ bool is_linear;
+ bool csum_unnecessary;
+};
+
+static void udp_set_dev_scratch(struct sk_buff *skb)
+{
+ struct udp_dev_scratch *scratch;
+
+ BUILD_BUG_ON(sizeof(struct udp_dev_scratch) > sizeof(long));
+ scratch = (struct udp_dev_scratch *)&skb->dev_scratch;
+ scratch->truesize = skb->truesize;
+ scratch->len = skb->len;
+ scratch->csum_unnecessary = !!skb_csum_unnecessary(skb);
+ scratch->is_linear = !skb_is_nonlinear(skb);
+}
+
+static int udp_skb_truesize(struct sk_buff *skb)
+{
+ return ((struct udp_dev_scratch *)&skb->dev_scratch)->truesize;
+}
+
+static unsigned int udp_skb_len(struct sk_buff *skb)
+{
+ return ((struct udp_dev_scratch *)&skb->dev_scratch)->len;
+}
+
+static bool udp_skb_csum_unnecessary(struct sk_buff *skb)
+{
+ return ((struct udp_dev_scratch *)&skb->dev_scratch)->csum_unnecessary;
+}
+
+static bool udp_skb_is_linear(struct sk_buff *skb)
+{
+ return ((struct udp_dev_scratch *)&skb->dev_scratch)->is_linear;
+}
+
+#else
+static void udp_set_dev_scratch(struct sk_buff *skb)
+{
+ skb->dev_scratch = skb->truesize;
+}
+
+static int udp_skb_truesize(struct sk_buff *skb)
+{
+ return skb->dev_scratch;
+}
+
+static unsigned int udp_skb_len(struct sk_buff *skb)
+{
+ return skb->len;
+}
+
+static bool udp_skb_csum_unnecessary(struct sk_buff *skb)
+{
+ return skb_csum_unnecessary(skb);
+}
+
+static bool udp_skb_is_linear(struct sk_buff *skb)
+{
+ return !skb_is_nonlinear(skb);
+}
+#endif
+
/* fully reclaim rmem/fwd memory allocated for skb */
static void udp_rmem_release(struct sock *sk, int size, int partial,
bool rx_queue_lock_held)
@@ -1213,14 +1290,16 @@ static void udp_rmem_release(struct sock *sk, int size, int partial,
*/
void udp_skb_destructor(struct sock *sk, struct sk_buff *skb)
{
- udp_rmem_release(sk, skb->dev_scratch, 1, false);
+ prefetch(&skb->data);
+ udp_rmem_release(sk, udp_skb_truesize(skb), 1, false);
}
EXPORT_SYMBOL(udp_skb_destructor);
/* as above, but the caller held the rx queue lock, too */
static void udp_skb_dtor_locked(struct sock *sk, struct sk_buff *skb)
{
- udp_rmem_release(sk, skb->dev_scratch, 1, true);
+ prefetch(&skb->data);
+ udp_rmem_release(sk, udp_skb_truesize(skb), 1, true);
}
/* Idea of busylocks is to let producers grab an extra spinlock
@@ -1274,10 +1353,7 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
busy = busylock_acquire(sk);
}
size = skb->truesize;
- /* Copy skb->truesize into skb->dev_scratch to avoid a cache line miss
- * in udp_skb_destructor()
- */
- skb->dev_scratch = size;
+ udp_set_dev_scratch(skb);
/* we drop only if the receive buf is full and the receive
* queue contains some other skb
@@ -1515,6 +1591,18 @@ struct sk_buff *__skb_recv_udp(struct sock *sk, unsigned int flags,
}
EXPORT_SYMBOL_GPL(__skb_recv_udp);
+static int copy_linear_skb(struct sk_buff *skb, int len, int off,
+ struct iov_iter *to)
+{
+ int n, copy = len - off;
+
+ n = copy_to_iter(skb->data + off, copy, to);
+ if (n == copy)
+ return 0;
+
+ return -EFAULT;
+}
+
/*
* This should be easy, if there is something there we
* return it, otherwise we block.
@@ -1541,7 +1629,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
if (!skb)
return err;
- ulen = skb->len;
+ ulen = udp_skb_len(skb);
copied = len;
if (copied > ulen - off)
copied = ulen - off;
@@ -1556,14 +1644,18 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
if (copied < ulen || peeking ||
(is_udplite && UDP_SKB_CB(skb)->partial_cov)) {
- checksum_valid = !udp_lib_checksum_complete(skb);
+ checksum_valid = udp_skb_csum_unnecessary(skb) ||
+ !__udp_lib_checksum_complete(skb);
if (!checksum_valid)
goto csum_copy_err;
}
- if (checksum_valid || skb_csum_unnecessary(skb))
- err = skb_copy_datagram_msg(skb, off, msg, copied);
- else {
+ if (checksum_valid || udp_skb_csum_unnecessary(skb)) {
+ if (udp_skb_is_linear(skb))
+ err = copy_linear_skb(skb, copied, off, &msg->msg_iter);
+ else
+ err = skb_copy_datagram_msg(skb, off, msg, copied);
+ } else {
err = skb_copy_and_csum_datagram_msg(skb, off, msg);
if (err == -EINVAL)
--
2.9.4
^ permalink raw reply related
* [PATCH v3 2/9] net: mvmdio: use tabs for defines
From: Antoine Tenart @ 2017-06-12 9:57 UTC (permalink / raw)
To: davem, jason, andrew, gregory.clement, sebastian.hesselbarth,
f.fainelli
Cc: thomas.petazzoni, netdev, Antoine Tenart, linux, nadavh, mw,
linux-arm-kernel
In-Reply-To: <20170612095745.11300-1-antoine.tenart@free-electrons.com>
Cosmetic patch replacing spaces by tabs for defined values.
Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/marvell/mvmdio.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 109a2bff334d..17b518b13ae3 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -30,25 +30,25 @@
#include <linux/sched.h>
#include <linux/wait.h>
-#define MVMDIO_SMI_DATA_SHIFT 0
-#define MVMDIO_SMI_PHY_ADDR_SHIFT 16
-#define MVMDIO_SMI_PHY_REG_SHIFT 21
-#define MVMDIO_SMI_READ_OPERATION BIT(26)
-#define MVMDIO_SMI_WRITE_OPERATION 0
-#define MVMDIO_SMI_READ_VALID BIT(27)
-#define MVMDIO_SMI_BUSY BIT(28)
-#define MVMDIO_ERR_INT_CAUSE 0x007C
-#define MVMDIO_ERR_INT_SMI_DONE 0x00000010
-#define MVMDIO_ERR_INT_MASK 0x0080
+#define MVMDIO_SMI_DATA_SHIFT 0
+#define MVMDIO_SMI_PHY_ADDR_SHIFT 16
+#define MVMDIO_SMI_PHY_REG_SHIFT 21
+#define MVMDIO_SMI_READ_OPERATION BIT(26)
+#define MVMDIO_SMI_WRITE_OPERATION 0
+#define MVMDIO_SMI_READ_VALID BIT(27)
+#define MVMDIO_SMI_BUSY BIT(28)
+#define MVMDIO_ERR_INT_CAUSE 0x007C
+#define MVMDIO_ERR_INT_SMI_DONE 0x00000010
+#define MVMDIO_ERR_INT_MASK 0x0080
/*
* SMI Timeout measurements:
* - Kirkwood 88F6281 (Globalscale Dreamplug): 45us to 95us (Interrupt)
* - Armada 370 (Globalscale Mirabox): 41us to 43us (Polled)
*/
-#define MVMDIO_SMI_TIMEOUT 1000 /* 1000us = 1ms */
-#define MVMDIO_SMI_POLL_INTERVAL_MIN 45
-#define MVMDIO_SMI_POLL_INTERVAL_MAX 55
+#define MVMDIO_SMI_TIMEOUT 1000 /* 1000us = 1ms */
+#define MVMDIO_SMI_POLL_INTERVAL_MIN 45
+#define MVMDIO_SMI_POLL_INTERVAL_MAX 55
struct orion_mdio_dev {
struct mutex lock;
--
2.9.4
^ permalink raw reply related
* [PATCH v3 1/9] net: mvmdio: reorder headers alphabetically
From: Antoine Tenart @ 2017-06-12 9:57 UTC (permalink / raw)
To: davem, jason, andrew, gregory.clement, sebastian.hesselbarth,
f.fainelli
Cc: Antoine Tenart, thomas.petazzoni, nadavh, mw, linux, netdev,
linux-arm-kernel
In-Reply-To: <20170612095745.11300-1-antoine.tenart@free-electrons.com>
Cosmetic fix reordering headers alphabetically.
Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/marvell/mvmdio.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 90a60b98c28e..109a2bff334d 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -17,16 +17,16 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/of_mdio.h>
#include <linux/phy.h>
-#include <linux/interrupt.h>
#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/of_mdio.h>
#include <linux/sched.h>
#include <linux/wait.h>
--
2.9.4
^ permalink raw reply related
* [PATCH v3 3/9] net: mvmdio: use GENMASK for masks
From: Antoine Tenart @ 2017-06-12 9:57 UTC (permalink / raw)
To: davem, jason, andrew, gregory.clement, sebastian.hesselbarth,
f.fainelli
Cc: Antoine Tenart, thomas.petazzoni, nadavh, mw, linux, netdev,
linux-arm-kernel
In-Reply-To: <20170612095745.11300-1-antoine.tenart@free-electrons.com>
Cosmetic patch to use the GENMASK helper for masks.
Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/marvell/mvmdio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 17b518b13ae3..583f1c5753c2 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -138,7 +138,7 @@ static int orion_mdio_read(struct mii_bus *bus, int mii_id,
goto out;
}
- ret = val & 0xFFFF;
+ ret = val & GENMASK(15, 0);
out:
mutex_unlock(&dev->lock);
return ret;
--
2.9.4
^ permalink raw reply related
* [PATCH v3 4/9] net: mvmdio: move the read valid check into its own function
From: Antoine Tenart @ 2017-06-12 9:57 UTC (permalink / raw)
To: davem, jason, andrew, gregory.clement, sebastian.hesselbarth,
f.fainelli
Cc: Antoine Tenart, thomas.petazzoni, nadavh, mw, linux, netdev,
linux-arm-kernel
In-Reply-To: <20170612095745.11300-1-antoine.tenart@free-electrons.com>
Move the read valid check in its own function. This is needed as a
requirement to factorize the driver to add the xMDIO support in the
future.
Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
drivers/net/ethernet/marvell/mvmdio.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 583f1c5753c2..2ed819d25305 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -69,6 +69,11 @@ static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev)
return !(readl(dev->regs) & MVMDIO_SMI_BUSY);
}
+static int orion_mdio_smi_is_read_valid(struct orion_mdio_dev *dev)
+{
+ return readl(dev->regs) & MVMDIO_SMI_READ_VALID;
+}
+
/* Wait for the SMI unit to be ready for another operation
*/
static int orion_mdio_wait_ready(struct mii_bus *bus)
@@ -113,7 +118,6 @@ static int orion_mdio_read(struct mii_bus *bus, int mii_id,
int regnum)
{
struct orion_mdio_dev *dev = bus->priv;
- u32 val;
int ret;
mutex_lock(&dev->lock);
@@ -131,14 +135,13 @@ static int orion_mdio_read(struct mii_bus *bus, int mii_id,
if (ret < 0)
goto out;
- val = readl(dev->regs);
- if (!(val & MVMDIO_SMI_READ_VALID)) {
+ if (!orion_mdio_smi_is_read_valid(dev)) {
dev_err(bus->parent, "SMI bus read not valid\n");
ret = -ENODEV;
goto out;
}
- ret = val & GENMASK(15, 0);
+ ret = readl(dev->regs) & GENMASK(15, 0);
out:
mutex_unlock(&dev->lock);
return ret;
--
2.9.4
^ permalink raw reply related
* [PATCH v3 5/9] net: mvmdio: introduce an ops structure
From: Antoine Tenart @ 2017-06-12 9:57 UTC (permalink / raw)
To: davem, jason, andrew, gregory.clement, sebastian.hesselbarth,
f.fainelli
Cc: Antoine Tenart, thomas.petazzoni, nadavh, mw, linux, netdev,
linux-arm-kernel
In-Reply-To: <20170612095745.11300-1-antoine.tenart@free-electrons.com>
Introduce an ops structure to add an indirection on functions accessing
the registers. This is needed to add the xMDIO support later.
Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
drivers/net/ethernet/marvell/mvmdio.c | 71 ++++++++++++++++++++++++++---------
1 file changed, 53 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 2ed819d25305..7d2f1b2e1fe1 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -64,6 +64,14 @@ struct orion_mdio_dev {
wait_queue_head_t smi_busy_wait;
};
+struct orion_mdio_ops {
+ int (*is_done)(struct orion_mdio_dev *);
+ int (*is_read_valid)(struct orion_mdio_dev *);
+ void (*start_read)(struct orion_mdio_dev *, int, int);
+ u16 (*read)(struct orion_mdio_dev *);
+ void (*write)(struct orion_mdio_dev *, int, int, u16);
+};
+
static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev)
{
return !(readl(dev->regs) & MVMDIO_SMI_BUSY);
@@ -74,9 +82,42 @@ static int orion_mdio_smi_is_read_valid(struct orion_mdio_dev *dev)
return readl(dev->regs) & MVMDIO_SMI_READ_VALID;
}
+static void orion_mdio_smi_start_read_op(struct orion_mdio_dev *dev, int mii_id,
+ int regnum)
+{
+ writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
+ (regnum << MVMDIO_SMI_PHY_REG_SHIFT) |
+ MVMDIO_SMI_READ_OPERATION),
+ dev->regs);
+}
+
+static u16 orion_mdio_smi_read_op(struct orion_mdio_dev *dev)
+{
+ return readl(dev->regs) & GENMASK(15, 0);
+}
+
+static void orion_mdio_smi_write_op(struct orion_mdio_dev *dev, int mii_id,
+ int regnum, u16 value)
+{
+ writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
+ (regnum << MVMDIO_SMI_PHY_REG_SHIFT) |
+ MVMDIO_SMI_WRITE_OPERATION |
+ (value << MVMDIO_SMI_DATA_SHIFT)),
+ dev->regs);
+}
+
+static const struct orion_mdio_ops orion_mdio_smi_ops = {
+ .is_done = orion_mdio_smi_is_done,
+ .is_read_valid = orion_mdio_smi_is_read_valid,
+ .start_read = orion_mdio_smi_start_read_op,
+ .read = orion_mdio_smi_read_op,
+ .write = orion_mdio_smi_write_op,
+};
+
/* Wait for the SMI unit to be ready for another operation
*/
-static int orion_mdio_wait_ready(struct mii_bus *bus)
+static int orion_mdio_wait_ready(const struct orion_mdio_ops *ops,
+ struct mii_bus *bus)
{
struct orion_mdio_dev *dev = bus->priv;
unsigned long timeout = usecs_to_jiffies(MVMDIO_SMI_TIMEOUT);
@@ -84,7 +125,7 @@ static int orion_mdio_wait_ready(struct mii_bus *bus)
int timedout = 0;
while (1) {
- if (orion_mdio_smi_is_done(dev))
+ if (ops->is_done(dev))
return 0;
else if (timedout)
break;
@@ -103,8 +144,7 @@ static int orion_mdio_wait_ready(struct mii_bus *bus)
if (timeout < 2)
timeout = 2;
wait_event_timeout(dev->smi_busy_wait,
- orion_mdio_smi_is_done(dev),
- timeout);
+ ops->is_done(dev), timeout);
++timedout;
}
@@ -118,30 +158,28 @@ static int orion_mdio_read(struct mii_bus *bus, int mii_id,
int regnum)
{
struct orion_mdio_dev *dev = bus->priv;
+ const struct orion_mdio_ops *ops = &orion_mdio_smi_ops;
int ret;
mutex_lock(&dev->lock);
- ret = orion_mdio_wait_ready(bus);
+ ret = orion_mdio_wait_ready(ops, bus);
if (ret < 0)
goto out;
- writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
- (regnum << MVMDIO_SMI_PHY_REG_SHIFT) |
- MVMDIO_SMI_READ_OPERATION),
- dev->regs);
+ ops->start_read(dev, mii_id, regnum);
- ret = orion_mdio_wait_ready(bus);
+ ret = orion_mdio_wait_ready(ops, bus);
if (ret < 0)
goto out;
- if (!orion_mdio_smi_is_read_valid(dev)) {
+ if (!ops->is_read_valid(dev)) {
dev_err(bus->parent, "SMI bus read not valid\n");
ret = -ENODEV;
goto out;
}
- ret = readl(dev->regs) & GENMASK(15, 0);
+ ret = ops->read(dev);
out:
mutex_unlock(&dev->lock);
return ret;
@@ -151,19 +189,16 @@ static int orion_mdio_write(struct mii_bus *bus, int mii_id,
int regnum, u16 value)
{
struct orion_mdio_dev *dev = bus->priv;
+ const struct orion_mdio_ops *ops = &orion_mdio_smi_ops;
int ret;
mutex_lock(&dev->lock);
- ret = orion_mdio_wait_ready(bus);
+ ret = orion_mdio_wait_ready(ops, bus);
if (ret < 0)
goto out;
- writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
- (regnum << MVMDIO_SMI_PHY_REG_SHIFT) |
- MVMDIO_SMI_WRITE_OPERATION |
- (value << MVMDIO_SMI_DATA_SHIFT)),
- dev->regs);
+ ops->write(dev, mii_id, regnum, value);
out:
mutex_unlock(&dev->lock);
--
2.9.4
^ permalink raw reply related
* [PATCH v3 6/9] net: mvmdio: put the poll intervals in the ops structure
From: Antoine Tenart @ 2017-06-12 9:57 UTC (permalink / raw)
To: davem, jason, andrew, gregory.clement, sebastian.hesselbarth,
f.fainelli
Cc: Antoine Tenart, thomas.petazzoni, nadavh, mw, linux, netdev,
linux-arm-kernel
In-Reply-To: <20170612095745.11300-1-antoine.tenart@free-electrons.com>
Put the two poll intervals (min and max) in the driver's ops
structure. This is needed to add the xmdio support later.
Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
drivers/net/ethernet/marvell/mvmdio.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 7d2f1b2e1fe1..41c75d7b84fb 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -70,6 +70,9 @@ struct orion_mdio_ops {
void (*start_read)(struct orion_mdio_dev *, int, int);
u16 (*read)(struct orion_mdio_dev *);
void (*write)(struct orion_mdio_dev *, int, int, u16);
+
+ unsigned int poll_interval_min;
+ unsigned int poll_interval_max;
};
static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev)
@@ -112,6 +115,9 @@ static const struct orion_mdio_ops orion_mdio_smi_ops = {
.start_read = orion_mdio_smi_start_read_op,
.read = orion_mdio_smi_read_op,
.write = orion_mdio_smi_write_op,
+
+ .poll_interval_min = MVMDIO_SMI_POLL_INTERVAL_MIN,
+ .poll_interval_max = MVMDIO_SMI_POLL_INTERVAL_MAX,
};
/* Wait for the SMI unit to be ready for another operation
@@ -131,8 +137,8 @@ static int orion_mdio_wait_ready(const struct orion_mdio_ops *ops,
break;
if (dev->err_interrupt <= 0) {
- usleep_range(MVMDIO_SMI_POLL_INTERVAL_MIN,
- MVMDIO_SMI_POLL_INTERVAL_MAX);
+ usleep_range(ops->poll_interval_min,
+ ops->poll_interval_max);
if (time_is_before_jiffies(end))
++timedout;
--
2.9.4
^ permalink raw reply related
* [PATCH v3 7/9] net: mvmdio: add xmdio xsmi support
From: Antoine Tenart @ 2017-06-12 9:57 UTC (permalink / raw)
To: davem, jason, andrew, gregory.clement, sebastian.hesselbarth,
f.fainelli
Cc: Antoine Tenart, thomas.petazzoni, nadavh, mw, linux, netdev,
linux-arm-kernel
In-Reply-To: <20170612095745.11300-1-antoine.tenart@free-electrons.com>
This patch adds the xmdio xsmi interface support in the mvmdio driver.
This interface is used in Ethernet controllers on Marvell 370, 7k and 8k
(as of now). The xsmi interface supported by this driver complies with
the IEEE 802.3 clause 45. The xSMI interface is used by 10GbE devices.
Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
drivers/net/ethernet/marvell/Kconfig | 6 +-
drivers/net/ethernet/marvell/mvmdio.c | 101 +++++++++++++++++++++++++++++++++-
2 files changed, 101 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
index da6fb825afea..205bb7e683b7 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -35,9 +35,9 @@ config MVMDIO
depends on HAS_IOMEM
select PHYLIB
---help---
- This driver supports the MDIO interface found in the network
- interface units of the Marvell EBU SoCs (Kirkwood, Orion5x,
- Dove, Armada 370 and Armada XP).
+ This driver supports the MDIO and xMDIO interfaces found in
+ the network interface units of the Marvell EBU SoCs (Kirkwood,
+ Orion5x, Dove, Armada 370, Armada XP, Armada 7k and Armada 8k).
This driver is used by the MV643XX_ETH and MVNETA drivers.
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 41c75d7b84fb..c43747f0be0b 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -24,6 +24,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/of_device.h>
#include <linux/of_mdio.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
@@ -41,6 +42,15 @@
#define MVMDIO_ERR_INT_SMI_DONE 0x00000010
#define MVMDIO_ERR_INT_MASK 0x0080
+#define MVMDIO_XSMI_MGNT_REG 0x0
+#define MVMDIO_XSMI_PHYADDR_SHIFT 16
+#define MVMDIO_XSMI_DEVADDR_SHIFT 21
+#define MVMDIO_XSMI_WRITE_OPERATION (0x5 << 26)
+#define MVMDIO_XSMI_READ_OPERATION (0x7 << 26)
+#define MVMDIO_XSMI_READ_VALID BIT(29)
+#define MVMDIO_XSMI_BUSY BIT(30)
+#define MVMDIO_XSMI_ADDR_REG 0x8
+
/*
* SMI Timeout measurements:
* - Kirkwood 88F6281 (Globalscale Dreamplug): 45us to 95us (Interrupt)
@@ -50,6 +60,14 @@
#define MVMDIO_SMI_POLL_INTERVAL_MIN 45
#define MVMDIO_SMI_POLL_INTERVAL_MAX 55
+#define MVMDIO_XSMI_POLL_INTERVAL_MIN 150
+#define MVMDIO_XSMI_POLL_INTERVAL_MAX 160
+
+enum orion_mdio_bus_type {
+ BUS_TYPE_SMI,
+ BUS_TYPE_XSMI
+};
+
struct orion_mdio_dev {
struct mutex lock;
void __iomem *regs;
@@ -62,6 +80,8 @@ struct orion_mdio_dev {
*/
int err_interrupt;
wait_queue_head_t smi_busy_wait;
+
+ enum orion_mdio_bus_type bus_type;
};
struct orion_mdio_ops {
@@ -75,6 +95,7 @@ struct orion_mdio_ops {
unsigned int poll_interval_max;
};
+/* mdio smi */
static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev)
{
return !(readl(dev->regs) & MVMDIO_SMI_BUSY);
@@ -120,6 +141,68 @@ static const struct orion_mdio_ops orion_mdio_smi_ops = {
.poll_interval_max = MVMDIO_SMI_POLL_INTERVAL_MAX,
};
+/* xmdio xsmi */
+static int orion_mdio_xsmi_is_done(struct orion_mdio_dev *dev)
+{
+ return !(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & MVMDIO_XSMI_BUSY);
+}
+
+static int orion_mdio_xsmi_is_read_valid(struct orion_mdio_dev *dev)
+{
+ return readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & MVMDIO_XSMI_READ_VALID;
+}
+
+static void orion_mdio_xsmi_start_read_op(struct orion_mdio_dev *dev,
+ int mii_id, int regnum)
+{
+ u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
+
+ writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
+ writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
+ (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
+ MVMDIO_XSMI_READ_OPERATION,
+ dev->regs + MVMDIO_XSMI_MGNT_REG);
+}
+
+static u16 orion_mdio_xsmi_read_op(struct orion_mdio_dev *dev)
+{
+ return readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0);
+}
+
+static void orion_mdio_xsmi_write_op(struct orion_mdio_dev *dev, int mii_id,
+ int regnum, u16 value)
+{
+ u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
+
+ writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
+ writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
+ (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
+ MVMDIO_XSMI_WRITE_OPERATION | value,
+ dev->regs + MVMDIO_XSMI_MGNT_REG);
+}
+
+static const struct orion_mdio_ops orion_mdio_xsmi_ops = {
+ .is_done = orion_mdio_xsmi_is_done,
+ .is_read_valid = orion_mdio_xsmi_is_read_valid,
+ .start_read = orion_mdio_xsmi_start_read_op,
+ .read = orion_mdio_xsmi_read_op,
+ .write = orion_mdio_xsmi_write_op,
+
+ .poll_interval_min = MVMDIO_XSMI_POLL_INTERVAL_MIN,
+ .poll_interval_max = MVMDIO_XSMI_POLL_INTERVAL_MAX,
+};
+
+static const struct orion_mdio_ops *orion_mdio_get_ops(struct orion_mdio_dev *dev,
+ int regnum)
+{
+ if (dev->bus_type == BUS_TYPE_XSMI && (regnum & MII_ADDR_C45))
+ return &orion_mdio_xsmi_ops;
+ else if (dev->bus_type == BUS_TYPE_SMI)
+ return &orion_mdio_smi_ops;
+
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
/* Wait for the SMI unit to be ready for another operation
*/
static int orion_mdio_wait_ready(const struct orion_mdio_ops *ops,
@@ -164,9 +247,13 @@ static int orion_mdio_read(struct mii_bus *bus, int mii_id,
int regnum)
{
struct orion_mdio_dev *dev = bus->priv;
- const struct orion_mdio_ops *ops = &orion_mdio_smi_ops;
+ const struct orion_mdio_ops *ops;
int ret;
+ ops = orion_mdio_get_ops(dev, regnum);
+ if (IS_ERR(ops))
+ return PTR_ERR(ops);
+
mutex_lock(&dev->lock);
ret = orion_mdio_wait_ready(ops, bus);
@@ -195,9 +282,13 @@ static int orion_mdio_write(struct mii_bus *bus, int mii_id,
int regnum, u16 value)
{
struct orion_mdio_dev *dev = bus->priv;
- const struct orion_mdio_ops *ops = &orion_mdio_smi_ops;
+ const struct orion_mdio_ops *ops;
int ret;
+ ops = orion_mdio_get_ops(dev, regnum);
+ if (IS_ERR(ops))
+ return PTR_ERR(ops);
+
mutex_lock(&dev->lock);
ret = orion_mdio_wait_ready(ops, bus);
@@ -288,6 +379,9 @@ static int orion_mdio_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
+ dev->bus_type =
+ (enum orion_mdio_bus_type)of_device_get_match_data(&pdev->dev);
+
mutex_init(&dev->lock);
if (pdev->dev.of_node)
@@ -338,7 +432,8 @@ static int orion_mdio_remove(struct platform_device *pdev)
}
static const struct of_device_id orion_mdio_match[] = {
- { .compatible = "marvell,orion-mdio" },
+ { .compatible = "marvell,orion-mdio", .data = (void *)BUS_TYPE_SMI },
+ { .compatible = "marvell,xmdio", .data = (void *)BUS_TYPE_XSMI },
{ }
};
MODULE_DEVICE_TABLE(of, orion_mdio_match);
--
2.9.4
^ permalink raw reply related
* [PATCH v3 8/9] dt-bindings: orion-mdio: document the new xmdio compatible
From: Antoine Tenart @ 2017-06-12 9:57 UTC (permalink / raw)
To: davem, jason, andrew, gregory.clement, sebastian.hesselbarth,
f.fainelli
Cc: Antoine Tenart, thomas.petazzoni, nadavh, mw, linux, netdev,
linux-arm-kernel
In-Reply-To: <20170612095745.11300-1-antoine.tenart@free-electrons.com>
A new compatible for Marvell xMDIO interfaces was added into the Marvell
MDIO driver. Document this new compatible.
Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
Documentation/devicetree/bindings/net/marvell-orion-mdio.txt | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt b/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt
index ccdabdcc8618..b93a5b5a0472 100644
--- a/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt
+++ b/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt
@@ -1,12 +1,12 @@
* Marvell MDIO Ethernet Controller interface
The Ethernet controllers of the Marvel Kirkwood, Dove, Orion5x,
-MV78xx0, Armada 370 and Armada XP have an identical unit that provides
-an interface with the MDIO bus. This driver handles this MDIO
-interface.
+MV78xx0, Armada 370, Armada XP, Armada 7k and Armada 8k have an
+identical unit that provides an interface with the MDIO bus or
+with the xMDIO bus. This driver handles these interfaces.
Required properties:
-- compatible: "marvell,orion-mdio"
+- compatible: "marvell,orion-mdio" or "marvell,xmdio"
- reg: address and length of the MDIO registers. When an interrupt is
not present, the length is the size of the SMI register (4 bytes)
otherwise it must be 0x84 bytes to cover the interrupt control
--
2.9.4
^ permalink raw reply related
* [PATCH v3 0/9] net: mvmdio: add xMDIO xSMI support
From: Antoine Tenart @ 2017-06-12 9:57 UTC (permalink / raw)
To: davem, jason, andrew, gregory.clement, sebastian.hesselbarth,
f.fainelli
Cc: Antoine Tenart, thomas.petazzoni, nadavh, mw, linux, netdev,
linux-arm-kernel
Hello,
This series aims to add the xSMI support on the xMDIO bus to the
mvmdio driver. The xSMI interface complies with the IEEE 802.3 clause 45
and is used by 10GbE devices. On 7k and 8k (as of now), such an
interface is found and is used by Ethernet controllers.
Patches 1-3 are cosmetic cleanups.
Patches 4-6 are prerequisites to the xSMI support.
Patches 7-9 add the xSMI support to the mvmdio driver, and a node is
added both in the cp110 slave and master device trees.
This was tested on an Armada 8040 mcbin, as well as on both the
Armada 7040 DB and the Armada 8040 DB to ensure the SMI interface
was still working.
@Dave: patch 9 should go through the mvebu tree as asked by Gregory,
thanks!
Thanks,
Antoine
Since v2:
- Brought back the marvell,xmdio compatible and updated the driver
accordingly. The ops (smi, xsmi) are chosen based on the compatible.
- Now return -EOPNOTSUPP when the MII_ADDR_C45 bit is wrongly set.
- Mask dev_addr with GENMASK(4, 0).
- Moved bit definitions under their register definition.
- Fixed the write operation shift.
- Added one space before the second parameter of GENMASK.
Since v1:
- Instead of using the smi/xsmi helpers based on the compatible, now
check if the MII_ADDR_C45 bit is set.
- Removed the marvell,xmdio compatible addition.
- Fixed the is_read_valid logic.
- Updated to use static const variables for ops.
- Added 3 Reviewed-by tags from Florian (I dropped another one as the
patch changed in v2).
Antoine Tenart (9):
net: mvmdio: reorder headers alphabetically
net: mvmdio: use tabs for defines
net: mvmdio: use GENMASK for masks
net: mvmdio: move the read valid check into its own function
net: mvmdio: introduce an ops structure
net: mvmdio: put the poll intervals in the ops structure
net: mvmdio: add xmdio xsmi support
dt-bindings: orion-mdio: document the new xmdio compatible
arm64: marvell: dts: add xmdio nodes for 7k/8k
.../devicetree/bindings/net/marvell-orion-mdio.txt | 8 +-
.../boot/dts/marvell/armada-cp110-master.dtsi | 8 +
.../arm64/boot/dts/marvell/armada-cp110-slave.dtsi | 8 +
drivers/net/ethernet/marvell/Kconfig | 6 +-
drivers/net/ethernet/marvell/mvmdio.c | 221 +++++++++++++++++----
5 files changed, 203 insertions(+), 48 deletions(-)
--
2.9.4
^ permalink raw reply
* [PATCH v3 9/9] arm64: marvell: dts: add xmdio nodes for 7k/8k
From: Antoine Tenart @ 2017-06-12 9:57 UTC (permalink / raw)
To: davem, jason, andrew, gregory.clement, sebastian.hesselbarth,
f.fainelli
Cc: Antoine Tenart, thomas.petazzoni, nadavh, mw, linux, netdev,
linux-arm-kernel
In-Reply-To: <20170612095745.11300-1-antoine.tenart@free-electrons.com>
Add the description of the xMDIO bus for the Marvell Armada 7k and
Marvell Armada 8k; for both CP110 slave and master. This bus is found
on Marvell Ethernet controllers and provides an interface with the
xMDIO bus.
Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
@Dave: this patch should go through the mvebu tree as asked by Gregory, thanks!
arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi | 8 ++++++++
arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi | 8 ++++++++
2 files changed, 16 insertions(+)
diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
index 037ed30d75a7..464c41d0e66a 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
@@ -98,6 +98,14 @@
clocks = <&cpm_syscon0 1 9>, <&cpm_syscon0 1 5>;
};
+ cpm_xmdio: mdio@12a600 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "marvell,xmdio";
+ reg = <0x12a600 0x10>;
+ status = "disabled";
+ };
+
cpm_icu: interrupt-controller@1e0000 {
compatible = "marvell,cp110-icu";
reg = <0x1e0000 0x10>;
diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
index 2a99ff8fca2a..bbb603234f30 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
@@ -103,6 +103,14 @@
clocks = <&cps_syscon0 1 9>, <&cps_syscon0 1 5>;
};
+ cps_xmdio: mdio@12a600 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "marvell,xmdio";
+ reg = <0x12a600 0x10>;
+ status = "disabled";
+ };
+
cps_icu: interrupt-controller@1e0000 {
compatible = "marvell,cp110-icu";
reg = <0x1e0000 0x10>;
--
2.9.4
^ permalink raw reply related
* Re: [PATCH v3 7/9] net: mvmdio: add xmdio xsmi support
From: Russell King - ARM Linux @ 2017-06-12 10:07 UTC (permalink / raw)
To: Antoine Tenart
Cc: davem, jason, andrew, gregory.clement, sebastian.hesselbarth,
f.fainelli, thomas.petazzoni, nadavh, mw, netdev,
linux-arm-kernel
In-Reply-To: <20170612095745.11300-8-antoine.tenart@free-electrons.com>
On Mon, Jun 12, 2017 at 11:57:43AM +0200, Antoine Tenart wrote:
> +static void orion_mdio_xsmi_start_read_op(struct orion_mdio_dev *dev,
> + int mii_id, int regnum)
> +{
> + u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
> +
> + writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
> + writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
> + (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
> + MVMDIO_XSMI_READ_OPERATION,
> + dev->regs + MVMDIO_XSMI_MGNT_REG);
So what happens if this function gets passed a Clause 22 formatted
request? Both regnum and mii_id are in the range 0-31. MII_ADDR_C45
in regnum is clear.
The answer is we produce two Clause 45 frames on the bus, which is
certainly not correct. You need to trap and error out if MII_ADDR_C45
is not set (as I've already said previously.)
The SMI operations need to do the reverse - they need to fail if they
receive a regnum with MII_ADDR_C45 set, as they are unable to produce
Clause 45 frames.
> +static void orion_mdio_xsmi_write_op(struct orion_mdio_dev *dev, int mii_id,
> + int regnum, u16 value)
> +{
> + u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
> +
> + writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
> + writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
> + (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
> + MVMDIO_XSMI_WRITE_OPERATION | value,
> + dev->regs + MVMDIO_XSMI_MGNT_REG);
It's even more important here, as a Clause 22 write will produce a
valid Clause 45 pair of frames with dev_addr = 0.
Again, the corresponding SMI code needs to reject Clause 45 requests
as the SMI interface is unable to produce Clause 45 frames.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* Re: [PATCH v3 7/9] net: mvmdio: add xmdio xsmi support
From: Russell King - ARM Linux @ 2017-06-12 10:17 UTC (permalink / raw)
To: Antoine Tenart
Cc: davem, jason, andrew, gregory.clement, sebastian.hesselbarth,
f.fainelli, thomas.petazzoni, nadavh, mw, netdev,
linux-arm-kernel
In-Reply-To: <20170612095745.11300-8-antoine.tenart@free-electrons.com>
On Mon, Jun 12, 2017 at 11:57:43AM +0200, Antoine Tenart wrote:
> +static const struct orion_mdio_ops *orion_mdio_get_ops(struct orion_mdio_dev *dev,
> + int regnum)
> +{
> + if (dev->bus_type == BUS_TYPE_XSMI && (regnum & MII_ADDR_C45))
> + return &orion_mdio_xsmi_ops;
> + else if (dev->bus_type == BUS_TYPE_SMI)
> + return &orion_mdio_smi_ops;
> +
> + return ERR_PTR(-EOPNOTSUPP);
> +}
Oh, this is where you're doing it - I'm not sure having this complexity
is really necessary - there is no dynamic choice between the two. This
seems to be way over-engineered.
You might as well make the SMI operations fail if MII_ADDR_C45 is set,
and the XSMI operations fail if MII_ADDR_C45 is not set.
Hmm, I think this whole driver is over-engineered:
1. the mdio read/write functions implement their own locking.
At the MDIO level, there is already locking in the form of a per-bus
lock "bus->mdio_lock" which will be taken whenever either of these
functions is called. So the driver's "dev->lock" is redundant.
2. with the redundant locking removed, orion_mdio_write() becomes a
call to orion_mdio_wait_ready() followed by a call to dev->ops->write.
It seems that orion_mdio_wait_ready() could be a library function
shared between a SMI version of orion_mdio_write() and a XSMI version.
3. the same is really true of orion_mdio_read(), although that function
is a little more complex in itself, the result would actually end up
being simpler.
With those changes together, it elimates "struct orion_mdio_ops" entirely,
and I think makes the driver smaller, simpler, and cleaner.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* Re: [PATCH v2] arm: eBPF JIT compiler
From: Daniel Borkmann @ 2017-06-12 10:21 UTC (permalink / raw)
To: Kees Cook, Shubham Bansal, Network Development, David S. Miller,
Alexei Starovoitov
Cc: Russell King, linux-arm-kernel@lists.infradead.org, LKML,
Andrew Lunn
In-Reply-To: <CAGXu5jKmLNMR+uhM9Ov2XPW6kCjip_SjScgEH0fTFp6fQtKFiA@mail.gmail.com>
On 05/30/2017 09:19 PM, Kees Cook wrote:
> Forwarding this to net-dev and eBPF folks, who weren't on CC...
Sorry for being late. Some comments below from a cursory look ...
> -Kees
>
> On Thu, May 25, 2017 at 4:13 PM, Shubham Bansal
> <illusionist.neo@gmail.com> wrote:
>> The JIT compiler emits ARM 32 bit instructions. Currently, It supports
>> eBPF only. Classic BPF is supported because of the conversion by BPF
>> core.
>>
>> This patch is essentially changing the current implementation of JIT
>> compiler of Berkeley Packet Filter from classic to internal with almost
>> all instructions from eBPF ISA supported except the following
>> BPF_ALU64 | BPF_DIV | BPF_K
>> BPF_ALU64 | BPF_DIV | BPF_X
>> BPF_ALU64 | BPF_MOD | BPF_K
>> BPF_ALU64 | BPF_MOD | BPF_X
>> BPF_STX | BPF_XADD | BPF_W
>> BPF_STX | BPF_XADD | BPF_DW
>> BPF_JMP | BPF_CALL
Any plans to implement above especially BPF_JMP | BPF_CALL in near future?
Reason why I'm asking is that i) currently the arm32 cBPF JIT implements
all of the cBPF extensions (except SKF_AD_RANDOM and SKF_AD_VLAN_TPID).
Some of the programs that were JITed before e.g. using SKF_AD_CPU would now
fall back to the eBPF interpreter due to lack of translation in JIT, but
also ii) that probably most (if not all) of eBPF programs use BPF helper
calls heavily, which will still redirect them to the interpreter right now
due to lack of BPF_JMP | BPF_CALL support, so it's really quite essential
to have it implemented.
>> Implementation is using scratch space to emulate 64 bit eBPF ISA on 32 bit
>> ARM because of deficiency of general purpose registers on ARM. Currently,
>> only LITTLE ENDIAN machines are supported in this eBPF JIT Compiler.
>>
>> Tested on ARMv7 with QEMU by me (Shubham Bansal).
>> Tested on ARMv5 by Andrew Lunn (andrew@lunn.ch).
>> Expected to work on ARMv6 as well, as its a part ARMv7 and part ARMv5.
>> Although, a proper testing is not done for ARMv6.
>>
>> Both of these testing are done with and without CONFIG_FRAME_POINTER
>> separately for LITTLE ENDIAN machine.
>>
>> For testing:
>>
>> 1. JIT is enabled with
>> echo 1 > /proc/sys/net/core/bpf_jit_enable
>> 2. Constant Blinding can be enabled along with JIT using
>> echo 1 > /proc/sys/net/core/bpf_jit_enable
>> echo 2 > /proc/sys/net/core/bpf_jit_harden
>>
>> See Documentation/networking/filter.txt for more information.
>>
>> Result : test_bpf: Summary: 314 PASSED, 0 FAILED, [278/306 JIT'ed]
Did you also manage to get the BPF selftest suite running in the meantime
(tools/testing/selftests/bpf/)? There are a couple of programs that clang
will compile (test_pkt_access.o, test_xdp.o, test_l4lb.o, test_tcp_estats.o)
and then test run.
Did you manage to get tail calls tested as well (I assume so since you
implemented emit_bpf_tail_call() in the patch but just out of curiosity)?
>> Signed-off-by: Shubham Bansal <illusionist.neo@gmail.com>
>> ---
>> Documentation/networking/filter.txt | 4 +-
>> arch/arm/Kconfig | 2 +-
>> arch/arm/net/bpf_jit_32.c | 2404 ++++++++++++++++++++++++-----------
>> arch/arm/net/bpf_jit_32.h | 108 +-
>> 4 files changed, 1713 insertions(+), 805 deletions(-)
>>
[...]
If arm folks take the patch, there will be two minor (silent) merge
conflicts with net-next:
1) In bpf_int_jit_compile(), below the jited = 1 assignment, there
needs to come a prog->jited_len = image_size.
2) The internal tail call opcode changed from BPF_JMP | BPF_CALL | BPF_X
into BPF_JMP | BPF_TAIL_CALL.
Two minor things below, could probably also be as follow-up.
[...]
>> + /* dst = imm64 */
>> + case BPF_LD | BPF_IMM | BPF_DW:
>> + {
>> + const struct bpf_insn insn1 = insn[1];
>> + u32 hi, lo = imm;
>> +
>> + if (insn1.code != 0 || insn1.src_reg != 0 ||
>> + insn1.dst_reg != 0 || insn1.off != 0) {
>> + /* Note: verifier in BPF core must catch invalid
>> + * instruction.
>> + */
>> + pr_err_once("Invalid BPF_LD_IMM64 instruction\n");
>> + return -EINVAL;
>> + }
Nit: this check can be removed as verifier already takes care
of it. (No JIT checks for this anymore.)
>> + hi = insn1.imm;
>> + emit_a32_mov_i(dst_lo, lo, dstk, ctx);
>> + emit_a32_mov_i(dst_hi, hi, dstk, ctx);
>> +
>> + return 1;
>> + }
[...]
>> - /* compute offsets only during the first pass */
>> - if (ctx->target == NULL)
>> - ctx->offsets[i] = ctx->idx * 4;
>> +static int validate_code(struct jit_ctx *ctx)
>> +{
>> + int i;
>> +
>> + for (i = 0; i < ctx->idx; i++) {
>> + u32 a32_insn = le32_to_cpu(ctx->target[i]);
Given __opcode_to_mem_arm(ARM_INST_UDF) is used to fill the image,
perhaps use the __mem_to_opcode_arm() helper for the check?
>> + if (a32_insn == ARM_INST_UDF)
>> + return -1;
>> + }
>>
>> return 0;
>> }
>>
>> +void bpf_jit_compile(struct bpf_prog *prog)
>> +{
>> + /* Nothing to do here. We support Internal BPF. */
>> +}
^ permalink raw reply
* Re: [PATCH net-next v10 1/4] net netlink: Add new type NLA_FLAG_BITS
From: Jiri Pirko @ 2017-06-12 10:34 UTC (permalink / raw)
To: Jamal Hadi Salim
Cc: davem, netdev, xiyou.wangcong, eric.dumazet, simon.horman, mrv
In-Reply-To: <4441aa62-d00e-82b6-d337-f86cf97e3c6d@mojatatu.com>
Sun, Jun 11, 2017 at 08:37:25PM CEST, jhs@mojatatu.com wrote:
>On 17-06-11 01:38 PM, Jamal Hadi Salim wrote:
>> On 17-06-11 09:49 AM, Jiri Pirko wrote:
>> > Sun, Jun 11, 2017 at 01:53:43PM CEST, jhs@mojatatu.com wrote:
>> > > From: Jamal Hadi Salim <jhs@mojatatu.com>
>>
>>
>> > > This patch also provides an extra feature: a validation callback
>> > > that could be speaciliazed for other types.
>> >
>> > s/speaciliazed/speciliazed/
>> >
>>
>> Will fix.
>>
>>
>> > >
>> > > [ATTR_GOO] = { .type = MYTYPE,
>> > > .validation_data = &myvalidation_data,
>> > > .validate_content = mycontent_validator },
>> >
>> > Indent is wrong. (Does not matter really in desc, but anyway)
>> >
>>
>> I cant find out how it got indented that way; my source
>> or email dont show it as such (but really doesnt matter).
>>
>>
>> > Suggested-by: Jiri Pirko <jiri@mellanox.com>
>> >
>>
>> Will add.
>>
>> >
>> > > ---
>> > > include/net/netlink.h | 11 +++++++++++
>> > > include/uapi/linux/rtnetlink.h | 17 +++++++++++++++++
>> > > lib/nlattr.c | 25 +++++++++++++++++++++++++
>> > > 3 files changed, 53 insertions(+)
>> > >
>> > > diff --git a/include/net/netlink.h b/include/net/netlink.h
>> > > index 0170917..8ab9784 100644
>> > > --- a/include/net/netlink.h
>> > > +++ b/include/net/netlink.h
>> > > @@ -6,6 +6,11 @@
>> > > #include <linux/jiffies.h>
>> > > #include <linux/in6.h>
>> > >
>> > > +struct nla_bit_flags {
>> > > + u32 nla_flag_values;
>> > > + u32 nla_flag_selector;
>> > > +};
>> >
>> > I don't understand why you redefine the struct here. You already have it
>> > defined in the uapi: struct __nla_bit_flags
>> >
>> > Just move this (struct nla_bit_flags) to the uapi and remove
>> > __nla_bit_flags ?
>> >
>>
>> I am not sure that will compile since the type is defined in netlink.h
>> Also, note: uapi uses _u32 and kernel uses u32 as types i.e it is pretty
>> common approach; i will try to move it to uapi and keep that uapi
>> format. If it doesnt compile without acrobatics I will keep it as is.
>>
>
>It doesnt compile - I could move it to linux/netlink.h but it seems
>so out of place.
>so i will keep things as is for now unless you can think of something
>else.
First of all, makes no sense to put this struct "struct __nla_bit_flags"
into rtnetlink.h uapi file. This is generic netlink stuff, not specifict
to rtnetlink.
I believe that this struct should go into:
include/uapi/linux/netlink.h
struct nla_flag_bits {
__u32 nla_flag_bits_values;
__u32 nla_flag_bits_selector;
};
Then you can use it from userspace and everywhere in kernel.
Btw, I find it very odd that enum containling NLA_* like NLA_U32 and
others is not part of uapi file and is rather defined in
include/net/netlink.h. Any idea why?
^ permalink raw reply
* Re: [PATCH v3 7/9] net: mvmdio: add xmdio xsmi support
From: Russell King - ARM Linux @ 2017-06-12 10:41 UTC (permalink / raw)
To: Antoine Tenart
Cc: thomas.petazzoni, andrew, f.fainelli, jason, netdev, nadavh,
gregory.clement, mw, davem, linux-arm-kernel,
sebastian.hesselbarth
In-Reply-To: <20170612101739.GA4902@n2100.armlinux.org.uk>
On Mon, Jun 12, 2017 at 11:17:39AM +0100, Russell King - ARM Linux wrote:
> On Mon, Jun 12, 2017 at 11:57:43AM +0200, Antoine Tenart wrote:
> > +static const struct orion_mdio_ops *orion_mdio_get_ops(struct orion_mdio_dev *dev,
> > + int regnum)
> > +{
> > + if (dev->bus_type == BUS_TYPE_XSMI && (regnum & MII_ADDR_C45))
> > + return &orion_mdio_xsmi_ops;
> > + else if (dev->bus_type == BUS_TYPE_SMI)
> > + return &orion_mdio_smi_ops;
> > +
> > + return ERR_PTR(-EOPNOTSUPP);
> > +}
>
> Oh, this is where you're doing it - I'm not sure having this complexity
> is really necessary - there is no dynamic choice between the two. This
> seems to be way over-engineered.
>
> You might as well make the SMI operations fail if MII_ADDR_C45 is set,
> and the XSMI operations fail if MII_ADDR_C45 is not set.
>
> Hmm, I think this whole driver is over-engineered:
>
> 1. the mdio read/write functions implement their own locking.
>
> At the MDIO level, there is already locking in the form of a per-bus
> lock "bus->mdio_lock" which will be taken whenever either of these
> functions is called. So the driver's "dev->lock" is redundant.
>
> 2. with the redundant locking removed, orion_mdio_write() becomes a
> call to orion_mdio_wait_ready() followed by a call to dev->ops->write.
> It seems that orion_mdio_wait_ready() could be a library function
> shared between a SMI version of orion_mdio_write() and a XSMI version.
>
> 3. the same is really true of orion_mdio_read(), although that function
> is a little more complex in itself, the result would actually end up
> being simpler.
>
> With those changes together, it elimates "struct orion_mdio_ops" entirely,
> and I think makes the driver smaller, simpler, and cleaner.
I wasn't able to completely get rid of the ops structure, but I think
this is cleaner. I haven't tested these two patches yet.
drivers/net/ethernet/marvell/mvmdio.c | 276 +++++++++++++++-------------------
1 file changed, 123 insertions(+), 153 deletions(-)
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* Re: [PATCH v3 7/9] net: mvmdio: add xmdio xsmi support
From: Russell King - ARM Linux @ 2017-06-12 10:42 UTC (permalink / raw)
To: Antoine Tenart
Cc: thomas.petazzoni, andrew, f.fainelli, jason, netdev, nadavh,
gregory.clement, mw, davem, linux-arm-kernel,
sebastian.hesselbarth
In-Reply-To: <20170612104126.GB4902@n2100.armlinux.org.uk>
From: Russell King <rmk+kernel@armlinux.org.uk>
Subject: [PATCH 1/2] net: mvmdio: remove duplicate locking
The MDIO layer already provides per-bus locking, so there's no need for
MDIO bus drivers to do their own internal locking. Remove this.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/marvell/mvmdio.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index c43747f0be0b..d6770217965e 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -23,7 +23,6 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/of_mdio.h>
#include <linux/phy.h>
@@ -69,7 +68,6 @@ enum orion_mdio_bus_type {
};
struct orion_mdio_dev {
- struct mutex lock;
void __iomem *regs;
struct clk *clk[3];
/*
@@ -254,8 +252,6 @@ static int orion_mdio_read(struct mii_bus *bus, int mii_id,
if (IS_ERR(ops))
return PTR_ERR(ops);
- mutex_lock(&dev->lock);
-
ret = orion_mdio_wait_ready(ops, bus);
if (ret < 0)
goto out;
@@ -274,7 +270,6 @@ static int orion_mdio_read(struct mii_bus *bus, int mii_id,
ret = ops->read(dev);
out:
- mutex_unlock(&dev->lock);
return ret;
}
@@ -289,8 +284,6 @@ static int orion_mdio_write(struct mii_bus *bus, int mii_id,
if (IS_ERR(ops))
return PTR_ERR(ops);
- mutex_lock(&dev->lock);
-
ret = orion_mdio_wait_ready(ops, bus);
if (ret < 0)
goto out;
@@ -298,7 +291,6 @@ static int orion_mdio_write(struct mii_bus *bus, int mii_id,
ops->write(dev, mii_id, regnum, value);
out:
- mutex_unlock(&dev->lock);
return ret;
}
@@ -382,8 +374,6 @@ static int orion_mdio_probe(struct platform_device *pdev)
dev->bus_type =
(enum orion_mdio_bus_type)of_device_get_match_data(&pdev->dev);
- mutex_init(&dev->lock);
-
if (pdev->dev.of_node)
ret = of_mdiobus_register(bus, pdev->dev.of_node);
else
--
2.7.4
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply related
* Re: [PATCH v3 7/9] net: mvmdio: add xmdio xsmi support
From: Russell King - ARM Linux @ 2017-06-12 10:42 UTC (permalink / raw)
To: Antoine Tenart
Cc: thomas.petazzoni, andrew, f.fainelli, jason, netdev, nadavh,
gregory.clement, mw, davem, linux-arm-kernel,
sebastian.hesselbarth
In-Reply-To: <20170612104126.GB4902@n2100.armlinux.org.uk>
From: Russell King <rmk+kernel@armlinux.org.uk>
Subject: [PATCH 2/2] net: mvmdio: get rid of fine-grained ops
MIME-Version: 1.0
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
Content-Type: text/plain; charset="utf-8"
The fine-grained ops makes the driver less readable, so let's instead
implement two pairs of read/write mii_bus ops, one for SMI and the
other for XSMI.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/marvell/mvmdio.c | 268 ++++++++++++++++------------------
1 file changed, 124 insertions(+), 144 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index d6770217965e..d04022db8619 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -84,123 +84,11 @@ struct orion_mdio_dev {
struct orion_mdio_ops {
int (*is_done)(struct orion_mdio_dev *);
- int (*is_read_valid)(struct orion_mdio_dev *);
- void (*start_read)(struct orion_mdio_dev *, int, int);
- u16 (*read)(struct orion_mdio_dev *);
- void (*write)(struct orion_mdio_dev *, int, int, u16);
unsigned int poll_interval_min;
unsigned int poll_interval_max;
};
-/* mdio smi */
-static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev)
-{
- return !(readl(dev->regs) & MVMDIO_SMI_BUSY);
-}
-
-static int orion_mdio_smi_is_read_valid(struct orion_mdio_dev *dev)
-{
- return readl(dev->regs) & MVMDIO_SMI_READ_VALID;
-}
-
-static void orion_mdio_smi_start_read_op(struct orion_mdio_dev *dev, int mii_id,
- int regnum)
-{
- writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
- (regnum << MVMDIO_SMI_PHY_REG_SHIFT) |
- MVMDIO_SMI_READ_OPERATION),
- dev->regs);
-}
-
-static u16 orion_mdio_smi_read_op(struct orion_mdio_dev *dev)
-{
- return readl(dev->regs) & GENMASK(15, 0);
-}
-
-static void orion_mdio_smi_write_op(struct orion_mdio_dev *dev, int mii_id,
- int regnum, u16 value)
-{
- writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
- (regnum << MVMDIO_SMI_PHY_REG_SHIFT) |
- MVMDIO_SMI_WRITE_OPERATION |
- (value << MVMDIO_SMI_DATA_SHIFT)),
- dev->regs);
-}
-
-static const struct orion_mdio_ops orion_mdio_smi_ops = {
- .is_done = orion_mdio_smi_is_done,
- .is_read_valid = orion_mdio_smi_is_read_valid,
- .start_read = orion_mdio_smi_start_read_op,
- .read = orion_mdio_smi_read_op,
- .write = orion_mdio_smi_write_op,
-
- .poll_interval_min = MVMDIO_SMI_POLL_INTERVAL_MIN,
- .poll_interval_max = MVMDIO_SMI_POLL_INTERVAL_MAX,
-};
-
-/* xmdio xsmi */
-static int orion_mdio_xsmi_is_done(struct orion_mdio_dev *dev)
-{
- return !(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & MVMDIO_XSMI_BUSY);
-}
-
-static int orion_mdio_xsmi_is_read_valid(struct orion_mdio_dev *dev)
-{
- return readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & MVMDIO_XSMI_READ_VALID;
-}
-
-static void orion_mdio_xsmi_start_read_op(struct orion_mdio_dev *dev,
- int mii_id, int regnum)
-{
- u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
-
- writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
- writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
- (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
- MVMDIO_XSMI_READ_OPERATION,
- dev->regs + MVMDIO_XSMI_MGNT_REG);
-}
-
-static u16 orion_mdio_xsmi_read_op(struct orion_mdio_dev *dev)
-{
- return readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0);
-}
-
-static void orion_mdio_xsmi_write_op(struct orion_mdio_dev *dev, int mii_id,
- int regnum, u16 value)
-{
- u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
-
- writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
- writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
- (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
- MVMDIO_XSMI_WRITE_OPERATION | value,
- dev->regs + MVMDIO_XSMI_MGNT_REG);
-}
-
-static const struct orion_mdio_ops orion_mdio_xsmi_ops = {
- .is_done = orion_mdio_xsmi_is_done,
- .is_read_valid = orion_mdio_xsmi_is_read_valid,
- .start_read = orion_mdio_xsmi_start_read_op,
- .read = orion_mdio_xsmi_read_op,
- .write = orion_mdio_xsmi_write_op,
-
- .poll_interval_min = MVMDIO_XSMI_POLL_INTERVAL_MIN,
- .poll_interval_max = MVMDIO_XSMI_POLL_INTERVAL_MAX,
-};
-
-static const struct orion_mdio_ops *orion_mdio_get_ops(struct orion_mdio_dev *dev,
- int regnum)
-{
- if (dev->bus_type == BUS_TYPE_XSMI && (regnum & MII_ADDR_C45))
- return &orion_mdio_xsmi_ops;
- else if (dev->bus_type == BUS_TYPE_SMI)
- return &orion_mdio_smi_ops;
-
- return ERR_PTR(-EOPNOTSUPP);
-}
-
/* Wait for the SMI unit to be ready for another operation
*/
static int orion_mdio_wait_ready(const struct orion_mdio_ops *ops,
@@ -241,57 +129,138 @@ static int orion_mdio_wait_ready(const struct orion_mdio_ops *ops,
return -ETIMEDOUT;
}
-static int orion_mdio_read(struct mii_bus *bus, int mii_id,
- int regnum)
+/* mdio smi */
+static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev)
+{
+ return !(readl(dev->regs) & MVMDIO_SMI_BUSY);
+}
+
+static const struct orion_mdio_ops orion_mdio_smi_ops = {
+ .is_done = orion_mdio_smi_is_done,
+
+ .poll_interval_min = MVMDIO_SMI_POLL_INTERVAL_MIN,
+ .poll_interval_max = MVMDIO_SMI_POLL_INTERVAL_MAX,
+};
+
+static int orion_mdio_smi_read(struct mii_bus *bus, int mii_id,
+ int regnum)
{
struct orion_mdio_dev *dev = bus->priv;
- const struct orion_mdio_ops *ops;
int ret;
- ops = orion_mdio_get_ops(dev, regnum);
- if (IS_ERR(ops))
- return PTR_ERR(ops);
+ if (regnum & MII_ADDR_C45)
+ return -EOPNOTSUPP;
- ret = orion_mdio_wait_ready(ops, bus);
+ ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus);
if (ret < 0)
- goto out;
+ return ret;
- ops->start_read(dev, mii_id, regnum);
+ writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
+ (regnum << MVMDIO_SMI_PHY_REG_SHIFT) |
+ MVMDIO_SMI_READ_OPERATION),
+ dev->regs);
- ret = orion_mdio_wait_ready(ops, bus);
+ ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus);
if (ret < 0)
- goto out;
+ return ret;
- if (!ops->is_read_valid(dev)) {
+ if (!(readl(dev->regs) & MVMDIO_SMI_READ_VALID)) {
dev_err(bus->parent, "SMI bus read not valid\n");
- ret = -ENODEV;
- goto out;
+ return -ENODEV;
}
- ret = ops->read(dev);
-out:
- return ret;
+ return readl(dev->regs) & GENMASK(15, 0);
}
-static int orion_mdio_write(struct mii_bus *bus, int mii_id,
- int regnum, u16 value)
+static int orion_mdio_smi_write(struct mii_bus *bus, int mii_id,
+ int regnum, u16 value)
{
struct orion_mdio_dev *dev = bus->priv;
- const struct orion_mdio_ops *ops;
int ret;
- ops = orion_mdio_get_ops(dev, regnum);
- if (IS_ERR(ops))
- return PTR_ERR(ops);
+ if (regnum & MII_ADDR_C45)
+ return -EOPNOTSUPP;
- ret = orion_mdio_wait_ready(ops, bus);
+ ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus);
if (ret < 0)
- goto out;
+ return ret;
+
+ writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
+ (regnum << MVMDIO_SMI_PHY_REG_SHIFT) |
+ MVMDIO_SMI_WRITE_OPERATION |
+ (value << MVMDIO_SMI_DATA_SHIFT)),
+ dev->regs);
- ops->write(dev, mii_id, regnum, value);
+ return 0;
+}
-out:
- return ret;
+/* xmdio xsmi */
+static int orion_mdio_xsmi_is_done(struct orion_mdio_dev *dev)
+{
+ return !(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & MVMDIO_XSMI_BUSY);
+}
+
+static const struct orion_mdio_ops orion_mdio_xsmi_ops = {
+ .is_done = orion_mdio_xsmi_is_done,
+
+ .poll_interval_min = MVMDIO_XSMI_POLL_INTERVAL_MIN,
+ .poll_interval_max = MVMDIO_XSMI_POLL_INTERVAL_MAX,
+};
+
+static int orion_mdio_xsmi_read(struct mii_bus *bus, int mii_id,
+ int regnum)
+{
+ struct orion_mdio_dev *dev = bus->priv;
+ u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
+ int ret;
+
+ if (!(regnum & MII_ADDR_C45))
+ return -EOPNOTSUPP;
+
+ ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus);
+ if (ret < 0)
+ return ret;
+
+ writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
+ writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
+ (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
+ MVMDIO_XSMI_READ_OPERATION,
+ dev->regs + MVMDIO_XSMI_MGNT_REG);
+
+ ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus);
+ if (ret < 0)
+ return ret;
+
+ if (!(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) &
+ MVMDIO_XSMI_READ_VALID)) {
+ dev_err(bus->parent, "XSMI bus read not valid\n");
+ return -ENODEV;
+ }
+
+ return readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0);
+}
+
+static int orion_mdio_xsmi_write(struct mii_bus *bus, int mii_id,
+ int regnum, u16 value)
+{
+ struct orion_mdio_dev *dev = bus->priv;
+ u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
+ int ret;
+
+ if (!(regnum & MII_ADDR_C45))
+ return -EOPNOTSUPP;
+
+ ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus);
+ if (ret < 0)
+ return ret;
+
+ writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
+ writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
+ (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
+ MVMDIO_XSMI_WRITE_OPERATION | value,
+ dev->regs + MVMDIO_XSMI_MGNT_REG);
+
+ return 0;
}
static irqreturn_t orion_mdio_err_irq(int irq, void *dev_id)
@@ -311,11 +280,14 @@ static irqreturn_t orion_mdio_err_irq(int irq, void *dev_id)
static int orion_mdio_probe(struct platform_device *pdev)
{
+ enum orion_mdio_bus_type type;
struct resource *r;
struct mii_bus *bus;
struct orion_mdio_dev *dev;
int i, ret;
+ type = (enum orion_mdio_bus_type)of_device_get_match_data(&pdev->dev);
+
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
dev_err(&pdev->dev, "No SMI register address given\n");
@@ -328,8 +300,17 @@ static int orion_mdio_probe(struct platform_device *pdev)
return -ENOMEM;
bus->name = "orion_mdio_bus";
- bus->read = orion_mdio_read;
- bus->write = orion_mdio_write;
+
+ switch (type) {
+ case BUS_TYPE_SMI:
+ bus->read = orion_mdio_smi_read;
+ bus->write = orion_mdio_smi_write;
+ break;
+ case BUS_TYPE_XSMI:
+ bus->read = orion_mdio_xsmi_read;
+ bus->write = orion_mdio_xsmi_write;
+ break;
+ }
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii",
dev_name(&pdev->dev));
bus->parent = &pdev->dev;
@@ -371,8 +352,7 @@ static int orion_mdio_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
- dev->bus_type =
- (enum orion_mdio_bus_type)of_device_get_match_data(&pdev->dev);
+ dev->bus_type = type;
if (pdev->dev.of_node)
ret = of_mdiobus_register(bus, pdev->dev.of_node);
--
2.7.4
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply related
* [PATCH v4 0/3] Add new PCI_DEV_FLAGS_NO_RELAXED_ORDERING flag
From: Ding Tianhong @ 2017-06-12 11:05 UTC (permalink / raw)
To: leedom, ashok.raj, helgaas, werner, ganeshgr, asit.k.mallick,
patrick.j.cramer, Suravee.Suthikulpanit, Bob.Shaw, l.stach, amira,
gabriele.paoloni, David.Laight, jeffrey.t.kirsher,
catalin.marinas, will.deacon, mark.rutland, robin.murphy, davem,
alexander.duyck, linux-arm-kernel, netdev, linux-pci,
linux-kernel
Cc: Ding Tianhong
Some devices have problems with Transaction Layer Packets with the Relaxed
Ordering Attribute set. This patch set adds a new PCIe Device Flag,
PCI_DEV_FLAGS_NO_RELAXED_ORDERING, a set of PCI Quirks to catch some known
devices with Relaxed Ordering issues, and a use of this new flag by the
cxgb4 driver to avoid using Relaxed Ordering with problematic Root Complex
Ports.
It's been years since I've submitted kernel.org patches, I appolgise for the
almost certain submission errors.
v2: Alexander point out that the v1 was only a part of the whole solution,
some platform which has some issues could use the new flag to indicate
that it is not safe to enable relaxed ordering attribute, then we need
to clear the relaxed ordering enable bits in the PCI configuration when
initializing the device. So add a new second patch to modify the PCI
initialization code to clear the relaxed ordering enable bit in the
event that the root complex doesn't want relaxed ordering enabled.
The third patch was base on the v1's second patch and only be changed
to query the relaxed ordering enable bit in the PCI configuration space
to allow the Chelsio NIC to send TLPs with the relaxed ordering attributes
set.
This version didn't plan to drop the defines for Intel Drivers to use the
new checking way to enable relaxed ordering because it is not the hardest
part of the moment, we could fix it in next patchset when this patches
reach the goal.
v3: Redesigned the logic for pci_configure_relaxed_ordering when configuration,
If a PCIe device didn't enable the relaxed ordering attribute default,
we should not do anything in the PCIe configuration, otherwise we
should check if any of the devices above us do not support relaxed
ordering by the PCI_DEV_FLAGS_NO_RELAXED_ORDERING flag, then base on
the result if we get a return that indicate that the relaxed ordering
is not supported we should update our device to disable relaxed ordering
in configuration space. If the device above us doesn't exist or isn't
the PCIe device, we shouldn't do anything and skip updating relaxed ordering
because we are probably running in a guest.
v4: Rename the functions pcie_get_relaxed_ordering and pcie_disable_relaxed_ordering
according John's suggestion, and modify the description, use the true/false
as the return value.
We shouldn't enable relaxed ordering attribute by the setting in the root
complex configuration space for PCIe device, so fix it for cxgb4.
Fix some format issues.
Casey Leedom (2):
PCI: Add new PCIe Fabric End Node flag,
PCI_DEV_FLAGS_NO_RELAXED_ORDERING
net/cxgb4: Use new PCI_DEV_FLAGS_NO_RELAXED_ORDERING flag
Ding Tianhong (1):
PCI: Enable PCIe Relaxed Ordering if supported
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 1 +
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 17 ++++++++++
drivers/net/ethernet/chelsio/cxgb4/sge.c | 5 +--
drivers/pci/pci.c | 32 +++++++++++++++++++
drivers/pci/probe.c | 41 +++++++++++++++++++++++++
drivers/pci/quirks.c | 38 +++++++++++++++++++++++
include/linux/pci.h | 4 +++
7 files changed, 136 insertions(+), 2 deletions(-)
--
1.9.0
^ permalink raw reply
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