* [PATCH 1/4] inet: Add skb_copy_datagram_iter
From: Herbert Xu @ 2014-11-04 8:31 UTC (permalink / raw)
To: Al Viro, David S. Miller, netdev, Linux Kernel Mailing List,
Benjamin LaHaise
In-Reply-To: <20141104033818.GA11149@gondor.apana.org.au>
This patch adds skb_copy_datagram_iter, which is identical to
skb_copy_datagram_iovec except that it operates on iov_iter
instead of iovec.
Eventually all users of skb_copy_datagram_iovec should switch
over to iov_iter and then we can remove skb_copy_datagram_iovec.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/linux/skbuff.h | 3 +
net/core/datagram.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 85 insertions(+)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 6c8b6f6..5ff7054 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -148,6 +148,7 @@
struct net_device;
struct scatterlist;
struct pipe_inode_info;
+struct iov_iter;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
struct nf_conntrack {
@@ -2641,6 +2642,8 @@ int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *frm,
int skb_copy_datagram_const_iovec(const struct sk_buff *from, int offset,
const struct iovec *to, int to_offset,
int size);
+int skb_copy_datagram_iter(const struct sk_buff *from, int offset,
+ struct iov_iter *to, int size);
void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb);
int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags);
diff --git a/net/core/datagram.c b/net/core/datagram.c
index fdbc9a8..45a9d4d 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -49,6 +49,7 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
+#include <linux/uio.h>
#include <net/protocol.h>
#include <linux/skbuff.h>
@@ -482,6 +483,87 @@ fault:
EXPORT_SYMBOL(skb_copy_datagram_const_iovec);
/**
+ * skb_copy_datagram_iter - Copy a datagram to an iovec iterator.
+ * @skb: buffer to copy
+ * @offset: offset in the buffer to start copying from
+ * @to: iovec iterator to copy to
+ * @len: amount of data to copy from buffer to iovec
+ */
+int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
+ struct iov_iter *to, int len)
+{
+ int start = skb_headlen(skb);
+ int i, copy = start - offset;
+ struct sk_buff *frag_iter;
+
+ trace_skb_copy_datagram_iovec(skb, len);
+
+ /* Copy header. */
+ if (copy > 0) {
+ if (copy > len)
+ copy = len;
+ if (copy_to_iter(skb->data + offset, copy, to))
+ goto fault;
+ if ((len -= copy) == 0)
+ return 0;
+ offset += copy;
+ }
+
+ /* Copy paged appendix. Hmm... why does this look so complicated? */
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ int end;
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ WARN_ON(start > offset + len);
+
+ end = start + skb_frag_size(frag);
+ if ((copy = end - offset) > 0) {
+ int err;
+ u8 *vaddr;
+ struct page *page = skb_frag_page(frag);
+
+ if (copy > len)
+ copy = len;
+ vaddr = kmap(page);
+ err = copy_to_iter(vaddr + frag->page_offset +
+ offset - start, copy, to);
+ kunmap(page);
+ if (err)
+ goto fault;
+ if (!(len -= copy))
+ return 0;
+ offset += copy;
+ }
+ start = end;
+ }
+
+ skb_walk_frags(skb, frag_iter) {
+ int end;
+
+ WARN_ON(start > offset + len);
+
+ end = start + frag_iter->len;
+ if ((copy = end - offset) > 0) {
+ if (copy > len)
+ copy = len;
+ if (skb_copy_datagram_iter(frag_iter, offset - start,
+ to, copy))
+ goto fault;
+ if ((len -= copy) == 0)
+ return 0;
+ offset += copy;
+ }
+ start = end;
+ }
+ if (!len)
+ return 0;
+
+fault:
+ return -EFAULT;
+}
+EXPORT_SYMBOL(skb_copy_datagram_iter);
+
+/**
* skb_copy_datagram_from_iovec - Copy a datagram from an iovec.
* @skb: buffer to copy
* @offset: offset in the buffer to start copying to
^ permalink raw reply related
* [PATCH 2/4] tun: Use iovec iterators
From: Herbert Xu @ 2014-11-04 8:31 UTC (permalink / raw)
To: Al Viro, David S. Miller, netdev, Linux Kernel Mailing List,
Benjamin LaHaise
In-Reply-To: <20141104033818.GA11149@gondor.apana.org.au>
This patch removes the use of skb_copy_datagram_const_iovec in
favour of the iovec iterator-based skb_copy_datagram_iter.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
drivers/net/tun.c | 65 +++++++++++++++++++++++++-----------------------------
1 file changed, 31 insertions(+), 34 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 9dd3746..cfb81ca 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -71,6 +71,7 @@
#include <net/rtnetlink.h>
#include <net/sock.h>
#include <linux/seq_file.h>
+#include <linux/uio.h>
#include <asm/uaccess.h>
@@ -1230,11 +1231,11 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
static ssize_t tun_put_user(struct tun_struct *tun,
struct tun_file *tfile,
struct sk_buff *skb,
- const struct iovec *iv, int len)
+ struct iov_iter *iter)
{
struct tun_pi pi = { 0, skb->protocol };
- ssize_t total = 0;
- int vlan_offset = 0, copied;
+ ssize_t total;
+ int vlan_offset;
int vlan_hlen = 0;
int vnet_hdr_sz = 0;
@@ -1244,23 +1245,25 @@ static ssize_t tun_put_user(struct tun_struct *tun,
if (tun->flags & TUN_VNET_HDR)
vnet_hdr_sz = tun->vnet_hdr_sz;
+ total = skb->len + vlan_hlen + vnet_hdr_sz;
+
if (!(tun->flags & TUN_NO_PI)) {
- if ((len -= sizeof(pi)) < 0)
+ if (iov_iter_count(iter) < sizeof(pi))
return -EINVAL;
- if (len < skb->len + vlan_hlen + vnet_hdr_sz) {
+ if (iov_iter_count(iter) < total) {
/* Packet will be striped */
pi.flags |= TUN_PKT_STRIP;
}
- if (memcpy_toiovecend(iv, (void *) &pi, 0, sizeof(pi)))
+ if (copy_to_iter(&pi, sizeof(pi), iter))
return -EFAULT;
total += sizeof(pi);
}
if (vnet_hdr_sz) {
struct virtio_net_hdr gso = { 0 }; /* no info leak */
- if ((len -= vnet_hdr_sz) < 0)
+ if (iov_iter_count(iter) < vnet_hdr_sz)
return -EINVAL;
if (skb_is_gso(skb)) {
@@ -1299,17 +1302,12 @@ static ssize_t tun_put_user(struct tun_struct *tun,
gso.flags = VIRTIO_NET_HDR_F_DATA_VALID;
} /* else everything is zero */
- if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total,
- sizeof(gso))))
+ if (copy_to_iter(&gso, sizeof(gso), iter))
return -EFAULT;
- total += vnet_hdr_sz;
}
- copied = total;
- len = min_t(int, skb->len + vlan_hlen, len);
- total += skb->len + vlan_hlen;
if (vlan_hlen) {
- int copy, ret;
+ int ret;
struct {
__be16 h_vlan_proto;
__be16 h_vlan_TCI;
@@ -1320,36 +1318,34 @@ static ssize_t tun_put_user(struct tun_struct *tun,
vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
- copy = min_t(int, vlan_offset, len);
- ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
- len -= copy;
- copied += copy;
- if (ret || !len)
+ ret = skb_copy_datagram_iter(skb, 0, iter, vlan_offset);
+ if (ret || !iov_iter_count(iter))
goto done;
- copy = min_t(int, sizeof(veth), len);
- ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy);
- len -= copy;
- copied += copy;
- if (ret || !len)
+ ret = copy_to_iter(&veth, sizeof(veth), iter);
+ if (ret || !iov_iter_count(iter))
goto done;
+
+ __skb_pull(skb, vlan_offset);
}
- skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
+ skb_copy_datagram_iter(skb, vlan_offset, iter, skb->len - vlan_offset);
done:
tun->dev->stats.tx_packets++;
- tun->dev->stats.tx_bytes += len;
+ tun->dev->stats.tx_bytes += skb->len + vlan_hlen;
return total;
}
static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
- const struct iovec *iv, ssize_t len, int noblock)
+ const struct iovec *iv, unsigned long segs,
+ ssize_t len, int noblock)
{
struct sk_buff *skb;
ssize_t ret = 0;
int peeked, err, off = 0;
+ struct iov_iter iter;
tun_debug(KERN_INFO, tun, "tun_do_read\n");
@@ -1362,11 +1358,12 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
/* Read frames from queue */
skb = __skb_recv_datagram(tfile->socket.sk, noblock ? MSG_DONTWAIT : 0,
&peeked, &off, &err);
- if (skb) {
- ret = tun_put_user(tun, tfile, skb, iv, len);
- kfree_skb(skb);
- } else
- ret = err;
+ if (!skb)
+ return ret;
+
+ iov_iter_init(&iter, READ, iv, segs, len);
+ ret = tun_put_user(tun, tfile, skb, &iter);
+ kfree_skb(skb);
return ret;
}
@@ -1387,7 +1384,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
goto out;
}
- ret = tun_do_read(tun, tfile, iv, len,
+ ret = tun_do_read(tun, tfile, iv, count, len,
file->f_flags & O_NONBLOCK);
ret = min_t(ssize_t, ret, len);
if (ret > 0)
@@ -1488,7 +1485,7 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
SOL_PACKET, TUN_TX_TIMESTAMP);
goto out;
}
- ret = tun_do_read(tun, tfile, m->msg_iov, total_len,
+ ret = tun_do_read(tun, tfile, m->msg_iov, m->msg_iovlen, total_len,
flags & MSG_DONTWAIT);
if (ret > total_len) {
m->msg_flags |= MSG_TRUNC;
^ permalink raw reply related
* [PATCH 4/4] net: Kill skb_copy_datagram_const_iovec
From: Herbert Xu @ 2014-11-04 8:31 UTC (permalink / raw)
To: Al Viro, David S. Miller, netdev, Linux Kernel Mailing List,
Benjamin LaHaise
In-Reply-To: <20141104033818.GA11149@gondor.apana.org.au>
Now that both macvtap and tun are using skb_copy_datagram_iter, we
can kill the abomination that is skb_copy_datagram_const_iovec.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/linux/skbuff.h | 3 -
net/core/datagram.c | 89 -------------------------------------------------
2 files changed, 92 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 5ff7054..dfd8623 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2639,9 +2639,6 @@ int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset,
int len);
int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *frm,
int offset, size_t count);
-int skb_copy_datagram_const_iovec(const struct sk_buff *from, int offset,
- const struct iovec *to, int to_offset,
- int size);
int skb_copy_datagram_iter(const struct sk_buff *from, int offset,
struct iov_iter *to, int size);
void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 45a9d4d..93054b9 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -394,95 +394,6 @@ fault:
EXPORT_SYMBOL(skb_copy_datagram_iovec);
/**
- * skb_copy_datagram_const_iovec - Copy a datagram to an iovec.
- * @skb: buffer to copy
- * @offset: offset in the buffer to start copying from
- * @to: io vector to copy to
- * @to_offset: offset in the io vector to start copying to
- * @len: amount of data to copy from buffer to iovec
- *
- * Returns 0 or -EFAULT.
- * Note: the iovec is not modified during the copy.
- */
-int skb_copy_datagram_const_iovec(const struct sk_buff *skb, int offset,
- const struct iovec *to, int to_offset,
- int len)
-{
- int start = skb_headlen(skb);
- int i, copy = start - offset;
- struct sk_buff *frag_iter;
-
- /* Copy header. */
- if (copy > 0) {
- if (copy > len)
- copy = len;
- if (memcpy_toiovecend(to, skb->data + offset, to_offset, copy))
- goto fault;
- if ((len -= copy) == 0)
- return 0;
- offset += copy;
- to_offset += copy;
- }
-
- /* Copy paged appendix. Hmm... why does this look so complicated? */
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- int end;
- const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
- WARN_ON(start > offset + len);
-
- end = start + skb_frag_size(frag);
- if ((copy = end - offset) > 0) {
- int err;
- u8 *vaddr;
- struct page *page = skb_frag_page(frag);
-
- if (copy > len)
- copy = len;
- vaddr = kmap(page);
- err = memcpy_toiovecend(to, vaddr + frag->page_offset +
- offset - start, to_offset, copy);
- kunmap(page);
- if (err)
- goto fault;
- if (!(len -= copy))
- return 0;
- offset += copy;
- to_offset += copy;
- }
- start = end;
- }
-
- skb_walk_frags(skb, frag_iter) {
- int end;
-
- WARN_ON(start > offset + len);
-
- end = start + frag_iter->len;
- if ((copy = end - offset) > 0) {
- if (copy > len)
- copy = len;
- if (skb_copy_datagram_const_iovec(frag_iter,
- offset - start,
- to, to_offset,
- copy))
- goto fault;
- if ((len -= copy) == 0)
- return 0;
- offset += copy;
- to_offset += copy;
- }
- start = end;
- }
- if (!len)
- return 0;
-
-fault:
- return -EFAULT;
-}
-EXPORT_SYMBOL(skb_copy_datagram_const_iovec);
-
-/**
* skb_copy_datagram_iter - Copy a datagram to an iovec iterator.
* @skb: buffer to copy
* @offset: offset in the buffer to start copying from
^ permalink raw reply related
* [PATCH 3/4] macvtap: Use iovec iterators
From: Herbert Xu @ 2014-11-04 8:31 UTC (permalink / raw)
To: Al Viro, David S. Miller, netdev, Linux Kernel Mailing List,
Benjamin LaHaise
In-Reply-To: <20141104033818.GA11149@gondor.apana.org.au>
This patch removes the use of skb_copy_datagram_const_iovec in
favour of the iovec iterator-based skb_copy_datagram_iter.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
drivers/net/macvtap.c | 45 ++++++++++++++++++++-------------------------
1 file changed, 20 insertions(+), 25 deletions(-)
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 880cc09..a0e1dd7 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -15,6 +15,7 @@
#include <linux/cdev.h>
#include <linux/idr.h>
#include <linux/fs.h>
+#include <linux/uio.h>
#include <net/ipv6.h>
#include <net/net_namespace.h>
@@ -778,31 +779,28 @@ static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv,
/* Put packet to the user space buffer */
static ssize_t macvtap_put_user(struct macvtap_queue *q,
const struct sk_buff *skb,
- const struct iovec *iv, int len)
+ struct iov_iter *iter)
{
int ret;
int vnet_hdr_len = 0;
int vlan_offset = 0;
- int copied, total;
+ int total;
if (q->flags & IFF_VNET_HDR) {
struct virtio_net_hdr vnet_hdr;
vnet_hdr_len = q->vnet_hdr_sz;
- if ((len -= vnet_hdr_len) < 0)
+ if (iov_iter_count(iter) < vnet_hdr_len)
return -EINVAL;
macvtap_skb_to_vnet_hdr(skb, &vnet_hdr);
- if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr)))
+ if (copy_to_iter(&vnet_hdr, sizeof(vnet_hdr), iter))
return -EFAULT;
}
- total = copied = vnet_hdr_len;
+ total = vnet_hdr_len;
total += skb->len;
- if (!vlan_tx_tag_present(skb))
- len = min_t(int, skb->len, len);
- else {
- int copy;
+ if (vlan_tx_tag_present(skb)) {
struct {
__be16 h_vlan_proto;
__be16 h_vlan_TCI;
@@ -811,37 +809,33 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb));
vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
- len = min_t(int, skb->len + VLAN_HLEN, len);
total += VLAN_HLEN;
- copy = min_t(int, vlan_offset, len);
- ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
- len -= copy;
- copied += copy;
- if (ret || !len)
+ ret = skb_copy_datagram_iter(skb, 0, iter, vlan_offset);
+ if (ret || !iov_iter_count(iter))
goto done;
- copy = min_t(int, sizeof(veth), len);
- ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy);
- len -= copy;
- copied += copy;
- if (ret || !len)
+ ret = copy_to_iter(&veth, sizeof(veth), iter);
+ if (ret || !iov_iter_count(iter))
goto done;
}
- ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
+ ret = skb_copy_datagram_iter(skb, vlan_offset, iter,
+ skb->len - vlan_offset);
done:
return ret ? ret : total;
}
static ssize_t macvtap_do_read(struct macvtap_queue *q,
- const struct iovec *iv, unsigned long len,
+ const struct iovec *iv, unsigned long segs,
+ unsigned long len,
int noblock)
{
DEFINE_WAIT(wait);
struct sk_buff *skb;
ssize_t ret = 0;
+ struct iov_iter iter;
while (len) {
if (!noblock)
@@ -863,7 +857,8 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q,
schedule();
continue;
}
- ret = macvtap_put_user(q, skb, iv, len);
+ iov_iter_init(&iter, READ, iv, segs, len);
+ ret = macvtap_put_user(q, skb, &iter);
kfree_skb(skb);
break;
}
@@ -886,7 +881,7 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv,
goto out;
}
- ret = macvtap_do_read(q, iv, len, file->f_flags & O_NONBLOCK);
+ ret = macvtap_do_read(q, iv, count, len, file->f_flags & O_NONBLOCK);
ret = min_t(ssize_t, ret, len);
if (ret > 0)
iocb->ki_pos = ret;
@@ -1117,7 +1112,7 @@ static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock,
int ret;
if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))
return -EINVAL;
- ret = macvtap_do_read(q, m->msg_iov, total_len,
+ ret = macvtap_do_read(q, m->msg_iov, m->msg_iovlen, total_len,
flags & MSG_DONTWAIT);
if (ret > total_len) {
m->msg_flags |= MSG_TRUNC;
^ permalink raw reply related
* Re: [PATCH 2/4] tun: Use iovec iterators
From: Herbert Xu @ 2014-11-04 8:37 UTC (permalink / raw)
To: Al Viro, David S. Miller, netdev, Linux Kernel Mailing List,
Benjamin LaHaise
In-Reply-To: <E1XlZWY-0003Hk-Qu@gondolin.me.apana.org.au>
Oops, this patch had a left-over skb_pull which made it broken.
Here is a fixed version.
tun: Use iovec iterators
This patch removes the use of skb_copy_datagram_const_iovec in
favour of the iovec iterator-based skb_copy_datagram_iter.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 9dd3746..ff955cdb 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -71,6 +71,7 @@
#include <net/rtnetlink.h>
#include <net/sock.h>
#include <linux/seq_file.h>
+#include <linux/uio.h>
#include <asm/uaccess.h>
@@ -1230,11 +1231,11 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
static ssize_t tun_put_user(struct tun_struct *tun,
struct tun_file *tfile,
struct sk_buff *skb,
- const struct iovec *iv, int len)
+ struct iov_iter *iter)
{
struct tun_pi pi = { 0, skb->protocol };
- ssize_t total = 0;
- int vlan_offset = 0, copied;
+ ssize_t total;
+ int vlan_offset;
int vlan_hlen = 0;
int vnet_hdr_sz = 0;
@@ -1244,23 +1245,25 @@ static ssize_t tun_put_user(struct tun_struct *tun,
if (tun->flags & TUN_VNET_HDR)
vnet_hdr_sz = tun->vnet_hdr_sz;
+ total = skb->len + vlan_hlen + vnet_hdr_sz;
+
if (!(tun->flags & TUN_NO_PI)) {
- if ((len -= sizeof(pi)) < 0)
+ if (iov_iter_count(iter) < sizeof(pi))
return -EINVAL;
- if (len < skb->len + vlan_hlen + vnet_hdr_sz) {
+ if (iov_iter_count(iter) < total) {
/* Packet will be striped */
pi.flags |= TUN_PKT_STRIP;
}
- if (memcpy_toiovecend(iv, (void *) &pi, 0, sizeof(pi)))
+ if (copy_to_iter(&pi, sizeof(pi), iter))
return -EFAULT;
total += sizeof(pi);
}
if (vnet_hdr_sz) {
struct virtio_net_hdr gso = { 0 }; /* no info leak */
- if ((len -= vnet_hdr_sz) < 0)
+ if (iov_iter_count(iter) < vnet_hdr_sz)
return -EINVAL;
if (skb_is_gso(skb)) {
@@ -1299,17 +1302,12 @@ static ssize_t tun_put_user(struct tun_struct *tun,
gso.flags = VIRTIO_NET_HDR_F_DATA_VALID;
} /* else everything is zero */
- if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total,
- sizeof(gso))))
+ if (copy_to_iter(&gso, sizeof(gso), iter))
return -EFAULT;
- total += vnet_hdr_sz;
}
- copied = total;
- len = min_t(int, skb->len + vlan_hlen, len);
- total += skb->len + vlan_hlen;
if (vlan_hlen) {
- int copy, ret;
+ int ret;
struct {
__be16 h_vlan_proto;
__be16 h_vlan_TCI;
@@ -1320,36 +1318,32 @@ static ssize_t tun_put_user(struct tun_struct *tun,
vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
- copy = min_t(int, vlan_offset, len);
- ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
- len -= copy;
- copied += copy;
- if (ret || !len)
+ ret = skb_copy_datagram_iter(skb, 0, iter, vlan_offset);
+ if (ret || !iov_iter_count(iter))
goto done;
- copy = min_t(int, sizeof(veth), len);
- ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy);
- len -= copy;
- copied += copy;
- if (ret || !len)
+ ret = copy_to_iter(&veth, sizeof(veth), iter);
+ if (ret || !iov_iter_count(iter))
goto done;
}
- skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
+ skb_copy_datagram_iter(skb, vlan_offset, iter, skb->len - vlan_offset);
done:
tun->dev->stats.tx_packets++;
- tun->dev->stats.tx_bytes += len;
+ tun->dev->stats.tx_bytes += skb->len + vlan_hlen;
return total;
}
static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
- const struct iovec *iv, ssize_t len, int noblock)
+ const struct iovec *iv, unsigned long segs,
+ ssize_t len, int noblock)
{
struct sk_buff *skb;
ssize_t ret = 0;
int peeked, err, off = 0;
+ struct iov_iter iter;
tun_debug(KERN_INFO, tun, "tun_do_read\n");
@@ -1362,11 +1356,12 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
/* Read frames from queue */
skb = __skb_recv_datagram(tfile->socket.sk, noblock ? MSG_DONTWAIT : 0,
&peeked, &off, &err);
- if (skb) {
- ret = tun_put_user(tun, tfile, skb, iv, len);
- kfree_skb(skb);
- } else
- ret = err;
+ if (!skb)
+ return ret;
+
+ iov_iter_init(&iter, READ, iv, segs, len);
+ ret = tun_put_user(tun, tfile, skb, &iter);
+ kfree_skb(skb);
return ret;
}
@@ -1387,7 +1382,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
goto out;
}
- ret = tun_do_read(tun, tfile, iv, len,
+ ret = tun_do_read(tun, tfile, iv, count, len,
file->f_flags & O_NONBLOCK);
ret = min_t(ssize_t, ret, len);
if (ret > 0)
@@ -1488,7 +1483,7 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
SOL_PACKET, TUN_TX_TIMESTAMP);
goto out;
}
- ret = tun_do_read(tun, tfile, m->msg_iov, total_len,
+ ret = tun_do_read(tun, tfile, m->msg_iov, m->msg_iovlen, total_len,
flags & MSG_DONTWAIT);
if (ret > total_len) {
m->msg_flags |= MSG_TRUNC;
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related
* Re: [PATCH v2 5/5] stmmac: pci: remove FSF address
From: Andy Shevchenko @ 2014-11-04 9:06 UTC (permalink / raw)
To: David Miller
Cc: peppe.cavallaro, netdev, hock.leong.kweh, vbridgers2013, rayagond
In-Reply-To: <20141103.155708.1102581898193715225.davem@davemloft.net>
On Mon, 2014-11-03 at 15:57 -0500, David Miller wrote:
> From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Date: Mon, 3 Nov 2014 15:02:17 +0200
>
> > The FSF address is subject to change, thus remove it from the file.
> >
> > Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>
> I cound 90t instances of this under drivers/net, therefore if this change is
> appropriate
Can't find fast the discussion, but there is the commit
4783f894d0f3bfb107cf3b1d9aed1f1a0672ee1d "checkpatch.pl: check for the
FSF mailing address".
> I'd rather someone script this and kill it across entire
> subdirectories.
I'm okay if you don't apply this patch now.
--
Andy Shevchenko <andriy.shevchenko@intel.com>
Intel Finland Oy
^ permalink raw reply
* Re: [PATCH 7/7] can: m_can: workaround for transmit data less than 4 bytes
From: Marc Kleine-Budde @ 2014-11-04 9:22 UTC (permalink / raw)
To: Dong Aisheng
Cc: linux-can, wg, varkabhadram, netdev, socketcan, linux-arm-kernel
In-Reply-To: <20141104082505.GA8060@shlinux1.ap.freescale.net>
[-- Attachment #1: Type: text/plain, Size: 5683 bytes --]
On 11/04/2014 09:25 AM, Dong Aisheng wrote:
>>> We meet an IC issue that we have to write the full 8 bytes (whatever
>>> value for the second word) in Message RAM to avoid bit error for transmit
>>> data less than 4 bytes.
>>
>> Is this a SoC or a m_can problem? Are all versions of the SoC/m_can
>> affected? Is there a m_can version register somewhere?
> I'm still not sure it's SoC or m_can problem.
> Our IC guys ran the simulation code and found this issue.
> But due to some reasons, it may be very slow for they to investigate
> and get the conclusion.
Let's hope they will find the root cause of this problem.
>>> Without the workaround, we can easily see the following errors:
>>> root@imx6qdlsolo:~# ip link set can0 up type can bitrate 1000000
>>> [ 66.882520] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready
>>> root@imx6qdlsolo:~# cansend can0 123#112233
>>> [ 66.935640] m_can 20e8000.can can0: Bit Error Uncorrected
>>>
>>> Signed-off-by: Dong Aisheng <b29396@freescale.com>
>>> ---
>>> drivers/net/can/m_can/m_can.c | 11 ++++++++++-
>>> 1 file changed, 10 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
>>> index 219e0e3..f2d9ebe 100644
>>> --- a/drivers/net/can/m_can/m_can.c
>>> +++ b/drivers/net/can/m_can/m_can.c
>>> @@ -1058,10 +1058,19 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
>>> m_can_fifo_write(priv, 0, M_CAN_FIFO_ID, id);
>>> m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, can_len2dlc(cf->len) << 16);
>>>
>>> - for (i = 0; i < cf->len; i += 4)
>>> + for (i = 0; i < cf->len; i += 4) {
>>> m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(i / 4),
>>> *(u32 *)(cf->data + i));
>>>
>>> + /* FIXME: we meet an IC issue that we have to write the full 8
>>
>> FIXME usually indicates that the driver needs some work here. Just
>> describe your hardware bug, you might add a reference to an errata if
>> available, though.
>
> We don't have an errata for it now.
> Because i'm not sure this is the final workaround and also not sure if other
> SoC vendors having the same issue, so i used FIXME here firstly.
> Since the code is harmless, so i wish we could put it here first
> until we find evidence no need for other SoC or only belong to specific
> IP version.
It's better to write this in the comment than a FIXME, which is much
harder to interpret....
>>> + * bytes (whatever value for the second word) in Message RAM to
>>> + * avoid bit error for transmit data less than 4 bytes
>>> + */
>>> + if (cf->len <= 4)
>>> + m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(i / 4 + 1),
>>> + 0x0);
>>
>> This workaround doesn't handle the dlc == 0 case, your error description
>> isn't completely if this is a problem, too.
> You're right.
> I just checked the dlc == 0 case also had such issue and it also needs
> the extra 8 bytes write to avoid such issue.
>
> BTW the issue only happened on the first time when you send a frame with no
> data(dlc == 0) at the first time.
> e.g.
> root@imx6sxsabresd:~# ip link set can0 up type can bitrate 1000000
> [ 62.326014] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready
> root@imx6sxsabresd:~# cansend can0 123#R
> [ 69.233645] m_can 20e8000.can can0: Bit Error Uncorrected
> [ 69.239167] m_can 20e8000.can can0: Bit Error Corrected
>
> If we send a frame success first (e.g. 5 bytes data), it will not fail
> again even you send no data frame (dlc == 0) later.
>
> The former failure of sending data less than 4 bytes is similar.
>
> Looks like the first 8 bytes of message ram has to be initialised
> for the first using.
What about putting
/* errata description goes here */
m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0), 0x0);
m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1), 0x0);
into the open() function? Can you ask the hardware colleges if this is a
functional workaround.
>> It should be possible to change the for loop to go always to 8, or
>> simply unroll the loop:
>>
>> /* errata description goes here */
>> m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0), *(u32 *)(cf->data + 0));
>> m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1), *(u32 *)(cf->data + 4));
>>
>
> Yes, i tried to fix it as follows.
>
> /* FIXME: we meet an IC issue that we have to write the full 8
> * bytes (whatever value for the second word) in Message RAM to
> * avoid bit error for transmit data less than 4 bytes
> */
> if (cf->len <= 4) {
> m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0),
> *(u32 *)(cf->data + 0));
> m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1),
> *(u32 *)(cf->data + 4));
> } else {
> for (i = 0; i < cf->len; i += 4)
> m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(i / 4),
> *(u32 *)(cf->data + i));
>
> Will update the patch.
Both branches of the above if are doing the same thing, I think you can
replace the while if ... else ... for with this:
/* errata description goes here */
m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0), *(u32 *)(cf->data + 0));
m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1), *(u32 *)(cf->data + 4));
However if writing to DATA(0) and DATA(1) once in the open() function is
enough this code should stay as it is.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* Re: [PATCH net-next 1/7] bpf: add 'flags' attribute to BPF_MAP_UPDATE_ELEM command
From: Daniel Borkmann @ 2014-11-04 9:25 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: David S. Miller, Ingo Molnar, Andy Lutomirski,
Hannes Frederic Sowa, Eric Dumazet, linux-api, netdev,
linux-kernel
In-Reply-To: <1415069656-14138-2-git-send-email-ast@plumgrid.com>
On 11/04/2014 03:54 AM, Alexei Starovoitov wrote:
> the current meaning of BPF_MAP_UPDATE_ELEM syscall command is:
> either update existing map element or create a new one.
> Initially the plan was to add a new command to handle the case of
> 'create new element if it didn't exist', but 'flags' style looks
> cleaner and overall diff is much smaller (more code reused), so add 'flags'
> attribute to BPF_MAP_UPDATE_ELEM command with the following meaning:
> enum {
> BPF_MAP_UPDATE_OR_CREATE = 0, /* add new element or update existing */
> BPF_MAP_CREATE_ONLY, /* add new element if it didn't exist */
> BPF_MAP_UPDATE_ONLY /* update existing element */
> };
From you commit message/code I currently don't see an explanation why
it cannot be done in typical ``flags style'' as various syscalls do,
i.e. BPF_MAP_UPDATE_OR_CREATE rather represented as ...
BPF_MAP_CREATE | BPF_MAP_UPDATE
Do you expect more than 64 different flags to be passed from user space
for BPF_MAP?
> BPF_MAP_CREATE_ONLY can fail with EEXIST if element already exists.
> BPF_MAP_UPDATE_ONLY can fail with ENOENT if element doesn't exist.
>
> Userspace will call it as:
> int bpf_update_elem(int fd, void *key, void *value, __u64 flags)
> {
> union bpf_attr attr = {
> .map_fd = fd,
> .key = ptr_to_u64(key),
> .value = ptr_to_u64(value),
> .flags = flags;
> };
>
> return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
> }
>
> Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
^ permalink raw reply
* Re: [PATCH 7/7] can: m_can: workaround for transmit data less than 4 bytes
From: Dong Aisheng @ 2014-11-04 9:27 UTC (permalink / raw)
To: Marc Kleine-Budde
Cc: linux-can, wg, varkabhadram, netdev, socketcan, linux-arm-kernel
In-Reply-To: <54589AC8.4010106@pengutronix.de>
On Tue, Nov 04, 2014 at 10:22:16AM +0100, Marc Kleine-Budde wrote:
> On 11/04/2014 09:25 AM, Dong Aisheng wrote:
> >>> We meet an IC issue that we have to write the full 8 bytes (whatever
> >>> value for the second word) in Message RAM to avoid bit error for transmit
> >>> data less than 4 bytes.
> >>
> >> Is this a SoC or a m_can problem? Are all versions of the SoC/m_can
> >> affected? Is there a m_can version register somewhere?
>
> > I'm still not sure it's SoC or m_can problem.
> > Our IC guys ran the simulation code and found this issue.
> > But due to some reasons, it may be very slow for they to investigate
> > and get the conclusion.
>
> Let's hope they will find the root cause of this problem.
>
> >>> Without the workaround, we can easily see the following errors:
> >>> root@imx6qdlsolo:~# ip link set can0 up type can bitrate 1000000
> >>> [ 66.882520] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready
> >>> root@imx6qdlsolo:~# cansend can0 123#112233
> >>> [ 66.935640] m_can 20e8000.can can0: Bit Error Uncorrected
> >>>
> >>> Signed-off-by: Dong Aisheng <b29396@freescale.com>
> >>> ---
> >>> drivers/net/can/m_can/m_can.c | 11 ++++++++++-
> >>> 1 file changed, 10 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
> >>> index 219e0e3..f2d9ebe 100644
> >>> --- a/drivers/net/can/m_can/m_can.c
> >>> +++ b/drivers/net/can/m_can/m_can.c
> >>> @@ -1058,10 +1058,19 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
> >>> m_can_fifo_write(priv, 0, M_CAN_FIFO_ID, id);
> >>> m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, can_len2dlc(cf->len) << 16);
> >>>
> >>> - for (i = 0; i < cf->len; i += 4)
> >>> + for (i = 0; i < cf->len; i += 4) {
> >>> m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(i / 4),
> >>> *(u32 *)(cf->data + i));
> >>>
> >>> + /* FIXME: we meet an IC issue that we have to write the full 8
> >>
> >> FIXME usually indicates that the driver needs some work here. Just
> >> describe your hardware bug, you might add a reference to an errata if
> >> available, though.
> >
> > We don't have an errata for it now.
> > Because i'm not sure this is the final workaround and also not sure if other
> > SoC vendors having the same issue, so i used FIXME here firstly.
> > Since the code is harmless, so i wish we could put it here first
> > until we find evidence no need for other SoC or only belong to specific
> > IP version.
>
> It's better to write this in the comment than a FIXME, which is much
> harder to interpret....
>
> >>> + * bytes (whatever value for the second word) in Message RAM to
> >>> + * avoid bit error for transmit data less than 4 bytes
> >>> + */
> >>> + if (cf->len <= 4)
> >>> + m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(i / 4 + 1),
> >>> + 0x0);
> >>
> >> This workaround doesn't handle the dlc == 0 case, your error description
> >> isn't completely if this is a problem, too.
>
> > You're right.
> > I just checked the dlc == 0 case also had such issue and it also needs
> > the extra 8 bytes write to avoid such issue.
> >
> > BTW the issue only happened on the first time when you send a frame with no
> > data(dlc == 0) at the first time.
> > e.g.
> > root@imx6sxsabresd:~# ip link set can0 up type can bitrate 1000000
> > [ 62.326014] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready
> > root@imx6sxsabresd:~# cansend can0 123#R
> > [ 69.233645] m_can 20e8000.can can0: Bit Error Uncorrected
> > [ 69.239167] m_can 20e8000.can can0: Bit Error Corrected
> >
> > If we send a frame success first (e.g. 5 bytes data), it will not fail
> > again even you send no data frame (dlc == 0) later.
> >
> > The former failure of sending data less than 4 bytes is similar.
> >
> > Looks like the first 8 bytes of message ram has to be initialised
> > for the first using.
>
> What about putting
>
> /* errata description goes here */
> m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0), 0x0);
> m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1), 0x0);
>
> into the open() function? Can you ask the hardware colleges if this is a
> functional workaround.
>
> >> It should be possible to change the for loop to go always to 8, or
> >> simply unroll the loop:
> >>
> >> /* errata description goes here */
> >> m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0), *(u32 *)(cf->data + 0));
> >> m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1), *(u32 *)(cf->data + 4));
> >>
> >
> > Yes, i tried to fix it as follows.
> >
> > /* FIXME: we meet an IC issue that we have to write the full 8
> > * bytes (whatever value for the second word) in Message RAM to
> > * avoid bit error for transmit data less than 4 bytes
> > */
> > if (cf->len <= 4) {
> > m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0),
> > *(u32 *)(cf->data + 0));
> > m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1),
> > *(u32 *)(cf->data + 4));
> > } else {
> > for (i = 0; i < cf->len; i += 4)
> > m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(i / 4),
> > *(u32 *)(cf->data + i));
> >
> > Will update the patch.
>
> Both branches of the above if are doing the same thing, I think you can
> replace the while if ... else ... for with this:
>
Not the same thing.
The later one will cover payload up to 64 bytes.
> /* errata description goes here */
> m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0), *(u32 *)(cf->data + 0));
> m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1), *(u32 *)(cf->data + 4));
>
> However if writing to DATA(0) and DATA(1) once in the open() function is
> enough this code should stay as it is.
I tried put them into open() function and the quick test showed it worked.
Do you think it's ok to put things into open() function for this issue
as follows?
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 065e4f1..ca55988 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -901,6 +901,15 @@ static void m_can_chip_config(struct net_device *dev)
/* set bittiming params */
m_can_set_bittiming(dev);
+ /* We meet an IC issue that we have to write the full 8
+ * bytes (whatever value for the second word) in Message RAM to
+ * avoid bit error for transmit data less than 4 bytes at the first
+ * time. By initializing the first 8 bytes of tx buffer before using
+ * it can avoid such issue.
+ */
+ m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0), 0x0);
+ m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1), 0x0);
+
m_can_config_endisable(priv, false);
}
Regards
Dong Aisheng
>
> Marc
> --
> Pengutronix e.K. | Marc Kleine-Budde |
> Industrial Linux Solutions | Phone: +49-231-2826-924 |
> Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
> Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
>
^ permalink raw reply related
* Re: [PATCH v1 1/2] dtb: xgene: fix: Disable 10GbE and SGMII based 1GbE by default
From: Arnd Bergmann @ 2014-11-04 9:40 UTC (permalink / raw)
To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Iyappan Subramanian,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, netdev,
patches, Keyur Chudgar, David Miller
In-Reply-To: <CAKh23FkVrPdCuR6dn1S4RvW14_f4Xq8MWaChUh9DyVp44kVtSg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Monday 03 November 2014 11:45:44 Iyappan Subramanian wrote:
>
> On Thu, Oct 30, 2014 at 3:13 AM, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> > On Wednesday 29 October 2014 17:56:19 Iyappan Subramanian wrote:
> >> @@ -621,7 +621,7 @@
> >> };
> >> };
> >>
> >> - sgenet0: ethernet@1f210000 {
> >> + sgenet0: sgenet@1f210000 {
> >> compatible = "apm,xgene-enet";
> >> status = "disabled";
> >> reg = <0x0 0x1f210000 0x0 0x10000>,
> >>
> >
> > This looks like you accidentally reverted a bug fix made earlier.
> > Network devices should always have the name 'ethernet@...'.
>
> Thanks for the review. Since our firmware was patching the dtb, based
> on the node-name, we thought by changing node-name, we can avoid the
> patching and maintain backward compatibility.
>
> Now we know that network devices should have 'ethernet@...', we will
> handle the backward compatibility in a different way and will post the
> patch v2 shortly.
It's not important enough to break backwards compatibility over this.
If you can't find a better way to handle compatibility with the old
firmware, just add a comment explaining the node name.
Arnd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 1/1] ip-link: in human readable output use dynamic precision length
From: Christian Hesse @ 2014-11-04 9:39 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev, Christian Hesse
Now that we use floating point numbers for human readable output we can
calculate precision length on the fly.
---
ip/ipaddress.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index e240bb5..0ddcb0d 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -343,8 +343,8 @@ static void print_num(FILE *fp, unsigned width, uint64_t count)
++prefix;
}
- snprintf(buf, sizeof(buf), "%.1f%c%s", (double) count / powi,
- *prefix, use_iec ? "i" : "");
+ snprintf(buf, sizeof(buf), "%.*f%c%s", 3 - snprintf(NULL, 0, "%"PRIu64, count / powi),
+ (double) count / powi, *prefix, use_iec ? "i" : "");
fprintf(fp, "%-*s ", width, buf);
}
--
2.1.3
^ permalink raw reply related
* Re: "asix: Don't reset PHY on if_up for ASIX 88772" breaks net on arndale platform
From: Riku Voipio @ 2014-11-04 9:43 UTC (permalink / raw)
To: Stam, Michel [FINT]
Cc: Riku Voipio, davem, linux-usb, netdev, linux-kernel,
linux-samsung-soc, ckeepax
In-Reply-To: <C89EFD3CD56F64468D3D206D683A8D2203985F49@ldam-msx2.fugro-nl.local>
On Tue, Nov 04, 2014 at 09:19:26AM +0100, Stam, Michel [FINT] wrote:
> Interesting, as the commit itself is a revert from a kernel back to 2.6
> somewhere. The problem I had is related to the PHY being reset on
> interface-up, can you confirm that you require this?
I can't confirm what exactly is needed on arndale. I'm neither expert in
USB or ethernet. However, I can confirm that without the PHY reset,
networking doesn't work on arndale.
I now see someone else has the same problem, adding Charles to CC.
http://www.spinics.net/lists/linux-usb/msg116656.html
> Reverting this
> breaks ethtool support in turn.
Fixing a bug (ethtool support) must not cause breakage elsewhere (in
this case on arndale). This is now a regression of functionality from
3.17.
I think it would better to revert the change now and with less hurry
introduce a ethtool fix that doesn't break arndale.
> Kind regards,
>
> Michel Stam
>
> -----Original Message-----
> From: Riku Voipio [mailto:riku.voipio@iki.fi]
> Sent: Tuesday, November 04, 2014 8:23 AM
> To: davem@davemloft.net; Stam, Michel [FINT]
> Cc: linux-usb@vger.kernel.org; netdev@vger.kernel.org;
> linux-kernel@vger.kernel.org; linux-samsung-soc@vger.kernel.org
> Subject: "asix: Don't reset PHY on if_up for ASIX 88772" breaks net on
> arndale platform
>
> Hi,
>
> With 3.18-rc3, asix on arndale (samsung exynos 5250 based board), fails
> to work. Interface is initialized but network traffic seem not to pass
> through. With kernel IP config the result looks like:
>
> [ 3.323275] usb 3-3.2.4: new high-speed USB device number 4 using
> exynos-ehci
> [ 3.419151] usb 3-3.2.4: New USB device found, idVendor=0b95,
> idProduct=772a
> [ 3.424735] usb 3-3.2.4: New USB device strings: Mfr=1, Product=2,
> SerialNumber=3
> [ 3.432196] usb 3-3.2.4: Product: AX88772
> [ 3.436279] usb 3-3.2.4: Manufacturer: ASIX Elec. Corp.
> [ 3.441486] usb 3-3.2.4: SerialNumber: 000001
> [ 3.447530] asix 3-3.2.4:1.0 (unnamed net_device) (uninitialized):
> invalid hw address, using random
> [ 3.764352] asix 3-3.2.4:1.0 eth0: register 'asix' at
> usb-12110000.usb-3.2.4, ASIX AX88772 USB 2.0 Ethernet, de:a2:66:bf:ca:4f
> [ 4.488773] asix 3-3.2.4:1.0 eth0: link down
> [ 5.690025] asix 3-3.2.4:1.0 eth0: link up, 100Mbps, full-duplex, lpa
> 0xC5E1
> [ 5.712947] Sending DHCP requests ...... timed out!
> [ 83.165303] IP-Config: Retrying forever (NFS root)...
> [ 83.170397] asix 3-3.2.4:1.0 eth0: link up, 100Mbps, full-duplex, lpa
> 0xC5E1
> [ 83.192944] Sending DHCP requests .....
>
> Similar results also with dhclient. Git bisect identified the breaking
> commit as:
>
> commit 3cc81d85ee01e5a0b7ea2f4190e2ed1165f53c31
> Author: Michel Stam <m.stam@fugro.nl>
> Date: Thu Oct 2 10:22:02 2014 +0200
>
> asix: Don't reset PHY on if_up for ASIX 88772
>
> Taking 3.18-rc3 and that commit reverted, network works again:
>
> [ 3.303500] usb 3-3.2.4: new high-speed USB device number 4 using
> exynos-ehci
> [ 3.399375] usb 3-3.2.4: New USB device found, idVendor=0b95,
> idProduct=772a
> [ 3.404963] usb 3-3.2.4: New USB device strings: Mfr=1, Product=2,
> SerialNumber=3
> [ 3.412424] usb 3-3.2.4: Product: AX88772
> [ 3.416508] usb 3-3.2.4: Manufacturer: ASIX Elec. Corp.
> [ 3.421715] usb 3-3.2.4: SerialNumber: 000001
> [ 3.427755] asix 3-3.2.4:1.0 (unnamed net_device) (uninitialized):
> invalid hw address, using random
> [ 3.744837] asix 3-3.2.4:1.0 eth0: register 'asix' at
> usb-12110000.usb-3.2.4, ASIX AX88772 USB 2.0 Ethernet, 12:59:f1:a8:43:90
> [ 7.098998] asix 3-3.2.4:1.0 eth0: link up, 100Mbps, full-duplex, lpa
> 0xC5E1
> [ 7.118258] Sending DHCP requests ., OK
> [ 9.753259] IP-Config: Got DHCP answer from 192.168.1.1, my address
> is 192.168.1.111
>
> There might something wrong on the samsung platform code (I understand
> the USB on arndale is "funny"), but this is still an regression from
> 3.17.
>
> Riku
^ permalink raw reply
* Re: [PATCH net-next 6/7] bpf: allow eBPF programs to use maps
From: Daniel Borkmann @ 2014-11-04 9:50 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: David S. Miller, Ingo Molnar, Andy Lutomirski,
Hannes Frederic Sowa, Eric Dumazet,
linux-api-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1415069656-14138-7-git-send-email-ast-uqk4Ao+rVK5Wk0Htik3J/w@public.gmane.org>
On 11/04/2014 03:54 AM, Alexei Starovoitov wrote:
> expose bpf_map_lookup_elem(), bpf_map_update_elem(), bpf_map_delete_elem()
> map accessors to eBPF programs
>
> Signed-off-by: Alexei Starovoitov <ast-uqk4Ao+rVK5Wk0Htik3J/w@public.gmane.org>
...
> +#include <linux/bpf.h>
> +#include <linux/rcupdate.h>
> +
> +/* called from eBPF program under rcu lock
> + *
> + * if kernel subsystem is allowing eBPF programs to call this function,
> + * inside its own verifier_ops->get_func_proto() callback it should return
> + * bpf_map_lookup_elem_proto, so that verifier can properly checks the arguments
> + */
> +static u64 bpf_map_lookup_elem(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
> +{
> + /* verifier checked that R1 contains a valid pointer to bpf_map
> + * and R2 points to a program stack and map->key_size bytes were
> + * initialized
> + */
> + struct bpf_map *map = (struct bpf_map *) (unsigned long) r1;
> + void *key = (void *) (unsigned long) r2;
> + void *value;
> +
> + WARN_ON_ONCE(!rcu_read_lock_held());
> +
> + value = map->ops->map_lookup_elem(map, key);
> +
> + /* lookup() returns either pointer to element value or NULL
> + * which is the meaning of PTR_TO_MAP_VALUE_OR_NULL type
> + */
> + return (unsigned long) value;
> +}
> +
> +struct bpf_func_proto bpf_map_lookup_elem_proto = {
> + .func = bpf_map_lookup_elem,
> + .gpl_only = false,
> + .ret_type = RET_PTR_TO_MAP_VALUE_OR_NULL,
> + .arg1_type = ARG_CONST_MAP_PTR,
> + .arg2_type = ARG_PTR_TO_MAP_KEY,
> +};
> +
> +/* called from eBPF program under rcu lock */
> +static u64 bpf_map_update_elem(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
> +{
> + struct bpf_map *map = (struct bpf_map *) (unsigned long) r1;
> + void *key = (void *) (unsigned long) r2;
> + void *value = (void *) (unsigned long) r3;
> +
> + WARN_ON_ONCE(!rcu_read_lock_held());
> +
> + return map->ops->map_update_elem(map, key, value, r4);
> +}
> +
> +struct bpf_func_proto bpf_map_update_elem_proto = {
> + .func = bpf_map_update_elem,
> + .gpl_only = false,
> + .ret_type = RET_INTEGER,
> + .arg1_type = ARG_CONST_MAP_PTR,
> + .arg2_type = ARG_PTR_TO_MAP_KEY,
> + .arg3_type = ARG_PTR_TO_MAP_VALUE,
> + .arg4_type = ARG_ANYTHING,
> +};
> +
> +/* called from eBPF program under rcu lock */
> +static u64 bpf_map_delete_elem(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
> +{
> + struct bpf_map *map = (struct bpf_map *) (unsigned long) r1;
> + void *key = (void *) (unsigned long) r2;
> +
> + WARN_ON_ONCE(!rcu_read_lock_held());
> +
> + return map->ops->map_delete_elem(map, key);
> +}
These WARN_ON_ONCE(!rcu_read_lock_held()) seem odd. While I see the point that
you're holding RCU read lock on the lookup, can you elaborate on your RCU usage
here and why it's necessary for delete/update?
I suspect due to the synchronize_rcu() you're using and not using any RCU
accessors but plain memcpy() e.g. in case of the array ...?
> +struct bpf_func_proto bpf_map_delete_elem_proto = {
> + .func = bpf_map_delete_elem,
> + .gpl_only = false,
> + .ret_type = RET_INTEGER,
> + .arg1_type = ARG_CONST_MAP_PTR,
> + .arg2_type = ARG_PTR_TO_MAP_KEY,
> +};
>
^ permalink raw reply
* Re: [PATCH net-next 3/7] bpf: add array type of eBPF maps
From: Daniel Borkmann @ 2014-11-04 9:58 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: David S. Miller, Ingo Molnar, Andy Lutomirski,
Hannes Frederic Sowa, Eric Dumazet, linux-api, netdev,
linux-kernel
In-Reply-To: <1415069656-14138-4-git-send-email-ast@plumgrid.com>
On 11/04/2014 03:54 AM, Alexei Starovoitov wrote:
> add new map type BPF_MAP_TYPE_ARRAY and its implementation
>
> - optimized for fastest possible lookup()
> . in the future verifier/JIT may recognize lookup() with constant key
> and optimize it into constant pointer. Can optimize non-constant
> key into direct pointer arithmetic as well, since pointers and
> value_size are constant for the life of the eBPF program.
> In other words array_map_lookup_elem() may be 'inlined' by verifier/JIT
> while preserving concurrent access to this map from user space
>
> - two main use cases for array type:
> . 'global' eBPF variables: array of 1 element with key=0 and value is a
> collection of 'global' variables which programs can use to keep the state
> between events
> . aggregation of tracing events into fixed set of buckets
>
> - all array elements pre-allocated and zero initialized at init time
>
> - key as an index in array and can only be 4 byte
>
> - map_delete_elem() returns EINVAL, since elements cannot be deleted
>
> - map_update_elem() replaces elements in an non-atomic way
> (for atomic updates hashtable type should be used instead)
>
> Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
...
> +/* Called from syscall or from eBPF program */
> +static int array_map_update_elem(struct bpf_map *map, void *key, void *value,
> + u64 map_flags)
> +{
> + struct bpf_array *array = container_of(map, struct bpf_array, map);
> + u32 index = *(u32 *)key;
> +
> + if (map_flags > BPF_MAP_UPDATE_ONLY)
> + /* unknown flags */
> + return -EINVAL;
> +
> + if (map_flags == BPF_MAP_CREATE_ONLY)
> + return -EINVAL;
> +
> + if (index >= array->map.max_entries)
> + /* all elements were pre-allocated, cannot insert a new one */
> + return -E2BIG;
> +
> + memcpy(array->value + array->elem_size * index, value, array->elem_size);
What would protect this from concurrent updates?
> + return 0;
> +}
^ permalink raw reply
* RE: TCP NewReno and single retransmit
From: David Laight @ 2014-11-04 9:56 UTC (permalink / raw)
To: 'Neal Cardwell', Marcelo Ricardo Leitner
Cc: Yuchung Cheng, netdev, Eric Dumazet
In-Reply-To: <CADVnQykXpA_A87+bFOCdbb-QLTRf-5TEgspCzE-STO49N+6waw@mail.gmail.com>
> Since there are no literal IETF-style "MUST" statements in RFC2582, I
> think the "MUST" in the code here is expressing the design philosophy
> behind the author. :-)
I wouldn't guarantee that the authors of any RFC (or other
standards document) managed to cover all possible cases.
David
^ permalink raw reply
* [PATCH v3 0/8] net: can: Use syscon regmap for TI specific RAMINIT register
From: Roger Quadros @ 2014-11-04 10:20 UTC (permalink / raw)
To: wg, mkl
Cc: wsa, tony, tglx, mugunthanvnm, george.cherian, balbi, nsekhar, nm,
sergei.shtylyov, linux-omap, linux-can, netdev, Roger Quadros
Hi,
Some hardware (TI am43xx) has a buggy RAMINIT DONE mechanism and it might
not always set the DONE bit. This will result in a lockup in c_can_hw_raminit_wait_ti(),
so patch 1 adds a timeout mechanism there.
There is a non compliancy within TI platforms with respect to the
layout of the RAMINIT register. The patches 2 and 3 address this issue
and make a flexible but standard way of defining the RAMINIT hardware register
layout in the device tree. The RAMINIT register is accessed using the syscon
regmap framework.
Patches available at
git@github.com:rogerq/linux.git [for-v3.19/can]
Patches are tested on am335x-evm, am437x-gp-evm and dra7-evm.
Board support files to allow CAN testing on these boards are available at
git@github.com:rogerq/linux.git [for-v3.19/omap-dts-dcan]
Changelog:
v3:
- allow driver data to be more than just CAN_ID
- RAMINIT register data moved to driver data instead of device tree file.
v2:
- added "ti" vendor prefix to TI specific raminit properties.
- split DTS changes into a separate series
cheers,
-roger
---
Roger Quadros (8):
net: can: c_can: Add timeout to c_can_hw_raminit_ti()
net: can: c_can: Introduce c_can_driver_data structure
net: can: c_can: Add RAMINIT register information to driver data
net: can: c_can: Add syscon/regmap RAMINIT mechanism
net: can: c_can: Add support for START pulse in RAMINIT sequence
net: can: c_can: Disable pins when CAN interface is down
net: can: c_can: Add support for TI DRA7 DCAN
net: can: c_can: Add support for TI am3352 DCAN
.../devicetree/bindings/net/can/c_can.txt | 5 +
drivers/net/can/c_can/c_can.c | 20 ++
drivers/net/can/c_can/c_can.h | 20 +-
drivers/net/can/c_can/c_can_platform.c | 207 +++++++++++++++------
4 files changed, 191 insertions(+), 61 deletions(-)
--
1.8.3.2
^ permalink raw reply
* [PATCH v3 1/8] net: can: c_can: Add timeout to c_can_hw_raminit_ti()
From: Roger Quadros @ 2014-11-04 10:20 UTC (permalink / raw)
To: wg, mkl
Cc: wsa, tony, tglx, mugunthanvnm, george.cherian, balbi, nsekhar, nm,
sergei.shtylyov, linux-omap, linux-can, netdev, Roger Quadros
In-Reply-To: <1415096461-25576-1-git-send-email-rogerq@ti.com>
TI's RAMINIT DONE mechanism is buggy on AM43xx SoC and may not always
be set after the START bit is set. Although it seems to work fine even
in that case. So add a timeout mechanism to c_can_hw_raminit_wait_ti().
Don't bail out in that failure case but just print an error message.
Signed-off-by: Roger Quadros <rogerq@ti.com>
---
drivers/net/can/c_can/c_can_platform.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index fb279d6..b144e71 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -75,10 +75,18 @@ static void c_can_plat_write_reg_aligned_to_32bit(const struct c_can_priv *priv,
static void c_can_hw_raminit_wait_ti(const struct c_can_priv *priv, u32 mask,
u32 val)
{
+ int timeout = 0;
/* We look only at the bits of our instance. */
val &= mask;
- while ((readl(priv->raminit_ctrlreg) & mask) != val)
+ while ((readl(priv->raminit_ctrlreg) & mask) != val) {
udelay(1);
+ timeout++;
+
+ if (timeout == 1000) {
+ dev_err(&priv->dev->dev, "%s: time out\n", __func__);
+ break;
+ }
+ }
}
static void c_can_hw_raminit_ti(const struct c_can_priv *priv, bool enable)
--
1.8.3.2
^ permalink raw reply related
* [PATCH v3 2/8] net: can: c_can: Introduce c_can_driver_data structure
From: Roger Quadros @ 2014-11-04 10:20 UTC (permalink / raw)
To: wg, mkl
Cc: wsa, tony, tglx, mugunthanvnm, george.cherian, balbi, nsekhar, nm,
sergei.shtylyov, linux-omap, linux-can, netdev, Roger Quadros
In-Reply-To: <1415096461-25576-1-git-send-email-rogerq@ti.com>
We want to have more data than just can_dev_id to be present
in the driver data e.g. TI platforms need RAMINIT register
description. Introduce the c_can_driver_data structure and move
the can_dev_id into it.
Tidy up the way it is used on probe().
Signed-off-by: Roger Quadros <rogerq@ti.com>
---
drivers/net/can/c_can/c_can.h | 4 +++
drivers/net/can/c_can/c_can_platform.c | 52 +++++++++++++++++++---------------
2 files changed, 33 insertions(+), 23 deletions(-)
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index 99ad1aa..26c975d 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -169,6 +169,10 @@ enum c_can_dev_id {
BOSCH_D_CAN,
};
+struct c_can_driver_data {
+ enum c_can_dev_id id;
+};
+
/* c_can private data structure */
struct c_can_priv {
struct can_priv can; /* must be the first member */
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index b144e71..1546c2b 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -167,26 +167,34 @@ static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable)
}
}
+static struct c_can_driver_data c_can_drvdata = {
+ .id = BOSCH_C_CAN,
+};
+
+static struct c_can_driver_data d_can_drvdata = {
+ .id = BOSCH_D_CAN,
+};
+
static struct platform_device_id c_can_id_table[] = {
- [BOSCH_C_CAN_PLATFORM] = {
+ {
.name = KBUILD_MODNAME,
- .driver_data = BOSCH_C_CAN,
+ .driver_data = (kernel_ulong_t)&c_can_drvdata,
},
- [BOSCH_C_CAN] = {
+ {
.name = "c_can",
- .driver_data = BOSCH_C_CAN,
+ .driver_data = (kernel_ulong_t)&c_can_drvdata,
},
- [BOSCH_D_CAN] = {
+ {
.name = "d_can",
- .driver_data = BOSCH_D_CAN,
- }, {
- }
+ .driver_data = (kernel_ulong_t)&d_can_drvdata,
+ },
+ { /* sentinel */ },
};
MODULE_DEVICE_TABLE(platform, c_can_id_table);
static const struct of_device_id c_can_of_table[] = {
- { .compatible = "bosch,c_can", .data = &c_can_id_table[BOSCH_C_CAN] },
- { .compatible = "bosch,d_can", .data = &c_can_id_table[BOSCH_D_CAN] },
+ { .compatible = "bosch,c_can", .data = &c_can_drvdata },
+ { .compatible = "bosch,d_can", .data = &d_can_drvdata },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, c_can_of_table);
@@ -198,21 +206,19 @@ static int c_can_plat_probe(struct platform_device *pdev)
struct net_device *dev;
struct c_can_priv *priv;
const struct of_device_id *match;
- const struct platform_device_id *id;
struct resource *mem, *res;
int irq;
struct clk *clk;
-
- if (pdev->dev.of_node) {
- match = of_match_device(c_can_of_table, &pdev->dev);
- if (!match) {
- dev_err(&pdev->dev, "Failed to find matching dt id\n");
- ret = -EINVAL;
- goto exit;
- }
- id = match->data;
+ const struct c_can_driver_data *drvdata;
+
+ match = of_match_device(c_can_of_table, &pdev->dev);
+ if (match) {
+ drvdata = match->data;
+ } else if (pdev->id_entry->driver_data) {
+ drvdata = (struct c_can_driver_data *)
+ pdev->id_entry->driver_data;
} else {
- id = platform_get_device_id(pdev);
+ return -ENODEV;
}
/* get the appropriate clk */
@@ -244,7 +250,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
}
priv = netdev_priv(dev);
- switch (id->driver_data) {
+ switch (drvdata->id) {
case BOSCH_C_CAN:
priv->regs = reg_map_c_can;
switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
@@ -303,7 +309,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
priv->device = &pdev->dev;
priv->can.clock.freq = clk_get_rate(clk);
priv->priv = clk;
- priv->type = id->driver_data;
+ priv->type = drvdata->id;
platform_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
--
1.8.3.2
^ permalink raw reply related
* [PATCH v3 4/8] net: can: c_can: Add syscon/regmap RAMINIT mechanism
From: Roger Quadros @ 2014-11-04 10:20 UTC (permalink / raw)
To: wg, mkl
Cc: wsa, tony, tglx, mugunthanvnm, george.cherian, balbi, nsekhar, nm,
sergei.shtylyov, linux-omap, linux-can, netdev, Roger Quadros
In-Reply-To: <1415096461-25576-1-git-send-email-rogerq@ti.com>
Some TI SoCs like DRA7 have a RAMINIT register specification
different from the other AMxx SoCs and as expected by the
existing driver.
To add more insanity, this register is shared with other
IPs like DSS, PCIe and PWM.
Provides a more generic mechanism to specify the RAMINIT
register location and START/DONE bit position and use the
syscon/regmap framework to access the register.
Signed-off-by: Roger Quadros <rogerq@ti.com>
---
.../devicetree/bindings/net/can/c_can.txt | 3 +
drivers/net/can/c_can/c_can.h | 9 ++-
drivers/net/can/c_can/c_can_platform.c | 93 +++++++++++++---------
3 files changed, 65 insertions(+), 40 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/can/c_can.txt b/Documentation/devicetree/bindings/net/can/c_can.txt
index 8f1ae81..917ac0e 100644
--- a/Documentation/devicetree/bindings/net/can/c_can.txt
+++ b/Documentation/devicetree/bindings/net/can/c_can.txt
@@ -12,6 +12,9 @@ Required properties:
Optional properties:
- ti,hwmods : Must be "d_can<n>" or "c_can<n>", n being the
instance number
+- syscon-raminit : Handle to system control region that contains the
+ RAMINIT register and register offset to the RAMINIT
+ register.
Note: "ti,hwmods" field is used to fetch the base address and irq
resources from TI, omap hwmod data base during device registration.
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index c3b2108..b5067bd 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -178,6 +178,12 @@ struct c_can_driver_data {
bool raminit_pulse; /* If set, sets and clears START bit (pulse) */
};
+/* Out of band RAMINIT register access via syscon regmap */
+struct c_can_raminit {
+ struct regmap *syscon; /* for raminit ctrl. reg. access */
+ unsigned int reg; /* register index within syscon */
+};
+
/* c_can private data structure */
struct c_can_priv {
struct can_priv can; /* must be the first member */
@@ -195,8 +201,7 @@ struct c_can_priv {
const u16 *regs;
void *priv; /* for board-specific data */
enum c_can_dev_id type;
- u32 __iomem *raminit_ctrlreg;
- int instance;
+ struct c_can_raminit raminit_sys; /* RAMINIT via syscon regmap */
void (*raminit) (const struct c_can_priv *priv, bool enable);
u32 comm_rcv_high;
u32 rxmasked;
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index 11946e8..d0ce439 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -32,14 +32,13 @@
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
#include <linux/can/dev.h>
#include "c_can.h"
-#define CAN_RAMINIT_START_MASK(i) (0x001 << (i))
-#define CAN_RAMINIT_DONE_MASK(i) (0x100 << (i))
-#define CAN_RAMINIT_ALL_MASK(i) (0x101 << (i))
#define DCAN_RAM_INIT_BIT (1 << 3)
static DEFINE_SPINLOCK(raminit_lock);
/*
@@ -72,47 +71,61 @@ static void c_can_plat_write_reg_aligned_to_32bit(const struct c_can_priv *priv,
writew(val, priv->base + 2 * priv->regs[index]);
}
-static void c_can_hw_raminit_wait_ti(const struct c_can_priv *priv, u32 mask,
- u32 val)
+static void c_can_hw_raminit_wait_syscon(const struct c_can_priv *priv,
+ u32 mask, u32 val)
{
int timeout = 0;
+ const struct c_can_raminit *raminit = &priv->raminit_sys;
+ u32 ctrl;
+
/* We look only at the bits of our instance. */
val &= mask;
- while ((readl(priv->raminit_ctrlreg) & mask) != val) {
+ do {
udelay(1);
timeout++;
+ regmap_read(raminit->syscon, raminit->reg, &ctrl);
if (timeout == 1000) {
dev_err(&priv->dev->dev, "%s: time out\n", __func__);
break;
}
- }
+ } while ((ctrl & mask) != val);
}
-static void c_can_hw_raminit_ti(const struct c_can_priv *priv, bool enable)
+static void c_can_hw_raminit_syscon(const struct c_can_priv *priv, bool enable)
{
- u32 mask = CAN_RAMINIT_ALL_MASK(priv->instance);
+ u32 mask;
u32 ctrl;
+ const struct c_can_raminit *raminit = &priv->raminit_sys;
+ u8 start_bit, done_bit;
+
+ start_bit = priv->drvdata->raminit_start_bit;
+ done_bit = priv->drvdata->raminit_done_bit;
spin_lock(&raminit_lock);
- ctrl = readl(priv->raminit_ctrlreg);
+ mask = 1 << start_bit | 1 << done_bit;
+ regmap_read(raminit->syscon, raminit->reg, &ctrl);
+
/* We clear the done and start bit first. The start bit is
* looking at the 0 -> transition, but is not self clearing;
* And we clear the init done bit as well.
+ * NOTE: DONE must be written with 1 to clear it.
*/
- ctrl &= ~CAN_RAMINIT_START_MASK(priv->instance);
- ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance);
- writel(ctrl, priv->raminit_ctrlreg);
- ctrl &= ~CAN_RAMINIT_DONE_MASK(priv->instance);
- c_can_hw_raminit_wait_ti(priv, mask, ctrl);
+ ctrl &= ~(1 << start_bit);
+ ctrl |= 1 << done_bit;
+ regmap_write(raminit->syscon, raminit->reg, ctrl);
+
+ ctrl &= ~(1 << done_bit);
+ c_can_hw_raminit_wait_syscon(priv, mask, ctrl);
if (enable) {
/* Set start bit and wait for the done bit. */
- ctrl |= CAN_RAMINIT_START_MASK(priv->instance);
- writel(ctrl, priv->raminit_ctrlreg);
- ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance);
- c_can_hw_raminit_wait_ti(priv, mask, ctrl);
+ ctrl |= 1 << start_bit;
+ regmap_write(raminit->syscon, raminit->reg, ctrl);
+
+ ctrl |= 1 << done_bit;
+ c_can_hw_raminit_wait_syscon(priv, mask, ctrl);
}
spin_unlock(&raminit_lock);
}
@@ -206,10 +219,11 @@ static int c_can_plat_probe(struct platform_device *pdev)
struct net_device *dev;
struct c_can_priv *priv;
const struct of_device_id *match;
- struct resource *mem, *res;
+ struct resource *mem;
int irq;
struct clk *clk;
const struct c_can_driver_data *drvdata;
+ struct device_node *np = pdev->dev.of_node;
match = of_match_device(c_can_of_table, &pdev->dev);
if (match) {
@@ -279,27 +293,30 @@ static int c_can_plat_probe(struct platform_device *pdev)
priv->read_reg32 = d_can_plat_read_reg32;
priv->write_reg32 = d_can_plat_write_reg32;
- if (pdev->dev.of_node)
- priv->instance = of_alias_get_id(pdev->dev.of_node, "d_can");
- else
- priv->instance = pdev->id;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- /* Not all D_CAN modules have a separate register for the D_CAN
- * RAM initialization. Use default RAM init bit in D_CAN module
- * if not specified in DT.
+ /* Check if we need custom RAMINIT via syscon. Mostly for TI
+ * platforms. Only supported with DT boot.
*/
- if (!res) {
+ if (np && of_property_read_bool(np, "syscon-raminit")) {
+ ret = -EINVAL;
+ priv->raminit_sys.syscon = syscon_regmap_lookup_by_phandle(np,
+ "syscon-raminit");
+ if (IS_ERR(priv->raminit_sys.syscon)) {
+ dev_err(&pdev->dev,
+ "couldn't get syscon regmap for RAMINIT reg.\n");
+ goto exit_free_device;
+ }
+
+ if (of_property_read_u32_index(np, "syscon-raminit", 1,
+ &priv->raminit_sys.reg)) {
+ dev_err(&pdev->dev,
+ "couldn't get the RAMINIT reg. offset!\n");
+ goto exit_free_device;
+ }
+
+ priv->raminit = c_can_hw_raminit_syscon;
+ } else {
priv->raminit = c_can_hw_raminit;
- break;
}
-
- priv->raminit_ctrlreg = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
- if (!priv->raminit_ctrlreg || priv->instance < 0)
- dev_info(&pdev->dev, "control memory is not used for raminit\n");
- else
- priv->raminit = c_can_hw_raminit_ti;
break;
default:
ret = -EINVAL;
--
1.8.3.2
^ permalink raw reply related
* [PATCH v3 6/8] net: can: c_can: Disable pins when CAN interface is down
From: Roger Quadros @ 2014-11-04 10:20 UTC (permalink / raw)
To: wg, mkl
Cc: wsa, tony, tglx, mugunthanvnm, george.cherian, balbi, nsekhar, nm,
sergei.shtylyov, linux-omap, linux-can, netdev, Roger Quadros
In-Reply-To: <1415096461-25576-1-git-send-email-rogerq@ti.com>
DRA7 CAN IP suffers from a problem which causes it to be prevented
from fully turning OFF (i.e. stuck in transition) if the module was
disabled while there was traffic on the CAN_RX line.
To work around this issue we select the SLEEP pin state by default
on probe and use the DEFAULT pin state on CAN up and back to the
SLEEP pin state on CAN down.
Signed-off-by: Roger Quadros <rogerq@ti.com>
---
drivers/net/can/c_can/c_can.c | 20 ++++++++++++++++++++
drivers/net/can/c_can/c_can.h | 1 +
drivers/net/can/c_can/c_can_platform.c | 20 ++++++++++++++++++++
3 files changed, 41 insertions(+)
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 8e78bb4..4dfc3ce 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -35,6 +35,7 @@
#include <linux/list.h>
#include <linux/io.h>
#include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/can.h>
#include <linux/can/dev.h>
@@ -603,6 +604,15 @@ static int c_can_start(struct net_device *dev)
priv->can.state = CAN_STATE_ERROR_ACTIVE;
+ /* activate pins */
+ if (!IS_ERR(priv->pinctrl)) {
+ struct pinctrl_state *s;
+
+ s = pinctrl_lookup_state(priv->pinctrl, PINCTRL_STATE_DEFAULT);
+ if (!IS_ERR(s))
+ pinctrl_select_state(priv->pinctrl, s);
+ }
+
return 0;
}
@@ -611,6 +621,16 @@ static void c_can_stop(struct net_device *dev)
struct c_can_priv *priv = netdev_priv(dev);
c_can_irq_control(priv, false);
+
+ /* deactivate pins */
+ if (!IS_ERR(priv->pinctrl)) {
+ struct pinctrl_state *s;
+
+ s = pinctrl_lookup_state(priv->pinctrl, PINCTRL_STATE_SLEEP);
+ if (!IS_ERR(s))
+ pinctrl_select_state(priv->pinctrl, s);
+ }
+
priv->can.state = CAN_STATE_STOPPED;
}
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index b5067bd..6b4ed1f 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -207,6 +207,7 @@ struct c_can_priv {
u32 rxmasked;
u32 dlc[C_CAN_MSG_OBJ_TX_NUM];
const struct c_can_driver_data *drvdata;
+ struct pinctrl *pinctrl;
};
struct net_device *alloc_c_can_dev(void);
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index ef1f5ce..d058820 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -34,6 +34,7 @@
#include <linux/of_device.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/can/dev.h>
@@ -230,6 +231,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
struct clk *clk;
const struct c_can_driver_data *drvdata;
struct device_node *np = pdev->dev.of_node;
+ struct pinctrl *pinctrl;
match = of_match_device(c_can_of_table, &pdev->dev);
if (match) {
@@ -241,6 +243,23 @@ static int c_can_plat_probe(struct platform_device *pdev)
return -ENODEV;
}
+ pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (!IS_ERR(pinctrl)) {
+ struct pinctrl_state *s;
+
+ /* Deactivate pins to prevent DRA7 DCAN IP from being
+ * stuck in transition when module is disabled.
+ * Pins are activated in c_can_start() and deactivated
+ * in c_can_stop()
+ */
+ s = pinctrl_lookup_state(pinctrl, PINCTRL_STATE_SLEEP);
+ if (!IS_ERR(s))
+ pinctrl_select_state(pinctrl, s);
+ } else {
+ dev_warn(&pdev->dev,
+ "failed to get pinctrl\n");
+ }
+
/* get the appropriate clk */
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
@@ -271,6 +290,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
priv = netdev_priv(dev);
priv->drvdata = drvdata;
+ priv->pinctrl = pinctrl;
switch (drvdata->id) {
case BOSCH_C_CAN:
--
1.8.3.2
^ permalink raw reply related
* [PATCH v3 7/8] net: can: c_can: Add support for TI DRA7 DCAN
From: Roger Quadros @ 2014-11-04 10:21 UTC (permalink / raw)
To: wg, mkl
Cc: wsa, tony, tglx, mugunthanvnm, george.cherian, balbi, nsekhar, nm,
sergei.shtylyov, linux-omap, linux-can, netdev, Roger Quadros
In-Reply-To: <1415096461-25576-1-git-send-email-rogerq@ti.com>
DRA7 SoC has 2 CAN IPs. Provide compatible IDs and RAMINIT
register data for both.
Signed-off-by: Roger Quadros <rogerq@ti.com>
---
Documentation/devicetree/bindings/net/can/c_can.txt | 1 +
drivers/net/can/c_can/c_can_platform.c | 16 ++++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/can/c_can.txt b/Documentation/devicetree/bindings/net/can/c_can.txt
index 917ac0e..746cc07 100644
--- a/Documentation/devicetree/bindings/net/can/c_can.txt
+++ b/Documentation/devicetree/bindings/net/can/c_can.txt
@@ -4,6 +4,7 @@ Bosch C_CAN/D_CAN controller Device Tree Bindings
Required properties:
- compatible : Should be "bosch,c_can" for C_CAN controllers and
"bosch,d_can" for D_CAN controllers.
+ Can be "ti,dra7-d_can1" or "ti,dra7-d_can2".
- reg : physical base address and size of the C_CAN/D_CAN
registers map
- interrupts : property with a value describing the interrupt
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index d058820..dc618ce 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -195,6 +195,20 @@ static struct c_can_driver_data d_can_drvdata = {
.id = BOSCH_D_CAN,
};
+static struct c_can_driver_data dra7_dcan1_drvdata = {
+ .id = BOSCH_D_CAN,
+ .raminit_start_bit = 3,
+ .raminit_done_bit = 1,
+ .raminit_pulse = true,
+};
+
+static struct c_can_driver_data dra7_dcan2_drvdata = {
+ .id = BOSCH_D_CAN,
+ .raminit_start_bit = 5,
+ .raminit_done_bit = 2,
+ .raminit_pulse = true,
+};
+
static struct platform_device_id c_can_id_table[] = {
{
.name = KBUILD_MODNAME,
@@ -215,6 +229,8 @@ MODULE_DEVICE_TABLE(platform, c_can_id_table);
static const struct of_device_id c_can_of_table[] = {
{ .compatible = "bosch,c_can", .data = &c_can_drvdata },
{ .compatible = "bosch,d_can", .data = &d_can_drvdata },
+ { .compatible = "ti,dra7-d_can1", .data = &dra7_dcan1_drvdata },
+ { .compatible = "ti,dra7-d_can2", .data = &dra7_dcan2_drvdata },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, c_can_of_table);
--
1.8.3.2
^ permalink raw reply related
* [PATCH v3 3/8] net: can: c_can: Add RAMINIT register information to driver data
From: Roger Quadros @ 2014-11-04 10:20 UTC (permalink / raw)
To: wg, mkl
Cc: wsa, tony, tglx, mugunthanvnm, george.cherian, balbi, nsekhar, nm,
sergei.shtylyov, linux-omap, linux-can, netdev, Roger Quadros
In-Reply-To: <1415096461-25576-1-git-send-email-rogerq@ti.com>
Some platforms (e.g. TI) need special RAMINIT register handling.
Provide a way to store RAMINIT register description in driver data.
Signed-off-by: Roger Quadros <rogerq@ti.com>
---
drivers/net/can/c_can/c_can.h | 6 ++++++
drivers/net/can/c_can/c_can_platform.c | 2 ++
2 files changed, 8 insertions(+)
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index 26c975d..c3b2108 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -171,6 +171,11 @@ enum c_can_dev_id {
struct c_can_driver_data {
enum c_can_dev_id id;
+
+ /* RAMINIT register description. Optional. */
+ u8 raminit_start_bit; /* START bit position in RAMINIT reg. */
+ u8 raminit_done_bit; /* DONE bit position in RAMINIT reg. */
+ bool raminit_pulse; /* If set, sets and clears START bit (pulse) */
};
/* c_can private data structure */
@@ -196,6 +201,7 @@ struct c_can_priv {
u32 comm_rcv_high;
u32 rxmasked;
u32 dlc[C_CAN_MSG_OBJ_TX_NUM];
+ const struct c_can_driver_data *drvdata;
};
struct net_device *alloc_c_can_dev(void);
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index 1546c2b..11946e8 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -250,6 +250,8 @@ static int c_can_plat_probe(struct platform_device *pdev)
}
priv = netdev_priv(dev);
+ priv->drvdata = drvdata;
+
switch (drvdata->id) {
case BOSCH_C_CAN:
priv->regs = reg_map_c_can;
--
1.8.3.2
^ permalink raw reply related
* [PATCH v3 5/8] net: can: c_can: Add support for START pulse in RAMINIT sequence
From: Roger Quadros @ 2014-11-04 10:20 UTC (permalink / raw)
To: wg, mkl
Cc: wsa, tony, tglx, mugunthanvnm, george.cherian, balbi, nsekhar, nm,
sergei.shtylyov, linux-omap, linux-can, netdev, Roger Quadros
In-Reply-To: <1415096461-25576-1-git-send-email-rogerq@ti.com>
Some SoCs e.g. (TI DRA7xx) need a START pulse to start the
RAMINIT sequence i.e. START bit must be set and cleared before
checking for the DONE bit status.
Signed-off-by: Roger Quadros <rogerq@ti.com>
---
drivers/net/can/c_can/c_can_platform.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index d0ce439..ef1f5ce 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -124,6 +124,12 @@ static void c_can_hw_raminit_syscon(const struct c_can_priv *priv, bool enable)
ctrl |= 1 << start_bit;
regmap_write(raminit->syscon, raminit->reg, ctrl);
+ /* clear START bit if start pulse is needed */
+ if (priv->drvdata->raminit_pulse) {
+ ctrl &= ~(1 << start_bit);
+ regmap_write(raminit->syscon, raminit->reg, ctrl);
+ }
+
ctrl |= 1 << done_bit;
c_can_hw_raminit_wait_syscon(priv, mask, ctrl);
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH v3 8/8] net: can: c_can: Add support for TI am3352 DCAN
From: Roger Quadros @ 2014-11-04 10:21 UTC (permalink / raw)
To: wg, mkl
Cc: wsa, tony, tglx, mugunthanvnm, george.cherian, balbi, nsekhar, nm,
sergei.shtylyov, linux-omap, linux-can, netdev, Roger Quadros
In-Reply-To: <1415096461-25576-1-git-send-email-rogerq@ti.com>
AM3352 SoC has 2 DCAN modules. Add compatible id and
raminit driver data for am3352 DCAN.
Signed-off-by: Roger Quadros <rogerq@ti.com>
---
Documentation/devicetree/bindings/net/can/c_can.txt | 3 ++-
drivers/net/can/c_can/c_can_platform.c | 14 ++++++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/net/can/c_can.txt b/Documentation/devicetree/bindings/net/can/c_can.txt
index 746cc07..27205d9 100644
--- a/Documentation/devicetree/bindings/net/can/c_can.txt
+++ b/Documentation/devicetree/bindings/net/can/c_can.txt
@@ -4,7 +4,8 @@ Bosch C_CAN/D_CAN controller Device Tree Bindings
Required properties:
- compatible : Should be "bosch,c_can" for C_CAN controllers and
"bosch,d_can" for D_CAN controllers.
- Can be "ti,dra7-d_can1" or "ti,dra7-d_can2".
+ Can be "ti,dra7-d_can1" or "ti,dra7-d_can2" or
+ "ti,am3352-d_can0" or "ti,am3352-d_can1".
- reg : physical base address and size of the C_CAN/D_CAN
registers map
- interrupts : property with a value describing the interrupt
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index dc618ce..7dcdcde 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -209,6 +209,18 @@ static struct c_can_driver_data dra7_dcan2_drvdata = {
.raminit_pulse = true,
};
+static struct c_can_driver_data am3352_dcan0_drvdata = {
+ .id = BOSCH_D_CAN,
+ .raminit_start_bit = 0,
+ .raminit_done_bit = 8,
+};
+
+static struct c_can_driver_data am3352_dcan1_drvdata = {
+ .id = BOSCH_D_CAN,
+ .raminit_start_bit = 1,
+ .raminit_done_bit = 9,
+};
+
static struct platform_device_id c_can_id_table[] = {
{
.name = KBUILD_MODNAME,
@@ -231,6 +243,8 @@ static const struct of_device_id c_can_of_table[] = {
{ .compatible = "bosch,d_can", .data = &d_can_drvdata },
{ .compatible = "ti,dra7-d_can1", .data = &dra7_dcan1_drvdata },
{ .compatible = "ti,dra7-d_can2", .data = &dra7_dcan2_drvdata },
+ { .compatible = "ti,am3352-d_can0", .data = &am3352_dcan0_drvdata },
+ { .compatible = "ti,am3352-d_can1", .data = &am3352_dcan1_drvdata },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, c_can_of_table);
--
1.8.3.2
^ permalink raw reply related
* RE: [PATCH] net: eth: realtek: atp: checkpatch errors and warnings corrected
From: David Laight @ 2014-11-04 10:19 UTC (permalink / raw)
To: 'Roberto Medina', Joe Perches
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <5457D2DF.5000508@gmail.com>
From: Roberto Medina
> On 11/03/2014 07:51 PM, Joe Perches wrote:
> >
> > Some ancient drivers could be regarded as neolithic
> > curiosities that never need updating. This may be one.
> >
> > But if you really want to change it, could you please
> > make sure that objdiff shows no changes?
> >
>
> I see some changes with objdiff, maybe this is caused by the include
> file that I changed to linux/io.h instead of asm/io.h
>
> ---
> /home/vov/Git/linux-next/.tmp_objdiff/a641d0e/drivers/net/ethernet/realtek/atp.dis
> 2014-11-03 19:59:18.723954900 +0100
> +++
> /home/vov/Git/linux-next/.tmp_objdiff/5f19b70/drivers/net/ethernet/realtek/atp.dis
> 2014-11-03 20:00:34.133954217 +0100
> @@ -1753,9 +1753,8 @@
> ...
> : e3 0a jrcxz 4c4 <__gcov_.atp_probe1+0x14>
> : 00 00 add %al,(%rax)
> -: e2 e2 loop 4a0 <__gcov_.atp_init+0x20>
> -: 9c pushfq
> -: 9a (bad)
> +: 4b b4 98 rex.WXB mov $0x98,%r12b
> +: ac lods %ds:(%rsi),%al
> : 67 2f addr32 (bad)
> : e4 e3 in $0xe3,%al
> : 00 00 add %al,(%rax)
That code (and all the ones below) are gibberish, neither the old or new
sequences make any sense.
Almost as though you used the wrong instruction set!
David
^ 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