Update to 3.5
Drop many patches that were backported from 3.5. Refresh debian/kernelvariables.patch Disable aufs and rt for now. svn path=/dists/trunk/linux/; revision=19270
This commit is contained in:
parent
f06fe79674
commit
bdf73892ab
|
@ -1,6 +1,11 @@
|
|||
linux (3.4.4-1~experimental.2) UNRELEASED; urgency=low
|
||||
linux (3.5-1~experimental.1) UNRELEASED; urgency=low
|
||||
|
||||
* New upstream release: http://kernelnewbies.org/Linux_3.5
|
||||
|
||||
[ Ben Hutchings ]
|
||||
* net: Enable OPENVSWITCH as module (Closes: #675010)
|
||||
* aufs: Disable until it is updated for Linux 3.5
|
||||
* rt: Disable until it is updated for Linux 3.5 or later
|
||||
|
||||
-- Ben Hutchings <ben@decadent.org.uk> Mon, 02 Jul 2012 15:09:43 +0100
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ arches:
|
|||
compiler: gcc-4.6
|
||||
featuresets:
|
||||
none
|
||||
rt
|
||||
# rt
|
||||
|
||||
[featureset-rt_base]
|
||||
enabled: true
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
From: Avi Kivity <avi@redhat.com>
|
||||
Date: Sun, 22 Apr 2012 17:02:11 +0300
|
||||
Subject: [PATCH] KVM: Fix buffer overflow in kvm_set_irq()
|
||||
|
||||
commit f2ebd422f71cda9c791f76f85d2ca102ae34a1ed upstream.
|
||||
|
||||
kvm_set_irq() has an internal buffer of three irq routing entries, allowing
|
||||
connecting a GSI to three IRQ chips or on MSI. However setup_routing_entry()
|
||||
does not properly enforce this, allowing three irqchip routes followed by
|
||||
an MSI route to overflow the buffer.
|
||||
|
||||
Fix by ensuring that an MSI entry is added to an empty list.
|
||||
|
||||
Signed-off-by: Avi Kivity <avi@redhat.com>
|
||||
---
|
||||
virt/kvm/irq_comm.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
|
||||
index a6a0365..5afb431 100644
|
||||
--- a/virt/kvm/irq_comm.c
|
||||
+++ b/virt/kvm/irq_comm.c
|
||||
@@ -332,6 +332,7 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt,
|
||||
*/
|
||||
hlist_for_each_entry(ei, n, &rt->map[ue->gsi], link)
|
||||
if (ei->type == KVM_IRQ_ROUTING_MSI ||
|
||||
+ ue->type == KVM_IRQ_ROUTING_MSI ||
|
||||
ue->u.irqchip.irqchip == ei->irqchip.irqchip)
|
||||
return r;
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
From: Jason Wang <jasowang@redhat.com>
|
||||
Date: Wed, 2 May 2012 11:41:30 +0800
|
||||
Subject: [1/5] macvtap: zerocopy: fix offset calculation when building skb
|
||||
|
||||
commit 3afc9621f15701c557e60f61eba9242bac2771dd upstream.
|
||||
|
||||
This patch fixes the offset calculation when building skb:
|
||||
|
||||
- offset1 were used as skb data offset not vector offset
|
||||
- reset offset to zero only when we advance to next vector
|
||||
|
||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
drivers/net/macvtap.c | 13 +++++++------
|
||||
1 file changed, 7 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
|
||||
index 0427c65..bd4a70d 100644
|
||||
--- a/drivers/net/macvtap.c
|
||||
+++ b/drivers/net/macvtap.c
|
||||
@@ -505,10 +505,11 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
|
||||
if (copy > size) {
|
||||
++from;
|
||||
--count;
|
||||
- }
|
||||
+ offset = 0;
|
||||
+ } else
|
||||
+ offset += size;
|
||||
copy -= size;
|
||||
offset1 += size;
|
||||
- offset = 0;
|
||||
}
|
||||
|
||||
if (len == offset1)
|
||||
@@ -519,13 +520,13 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
|
||||
int num_pages;
|
||||
unsigned long base;
|
||||
|
||||
- len = from->iov_len - offset1;
|
||||
+ len = from->iov_len - offset;
|
||||
if (!len) {
|
||||
- offset1 = 0;
|
||||
+ offset = 0;
|
||||
++from;
|
||||
continue;
|
||||
}
|
||||
- base = (unsigned long)from->iov_base + offset1;
|
||||
+ base = (unsigned long)from->iov_base + offset;
|
||||
size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
|
||||
num_pages = get_user_pages_fast(base, size, 0, &page[i]);
|
||||
if ((num_pages != size) ||
|
||||
@@ -546,7 +547,7 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
|
||||
len -= size;
|
||||
i++;
|
||||
}
|
||||
- offset1 = 0;
|
||||
+ offset = 0;
|
||||
++from;
|
||||
}
|
||||
return 0;
|
|
@ -1,41 +0,0 @@
|
|||
From: Jason Wang <jasowang@redhat.com>
|
||||
Date: Wed, 2 May 2012 11:41:44 +0800
|
||||
Subject: [2/5] macvtap: zerocopy: fix truesize underestimation
|
||||
|
||||
commit 4ef67ebedffa44ed9939b34708ac2fee06d2f65f upstream.
|
||||
|
||||
As the skb fragment were pinned/built from user pages, we should
|
||||
account the page instead of length for truesize.
|
||||
|
||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
drivers/net/macvtap.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
|
||||
index bd4a70d..7cb2684 100644
|
||||
--- a/drivers/net/macvtap.c
|
||||
+++ b/drivers/net/macvtap.c
|
||||
@@ -519,6 +519,7 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
|
||||
struct page *page[MAX_SKB_FRAGS];
|
||||
int num_pages;
|
||||
unsigned long base;
|
||||
+ unsigned long truesize;
|
||||
|
||||
len = from->iov_len - offset;
|
||||
if (!len) {
|
||||
@@ -533,10 +534,11 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
|
||||
(num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags))
|
||||
/* put_page is in skb free */
|
||||
return -EFAULT;
|
||||
+ truesize = size * PAGE_SIZE;
|
||||
skb->data_len += len;
|
||||
skb->len += len;
|
||||
- skb->truesize += len;
|
||||
- atomic_add(len, &skb->sk->sk_wmem_alloc);
|
||||
+ skb->truesize += truesize;
|
||||
+ atomic_add(truesize, &skb->sk->sk_wmem_alloc);
|
||||
while (len) {
|
||||
int off = base & ~PAGE_MASK;
|
||||
int size = min_t(int, len, PAGE_SIZE - off);
|
|
@ -1,35 +0,0 @@
|
|||
From: Jason Wang <jasowang@redhat.com>
|
||||
Date: Wed, 2 May 2012 11:41:58 +0800
|
||||
Subject: [3/5] macvtap: zerocopy: put page when fail to get all requested
|
||||
user pages
|
||||
|
||||
commit 02ce04bb3d28c3333231f43bca677228dbc686fe upstream.
|
||||
|
||||
When get_user_pages_fast() fails to get all requested pages, we could not use
|
||||
kfree_skb() to free it as it has not been put in the skb fragments. So we need
|
||||
to call put_page() instead.
|
||||
|
||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
drivers/net/macvtap.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
|
||||
index 7cb2684..9ab182a 100644
|
||||
--- a/drivers/net/macvtap.c
|
||||
+++ b/drivers/net/macvtap.c
|
||||
@@ -531,9 +531,11 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
|
||||
size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
|
||||
num_pages = get_user_pages_fast(base, size, 0, &page[i]);
|
||||
if ((num_pages != size) ||
|
||||
- (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags))
|
||||
- /* put_page is in skb free */
|
||||
+ (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags)) {
|
||||
+ for (i = 0; i < num_pages; i++)
|
||||
+ put_page(page[i]);
|
||||
return -EFAULT;
|
||||
+ }
|
||||
truesize = size * PAGE_SIZE;
|
||||
skb->data_len += len;
|
||||
skb->len += len;
|
|
@ -1,48 +0,0 @@
|
|||
From: Jason Wang <jasowang@redhat.com>
|
||||
Date: Wed, 2 May 2012 11:42:06 +0800
|
||||
Subject: [4/5] macvtap: zerocopy: set SKBTX_DEV_ZEROCOPY only when skb is
|
||||
built successfully
|
||||
|
||||
commit 01d6657b388438def19c8baaea28e742b6ed32ec upstream.
|
||||
|
||||
Current the SKBTX_DEV_ZEROCOPY is set unconditionally after
|
||||
zerocopy_sg_from_iovec(), this would lead NULL pointer when macvtap
|
||||
fails to build zerocopy skb because destructor_arg was not
|
||||
initialized. Solve this by set this flag after the skb were built
|
||||
successfully.
|
||||
|
||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
drivers/net/macvtap.c | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
|
||||
index 9ab182a..a4ff694 100644
|
||||
--- a/drivers/net/macvtap.c
|
||||
+++ b/drivers/net/macvtap.c
|
||||
@@ -699,10 +699,9 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
|
||||
if (!skb)
|
||||
goto err;
|
||||
|
||||
- if (zerocopy) {
|
||||
+ if (zerocopy)
|
||||
err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count);
|
||||
- skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
|
||||
- } else
|
||||
+ else
|
||||
err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len,
|
||||
len);
|
||||
if (err)
|
||||
@@ -721,8 +720,10 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
|
||||
rcu_read_lock_bh();
|
||||
vlan = rcu_dereference_bh(q->vlan);
|
||||
/* copy skb_ubuf_info for callback when skb has no error */
|
||||
- if (zerocopy)
|
||||
+ if (zerocopy) {
|
||||
skb_shinfo(skb)->destructor_arg = m->msg_control;
|
||||
+ skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
|
||||
+ }
|
||||
if (vlan)
|
||||
macvlan_start_xmit(skb, vlan->dev);
|
||||
else
|
|
@ -1,78 +0,0 @@
|
|||
From: Jason Wang <jasowang@redhat.com>
|
||||
Date: Wed, 2 May 2012 11:42:15 +0800
|
||||
Subject: macvtap: zerocopy: validate vectors before building skb
|
||||
|
||||
commit b92946e2919134ebe2a4083e4302236295ea2a73 upstream.
|
||||
|
||||
There're several reasons that the vectors need to be validated:
|
||||
|
||||
- Return error when caller provides vectors whose num is greater than UIO_MAXIOV.
|
||||
- Linearize part of skb when userspace provides vectors grater than MAX_SKB_FRAGS.
|
||||
- Return error when userspace provides vectors whose total length may exceed
|
||||
- MAX_SKB_FRAGS * PAGE_SIZE.
|
||||
|
||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
drivers/net/macvtap.c | 25 +++++++++++++++++++++----
|
||||
1 file changed, 21 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
|
||||
index a4ff694..163559c 100644
|
||||
--- a/drivers/net/macvtap.c
|
||||
+++ b/drivers/net/macvtap.c
|
||||
@@ -529,9 +529,10 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
|
||||
}
|
||||
base = (unsigned long)from->iov_base + offset;
|
||||
size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
|
||||
+ if (i + size > MAX_SKB_FRAGS)
|
||||
+ return -EMSGSIZE;
|
||||
num_pages = get_user_pages_fast(base, size, 0, &page[i]);
|
||||
- if ((num_pages != size) ||
|
||||
- (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags)) {
|
||||
+ if (num_pages != size) {
|
||||
for (i = 0; i < num_pages; i++)
|
||||
put_page(page[i]);
|
||||
return -EFAULT;
|
||||
@@ -651,7 +652,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
|
||||
int err;
|
||||
struct virtio_net_hdr vnet_hdr = { 0 };
|
||||
int vnet_hdr_len = 0;
|
||||
- int copylen;
|
||||
+ int copylen = 0;
|
||||
bool zerocopy = false;
|
||||
|
||||
if (q->flags & IFF_VNET_HDR) {
|
||||
@@ -680,15 +681,31 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
|
||||
if (unlikely(len < ETH_HLEN))
|
||||
goto err;
|
||||
|
||||
+ err = -EMSGSIZE;
|
||||
+ if (unlikely(count > UIO_MAXIOV))
|
||||
+ goto err;
|
||||
+
|
||||
if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY))
|
||||
zerocopy = true;
|
||||
|
||||
if (zerocopy) {
|
||||
+ /* Userspace may produce vectors with count greater than
|
||||
+ * MAX_SKB_FRAGS, so we need to linearize parts of the skb
|
||||
+ * to let the rest of data to be fit in the frags.
|
||||
+ */
|
||||
+ if (count > MAX_SKB_FRAGS) {
|
||||
+ copylen = iov_length(iv, count - MAX_SKB_FRAGS);
|
||||
+ if (copylen < vnet_hdr_len)
|
||||
+ copylen = 0;
|
||||
+ else
|
||||
+ copylen -= vnet_hdr_len;
|
||||
+ }
|
||||
/* There are 256 bytes to be copied in skb, so there is enough
|
||||
* room for skb expand head in case it is used.
|
||||
* The rest buffer is mapped from userspace.
|
||||
*/
|
||||
- copylen = vnet_hdr.hdr_len;
|
||||
+ if (copylen < vnet_hdr.hdr_len)
|
||||
+ copylen = vnet_hdr.hdr_len;
|
||||
if (!copylen)
|
||||
copylen = GOODCOPY_LEN;
|
||||
} else
|
|
@ -1,48 +0,0 @@
|
|||
From: Jason Wang <jasowang@redhat.com>
|
||||
Date: Wed, 30 May 2012 21:18:10 +0000
|
||||
Subject: net: sock: validate data_len before allocating skb in
|
||||
sock_alloc_send_pskb()
|
||||
|
||||
commit cc9b17ad29ecaa20bfe426a8d4dbfb94b13ff1cc upstream.
|
||||
|
||||
We need to validate the number of pages consumed by data_len, otherwise frags
|
||||
array could be overflowed by userspace. So this patch validate data_len and
|
||||
return -EMSGSIZE when data_len may occupies more frags than MAX_SKB_FRAGS.
|
||||
|
||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
net/core/sock.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/net/core/sock.c b/net/core/sock.c
|
||||
index 653f8c0..9e5b71f 100644
|
||||
--- a/net/core/sock.c
|
||||
+++ b/net/core/sock.c
|
||||
@@ -1592,6 +1592,11 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
|
||||
gfp_t gfp_mask;
|
||||
long timeo;
|
||||
int err;
|
||||
+ int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
|
||||
+
|
||||
+ err = -EMSGSIZE;
|
||||
+ if (npages > MAX_SKB_FRAGS)
|
||||
+ goto failure;
|
||||
|
||||
gfp_mask = sk->sk_allocation;
|
||||
if (gfp_mask & __GFP_WAIT)
|
||||
@@ -1610,14 +1615,12 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
|
||||
if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
|
||||
skb = alloc_skb(header_len, gfp_mask);
|
||||
if (skb) {
|
||||
- int npages;
|
||||
int i;
|
||||
|
||||
/* No pages, we're done... */
|
||||
if (!data_len)
|
||||
break;
|
||||
|
||||
- npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
|
||||
skb->truesize += data_len;
|
||||
skb_shinfo(skb)->nr_frags = npages;
|
||||
for (i = 0; i < npages; i++) {
|
|
@ -1,42 +0,0 @@
|
|||
From: Michael Cree <mcree@orcon.net.nz>
|
||||
To: linux-alpha@vger.kernel.org
|
||||
Cc: Michael Cree <mcree@orcon.net.nz>, linux-kernel@vger.kernel.org, Matt
|
||||
Turner <mattst88@gmail.com>, Richard Henderson <rth@twiddle.net>, Ivan
|
||||
Kokshaysky <ink@jurassic.park.msu.ru>, 649468@bugs.debian.org, Ben
|
||||
Hutchings <ben@decadent.org.uk>
|
||||
Subject: [PATCH] alpha: add io{read,write}{16,32}be functions
|
||||
Date: Wed, 30 Nov 2011 21:01:40 +1300
|
||||
Message-Id: <1322640100-14534-1-git-send-email-mcree@orcon.net.nz>
|
||||
|
||||
These functions are used in some PCI drivers with big-endian
|
||||
MMIO space.
|
||||
|
||||
Admittedly it is almost certain that no one this side of the
|
||||
Moon would use such a card in an Alpha but it does get us
|
||||
closer to being able to build allyesconfig or allmodconfig,
|
||||
and it enables the Debian default generic config to build.
|
||||
|
||||
Signed-off-by: Michael Cree <mcree@orcon.net.nz>
|
||||
---
|
||||
arch/alpha/include/asm/io.h | 5 +++++
|
||||
1 files changed, 5 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/alpha/include/asm/io.h b/arch/alpha/include/asm/io.h
|
||||
index 56ff965..6365ef2 100644
|
||||
--- a/arch/alpha/include/asm/io.h
|
||||
+++ b/arch/alpha/include/asm/io.h
|
||||
@@ -490,6 +490,11 @@ extern inline void writeq(u64 b, volatile void __iomem *addr)
|
||||
}
|
||||
#endif
|
||||
|
||||
+#define ioread16be(p) be16_to_cpu(ioread16(p))
|
||||
+#define ioread32be(p) be32_to_cpu(ioread32(p))
|
||||
+#define iowrite16be(v,p) iowrite16(cpu_to_be16(v), (p))
|
||||
+#define iowrite32be(v,p) iowrite32(cpu_to_be32(v), (p))
|
||||
+
|
||||
#define inb_p inb
|
||||
#define inw_p inw
|
||||
#define inl_p inl
|
||||
--
|
||||
1.7.4.3
|
||||
|
|
@ -1,214 +0,0 @@
|
|||
From: Andrea Arcangeli <aarcange@redhat.com>
|
||||
Date: Tue, 29 May 2012 15:06:49 -0700
|
||||
Subject: mm: pmd_read_atomic: fix 32bit PAE pmd walk vs pmd_populate SMP race
|
||||
condition
|
||||
|
||||
commit 26c191788f18129af0eb32a358cdaea0c7479626 upstream.
|
||||
|
||||
When holding the mmap_sem for reading, pmd_offset_map_lock should only
|
||||
run on a pmd_t that has been read atomically from the pmdp pointer,
|
||||
otherwise we may read only half of it leading to this crash.
|
||||
|
||||
PID: 11679 TASK: f06e8000 CPU: 3 COMMAND: "do_race_2_panic"
|
||||
#0 [f06a9dd8] crash_kexec at c049b5ec
|
||||
#1 [f06a9e2c] oops_end at c083d1c2
|
||||
#2 [f06a9e40] no_context at c0433ded
|
||||
#3 [f06a9e64] bad_area_nosemaphore at c043401a
|
||||
#4 [f06a9e6c] __do_page_fault at c0434493
|
||||
#5 [f06a9eec] do_page_fault at c083eb45
|
||||
#6 [f06a9f04] error_code (via page_fault) at c083c5d5
|
||||
EAX: 01fb470c EBX: fff35000 ECX: 00000003 EDX: 00000100 EBP:
|
||||
00000000
|
||||
DS: 007b ESI: 9e201000 ES: 007b EDI: 01fb4700 GS: 00e0
|
||||
CS: 0060 EIP: c083bc14 ERR: ffffffff EFLAGS: 00010246
|
||||
#7 [f06a9f38] _spin_lock at c083bc14
|
||||
#8 [f06a9f44] sys_mincore at c0507b7d
|
||||
#9 [f06a9fb0] system_call at c083becd
|
||||
start len
|
||||
EAX: ffffffda EBX: 9e200000 ECX: 00001000 EDX: 6228537f
|
||||
DS: 007b ESI: 00000000 ES: 007b EDI: 003d0f00
|
||||
SS: 007b ESP: 62285354 EBP: 62285388 GS: 0033
|
||||
CS: 0073 EIP: 00291416 ERR: 000000da EFLAGS: 00000286
|
||||
|
||||
This should be a longstanding bug affecting x86 32bit PAE without THP.
|
||||
Only archs with 64bit large pmd_t and 32bit unsigned long should be
|
||||
affected.
|
||||
|
||||
With THP enabled the barrier() in pmd_none_or_trans_huge_or_clear_bad()
|
||||
would partly hide the bug when the pmd transition from none to stable,
|
||||
by forcing a re-read of the *pmd in pmd_offset_map_lock, but when THP is
|
||||
enabled a new set of problem arises by the fact could then transition
|
||||
freely in any of the none, pmd_trans_huge or pmd_trans_stable states.
|
||||
So making the barrier in pmd_none_or_trans_huge_or_clear_bad()
|
||||
unconditional isn't good idea and it would be a flakey solution.
|
||||
|
||||
This should be fully fixed by introducing a pmd_read_atomic that reads
|
||||
the pmd in order with THP disabled, or by reading the pmd atomically
|
||||
with cmpxchg8b with THP enabled.
|
||||
|
||||
Luckily this new race condition only triggers in the places that must
|
||||
already be covered by pmd_none_or_trans_huge_or_clear_bad() so the fix
|
||||
is localized there but this bug is not related to THP.
|
||||
|
||||
NOTE: this can trigger on x86 32bit systems with PAE enabled with more
|
||||
than 4G of ram, otherwise the high part of the pmd will never risk to be
|
||||
truncated because it would be zero at all times, in turn so hiding the
|
||||
SMP race.
|
||||
|
||||
This bug was discovered and fully debugged by Ulrich, quote:
|
||||
|
||||
----
|
||||
[..]
|
||||
pmd_none_or_trans_huge_or_clear_bad() loads the content of edx and
|
||||
eax.
|
||||
|
||||
496 static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t
|
||||
*pmd)
|
||||
497 {
|
||||
498 /* depend on compiler for an atomic pmd read */
|
||||
499 pmd_t pmdval = *pmd;
|
||||
|
||||
// edi = pmd pointer
|
||||
0xc0507a74 <sys_mincore+548>: mov 0x8(%esp),%edi
|
||||
...
|
||||
// edx = PTE page table high address
|
||||
0xc0507a84 <sys_mincore+564>: mov 0x4(%edi),%edx
|
||||
...
|
||||
// eax = PTE page table low address
|
||||
0xc0507a8e <sys_mincore+574>: mov (%edi),%eax
|
||||
|
||||
[..]
|
||||
|
||||
Please note that the PMD is not read atomically. These are two "mov"
|
||||
instructions where the high order bits of the PMD entry are fetched
|
||||
first. Hence, the above machine code is prone to the following race.
|
||||
|
||||
- The PMD entry {high|low} is 0x0000000000000000.
|
||||
The "mov" at 0xc0507a84 loads 0x00000000 into edx.
|
||||
|
||||
- A page fault (on another CPU) sneaks in between the two "mov"
|
||||
instructions and instantiates the PMD.
|
||||
|
||||
- The PMD entry {high|low} is now 0x00000003fda38067.
|
||||
The "mov" at 0xc0507a8e loads 0xfda38067 into eax.
|
||||
----
|
||||
|
||||
Reported-by: Ulrich Obergfell <uobergfe@redhat.com>
|
||||
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
|
||||
Cc: Mel Gorman <mgorman@suse.de>
|
||||
Cc: Hugh Dickins <hughd@google.com>
|
||||
Cc: Larry Woodman <lwoodman@redhat.com>
|
||||
Cc: Petr Matousek <pmatouse@redhat.com>
|
||||
Cc: Rik van Riel <riel@redhat.com>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
||||
---
|
||||
arch/x86/include/asm/pgtable-3level.h | 50 +++++++++++++++++++++++++++++++++
|
||||
include/asm-generic/pgtable.h | 22 +++++++++++++--
|
||||
2 files changed, 70 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h
|
||||
index effff47..43876f1 100644
|
||||
--- a/arch/x86/include/asm/pgtable-3level.h
|
||||
+++ b/arch/x86/include/asm/pgtable-3level.h
|
||||
@@ -31,6 +31,56 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte)
|
||||
ptep->pte_low = pte.pte_low;
|
||||
}
|
||||
|
||||
+#define pmd_read_atomic pmd_read_atomic
|
||||
+/*
|
||||
+ * pte_offset_map_lock on 32bit PAE kernels was reading the pmd_t with
|
||||
+ * a "*pmdp" dereference done by gcc. Problem is, in certain places
|
||||
+ * where pte_offset_map_lock is called, concurrent page faults are
|
||||
+ * allowed, if the mmap_sem is hold for reading. An example is mincore
|
||||
+ * vs page faults vs MADV_DONTNEED. On the page fault side
|
||||
+ * pmd_populate rightfully does a set_64bit, but if we're reading the
|
||||
+ * pmd_t with a "*pmdp" on the mincore side, a SMP race can happen
|
||||
+ * because gcc will not read the 64bit of the pmd atomically. To fix
|
||||
+ * this all places running pmd_offset_map_lock() while holding the
|
||||
+ * mmap_sem in read mode, shall read the pmdp pointer using this
|
||||
+ * function to know if the pmd is null nor not, and in turn to know if
|
||||
+ * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd
|
||||
+ * operations.
|
||||
+ *
|
||||
+ * Without THP if the mmap_sem is hold for reading, the
|
||||
+ * pmd can only transition from null to not null while pmd_read_atomic runs.
|
||||
+ * So there's no need of literally reading it atomically.
|
||||
+ *
|
||||
+ * With THP if the mmap_sem is hold for reading, the pmd can become
|
||||
+ * THP or null or point to a pte (and in turn become "stable") at any
|
||||
+ * time under pmd_read_atomic, so it's mandatory to read it atomically
|
||||
+ * with cmpxchg8b.
|
||||
+ */
|
||||
+#ifndef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
+static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
|
||||
+{
|
||||
+ pmdval_t ret;
|
||||
+ u32 *tmp = (u32 *)pmdp;
|
||||
+
|
||||
+ ret = (pmdval_t) (*tmp);
|
||||
+ if (ret) {
|
||||
+ /*
|
||||
+ * If the low part is null, we must not read the high part
|
||||
+ * or we can end up with a partial pmd.
|
||||
+ */
|
||||
+ smp_rmb();
|
||||
+ ret |= ((pmdval_t)*(tmp + 1)) << 32;
|
||||
+ }
|
||||
+
|
||||
+ return (pmd_t) { ret };
|
||||
+}
|
||||
+#else /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
+static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
|
||||
+{
|
||||
+ return (pmd_t) { atomic64_read((atomic64_t *)pmdp) };
|
||||
+}
|
||||
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
+
|
||||
static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
|
||||
{
|
||||
set_64bit((unsigned long long *)(ptep), native_pte_val(pte));
|
||||
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
|
||||
index e2768f1..6f2b45a 100644
|
||||
--- a/include/asm-generic/pgtable.h
|
||||
+++ b/include/asm-generic/pgtable.h
|
||||
@@ -445,6 +445,18 @@ static inline int pmd_write(pmd_t pmd)
|
||||
#endif /* __HAVE_ARCH_PMD_WRITE */
|
||||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
|
||||
+#ifndef pmd_read_atomic
|
||||
+static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
|
||||
+{
|
||||
+ /*
|
||||
+ * Depend on compiler for an atomic pmd read. NOTE: this is
|
||||
+ * only going to work, if the pmdval_t isn't larger than
|
||||
+ * an unsigned long.
|
||||
+ */
|
||||
+ return *pmdp;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* This function is meant to be used by sites walking pagetables with
|
||||
* the mmap_sem hold in read mode to protect against MADV_DONTNEED and
|
||||
@@ -458,11 +470,17 @@ static inline int pmd_write(pmd_t pmd)
|
||||
* undefined so behaving like if the pmd was none is safe (because it
|
||||
* can return none anyway). The compiler level barrier() is critically
|
||||
* important to compute the two checks atomically on the same pmdval.
|
||||
+ *
|
||||
+ * For 32bit kernels with a 64bit large pmd_t this automatically takes
|
||||
+ * care of reading the pmd atomically to avoid SMP race conditions
|
||||
+ * against pmd_populate() when the mmap_sem is hold for reading by the
|
||||
+ * caller (a special atomic read not done by "gcc" as in the generic
|
||||
+ * version above, is also needed when THP is disabled because the page
|
||||
+ * fault can populate the pmd from under us).
|
||||
*/
|
||||
static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
|
||||
{
|
||||
- /* depend on compiler for an atomic pmd read */
|
||||
- pmd_t pmdval = *pmd;
|
||||
+ pmd_t pmdval = pmd_read_atomic(pmd);
|
||||
/*
|
||||
* The barrier will stabilize the pmdval in a register or on
|
||||
* the stack so that it will stop changing under the code.
|
|
@ -1,112 +0,0 @@
|
|||
From: Andrea Arcangeli <aarcange@redhat.com>
|
||||
Subject: thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE
|
||||
|
||||
In the x86 32bit PAE CONFIG_TRANSPARENT_HUGEPAGE=y case while holding the
|
||||
mmap_sem for reading, cmpxchg8b cannot be used to read pmd contents under
|
||||
Xen.
|
||||
|
||||
So instead of dealing only with "consistent" pmdvals in
|
||||
pmd_none_or_trans_huge_or_clear_bad() (which would be conceptually
|
||||
simpler) we let pmd_none_or_trans_huge_or_clear_bad() deal with pmdvals
|
||||
where the low 32bit and high 32bit could be inconsistent (to avoid having
|
||||
to use cmpxchg8b).
|
||||
|
||||
The only guarantee we get from pmd_read_atomic is that if the low part of
|
||||
the pmd was found null, the high part will be null too (so the pmd will be
|
||||
considered unstable). And if the low part of the pmd is found "stable"
|
||||
later, then it means the whole pmd was read atomically (because after a
|
||||
pmd is stable, neither MADV_DONTNEED nor page faults can alter it anymore,
|
||||
and we read the high part after the low part).
|
||||
|
||||
In the 32bit PAE x86 case, it is enough to read the low part of the pmdval
|
||||
atomically to declare the pmd as "stable" and that's true for THP and no
|
||||
THP, furthermore in the THP case we also have a barrier() that will
|
||||
prevent any inconsistent pmdvals to be cached by a later re-read of the
|
||||
*pmd.
|
||||
|
||||
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
|
||||
Cc: Jonathan Nieder <jrnieder@gmail.com>
|
||||
Cc: Ulrich Obergfell <uobergfe@redhat.com>
|
||||
Cc: Mel Gorman <mgorman@suse.de>
|
||||
Cc: Hugh Dickins <hughd@google.com>
|
||||
Cc: Larry Woodman <lwoodman@redhat.com>
|
||||
Cc: Petr Matousek <pmatouse@redhat.com>
|
||||
Cc: Rik van Riel <riel@redhat.com>
|
||||
Cc: Jan Beulich <jbeulich@suse.com>
|
||||
Cc: KOSAKI Motohiro <kosaki.motohiro@gmail.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
|
||||
arch/x86/include/asm/pgtable-3level.h | 30 +++++++++++++-----------
|
||||
include/asm-generic/pgtable.h | 10 ++++++++
|
||||
2 files changed, 27 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/arch/x86/include/asm/pgtable-3level.h
|
||||
+++ b/arch/x86/include/asm/pgtable-3level.h
|
||||
@@ -47,16 +47,26 @@
|
||||
* they can run pmd_offset_map_lock or pmd_trans_huge or other pmd
|
||||
* operations.
|
||||
*
|
||||
- * Without THP if the mmap_sem is hold for reading, the
|
||||
- * pmd can only transition from null to not null while pmd_read_atomic runs.
|
||||
- * So there's no need of literally reading it atomically.
|
||||
+ * Without THP if the mmap_sem is hold for reading, the pmd can only
|
||||
+ * transition from null to not null while pmd_read_atomic runs. So
|
||||
+ * we can always return atomic pmd values with this function.
|
||||
*
|
||||
* With THP if the mmap_sem is hold for reading, the pmd can become
|
||||
- * THP or null or point to a pte (and in turn become "stable") at any
|
||||
- * time under pmd_read_atomic, so it's mandatory to read it atomically
|
||||
- * with cmpxchg8b.
|
||||
+ * trans_huge or none or point to a pte (and in turn become "stable")
|
||||
+ * at any time under pmd_read_atomic. We could read it really
|
||||
+ * atomically here with a atomic64_read for the THP enabled case (and
|
||||
+ * it would be a whole lot simpler), but to avoid using cmpxchg8b we
|
||||
+ * only return an atomic pmdval if the low part of the pmdval is later
|
||||
+ * found stable (i.e. pointing to a pte). And we're returning a none
|
||||
+ * pmdval if the low part of the pmd is none. In some cases the high
|
||||
+ * and low part of the pmdval returned may not be consistent if THP is
|
||||
+ * enabled (the low part may point to previously mapped hugepage,
|
||||
+ * while the high part may point to a more recently mapped hugepage),
|
||||
+ * but pmd_none_or_trans_huge_or_clear_bad() only needs the low part
|
||||
+ * of the pmd to be read atomically to decide if the pmd is unstable
|
||||
+ * or not, with the only exception of when the low part of the pmd is
|
||||
+ * zero in which case we return a none pmd.
|
||||
*/
|
||||
-#ifndef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
|
||||
{
|
||||
pmdval_t ret;
|
||||
@@ -74,12 +84,6 @@
|
||||
|
||||
return (pmd_t) { ret };
|
||||
}
|
||||
-#else /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
-static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
|
||||
-{
|
||||
- return (pmd_t) { atomic64_read((atomic64_t *)pmdp) };
|
||||
-}
|
||||
-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
|
||||
static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
|
||||
{
|
||||
--- a/include/asm-generic/pgtable.h
|
||||
+++ b/include/asm-generic/pgtable.h
|
||||
@@ -484,6 +484,16 @@
|
||||
/*
|
||||
* The barrier will stabilize the pmdval in a register or on
|
||||
* the stack so that it will stop changing under the code.
|
||||
+ *
|
||||
+ * When CONFIG_TRANSPARENT_HUGEPAGE=y on x86 32bit PAE,
|
||||
+ * pmd_read_atomic is allowed to return a not atomic pmdval
|
||||
+ * (for example pointing to an hugepage that has never been
|
||||
+ * mapped in the pmd). The below checks will only care about
|
||||
+ * the low part of the pmd with 32bit PAE x86 anyway, with the
|
||||
+ * exception of pmd_none(). So the important thing is that if
|
||||
+ * the low part of the pmd is found null, the high part will
|
||||
+ * be also null or the pmd_none() check below would be
|
||||
+ * confused.
|
||||
*/
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
barrier();
|
|
@ -13,7 +13,7 @@ use of $(ARCH) needs to be moved after this.
|
|||
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -195,46 +195,6 @@
|
||||
@@ -195,42 +195,6 @@ export KBUILD_BUILDHOST := $(SUBARCH)
|
||||
ARCH ?= $(SUBARCH)
|
||||
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
|
||||
|
||||
|
@ -52,15 +52,11 @@ use of $(ARCH) needs to be moved after this.
|
|||
-
|
||||
-# Where to locate arch specific headers
|
||||
-hdr-arch := $(SRCARCH)
|
||||
-
|
||||
-ifeq ($(ARCH),m68knommu)
|
||||
- hdr-arch := m68k
|
||||
-endif
|
||||
-
|
||||
KCONFIG_CONFIG ?= .config
|
||||
export KCONFIG_CONFIG
|
||||
|
||||
@@ -354,6 +314,44 @@
|
||||
@@ -349,6 +313,44 @@ CFLAGS_KERNEL =
|
||||
AFLAGS_KERNEL =
|
||||
CFLAGS_GCOV = -fprofile-arcs -ftest-coverage
|
||||
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
From: Rick Jones <rick.jones2@hp.com>
|
||||
Date: Mon, 7 Nov 2011 13:29:27 +0000
|
||||
Subject: [PATCH 01/58] sweep the floors and convert some .get_drvinfo
|
||||
routines to strlcpy
|
||||
|
||||
commit 68aad78c5023b8aa82da99b47f9d8cf40e8ca453 upstream.
|
||||
|
||||
Per the mention made by Ben Hutchings that strlcpy is now the preferred
|
||||
string copy routine for a .get_drvinfo routine, do a bit of floor
|
||||
sweeping and convert some of the as-yet unconverted ethernet drivers to
|
||||
it.
|
||||
|
||||
Signed-off-by: Rick Jones <rick.jones2@hp.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
[bwh: Restrict to drivers/net/ethernet/emulex/benet/]
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_ethtool.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
index bf8153e..1ad7a28 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
@@ -127,8 +127,8 @@ static void be_get_drvinfo(struct net_device *netdev,
|
||||
memset(fw_on_flash, 0 , sizeof(fw_on_flash));
|
||||
be_cmd_get_fw_ver(adapter, adapter->fw_ver, fw_on_flash);
|
||||
|
||||
- strcpy(drvinfo->driver, DRV_NAME);
|
||||
- strcpy(drvinfo->version, DRV_VER);
|
||||
+ strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
|
||||
+ strlcpy(drvinfo->version, DRV_VER, sizeof(drvinfo->version));
|
||||
strncpy(drvinfo->fw_version, adapter->fw_ver, FW_VER_LEN);
|
||||
if (memcmp(adapter->fw_ver, fw_on_flash, FW_VER_LEN) != 0) {
|
||||
strcat(drvinfo->fw_version, " [");
|
||||
@@ -136,7 +136,8 @@ static void be_get_drvinfo(struct net_device *netdev,
|
||||
strcat(drvinfo->fw_version, "]");
|
||||
}
|
||||
|
||||
- strcpy(drvinfo->bus_info, pci_name(adapter->pdev));
|
||||
+ strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
|
||||
+ sizeof(drvinfo->bus_info));
|
||||
drvinfo->testinfo_len = 0;
|
||||
drvinfo->regdump_len = 0;
|
||||
drvinfo->eedump_len = 0;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,227 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Thu, 10 Nov 2011 19:17:57 +0000
|
||||
Subject: [PATCH 02/58] be2net: init (vf)_if_handle/vf_pmac_id to handle
|
||||
failure scenarios
|
||||
|
||||
commit 30128031d71741ef7d0e32c345e3bf02aa8a0704 upstream.
|
||||
|
||||
Initialize if_handle, vf_if_handle and vf_pmac_id with "-1" so that in
|
||||
failure cases when be_clear() is called, we can skip over
|
||||
if_destroy/pmac_del cmds if they have not been created.
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 8 ++--
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 9 +++--
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.h | 4 +-
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 55 +++++++++++++++------------
|
||||
4 files changed, 42 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index 644e8fe..4163980 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -289,14 +289,12 @@ struct be_drv_stats {
|
||||
|
||||
struct be_vf_cfg {
|
||||
unsigned char vf_mac_addr[ETH_ALEN];
|
||||
- u32 vf_if_handle;
|
||||
- u32 vf_pmac_id;
|
||||
+ int vf_if_handle;
|
||||
+ int vf_pmac_id;
|
||||
u16 vf_vlan_tag;
|
||||
u32 vf_tx_rate;
|
||||
};
|
||||
|
||||
-#define BE_INVALID_PMAC_ID 0xffffffff
|
||||
-
|
||||
struct be_adapter {
|
||||
struct pci_dev *pdev;
|
||||
struct net_device *netdev;
|
||||
@@ -347,7 +345,7 @@ struct be_adapter {
|
||||
|
||||
/* Ethtool knobs and info */
|
||||
char fw_ver[FW_VER_LEN];
|
||||
- u32 if_handle; /* Used to configure filtering */
|
||||
+ int if_handle; /* Used to configure filtering */
|
||||
u32 pmac_id; /* MAC addr handle used by BE card */
|
||||
u32 beacon_state; /* for set_phys_id */
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 2c7b366..c5912c4 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -695,12 +695,15 @@ err:
|
||||
}
|
||||
|
||||
/* Uses synchronous MCCQ */
|
||||
-int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id, u32 dom)
|
||||
+int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom)
|
||||
{
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_cmd_req_pmac_del *req;
|
||||
int status;
|
||||
|
||||
+ if (pmac_id == -1)
|
||||
+ return 0;
|
||||
+
|
||||
spin_lock_bh(&adapter->mcc_lock);
|
||||
|
||||
wrb = wrb_from_mccq(adapter);
|
||||
@@ -1136,7 +1139,7 @@ err:
|
||||
}
|
||||
|
||||
/* Uses MCCQ */
|
||||
-int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id, u32 domain)
|
||||
+int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain)
|
||||
{
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_cmd_req_if_destroy *req;
|
||||
@@ -1145,7 +1148,7 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id, u32 domain)
|
||||
if (adapter->eeh_err)
|
||||
return -EIO;
|
||||
|
||||
- if (!interface_id)
|
||||
+ if (interface_id == -1)
|
||||
return 0;
|
||||
|
||||
spin_lock_bh(&adapter->mcc_lock);
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
index a35cd03..0818039 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
@@ -1417,11 +1417,11 @@ extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
|
||||
extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
|
||||
u32 if_id, u32 *pmac_id, u32 domain);
|
||||
extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id,
|
||||
- u32 pmac_id, u32 domain);
|
||||
+ int pmac_id, u32 domain);
|
||||
extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags,
|
||||
u32 en_flags, u8 *mac, u32 *if_handle, u32 *pmac_id,
|
||||
u32 domain);
|
||||
-extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle,
|
||||
+extern int be_cmd_if_destroy(struct be_adapter *adapter, int if_handle,
|
||||
u32 domain);
|
||||
extern int be_cmd_eq_create(struct be_adapter *adapter,
|
||||
struct be_queue_info *eq, int eq_delay);
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index bf266a0..83d971d 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -848,15 +848,11 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
|
||||
if (!is_valid_ether_addr(mac) || (vf >= num_vfs))
|
||||
return -EINVAL;
|
||||
|
||||
- if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID)
|
||||
- status = be_cmd_pmac_del(adapter,
|
||||
- adapter->vf_cfg[vf].vf_if_handle,
|
||||
- adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
|
||||
+ status = be_cmd_pmac_del(adapter, adapter->vf_cfg[vf].vf_if_handle,
|
||||
+ adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
|
||||
|
||||
- status = be_cmd_pmac_add(adapter, mac,
|
||||
- adapter->vf_cfg[vf].vf_if_handle,
|
||||
+ status = be_cmd_pmac_add(adapter, mac, adapter->vf_cfg[vf].vf_if_handle,
|
||||
&adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
|
||||
-
|
||||
if (status)
|
||||
dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n",
|
||||
mac, vf);
|
||||
@@ -2488,17 +2484,13 @@ static void be_vf_clear(struct be_adapter *adapter)
|
||||
{
|
||||
u32 vf;
|
||||
|
||||
- for (vf = 0; vf < num_vfs; vf++) {
|
||||
- if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID)
|
||||
- be_cmd_pmac_del(adapter,
|
||||
- adapter->vf_cfg[vf].vf_if_handle,
|
||||
- adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
|
||||
- }
|
||||
+ for (vf = 0; vf < num_vfs; vf++)
|
||||
+ be_cmd_pmac_del(adapter, adapter->vf_cfg[vf].vf_if_handle,
|
||||
+ adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
|
||||
|
||||
for (vf = 0; vf < num_vfs; vf++)
|
||||
- if (adapter->vf_cfg[vf].vf_if_handle)
|
||||
- be_cmd_if_destroy(adapter,
|
||||
- adapter->vf_cfg[vf].vf_if_handle, vf + 1);
|
||||
+ be_cmd_if_destroy(adapter, adapter->vf_cfg[vf].vf_if_handle,
|
||||
+ vf + 1);
|
||||
}
|
||||
|
||||
static int be_clear(struct be_adapter *adapter)
|
||||
@@ -2511,22 +2503,30 @@ static int be_clear(struct be_adapter *adapter)
|
||||
be_mcc_queues_destroy(adapter);
|
||||
be_rx_queues_destroy(adapter);
|
||||
be_tx_queues_destroy(adapter);
|
||||
- adapter->eq_next_idx = 0;
|
||||
-
|
||||
- adapter->be3_native = false;
|
||||
- adapter->promiscuous = false;
|
||||
|
||||
/* tell fw we're done with firing cmds */
|
||||
be_cmd_fw_clean(adapter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void be_vf_setup_init(struct be_adapter *adapter)
|
||||
+{
|
||||
+ int vf;
|
||||
+
|
||||
+ for (vf = 0; vf < num_vfs; vf++) {
|
||||
+ adapter->vf_cfg[vf].vf_if_handle = -1;
|
||||
+ adapter->vf_cfg[vf].vf_pmac_id = -1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int be_vf_setup(struct be_adapter *adapter)
|
||||
{
|
||||
u32 cap_flags, en_flags, vf;
|
||||
u16 lnk_speed;
|
||||
int status;
|
||||
|
||||
+ be_vf_setup_init(adapter);
|
||||
+
|
||||
cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST;
|
||||
for (vf = 0; vf < num_vfs; vf++) {
|
||||
status = be_cmd_if_create(adapter, cap_flags, en_flags, NULL,
|
||||
@@ -2534,7 +2534,6 @@ static int be_vf_setup(struct be_adapter *adapter)
|
||||
NULL, vf+1);
|
||||
if (status)
|
||||
goto err;
|
||||
- adapter->vf_cfg[vf].vf_pmac_id = BE_INVALID_PMAC_ID;
|
||||
}
|
||||
|
||||
if (!lancer_chip(adapter)) {
|
||||
@@ -2555,6 +2554,16 @@ err:
|
||||
return status;
|
||||
}
|
||||
|
||||
+static void be_setup_init(struct be_adapter *adapter)
|
||||
+{
|
||||
+ adapter->vlan_prio_bmap = 0xff;
|
||||
+ adapter->link_speed = -1;
|
||||
+ adapter->if_handle = -1;
|
||||
+ adapter->be3_native = false;
|
||||
+ adapter->promiscuous = false;
|
||||
+ adapter->eq_next_idx = 0;
|
||||
+}
|
||||
+
|
||||
static int be_setup(struct be_adapter *adapter)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
@@ -2563,9 +2572,7 @@ static int be_setup(struct be_adapter *adapter)
|
||||
int status;
|
||||
u8 mac[ETH_ALEN];
|
||||
|
||||
- /* Allow all priorities by default. A GRP5 evt may modify this */
|
||||
- adapter->vlan_prio_bmap = 0xff;
|
||||
- adapter->link_speed = -1;
|
||||
+ be_setup_init(adapter);
|
||||
|
||||
be_cmd_req_native_mode(adapter);
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Thu, 10 Nov 2011 19:17:58 +0000
|
||||
Subject: [PATCH 03/58] be2net: stop checking the UE registers after an EEH
|
||||
error
|
||||
|
||||
commit 72f02485626b3e71955e54d227ede1b54021d571 upstream.
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 83d971d..99da07f 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -1978,6 +1978,9 @@ void be_detect_dump_ue(struct be_adapter *adapter)
|
||||
u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0;
|
||||
u32 i;
|
||||
|
||||
+ if (adapter->eeh_err || adapter->ue_detected)
|
||||
+ return;
|
||||
+
|
||||
if (lancer_chip(adapter)) {
|
||||
sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
|
||||
if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
|
||||
@@ -2039,8 +2042,7 @@ static void be_worker(struct work_struct *work)
|
||||
struct be_rx_obj *rxo;
|
||||
int i;
|
||||
|
||||
- if (!adapter->ue_detected)
|
||||
- be_detect_dump_ue(adapter);
|
||||
+ be_detect_dump_ue(adapter);
|
||||
|
||||
/* when interrupts are not yet enabled, just reap any pending
|
||||
* mcc completions */
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Thu, 10 Nov 2011 19:17:59 +0000
|
||||
Subject: [PATCH 04/58] be2net: don't log more than one error on detecting
|
||||
EEH/UE errors
|
||||
|
||||
commit 434b3648e9a58600cea5f3a1a0a7a89048e4df61 upstream.
|
||||
|
||||
Currently we're spamming error messages each time a FW cmd call is made
|
||||
while in EEH/UE error state. One log msg on error detection is enough.
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 15 +++------------
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 3 ++-
|
||||
2 files changed, 5 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index c5912c4..94cd77c 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -31,11 +31,8 @@ static void be_mcc_notify(struct be_adapter *adapter)
|
||||
struct be_queue_info *mccq = &adapter->mcc_obj.q;
|
||||
u32 val = 0;
|
||||
|
||||
- if (adapter->eeh_err) {
|
||||
- dev_info(&adapter->pdev->dev,
|
||||
- "Error in Card Detected! Cannot issue commands\n");
|
||||
+ if (adapter->eeh_err)
|
||||
return;
|
||||
- }
|
||||
|
||||
val |= mccq->id & DB_MCCQ_RING_ID_MASK;
|
||||
val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT;
|
||||
@@ -298,19 +295,13 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
|
||||
int msecs = 0;
|
||||
u32 ready;
|
||||
|
||||
- if (adapter->eeh_err) {
|
||||
- dev_err(&adapter->pdev->dev,
|
||||
- "Error detected in card.Cannot issue commands\n");
|
||||
+ if (adapter->eeh_err)
|
||||
return -EIO;
|
||||
- }
|
||||
|
||||
do {
|
||||
ready = ioread32(db);
|
||||
- if (ready == 0xffffffff) {
|
||||
- dev_err(&adapter->pdev->dev,
|
||||
- "pci slot disconnected\n");
|
||||
+ if (ready == 0xffffffff)
|
||||
return -1;
|
||||
- }
|
||||
|
||||
ready &= MPU_MAILBOX_DB_RDY_MASK;
|
||||
if (ready)
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 99da07f..0e97b6d 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -2007,7 +2007,8 @@ void be_detect_dump_ue(struct be_adapter *adapter)
|
||||
sliport_status & SLIPORT_STATUS_ERR_MASK) {
|
||||
adapter->ue_detected = true;
|
||||
adapter->eeh_err = true;
|
||||
- dev_err(&adapter->pdev->dev, "UE Detected!!\n");
|
||||
+ dev_err(&adapter->pdev->dev,
|
||||
+ "Unrecoverable error in the card\n");
|
||||
}
|
||||
|
||||
if (ue_lo) {
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Thu, 10 Nov 2011 19:18:00 +0000
|
||||
Subject: [PATCH 05/58] be2net: stop issuing FW cmds if any cmd times out
|
||||
|
||||
commit 6589ade019dcab245d3bb847370f855b56cdf6ad upstream.
|
||||
|
||||
A FW cmd timeout (with a sufficiently large timeout value in the
|
||||
order of tens of seconds) indicates an unresponsive FW. In this state
|
||||
issuing further cmds and waiting for a completion will only stall the process.
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 8 +++++++-
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 29 ++++++++++-----------------
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 2 ++
|
||||
3 files changed, 20 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index 4163980..34f162d 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -350,6 +350,8 @@ struct be_adapter {
|
||||
u32 beacon_state; /* for set_phys_id */
|
||||
|
||||
bool eeh_err;
|
||||
+ bool ue_detected;
|
||||
+ bool fw_timeout;
|
||||
u32 port_num;
|
||||
bool promiscuous;
|
||||
bool wol;
|
||||
@@ -357,7 +359,6 @@ struct be_adapter {
|
||||
u32 function_caps;
|
||||
u32 rx_fc; /* Rx flow control */
|
||||
u32 tx_fc; /* Tx flow control */
|
||||
- bool ue_detected;
|
||||
bool stats_cmd_sent;
|
||||
int link_speed;
|
||||
u8 port_type;
|
||||
@@ -522,6 +523,11 @@ static inline bool be_multi_rxq(const struct be_adapter *adapter)
|
||||
return adapter->num_rx_qs > 1;
|
||||
}
|
||||
|
||||
+static inline bool be_error(struct be_adapter *adapter)
|
||||
+{
|
||||
+ return adapter->eeh_err || adapter->ue_detected || adapter->fw_timeout;
|
||||
+}
|
||||
+
|
||||
extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
|
||||
u16 num_popped);
|
||||
extern void be_link_status_update(struct be_adapter *adapter, u32 link_status);
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 94cd77c..ad3eef0 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -31,7 +31,7 @@ static void be_mcc_notify(struct be_adapter *adapter)
|
||||
struct be_queue_info *mccq = &adapter->mcc_obj.q;
|
||||
u32 val = 0;
|
||||
|
||||
- if (adapter->eeh_err)
|
||||
+ if (be_error(adapter))
|
||||
return;
|
||||
|
||||
val |= mccq->id & DB_MCCQ_RING_ID_MASK;
|
||||
@@ -263,10 +263,10 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
|
||||
int i, num, status = 0;
|
||||
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
|
||||
|
||||
- if (adapter->eeh_err)
|
||||
- return -EIO;
|
||||
-
|
||||
for (i = 0; i < mcc_timeout; i++) {
|
||||
+ if (be_error(adapter))
|
||||
+ return -EIO;
|
||||
+
|
||||
num = be_process_mcc(adapter, &status);
|
||||
if (num)
|
||||
be_cq_notify(adapter, mcc_obj->cq.id,
|
||||
@@ -277,7 +277,8 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
|
||||
udelay(100);
|
||||
}
|
||||
if (i == mcc_timeout) {
|
||||
- dev_err(&adapter->pdev->dev, "mccq poll timed out\n");
|
||||
+ dev_err(&adapter->pdev->dev, "FW not responding\n");
|
||||
+ adapter->fw_timeout = true;
|
||||
return -1;
|
||||
}
|
||||
return status;
|
||||
@@ -295,10 +296,10 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
|
||||
int msecs = 0;
|
||||
u32 ready;
|
||||
|
||||
- if (adapter->eeh_err)
|
||||
- return -EIO;
|
||||
-
|
||||
do {
|
||||
+ if (be_error(adapter))
|
||||
+ return -EIO;
|
||||
+
|
||||
ready = ioread32(db);
|
||||
if (ready == 0xffffffff)
|
||||
return -1;
|
||||
@@ -308,7 +309,8 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
|
||||
break;
|
||||
|
||||
if (msecs > 4000) {
|
||||
- dev_err(&adapter->pdev->dev, "mbox poll timed out\n");
|
||||
+ dev_err(&adapter->pdev->dev, "FW not responding\n");
|
||||
+ adapter->fw_timeout = true;
|
||||
be_detect_dump_ue(adapter);
|
||||
return -1;
|
||||
}
|
||||
@@ -546,9 +548,6 @@ int be_cmd_fw_clean(struct be_adapter *adapter)
|
||||
u8 *wrb;
|
||||
int status;
|
||||
|
||||
- if (adapter->eeh_err)
|
||||
- return -EIO;
|
||||
-
|
||||
if (mutex_lock_interruptible(&adapter->mbox_lock))
|
||||
return -1;
|
||||
|
||||
@@ -1012,9 +1011,6 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
|
||||
u8 subsys = 0, opcode = 0;
|
||||
int status;
|
||||
|
||||
- if (adapter->eeh_err)
|
||||
- return -EIO;
|
||||
-
|
||||
if (mutex_lock_interruptible(&adapter->mbox_lock))
|
||||
return -1;
|
||||
|
||||
@@ -1136,9 +1132,6 @@ int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain)
|
||||
struct be_cmd_req_if_destroy *req;
|
||||
int status;
|
||||
|
||||
- if (adapter->eeh_err)
|
||||
- return -EIO;
|
||||
-
|
||||
if (interface_id == -1)
|
||||
return 0;
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 0e97b6d..ce20d64 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -3569,6 +3569,8 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev)
|
||||
|
||||
dev_info(&adapter->pdev->dev, "EEH reset\n");
|
||||
adapter->eeh_err = false;
|
||||
+ adapter->ue_detected = false;
|
||||
+ adapter->fw_timeout = false;
|
||||
|
||||
status = pci_enable_device(pdev);
|
||||
if (status)
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Wed, 16 Nov 2011 02:02:23 +0000
|
||||
Subject: [PATCH 06/58] be2net: Fix TX queue create for Lancer
|
||||
|
||||
commit 293c4a7d9b95d0beeb5df03c14bd35bc21f9e6f2 upstream.
|
||||
|
||||
Lancer uses V1 version of TXQ create. This command needs interface
|
||||
id for TX queue creation. Rearrange code such that tx queue create
|
||||
is after interface create. As TXQ create is now called after MCC
|
||||
ring create use MCC instead of MBOX.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 15 ++++++++++-----
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 12 ++++++++----
|
||||
2 files changed, 18 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index ad3eef0..d35a214 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -916,10 +916,14 @@ int be_cmd_txq_create(struct be_adapter *adapter,
|
||||
void *ctxt;
|
||||
int status;
|
||||
|
||||
- if (mutex_lock_interruptible(&adapter->mbox_lock))
|
||||
- return -1;
|
||||
+ spin_lock_bh(&adapter->mcc_lock);
|
||||
+
|
||||
+ wrb = wrb_from_mccq(adapter);
|
||||
+ if (!wrb) {
|
||||
+ status = -EBUSY;
|
||||
+ goto err;
|
||||
+ }
|
||||
|
||||
- wrb = wrb_from_mbox(adapter);
|
||||
req = embedded_payload(wrb);
|
||||
ctxt = &req->context;
|
||||
|
||||
@@ -945,14 +949,15 @@ int be_cmd_txq_create(struct be_adapter *adapter,
|
||||
|
||||
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
|
||||
|
||||
- status = be_mbox_notify_wait(adapter);
|
||||
+ status = be_mcc_notify_wait(adapter);
|
||||
if (!status) {
|
||||
struct be_cmd_resp_eth_tx_create *resp = embedded_payload(wrb);
|
||||
txq->id = le16_to_cpu(resp->cid);
|
||||
txq->created = true;
|
||||
}
|
||||
|
||||
- mutex_unlock(&adapter->mbox_lock);
|
||||
+err:
|
||||
+ spin_unlock_bh(&adapter->mcc_lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index ce20d64..c982b51 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -1689,9 +1689,6 @@ static int be_tx_queues_create(struct be_adapter *adapter)
|
||||
if (be_queue_alloc(adapter, q, TX_Q_LEN,
|
||||
sizeof(struct be_eth_wrb)))
|
||||
goto err;
|
||||
-
|
||||
- if (be_cmd_txq_create(adapter, q, cq))
|
||||
- goto err;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -2572,8 +2569,9 @@ static int be_setup(struct be_adapter *adapter)
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
u32 cap_flags, en_flags;
|
||||
u32 tx_fc, rx_fc;
|
||||
- int status;
|
||||
+ int status, i;
|
||||
u8 mac[ETH_ALEN];
|
||||
+ struct be_tx_obj *txo;
|
||||
|
||||
be_setup_init(adapter);
|
||||
|
||||
@@ -2613,6 +2611,12 @@ static int be_setup(struct be_adapter *adapter)
|
||||
if (status != 0)
|
||||
goto err;
|
||||
|
||||
+ for_all_tx_queues(adapter, txo, i) {
|
||||
+ status = be_cmd_txq_create(adapter, &txo->q, &txo->cq);
|
||||
+ if (status)
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
/* For BEx, the VF's permanent mac queried from card is incorrect.
|
||||
* Query the mac configued by the PF using if_handle
|
||||
*/
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,234 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Wed, 16 Nov 2011 02:02:43 +0000
|
||||
Subject: [PATCH 07/58] be2net: add register dump feature for Lancer
|
||||
|
||||
commit de49bd5a447887fa630c54bb2769102d50fbe40a upstream.
|
||||
|
||||
Implement register dump using ethtool for Lancer.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 47 +++++++++++++++
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.h | 34 +++++++++++
|
||||
drivers/net/ethernet/emulex/benet/be_ethtool.c | 74 ++++++++++++++++++++++--
|
||||
3 files changed, 151 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index d35a214..1522065 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -1828,6 +1828,53 @@ err_unlock:
|
||||
return status;
|
||||
}
|
||||
|
||||
+int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
||||
+ u32 data_size, u32 data_offset, const char *obj_name,
|
||||
+ u32 *data_read, u32 *eof, u8 *addn_status)
|
||||
+{
|
||||
+ struct be_mcc_wrb *wrb;
|
||||
+ struct lancer_cmd_req_read_object *req;
|
||||
+ struct lancer_cmd_resp_read_object *resp;
|
||||
+ int status;
|
||||
+
|
||||
+ spin_lock_bh(&adapter->mcc_lock);
|
||||
+
|
||||
+ wrb = wrb_from_mccq(adapter);
|
||||
+ if (!wrb) {
|
||||
+ status = -EBUSY;
|
||||
+ goto err_unlock;
|
||||
+ }
|
||||
+
|
||||
+ req = embedded_payload(wrb);
|
||||
+
|
||||
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
+ OPCODE_COMMON_READ_OBJECT,
|
||||
+ sizeof(struct lancer_cmd_req_read_object), wrb,
|
||||
+ NULL);
|
||||
+
|
||||
+ req->desired_read_len = cpu_to_le32(data_size);
|
||||
+ req->read_offset = cpu_to_le32(data_offset);
|
||||
+ strcpy(req->object_name, obj_name);
|
||||
+ req->descriptor_count = cpu_to_le32(1);
|
||||
+ req->buf_len = cpu_to_le32(data_size);
|
||||
+ req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF));
|
||||
+ req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma));
|
||||
+
|
||||
+ status = be_mcc_notify_wait(adapter);
|
||||
+
|
||||
+ resp = embedded_payload(wrb);
|
||||
+ if (!status) {
|
||||
+ *data_read = le32_to_cpu(resp->actual_read_len);
|
||||
+ *eof = le32_to_cpu(resp->eof);
|
||||
+ } else {
|
||||
+ *addn_status = resp->additional_status;
|
||||
+ }
|
||||
+
|
||||
+err_unlock:
|
||||
+ spin_unlock_bh(&adapter->mcc_lock);
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
||||
u32 flash_type, u32 flash_opcode, u32 buf_size)
|
||||
{
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
index 0818039..2d3fe6a 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
@@ -189,6 +189,7 @@ struct be_mcc_mailbox {
|
||||
#define OPCODE_COMMON_GET_PHY_DETAILS 102
|
||||
#define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103
|
||||
#define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121
|
||||
+#define OPCODE_COMMON_READ_OBJECT 171
|
||||
#define OPCODE_COMMON_WRITE_OBJECT 172
|
||||
|
||||
#define OPCODE_ETH_RSS_CONFIG 1
|
||||
@@ -1161,6 +1162,36 @@ struct lancer_cmd_resp_write_object {
|
||||
u32 actual_write_len;
|
||||
};
|
||||
|
||||
+/************************ Lancer Read FW info **************/
|
||||
+#define LANCER_READ_FILE_CHUNK (32*1024)
|
||||
+#define LANCER_READ_FILE_EOF_MASK 0x80000000
|
||||
+
|
||||
+#define LANCER_FW_DUMP_FILE "/dbg/dump.bin"
|
||||
+
|
||||
+struct lancer_cmd_req_read_object {
|
||||
+ struct be_cmd_req_hdr hdr;
|
||||
+ u32 desired_read_len;
|
||||
+ u32 read_offset;
|
||||
+ u8 object_name[104];
|
||||
+ u32 descriptor_count;
|
||||
+ u32 buf_len;
|
||||
+ u32 addr_low;
|
||||
+ u32 addr_high;
|
||||
+};
|
||||
+
|
||||
+struct lancer_cmd_resp_read_object {
|
||||
+ u8 opcode;
|
||||
+ u8 subsystem;
|
||||
+ u8 rsvd1[2];
|
||||
+ u8 status;
|
||||
+ u8 additional_status;
|
||||
+ u8 rsvd2[2];
|
||||
+ u32 resp_len;
|
||||
+ u32 actual_resp_len;
|
||||
+ u32 actual_read_len;
|
||||
+ u32 eof;
|
||||
+};
|
||||
+
|
||||
/************************ WOL *******************************/
|
||||
struct be_cmd_req_acpi_wol_magic_config{
|
||||
struct be_cmd_req_hdr hdr;
|
||||
@@ -1480,6 +1511,9 @@ extern int lancer_cmd_write_object(struct be_adapter *adapter,
|
||||
u32 data_size, u32 data_offset,
|
||||
const char *obj_name,
|
||||
u32 *data_written, u8 *addn_status);
|
||||
+int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
||||
+ u32 data_size, u32 data_offset, const char *obj_name,
|
||||
+ u32 *data_read, u32 *eof, u8 *addn_status);
|
||||
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
|
||||
int offset);
|
||||
extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
index 1ad7a28..1e7252e 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
@@ -143,15 +143,77 @@ static void be_get_drvinfo(struct net_device *netdev,
|
||||
drvinfo->eedump_len = 0;
|
||||
}
|
||||
|
||||
+static u32
|
||||
+lancer_cmd_get_file_len(struct be_adapter *adapter, u8 *file_name)
|
||||
+{
|
||||
+ u32 data_read = 0, eof;
|
||||
+ u8 addn_status;
|
||||
+ struct be_dma_mem data_len_cmd;
|
||||
+ int status;
|
||||
+
|
||||
+ memset(&data_len_cmd, 0, sizeof(data_len_cmd));
|
||||
+ /* data_offset and data_size should be 0 to get reg len */
|
||||
+ status = lancer_cmd_read_object(adapter, &data_len_cmd, 0, 0,
|
||||
+ file_name, &data_read, &eof, &addn_status);
|
||||
+
|
||||
+ return data_read;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+lancer_cmd_read_file(struct be_adapter *adapter, u8 *file_name,
|
||||
+ u32 buf_len, void *buf)
|
||||
+{
|
||||
+ struct be_dma_mem read_cmd;
|
||||
+ u32 read_len = 0, total_read_len = 0, chunk_size;
|
||||
+ u32 eof = 0;
|
||||
+ u8 addn_status;
|
||||
+ int status = 0;
|
||||
+
|
||||
+ read_cmd.size = LANCER_READ_FILE_CHUNK;
|
||||
+ read_cmd.va = pci_alloc_consistent(adapter->pdev, read_cmd.size,
|
||||
+ &read_cmd.dma);
|
||||
+
|
||||
+ if (!read_cmd.va) {
|
||||
+ dev_err(&adapter->pdev->dev,
|
||||
+ "Memory allocation failure while reading dump\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ while ((total_read_len < buf_len) && !eof) {
|
||||
+ chunk_size = min_t(u32, (buf_len - total_read_len),
|
||||
+ LANCER_READ_FILE_CHUNK);
|
||||
+ chunk_size = ALIGN(chunk_size, 4);
|
||||
+ status = lancer_cmd_read_object(adapter, &read_cmd, chunk_size,
|
||||
+ total_read_len, file_name, &read_len,
|
||||
+ &eof, &addn_status);
|
||||
+ if (!status) {
|
||||
+ memcpy(buf + total_read_len, read_cmd.va, read_len);
|
||||
+ total_read_len += read_len;
|
||||
+ eof &= LANCER_READ_FILE_EOF_MASK;
|
||||
+ } else {
|
||||
+ status = -EIO;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ pci_free_consistent(adapter->pdev, read_cmd.size, read_cmd.va,
|
||||
+ read_cmd.dma);
|
||||
+
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
be_get_reg_len(struct net_device *netdev)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
u32 log_size = 0;
|
||||
|
||||
- if (be_physfn(adapter))
|
||||
- be_cmd_get_reg_len(adapter, &log_size);
|
||||
-
|
||||
+ if (be_physfn(adapter)) {
|
||||
+ if (lancer_chip(adapter))
|
||||
+ log_size = lancer_cmd_get_file_len(adapter,
|
||||
+ LANCER_FW_DUMP_FILE);
|
||||
+ else
|
||||
+ be_cmd_get_reg_len(adapter, &log_size);
|
||||
+ }
|
||||
return log_size;
|
||||
}
|
||||
|
||||
@@ -162,7 +224,11 @@ be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
|
||||
|
||||
if (be_physfn(adapter)) {
|
||||
memset(buf, 0, regs->len);
|
||||
- be_cmd_get_regs(adapter, regs->len, buf);
|
||||
+ if (lancer_chip(adapter))
|
||||
+ lancer_cmd_read_file(adapter, LANCER_FW_DUMP_FILE,
|
||||
+ regs->len, buf);
|
||||
+ else
|
||||
+ be_cmd_get_regs(adapter, regs->len, buf);
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Wed, 16 Nov 2011 02:03:07 +0000
|
||||
Subject: [PATCH 08/58] be2net: Add EEPROM dump feature for Lancer
|
||||
|
||||
commit af5875bdfed02a10a0c76bbd547753fea7979244 upstream.
|
||||
|
||||
Implemented eeprom dump using ethtool feature for Lancer.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.h | 2 ++
|
||||
drivers/net/ethernet/emulex/benet/be_ethtool.c | 21 ++++++++++++++++++++-
|
||||
2 files changed, 22 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
index 2d3fe6a..ac11246 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
@@ -1167,6 +1167,8 @@ struct lancer_cmd_resp_write_object {
|
||||
#define LANCER_READ_FILE_EOF_MASK 0x80000000
|
||||
|
||||
#define LANCER_FW_DUMP_FILE "/dbg/dump.bin"
|
||||
+#define LANCER_VPD_PF_FILE "/vpd/ntr_pf.vpd"
|
||||
+#define LANCER_VPD_VF_FILE "/vpd/ntr_vf.vpd"
|
||||
|
||||
struct lancer_cmd_req_read_object {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
index 1e7252e..575c783 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
@@ -727,7 +727,17 @@ be_do_flash(struct net_device *netdev, struct ethtool_flash *efl)
|
||||
static int
|
||||
be_get_eeprom_len(struct net_device *netdev)
|
||||
{
|
||||
- return BE_READ_SEEPROM_LEN;
|
||||
+ struct be_adapter *adapter = netdev_priv(netdev);
|
||||
+ if (lancer_chip(adapter)) {
|
||||
+ if (be_physfn(adapter))
|
||||
+ return lancer_cmd_get_file_len(adapter,
|
||||
+ LANCER_VPD_PF_FILE);
|
||||
+ else
|
||||
+ return lancer_cmd_get_file_len(adapter,
|
||||
+ LANCER_VPD_VF_FILE);
|
||||
+ } else {
|
||||
+ return BE_READ_SEEPROM_LEN;
|
||||
+ }
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -742,6 +752,15 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
|
||||
if (!eeprom->len)
|
||||
return -EINVAL;
|
||||
|
||||
+ if (lancer_chip(adapter)) {
|
||||
+ if (be_physfn(adapter))
|
||||
+ return lancer_cmd_read_file(adapter, LANCER_VPD_PF_FILE,
|
||||
+ eeprom->len, data);
|
||||
+ else
|
||||
+ return lancer_cmd_read_file(adapter, LANCER_VPD_VF_FILE,
|
||||
+ eeprom->len, data);
|
||||
+ }
|
||||
+
|
||||
eeprom->magic = BE_VENDOR_ID | (adapter->pdev->device<<16);
|
||||
|
||||
memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem));
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Wed, 16 Nov 2011 02:03:32 +0000
|
||||
Subject: [PATCH 09/58] be2net: Fix VLAN promiscous mode for Lancer
|
||||
|
||||
commit 5d5adb93d0efca8b47cc3e649a41ba650ff3d270 upstream.
|
||||
|
||||
To enable VLAN promiscous mode, the HW interface should be created
|
||||
with VLAN promiscous capability in Lancer. Add this capability during
|
||||
creation of the HW interface.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index c982b51..93869d4 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -2600,7 +2600,8 @@ static int be_setup(struct be_adapter *adapter)
|
||||
en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
|
||||
BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS;
|
||||
cap_flags = en_flags | BE_IF_FLAGS_MCAST_PROMISCUOUS |
|
||||
- BE_IF_FLAGS_PROMISCUOUS;
|
||||
+ BE_IF_FLAGS_VLAN_PROMISCUOUS | BE_IF_FLAGS_PROMISCUOUS;
|
||||
+
|
||||
if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) {
|
||||
cap_flags |= BE_IF_FLAGS_RSS;
|
||||
en_flags |= BE_IF_FLAGS_RSS;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Wed, 16 Nov 2011 02:03:45 +0000
|
||||
Subject: [PATCH 10/58] be2net: Use V1 query link status command for lancer
|
||||
|
||||
commit daad6167d97b43cfc448cfe698784730b53ed3d6 upstream.
|
||||
|
||||
Use V1 version of query link status command for Lancer.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 1522065..64f0c1a 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -1246,6 +1246,9 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
|
||||
}
|
||||
req = embedded_payload(wrb);
|
||||
|
||||
+ if (lancer_chip(adapter))
|
||||
+ req->hdr.version = 1;
|
||||
+
|
||||
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL);
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,393 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Fri, 25 Nov 2011 05:47:26 +0000
|
||||
Subject: [PATCH 11/58] be2net: Move to new SR-IOV implementation in Lancer
|
||||
|
||||
commit 590c391dd362479b27a67c8d797ce348c5798b93 upstream.
|
||||
|
||||
SR-IOV implementation is Lancer has changed in following ways -
|
||||
1)PF driver assigns one MAC addresses for VF using COMMON_SET_IFACE_MAC_LIST.
|
||||
2)VF driver queries its MAC address using COMMON_GET_IFACE_MAC_LIST command
|
||||
and assigns it to its interface.
|
||||
|
||||
Signed-off-by: Mammatha Edhala <mammatha.edhala@emulex.com>
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 99 ++++++++++++++++++++++++++-
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.h | 37 +++++++++-
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 89 +++++++++++++++++-------
|
||||
3 files changed, 200 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 64f0c1a..7988798 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -609,7 +609,7 @@ int be_cmd_eq_create(struct be_adapter *adapter,
|
||||
|
||||
/* Use MCC */
|
||||
int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
|
||||
- u8 type, bool permanent, u32 if_handle)
|
||||
+ u8 type, bool permanent, u32 if_handle, u32 pmac_id)
|
||||
{
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_cmd_req_mac_query *req;
|
||||
@@ -631,6 +631,7 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
|
||||
req->permanent = 1;
|
||||
} else {
|
||||
req->if_id = cpu_to_le16((u16) if_handle);
|
||||
+ req->pmac_id = cpu_to_le32(pmac_id);
|
||||
req->permanent = 0;
|
||||
}
|
||||
|
||||
@@ -2280,3 +2281,99 @@ err:
|
||||
mutex_unlock(&adapter->mbox_lock);
|
||||
return status;
|
||||
}
|
||||
+
|
||||
+/* Uses synchronous MCCQ */
|
||||
+int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain,
|
||||
+ u32 *pmac_id)
|
||||
+{
|
||||
+ struct be_mcc_wrb *wrb;
|
||||
+ struct be_cmd_req_get_mac_list *req;
|
||||
+ int status;
|
||||
+ int mac_count;
|
||||
+
|
||||
+ spin_lock_bh(&adapter->mcc_lock);
|
||||
+
|
||||
+ wrb = wrb_from_mccq(adapter);
|
||||
+ if (!wrb) {
|
||||
+ status = -EBUSY;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ req = embedded_payload(wrb);
|
||||
+
|
||||
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
+ OPCODE_COMMON_GET_MAC_LIST, sizeof(*req),
|
||||
+ wrb, NULL);
|
||||
+
|
||||
+ req->hdr.domain = domain;
|
||||
+
|
||||
+ status = be_mcc_notify_wait(adapter);
|
||||
+ if (!status) {
|
||||
+ struct be_cmd_resp_get_mac_list *resp =
|
||||
+ embedded_payload(wrb);
|
||||
+ int i;
|
||||
+ u8 *ctxt = &resp->context[0][0];
|
||||
+ status = -EIO;
|
||||
+ mac_count = resp->mac_count;
|
||||
+ be_dws_le_to_cpu(&resp->context, sizeof(resp->context));
|
||||
+ for (i = 0; i < mac_count; i++) {
|
||||
+ if (!AMAP_GET_BITS(struct amap_get_mac_list_context,
|
||||
+ act, ctxt)) {
|
||||
+ *pmac_id = AMAP_GET_BITS
|
||||
+ (struct amap_get_mac_list_context,
|
||||
+ macid, ctxt);
|
||||
+ status = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ ctxt += sizeof(struct amap_get_mac_list_context) / 8;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+err:
|
||||
+ spin_unlock_bh(&adapter->mcc_lock);
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+/* Uses synchronous MCCQ */
|
||||
+int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
|
||||
+ u8 mac_count, u32 domain)
|
||||
+{
|
||||
+ struct be_mcc_wrb *wrb;
|
||||
+ struct be_cmd_req_set_mac_list *req;
|
||||
+ int status;
|
||||
+ struct be_dma_mem cmd;
|
||||
+
|
||||
+ memset(&cmd, 0, sizeof(struct be_dma_mem));
|
||||
+ cmd.size = sizeof(struct be_cmd_req_set_mac_list);
|
||||
+ cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size,
|
||||
+ &cmd.dma, GFP_KERNEL);
|
||||
+ if (!cmd.va) {
|
||||
+ dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ spin_lock_bh(&adapter->mcc_lock);
|
||||
+
|
||||
+ wrb = wrb_from_mccq(adapter);
|
||||
+ if (!wrb) {
|
||||
+ status = -EBUSY;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ req = cmd.va;
|
||||
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
+ OPCODE_COMMON_SET_MAC_LIST, sizeof(*req),
|
||||
+ wrb, &cmd);
|
||||
+
|
||||
+ req->hdr.domain = domain;
|
||||
+ req->mac_count = mac_count;
|
||||
+ if (mac_count)
|
||||
+ memcpy(req->mac, mac_array, ETH_ALEN*mac_count);
|
||||
+
|
||||
+ status = be_mcc_notify_wait(adapter);
|
||||
+
|
||||
+err:
|
||||
+ dma_free_coherent(&adapter->pdev->dev, cmd.size,
|
||||
+ cmd.va, cmd.dma);
|
||||
+ spin_unlock_bh(&adapter->mcc_lock);
|
||||
+ return status;
|
||||
+}
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
index ac11246..0b694c6 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
@@ -189,6 +189,8 @@ struct be_mcc_mailbox {
|
||||
#define OPCODE_COMMON_GET_PHY_DETAILS 102
|
||||
#define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103
|
||||
#define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121
|
||||
+#define OPCODE_COMMON_GET_MAC_LIST 147
|
||||
+#define OPCODE_COMMON_SET_MAC_LIST 148
|
||||
#define OPCODE_COMMON_READ_OBJECT 171
|
||||
#define OPCODE_COMMON_WRITE_OBJECT 172
|
||||
|
||||
@@ -295,6 +297,7 @@ struct be_cmd_req_mac_query {
|
||||
u8 type;
|
||||
u8 permanent;
|
||||
u16 if_id;
|
||||
+ u32 pmac_id;
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_resp_mac_query {
|
||||
@@ -1340,6 +1343,34 @@ struct be_cmd_resp_set_func_cap {
|
||||
u8 rsvd[212];
|
||||
};
|
||||
|
||||
+/******************** GET/SET_MACLIST **************************/
|
||||
+#define BE_MAX_MAC 64
|
||||
+struct amap_get_mac_list_context {
|
||||
+ u8 macid[31];
|
||||
+ u8 act;
|
||||
+} __packed;
|
||||
+
|
||||
+struct be_cmd_req_get_mac_list {
|
||||
+ struct be_cmd_req_hdr hdr;
|
||||
+ u32 rsvd;
|
||||
+} __packed;
|
||||
+
|
||||
+struct be_cmd_resp_get_mac_list {
|
||||
+ struct be_cmd_resp_hdr hdr;
|
||||
+ u8 mac_count;
|
||||
+ u8 rsvd1;
|
||||
+ u16 rsvd2;
|
||||
+ u8 context[sizeof(struct amap_get_mac_list_context) / 8][BE_MAX_MAC];
|
||||
+} __packed;
|
||||
+
|
||||
+struct be_cmd_req_set_mac_list {
|
||||
+ struct be_cmd_req_hdr hdr;
|
||||
+ u8 mac_count;
|
||||
+ u8 rsvd1;
|
||||
+ u16 rsvd2;
|
||||
+ struct macaddr mac[BE_MAX_MAC];
|
||||
+} __packed;
|
||||
+
|
||||
/*************** HW Stats Get v1 **********************************/
|
||||
#define BE_TXP_SW_SZ 48
|
||||
struct be_port_rxf_stats_v1 {
|
||||
@@ -1446,7 +1477,7 @@ static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter)
|
||||
extern int be_pci_fnum_get(struct be_adapter *adapter);
|
||||
extern int be_cmd_POST(struct be_adapter *adapter);
|
||||
extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
|
||||
- u8 type, bool permanent, u32 if_handle);
|
||||
+ u8 type, bool permanent, u32 if_handle, u32 pmac_id);
|
||||
extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
|
||||
u32 if_id, u32 *pmac_id, u32 domain);
|
||||
extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id,
|
||||
@@ -1542,4 +1573,8 @@ extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
|
||||
extern int be_cmd_req_native_mode(struct be_adapter *adapter);
|
||||
extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
|
||||
extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
|
||||
+extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain,
|
||||
+ u32 *pmac_id);
|
||||
+extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
|
||||
+ u8 mac_count, u32 domain);
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 93869d4..c6fb7c3 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -237,7 +237,8 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
status = be_cmd_mac_addr_query(adapter, current_mac,
|
||||
- MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle);
|
||||
+ MAC_ADDRESS_TYPE_NETWORK, false,
|
||||
+ adapter->if_handle, 0);
|
||||
if (status)
|
||||
goto err;
|
||||
|
||||
@@ -848,11 +849,18 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
|
||||
if (!is_valid_ether_addr(mac) || (vf >= num_vfs))
|
||||
return -EINVAL;
|
||||
|
||||
- status = be_cmd_pmac_del(adapter, adapter->vf_cfg[vf].vf_if_handle,
|
||||
+ if (lancer_chip(adapter)) {
|
||||
+ status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1);
|
||||
+ } else {
|
||||
+ status = be_cmd_pmac_del(adapter,
|
||||
+ adapter->vf_cfg[vf].vf_if_handle,
|
||||
adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
|
||||
|
||||
- status = be_cmd_pmac_add(adapter, mac, adapter->vf_cfg[vf].vf_if_handle,
|
||||
+ status = be_cmd_pmac_add(adapter, mac,
|
||||
+ adapter->vf_cfg[vf].vf_if_handle,
|
||||
&adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
|
||||
+ }
|
||||
+
|
||||
if (status)
|
||||
dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n",
|
||||
mac, vf);
|
||||
@@ -2465,13 +2473,18 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter)
|
||||
be_vf_eth_addr_generate(adapter, mac);
|
||||
|
||||
for (vf = 0; vf < num_vfs; vf++) {
|
||||
- status = be_cmd_pmac_add(adapter, mac,
|
||||
+ if (lancer_chip(adapter)) {
|
||||
+ status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1);
|
||||
+ } else {
|
||||
+ status = be_cmd_pmac_add(adapter, mac,
|
||||
adapter->vf_cfg[vf].vf_if_handle,
|
||||
&adapter->vf_cfg[vf].vf_pmac_id,
|
||||
vf + 1);
|
||||
+ }
|
||||
+
|
||||
if (status)
|
||||
dev_err(&adapter->pdev->dev,
|
||||
- "Mac address add failed for VF %d\n", vf);
|
||||
+ "Mac address assignment failed for VF %d\n", vf);
|
||||
else
|
||||
memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN);
|
||||
|
||||
@@ -2484,9 +2497,14 @@ static void be_vf_clear(struct be_adapter *adapter)
|
||||
{
|
||||
u32 vf;
|
||||
|
||||
- for (vf = 0; vf < num_vfs; vf++)
|
||||
- be_cmd_pmac_del(adapter, adapter->vf_cfg[vf].vf_if_handle,
|
||||
- adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
|
||||
+ for (vf = 0; vf < num_vfs; vf++) {
|
||||
+ if (lancer_chip(adapter))
|
||||
+ be_cmd_set_mac_list(adapter, NULL, 0, vf + 1);
|
||||
+ else
|
||||
+ be_cmd_pmac_del(adapter,
|
||||
+ adapter->vf_cfg[vf].vf_if_handle,
|
||||
+ adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
|
||||
+ }
|
||||
|
||||
for (vf = 0; vf < num_vfs; vf++)
|
||||
be_cmd_if_destroy(adapter, adapter->vf_cfg[vf].vf_if_handle,
|
||||
@@ -2527,7 +2545,9 @@ static int be_vf_setup(struct be_adapter *adapter)
|
||||
|
||||
be_vf_setup_init(adapter);
|
||||
|
||||
- cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST;
|
||||
+ cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
|
||||
+ BE_IF_FLAGS_MULTICAST;
|
||||
+
|
||||
for (vf = 0; vf < num_vfs; vf++) {
|
||||
status = be_cmd_if_create(adapter, cap_flags, en_flags, NULL,
|
||||
&adapter->vf_cfg[vf].vf_if_handle,
|
||||
@@ -2536,11 +2556,9 @@ static int be_vf_setup(struct be_adapter *adapter)
|
||||
goto err;
|
||||
}
|
||||
|
||||
- if (!lancer_chip(adapter)) {
|
||||
- status = be_vf_eth_addr_config(adapter);
|
||||
- if (status)
|
||||
- goto err;
|
||||
- }
|
||||
+ status = be_vf_eth_addr_config(adapter);
|
||||
+ if (status)
|
||||
+ goto err;
|
||||
|
||||
for (vf = 0; vf < num_vfs; vf++) {
|
||||
status = be_cmd_link_status_query(adapter, NULL, &lnk_speed,
|
||||
@@ -2564,6 +2582,23 @@ static void be_setup_init(struct be_adapter *adapter)
|
||||
adapter->eq_next_idx = 0;
|
||||
}
|
||||
|
||||
+static int be_configure_mac_from_list(struct be_adapter *adapter, u8 *mac)
|
||||
+{
|
||||
+ u32 pmac_id;
|
||||
+ int status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id);
|
||||
+ if (status != 0)
|
||||
+ goto do_none;
|
||||
+ status = be_cmd_mac_addr_query(adapter, mac,
|
||||
+ MAC_ADDRESS_TYPE_NETWORK,
|
||||
+ false, adapter->if_handle, pmac_id);
|
||||
+ if (status != 0)
|
||||
+ goto do_none;
|
||||
+ status = be_cmd_pmac_add(adapter, mac, adapter->if_handle,
|
||||
+ &adapter->pmac_id, 0);
|
||||
+do_none:
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
static int be_setup(struct be_adapter *adapter)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
@@ -2591,7 +2626,7 @@ static int be_setup(struct be_adapter *adapter)
|
||||
|
||||
memset(mac, 0, ETH_ALEN);
|
||||
status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK,
|
||||
- true /*permanent */, 0);
|
||||
+ true /*permanent */, 0, 0);
|
||||
if (status)
|
||||
return status;
|
||||
memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
|
||||
@@ -2618,12 +2653,17 @@ static int be_setup(struct be_adapter *adapter)
|
||||
goto err;
|
||||
}
|
||||
|
||||
- /* For BEx, the VF's permanent mac queried from card is incorrect.
|
||||
- * Query the mac configued by the PF using if_handle
|
||||
- */
|
||||
- if (!be_physfn(adapter) && !lancer_chip(adapter)) {
|
||||
- status = be_cmd_mac_addr_query(adapter, mac,
|
||||
- MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle);
|
||||
+ /* The VF's permanent mac queried from card is incorrect.
|
||||
+ * For BEx: Query the mac configued by the PF using if_handle
|
||||
+ * For Lancer: Get and use mac_list to obtain mac address.
|
||||
+ */
|
||||
+ if (!be_physfn(adapter)) {
|
||||
+ if (lancer_chip(adapter))
|
||||
+ status = be_configure_mac_from_list(adapter, mac);
|
||||
+ else
|
||||
+ status = be_cmd_mac_addr_query(adapter, mac,
|
||||
+ MAC_ADDRESS_TYPE_NETWORK, false,
|
||||
+ adapter->if_handle, 0);
|
||||
if (!status) {
|
||||
memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
|
||||
memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
|
||||
@@ -2639,12 +2679,15 @@ static int be_setup(struct be_adapter *adapter)
|
||||
be_set_rx_mode(adapter->netdev);
|
||||
|
||||
status = be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc);
|
||||
- if (status)
|
||||
+ /* For Lancer: It is legal for this cmd to fail on VF */
|
||||
+ if (status && (be_physfn(adapter) || !lancer_chip(adapter)))
|
||||
goto err;
|
||||
+
|
||||
if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc) {
|
||||
status = be_cmd_set_flow_control(adapter, adapter->tx_fc,
|
||||
adapter->rx_fc);
|
||||
- if (status)
|
||||
+ /* For Lancer: It is legal for this cmd to fail on VF */
|
||||
+ if (status && (be_physfn(adapter) || !lancer_chip(adapter)))
|
||||
goto err;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Fri, 25 Nov 2011 05:48:06 +0000
|
||||
Subject: [PATCH 12/58] be2net: Fix error recovery paths
|
||||
|
||||
commit 3bb62f4f95ba004048bafb460179b5db33aff787 upstream.
|
||||
|
||||
When TX queues are created again after error recovery,
|
||||
netif_set_real_num_tx_queues() is invoked to update number of real
|
||||
TX queues created. rtnl lock needs to be held when invoking this routine.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index c6fb7c3..a1b8ebc 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -1666,9 +1666,12 @@ static int be_tx_queues_create(struct be_adapter *adapter)
|
||||
u8 i;
|
||||
|
||||
adapter->num_tx_qs = be_num_txqs_want(adapter);
|
||||
- if (adapter->num_tx_qs != MAX_TX_QS)
|
||||
+ if (adapter->num_tx_qs != MAX_TX_QS) {
|
||||
+ rtnl_lock();
|
||||
netif_set_real_num_tx_queues(adapter->netdev,
|
||||
adapter->num_tx_qs);
|
||||
+ rtnl_unlock();
|
||||
+ }
|
||||
|
||||
adapter->tx_eq.max_eqd = 0;
|
||||
adapter->tx_eq.min_eqd = 0;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Fri, 25 Nov 2011 05:48:23 +0000
|
||||
Subject: [PATCH 13/58] be2net: Add error handling for Lancer
|
||||
|
||||
commit d8110f62c020ebc49108de57510a1482bfcbe86a upstream.
|
||||
|
||||
Detect error in Lancer by polling a HW register and
|
||||
recover from this error if it is recoverable.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 155 ++++++++++++++++++---------
|
||||
1 file changed, 106 insertions(+), 49 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index a1b8ebc..66429ea 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -2044,52 +2044,6 @@ void be_detect_dump_ue(struct be_adapter *adapter)
|
||||
}
|
||||
}
|
||||
|
||||
-static void be_worker(struct work_struct *work)
|
||||
-{
|
||||
- struct be_adapter *adapter =
|
||||
- container_of(work, struct be_adapter, work.work);
|
||||
- struct be_rx_obj *rxo;
|
||||
- int i;
|
||||
-
|
||||
- be_detect_dump_ue(adapter);
|
||||
-
|
||||
- /* when interrupts are not yet enabled, just reap any pending
|
||||
- * mcc completions */
|
||||
- if (!netif_running(adapter->netdev)) {
|
||||
- int mcc_compl, status = 0;
|
||||
-
|
||||
- mcc_compl = be_process_mcc(adapter, &status);
|
||||
-
|
||||
- if (mcc_compl) {
|
||||
- struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
|
||||
- be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl);
|
||||
- }
|
||||
-
|
||||
- goto reschedule;
|
||||
- }
|
||||
-
|
||||
- if (!adapter->stats_cmd_sent) {
|
||||
- if (lancer_chip(adapter))
|
||||
- lancer_cmd_get_pport_stats(adapter,
|
||||
- &adapter->stats_cmd);
|
||||
- else
|
||||
- be_cmd_get_stats(adapter, &adapter->stats_cmd);
|
||||
- }
|
||||
-
|
||||
- for_all_rx_queues(adapter, rxo, i) {
|
||||
- be_rx_eqd_update(adapter, rxo);
|
||||
-
|
||||
- if (rxo->rx_post_starved) {
|
||||
- rxo->rx_post_starved = false;
|
||||
- be_post_rx_frags(rxo, GFP_KERNEL);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
-reschedule:
|
||||
- adapter->work_counter++;
|
||||
- schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
|
||||
-}
|
||||
-
|
||||
static void be_msix_disable(struct be_adapter *adapter)
|
||||
{
|
||||
if (msix_enabled(adapter)) {
|
||||
@@ -3328,7 +3282,7 @@ static int be_dev_family_check(struct be_adapter *adapter)
|
||||
|
||||
static int lancer_wait_ready(struct be_adapter *adapter)
|
||||
{
|
||||
-#define SLIPORT_READY_TIMEOUT 500
|
||||
+#define SLIPORT_READY_TIMEOUT 30
|
||||
u32 sliport_status;
|
||||
int status = 0, i;
|
||||
|
||||
@@ -3337,7 +3291,7 @@ static int lancer_wait_ready(struct be_adapter *adapter)
|
||||
if (sliport_status & SLIPORT_STATUS_RDY_MASK)
|
||||
break;
|
||||
|
||||
- msleep(20);
|
||||
+ msleep(1000);
|
||||
}
|
||||
|
||||
if (i == SLIPORT_READY_TIMEOUT)
|
||||
@@ -3374,6 +3328,104 @@ static int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
|
||||
return status;
|
||||
}
|
||||
|
||||
+static void lancer_test_and_recover_fn_err(struct be_adapter *adapter)
|
||||
+{
|
||||
+ int status;
|
||||
+ u32 sliport_status;
|
||||
+
|
||||
+ if (adapter->eeh_err || adapter->ue_detected)
|
||||
+ return;
|
||||
+
|
||||
+ sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
|
||||
+
|
||||
+ if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
|
||||
+ dev_err(&adapter->pdev->dev,
|
||||
+ "Adapter in error state."
|
||||
+ "Trying to recover.\n");
|
||||
+
|
||||
+ status = lancer_test_and_set_rdy_state(adapter);
|
||||
+ if (status)
|
||||
+ goto err;
|
||||
+
|
||||
+ netif_device_detach(adapter->netdev);
|
||||
+
|
||||
+ if (netif_running(adapter->netdev))
|
||||
+ be_close(adapter->netdev);
|
||||
+
|
||||
+ be_clear(adapter);
|
||||
+
|
||||
+ adapter->fw_timeout = false;
|
||||
+
|
||||
+ status = be_setup(adapter);
|
||||
+ if (status)
|
||||
+ goto err;
|
||||
+
|
||||
+ if (netif_running(adapter->netdev)) {
|
||||
+ status = be_open(adapter->netdev);
|
||||
+ if (status)
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ netif_device_attach(adapter->netdev);
|
||||
+
|
||||
+ dev_err(&adapter->pdev->dev,
|
||||
+ "Adapter error recovery succeeded\n");
|
||||
+ }
|
||||
+ return;
|
||||
+err:
|
||||
+ dev_err(&adapter->pdev->dev,
|
||||
+ "Adapter error recovery failed\n");
|
||||
+}
|
||||
+
|
||||
+static void be_worker(struct work_struct *work)
|
||||
+{
|
||||
+ struct be_adapter *adapter =
|
||||
+ container_of(work, struct be_adapter, work.work);
|
||||
+ struct be_rx_obj *rxo;
|
||||
+ int i;
|
||||
+
|
||||
+ if (lancer_chip(adapter))
|
||||
+ lancer_test_and_recover_fn_err(adapter);
|
||||
+
|
||||
+ be_detect_dump_ue(adapter);
|
||||
+
|
||||
+ /* when interrupts are not yet enabled, just reap any pending
|
||||
+ * mcc completions */
|
||||
+ if (!netif_running(adapter->netdev)) {
|
||||
+ int mcc_compl, status = 0;
|
||||
+
|
||||
+ mcc_compl = be_process_mcc(adapter, &status);
|
||||
+
|
||||
+ if (mcc_compl) {
|
||||
+ struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
|
||||
+ be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl);
|
||||
+ }
|
||||
+
|
||||
+ goto reschedule;
|
||||
+ }
|
||||
+
|
||||
+ if (!adapter->stats_cmd_sent) {
|
||||
+ if (lancer_chip(adapter))
|
||||
+ lancer_cmd_get_pport_stats(adapter,
|
||||
+ &adapter->stats_cmd);
|
||||
+ else
|
||||
+ be_cmd_get_stats(adapter, &adapter->stats_cmd);
|
||||
+ }
|
||||
+
|
||||
+ for_all_rx_queues(adapter, rxo, i) {
|
||||
+ be_rx_eqd_update(adapter, rxo);
|
||||
+
|
||||
+ if (rxo->rx_post_starved) {
|
||||
+ rxo->rx_post_starved = false;
|
||||
+ be_post_rx_frags(rxo, GFP_KERNEL);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+reschedule:
|
||||
+ adapter->work_counter++;
|
||||
+ schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
|
||||
+}
|
||||
+
|
||||
static int __devinit be_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *pdev_id)
|
||||
{
|
||||
@@ -3426,7 +3478,12 @@ static int __devinit be_probe(struct pci_dev *pdev,
|
||||
goto disable_sriov;
|
||||
|
||||
if (lancer_chip(adapter)) {
|
||||
- status = lancer_test_and_set_rdy_state(adapter);
|
||||
+ status = lancer_wait_ready(adapter);
|
||||
+ if (!status) {
|
||||
+ iowrite32(SLI_PORT_CONTROL_IP_MASK,
|
||||
+ adapter->db + SLIPORT_CONTROL_OFFSET);
|
||||
+ status = lancer_test_and_set_rdy_state(adapter);
|
||||
+ }
|
||||
if (status) {
|
||||
dev_err(&pdev->dev, "Adapter in non recoverable error\n");
|
||||
goto ctrl_clean;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Fri, 25 Nov 2011 05:48:38 +0000
|
||||
Subject: [PATCH 14/58] be2net: Use new hash key
|
||||
|
||||
commit 65f8584e253f4676c8b39e976a10e918ec984b7c upstream.
|
||||
|
||||
This new hash key gives better distribution of packets across RX
|
||||
queues.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 7988798..62868ea 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -1669,8 +1669,9 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size)
|
||||
{
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_cmd_req_rss_config *req;
|
||||
- u32 myhash[10] = {0x0123, 0x4567, 0x89AB, 0xCDEF, 0x01EF,
|
||||
- 0x0123, 0x4567, 0x89AB, 0xCDEF, 0x01EF};
|
||||
+ u32 myhash[10] = {0x15d43fa5, 0x2534685a, 0x5f87693a, 0x5668494e,
|
||||
+ 0x33cf6a53, 0x383334c6, 0x76ac4257, 0x59b242b2,
|
||||
+ 0x3ea83c02, 0x4a110304};
|
||||
int status;
|
||||
|
||||
if (mutex_lock_interruptible(&adapter->mbox_lock))
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Fri, 25 Nov 2011 05:48:53 +0000
|
||||
Subject: [PATCH 15/58] be2net: Fix non utilization of RX queues
|
||||
|
||||
commit e9008ee99c77207b2f6aee67e5f849b1e1400a11 upstream.
|
||||
|
||||
When non power of two MSIX vectors are given to driver, some RX queues
|
||||
are not utilized. Program RSS table in such a way that all queues
|
||||
are utilized.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 16 ++++++++++------
|
||||
1 file changed, 10 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 66429ea..7236280 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -2312,8 +2312,8 @@ static int be_close(struct net_device *netdev)
|
||||
static int be_rx_queues_setup(struct be_adapter *adapter)
|
||||
{
|
||||
struct be_rx_obj *rxo;
|
||||
- int rc, i;
|
||||
- u8 rsstable[MAX_RSS_QS];
|
||||
+ int rc, i, j;
|
||||
+ u8 rsstable[128];
|
||||
|
||||
for_all_rx_queues(adapter, rxo, i) {
|
||||
rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id,
|
||||
@@ -2325,11 +2325,15 @@ static int be_rx_queues_setup(struct be_adapter *adapter)
|
||||
}
|
||||
|
||||
if (be_multi_rxq(adapter)) {
|
||||
- for_all_rss_queues(adapter, rxo, i)
|
||||
- rsstable[i] = rxo->rss_id;
|
||||
+ for (j = 0; j < 128; j += adapter->num_rx_qs - 1) {
|
||||
+ for_all_rss_queues(adapter, rxo, i) {
|
||||
+ if ((j + i) >= 128)
|
||||
+ break;
|
||||
+ rsstable[j + i] = rxo->rss_id;
|
||||
+ }
|
||||
+ }
|
||||
+ rc = be_cmd_rss_config(adapter, rsstable, 128);
|
||||
|
||||
- rc = be_cmd_rss_config(adapter, rsstable,
|
||||
- adapter->num_rx_qs - 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
From: Ivan Vecera <ivecera@redhat.com>
|
||||
Date: Thu, 8 Dec 2011 01:31:21 +0000
|
||||
Subject: [PATCH 16/58] be2net: netpoll support
|
||||
|
||||
commit 6626873980475f303367f7b709f4703b571cf854 upstream.
|
||||
|
||||
Add missing netpoll support.
|
||||
|
||||
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 18 +++++++++++++++++-
|
||||
1 file changed, 17 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 7236280..3854fb0 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -2666,6 +2666,19 @@ err:
|
||||
return status;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
+static void be_netpoll(struct net_device *netdev)
|
||||
+{
|
||||
+ struct be_adapter *adapter = netdev_priv(netdev);
|
||||
+ struct be_rx_obj *rxo;
|
||||
+ int i;
|
||||
+
|
||||
+ event_handle(adapter, &adapter->tx_eq, false);
|
||||
+ for_all_rx_queues(adapter, rxo, i)
|
||||
+ event_handle(adapter, &rxo->rx_eq, true);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
#define FW_FILE_HDR_SIGN "ServerEngines Corp. "
|
||||
static bool be_flash_redboot(struct be_adapter *adapter,
|
||||
const u8 *p, u32 img_start, int image_size,
|
||||
@@ -3014,7 +3027,10 @@ static struct net_device_ops be_netdev_ops = {
|
||||
.ndo_set_vf_mac = be_set_vf_mac,
|
||||
.ndo_set_vf_vlan = be_set_vf_vlan,
|
||||
.ndo_set_vf_tx_rate = be_set_vf_tx_rate,
|
||||
- .ndo_get_vf_config = be_get_vf_config
|
||||
+ .ndo_get_vf_config = be_get_vf_config,
|
||||
+#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
+ .ndo_poll_controller = be_netpoll,
|
||||
+#endif
|
||||
};
|
||||
|
||||
static void be_netdev_init(struct net_device *netdev)
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
From: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Date: Fri, 9 Dec 2011 13:53:09 +0000
|
||||
Subject: [PATCH 17/58] be2net: update some counters to display via ethtool
|
||||
|
||||
commit 02fe7027961969a052fbbe453304f329d4e9735a upstream.
|
||||
|
||||
update pmem_fifo_overflow_drop, rx_priority_pause_frames counters.
|
||||
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 3854fb0..0da3df0 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -316,6 +316,8 @@ static void populate_be3_stats(struct be_adapter *adapter)
|
||||
struct be_drv_stats *drvs = &adapter->drv_stats;
|
||||
|
||||
be_dws_le_to_cpu(hw_stats, sizeof(*hw_stats));
|
||||
+ drvs->pmem_fifo_overflow_drop = port_stats->pmem_fifo_overflow_drop;
|
||||
+ drvs->rx_priority_pause_frames = port_stats->rx_priority_pause_frames;
|
||||
drvs->rx_pause_frames = port_stats->rx_pause_frames;
|
||||
drvs->rx_crc_errors = port_stats->rx_crc_errors;
|
||||
drvs->rx_control_frames = port_stats->rx_control_frames;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
From: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Date: Fri, 9 Dec 2011 13:53:17 +0000
|
||||
Subject: [PATCH 18/58] be2net: workaround to fix a bug in BE
|
||||
|
||||
commit 1ded132d4c3442aa3a619c94c245d7b5e0eb9731 upstream.
|
||||
|
||||
disable Tx vlan offloading in certain cases.
|
||||
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 46 ++++++++++++++++++++++-----
|
||||
1 file changed, 38 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 0da3df0..f180f49 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -552,11 +552,26 @@ static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len)
|
||||
wrb->frag_len = len & ETH_WRB_FRAG_LEN_MASK;
|
||||
}
|
||||
|
||||
+static inline u16 be_get_tx_vlan_tag(struct be_adapter *adapter,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ u8 vlan_prio;
|
||||
+ u16 vlan_tag;
|
||||
+
|
||||
+ vlan_tag = vlan_tx_tag_get(skb);
|
||||
+ vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
|
||||
+ /* If vlan priority provided by OS is NOT in available bmap */
|
||||
+ if (!(adapter->vlan_prio_bmap & (1 << vlan_prio)))
|
||||
+ vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) |
|
||||
+ adapter->recommended_prio;
|
||||
+
|
||||
+ return vlan_tag;
|
||||
+}
|
||||
+
|
||||
static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
|
||||
struct sk_buff *skb, u32 wrb_cnt, u32 len)
|
||||
{
|
||||
- u8 vlan_prio = 0;
|
||||
- u16 vlan_tag = 0;
|
||||
+ u16 vlan_tag;
|
||||
|
||||
memset(hdr, 0, sizeof(*hdr));
|
||||
|
||||
@@ -587,12 +602,7 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
|
||||
|
||||
if (vlan_tx_tag_present(skb)) {
|
||||
AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1);
|
||||
- vlan_tag = vlan_tx_tag_get(skb);
|
||||
- vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
|
||||
- /* If vlan priority provided by OS is NOT in available bmap */
|
||||
- if (!(adapter->vlan_prio_bmap & (1 << vlan_prio)))
|
||||
- vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) |
|
||||
- adapter->recommended_prio;
|
||||
+ vlan_tag = be_get_tx_vlan_tag(adapter, skb);
|
||||
AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag, hdr, vlan_tag);
|
||||
}
|
||||
|
||||
@@ -695,6 +705,25 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
|
||||
u32 start = txq->head;
|
||||
bool dummy_wrb, stopped = false;
|
||||
|
||||
+ /* For vlan tagged pkts, BE
|
||||
+ * 1) calculates checksum even when CSO is not requested
|
||||
+ * 2) calculates checksum wrongly for padded pkt less than
|
||||
+ * 60 bytes long.
|
||||
+ * As a workaround disable TX vlan offloading in such cases.
|
||||
+ */
|
||||
+ if (unlikely(vlan_tx_tag_present(skb) &&
|
||||
+ (skb->ip_summed != CHECKSUM_PARTIAL || skb->len <= 60))) {
|
||||
+ skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
+ if (unlikely(!skb))
|
||||
+ goto tx_drop;
|
||||
+
|
||||
+ skb = __vlan_put_tag(skb, be_get_tx_vlan_tag(adapter, skb));
|
||||
+ if (unlikely(!skb))
|
||||
+ goto tx_drop;
|
||||
+
|
||||
+ skb->vlan_tci = 0;
|
||||
+ }
|
||||
+
|
||||
wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb);
|
||||
|
||||
copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb);
|
||||
@@ -722,6 +751,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
|
||||
txq->head = start;
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
+tx_drop:
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Tue, 13 Dec 2011 00:58:49 +0000
|
||||
Subject: [PATCH 19/58] be2net: fix ethtool ringparam reporting
|
||||
|
||||
commit 110b82bc6265a48c1a0bf198109bed325ed055e2 upstream.
|
||||
|
||||
The ethtool "-g" option is supposed to report the max queue length and
|
||||
user modified queue length for RX and TX queues. be2net doesn't support
|
||||
user modification of queue lengths. So, the correct values for these
|
||||
would be the max numbers.
|
||||
be2net incorrectly reports the queue used values for these fields.
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_ethtool.c | 11 ++++-------
|
||||
1 file changed, 4 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
index 575c783..6ba2dc6 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
@@ -520,16 +520,13 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void
|
||||
-be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
|
||||
+static void be_get_ringparam(struct net_device *netdev,
|
||||
+ struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
- ring->rx_max_pending = adapter->rx_obj[0].q.len;
|
||||
- ring->tx_max_pending = adapter->tx_obj[0].q.len;
|
||||
-
|
||||
- ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used);
|
||||
- ring->tx_pending = atomic_read(&adapter->tx_obj[0].q.used);
|
||||
+ ring->rx_max_pending = ring->rx_pending = adapter->rx_obj[0].q.len;
|
||||
+ ring->tx_max_pending = ring->tx_pending = adapter->tx_obj[0].q.len;
|
||||
}
|
||||
|
||||
static void
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,416 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Tue, 13 Dec 2011 00:58:50 +0000
|
||||
Subject: [PATCH 20/58] be2net: refactor/cleanup vf configuration code
|
||||
|
||||
commit 11ac75ed1eb9d8f5ff067fa9a82ebf5075989281 upstream.
|
||||
|
||||
- use adapter->num_vfs (and not the module param) to store the actual
|
||||
number of vfs created. Use the same variable to reflect SRIOV
|
||||
enable/disable state. So, drop the adapter->sriov_enabled field.
|
||||
|
||||
- use for_all_vfs() macro in VF configuration code
|
||||
|
||||
- drop the "vf_" prefix for the fields of be_vf_cfg; the prefix is
|
||||
redundant and removing it helps reduce line wrap
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 20 ++--
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 137 +++++++++++++--------------
|
||||
2 files changed, 80 insertions(+), 77 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index 34f162d..a3588fb 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -288,11 +288,11 @@ struct be_drv_stats {
|
||||
};
|
||||
|
||||
struct be_vf_cfg {
|
||||
- unsigned char vf_mac_addr[ETH_ALEN];
|
||||
- int vf_if_handle;
|
||||
- int vf_pmac_id;
|
||||
- u16 vf_vlan_tag;
|
||||
- u32 vf_tx_rate;
|
||||
+ unsigned char mac_addr[ETH_ALEN];
|
||||
+ int if_handle;
|
||||
+ int pmac_id;
|
||||
+ u16 vlan_tag;
|
||||
+ u32 tx_rate;
|
||||
};
|
||||
|
||||
struct be_adapter {
|
||||
@@ -368,16 +368,20 @@ struct be_adapter {
|
||||
u32 flash_status;
|
||||
struct completion flash_compl;
|
||||
|
||||
- bool be3_native;
|
||||
- bool sriov_enabled;
|
||||
- struct be_vf_cfg *vf_cfg;
|
||||
+ u32 num_vfs;
|
||||
u8 is_virtfn;
|
||||
+ struct be_vf_cfg *vf_cfg;
|
||||
+ bool be3_native;
|
||||
u32 sli_family;
|
||||
u8 hba_port_num;
|
||||
u16 pvid;
|
||||
};
|
||||
|
||||
#define be_physfn(adapter) (!adapter->is_virtfn)
|
||||
+#define sriov_enabled(adapter) (adapter->num_vfs > 0)
|
||||
+#define for_all_vfs(adapter, vf_cfg, i) \
|
||||
+ for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \
|
||||
+ i++, vf_cfg++)
|
||||
|
||||
/* BladeEngine Generation numbers */
|
||||
#define BE_GEN2 2
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index f180f49..cf83b33 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -27,13 +27,14 @@ MODULE_DESCRIPTION(DRV_DESC " " DRV_VER);
|
||||
MODULE_AUTHOR("ServerEngines Corporation");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
-static ushort rx_frag_size = 2048;
|
||||
static unsigned int num_vfs;
|
||||
-module_param(rx_frag_size, ushort, S_IRUGO);
|
||||
module_param(num_vfs, uint, S_IRUGO);
|
||||
-MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");
|
||||
MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize");
|
||||
|
||||
+static ushort rx_frag_size = 2048;
|
||||
+module_param(rx_frag_size, ushort, S_IRUGO);
|
||||
+MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");
|
||||
+
|
||||
static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
|
||||
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
|
||||
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
|
||||
@@ -779,15 +780,15 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu)
|
||||
*/
|
||||
static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)
|
||||
{
|
||||
+ struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf_num];
|
||||
u16 vtag[BE_NUM_VLANS_SUPPORTED];
|
||||
u16 ntags = 0, i;
|
||||
int status = 0;
|
||||
- u32 if_handle;
|
||||
|
||||
if (vf) {
|
||||
- if_handle = adapter->vf_cfg[vf_num].vf_if_handle;
|
||||
- vtag[0] = cpu_to_le16(adapter->vf_cfg[vf_num].vf_vlan_tag);
|
||||
- status = be_cmd_vlan_config(adapter, if_handle, vtag, 1, 1, 0);
|
||||
+ vtag[0] = cpu_to_le16(vf_cfg->vlan_tag);
|
||||
+ status = be_cmd_vlan_config(adapter, vf_cfg->if_handle, vtag,
|
||||
+ 1, 1, 0);
|
||||
}
|
||||
|
||||
/* No need to further configure vids if in promiscuous mode */
|
||||
@@ -873,31 +874,30 @@ done:
|
||||
static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
+ struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
|
||||
int status;
|
||||
|
||||
- if (!adapter->sriov_enabled)
|
||||
+ if (!sriov_enabled(adapter))
|
||||
return -EPERM;
|
||||
|
||||
- if (!is_valid_ether_addr(mac) || (vf >= num_vfs))
|
||||
+ if (!is_valid_ether_addr(mac) || vf >= adapter->num_vfs)
|
||||
return -EINVAL;
|
||||
|
||||
if (lancer_chip(adapter)) {
|
||||
status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1);
|
||||
} else {
|
||||
- status = be_cmd_pmac_del(adapter,
|
||||
- adapter->vf_cfg[vf].vf_if_handle,
|
||||
- adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
|
||||
+ status = be_cmd_pmac_del(adapter, vf_cfg->if_handle,
|
||||
+ vf_cfg->pmac_id, vf + 1);
|
||||
|
||||
- status = be_cmd_pmac_add(adapter, mac,
|
||||
- adapter->vf_cfg[vf].vf_if_handle,
|
||||
- &adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
|
||||
+ status = be_cmd_pmac_add(adapter, mac, vf_cfg->if_handle,
|
||||
+ &vf_cfg->pmac_id, vf + 1);
|
||||
}
|
||||
|
||||
if (status)
|
||||
dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n",
|
||||
mac, vf);
|
||||
else
|
||||
- memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN);
|
||||
+ memcpy(vf_cfg->mac_addr, mac, ETH_ALEN);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -906,18 +906,19 @@ static int be_get_vf_config(struct net_device *netdev, int vf,
|
||||
struct ifla_vf_info *vi)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
+ struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
|
||||
|
||||
- if (!adapter->sriov_enabled)
|
||||
+ if (!sriov_enabled(adapter))
|
||||
return -EPERM;
|
||||
|
||||
- if (vf >= num_vfs)
|
||||
+ if (vf >= adapter->num_vfs)
|
||||
return -EINVAL;
|
||||
|
||||
vi->vf = vf;
|
||||
- vi->tx_rate = adapter->vf_cfg[vf].vf_tx_rate;
|
||||
- vi->vlan = adapter->vf_cfg[vf].vf_vlan_tag;
|
||||
+ vi->tx_rate = vf_cfg->tx_rate;
|
||||
+ vi->vlan = vf_cfg->vlan_tag;
|
||||
vi->qos = 0;
|
||||
- memcpy(&vi->mac, adapter->vf_cfg[vf].vf_mac_addr, ETH_ALEN);
|
||||
+ memcpy(&vi->mac, vf_cfg->mac_addr, ETH_ALEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -928,17 +929,17 @@ static int be_set_vf_vlan(struct net_device *netdev,
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
int status = 0;
|
||||
|
||||
- if (!adapter->sriov_enabled)
|
||||
+ if (!sriov_enabled(adapter))
|
||||
return -EPERM;
|
||||
|
||||
- if ((vf >= num_vfs) || (vlan > 4095))
|
||||
+ if (vf >= adapter->num_vfs || vlan > 4095)
|
||||
return -EINVAL;
|
||||
|
||||
if (vlan) {
|
||||
- adapter->vf_cfg[vf].vf_vlan_tag = vlan;
|
||||
+ adapter->vf_cfg[vf].vlan_tag = vlan;
|
||||
adapter->vlans_added++;
|
||||
} else {
|
||||
- adapter->vf_cfg[vf].vf_vlan_tag = 0;
|
||||
+ adapter->vf_cfg[vf].vlan_tag = 0;
|
||||
adapter->vlans_added--;
|
||||
}
|
||||
|
||||
@@ -956,16 +957,16 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
int status = 0;
|
||||
|
||||
- if (!adapter->sriov_enabled)
|
||||
+ if (!sriov_enabled(adapter))
|
||||
return -EPERM;
|
||||
|
||||
- if ((vf >= num_vfs) || (rate < 0))
|
||||
+ if (vf >= adapter->num_vfs || rate < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (rate > 10000)
|
||||
rate = 10000;
|
||||
|
||||
- adapter->vf_cfg[vf].vf_tx_rate = rate;
|
||||
+ adapter->vf_cfg[vf].tx_rate = rate;
|
||||
status = be_cmd_set_qos(adapter, rate / 10, vf + 1);
|
||||
|
||||
if (status)
|
||||
@@ -1681,8 +1682,7 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
|
||||
|
||||
static int be_num_txqs_want(struct be_adapter *adapter)
|
||||
{
|
||||
- if ((num_vfs && adapter->sriov_enabled) ||
|
||||
- be_is_mc(adapter) ||
|
||||
+ if (sriov_enabled(adapter) || be_is_mc(adapter) ||
|
||||
lancer_chip(adapter) || !be_physfn(adapter) ||
|
||||
adapter->generation == BE_GEN2)
|
||||
return 1;
|
||||
@@ -1764,8 +1764,8 @@ static void be_rx_queues_destroy(struct be_adapter *adapter)
|
||||
static u32 be_num_rxqs_want(struct be_adapter *adapter)
|
||||
{
|
||||
if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
|
||||
- !adapter->sriov_enabled && be_physfn(adapter) &&
|
||||
- !be_is_mc(adapter)) {
|
||||
+ !sriov_enabled(adapter) && be_physfn(adapter) &&
|
||||
+ !be_is_mc(adapter)) {
|
||||
return 1 + MAX_RSS_QS; /* one default non-RSS queue */
|
||||
} else {
|
||||
dev_warn(&adapter->pdev->dev,
|
||||
@@ -2112,27 +2112,28 @@ done:
|
||||
static int be_sriov_enable(struct be_adapter *adapter)
|
||||
{
|
||||
be_check_sriov_fn_type(adapter);
|
||||
+
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
if (be_physfn(adapter) && num_vfs) {
|
||||
int status, pos;
|
||||
- u16 nvfs;
|
||||
+ u16 dev_vfs;
|
||||
|
||||
pos = pci_find_ext_capability(adapter->pdev,
|
||||
PCI_EXT_CAP_ID_SRIOV);
|
||||
pci_read_config_word(adapter->pdev,
|
||||
- pos + PCI_SRIOV_TOTAL_VF, &nvfs);
|
||||
+ pos + PCI_SRIOV_TOTAL_VF, &dev_vfs);
|
||||
|
||||
- if (num_vfs > nvfs) {
|
||||
+ adapter->num_vfs = min_t(u16, num_vfs, dev_vfs);
|
||||
+ if (adapter->num_vfs != num_vfs)
|
||||
dev_info(&adapter->pdev->dev,
|
||||
- "Device supports %d VFs and not %d\n",
|
||||
- nvfs, num_vfs);
|
||||
- num_vfs = nvfs;
|
||||
- }
|
||||
+ "Device supports %d VFs and not %d\n",
|
||||
+ adapter->num_vfs, num_vfs);
|
||||
|
||||
- status = pci_enable_sriov(adapter->pdev, num_vfs);
|
||||
- adapter->sriov_enabled = status ? false : true;
|
||||
+ status = pci_enable_sriov(adapter->pdev, adapter->num_vfs);
|
||||
+ if (status)
|
||||
+ adapter->num_vfs = 0;
|
||||
|
||||
- if (adapter->sriov_enabled) {
|
||||
+ if (adapter->num_vfs) {
|
||||
adapter->vf_cfg = kcalloc(num_vfs,
|
||||
sizeof(struct be_vf_cfg),
|
||||
GFP_KERNEL);
|
||||
@@ -2147,10 +2148,10 @@ static int be_sriov_enable(struct be_adapter *adapter)
|
||||
static void be_sriov_disable(struct be_adapter *adapter)
|
||||
{
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
- if (adapter->sriov_enabled) {
|
||||
+ if (sriov_enabled(adapter)) {
|
||||
pci_disable_sriov(adapter->pdev);
|
||||
kfree(adapter->vf_cfg);
|
||||
- adapter->sriov_enabled = false;
|
||||
+ adapter->num_vfs = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -2462,24 +2463,24 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter)
|
||||
u32 vf;
|
||||
int status = 0;
|
||||
u8 mac[ETH_ALEN];
|
||||
+ struct be_vf_cfg *vf_cfg;
|
||||
|
||||
be_vf_eth_addr_generate(adapter, mac);
|
||||
|
||||
- for (vf = 0; vf < num_vfs; vf++) {
|
||||
+ for_all_vfs(adapter, vf_cfg, vf) {
|
||||
if (lancer_chip(adapter)) {
|
||||
status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1);
|
||||
} else {
|
||||
status = be_cmd_pmac_add(adapter, mac,
|
||||
- adapter->vf_cfg[vf].vf_if_handle,
|
||||
- &adapter->vf_cfg[vf].vf_pmac_id,
|
||||
- vf + 1);
|
||||
+ vf_cfg->if_handle,
|
||||
+ &vf_cfg->pmac_id, vf + 1);
|
||||
}
|
||||
|
||||
if (status)
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Mac address assignment failed for VF %d\n", vf);
|
||||
else
|
||||
- memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN);
|
||||
+ memcpy(vf_cfg->mac_addr, mac, ETH_ALEN);
|
||||
|
||||
mac[5] += 1;
|
||||
}
|
||||
@@ -2488,25 +2489,23 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter)
|
||||
|
||||
static void be_vf_clear(struct be_adapter *adapter)
|
||||
{
|
||||
+ struct be_vf_cfg *vf_cfg;
|
||||
u32 vf;
|
||||
|
||||
- for (vf = 0; vf < num_vfs; vf++) {
|
||||
+ for_all_vfs(adapter, vf_cfg, vf) {
|
||||
if (lancer_chip(adapter))
|
||||
be_cmd_set_mac_list(adapter, NULL, 0, vf + 1);
|
||||
else
|
||||
- be_cmd_pmac_del(adapter,
|
||||
- adapter->vf_cfg[vf].vf_if_handle,
|
||||
- adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
|
||||
- }
|
||||
+ be_cmd_pmac_del(adapter, vf_cfg->if_handle,
|
||||
+ vf_cfg->pmac_id, vf + 1);
|
||||
|
||||
- for (vf = 0; vf < num_vfs; vf++)
|
||||
- be_cmd_if_destroy(adapter, adapter->vf_cfg[vf].vf_if_handle,
|
||||
- vf + 1);
|
||||
+ be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1);
|
||||
+ }
|
||||
}
|
||||
|
||||
static int be_clear(struct be_adapter *adapter)
|
||||
{
|
||||
- if (be_physfn(adapter) && adapter->sriov_enabled)
|
||||
+ if (sriov_enabled(adapter))
|
||||
be_vf_clear(adapter);
|
||||
|
||||
be_cmd_if_destroy(adapter, adapter->if_handle, 0);
|
||||
@@ -2522,16 +2521,18 @@ static int be_clear(struct be_adapter *adapter)
|
||||
|
||||
static void be_vf_setup_init(struct be_adapter *adapter)
|
||||
{
|
||||
+ struct be_vf_cfg *vf_cfg;
|
||||
int vf;
|
||||
|
||||
- for (vf = 0; vf < num_vfs; vf++) {
|
||||
- adapter->vf_cfg[vf].vf_if_handle = -1;
|
||||
- adapter->vf_cfg[vf].vf_pmac_id = -1;
|
||||
+ for_all_vfs(adapter, vf_cfg, vf) {
|
||||
+ vf_cfg->if_handle = -1;
|
||||
+ vf_cfg->pmac_id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int be_vf_setup(struct be_adapter *adapter)
|
||||
{
|
||||
+ struct be_vf_cfg *vf_cfg;
|
||||
u32 cap_flags, en_flags, vf;
|
||||
u16 lnk_speed;
|
||||
int status;
|
||||
@@ -2540,11 +2541,9 @@ static int be_vf_setup(struct be_adapter *adapter)
|
||||
|
||||
cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
|
||||
BE_IF_FLAGS_MULTICAST;
|
||||
-
|
||||
- for (vf = 0; vf < num_vfs; vf++) {
|
||||
+ for_all_vfs(adapter, vf_cfg, vf) {
|
||||
status = be_cmd_if_create(adapter, cap_flags, en_flags, NULL,
|
||||
- &adapter->vf_cfg[vf].vf_if_handle,
|
||||
- NULL, vf+1);
|
||||
+ &vf_cfg->if_handle, NULL, vf + 1);
|
||||
if (status)
|
||||
goto err;
|
||||
}
|
||||
@@ -2553,12 +2552,12 @@ static int be_vf_setup(struct be_adapter *adapter)
|
||||
if (status)
|
||||
goto err;
|
||||
|
||||
- for (vf = 0; vf < num_vfs; vf++) {
|
||||
+ for_all_vfs(adapter, vf_cfg, vf) {
|
||||
status = be_cmd_link_status_query(adapter, NULL, &lnk_speed,
|
||||
- vf + 1);
|
||||
+ vf + 1);
|
||||
if (status)
|
||||
goto err;
|
||||
- adapter->vf_cfg[vf].vf_tx_rate = lnk_speed * 10;
|
||||
+ vf_cfg->tx_rate = lnk_speed * 10;
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
@@ -2686,7 +2685,7 @@ static int be_setup(struct be_adapter *adapter)
|
||||
|
||||
pcie_set_readrq(adapter->pdev, 4096);
|
||||
|
||||
- if (be_physfn(adapter) && adapter->sriov_enabled) {
|
||||
+ if (sriov_enabled(adapter)) {
|
||||
status = be_vf_setup(adapter);
|
||||
if (status)
|
||||
goto err;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
From: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Date: Thu, 15 Dec 2011 06:31:38 +0000
|
||||
Subject: [PATCH 21/58] be2net: Add support for Skyhawk cards
|
||||
|
||||
commit ecedb6ae908e3a8a19942da921a3ffb1c5a0d6ab upstream.
|
||||
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 4 ++++
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 2 ++
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index a3588fb..995198d 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -40,6 +40,7 @@
|
||||
#define OC_NAME "Emulex OneConnect 10Gbps NIC"
|
||||
#define OC_NAME_BE OC_NAME "(be3)"
|
||||
#define OC_NAME_LANCER OC_NAME "(Lancer)"
|
||||
+#define OC_NAME_SH OC_NAME "(Skyhawk)"
|
||||
#define DRV_DESC "ServerEngines BladeEngine 10Gbps NIC Driver"
|
||||
|
||||
#define BE_VENDOR_ID 0x19a2
|
||||
@@ -50,6 +51,7 @@
|
||||
#define OC_DEVICE_ID2 0x710 /* Device Id for BE3 cards */
|
||||
#define OC_DEVICE_ID3 0xe220 /* Device id for Lancer cards */
|
||||
#define OC_DEVICE_ID4 0xe228 /* Device id for VF in Lancer */
|
||||
+#define OC_DEVICE_ID5 0x720 /* Device Id for Skyhawk cards */
|
||||
|
||||
static inline char *nic_name(struct pci_dev *pdev)
|
||||
{
|
||||
@@ -63,6 +65,8 @@ static inline char *nic_name(struct pci_dev *pdev)
|
||||
return OC_NAME_LANCER;
|
||||
case BE_DEVICE_ID2:
|
||||
return BE3_NAME;
|
||||
+ case OC_DEVICE_ID5:
|
||||
+ return OC_NAME_SH;
|
||||
default:
|
||||
return BE_NAME;
|
||||
}
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index cf83b33..3ed2987 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -42,6 +42,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
|
||||
{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
|
||||
{ PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)},
|
||||
{ PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID4)},
|
||||
+ { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID5)},
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, be_dev_ids);
|
||||
@@ -3308,6 +3309,7 @@ static int be_dev_family_check(struct be_adapter *adapter)
|
||||
break;
|
||||
case BE_DEVICE_ID2:
|
||||
case OC_DEVICE_ID2:
|
||||
+ case OC_DEVICE_ID5:
|
||||
adapter->generation = BE_GEN3;
|
||||
break;
|
||||
case OC_DEVICE_ID3:
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Mon, 19 Dec 2011 01:53:35 +0000
|
||||
Subject: [PATCH 22/58] be2net: Fix INTx processing for Lancer
|
||||
|
||||
commit 93c86700c0ae3a1407b979073f423e62e29372c1 upstream.
|
||||
|
||||
Lancer does not have HW registers to indicate the EQ causing the INTx
|
||||
interrupt. As a result EQE entries of one EQ may be consumed when interrupt
|
||||
is caused by another EQ. Fix this by arming CQs at the end of NAPI poll
|
||||
routine to regenerate the EQEs.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 3ed2987..a185e61 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -1966,6 +1966,7 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
|
||||
struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi);
|
||||
struct be_adapter *adapter =
|
||||
container_of(tx_eq, struct be_adapter, tx_eq);
|
||||
+ struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
|
||||
struct be_tx_obj *txo;
|
||||
struct be_eth_tx_compl *txcp;
|
||||
int tx_compl, mcc_compl, status = 0;
|
||||
@@ -2002,12 +2003,19 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
|
||||
mcc_compl = be_process_mcc(adapter, &status);
|
||||
|
||||
if (mcc_compl) {
|
||||
- struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
|
||||
be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl);
|
||||
}
|
||||
|
||||
napi_complete(napi);
|
||||
|
||||
+ /* Arm CQ again to regenerate EQEs for Lancer in INTx mode */
|
||||
+ if (lancer_chip(adapter) && !msix_enabled(adapter)) {
|
||||
+ for_all_tx_queues(adapter, txo, i)
|
||||
+ be_cq_notify(adapter, txo->cq.id, true, 0);
|
||||
+
|
||||
+ be_cq_notify(adapter, mcc_obj->cq.id, true, 0);
|
||||
+ }
|
||||
+
|
||||
be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
|
||||
adapter->drv_stats.tx_events++;
|
||||
return 1;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
From: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Date: Fri, 25 May 2012 21:21:23 +0530
|
||||
Subject: [PATCH 23/58] be2net: fix be_vlan_add/rem_vid
|
||||
|
||||
commit 80817cbf5ac13da76f3ee2b9259f26c09b385e84 upstream.
|
||||
|
||||
1) fix be_vlan_add/rem_vid to return proper status
|
||||
2) perform appropriate housekeeping if firmware command succeeds.
|
||||
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 19 ++++++++++++++-----
|
||||
1 file changed, 14 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index a185e61..acef082 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -817,28 +817,37 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)
|
||||
static void be_vlan_add_vid(struct net_device *netdev, u16 vid)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
+ int status = 0;
|
||||
|
||||
- adapter->vlans_added++;
|
||||
if (!be_physfn(adapter))
|
||||
return;
|
||||
|
||||
adapter->vlan_tag[vid] = 1;
|
||||
if (adapter->vlans_added <= (adapter->max_vlans + 1))
|
||||
- be_vid_config(adapter, false, 0);
|
||||
+ status = be_vid_config(adapter, false, 0);
|
||||
+
|
||||
+ if (!status)
|
||||
+ adapter->vlans_added++;
|
||||
+ else
|
||||
+ adapter->vlan_tag[vid] = 0;
|
||||
}
|
||||
|
||||
static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
-
|
||||
- adapter->vlans_added--;
|
||||
+ int status = 0;
|
||||
|
||||
if (!be_physfn(adapter))
|
||||
return;
|
||||
|
||||
adapter->vlan_tag[vid] = 0;
|
||||
if (adapter->vlans_added <= adapter->max_vlans)
|
||||
- be_vid_config(adapter, false, 0);
|
||||
+ status = be_vid_config(adapter, false, 0);
|
||||
+
|
||||
+ if (!status)
|
||||
+ adapter->vlans_added--;
|
||||
+ else
|
||||
+ adapter->vlan_tag[vid] = 1;
|
||||
}
|
||||
|
||||
static void be_set_rx_mode(struct net_device *netdev)
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
From: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Date: Fri, 30 Dec 2011 12:15:30 +0000
|
||||
Subject: [PATCH 24/58] be2net: fix range check for set_qos for a VF
|
||||
|
||||
commit 94f434c2055db5fe20f10d4e0ec50ab395e1f62b upstream.
|
||||
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 14 +++++++++-----
|
||||
1 file changed, 9 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index acef082..cd7f5e3 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -970,18 +970,22 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
|
||||
if (!sriov_enabled(adapter))
|
||||
return -EPERM;
|
||||
|
||||
- if (vf >= adapter->num_vfs || rate < 0)
|
||||
+ if (vf >= adapter->num_vfs)
|
||||
return -EINVAL;
|
||||
|
||||
- if (rate > 10000)
|
||||
- rate = 10000;
|
||||
+ if (rate < 100 || rate > 10000) {
|
||||
+ dev_err(&adapter->pdev->dev,
|
||||
+ "tx rate must be between 100 and 10000 Mbps\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
- adapter->vf_cfg[vf].tx_rate = rate;
|
||||
status = be_cmd_set_qos(adapter, rate / 10, vf + 1);
|
||||
|
||||
if (status)
|
||||
- dev_info(&adapter->pdev->dev,
|
||||
+ dev_err(&adapter->pdev->dev,
|
||||
"tx rate %d on VF %d failed\n", rate, vf);
|
||||
+ else
|
||||
+ adapter->vf_cfg[vf].tx_rate = rate;
|
||||
return status;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,234 +0,0 @@
|
|||
From: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Date: Fri, 30 Dec 2011 12:15:40 +0000
|
||||
Subject: [PATCH 25/58] be2net: query link status in be_open()
|
||||
|
||||
commit b236916a68d923acff15787b5439d7d684c17ae5 upstream.
|
||||
|
||||
be2net gets an async link status notification from the FW when it creates
|
||||
an MCC queue. There are some cases in which this gratuitous notification
|
||||
is not received from FW. To cover this explicitly query the link status
|
||||
in be_open().
|
||||
|
||||
Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com>
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 5 ++++-
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 21 +++++++++++++++++----
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.h | 7 ++++---
|
||||
drivers/net/ethernet/emulex/benet/be_ethtool.c | 7 +++++--
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 24 +++++++++++++++---------
|
||||
5 files changed, 45 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index 995198d..cbdec25 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -299,6 +299,8 @@ struct be_vf_cfg {
|
||||
u32 tx_rate;
|
||||
};
|
||||
|
||||
+#define BE_FLAGS_LINK_STATUS_INIT 1
|
||||
+
|
||||
struct be_adapter {
|
||||
struct pci_dev *pdev;
|
||||
struct net_device *netdev;
|
||||
@@ -347,6 +349,7 @@ struct be_adapter {
|
||||
struct delayed_work work;
|
||||
u16 work_counter;
|
||||
|
||||
+ u32 flags;
|
||||
/* Ethtool knobs and info */
|
||||
char fw_ver[FW_VER_LEN];
|
||||
int if_handle; /* Used to configure filtering */
|
||||
@@ -538,7 +541,7 @@ static inline bool be_error(struct be_adapter *adapter)
|
||||
|
||||
extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
|
||||
u16 num_popped);
|
||||
-extern void be_link_status_update(struct be_adapter *adapter, u32 link_status);
|
||||
+extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
|
||||
extern void be_parse_stats(struct be_adapter *adapter);
|
||||
extern int be_load_fw(struct be_adapter *adapter, u8 *func);
|
||||
#endif /* BE_H */
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 62868ea..0fcb456 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -125,7 +125,14 @@ done:
|
||||
static void be_async_link_state_process(struct be_adapter *adapter,
|
||||
struct be_async_event_link_state *evt)
|
||||
{
|
||||
- be_link_status_update(adapter, evt->port_link_status);
|
||||
+ /* When link status changes, link speed must be re-queried from FW */
|
||||
+ adapter->link_speed = -1;
|
||||
+
|
||||
+ /* For the initial link status do not rely on the ASYNC event as
|
||||
+ * it may not be received in some cases.
|
||||
+ */
|
||||
+ if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT)
|
||||
+ be_link_status_update(adapter, evt->port_link_status);
|
||||
}
|
||||
|
||||
/* Grp5 CoS Priority evt */
|
||||
@@ -1232,7 +1239,7 @@ err:
|
||||
|
||||
/* Uses synchronous mcc */
|
||||
int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
|
||||
- u16 *link_speed, u32 dom)
|
||||
+ u16 *link_speed, u8 *link_status, u32 dom)
|
||||
{
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_cmd_req_link_status *req;
|
||||
@@ -1240,6 +1247,9 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
|
||||
|
||||
spin_lock_bh(&adapter->mcc_lock);
|
||||
|
||||
+ if (link_status)
|
||||
+ *link_status = LINK_DOWN;
|
||||
+
|
||||
wrb = wrb_from_mccq(adapter);
|
||||
if (!wrb) {
|
||||
status = -EBUSY;
|
||||
@@ -1247,7 +1257,7 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
|
||||
}
|
||||
req = embedded_payload(wrb);
|
||||
|
||||
- if (lancer_chip(adapter))
|
||||
+ if (adapter->generation == BE_GEN3 || lancer_chip(adapter))
|
||||
req->hdr.version = 1;
|
||||
|
||||
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
@@ -1257,10 +1267,13 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
|
||||
if (!status) {
|
||||
struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
|
||||
if (resp->mac_speed != PHY_LINK_SPEED_ZERO) {
|
||||
- *link_speed = le16_to_cpu(resp->link_speed);
|
||||
+ if (link_speed)
|
||||
+ *link_speed = le16_to_cpu(resp->link_speed);
|
||||
if (mac_speed)
|
||||
*mac_speed = resp->mac_speed;
|
||||
}
|
||||
+ if (link_status)
|
||||
+ *link_status = resp->logical_link_status;
|
||||
}
|
||||
|
||||
err:
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
index 0b694c6..dca8924 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
@@ -960,7 +960,8 @@ struct be_cmd_resp_link_status {
|
||||
u8 mgmt_mac_duplex;
|
||||
u8 mgmt_mac_speed;
|
||||
u16 link_speed;
|
||||
- u32 rsvd0;
|
||||
+ u8 logical_link_status;
|
||||
+ u8 rsvd1[3];
|
||||
} __packed;
|
||||
|
||||
/******************** Port Identification ***************************/
|
||||
@@ -1507,8 +1508,8 @@ extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
|
||||
int type);
|
||||
extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
|
||||
struct be_queue_info *q);
|
||||
-extern int be_cmd_link_status_query(struct be_adapter *adapter,
|
||||
- u8 *mac_speed, u16 *link_speed, u32 dom);
|
||||
+extern int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
|
||||
+ u16 *link_speed, u8 *link_status, u32 dom);
|
||||
extern int be_cmd_reset(struct be_adapter *adapter);
|
||||
extern int be_cmd_get_stats(struct be_adapter *adapter,
|
||||
struct be_dma_mem *nonemb_cmd);
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
index 6ba2dc6..6db6b6a 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
@@ -429,11 +429,14 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
|
||||
struct be_phy_info phy_info;
|
||||
u8 mac_speed = 0;
|
||||
u16 link_speed = 0;
|
||||
+ u8 link_status;
|
||||
int status;
|
||||
|
||||
if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) {
|
||||
status = be_cmd_link_status_query(adapter, &mac_speed,
|
||||
- &link_speed, 0);
|
||||
+ &link_speed, &link_status, 0);
|
||||
+ if (!status)
|
||||
+ be_link_status_update(adapter, link_status);
|
||||
|
||||
/* link_speed is in units of 10 Mbps */
|
||||
if (link_speed) {
|
||||
@@ -700,7 +703,7 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
|
||||
}
|
||||
|
||||
if (be_cmd_link_status_query(adapter, &mac_speed,
|
||||
- &qos_link_speed, 0) != 0) {
|
||||
+ &qos_link_speed, NULL, 0) != 0) {
|
||||
test->flags |= ETH_TEST_FL_FAILED;
|
||||
data[4] = -1;
|
||||
} else if (!mac_speed) {
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index cd7f5e3..42ee4c9 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -496,19 +496,19 @@ static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
|
||||
return stats;
|
||||
}
|
||||
|
||||
-void be_link_status_update(struct be_adapter *adapter, u32 link_status)
|
||||
+void be_link_status_update(struct be_adapter *adapter, u8 link_status)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
|
||||
- /* when link status changes, link speed must be re-queried from card */
|
||||
- adapter->link_speed = -1;
|
||||
- if ((link_status & LINK_STATUS_MASK) == LINK_UP) {
|
||||
- netif_carrier_on(netdev);
|
||||
- dev_info(&adapter->pdev->dev, "%s: Link up\n", netdev->name);
|
||||
- } else {
|
||||
+ if (!(adapter->flags & BE_FLAGS_LINK_STATUS_INIT)) {
|
||||
netif_carrier_off(netdev);
|
||||
- dev_info(&adapter->pdev->dev, "%s: Link down\n", netdev->name);
|
||||
+ adapter->flags |= BE_FLAGS_LINK_STATUS_INIT;
|
||||
}
|
||||
+
|
||||
+ if ((link_status & LINK_STATUS_MASK) == LINK_UP)
|
||||
+ netif_carrier_on(netdev);
|
||||
+ else
|
||||
+ netif_carrier_off(netdev);
|
||||
}
|
||||
|
||||
static void be_tx_stats_update(struct be_tx_obj *txo,
|
||||
@@ -2406,6 +2406,7 @@ static int be_open(struct net_device *netdev)
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
struct be_eq_obj *tx_eq = &adapter->tx_eq;
|
||||
struct be_rx_obj *rxo;
|
||||
+ u8 link_status;
|
||||
int status, i;
|
||||
|
||||
status = be_rx_queues_setup(adapter);
|
||||
@@ -2429,6 +2430,11 @@ static int be_open(struct net_device *netdev)
|
||||
/* Now that interrupts are on we can process async mcc */
|
||||
be_async_mcc_enable(adapter);
|
||||
|
||||
+ status = be_cmd_link_status_query(adapter, NULL, NULL,
|
||||
+ &link_status, 0);
|
||||
+ if (!status)
|
||||
+ be_link_status_update(adapter, link_status);
|
||||
+
|
||||
return 0;
|
||||
err:
|
||||
be_close(adapter->netdev);
|
||||
@@ -2576,7 +2582,7 @@ static int be_vf_setup(struct be_adapter *adapter)
|
||||
|
||||
for_all_vfs(adapter, vf_cfg, vf) {
|
||||
status = be_cmd_link_status_query(adapter, NULL, &lnk_speed,
|
||||
- vf + 1);
|
||||
+ NULL, vf + 1);
|
||||
if (status)
|
||||
goto err;
|
||||
vf_cfg->tx_rate = lnk_speed * 10;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
From: stephen hemminger <shemminger@vyatta.com>
|
||||
Date: Thu, 5 Jan 2012 19:10:25 +0000
|
||||
Subject: [PATCH 26/58] netdev: make net_device_ops const
|
||||
|
||||
commit e5686ad82ca2aeed7a8f24ffca115c0b7478dec9 upstream.
|
||||
|
||||
More drivers where net_device_ops should be const.
|
||||
|
||||
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
[bwh: Restrict to drivers/net/ethernet/emulex/benet/]
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 42ee4c9..804ab7e 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -3072,7 +3072,7 @@ fw_exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
-static struct net_device_ops be_netdev_ops = {
|
||||
+static const struct net_device_ops be_netdev_ops = {
|
||||
.ndo_open = be_open,
|
||||
.ndo_stop = be_close,
|
||||
.ndo_start_xmit = be_xmit,
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Thu, 19 Jan 2012 20:34:04 +0000
|
||||
Subject: [PATCH 27/58] be2net: create RSS rings even in multi-channel configs
|
||||
|
||||
commit df505eb804d5221c3164ebecd1286cb7fc7f49ba upstream.
|
||||
|
||||
Currently RSS rings are not created in a multi-channel config.
|
||||
RSS rings can be created on one (out of four) interfaces per port in a
|
||||
multi-channel config. Doing this insulates the driver from a FW bug wherin
|
||||
multi-channel config is wrongly reported even when not enabled. This also
|
||||
helps performance in a multi-channel config, as one interface per port gets
|
||||
RSS rings.
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 804ab7e..adfd66a 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -1778,8 +1778,7 @@ static void be_rx_queues_destroy(struct be_adapter *adapter)
|
||||
static u32 be_num_rxqs_want(struct be_adapter *adapter)
|
||||
{
|
||||
if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
|
||||
- !sriov_enabled(adapter) && be_physfn(adapter) &&
|
||||
- !be_is_mc(adapter)) {
|
||||
+ !sriov_enabled(adapter) && be_physfn(adapter)) {
|
||||
return 1 + MAX_RSS_QS; /* one default non-RSS queue */
|
||||
} else {
|
||||
dev_warn(&adapter->pdev->dev,
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
From: Eric Dumazet <eric.dumazet@gmail.com>
|
||||
Date: Wed, 25 Jan 2012 03:56:30 +0000
|
||||
Subject: [PATCH 28/58] be2net: allocate more headroom in incoming skbs
|
||||
|
||||
commit bb349bb4b19b39830e0486aedfd7c7dca23b7baf upstream.
|
||||
|
||||
Allocation of 64 bytes in skb headroom is not enough if we have to pull
|
||||
ethernet + ipv6 + tcp headers, and/or extra tunneling header.
|
||||
|
||||
Its currently not noticed because netdev_alloc_skb_ip_align(64) give us
|
||||
more room, thanks to power-of-two kmalloc() roundups.
|
||||
|
||||
Make sure we ask for 128 bytes so that side effects of upcoming patches
|
||||
from Ian Campbell dont decrease benet rx performance, because of extra
|
||||
skb head reallocations.
|
||||
|
||||
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
|
||||
Cc: Ian Campbell <Ian.Campbell@citrix.com>
|
||||
Cc: Vasundhara Volam <vasundhara.volam@emulex.com>
|
||||
Cc: Sathya Perla <sathya.perla@emulex.com>
|
||||
Cc: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 3 +++
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 2 +-
|
||||
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index cbdec25..453d486 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -74,6 +74,9 @@ static inline char *nic_name(struct pci_dev *pdev)
|
||||
|
||||
/* Number of bytes of an RX frame that are copied to skb->data */
|
||||
#define BE_HDR_LEN ((u16) 64)
|
||||
+/* allocate extra space to allow tunneling decapsulation without head reallocation */
|
||||
+#define BE_RX_SKB_ALLOC_SIZE (BE_HDR_LEN + 64)
|
||||
+
|
||||
#define BE_MAX_JUMBO_FRAME_SIZE 9018
|
||||
#define BE_MIN_MTU 256
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index adfd66a..860c461 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -1181,7 +1181,7 @@ static void be_rx_compl_process(struct be_adapter *adapter,
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct sk_buff *skb;
|
||||
|
||||
- skb = netdev_alloc_skb_ip_align(netdev, BE_HDR_LEN);
|
||||
+ skb = netdev_alloc_skb_ip_align(netdev, BE_RX_SKB_ALLOC_SIZE);
|
||||
if (unlikely(!skb)) {
|
||||
rx_stats(rxo)->rx_drops_no_skbs++;
|
||||
be_rx_compl_discard(adapter, rxo, rxcp);
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,259 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Sun, 29 Jan 2012 20:17:39 +0000
|
||||
Subject: [PATCH 29/58] be2net: add descriptions for stat counters reported
|
||||
via ethtool
|
||||
|
||||
commit d45b9d39a1aed7851948460d29b843ce70eb0a68 upstream.
|
||||
|
||||
Also rename a few counters appropritely and delete 2 counters that are not
|
||||
implemented in HW.
|
||||
|
||||
vlan_mismatch_drops does not exist in BE3 and is accounted for in
|
||||
address_mismatch_drops. Do the same thing for BE2 and Lancer.
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 3 +-
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.h | 10 ++--
|
||||
drivers/net/ethernet/emulex/benet/be_ethtool.c | 64 ++++++++++++++++++++++--
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 15 +++---
|
||||
4 files changed, 74 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index 453d486..74aa148 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -265,7 +265,6 @@ struct be_drv_stats {
|
||||
u32 rx_drops_no_erx_descr;
|
||||
u32 rx_drops_no_tpre_descr;
|
||||
u32 rx_drops_too_many_frags;
|
||||
- u32 rx_drops_invalid_ring;
|
||||
u32 forwarded_packets;
|
||||
u32 rx_drops_mtu;
|
||||
u32 rx_crc_errors;
|
||||
@@ -276,7 +275,7 @@ struct be_drv_stats {
|
||||
u32 rx_in_range_errors;
|
||||
u32 rx_out_range_errors;
|
||||
u32 rx_frame_too_long;
|
||||
- u32 rx_address_match_errors;
|
||||
+ u32 rx_address_mismatch_drops;
|
||||
u32 rx_dropped_too_small;
|
||||
u32 rx_dropped_too_short;
|
||||
u32 rx_dropped_header_too_small;
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
index dca8924..bbd012b 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
@@ -592,8 +592,8 @@ struct be_port_rxf_stats_v0 {
|
||||
u32 rx_in_range_errors; /* dword 10*/
|
||||
u32 rx_out_range_errors; /* dword 11*/
|
||||
u32 rx_frame_too_long; /* dword 12*/
|
||||
- u32 rx_address_match_errors; /* dword 13*/
|
||||
- u32 rx_vlan_mismatch; /* dword 14*/
|
||||
+ u32 rx_address_mismatch_drops; /* dword 13*/
|
||||
+ u32 rx_vlan_mismatch_drops; /* dword 14*/
|
||||
u32 rx_dropped_too_small; /* dword 15*/
|
||||
u32 rx_dropped_too_short; /* dword 16*/
|
||||
u32 rx_dropped_header_too_small; /* dword 17*/
|
||||
@@ -799,8 +799,8 @@ struct lancer_pport_stats {
|
||||
u32 rx_control_frames_unknown_opcode_hi;
|
||||
u32 rx_in_range_errors;
|
||||
u32 rx_out_of_range_errors;
|
||||
- u32 rx_address_match_errors;
|
||||
- u32 rx_vlan_mismatch_errors;
|
||||
+ u32 rx_address_mismatch_drops;
|
||||
+ u32 rx_vlan_mismatch_drops;
|
||||
u32 rx_dropped_too_small;
|
||||
u32 rx_dropped_too_short;
|
||||
u32 rx_dropped_header_too_small;
|
||||
@@ -1384,7 +1384,7 @@ struct be_port_rxf_stats_v1 {
|
||||
u32 rx_in_range_errors;
|
||||
u32 rx_out_range_errors;
|
||||
u32 rx_frame_too_long;
|
||||
- u32 rx_address_match_errors;
|
||||
+ u32 rx_address_mismatch_drops;
|
||||
u32 rx_dropped_too_small;
|
||||
u32 rx_dropped_too_short;
|
||||
u32 rx_dropped_header_too_small;
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
index 6db6b6a..0a5ee22 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
@@ -42,15 +42,42 @@ static const struct be_ethtool_stat et_stats[] = {
|
||||
{DRVSTAT_INFO(rx_alignment_symbol_errors)},
|
||||
{DRVSTAT_INFO(rx_pause_frames)},
|
||||
{DRVSTAT_INFO(rx_control_frames)},
|
||||
+ /* Received packets dropped when the Ethernet length field
|
||||
+ * is not equal to the actual Ethernet data length.
|
||||
+ */
|
||||
{DRVSTAT_INFO(rx_in_range_errors)},
|
||||
+ /* Received packets dropped when their length field is >= 1501 bytes
|
||||
+ * and <= 1535 bytes.
|
||||
+ */
|
||||
{DRVSTAT_INFO(rx_out_range_errors)},
|
||||
+ /* Received packets dropped when they are longer than 9216 bytes */
|
||||
{DRVSTAT_INFO(rx_frame_too_long)},
|
||||
- {DRVSTAT_INFO(rx_address_match_errors)},
|
||||
+ /* Received packets dropped when they don't pass the unicast or
|
||||
+ * multicast address filtering.
|
||||
+ */
|
||||
+ {DRVSTAT_INFO(rx_address_mismatch_drops)},
|
||||
+ /* Received packets dropped when IP packet length field is less than
|
||||
+ * the IP header length field.
|
||||
+ */
|
||||
{DRVSTAT_INFO(rx_dropped_too_small)},
|
||||
+ /* Received packets dropped when IP length field is greater than
|
||||
+ * the actual packet length.
|
||||
+ */
|
||||
{DRVSTAT_INFO(rx_dropped_too_short)},
|
||||
+ /* Received packets dropped when the IP header length field is less
|
||||
+ * than 5.
|
||||
+ */
|
||||
{DRVSTAT_INFO(rx_dropped_header_too_small)},
|
||||
+ /* Received packets dropped when the TCP header length field is less
|
||||
+ * than 5 or the TCP header length + IP header length is more
|
||||
+ * than IP packet length.
|
||||
+ */
|
||||
{DRVSTAT_INFO(rx_dropped_tcp_length)},
|
||||
{DRVSTAT_INFO(rx_dropped_runt)},
|
||||
+ /* Number of received packets dropped when a fifo for descriptors going
|
||||
+ * into the packet demux block overflows. In normal operation, this
|
||||
+ * fifo must never overflow.
|
||||
+ */
|
||||
{DRVSTAT_INFO(rxpp_fifo_overflow_drop)},
|
||||
{DRVSTAT_INFO(rx_input_fifo_overflow_drop)},
|
||||
{DRVSTAT_INFO(rx_ip_checksum_errs)},
|
||||
@@ -59,16 +86,35 @@ static const struct be_ethtool_stat et_stats[] = {
|
||||
{DRVSTAT_INFO(tx_pauseframes)},
|
||||
{DRVSTAT_INFO(tx_controlframes)},
|
||||
{DRVSTAT_INFO(rx_priority_pause_frames)},
|
||||
+ /* Received packets dropped when an internal fifo going into
|
||||
+ * main packet buffer tank (PMEM) overflows.
|
||||
+ */
|
||||
{DRVSTAT_INFO(pmem_fifo_overflow_drop)},
|
||||
{DRVSTAT_INFO(jabber_events)},
|
||||
+ /* Received packets dropped due to lack of available HW packet buffers
|
||||
+ * used to temporarily hold the received packets.
|
||||
+ */
|
||||
{DRVSTAT_INFO(rx_drops_no_pbuf)},
|
||||
- {DRVSTAT_INFO(rx_drops_no_txpb)},
|
||||
+ /* Received packets dropped due to input receive buffer
|
||||
+ * descriptor fifo overflowing.
|
||||
+ */
|
||||
{DRVSTAT_INFO(rx_drops_no_erx_descr)},
|
||||
+ /* Packets dropped because the internal FIFO to the offloaded TCP
|
||||
+ * receive processing block is full. This could happen only for
|
||||
+ * offloaded iSCSI or FCoE trarffic.
|
||||
+ */
|
||||
{DRVSTAT_INFO(rx_drops_no_tpre_descr)},
|
||||
+ /* Received packets dropped when they need more than 8
|
||||
+ * receive buffers. This cannot happen as the driver configures
|
||||
+ * 2048 byte receive buffers.
|
||||
+ */
|
||||
{DRVSTAT_INFO(rx_drops_too_many_frags)},
|
||||
- {DRVSTAT_INFO(rx_drops_invalid_ring)},
|
||||
{DRVSTAT_INFO(forwarded_packets)},
|
||||
+ /* Received packets dropped when the frame length
|
||||
+ * is more than 9018 bytes
|
||||
+ */
|
||||
{DRVSTAT_INFO(rx_drops_mtu)},
|
||||
+ /* Number of packets dropped due to random early drop function */
|
||||
{DRVSTAT_INFO(eth_red_drops)},
|
||||
{DRVSTAT_INFO(be_on_die_temperature)}
|
||||
};
|
||||
@@ -84,8 +130,15 @@ static const struct be_ethtool_stat et_rx_stats[] = {
|
||||
{DRVSTAT_RX_INFO(rx_events)},
|
||||
{DRVSTAT_RX_INFO(rx_compl)},
|
||||
{DRVSTAT_RX_INFO(rx_mcast_pkts)},
|
||||
+ /* Number of page allocation failures while posting receive buffers
|
||||
+ * to HW.
|
||||
+ */
|
||||
{DRVSTAT_RX_INFO(rx_post_fail)},
|
||||
+ /* Recevied packets dropped due to skb allocation failure */
|
||||
{DRVSTAT_RX_INFO(rx_drops_no_skbs)},
|
||||
+ /* Received packets dropped due to lack of available fetched buffers
|
||||
+ * posted by the driver.
|
||||
+ */
|
||||
{DRVSTAT_RX_INFO(rx_drops_no_frags)}
|
||||
};
|
||||
#define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))
|
||||
@@ -97,9 +150,14 @@ static const struct be_ethtool_stat et_tx_stats[] = {
|
||||
{DRVSTAT_TX_INFO(tx_compl)}, /* If moving this member see above note */
|
||||
{DRVSTAT_TX_INFO(tx_bytes)},
|
||||
{DRVSTAT_TX_INFO(tx_pkts)},
|
||||
+ /* Number of skbs queued for trasmission by the driver */
|
||||
{DRVSTAT_TX_INFO(tx_reqs)},
|
||||
+ /* Number of TX work request blocks DMAed to HW */
|
||||
{DRVSTAT_TX_INFO(tx_wrbs)},
|
||||
{DRVSTAT_TX_INFO(tx_compl)},
|
||||
+ /* Number of times the TX queue was stopped due to lack
|
||||
+ * of spaces in the TXQ.
|
||||
+ */
|
||||
{DRVSTAT_TX_INFO(tx_stops)}
|
||||
};
|
||||
#define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats))
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 860c461..d1536e2 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -286,7 +286,9 @@ static void populate_be2_stats(struct be_adapter *adapter)
|
||||
drvs->rx_input_fifo_overflow_drop = port_stats->rx_input_fifo_overflow;
|
||||
drvs->rx_dropped_header_too_small =
|
||||
port_stats->rx_dropped_header_too_small;
|
||||
- drvs->rx_address_match_errors = port_stats->rx_address_match_errors;
|
||||
+ drvs->rx_address_mismatch_drops =
|
||||
+ port_stats->rx_address_mismatch_drops +
|
||||
+ port_stats->rx_vlan_mismatch_drops;
|
||||
drvs->rx_alignment_symbol_errors =
|
||||
port_stats->rx_alignment_symbol_errors;
|
||||
|
||||
@@ -298,9 +300,7 @@ static void populate_be2_stats(struct be_adapter *adapter)
|
||||
else
|
||||
drvs->jabber_events = rxf_stats->port0_jabber_events;
|
||||
drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf;
|
||||
- drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb;
|
||||
drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr;
|
||||
- drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring;
|
||||
drvs->forwarded_packets = rxf_stats->forwarded_packets;
|
||||
drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu;
|
||||
drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr;
|
||||
@@ -337,7 +337,7 @@ static void populate_be3_stats(struct be_adapter *adapter)
|
||||
port_stats->rx_dropped_header_too_small;
|
||||
drvs->rx_input_fifo_overflow_drop =
|
||||
port_stats->rx_input_fifo_overflow_drop;
|
||||
- drvs->rx_address_match_errors = port_stats->rx_address_match_errors;
|
||||
+ drvs->rx_address_mismatch_drops = port_stats->rx_address_mismatch_drops;
|
||||
drvs->rx_alignment_symbol_errors =
|
||||
port_stats->rx_alignment_symbol_errors;
|
||||
drvs->rxpp_fifo_overflow_drop = port_stats->rxpp_fifo_overflow_drop;
|
||||
@@ -345,9 +345,7 @@ static void populate_be3_stats(struct be_adapter *adapter)
|
||||
drvs->tx_controlframes = port_stats->tx_controlframes;
|
||||
drvs->jabber_events = port_stats->jabber_events;
|
||||
drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf;
|
||||
- drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb;
|
||||
drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr;
|
||||
- drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring;
|
||||
drvs->forwarded_packets = rxf_stats->forwarded_packets;
|
||||
drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu;
|
||||
drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr;
|
||||
@@ -380,13 +378,14 @@ static void populate_lancer_stats(struct be_adapter *adapter)
|
||||
drvs->rx_dropped_header_too_small =
|
||||
pport_stats->rx_dropped_header_too_small;
|
||||
drvs->rx_input_fifo_overflow_drop = pport_stats->rx_fifo_overflow;
|
||||
- drvs->rx_address_match_errors = pport_stats->rx_address_match_errors;
|
||||
+ drvs->rx_address_mismatch_drops =
|
||||
+ pport_stats->rx_address_mismatch_drops +
|
||||
+ pport_stats->rx_vlan_mismatch_drops;
|
||||
drvs->rx_alignment_symbol_errors = pport_stats->rx_symbol_errors_lo;
|
||||
drvs->rxpp_fifo_overflow_drop = pport_stats->rx_fifo_overflow;
|
||||
drvs->tx_pauseframes = pport_stats->tx_pause_frames_lo;
|
||||
drvs->tx_controlframes = pport_stats->tx_control_frames_lo;
|
||||
drvs->jabber_events = pport_stats->rx_jabbers;
|
||||
- drvs->rx_drops_invalid_ring = pport_stats->rx_drops_invalid_queue;
|
||||
drvs->forwarded_packets = pport_stats->num_forwards_lo;
|
||||
drvs->rx_drops_mtu = pport_stats->rx_drops_mtu_lo;
|
||||
drvs->rx_drops_too_many_frags =
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Fri, 3 Feb 2012 09:49:46 +0000
|
||||
Subject: [PATCH 30/58] be2net: Fix link status query command
|
||||
|
||||
commit 57cd80d4d511748f3973accc6919e7e1e1936ebb upstream.
|
||||
|
||||
Version number in query link status command is getting overwritten in
|
||||
be_wrb_cmd_hdr_prepare() routine. Move the initialization to fix this
|
||||
issue. Also initialize the domain field.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 0fcb456..dd6e8e2 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -1257,11 +1257,13 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
|
||||
}
|
||||
req = embedded_payload(wrb);
|
||||
|
||||
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
+ OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL);
|
||||
+
|
||||
if (adapter->generation == BE_GEN3 || lancer_chip(adapter))
|
||||
req->hdr.version = 1;
|
||||
|
||||
- be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
- OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL);
|
||||
+ req->hdr.domain = dom;
|
||||
|
||||
status = be_mcc_notify_wait(adapter);
|
||||
if (!status) {
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,237 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Fri, 3 Feb 2012 09:50:17 +0000
|
||||
Subject: [PATCH 31/58] be2net: Use new implementation of get mac list command
|
||||
|
||||
commit e5e1ee89461543043a0144e6dac90547fefe2f89 upstream.
|
||||
|
||||
VFs use get mac list command to get their mac address. The format of
|
||||
this command has changed. Update driver to use the new format.
|
||||
|
||||
Signed-off-by: Mammatha Edhala <mammatha.edhala@emulex.com>
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 67 +++++++++++++++++++--------
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.h | 36 +++++++++-----
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 29 ++++++++----
|
||||
3 files changed, 92 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index dd6e8e2..29dff7d 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -2300,52 +2300,81 @@ err:
|
||||
|
||||
/* Uses synchronous MCCQ */
|
||||
int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain,
|
||||
- u32 *pmac_id)
|
||||
+ bool *pmac_id_active, u32 *pmac_id, u8 *mac)
|
||||
{
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_cmd_req_get_mac_list *req;
|
||||
int status;
|
||||
int mac_count;
|
||||
+ struct be_dma_mem get_mac_list_cmd;
|
||||
+ int i;
|
||||
+
|
||||
+ memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem));
|
||||
+ get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list);
|
||||
+ get_mac_list_cmd.va = pci_alloc_consistent(adapter->pdev,
|
||||
+ get_mac_list_cmd.size,
|
||||
+ &get_mac_list_cmd.dma);
|
||||
+
|
||||
+ if (!get_mac_list_cmd.va) {
|
||||
+ dev_err(&adapter->pdev->dev,
|
||||
+ "Memory allocation failure during GET_MAC_LIST\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
|
||||
spin_lock_bh(&adapter->mcc_lock);
|
||||
|
||||
wrb = wrb_from_mccq(adapter);
|
||||
if (!wrb) {
|
||||
status = -EBUSY;
|
||||
- goto err;
|
||||
+ goto out;
|
||||
}
|
||||
- req = embedded_payload(wrb);
|
||||
+
|
||||
+ req = get_mac_list_cmd.va;
|
||||
|
||||
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
OPCODE_COMMON_GET_MAC_LIST, sizeof(*req),
|
||||
- wrb, NULL);
|
||||
+ wrb, &get_mac_list_cmd);
|
||||
|
||||
req->hdr.domain = domain;
|
||||
+ req->mac_type = MAC_ADDRESS_TYPE_NETWORK;
|
||||
+ req->perm_override = 1;
|
||||
|
||||
status = be_mcc_notify_wait(adapter);
|
||||
if (!status) {
|
||||
struct be_cmd_resp_get_mac_list *resp =
|
||||
- embedded_payload(wrb);
|
||||
- int i;
|
||||
- u8 *ctxt = &resp->context[0][0];
|
||||
- status = -EIO;
|
||||
- mac_count = resp->mac_count;
|
||||
- be_dws_le_to_cpu(&resp->context, sizeof(resp->context));
|
||||
+ get_mac_list_cmd.va;
|
||||
+ mac_count = resp->true_mac_count + resp->pseudo_mac_count;
|
||||
+ /* Mac list returned could contain one or more active mac_ids
|
||||
+ * or one or more pseudo permanant mac addresses. If an active
|
||||
+ * mac_id is present, return first active mac_id found
|
||||
+ */
|
||||
for (i = 0; i < mac_count; i++) {
|
||||
- if (!AMAP_GET_BITS(struct amap_get_mac_list_context,
|
||||
- act, ctxt)) {
|
||||
- *pmac_id = AMAP_GET_BITS
|
||||
- (struct amap_get_mac_list_context,
|
||||
- macid, ctxt);
|
||||
- status = 0;
|
||||
- break;
|
||||
+ struct get_list_macaddr *mac_entry;
|
||||
+ u16 mac_addr_size;
|
||||
+ u32 mac_id;
|
||||
+
|
||||
+ mac_entry = &resp->macaddr_list[i];
|
||||
+ mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size);
|
||||
+ /* mac_id is a 32 bit value and mac_addr size
|
||||
+ * is 6 bytes
|
||||
+ */
|
||||
+ if (mac_addr_size == sizeof(u32)) {
|
||||
+ *pmac_id_active = true;
|
||||
+ mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id;
|
||||
+ *pmac_id = le32_to_cpu(mac_id);
|
||||
+ goto out;
|
||||
}
|
||||
- ctxt += sizeof(struct amap_get_mac_list_context) / 8;
|
||||
}
|
||||
+ /* If no active mac_id found, return first pseudo mac addr */
|
||||
+ *pmac_id_active = false;
|
||||
+ memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr,
|
||||
+ ETH_ALEN);
|
||||
}
|
||||
|
||||
-err:
|
||||
+out:
|
||||
spin_unlock_bh(&adapter->mcc_lock);
|
||||
+ pci_free_consistent(adapter->pdev, get_mac_list_cmd.size,
|
||||
+ get_mac_list_cmd.va, get_mac_list_cmd.dma);
|
||||
return status;
|
||||
}
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
index bbd012b..5bb66c8 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
@@ -1346,22 +1346,36 @@ struct be_cmd_resp_set_func_cap {
|
||||
|
||||
/******************** GET/SET_MACLIST **************************/
|
||||
#define BE_MAX_MAC 64
|
||||
-struct amap_get_mac_list_context {
|
||||
- u8 macid[31];
|
||||
- u8 act;
|
||||
-} __packed;
|
||||
-
|
||||
struct be_cmd_req_get_mac_list {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
- u32 rsvd;
|
||||
+ u8 mac_type;
|
||||
+ u8 perm_override;
|
||||
+ u16 iface_id;
|
||||
+ u32 mac_id;
|
||||
+ u32 rsvd[3];
|
||||
+} __packed;
|
||||
+
|
||||
+struct get_list_macaddr {
|
||||
+ u16 mac_addr_size;
|
||||
+ union {
|
||||
+ u8 macaddr[6];
|
||||
+ struct {
|
||||
+ u8 rsvd[2];
|
||||
+ u32 mac_id;
|
||||
+ } __packed s_mac_id;
|
||||
+ } __packed mac_addr_id;
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_resp_get_mac_list {
|
||||
struct be_cmd_resp_hdr hdr;
|
||||
- u8 mac_count;
|
||||
- u8 rsvd1;
|
||||
- u16 rsvd2;
|
||||
- u8 context[sizeof(struct amap_get_mac_list_context) / 8][BE_MAX_MAC];
|
||||
+ struct get_list_macaddr fd_macaddr; /* Factory default mac */
|
||||
+ struct get_list_macaddr macid_macaddr; /* soft mac */
|
||||
+ u8 true_mac_count;
|
||||
+ u8 pseudo_mac_count;
|
||||
+ u8 mac_list_size;
|
||||
+ u8 rsvd;
|
||||
+ /* perm override mac */
|
||||
+ struct get_list_macaddr macaddr_list[BE_MAX_MAC];
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_req_set_mac_list {
|
||||
@@ -1575,7 +1589,7 @@ extern int be_cmd_req_native_mode(struct be_adapter *adapter);
|
||||
extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
|
||||
extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
|
||||
extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain,
|
||||
- u32 *pmac_id);
|
||||
+ bool *pmac_id_active, u32 *pmac_id, u8 *mac);
|
||||
extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
|
||||
u8 mac_count, u32 domain);
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index d1536e2..4364f01 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -2600,19 +2600,28 @@ static void be_setup_init(struct be_adapter *adapter)
|
||||
adapter->eq_next_idx = 0;
|
||||
}
|
||||
|
||||
-static int be_configure_mac_from_list(struct be_adapter *adapter, u8 *mac)
|
||||
+static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac)
|
||||
{
|
||||
u32 pmac_id;
|
||||
- int status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id);
|
||||
- if (status != 0)
|
||||
- goto do_none;
|
||||
- status = be_cmd_mac_addr_query(adapter, mac,
|
||||
- MAC_ADDRESS_TYPE_NETWORK,
|
||||
- false, adapter->if_handle, pmac_id);
|
||||
+ int status;
|
||||
+ bool pmac_id_active;
|
||||
+
|
||||
+ status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id_active,
|
||||
+ &pmac_id, mac);
|
||||
if (status != 0)
|
||||
goto do_none;
|
||||
- status = be_cmd_pmac_add(adapter, mac, adapter->if_handle,
|
||||
- &adapter->pmac_id, 0);
|
||||
+
|
||||
+ if (pmac_id_active) {
|
||||
+ status = be_cmd_mac_addr_query(adapter, mac,
|
||||
+ MAC_ADDRESS_TYPE_NETWORK,
|
||||
+ false, adapter->if_handle, pmac_id);
|
||||
+
|
||||
+ if (!status)
|
||||
+ adapter->pmac_id = pmac_id;
|
||||
+ } else {
|
||||
+ status = be_cmd_pmac_add(adapter, mac,
|
||||
+ adapter->if_handle, &adapter->pmac_id, 0);
|
||||
+ }
|
||||
do_none:
|
||||
return status;
|
||||
}
|
||||
@@ -2677,7 +2686,7 @@ static int be_setup(struct be_adapter *adapter)
|
||||
*/
|
||||
if (!be_physfn(adapter)) {
|
||||
if (lancer_chip(adapter))
|
||||
- status = be_configure_mac_from_list(adapter, mac);
|
||||
+ status = be_add_mac_from_list(adapter, mac);
|
||||
else
|
||||
status = be_cmd_mac_addr_query(adapter, mac,
|
||||
MAC_ADDRESS_TYPE_NETWORK, false,
|
||||
--
|
||||
1.7.10
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,90 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Thu, 23 Feb 2012 18:50:13 +0000
|
||||
Subject: [PATCH 33/58] be2net: cancel be_worker during EEH recovery
|
||||
|
||||
commit 191eb7563164529bc7d6a693742fe5bed33cf004 upstream.
|
||||
|
||||
EEH recovery involves ring cleanup and re-creation. The worker
|
||||
thread must not run during EEH cleanup/resume.
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 1 +
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 13 ++++++++-----
|
||||
2 files changed, 9 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index 86f51de..4b1994d 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -304,6 +304,7 @@ struct be_vf_cfg {
|
||||
};
|
||||
|
||||
#define BE_FLAGS_LINK_STATUS_INIT 1
|
||||
+#define BE_FLAGS_WORKER_SCHEDULED (1 << 3)
|
||||
|
||||
struct be_adapter {
|
||||
struct pci_dev *pdev;
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 4a3a186..2c146ac 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -2439,6 +2439,11 @@ static void be_vf_clear(struct be_adapter *adapter)
|
||||
|
||||
static int be_clear(struct be_adapter *adapter)
|
||||
{
|
||||
+ if (adapter->flags & BE_FLAGS_WORKER_SCHEDULED) {
|
||||
+ cancel_delayed_work_sync(&adapter->work);
|
||||
+ adapter->flags &= ~BE_FLAGS_WORKER_SCHEDULED;
|
||||
+ }
|
||||
+
|
||||
if (sriov_enabled(adapter))
|
||||
be_vf_clear(adapter);
|
||||
|
||||
@@ -2640,6 +2645,9 @@ static int be_setup(struct be_adapter *adapter)
|
||||
goto err;
|
||||
}
|
||||
|
||||
+ schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
|
||||
+ adapter->flags |= BE_FLAGS_WORKER_SCHEDULED;
|
||||
+
|
||||
return 0;
|
||||
err:
|
||||
be_clear(adapter);
|
||||
@@ -3200,8 +3208,6 @@ static void __devexit be_remove(struct pci_dev *pdev)
|
||||
if (!adapter)
|
||||
return;
|
||||
|
||||
- cancel_delayed_work_sync(&adapter->work);
|
||||
-
|
||||
unregister_netdev(adapter->netdev);
|
||||
|
||||
be_clear(adapter);
|
||||
@@ -3525,7 +3531,6 @@ static int __devinit be_probe(struct pci_dev *pdev,
|
||||
dev_info(&pdev->dev, "%s: %s port %d\n", netdev->name, nic_name(pdev),
|
||||
adapter->port_num);
|
||||
|
||||
- schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
|
||||
return 0;
|
||||
|
||||
unsetup:
|
||||
@@ -3555,7 +3560,6 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
struct be_adapter *adapter = pci_get_drvdata(pdev);
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
|
||||
- cancel_delayed_work_sync(&adapter->work);
|
||||
if (adapter->wol)
|
||||
be_setup_wol(adapter, true);
|
||||
|
||||
@@ -3604,7 +3608,6 @@ static int be_resume(struct pci_dev *pdev)
|
||||
if (adapter->wol)
|
||||
be_setup_wol(adapter, false);
|
||||
|
||||
- schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Thu, 23 Feb 2012 18:50:14 +0000
|
||||
Subject: [PATCH 34/58] be2net: fix tx completion cleanup
|
||||
|
||||
commit 0ae57bb3df562e57ac89ad7bc524b6f2e83235f9 upstream.
|
||||
|
||||
As a part of be_close(), instead of waiting for a max of 200ms for each TXQ,
|
||||
wait for a total of 200ms for completions from all TXQs to arrive.
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 75 +++++++++++++++------------
|
||||
1 file changed, 42 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 2c146ac..dce97dc 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -1555,51 +1555,62 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo)
|
||||
rxq->tail = rxq->head = 0;
|
||||
}
|
||||
|
||||
-static void be_tx_compl_clean(struct be_adapter *adapter,
|
||||
- struct be_tx_obj *txo)
|
||||
+static void be_tx_compl_clean(struct be_adapter *adapter)
|
||||
{
|
||||
- struct be_queue_info *tx_cq = &txo->cq;
|
||||
- struct be_queue_info *txq = &txo->q;
|
||||
+ struct be_tx_obj *txo;
|
||||
+ struct be_queue_info *txq;
|
||||
struct be_eth_tx_compl *txcp;
|
||||
u16 end_idx, cmpl = 0, timeo = 0, num_wrbs = 0;
|
||||
- struct sk_buff **sent_skbs = txo->sent_skb_list;
|
||||
struct sk_buff *sent_skb;
|
||||
bool dummy_wrb;
|
||||
+ int i, pending_txqs;
|
||||
|
||||
/* Wait for a max of 200ms for all the tx-completions to arrive. */
|
||||
do {
|
||||
- while ((txcp = be_tx_compl_get(tx_cq))) {
|
||||
- end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
|
||||
- wrb_index, txcp);
|
||||
- num_wrbs += be_tx_compl_process(adapter, txo, end_idx);
|
||||
- cmpl++;
|
||||
- }
|
||||
- if (cmpl) {
|
||||
- be_cq_notify(adapter, tx_cq->id, false, cmpl);
|
||||
- atomic_sub(num_wrbs, &txq->used);
|
||||
- cmpl = 0;
|
||||
- num_wrbs = 0;
|
||||
+ pending_txqs = adapter->num_tx_qs;
|
||||
+
|
||||
+ for_all_tx_queues(adapter, txo, i) {
|
||||
+ txq = &txo->q;
|
||||
+ while ((txcp = be_tx_compl_get(&txo->cq))) {
|
||||
+ end_idx =
|
||||
+ AMAP_GET_BITS(struct amap_eth_tx_compl,
|
||||
+ wrb_index, txcp);
|
||||
+ num_wrbs += be_tx_compl_process(adapter, txo,
|
||||
+ end_idx);
|
||||
+ cmpl++;
|
||||
+ }
|
||||
+ if (cmpl) {
|
||||
+ be_cq_notify(adapter, txo->cq.id, false, cmpl);
|
||||
+ atomic_sub(num_wrbs, &txq->used);
|
||||
+ cmpl = 0;
|
||||
+ num_wrbs = 0;
|
||||
+ }
|
||||
+ if (atomic_read(&txq->used) == 0)
|
||||
+ pending_txqs--;
|
||||
}
|
||||
|
||||
- if (atomic_read(&txq->used) == 0 || ++timeo > 200)
|
||||
+ if (pending_txqs == 0 || ++timeo > 200)
|
||||
break;
|
||||
|
||||
mdelay(1);
|
||||
} while (true);
|
||||
|
||||
- if (atomic_read(&txq->used))
|
||||
- dev_err(&adapter->pdev->dev, "%d pending tx-completions\n",
|
||||
- atomic_read(&txq->used));
|
||||
-
|
||||
- /* free posted tx for which compls will never arrive */
|
||||
- while (atomic_read(&txq->used)) {
|
||||
- sent_skb = sent_skbs[txq->tail];
|
||||
- end_idx = txq->tail;
|
||||
- index_adv(&end_idx,
|
||||
- wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1,
|
||||
- txq->len);
|
||||
- num_wrbs = be_tx_compl_process(adapter, txo, end_idx);
|
||||
- atomic_sub(num_wrbs, &txq->used);
|
||||
+ for_all_tx_queues(adapter, txo, i) {
|
||||
+ txq = &txo->q;
|
||||
+ if (atomic_read(&txq->used))
|
||||
+ dev_err(&adapter->pdev->dev, "%d pending tx-compls\n",
|
||||
+ atomic_read(&txq->used));
|
||||
+
|
||||
+ /* free posted tx for which compls will never arrive */
|
||||
+ while (atomic_read(&txq->used)) {
|
||||
+ sent_skb = txo->sent_skb_list[txq->tail];
|
||||
+ end_idx = txq->tail;
|
||||
+ num_wrbs = wrb_cnt_for_skb(adapter, sent_skb,
|
||||
+ &dummy_wrb);
|
||||
+ index_adv(&end_idx, num_wrbs - 1, txq->len);
|
||||
+ num_wrbs = be_tx_compl_process(adapter, txo, end_idx);
|
||||
+ atomic_sub(num_wrbs, &txq->used);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2228,7 +2239,6 @@ static void be_rx_qs_destroy(struct be_adapter *adapter)
|
||||
static int be_close(struct net_device *netdev)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
- struct be_tx_obj *txo;
|
||||
struct be_eq_obj *eqo;
|
||||
int i;
|
||||
|
||||
@@ -2251,8 +2261,7 @@ static int be_close(struct net_device *netdev)
|
||||
/* Wait for all pending tx completions to arrive so that
|
||||
* all tx skbs are freed.
|
||||
*/
|
||||
- for_all_tx_queues(adapter, txo, i)
|
||||
- be_tx_compl_clean(adapter, txo);
|
||||
+ be_tx_compl_clean(adapter);
|
||||
|
||||
be_rx_qs_destroy(adapter);
|
||||
return 0;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Thu, 23 Feb 2012 18:50:15 +0000
|
||||
Subject: [PATCH 35/58] be2net: reset queue address after freeing
|
||||
|
||||
commit 1cfafab965198bc0d9cb794af5065d0797969727 upstream.
|
||||
|
||||
This will prevent double free in some cases where be_clear() is called
|
||||
for cleanup when be_setup() fails half-way.
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index dce97dc..c1b9cdf 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -127,9 +127,11 @@ static inline bool be_is_mc(struct be_adapter *adapter) {
|
||||
static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q)
|
||||
{
|
||||
struct be_dma_mem *mem = &q->dma_mem;
|
||||
- if (mem->va)
|
||||
+ if (mem->va) {
|
||||
dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
|
||||
mem->dma);
|
||||
+ mem->va = NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
|
||||
@@ -1652,7 +1654,7 @@ static int be_evt_queues_create(struct be_adapter *adapter)
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
- return rc;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void be_mcc_queues_destroy(struct be_adapter *adapter)
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Thu, 23 Feb 2012 18:50:16 +0000
|
||||
Subject: [PATCH 36/58] be2net: enable RSS for ipv6 pkts
|
||||
|
||||
commit 1ca7ba921e8af04266881bc485be08d4fac5f1bc upstream.
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 6432efa..398fb5c 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -1694,7 +1694,8 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size)
|
||||
OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL);
|
||||
|
||||
req->if_id = cpu_to_le32(adapter->if_handle);
|
||||
- req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4);
|
||||
+ req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4 |
|
||||
+ RSS_ENABLE_TCP_IPV6 | RSS_ENABLE_IPV6);
|
||||
req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1);
|
||||
memcpy(req->cpu_table, rsstable, table_size);
|
||||
memcpy(req->hash, myhash, sizeof(myhash));
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Thu, 23 Feb 2012 18:50:17 +0000
|
||||
Subject: [PATCH 37/58] be2net: update driver version
|
||||
|
||||
commit d708f6039b21ca8f0508ba1da1aaf3d00a36446f upstream.
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index 4b1994d..c357172 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include "be_hw.h"
|
||||
|
||||
-#define DRV_VER "4.0.100u"
|
||||
+#define DRV_VER "4.2.116u"
|
||||
#define DRV_NAME "be2net"
|
||||
#define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC"
|
||||
#define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC"
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
From: Roland Dreier <roland@purestorage.com>
|
||||
Date: Wed, 29 Feb 2012 20:40:46 +0000
|
||||
Subject: [PATCH 38/58] be2net: Remove unused OFFSET_IN_PAGE() macro
|
||||
|
||||
commit 97767a87f3be8834192dc3fc9412aaccf708d87f upstream.
|
||||
|
||||
Signed-off-by: Roland Dreier <roland@purestorage.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 4 ----
|
||||
1 file changed, 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index c357172..ab24e46 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -442,10 +442,6 @@ extern const struct ethtool_ops be_ethtool_ops;
|
||||
((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \
|
||||
(size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K))
|
||||
|
||||
-/* Byte offset into the page corresponding to given address */
|
||||
-#define OFFSET_IN_PAGE(addr) \
|
||||
- ((size_t)(addr) & (PAGE_SIZE_4K-1))
|
||||
-
|
||||
/* Returns bit offset within a DWORD of a bitfield */
|
||||
#define AMAP_BIT_OFFSET(_struct, field) \
|
||||
(((size_t)&(((_struct *)0)->field))%32)
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,274 +0,0 @@
|
|||
From: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Date: Sun, 18 Mar 2012 06:23:11 +0000
|
||||
Subject: [PATCH 39/58] be2net: enable WOL by default if h/w supports it
|
||||
|
||||
commit 4762f6cec4455f3bbe4ca82c100fe5d85d3c02a2 upstream.
|
||||
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 26 ++++++++++-
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 55 ++++++++++++++++++++++++
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.h | 28 ++++++++++++
|
||||
drivers/net/ethernet/emulex/benet/be_ethtool.c | 27 +++++-------
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 17 ++++++++
|
||||
5 files changed, 136 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index ab24e46..cabe1b8 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -52,6 +52,10 @@
|
||||
#define OC_DEVICE_ID3 0xe220 /* Device id for Lancer cards */
|
||||
#define OC_DEVICE_ID4 0xe228 /* Device id for VF in Lancer */
|
||||
#define OC_DEVICE_ID5 0x720 /* Device Id for Skyhawk cards */
|
||||
+#define OC_SUBSYS_DEVICE_ID1 0xE602
|
||||
+#define OC_SUBSYS_DEVICE_ID2 0xE642
|
||||
+#define OC_SUBSYS_DEVICE_ID3 0xE612
|
||||
+#define OC_SUBSYS_DEVICE_ID4 0xE652
|
||||
|
||||
static inline char *nic_name(struct pci_dev *pdev)
|
||||
{
|
||||
@@ -365,7 +369,6 @@ struct be_adapter {
|
||||
bool fw_timeout;
|
||||
u32 port_num;
|
||||
bool promiscuous;
|
||||
- bool wol;
|
||||
u32 function_mode;
|
||||
u32 function_caps;
|
||||
u32 rx_fc; /* Rx flow control */
|
||||
@@ -386,6 +389,8 @@ struct be_adapter {
|
||||
u32 sli_family;
|
||||
u8 hba_port_num;
|
||||
u16 pvid;
|
||||
+ u8 wol_cap;
|
||||
+ bool wol;
|
||||
};
|
||||
|
||||
#define be_physfn(adapter) (!adapter->is_virtfn)
|
||||
@@ -549,9 +554,28 @@ static inline bool be_error(struct be_adapter *adapter)
|
||||
return adapter->eeh_err || adapter->ue_detected || adapter->fw_timeout;
|
||||
}
|
||||
|
||||
+static inline bool be_is_wol_excluded(struct be_adapter *adapter)
|
||||
+{
|
||||
+ struct pci_dev *pdev = adapter->pdev;
|
||||
+
|
||||
+ if (!be_physfn(adapter))
|
||||
+ return true;
|
||||
+
|
||||
+ switch (pdev->subsystem_device) {
|
||||
+ case OC_SUBSYS_DEVICE_ID1:
|
||||
+ case OC_SUBSYS_DEVICE_ID2:
|
||||
+ case OC_SUBSYS_DEVICE_ID3:
|
||||
+ case OC_SUBSYS_DEVICE_ID4:
|
||||
+ return true;
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
|
||||
u16 num_popped);
|
||||
extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
|
||||
extern void be_parse_stats(struct be_adapter *adapter);
|
||||
extern int be_load_fw(struct be_adapter *adapter, u8 *func);
|
||||
+extern bool be_is_wol_supported(struct be_adapter *adapter);
|
||||
#endif /* BE_H */
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 398fb5c..d72c2b4 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -2418,3 +2418,58 @@ err:
|
||||
spin_unlock_bh(&adapter->mcc_lock);
|
||||
return status;
|
||||
}
|
||||
+
|
||||
+int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
|
||||
+{
|
||||
+ struct be_mcc_wrb *wrb;
|
||||
+ struct be_cmd_req_acpi_wol_magic_config_v1 *req;
|
||||
+ int status;
|
||||
+ int payload_len = sizeof(*req);
|
||||
+ struct be_dma_mem cmd;
|
||||
+
|
||||
+ memset(&cmd, 0, sizeof(struct be_dma_mem));
|
||||
+ cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
|
||||
+ cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
|
||||
+ &cmd.dma);
|
||||
+ if (!cmd.va) {
|
||||
+ dev_err(&adapter->pdev->dev,
|
||||
+ "Memory allocation failure\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ if (mutex_lock_interruptible(&adapter->mbox_lock))
|
||||
+ return -1;
|
||||
+
|
||||
+ wrb = wrb_from_mbox(adapter);
|
||||
+ if (!wrb) {
|
||||
+ status = -EBUSY;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ req = cmd.va;
|
||||
+
|
||||
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
|
||||
+ OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
|
||||
+ payload_len, wrb, &cmd);
|
||||
+
|
||||
+ req->hdr.version = 1;
|
||||
+ req->query_options = BE_GET_WOL_CAP;
|
||||
+
|
||||
+ status = be_mbox_notify_wait(adapter);
|
||||
+ if (!status) {
|
||||
+ struct be_cmd_resp_acpi_wol_magic_config_v1 *resp;
|
||||
+ resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *) cmd.va;
|
||||
+
|
||||
+ /* the command could succeed misleadingly on old f/w
|
||||
+ * which is not aware of the V1 version. fake an error. */
|
||||
+ if (resp->hdr.response_length < payload_len) {
|
||||
+ status = -1;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ adapter->wol_cap = resp->wol_settings;
|
||||
+ }
|
||||
+err:
|
||||
+ mutex_unlock(&adapter->mbox_lock);
|
||||
+ pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
|
||||
+ return status;
|
||||
+}
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
index 687c420..345d49e 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
@@ -1206,6 +1206,33 @@ struct be_cmd_req_acpi_wol_magic_config{
|
||||
u8 rsvd2[2];
|
||||
} __packed;
|
||||
|
||||
+struct be_cmd_req_acpi_wol_magic_config_v1 {
|
||||
+ struct be_cmd_req_hdr hdr;
|
||||
+ u8 rsvd0[2];
|
||||
+ u8 query_options;
|
||||
+ u8 rsvd1[5];
|
||||
+ u32 rsvd2[288];
|
||||
+ u8 magic_mac[6];
|
||||
+ u8 rsvd3[22];
|
||||
+} __packed;
|
||||
+
|
||||
+struct be_cmd_resp_acpi_wol_magic_config_v1 {
|
||||
+ struct be_cmd_resp_hdr hdr;
|
||||
+ u8 rsvd0[2];
|
||||
+ u8 wol_settings;
|
||||
+ u8 rsvd1[5];
|
||||
+ u32 rsvd2[295];
|
||||
+} __packed;
|
||||
+
|
||||
+#define BE_GET_WOL_CAP 2
|
||||
+
|
||||
+#define BE_WOL_CAP 0x1
|
||||
+#define BE_PME_D0_CAP 0x8
|
||||
+#define BE_PME_D1_CAP 0x10
|
||||
+#define BE_PME_D2_CAP 0x20
|
||||
+#define BE_PME_D3HOT_CAP 0x40
|
||||
+#define BE_PME_D3COLD_CAP 0x80
|
||||
+
|
||||
/********************** LoopBack test *********************/
|
||||
struct be_cmd_req_loopback_test {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
@@ -1590,4 +1617,5 @@ extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain,
|
||||
bool *pmac_id_active, u32 *pmac_id, u8 *mac);
|
||||
extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
|
||||
u8 mac_count, u32 domain);
|
||||
+extern int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter);
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
index d98ad7e..e0eb995 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
@@ -600,26 +600,16 @@ be_set_phys_id(struct net_device *netdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static bool
|
||||
-be_is_wol_supported(struct be_adapter *adapter)
|
||||
-{
|
||||
- if (!be_physfn(adapter))
|
||||
- return false;
|
||||
- else
|
||||
- return true;
|
||||
-}
|
||||
|
||||
static void
|
||||
be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
- if (be_is_wol_supported(adapter))
|
||||
- wol->supported = WAKE_MAGIC;
|
||||
-
|
||||
- if (adapter->wol)
|
||||
- wol->wolopts = WAKE_MAGIC;
|
||||
- else
|
||||
+ if (be_is_wol_supported(adapter)) {
|
||||
+ wol->supported |= WAKE_MAGIC;
|
||||
+ wol->wolopts |= WAKE_MAGIC;
|
||||
+ } else
|
||||
wol->wolopts = 0;
|
||||
memset(&wol->sopass, 0, sizeof(wol->sopass));
|
||||
}
|
||||
@@ -630,9 +620,14 @@ be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
if (wol->wolopts & ~WAKE_MAGIC)
|
||||
- return -EINVAL;
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (!be_is_wol_supported(adapter)) {
|
||||
+ dev_warn(&adapter->pdev->dev, "WOL not supported\n");
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
|
||||
- if ((wol->wolopts & WAKE_MAGIC) && be_is_wol_supported(adapter))
|
||||
+ if (wol->wolopts & WAKE_MAGIC)
|
||||
adapter->wol = true;
|
||||
else
|
||||
adapter->wol = false;
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index c1b9cdf..70b138f 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -3236,6 +3236,12 @@ static void __devexit be_remove(struct pci_dev *pdev)
|
||||
free_netdev(adapter->netdev);
|
||||
}
|
||||
|
||||
+bool be_is_wol_supported(struct be_adapter *adapter)
|
||||
+{
|
||||
+ return ((adapter->wol_cap & BE_WOL_CAP) &&
|
||||
+ !be_is_wol_excluded(adapter)) ? true : false;
|
||||
+}
|
||||
+
|
||||
static int be_get_config(struct be_adapter *adapter)
|
||||
{
|
||||
int status;
|
||||
@@ -3254,6 +3260,17 @@ static int be_get_config(struct be_adapter *adapter)
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
+ status = be_cmd_get_acpi_wol_cap(adapter);
|
||||
+ if (status) {
|
||||
+ /* in case of a failure to get wol capabillities
|
||||
+ * check the exclusion list to determine WOL capability */
|
||||
+ if (!be_is_wol_excluded(adapter))
|
||||
+ adapter->wol_cap |= BE_WOL_CAP;
|
||||
+ }
|
||||
+
|
||||
+ if (be_is_wol_supported(adapter))
|
||||
+ adapter->wol = true;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,177 +0,0 @@
|
|||
From: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Date: Sun, 18 Mar 2012 06:23:21 +0000
|
||||
Subject: [PATCH 40/58] be2net: Program secondary UC MAC address into MAC
|
||||
filter
|
||||
|
||||
commit fbc13f018c0043146f8eccc7d6a6c0e66339e2d5 upstream.
|
||||
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 6 ++-
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 53 ++++++++++++++++++++++++---
|
||||
2 files changed, 53 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index cabe1b8..03fc3db 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -309,6 +309,8 @@ struct be_vf_cfg {
|
||||
|
||||
#define BE_FLAGS_LINK_STATUS_INIT 1
|
||||
#define BE_FLAGS_WORKER_SCHEDULED (1 << 3)
|
||||
+#define BE_UC_PMAC_COUNT 30
|
||||
+#define BE_VF_UC_PMAC_COUNT 2
|
||||
|
||||
struct be_adapter {
|
||||
struct pci_dev *pdev;
|
||||
@@ -361,7 +363,7 @@ struct be_adapter {
|
||||
/* Ethtool knobs and info */
|
||||
char fw_ver[FW_VER_LEN];
|
||||
int if_handle; /* Used to configure filtering */
|
||||
- u32 pmac_id; /* MAC addr handle used by BE card */
|
||||
+ u32 *pmac_id; /* MAC addr handle used by BE card */
|
||||
u32 beacon_state; /* for set_phys_id */
|
||||
|
||||
bool eeh_err;
|
||||
@@ -391,6 +393,8 @@ struct be_adapter {
|
||||
u16 pvid;
|
||||
u8 wol_cap;
|
||||
bool wol;
|
||||
+ u32 max_pmac_cnt; /* Max secondary UC MACs programmable */
|
||||
+ u32 uc_macs; /* Count of secondary UC MAC programmed */
|
||||
};
|
||||
|
||||
#define be_physfn(adapter) (!adapter->is_virtfn)
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 70b138f..b8b34f5 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -235,7 +235,7 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
|
||||
struct sockaddr *addr = p;
|
||||
int status = 0;
|
||||
u8 current_mac[ETH_ALEN];
|
||||
- u32 pmac_id = adapter->pmac_id;
|
||||
+ u32 pmac_id = adapter->pmac_id[0];
|
||||
|
||||
if (!is_valid_ether_addr(addr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
@@ -248,7 +248,7 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
|
||||
|
||||
if (memcmp(addr->sa_data, current_mac, ETH_ALEN)) {
|
||||
status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
|
||||
- adapter->if_handle, &adapter->pmac_id, 0);
|
||||
+ adapter->if_handle, &adapter->pmac_id[0], 0);
|
||||
if (status)
|
||||
goto err;
|
||||
|
||||
@@ -877,6 +877,29 @@ static void be_set_rx_mode(struct net_device *netdev)
|
||||
goto done;
|
||||
}
|
||||
|
||||
+ if (netdev_uc_count(netdev) != adapter->uc_macs) {
|
||||
+ struct netdev_hw_addr *ha;
|
||||
+ int i = 1; /* First slot is claimed by the Primary MAC */
|
||||
+
|
||||
+ for (; adapter->uc_macs > 0; adapter->uc_macs--, i++) {
|
||||
+ be_cmd_pmac_del(adapter, adapter->if_handle,
|
||||
+ adapter->pmac_id[i], 0);
|
||||
+ }
|
||||
+
|
||||
+ if (netdev_uc_count(netdev) > adapter->max_pmac_cnt) {
|
||||
+ be_cmd_rx_filter(adapter, IFF_PROMISC, ON);
|
||||
+ adapter->promiscuous = true;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ netdev_for_each_uc_addr(ha, adapter->netdev) {
|
||||
+ adapter->uc_macs++; /* First slot is for Primary MAC */
|
||||
+ be_cmd_pmac_add(adapter, (u8 *)ha->addr,
|
||||
+ adapter->if_handle,
|
||||
+ &adapter->pmac_id[adapter->uc_macs], 0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
be_cmd_rx_filter(adapter, IFF_MULTICAST, ON);
|
||||
done:
|
||||
return;
|
||||
@@ -2450,6 +2473,8 @@ static void be_vf_clear(struct be_adapter *adapter)
|
||||
|
||||
static int be_clear(struct be_adapter *adapter)
|
||||
{
|
||||
+ int i = 1;
|
||||
+
|
||||
if (adapter->flags & BE_FLAGS_WORKER_SCHEDULED) {
|
||||
cancel_delayed_work_sync(&adapter->work);
|
||||
adapter->flags &= ~BE_FLAGS_WORKER_SCHEDULED;
|
||||
@@ -2458,6 +2483,10 @@ static int be_clear(struct be_adapter *adapter)
|
||||
if (sriov_enabled(adapter))
|
||||
be_vf_clear(adapter);
|
||||
|
||||
+ for (; adapter->uc_macs > 0; adapter->uc_macs--, i++)
|
||||
+ be_cmd_pmac_del(adapter, adapter->if_handle,
|
||||
+ adapter->pmac_id[i], 0);
|
||||
+
|
||||
be_cmd_if_destroy(adapter, adapter->if_handle, 0);
|
||||
|
||||
be_mcc_queues_destroy(adapter);
|
||||
@@ -2469,6 +2498,7 @@ static int be_clear(struct be_adapter *adapter)
|
||||
be_cmd_fw_clean(adapter);
|
||||
|
||||
be_msix_disable(adapter);
|
||||
+ kfree(adapter->pmac_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2544,10 +2574,10 @@ static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac)
|
||||
false, adapter->if_handle, pmac_id);
|
||||
|
||||
if (!status)
|
||||
- adapter->pmac_id = pmac_id;
|
||||
+ adapter->pmac_id[0] = pmac_id;
|
||||
} else {
|
||||
status = be_cmd_pmac_add(adapter, mac,
|
||||
- adapter->if_handle, &adapter->pmac_id, 0);
|
||||
+ adapter->if_handle, &adapter->pmac_id[0], 0);
|
||||
}
|
||||
do_none:
|
||||
return status;
|
||||
@@ -2602,7 +2632,7 @@ static int be_setup(struct be_adapter *adapter)
|
||||
}
|
||||
status = be_cmd_if_create(adapter, cap_flags, en_flags,
|
||||
netdev->dev_addr, &adapter->if_handle,
|
||||
- &adapter->pmac_id, 0);
|
||||
+ &adapter->pmac_id[0], 0);
|
||||
if (status != 0)
|
||||
goto err;
|
||||
|
||||
@@ -3051,6 +3081,8 @@ static void be_netdev_init(struct net_device *netdev)
|
||||
netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
|
||||
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
|
||||
|
||||
+ netdev->priv_flags |= IFF_UNICAST_FLT;
|
||||
+
|
||||
netdev->flags |= IFF_MULTICAST;
|
||||
|
||||
netif_set_gso_max_size(netdev, 65535);
|
||||
@@ -3256,6 +3288,17 @@ static int be_get_config(struct be_adapter *adapter)
|
||||
else
|
||||
adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
|
||||
|
||||
+ if (be_physfn(adapter))
|
||||
+ adapter->max_pmac_cnt = BE_UC_PMAC_COUNT;
|
||||
+ else
|
||||
+ adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT;
|
||||
+
|
||||
+ /* primary mac needs 1 pmac entry */
|
||||
+ adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1,
|
||||
+ sizeof(u32), GFP_KERNEL);
|
||||
+ if (!adapter->pmac_id)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
status = be_cmd_get_cntl_attributes(adapter);
|
||||
if (status)
|
||||
return status;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
From: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Date: Sun, 18 Mar 2012 06:23:31 +0000
|
||||
Subject: [PATCH 41/58] be2net: Fix number of vlan slots in flex mode
|
||||
|
||||
commit 456d9c962bb5824423fa93277c8f7f5b2e3d5e1c upstream.
|
||||
|
||||
In flex10 mode the number of vlan slots supported is halved.
|
||||
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index b8b34f5..c9a9bf0 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -3284,7 +3284,7 @@ static int be_get_config(struct be_adapter *adapter)
|
||||
return status;
|
||||
|
||||
if (adapter->function_mode & FLEX10_MODE)
|
||||
- adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/4;
|
||||
+ adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
|
||||
else
|
||||
adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,255 +0,0 @@
|
|||
From: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Date: Sun, 18 Mar 2012 06:23:41 +0000
|
||||
Subject: [PATCH 42/58] be2net: fix programming of VLAN tags for VF
|
||||
|
||||
commit f1f3ee1bcc996e21f122442fd8c34de51622c76a upstream.
|
||||
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 1 +
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 83 +++++++++++++++++++++++++++
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.h | 55 ++++++++++++++++++
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 23 ++++++--
|
||||
4 files changed, 157 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index 03fc3db..9576ac0 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -303,6 +303,7 @@ struct be_vf_cfg {
|
||||
unsigned char mac_addr[ETH_ALEN];
|
||||
int if_handle;
|
||||
int pmac_id;
|
||||
+ u16 def_vid;
|
||||
u16 vlan_tag;
|
||||
u32 tx_rate;
|
||||
};
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index d72c2b4..67b030d 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -2419,6 +2419,89 @@ err:
|
||||
return status;
|
||||
}
|
||||
|
||||
+int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
|
||||
+ u32 domain, u16 intf_id)
|
||||
+{
|
||||
+ struct be_mcc_wrb *wrb;
|
||||
+ struct be_cmd_req_set_hsw_config *req;
|
||||
+ void *ctxt;
|
||||
+ int status;
|
||||
+
|
||||
+ spin_lock_bh(&adapter->mcc_lock);
|
||||
+
|
||||
+ wrb = wrb_from_mccq(adapter);
|
||||
+ if (!wrb) {
|
||||
+ status = -EBUSY;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ req = embedded_payload(wrb);
|
||||
+ ctxt = &req->context;
|
||||
+
|
||||
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
+ OPCODE_COMMON_SET_HSW_CONFIG, sizeof(*req), wrb, NULL);
|
||||
+
|
||||
+ req->hdr.domain = domain;
|
||||
+ AMAP_SET_BITS(struct amap_set_hsw_context, interface_id, ctxt, intf_id);
|
||||
+ if (pvid) {
|
||||
+ AMAP_SET_BITS(struct amap_set_hsw_context, pvid_valid, ctxt, 1);
|
||||
+ AMAP_SET_BITS(struct amap_set_hsw_context, pvid, ctxt, pvid);
|
||||
+ }
|
||||
+
|
||||
+ be_dws_cpu_to_le(req->context, sizeof(req->context));
|
||||
+ status = be_mcc_notify_wait(adapter);
|
||||
+
|
||||
+err:
|
||||
+ spin_unlock_bh(&adapter->mcc_lock);
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+/* Get Hyper switch config */
|
||||
+int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
|
||||
+ u32 domain, u16 intf_id)
|
||||
+{
|
||||
+ struct be_mcc_wrb *wrb;
|
||||
+ struct be_cmd_req_get_hsw_config *req;
|
||||
+ void *ctxt;
|
||||
+ int status;
|
||||
+ u16 vid;
|
||||
+
|
||||
+ spin_lock_bh(&adapter->mcc_lock);
|
||||
+
|
||||
+ wrb = wrb_from_mccq(adapter);
|
||||
+ if (!wrb) {
|
||||
+ status = -EBUSY;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ req = embedded_payload(wrb);
|
||||
+ ctxt = &req->context;
|
||||
+
|
||||
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
+ OPCODE_COMMON_GET_HSW_CONFIG, sizeof(*req), wrb, NULL);
|
||||
+
|
||||
+ req->hdr.domain = domain;
|
||||
+ AMAP_SET_BITS(struct amap_get_hsw_req_context, interface_id, ctxt,
|
||||
+ intf_id);
|
||||
+ AMAP_SET_BITS(struct amap_get_hsw_req_context, pvid_valid, ctxt, 1);
|
||||
+ be_dws_cpu_to_le(req->context, sizeof(req->context));
|
||||
+
|
||||
+ status = be_mcc_notify_wait(adapter);
|
||||
+ if (!status) {
|
||||
+ struct be_cmd_resp_get_hsw_config *resp =
|
||||
+ embedded_payload(wrb);
|
||||
+ be_dws_le_to_cpu(&resp->context,
|
||||
+ sizeof(resp->context));
|
||||
+ vid = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
|
||||
+ pvid, &resp->context);
|
||||
+ *pvid = le16_to_cpu(vid);
|
||||
+ }
|
||||
+
|
||||
+err:
|
||||
+ spin_unlock_bh(&adapter->mcc_lock);
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
|
||||
{
|
||||
struct be_mcc_wrb *wrb;
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
index 345d49e..d5b680c 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
@@ -191,6 +191,8 @@ struct be_mcc_mailbox {
|
||||
#define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121
|
||||
#define OPCODE_COMMON_GET_MAC_LIST 147
|
||||
#define OPCODE_COMMON_SET_MAC_LIST 148
|
||||
+#define OPCODE_COMMON_GET_HSW_CONFIG 152
|
||||
+#define OPCODE_COMMON_SET_HSW_CONFIG 153
|
||||
#define OPCODE_COMMON_READ_OBJECT 171
|
||||
#define OPCODE_COMMON_WRITE_OBJECT 172
|
||||
|
||||
@@ -1413,6 +1415,55 @@ struct be_cmd_req_set_mac_list {
|
||||
struct macaddr mac[BE_MAX_MAC];
|
||||
} __packed;
|
||||
|
||||
+/*********************** HSW Config ***********************/
|
||||
+struct amap_set_hsw_context {
|
||||
+ u8 interface_id[16];
|
||||
+ u8 rsvd0[14];
|
||||
+ u8 pvid_valid;
|
||||
+ u8 rsvd1;
|
||||
+ u8 rsvd2[16];
|
||||
+ u8 pvid[16];
|
||||
+ u8 rsvd3[32];
|
||||
+ u8 rsvd4[32];
|
||||
+ u8 rsvd5[32];
|
||||
+} __packed;
|
||||
+
|
||||
+struct be_cmd_req_set_hsw_config {
|
||||
+ struct be_cmd_req_hdr hdr;
|
||||
+ u8 context[sizeof(struct amap_set_hsw_context) / 8];
|
||||
+} __packed;
|
||||
+
|
||||
+struct be_cmd_resp_set_hsw_config {
|
||||
+ struct be_cmd_resp_hdr hdr;
|
||||
+ u32 rsvd;
|
||||
+};
|
||||
+
|
||||
+struct amap_get_hsw_req_context {
|
||||
+ u8 interface_id[16];
|
||||
+ u8 rsvd0[14];
|
||||
+ u8 pvid_valid;
|
||||
+ u8 pport;
|
||||
+} __packed;
|
||||
+
|
||||
+struct amap_get_hsw_resp_context {
|
||||
+ u8 rsvd1[16];
|
||||
+ u8 pvid[16];
|
||||
+ u8 rsvd2[32];
|
||||
+ u8 rsvd3[32];
|
||||
+ u8 rsvd4[32];
|
||||
+} __packed;
|
||||
+
|
||||
+struct be_cmd_req_get_hsw_config {
|
||||
+ struct be_cmd_req_hdr hdr;
|
||||
+ u8 context[sizeof(struct amap_get_hsw_req_context) / 8];
|
||||
+} __packed;
|
||||
+
|
||||
+struct be_cmd_resp_get_hsw_config {
|
||||
+ struct be_cmd_resp_hdr hdr;
|
||||
+ u8 context[sizeof(struct amap_get_hsw_resp_context) / 8];
|
||||
+ u32 rsvd;
|
||||
+};
|
||||
+
|
||||
/*************** HW Stats Get v1 **********************************/
|
||||
#define BE_TXP_SW_SZ 48
|
||||
struct be_port_rxf_stats_v1 {
|
||||
@@ -1617,5 +1668,9 @@ extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain,
|
||||
bool *pmac_id_active, u32 *pmac_id, u8 *mac);
|
||||
extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
|
||||
u8 mac_count, u32 domain);
|
||||
+extern int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
|
||||
+ u32 domain, u16 intf_id);
|
||||
+extern int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
|
||||
+ u32 domain, u16 intf_id);
|
||||
extern int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter);
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index c9a9bf0..2e54335 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -970,14 +970,21 @@ static int be_set_vf_vlan(struct net_device *netdev,
|
||||
return -EINVAL;
|
||||
|
||||
if (vlan) {
|
||||
- adapter->vf_cfg[vf].vlan_tag = vlan;
|
||||
- adapter->vlans_added++;
|
||||
+ if (adapter->vf_cfg[vf].vlan_tag != vlan) {
|
||||
+ /* If this is new value, program it. Else skip. */
|
||||
+ adapter->vf_cfg[vf].vlan_tag = vlan;
|
||||
+
|
||||
+ status = be_cmd_set_hsw_config(adapter, vlan,
|
||||
+ vf + 1, adapter->vf_cfg[vf].if_handle);
|
||||
+ }
|
||||
} else {
|
||||
+ /* Reset Transparent Vlan Tagging. */
|
||||
adapter->vf_cfg[vf].vlan_tag = 0;
|
||||
- adapter->vlans_added--;
|
||||
+ vlan = adapter->vf_cfg[vf].def_vid;
|
||||
+ status = be_cmd_set_hsw_config(adapter, vlan, vf + 1,
|
||||
+ adapter->vf_cfg[vf].if_handle);
|
||||
}
|
||||
|
||||
- status = be_vid_config(adapter, true, vf);
|
||||
|
||||
if (status)
|
||||
dev_info(&adapter->pdev->dev,
|
||||
@@ -2517,7 +2524,7 @@ static int be_vf_setup(struct be_adapter *adapter)
|
||||
{
|
||||
struct be_vf_cfg *vf_cfg;
|
||||
u32 cap_flags, en_flags, vf;
|
||||
- u16 lnk_speed;
|
||||
+ u16 def_vlan, lnk_speed;
|
||||
int status;
|
||||
|
||||
be_vf_setup_init(adapter);
|
||||
@@ -2541,6 +2548,12 @@ static int be_vf_setup(struct be_adapter *adapter)
|
||||
if (status)
|
||||
goto err;
|
||||
vf_cfg->tx_rate = lnk_speed * 10;
|
||||
+
|
||||
+ status = be_cmd_get_hsw_config(adapter, &def_vlan,
|
||||
+ vf + 1, vf_cfg->if_handle);
|
||||
+ if (status)
|
||||
+ goto err;
|
||||
+ vf_cfg->def_vid = def_vlan;
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,521 +0,0 @@
|
|||
From: Ajit Khaparde <ajitkhaparde@gmail.com>
|
||||
Date: Sat, 21 Apr 2012 18:53:22 +0000
|
||||
Subject: [PATCH 43/58] be2net: fix ethtool get settings
|
||||
|
||||
commit 42f11cf20cc5b76766fd1f0e591eda26283a38ec upstream.
|
||||
|
||||
ethtool get settings was not displaying all the settings correctly.
|
||||
use the get_phy_info to get more information about the PHY to fix this.
|
||||
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 23 ++-
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 17 +-
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.h | 36 +++-
|
||||
drivers/net/ethernet/emulex/benet/be_ethtool.c | 245 ++++++++++++++++--------
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 20 +-
|
||||
5 files changed, 239 insertions(+), 102 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index 9576ac0..ad69cf8 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -313,6 +313,23 @@ struct be_vf_cfg {
|
||||
#define BE_UC_PMAC_COUNT 30
|
||||
#define BE_VF_UC_PMAC_COUNT 2
|
||||
|
||||
+struct phy_info {
|
||||
+ u8 transceiver;
|
||||
+ u8 autoneg;
|
||||
+ u8 fc_autoneg;
|
||||
+ u8 port_type;
|
||||
+ u16 phy_type;
|
||||
+ u16 interface_type;
|
||||
+ u32 misc_params;
|
||||
+ u16 auto_speeds_supported;
|
||||
+ u16 fixed_speeds_supported;
|
||||
+ int link_speed;
|
||||
+ int forced_port_speed;
|
||||
+ u32 dac_cable_len;
|
||||
+ u32 advertising;
|
||||
+ u32 supported;
|
||||
+};
|
||||
+
|
||||
struct be_adapter {
|
||||
struct pci_dev *pdev;
|
||||
struct net_device *netdev;
|
||||
@@ -377,10 +394,6 @@ struct be_adapter {
|
||||
u32 rx_fc; /* Rx flow control */
|
||||
u32 tx_fc; /* Tx flow control */
|
||||
bool stats_cmd_sent;
|
||||
- int link_speed;
|
||||
- u8 port_type;
|
||||
- u8 transceiver;
|
||||
- u8 autoneg;
|
||||
u8 generation; /* BladeEngine ASIC generation */
|
||||
u32 flash_status;
|
||||
struct completion flash_compl;
|
||||
@@ -392,6 +405,7 @@ struct be_adapter {
|
||||
u32 sli_family;
|
||||
u8 hba_port_num;
|
||||
u16 pvid;
|
||||
+ struct phy_info phy;
|
||||
u8 wol_cap;
|
||||
bool wol;
|
||||
u32 max_pmac_cnt; /* Max secondary UC MACs programmable */
|
||||
@@ -583,4 +597,5 @@ extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
|
||||
extern void be_parse_stats(struct be_adapter *adapter);
|
||||
extern int be_load_fw(struct be_adapter *adapter, u8 *func);
|
||||
extern bool be_is_wol_supported(struct be_adapter *adapter);
|
||||
+extern bool be_pause_supported(struct be_adapter *adapter);
|
||||
#endif /* BE_H */
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 67b030d..22be08c 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -126,7 +126,7 @@ static void be_async_link_state_process(struct be_adapter *adapter,
|
||||
struct be_async_event_link_state *evt)
|
||||
{
|
||||
/* When link status changes, link speed must be re-queried from FW */
|
||||
- adapter->link_speed = -1;
|
||||
+ adapter->phy.link_speed = -1;
|
||||
|
||||
/* For the initial link status do not rely on the ASYNC event as
|
||||
* it may not be received in some cases.
|
||||
@@ -153,7 +153,7 @@ static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
|
||||
{
|
||||
if (evt->physical_port == adapter->port_num) {
|
||||
/* qos_link_speed is in units of 10 Mbps */
|
||||
- adapter->link_speed = evt->qos_link_speed * 10;
|
||||
+ adapter->phy.link_speed = evt->qos_link_speed * 10;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2136,8 +2136,7 @@ err:
|
||||
return status;
|
||||
}
|
||||
|
||||
-int be_cmd_get_phy_info(struct be_adapter *adapter,
|
||||
- struct be_phy_info *phy_info)
|
||||
+int be_cmd_get_phy_info(struct be_adapter *adapter)
|
||||
{
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_cmd_req_get_phy_info *req;
|
||||
@@ -2170,9 +2169,15 @@ int be_cmd_get_phy_info(struct be_adapter *adapter,
|
||||
if (!status) {
|
||||
struct be_phy_info *resp_phy_info =
|
||||
cmd.va + sizeof(struct be_cmd_req_hdr);
|
||||
- phy_info->phy_type = le16_to_cpu(resp_phy_info->phy_type);
|
||||
- phy_info->interface_type =
|
||||
+ adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type);
|
||||
+ adapter->phy.interface_type =
|
||||
le16_to_cpu(resp_phy_info->interface_type);
|
||||
+ adapter->phy.auto_speeds_supported =
|
||||
+ le16_to_cpu(resp_phy_info->auto_speeds_supported);
|
||||
+ adapter->phy.fixed_speeds_supported =
|
||||
+ le16_to_cpu(resp_phy_info->fixed_speeds_supported);
|
||||
+ adapter->phy.misc_params =
|
||||
+ le32_to_cpu(resp_phy_info->misc_params);
|
||||
}
|
||||
pci_free_consistent(adapter->pdev, cmd.size,
|
||||
cmd.va, cmd.dma);
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
index d5b680c..3c54361 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
@@ -1309,9 +1309,36 @@ enum {
|
||||
PHY_TYPE_KX4_10GB,
|
||||
PHY_TYPE_BASET_10GB,
|
||||
PHY_TYPE_BASET_1GB,
|
||||
+ PHY_TYPE_BASEX_1GB,
|
||||
+ PHY_TYPE_SGMII,
|
||||
PHY_TYPE_DISABLED = 255
|
||||
};
|
||||
|
||||
+#define BE_SUPPORTED_SPEED_NONE 0
|
||||
+#define BE_SUPPORTED_SPEED_10MBPS 1
|
||||
+#define BE_SUPPORTED_SPEED_100MBPS 2
|
||||
+#define BE_SUPPORTED_SPEED_1GBPS 4
|
||||
+#define BE_SUPPORTED_SPEED_10GBPS 8
|
||||
+
|
||||
+#define BE_AN_EN 0x2
|
||||
+#define BE_PAUSE_SYM_EN 0x80
|
||||
+
|
||||
+/* MAC speed valid values */
|
||||
+#define SPEED_DEFAULT 0x0
|
||||
+#define SPEED_FORCED_10GB 0x1
|
||||
+#define SPEED_FORCED_1GB 0x2
|
||||
+#define SPEED_AUTONEG_10GB 0x3
|
||||
+#define SPEED_AUTONEG_1GB 0x4
|
||||
+#define SPEED_AUTONEG_100MB 0x5
|
||||
+#define SPEED_AUTONEG_10GB_1GB 0x6
|
||||
+#define SPEED_AUTONEG_10GB_1GB_100MB 0x7
|
||||
+#define SPEED_AUTONEG_1GB_100MB 0x8
|
||||
+#define SPEED_AUTONEG_10MB 0x9
|
||||
+#define SPEED_AUTONEG_1GB_100MB_10MB 0xa
|
||||
+#define SPEED_AUTONEG_100MB_10MB 0xb
|
||||
+#define SPEED_FORCED_100MB 0xc
|
||||
+#define SPEED_FORCED_10MB 0xd
|
||||
+
|
||||
struct be_cmd_req_get_phy_info {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u8 rsvd0[24];
|
||||
@@ -1321,7 +1348,11 @@ struct be_phy_info {
|
||||
u16 phy_type;
|
||||
u16 interface_type;
|
||||
u32 misc_params;
|
||||
- u32 future_use[4];
|
||||
+ u16 ext_phy_details;
|
||||
+ u16 rsvd;
|
||||
+ u16 auto_speeds_supported;
|
||||
+ u16 fixed_speeds_supported;
|
||||
+ u32 future_use[2];
|
||||
};
|
||||
|
||||
struct be_cmd_resp_get_phy_info {
|
||||
@@ -1655,8 +1686,7 @@ extern int be_cmd_get_seeprom_data(struct be_adapter *adapter,
|
||||
struct be_dma_mem *nonemb_cmd);
|
||||
extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
|
||||
u8 loopback_type, u8 enable);
|
||||
-extern int be_cmd_get_phy_info(struct be_adapter *adapter,
|
||||
- struct be_phy_info *phy_info);
|
||||
+extern int be_cmd_get_phy_info(struct be_adapter *adapter);
|
||||
extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);
|
||||
extern void be_detect_dump_ue(struct be_adapter *adapter);
|
||||
extern int be_cmd_get_die_temperature(struct be_adapter *adapter);
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
index e0eb995..076adeb 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
@@ -433,102 +433,193 @@ static int be_get_sset_count(struct net_device *netdev, int stringset)
|
||||
}
|
||||
}
|
||||
|
||||
+static u32 be_get_port_type(u32 phy_type, u32 dac_cable_len)
|
||||
+{
|
||||
+ u32 port;
|
||||
+
|
||||
+ switch (phy_type) {
|
||||
+ case PHY_TYPE_BASET_1GB:
|
||||
+ case PHY_TYPE_BASEX_1GB:
|
||||
+ case PHY_TYPE_SGMII:
|
||||
+ port = PORT_TP;
|
||||
+ break;
|
||||
+ case PHY_TYPE_SFP_PLUS_10GB:
|
||||
+ port = dac_cable_len ? PORT_DA : PORT_FIBRE;
|
||||
+ break;
|
||||
+ case PHY_TYPE_XFP_10GB:
|
||||
+ case PHY_TYPE_SFP_1GB:
|
||||
+ port = PORT_FIBRE;
|
||||
+ break;
|
||||
+ case PHY_TYPE_BASET_10GB:
|
||||
+ port = PORT_TP;
|
||||
+ break;
|
||||
+ default:
|
||||
+ port = PORT_OTHER;
|
||||
+ }
|
||||
+
|
||||
+ return port;
|
||||
+}
|
||||
+
|
||||
+static u32 convert_to_et_setting(u32 if_type, u32 if_speeds)
|
||||
+{
|
||||
+ u32 val = 0;
|
||||
+
|
||||
+ switch (if_type) {
|
||||
+ case PHY_TYPE_BASET_1GB:
|
||||
+ case PHY_TYPE_BASEX_1GB:
|
||||
+ case PHY_TYPE_SGMII:
|
||||
+ val |= SUPPORTED_TP;
|
||||
+ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)
|
||||
+ val |= SUPPORTED_1000baseT_Full;
|
||||
+ if (if_speeds & BE_SUPPORTED_SPEED_100MBPS)
|
||||
+ val |= SUPPORTED_100baseT_Full;
|
||||
+ if (if_speeds & BE_SUPPORTED_SPEED_10MBPS)
|
||||
+ val |= SUPPORTED_10baseT_Full;
|
||||
+ break;
|
||||
+ case PHY_TYPE_KX4_10GB:
|
||||
+ val |= SUPPORTED_Backplane;
|
||||
+ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)
|
||||
+ val |= SUPPORTED_1000baseKX_Full;
|
||||
+ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)
|
||||
+ val |= SUPPORTED_10000baseKX4_Full;
|
||||
+ break;
|
||||
+ case PHY_TYPE_KR_10GB:
|
||||
+ val |= SUPPORTED_Backplane |
|
||||
+ SUPPORTED_10000baseKR_Full;
|
||||
+ break;
|
||||
+ case PHY_TYPE_SFP_PLUS_10GB:
|
||||
+ case PHY_TYPE_XFP_10GB:
|
||||
+ case PHY_TYPE_SFP_1GB:
|
||||
+ val |= SUPPORTED_FIBRE;
|
||||
+ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)
|
||||
+ val |= SUPPORTED_10000baseT_Full;
|
||||
+ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)
|
||||
+ val |= SUPPORTED_1000baseT_Full;
|
||||
+ break;
|
||||
+ case PHY_TYPE_BASET_10GB:
|
||||
+ val |= SUPPORTED_TP;
|
||||
+ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)
|
||||
+ val |= SUPPORTED_10000baseT_Full;
|
||||
+ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)
|
||||
+ val |= SUPPORTED_1000baseT_Full;
|
||||
+ if (if_speeds & BE_SUPPORTED_SPEED_100MBPS)
|
||||
+ val |= SUPPORTED_100baseT_Full;
|
||||
+ break;
|
||||
+ default:
|
||||
+ val |= SUPPORTED_TP;
|
||||
+ }
|
||||
+
|
||||
+ return val;
|
||||
+}
|
||||
+
|
||||
+static int convert_to_et_speed(u32 be_speed)
|
||||
+{
|
||||
+ int et_speed = SPEED_10000;
|
||||
+
|
||||
+ switch (be_speed) {
|
||||
+ case PHY_LINK_SPEED_10MBPS:
|
||||
+ et_speed = SPEED_10;
|
||||
+ break;
|
||||
+ case PHY_LINK_SPEED_100MBPS:
|
||||
+ et_speed = SPEED_100;
|
||||
+ break;
|
||||
+ case PHY_LINK_SPEED_1GBPS:
|
||||
+ et_speed = SPEED_1000;
|
||||
+ break;
|
||||
+ case PHY_LINK_SPEED_10GBPS:
|
||||
+ et_speed = SPEED_10000;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return et_speed;
|
||||
+}
|
||||
+
|
||||
+bool be_pause_supported(struct be_adapter *adapter)
|
||||
+{
|
||||
+ return (adapter->phy.interface_type == PHY_TYPE_SFP_PLUS_10GB ||
|
||||
+ adapter->phy.interface_type == PHY_TYPE_XFP_10GB) ?
|
||||
+ false : true;
|
||||
+}
|
||||
+
|
||||
static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
- struct be_phy_info phy_info;
|
||||
- u8 mac_speed = 0;
|
||||
+ u8 port_speed = 0;
|
||||
u16 link_speed = 0;
|
||||
u8 link_status;
|
||||
+ u32 et_speed = 0;
|
||||
int status;
|
||||
|
||||
- if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) {
|
||||
- status = be_cmd_link_status_query(adapter, &mac_speed,
|
||||
- &link_speed, &link_status, 0);
|
||||
- if (!status)
|
||||
- be_link_status_update(adapter, link_status);
|
||||
-
|
||||
- /* link_speed is in units of 10 Mbps */
|
||||
- if (link_speed) {
|
||||
- ethtool_cmd_speed_set(ecmd, link_speed*10);
|
||||
+ if (adapter->phy.link_speed < 0 || !(netdev->flags & IFF_UP)) {
|
||||
+ if (adapter->phy.forced_port_speed < 0) {
|
||||
+ status = be_cmd_link_status_query(adapter, &port_speed,
|
||||
+ &link_speed, &link_status, 0);
|
||||
+ if (!status)
|
||||
+ be_link_status_update(adapter, link_status);
|
||||
+ if (link_speed)
|
||||
+ et_speed = link_speed;
|
||||
+ else
|
||||
+ et_speed = convert_to_et_speed(port_speed);
|
||||
} else {
|
||||
- switch (mac_speed) {
|
||||
- case PHY_LINK_SPEED_10MBPS:
|
||||
- ethtool_cmd_speed_set(ecmd, SPEED_10);
|
||||
- break;
|
||||
- case PHY_LINK_SPEED_100MBPS:
|
||||
- ethtool_cmd_speed_set(ecmd, SPEED_100);
|
||||
- break;
|
||||
- case PHY_LINK_SPEED_1GBPS:
|
||||
- ethtool_cmd_speed_set(ecmd, SPEED_1000);
|
||||
- break;
|
||||
- case PHY_LINK_SPEED_10GBPS:
|
||||
- ethtool_cmd_speed_set(ecmd, SPEED_10000);
|
||||
- break;
|
||||
- case PHY_LINK_SPEED_ZERO:
|
||||
- ethtool_cmd_speed_set(ecmd, 0);
|
||||
- break;
|
||||
- }
|
||||
+ et_speed = adapter->phy.forced_port_speed;
|
||||
}
|
||||
|
||||
- status = be_cmd_get_phy_info(adapter, &phy_info);
|
||||
- if (!status) {
|
||||
- switch (phy_info.interface_type) {
|
||||
- case PHY_TYPE_XFP_10GB:
|
||||
- case PHY_TYPE_SFP_1GB:
|
||||
- case PHY_TYPE_SFP_PLUS_10GB:
|
||||
- ecmd->port = PORT_FIBRE;
|
||||
- break;
|
||||
- default:
|
||||
- ecmd->port = PORT_TP;
|
||||
- break;
|
||||
- }
|
||||
+ ethtool_cmd_speed_set(ecmd, et_speed);
|
||||
+
|
||||
+ status = be_cmd_get_phy_info(adapter);
|
||||
+ if (status)
|
||||
+ return status;
|
||||
+
|
||||
+ ecmd->supported =
|
||||
+ convert_to_et_setting(adapter->phy.interface_type,
|
||||
+ adapter->phy.auto_speeds_supported |
|
||||
+ adapter->phy.fixed_speeds_supported);
|
||||
+ ecmd->advertising =
|
||||
+ convert_to_et_setting(adapter->phy.interface_type,
|
||||
+ adapter->phy.auto_speeds_supported);
|
||||
|
||||
- switch (phy_info.interface_type) {
|
||||
- case PHY_TYPE_KR_10GB:
|
||||
- case PHY_TYPE_KX4_10GB:
|
||||
- ecmd->autoneg = AUTONEG_ENABLE;
|
||||
+ ecmd->port = be_get_port_type(adapter->phy.interface_type,
|
||||
+ adapter->phy.dac_cable_len);
|
||||
+
|
||||
+ if (adapter->phy.auto_speeds_supported) {
|
||||
+ ecmd->supported |= SUPPORTED_Autoneg;
|
||||
+ ecmd->autoneg = AUTONEG_ENABLE;
|
||||
+ ecmd->advertising |= ADVERTISED_Autoneg;
|
||||
+ }
|
||||
+
|
||||
+ if (be_pause_supported(adapter)) {
|
||||
+ ecmd->supported |= SUPPORTED_Pause;
|
||||
+ ecmd->advertising |= ADVERTISED_Pause;
|
||||
+ }
|
||||
+
|
||||
+ switch (adapter->phy.interface_type) {
|
||||
+ case PHY_TYPE_KR_10GB:
|
||||
+ case PHY_TYPE_KX4_10GB:
|
||||
ecmd->transceiver = XCVR_INTERNAL;
|
||||
- break;
|
||||
- default:
|
||||
- ecmd->autoneg = AUTONEG_DISABLE;
|
||||
- ecmd->transceiver = XCVR_EXTERNAL;
|
||||
- break;
|
||||
- }
|
||||
+ break;
|
||||
+ default:
|
||||
+ ecmd->transceiver = XCVR_EXTERNAL;
|
||||
+ break;
|
||||
}
|
||||
|
||||
/* Save for future use */
|
||||
- adapter->link_speed = ethtool_cmd_speed(ecmd);
|
||||
- adapter->port_type = ecmd->port;
|
||||
- adapter->transceiver = ecmd->transceiver;
|
||||
- adapter->autoneg = ecmd->autoneg;
|
||||
+ adapter->phy.link_speed = ethtool_cmd_speed(ecmd);
|
||||
+ adapter->phy.port_type = ecmd->port;
|
||||
+ adapter->phy.transceiver = ecmd->transceiver;
|
||||
+ adapter->phy.autoneg = ecmd->autoneg;
|
||||
+ adapter->phy.advertising = ecmd->advertising;
|
||||
+ adapter->phy.supported = ecmd->supported;
|
||||
} else {
|
||||
- ethtool_cmd_speed_set(ecmd, adapter->link_speed);
|
||||
- ecmd->port = adapter->port_type;
|
||||
- ecmd->transceiver = adapter->transceiver;
|
||||
- ecmd->autoneg = adapter->autoneg;
|
||||
+ ethtool_cmd_speed_set(ecmd, adapter->phy.link_speed);
|
||||
+ ecmd->port = adapter->phy.port_type;
|
||||
+ ecmd->transceiver = adapter->phy.transceiver;
|
||||
+ ecmd->autoneg = adapter->phy.autoneg;
|
||||
+ ecmd->advertising = adapter->phy.advertising;
|
||||
+ ecmd->supported = adapter->phy.supported;
|
||||
}
|
||||
|
||||
ecmd->duplex = DUPLEX_FULL;
|
||||
ecmd->phy_address = adapter->port_num;
|
||||
- switch (ecmd->port) {
|
||||
- case PORT_FIBRE:
|
||||
- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
|
||||
- break;
|
||||
- case PORT_TP:
|
||||
- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP);
|
||||
- break;
|
||||
- case PORT_AUI:
|
||||
- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_AUI);
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if (ecmd->autoneg) {
|
||||
- ecmd->supported |= SUPPORTED_1000baseT_Full;
|
||||
- ecmd->supported |= SUPPORTED_Autoneg;
|
||||
- ecmd->advertising |= (ADVERTISED_10000baseT_Full |
|
||||
- ADVERTISED_1000baseT_Full);
|
||||
- }
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -548,7 +639,7 @@ be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
be_cmd_get_flow_control(adapter, &ecmd->tx_pause, &ecmd->rx_pause);
|
||||
- ecmd->autoneg = 0;
|
||||
+ ecmd->autoneg = adapter->phy.fc_autoneg;
|
||||
}
|
||||
|
||||
static int
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 2e54335..376a2fa 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -2563,11 +2563,12 @@ err:
|
||||
static void be_setup_init(struct be_adapter *adapter)
|
||||
{
|
||||
adapter->vlan_prio_bmap = 0xff;
|
||||
- adapter->link_speed = -1;
|
||||
+ adapter->phy.link_speed = -1;
|
||||
adapter->if_handle = -1;
|
||||
adapter->be3_native = false;
|
||||
adapter->promiscuous = false;
|
||||
adapter->eq_next_idx = 0;
|
||||
+ adapter->phy.forced_port_speed = -1;
|
||||
}
|
||||
|
||||
static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac)
|
||||
@@ -2699,6 +2700,10 @@ static int be_setup(struct be_adapter *adapter)
|
||||
goto err;
|
||||
}
|
||||
|
||||
+ be_cmd_get_phy_info(adapter);
|
||||
+ if (be_pause_supported(adapter))
|
||||
+ adapter->phy.fc_autoneg = 1;
|
||||
+
|
||||
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
|
||||
adapter->flags |= BE_FLAGS_WORKER_SCHEDULED;
|
||||
|
||||
@@ -2752,17 +2757,8 @@ static bool be_flash_redboot(struct be_adapter *adapter,
|
||||
|
||||
static bool phy_flashing_required(struct be_adapter *adapter)
|
||||
{
|
||||
- int status = 0;
|
||||
- struct be_phy_info phy_info;
|
||||
-
|
||||
- status = be_cmd_get_phy_info(adapter, &phy_info);
|
||||
- if (status)
|
||||
- return false;
|
||||
- if ((phy_info.phy_type == TN_8022) &&
|
||||
- (phy_info.interface_type == PHY_TYPE_BASET_10GB)) {
|
||||
- return true;
|
||||
- }
|
||||
- return false;
|
||||
+ return (adapter->phy.phy_type == TN_8022 &&
|
||||
+ adapter->phy.interface_type == PHY_TYPE_BASET_10GB);
|
||||
}
|
||||
|
||||
static int be_flash_data(struct be_adapter *adapter,
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Fri, 25 May 2012 21:28:09 +0530
|
||||
Subject: [PATCH 44/58] be2net: Fix VLAN/multicast packet reception
|
||||
|
||||
commit 0fc16ebf69fc57b42110712eaaf8a6aa2492afbe upstream.
|
||||
|
||||
VLAN and multicast hardware filters are limited and can get
|
||||
exhausted in adapters with many PCI functions. If setting
|
||||
a VLAN or multicast filter fails due to lack of sufficient
|
||||
hardware resources, these packets get dropped. Fix this by
|
||||
switching to VLAN or multicast promiscous mode so that these
|
||||
packets are not dropped.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 44 ++++++++++++++++++---------
|
||||
1 file changed, 30 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -797,22 +797,30 @@
|
||||
if (adapter->promiscuous)
|
||||
return 0;
|
||||
|
||||
- if (adapter->vlans_added <= adapter->max_vlans) {
|
||||
- /* Construct VLAN Table to give to HW */
|
||||
- for (i = 0; i < VLAN_N_VID; i++) {
|
||||
- if (adapter->vlan_tag[i]) {
|
||||
- vtag[ntags] = cpu_to_le16(i);
|
||||
- ntags++;
|
||||
- }
|
||||
- }
|
||||
- status = be_cmd_vlan_config(adapter, adapter->if_handle,
|
||||
- vtag, ntags, 1, 0);
|
||||
- } else {
|
||||
- status = be_cmd_vlan_config(adapter, adapter->if_handle,
|
||||
- NULL, 0, 1, 1);
|
||||
+ if (adapter->vlans_added > adapter->max_vlans)
|
||||
+ goto set_vlan_promisc;
|
||||
+
|
||||
+ /* Construct VLAN Table to give to HW */
|
||||
+ for (i = 0; i < VLAN_N_VID; i++)
|
||||
+ if (adapter->vlan_tag[i])
|
||||
+ vtag[ntags++] = cpu_to_le16(i);
|
||||
+
|
||||
+ status = be_cmd_vlan_config(adapter, adapter->if_handle,
|
||||
+ vtag, ntags, 1, 0);
|
||||
+
|
||||
+ /* Set to VLAN promisc mode as setting VLAN filter failed */
|
||||
+ if (status) {
|
||||
+ dev_info(&adapter->pdev->dev, "Exhausted VLAN HW filters.\n");
|
||||
+ dev_info(&adapter->pdev->dev, "Disabling HW VLAN filtering.\n");
|
||||
+ goto set_vlan_promisc;
|
||||
}
|
||||
|
||||
return status;
|
||||
+
|
||||
+set_vlan_promisc:
|
||||
+ status = be_cmd_vlan_config(adapter, adapter->if_handle,
|
||||
+ NULL, 0, 1, 1);
|
||||
+ return status;
|
||||
}
|
||||
|
||||
static int be_vlan_add_vid(struct net_device *netdev, u16 vid)
|
||||
@@ -862,6 +870,7 @@
|
||||
static void be_set_rx_mode(struct net_device *netdev)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
+ int status;
|
||||
|
||||
if (netdev->flags & IFF_PROMISC) {
|
||||
be_cmd_rx_filter(adapter, IFF_PROMISC, ON);
|
||||
@@ -908,7 +917,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
- be_cmd_rx_filter(adapter, IFF_MULTICAST, ON);
|
||||
+ status = be_cmd_rx_filter(adapter, IFF_MULTICAST, ON);
|
||||
+
|
||||
+ /* Set to MCAST promisc mode if setting MULTICAST address fails */
|
||||
+ if (status) {
|
||||
+ dev_info(&adapter->pdev->dev, "Exhausted multicast HW filters.\n");
|
||||
+ dev_info(&adapter->pdev->dev, "Disabling HW multicast filtering.\n");
|
||||
+ be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON);
|
||||
+ }
|
||||
done:
|
||||
return;
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Wed, 25 Apr 2012 01:46:18 +0000
|
||||
Subject: [PATCH 45/58] be2net: Fix FW download in Lancer
|
||||
|
||||
commit 804c751599855a83efdc781cd9a2bda725d1391c upstream.
|
||||
|
||||
Increase time given by driver to adapter for completing FW download
|
||||
to 30 seconds. Also return correct status when FW download times out.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 8 +++-----
|
||||
1 file changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 22be08c..3ba4aed 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -1824,18 +1824,16 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
||||
spin_unlock_bh(&adapter->mcc_lock);
|
||||
|
||||
if (!wait_for_completion_timeout(&adapter->flash_compl,
|
||||
- msecs_to_jiffies(12000)))
|
||||
+ msecs_to_jiffies(30000)))
|
||||
status = -1;
|
||||
else
|
||||
status = adapter->flash_status;
|
||||
|
||||
resp = embedded_payload(wrb);
|
||||
- if (!status) {
|
||||
+ if (!status)
|
||||
*data_written = le32_to_cpu(resp->actual_write_len);
|
||||
- } else {
|
||||
+ else
|
||||
*addn_status = resp->additional_status;
|
||||
- status = resp->status;
|
||||
- }
|
||||
|
||||
return status;
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Wed, 25 Apr 2012 01:46:28 +0000
|
||||
Subject: [PATCH 46/58] be2net: Fix ethtool self test for Lancer
|
||||
|
||||
commit a70473949698c1c46e5523e1810a0a0f904a1fd2 upstream.
|
||||
|
||||
Lancer does not support DDR self test. Fix ethtool self test by
|
||||
skipping this test for Lancer.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_ethtool.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
index 076adeb..9d71bad 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
@@ -793,7 +793,7 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
|
||||
}
|
||||
}
|
||||
|
||||
- if (be_test_ddr_dma(adapter) != 0) {
|
||||
+ if (!lancer_chip(adapter) && be_test_ddr_dma(adapter) != 0) {
|
||||
data[3] = 1;
|
||||
test->flags |= ETH_TEST_FL_FAILED;
|
||||
}
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Wed, 25 Apr 2012 01:46:39 +0000
|
||||
Subject: [PATCH 47/58] be2net: Fix traffic stall INTx mode
|
||||
|
||||
commit af311fe31015e2b27bd65e22fc103230fb3a78b7 upstream.
|
||||
|
||||
EQ is getting armed wrongly in INTx mode as INTx interrupt is taking
|
||||
some time to deassert. This can cause another interrupt while NAPI is
|
||||
scheduled and scheduling a NAPI in interrupt does not take effect.
|
||||
This causes interrupt to be missed and traffic stalls. Fixing this by
|
||||
preventing wrong arming of EQ.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 34b8ad2..915b95e 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -1563,7 +1563,9 @@ static int event_handle(struct be_eq_obj *eqo)
|
||||
if (!num)
|
||||
rearm = true;
|
||||
|
||||
- be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num);
|
||||
+ if (num || msix_enabled(eqo->adapter))
|
||||
+ be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num);
|
||||
+
|
||||
if (num)
|
||||
napi_schedule(&eqo->napi);
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Wed, 25 Apr 2012 01:46:52 +0000
|
||||
Subject: [PATCH 48/58] be2net: Fix Lancer statistics
|
||||
|
||||
commit d51ebd331166e102591e5c25805d8015df0e1e21 upstream.
|
||||
|
||||
Fix port num sent in command to get stats. Also skip unnecessary
|
||||
parsing of stats for Lancer.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 2 +-
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 5 +++++
|
||||
2 files changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 3ba4aed..4e07e58 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -1221,7 +1221,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
|
||||
OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size, wrb,
|
||||
nonemb_cmd);
|
||||
|
||||
- req->cmd_params.params.pport_num = cpu_to_le16(adapter->port_num);
|
||||
+ req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num);
|
||||
req->cmd_params.params.reset_stats = 0;
|
||||
|
||||
be_mcc_notify(adapter);
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 915b95e..9b1c03e 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -421,6 +421,9 @@ void be_parse_stats(struct be_adapter *adapter)
|
||||
populate_be2_stats(adapter);
|
||||
}
|
||||
|
||||
+ if (lancer_chip(adapter))
|
||||
+ goto done;
|
||||
+
|
||||
/* as erx_v1 is longer than v0, ok to use v1 defn for v0 access */
|
||||
for_all_rx_queues(adapter, rxo, i) {
|
||||
/* below erx HW counter can actually wrap around after
|
||||
@@ -429,6 +432,8 @@ void be_parse_stats(struct be_adapter *adapter)
|
||||
accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags,
|
||||
(u16)erx->rx_drops_no_fragments[rxo->q.id]);
|
||||
}
|
||||
+done:
|
||||
+ return;
|
||||
}
|
||||
|
||||
static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,232 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Wed, 25 Apr 2012 01:47:03 +0000
|
||||
Subject: [PATCH 49/58] be2net: Fix wrong status getting returned for MCC
|
||||
commands
|
||||
|
||||
commit 652bf64622f32c938dd4a8738ba12d51dc9fbdd4 upstream.
|
||||
|
||||
MCC Response CQEs are processed as part of NAPI poll routine and
|
||||
also synchronously. If MCC completions are consumed by NAPI poll
|
||||
routine, wrong status is returned to synchronously waiting routine.
|
||||
Fix this by getting status of MCC command from command response
|
||||
instead of response CQEs.
|
||||
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 5 ++
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 81 ++++++++++++++++++---------
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.h | 8 ++-
|
||||
3 files changed, 67 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index ad69cf8..4bc18ef 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -162,6 +162,11 @@ static inline void queue_head_inc(struct be_queue_info *q)
|
||||
index_inc(&q->head, q->len);
|
||||
}
|
||||
|
||||
+static inline void index_dec(u16 *index, u16 limit)
|
||||
+{
|
||||
+ *index = MODULO((*index - 1), limit);
|
||||
+}
|
||||
+
|
||||
static inline void queue_tail_inc(struct be_queue_info *q)
|
||||
{
|
||||
index_inc(&q->tail, q->len);
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 4e07e58..2673081 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -61,10 +61,21 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
|
||||
compl->flags = 0;
|
||||
}
|
||||
|
||||
+static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1)
|
||||
+{
|
||||
+ unsigned long addr;
|
||||
+
|
||||
+ addr = tag1;
|
||||
+ addr = ((addr << 16) << 16) | tag0;
|
||||
+ return (void *)addr;
|
||||
+}
|
||||
+
|
||||
static int be_mcc_compl_process(struct be_adapter *adapter,
|
||||
- struct be_mcc_compl *compl)
|
||||
+ struct be_mcc_compl *compl)
|
||||
{
|
||||
u16 compl_status, extd_status;
|
||||
+ struct be_cmd_resp_hdr *resp_hdr;
|
||||
+ u8 opcode = 0, subsystem = 0;
|
||||
|
||||
/* Just swap the status to host endian; mcc tag is opaquely copied
|
||||
* from mcc_wrb */
|
||||
@@ -73,32 +84,36 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
|
||||
compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
|
||||
CQE_STATUS_COMPL_MASK;
|
||||
|
||||
- if (((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) ||
|
||||
- (compl->tag0 == OPCODE_COMMON_WRITE_OBJECT)) &&
|
||||
- (compl->tag1 == CMD_SUBSYSTEM_COMMON)) {
|
||||
+ resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
|
||||
+
|
||||
+ if (resp_hdr) {
|
||||
+ opcode = resp_hdr->opcode;
|
||||
+ subsystem = resp_hdr->subsystem;
|
||||
+ }
|
||||
+
|
||||
+ if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) ||
|
||||
+ (opcode == OPCODE_COMMON_WRITE_OBJECT)) &&
|
||||
+ (subsystem == CMD_SUBSYSTEM_COMMON)) {
|
||||
adapter->flash_status = compl_status;
|
||||
complete(&adapter->flash_compl);
|
||||
}
|
||||
|
||||
if (compl_status == MCC_STATUS_SUCCESS) {
|
||||
- if (((compl->tag0 == OPCODE_ETH_GET_STATISTICS) ||
|
||||
- (compl->tag0 == OPCODE_ETH_GET_PPORT_STATS)) &&
|
||||
- (compl->tag1 == CMD_SUBSYSTEM_ETH)) {
|
||||
+ if (((opcode == OPCODE_ETH_GET_STATISTICS) ||
|
||||
+ (opcode == OPCODE_ETH_GET_PPORT_STATS)) &&
|
||||
+ (subsystem == CMD_SUBSYSTEM_ETH)) {
|
||||
be_parse_stats(adapter);
|
||||
adapter->stats_cmd_sent = false;
|
||||
}
|
||||
- if (compl->tag0 ==
|
||||
- OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) {
|
||||
- struct be_mcc_wrb *mcc_wrb =
|
||||
- queue_index_node(&adapter->mcc_obj.q,
|
||||
- compl->tag1);
|
||||
+ if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
|
||||
+ subsystem == CMD_SUBSYSTEM_COMMON) {
|
||||
struct be_cmd_resp_get_cntl_addnl_attribs *resp =
|
||||
- embedded_payload(mcc_wrb);
|
||||
+ (void *)resp_hdr;
|
||||
adapter->drv_stats.be_on_die_temperature =
|
||||
resp->on_die_temperature;
|
||||
}
|
||||
} else {
|
||||
- if (compl->tag0 == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
|
||||
+ if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
|
||||
be_get_temp_freq = 0;
|
||||
|
||||
if (compl_status == MCC_STATUS_NOT_SUPPORTED ||
|
||||
@@ -108,13 +123,13 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
|
||||
if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
|
||||
dev_warn(&adapter->pdev->dev, "This domain(VM) is not "
|
||||
"permitted to execute this cmd (opcode %d)\n",
|
||||
- compl->tag0);
|
||||
+ opcode);
|
||||
} else {
|
||||
extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
|
||||
CQE_STATUS_EXTD_MASK;
|
||||
dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:"
|
||||
"status %d, extd-status %d\n",
|
||||
- compl->tag0, compl_status, extd_status);
|
||||
+ opcode, compl_status, extd_status);
|
||||
}
|
||||
}
|
||||
done:
|
||||
@@ -286,7 +301,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
|
||||
if (i == mcc_timeout) {
|
||||
dev_err(&adapter->pdev->dev, "FW not responding\n");
|
||||
adapter->fw_timeout = true;
|
||||
- return -1;
|
||||
+ return -EIO;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -294,8 +309,26 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
|
||||
/* Notify MCC requests and wait for completion */
|
||||
static int be_mcc_notify_wait(struct be_adapter *adapter)
|
||||
{
|
||||
+ int status;
|
||||
+ struct be_mcc_wrb *wrb;
|
||||
+ struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
|
||||
+ u16 index = mcc_obj->q.head;
|
||||
+ struct be_cmd_resp_hdr *resp;
|
||||
+
|
||||
+ index_dec(&index, mcc_obj->q.len);
|
||||
+ wrb = queue_index_node(&mcc_obj->q, index);
|
||||
+
|
||||
+ resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1);
|
||||
+
|
||||
be_mcc_notify(adapter);
|
||||
- return be_mcc_wait_compl(adapter);
|
||||
+
|
||||
+ status = be_mcc_wait_compl(adapter);
|
||||
+ if (status == -EIO)
|
||||
+ goto out;
|
||||
+
|
||||
+ status = resp->status;
|
||||
+out:
|
||||
+ return status;
|
||||
}
|
||||
|
||||
static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
|
||||
@@ -435,14 +468,17 @@ static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
|
||||
struct be_mcc_wrb *wrb, struct be_dma_mem *mem)
|
||||
{
|
||||
struct be_sge *sge;
|
||||
+ unsigned long addr = (unsigned long)req_hdr;
|
||||
+ u64 req_addr = addr;
|
||||
|
||||
req_hdr->opcode = opcode;
|
||||
req_hdr->subsystem = subsystem;
|
||||
req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
|
||||
req_hdr->version = 0;
|
||||
|
||||
- wrb->tag0 = opcode;
|
||||
- wrb->tag1 = subsystem;
|
||||
+ wrb->tag0 = req_addr & 0xFFFFFFFF;
|
||||
+ wrb->tag1 = upper_32_bits(req_addr);
|
||||
+
|
||||
wrb->payload_length = cmd_len;
|
||||
if (mem) {
|
||||
wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) <<
|
||||
@@ -1283,13 +1319,10 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter)
|
||||
{
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_cmd_req_get_cntl_addnl_attribs *req;
|
||||
- u16 mccq_index;
|
||||
int status;
|
||||
|
||||
spin_lock_bh(&adapter->mcc_lock);
|
||||
|
||||
- mccq_index = adapter->mcc_obj.q.head;
|
||||
-
|
||||
wrb = wrb_from_mccq(adapter);
|
||||
if (!wrb) {
|
||||
status = -EBUSY;
|
||||
@@ -1301,8 +1334,6 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter)
|
||||
OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, sizeof(*req),
|
||||
wrb, NULL);
|
||||
|
||||
- wrb->tag1 = mccq_index;
|
||||
-
|
||||
be_mcc_notify(adapter);
|
||||
|
||||
err:
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
index 3c54361..944f031 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
||||
@@ -225,8 +225,12 @@ struct be_cmd_req_hdr {
|
||||
#define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */
|
||||
#define RESP_HDR_INFO_SUBSYS_SHIFT 8 /* bits 8 - 15 */
|
||||
struct be_cmd_resp_hdr {
|
||||
- u32 info; /* dword 0 */
|
||||
- u32 status; /* dword 1 */
|
||||
+ u8 opcode; /* dword 0 */
|
||||
+ u8 subsystem; /* dword 0 */
|
||||
+ u8 rsvd[2]; /* dword 0 */
|
||||
+ u8 status; /* dword 1 */
|
||||
+ u8 add_status; /* dword 1 */
|
||||
+ u8 rsvd1[2]; /* dword 1 */
|
||||
u32 response_length; /* dword 2 */
|
||||
u32 actual_resp_len; /* dword 3 */
|
||||
};
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,383 +0,0 @@
|
|||
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Date: Wed, 25 Apr 2012 01:47:15 +0000
|
||||
Subject: [PATCH 50/58] be2net: Fix FW download for BE
|
||||
|
||||
commit c165541efc4d1024d7db22ecdf64359b1f6107fc upstream.
|
||||
|
||||
Skip flashing a FW component if that component is not present in a
|
||||
particular FW UFI image.
|
||||
|
||||
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
|
||||
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_cmds.c | 2 +-
|
||||
drivers/net/ethernet/emulex/benet/be_hw.h | 74 ++++++++----
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 168 ++++++++++++++++++---------
|
||||
3 files changed, 166 insertions(+), 78 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
index 2673081..43167e8 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
||||
@@ -1979,7 +1979,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
|
||||
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
|
||||
OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4, wrb, NULL);
|
||||
|
||||
- req->params.op_type = cpu_to_le32(IMG_TYPE_REDBOOT);
|
||||
+ req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT);
|
||||
req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
|
||||
req->params.offset = cpu_to_le32(offset);
|
||||
req->params.data_buf_size = cpu_to_le32(0x4);
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
|
||||
index f2c89e3..0949aa6 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
|
||||
@@ -162,22 +162,23 @@
|
||||
#define QUERY_FAT 1
|
||||
|
||||
/* Flashrom related descriptors */
|
||||
+#define MAX_FLASH_COMP 32
|
||||
#define IMAGE_TYPE_FIRMWARE 160
|
||||
#define IMAGE_TYPE_BOOTCODE 224
|
||||
#define IMAGE_TYPE_OPTIONROM 32
|
||||
|
||||
#define NUM_FLASHDIR_ENTRIES 32
|
||||
|
||||
-#define IMG_TYPE_ISCSI_ACTIVE 0
|
||||
-#define IMG_TYPE_REDBOOT 1
|
||||
-#define IMG_TYPE_BIOS 2
|
||||
-#define IMG_TYPE_PXE_BIOS 3
|
||||
-#define IMG_TYPE_FCOE_BIOS 8
|
||||
-#define IMG_TYPE_ISCSI_BACKUP 9
|
||||
-#define IMG_TYPE_FCOE_FW_ACTIVE 10
|
||||
-#define IMG_TYPE_FCOE_FW_BACKUP 11
|
||||
-#define IMG_TYPE_NCSI_FW 13
|
||||
-#define IMG_TYPE_PHY_FW 99
|
||||
+#define OPTYPE_ISCSI_ACTIVE 0
|
||||
+#define OPTYPE_REDBOOT 1
|
||||
+#define OPTYPE_BIOS 2
|
||||
+#define OPTYPE_PXE_BIOS 3
|
||||
+#define OPTYPE_FCOE_BIOS 8
|
||||
+#define OPTYPE_ISCSI_BACKUP 9
|
||||
+#define OPTYPE_FCOE_FW_ACTIVE 10
|
||||
+#define OPTYPE_FCOE_FW_BACKUP 11
|
||||
+#define OPTYPE_NCSI_FW 13
|
||||
+#define OPTYPE_PHY_FW 99
|
||||
#define TN_8022 13
|
||||
|
||||
#define ILLEGAL_IOCTL_REQ 2
|
||||
@@ -223,6 +224,24 @@
|
||||
#define FLASH_REDBOOT_START_g3 (262144)
|
||||
#define FLASH_PHY_FW_START_g3 1310720
|
||||
|
||||
+#define IMAGE_NCSI 16
|
||||
+#define IMAGE_OPTION_ROM_PXE 32
|
||||
+#define IMAGE_OPTION_ROM_FCoE 33
|
||||
+#define IMAGE_OPTION_ROM_ISCSI 34
|
||||
+#define IMAGE_FLASHISM_JUMPVECTOR 48
|
||||
+#define IMAGE_FLASH_ISM 49
|
||||
+#define IMAGE_JUMP_VECTOR 50
|
||||
+#define IMAGE_FIRMWARE_iSCSI 160
|
||||
+#define IMAGE_FIRMWARE_COMP_iSCSI 161
|
||||
+#define IMAGE_FIRMWARE_FCoE 162
|
||||
+#define IMAGE_FIRMWARE_COMP_FCoE 163
|
||||
+#define IMAGE_FIRMWARE_BACKUP_iSCSI 176
|
||||
+#define IMAGE_FIRMWARE_BACKUP_COMP_iSCSI 177
|
||||
+#define IMAGE_FIRMWARE_BACKUP_FCoE 178
|
||||
+#define IMAGE_FIRMWARE_BACKUP_COMP_FCoE 179
|
||||
+#define IMAGE_FIRMWARE_PHY 192
|
||||
+#define IMAGE_BOOT_CODE 224
|
||||
+
|
||||
/************* Rx Packet Type Encoding **************/
|
||||
#define BE_UNICAST_PACKET 0
|
||||
#define BE_MULTICAST_PACKET 1
|
||||
@@ -445,6 +464,7 @@ struct flash_comp {
|
||||
unsigned long offset;
|
||||
int optype;
|
||||
int size;
|
||||
+ int img_type;
|
||||
};
|
||||
|
||||
struct image_hdr {
|
||||
@@ -481,17 +501,19 @@ struct flash_section_hdr {
|
||||
u32 format_rev;
|
||||
u32 cksum;
|
||||
u32 antidote;
|
||||
- u32 build_no;
|
||||
- u8 id_string[64];
|
||||
- u32 active_entry_mask;
|
||||
- u32 valid_entry_mask;
|
||||
- u32 org_content_mask;
|
||||
- u32 rsvd0;
|
||||
- u32 rsvd1;
|
||||
- u32 rsvd2;
|
||||
- u32 rsvd3;
|
||||
- u32 rsvd4;
|
||||
-};
|
||||
+ u32 num_images;
|
||||
+ u8 id_string[128];
|
||||
+ u32 rsvd[4];
|
||||
+} __packed;
|
||||
+
|
||||
+struct flash_section_hdr_g2 {
|
||||
+ u32 format_rev;
|
||||
+ u32 cksum;
|
||||
+ u32 antidote;
|
||||
+ u32 build_num;
|
||||
+ u8 id_string[128];
|
||||
+ u32 rsvd[8];
|
||||
+} __packed;
|
||||
|
||||
struct flash_section_entry {
|
||||
u32 type;
|
||||
@@ -503,10 +525,16 @@ struct flash_section_entry {
|
||||
u32 rsvd0;
|
||||
u32 rsvd1;
|
||||
u8 ver_data[32];
|
||||
-};
|
||||
+} __packed;
|
||||
|
||||
struct flash_section_info {
|
||||
u8 cookie[32];
|
||||
struct flash_section_hdr fsec_hdr;
|
||||
struct flash_section_entry fsec_entry[32];
|
||||
-};
|
||||
+} __packed;
|
||||
+
|
||||
+struct flash_section_info_g2 {
|
||||
+ u8 cookie[32];
|
||||
+ struct flash_section_hdr_g2 fsec_hdr;
|
||||
+ struct flash_section_entry fsec_entry[32];
|
||||
+} __packed;
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 9b1c03e..730fb1b 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -2751,6 +2751,8 @@ static void be_netpoll(struct net_device *netdev)
|
||||
#endif
|
||||
|
||||
#define FW_FILE_HDR_SIGN "ServerEngines Corp. "
|
||||
+char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "};
|
||||
+
|
||||
static bool be_flash_redboot(struct be_adapter *adapter,
|
||||
const u8 *p, u32 img_start, int image_size,
|
||||
int hdr_size)
|
||||
@@ -2784,58 +2786,101 @@ static bool phy_flashing_required(struct be_adapter *adapter)
|
||||
adapter->phy.interface_type == PHY_TYPE_BASET_10GB);
|
||||
}
|
||||
|
||||
+static bool is_comp_in_ufi(struct be_adapter *adapter,
|
||||
+ struct flash_section_info *fsec, int type)
|
||||
+{
|
||||
+ int i = 0, img_type = 0;
|
||||
+ struct flash_section_info_g2 *fsec_g2 = NULL;
|
||||
+
|
||||
+ if (adapter->generation != BE_GEN3)
|
||||
+ fsec_g2 = (struct flash_section_info_g2 *)fsec;
|
||||
+
|
||||
+ for (i = 0; i < MAX_FLASH_COMP; i++) {
|
||||
+ if (fsec_g2)
|
||||
+ img_type = le32_to_cpu(fsec_g2->fsec_entry[i].type);
|
||||
+ else
|
||||
+ img_type = le32_to_cpu(fsec->fsec_entry[i].type);
|
||||
+
|
||||
+ if (img_type == type)
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
|
||||
+ int header_size,
|
||||
+ const struct firmware *fw)
|
||||
+{
|
||||
+ struct flash_section_info *fsec = NULL;
|
||||
+ const u8 *p = fw->data;
|
||||
+
|
||||
+ p += header_size;
|
||||
+ while (p < (fw->data + fw->size)) {
|
||||
+ fsec = (struct flash_section_info *)p;
|
||||
+ if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie)))
|
||||
+ return fsec;
|
||||
+ p += 32;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static int be_flash_data(struct be_adapter *adapter,
|
||||
- const struct firmware *fw,
|
||||
- struct be_dma_mem *flash_cmd, int num_of_images)
|
||||
+ const struct firmware *fw,
|
||||
+ struct be_dma_mem *flash_cmd,
|
||||
+ int num_of_images)
|
||||
|
||||
{
|
||||
int status = 0, i, filehdr_size = 0;
|
||||
+ int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
|
||||
u32 total_bytes = 0, flash_op;
|
||||
int num_bytes;
|
||||
const u8 *p = fw->data;
|
||||
struct be_cmd_write_flashrom *req = flash_cmd->va;
|
||||
const struct flash_comp *pflashcomp;
|
||||
- int num_comp;
|
||||
-
|
||||
- static const struct flash_comp gen3_flash_types[10] = {
|
||||
- { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE,
|
||||
- FLASH_IMAGE_MAX_SIZE_g3},
|
||||
- { FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT,
|
||||
- FLASH_REDBOOT_IMAGE_MAX_SIZE_g3},
|
||||
- { FLASH_iSCSI_BIOS_START_g3, IMG_TYPE_BIOS,
|
||||
- FLASH_BIOS_IMAGE_MAX_SIZE_g3},
|
||||
- { FLASH_PXE_BIOS_START_g3, IMG_TYPE_PXE_BIOS,
|
||||
- FLASH_BIOS_IMAGE_MAX_SIZE_g3},
|
||||
- { FLASH_FCoE_BIOS_START_g3, IMG_TYPE_FCOE_BIOS,
|
||||
- FLASH_BIOS_IMAGE_MAX_SIZE_g3},
|
||||
- { FLASH_iSCSI_BACKUP_IMAGE_START_g3, IMG_TYPE_ISCSI_BACKUP,
|
||||
- FLASH_IMAGE_MAX_SIZE_g3},
|
||||
- { FLASH_FCoE_PRIMARY_IMAGE_START_g3, IMG_TYPE_FCOE_FW_ACTIVE,
|
||||
- FLASH_IMAGE_MAX_SIZE_g3},
|
||||
- { FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP,
|
||||
- FLASH_IMAGE_MAX_SIZE_g3},
|
||||
- { FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW,
|
||||
- FLASH_NCSI_IMAGE_MAX_SIZE_g3},
|
||||
- { FLASH_PHY_FW_START_g3, IMG_TYPE_PHY_FW,
|
||||
- FLASH_PHY_FW_IMAGE_MAX_SIZE_g3}
|
||||
+ int num_comp, hdr_size;
|
||||
+ struct flash_section_info *fsec = NULL;
|
||||
+
|
||||
+ struct flash_comp gen3_flash_types[] = {
|
||||
+ { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, OPTYPE_ISCSI_ACTIVE,
|
||||
+ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_iSCSI},
|
||||
+ { FLASH_REDBOOT_START_g3, OPTYPE_REDBOOT,
|
||||
+ FLASH_REDBOOT_IMAGE_MAX_SIZE_g3, IMAGE_BOOT_CODE},
|
||||
+ { FLASH_iSCSI_BIOS_START_g3, OPTYPE_BIOS,
|
||||
+ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_ISCSI},
|
||||
+ { FLASH_PXE_BIOS_START_g3, OPTYPE_PXE_BIOS,
|
||||
+ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_PXE},
|
||||
+ { FLASH_FCoE_BIOS_START_g3, OPTYPE_FCOE_BIOS,
|
||||
+ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_FCoE},
|
||||
+ { FLASH_iSCSI_BACKUP_IMAGE_START_g3, OPTYPE_ISCSI_BACKUP,
|
||||
+ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_iSCSI},
|
||||
+ { FLASH_FCoE_PRIMARY_IMAGE_START_g3, OPTYPE_FCOE_FW_ACTIVE,
|
||||
+ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_FCoE},
|
||||
+ { FLASH_FCoE_BACKUP_IMAGE_START_g3, OPTYPE_FCOE_FW_BACKUP,
|
||||
+ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_FCoE},
|
||||
+ { FLASH_NCSI_START_g3, OPTYPE_NCSI_FW,
|
||||
+ FLASH_NCSI_IMAGE_MAX_SIZE_g3, IMAGE_NCSI},
|
||||
+ { FLASH_PHY_FW_START_g3, OPTYPE_PHY_FW,
|
||||
+ FLASH_PHY_FW_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_PHY}
|
||||
};
|
||||
- static const struct flash_comp gen2_flash_types[8] = {
|
||||
- { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE,
|
||||
- FLASH_IMAGE_MAX_SIZE_g2},
|
||||
- { FLASH_REDBOOT_START_g2, IMG_TYPE_REDBOOT,
|
||||
- FLASH_REDBOOT_IMAGE_MAX_SIZE_g2},
|
||||
- { FLASH_iSCSI_BIOS_START_g2, IMG_TYPE_BIOS,
|
||||
- FLASH_BIOS_IMAGE_MAX_SIZE_g2},
|
||||
- { FLASH_PXE_BIOS_START_g2, IMG_TYPE_PXE_BIOS,
|
||||
- FLASH_BIOS_IMAGE_MAX_SIZE_g2},
|
||||
- { FLASH_FCoE_BIOS_START_g2, IMG_TYPE_FCOE_BIOS,
|
||||
- FLASH_BIOS_IMAGE_MAX_SIZE_g2},
|
||||
- { FLASH_iSCSI_BACKUP_IMAGE_START_g2, IMG_TYPE_ISCSI_BACKUP,
|
||||
- FLASH_IMAGE_MAX_SIZE_g2},
|
||||
- { FLASH_FCoE_PRIMARY_IMAGE_START_g2, IMG_TYPE_FCOE_FW_ACTIVE,
|
||||
- FLASH_IMAGE_MAX_SIZE_g2},
|
||||
- { FLASH_FCoE_BACKUP_IMAGE_START_g2, IMG_TYPE_FCOE_FW_BACKUP,
|
||||
- FLASH_IMAGE_MAX_SIZE_g2}
|
||||
+
|
||||
+ struct flash_comp gen2_flash_types[] = {
|
||||
+ { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, OPTYPE_ISCSI_ACTIVE,
|
||||
+ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_iSCSI},
|
||||
+ { FLASH_REDBOOT_START_g2, OPTYPE_REDBOOT,
|
||||
+ FLASH_REDBOOT_IMAGE_MAX_SIZE_g2, IMAGE_BOOT_CODE},
|
||||
+ { FLASH_iSCSI_BIOS_START_g2, OPTYPE_BIOS,
|
||||
+ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_ISCSI},
|
||||
+ { FLASH_PXE_BIOS_START_g2, OPTYPE_PXE_BIOS,
|
||||
+ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_PXE},
|
||||
+ { FLASH_FCoE_BIOS_START_g2, OPTYPE_FCOE_BIOS,
|
||||
+ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_FCoE},
|
||||
+ { FLASH_iSCSI_BACKUP_IMAGE_START_g2, OPTYPE_ISCSI_BACKUP,
|
||||
+ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_iSCSI},
|
||||
+ { FLASH_FCoE_PRIMARY_IMAGE_START_g2, OPTYPE_FCOE_FW_ACTIVE,
|
||||
+ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_FCoE},
|
||||
+ { FLASH_FCoE_BACKUP_IMAGE_START_g2, OPTYPE_FCOE_FW_BACKUP,
|
||||
+ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_FCoE}
|
||||
};
|
||||
|
||||
if (adapter->generation == BE_GEN3) {
|
||||
@@ -2847,22 +2892,37 @@ static int be_flash_data(struct be_adapter *adapter,
|
||||
filehdr_size = sizeof(struct flash_file_hdr_g2);
|
||||
num_comp = ARRAY_SIZE(gen2_flash_types);
|
||||
}
|
||||
+ /* Get flash section info*/
|
||||
+ fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
|
||||
+ if (!fsec) {
|
||||
+ dev_err(&adapter->pdev->dev,
|
||||
+ "Invalid Cookie. UFI corrupted ?\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
for (i = 0; i < num_comp; i++) {
|
||||
- if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) &&
|
||||
- memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
|
||||
+ if (!is_comp_in_ufi(adapter, fsec, pflashcomp[i].img_type))
|
||||
continue;
|
||||
- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW) {
|
||||
+
|
||||
+ if ((pflashcomp[i].optype == OPTYPE_NCSI_FW) &&
|
||||
+ memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (pflashcomp[i].optype == OPTYPE_PHY_FW) {
|
||||
if (!phy_flashing_required(adapter))
|
||||
continue;
|
||||
}
|
||||
- if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) &&
|
||||
- (!be_flash_redboot(adapter, fw->data,
|
||||
- pflashcomp[i].offset, pflashcomp[i].size, filehdr_size +
|
||||
- (num_of_images * sizeof(struct image_hdr)))))
|
||||
+
|
||||
+ hdr_size = filehdr_size +
|
||||
+ (num_of_images * sizeof(struct image_hdr));
|
||||
+
|
||||
+ if ((pflashcomp[i].optype == OPTYPE_REDBOOT) &&
|
||||
+ (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset,
|
||||
+ pflashcomp[i].size, hdr_size)))
|
||||
continue;
|
||||
+
|
||||
+ /* Flash the component */
|
||||
p = fw->data;
|
||||
- p += filehdr_size + pflashcomp[i].offset
|
||||
- + (num_of_images * sizeof(struct image_hdr));
|
||||
+ p += filehdr_size + pflashcomp[i].offset + img_hdrs_size;
|
||||
if (p + pflashcomp[i].size > fw->data + fw->size)
|
||||
return -1;
|
||||
total_bytes = pflashcomp[i].size;
|
||||
@@ -2873,12 +2933,12 @@ static int be_flash_data(struct be_adapter *adapter,
|
||||
num_bytes = total_bytes;
|
||||
total_bytes -= num_bytes;
|
||||
if (!total_bytes) {
|
||||
- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW)
|
||||
+ if (pflashcomp[i].optype == OPTYPE_PHY_FW)
|
||||
flash_op = FLASHROM_OPER_PHY_FLASH;
|
||||
else
|
||||
flash_op = FLASHROM_OPER_FLASH;
|
||||
} else {
|
||||
- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW)
|
||||
+ if (pflashcomp[i].optype == OPTYPE_PHY_FW)
|
||||
flash_op = FLASHROM_OPER_PHY_SAVE;
|
||||
else
|
||||
flash_op = FLASHROM_OPER_SAVE;
|
||||
@@ -2890,7 +2950,7 @@ static int be_flash_data(struct be_adapter *adapter,
|
||||
if (status) {
|
||||
if ((status == ILLEGAL_IOCTL_REQ) &&
|
||||
(pflashcomp[i].optype ==
|
||||
- IMG_TYPE_PHY_FW))
|
||||
+ OPTYPE_PHY_FW))
|
||||
break;
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"cmd to write to flash rom failed.\n");
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
From: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Date: Thu, 26 Apr 2012 15:42:31 +0000
|
||||
Subject: [PATCH 51/58] be2net: Ignore status of some ioctls during driver
|
||||
load
|
||||
|
||||
commit ddc3f5cbaf1ddea122ec1d51c1cce97482b4d0c2 upstream.
|
||||
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 17 ++++-------------
|
||||
1 file changed, 4 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 730fb1b..9effea4 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -2696,24 +2696,15 @@ static int be_setup(struct be_adapter *adapter)
|
||||
|
||||
be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL);
|
||||
|
||||
- status = be_vid_config(adapter, false, 0);
|
||||
- if (status)
|
||||
- goto err;
|
||||
+ be_vid_config(adapter, false, 0);
|
||||
|
||||
be_set_rx_mode(adapter->netdev);
|
||||
|
||||
- status = be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc);
|
||||
- /* For Lancer: It is legal for this cmd to fail on VF */
|
||||
- if (status && (be_physfn(adapter) || !lancer_chip(adapter)))
|
||||
- goto err;
|
||||
+ be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc);
|
||||
|
||||
- if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc) {
|
||||
- status = be_cmd_set_flow_control(adapter, adapter->tx_fc,
|
||||
+ if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc)
|
||||
+ be_cmd_set_flow_control(adapter, adapter->tx_fc,
|
||||
adapter->rx_fc);
|
||||
- /* For Lancer: It is legal for this cmd to fail on VF */
|
||||
- if (status && (be_physfn(adapter) || !lancer_chip(adapter)))
|
||||
- goto err;
|
||||
- }
|
||||
|
||||
pcie_set_readrq(adapter->pdev, 4096);
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
From: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Date: Thu, 26 Apr 2012 15:42:39 +0000
|
||||
Subject: [PATCH 52/58] be2net: fix speed displayed by ethtool on certain SKUs
|
||||
|
||||
commit 2a89611a051cdcfcf4a7ae21d18eef64fab517b4 upstream.
|
||||
|
||||
logical speed returned by link_status_query needs to be multiplied by 10.
|
||||
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_ethtool.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
index 9d71bad..b3b5fae 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
@@ -557,7 +557,7 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
|
||||
if (!status)
|
||||
be_link_status_update(adapter, link_status);
|
||||
if (link_speed)
|
||||
- et_speed = link_speed;
|
||||
+ et_speed = link_speed * 10;
|
||||
else
|
||||
et_speed = convert_to_et_speed(port_speed);
|
||||
} else {
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
From: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Date: Thu, 26 Apr 2012 15:42:46 +0000
|
||||
Subject: [PATCH 53/58] be2net: update the driver version
|
||||
|
||||
commit 06b0ab373df74f7916282b452b35d6389a605b8a upstream.
|
||||
|
||||
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index 4bc18ef..c3ee910 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include "be_hw.h"
|
||||
|
||||
-#define DRV_VER "4.2.116u"
|
||||
+#define DRV_VER "4.2.220u"
|
||||
#define DRV_NAME "be2net"
|
||||
#define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC"
|
||||
#define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC"
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
From: Somnath Kotur <somnath.kotur@emulex.com>
|
||||
Date: Wed, 2 May 2012 03:40:16 +0000
|
||||
Subject: [PATCH 54/58] be2net: Fix to not set link speed for disabled
|
||||
functions of a UMC card
|
||||
|
||||
commit 22ca7a6e9a68a7e0c149b22ebed9dcd106245bb7 upstream.
|
||||
|
||||
This renders the interface view somewhat inconsistent from the Host OS POV
|
||||
considering the rest of the interfaces are showing their respective speeds
|
||||
based on the bandwidth assigned to them.
|
||||
|
||||
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_ethtool.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
index b3b5fae..1763836 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
@@ -558,7 +558,7 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
|
||||
be_link_status_update(adapter, link_status);
|
||||
if (link_speed)
|
||||
et_speed = link_speed * 10;
|
||||
- else
|
||||
+ else if (link_status)
|
||||
et_speed = convert_to_et_speed(port_speed);
|
||||
} else {
|
||||
et_speed = adapter->phy.forced_port_speed;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
From: Somnath Kotur <somnath.kotur@emulex.com>
|
||||
Date: Wed, 2 May 2012 03:40:32 +0000
|
||||
Subject: [PATCH 55/58] be2net: Fix to apply duplex value as unknown when link
|
||||
is down.
|
||||
|
||||
commit 682256dbef8e827385cf214f3ada8b62f6c227ed upstream.
|
||||
|
||||
Suggested-by: Ben Hutchings <bhutchings@solarflare.com>
|
||||
Signed-off-by: Sarveshwar Bandi <sarveshwar.bandi@emulex.com>
|
||||
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_ethtool.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
index 1763836..730e96a 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
|
||||
@@ -618,7 +618,7 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
|
||||
ecmd->supported = adapter->phy.supported;
|
||||
}
|
||||
|
||||
- ecmd->duplex = DUPLEX_FULL;
|
||||
+ ecmd->duplex = netif_carrier_ok(netdev) ? DUPLEX_FULL : DUPLEX_UNKNOWN;
|
||||
ecmd->phy_address = adapter->port_num;
|
||||
|
||||
return 0;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
From: Somnath Kotur <somnath.kotur@emulex.com>
|
||||
Date: Wed, 2 May 2012 03:40:49 +0000
|
||||
Subject: [PATCH 56/58] be2net: Record receive queue index in skb to aid RPS.
|
||||
|
||||
commit aaa6daec586cd39a6cd44b3d0ab91a84b0e3d53a upstream.
|
||||
|
||||
Signed-off-by: Sarveshwar Bandi <Sarveshwar.Bandi@emulex.com>
|
||||
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 9effea4..0dd4b88 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -1251,6 +1251,7 @@ static void be_rx_compl_process(struct be_rx_obj *rxo,
|
||||
skb_checksum_none_assert(skb);
|
||||
|
||||
skb->protocol = eth_type_trans(skb, netdev);
|
||||
+ skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]);
|
||||
if (netdev->features & NETIF_F_RXHASH)
|
||||
skb->rxhash = rxcp->rss_hash;
|
||||
|
||||
@@ -1307,6 +1308,7 @@ void be_rx_compl_process_gro(struct be_rx_obj *rxo, struct napi_struct *napi,
|
||||
skb->len = rxcp->pkt_size;
|
||||
skb->data_len = rxcp->pkt_size;
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
+ skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]);
|
||||
if (adapter->netdev->features & NETIF_F_RXHASH)
|
||||
skb->rxhash = rxcp->rss_hash;
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
From: Somnath Kotur <somnath.kotur@emulex.com>
|
||||
Date: Wed, 2 May 2012 03:41:01 +0000
|
||||
Subject: [PATCH 57/58] be2net: Fix EEH error reset before a flash dump
|
||||
completes
|
||||
|
||||
commit eeb7fc7bc095546b21188e8e076a59bce73f9ca6 upstream.
|
||||
|
||||
An EEH error can cause the FW to trigger a flash debug dump.
|
||||
Resetting the card while flash dump is in progress can cause it not to recover.
|
||||
Wait for it to finish before letting EEH flow to reset the card.
|
||||
|
||||
Signed-off-by: Sathya Perla <Sathya.Perla@emulex.com>
|
||||
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 0dd4b88..3492dc8 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -3813,6 +3813,11 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev,
|
||||
|
||||
pci_disable_device(pdev);
|
||||
|
||||
+ /* The error could cause the FW to trigger a flash debug dump.
|
||||
+ * Resetting the card while flash dump is in progress
|
||||
+ * can cause it not to recover; wait for it to finish
|
||||
+ */
|
||||
+ ssleep(30);
|
||||
return PCI_ERS_RESULT_NEED_RESET;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,473 +0,0 @@
|
|||
From: Sathya Perla <sathya.perla@emulex.com>
|
||||
Date: Tue, 8 May 2012 19:41:24 +0000
|
||||
Subject: [PATCH 58/58] be2net: avoid disabling sriov while VFs are assigned
|
||||
|
||||
commit 39f1d94d300a58eb3e9b851d077cada4e2fa9d46 upstream.
|
||||
|
||||
Calling pci_disable_sriov() while VFs are assigned to VMs causes
|
||||
kernel panic. This patch uses PCI_DEV_FLAGS_ASSIGNED bit state of the
|
||||
VF's pci_dev to avoid this. Also, the unconditional function reset cmd
|
||||
issued on a PF probe can delete the VF configuration for the
|
||||
previously enabled VFs. A scratchpad register is now used to issue a
|
||||
function reset only when needed (i.e., in a crash dump scenario.)
|
||||
|
||||
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/emulex/benet/be.h | 22 +--
|
||||
drivers/net/ethernet/emulex/benet/be_hw.h | 2 +
|
||||
drivers/net/ethernet/emulex/benet/be_main.c | 199 ++++++++++++++++-----------
|
||||
3 files changed, 134 insertions(+), 89 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
|
||||
index c3ee910..ecf1a81 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be.h
|
||||
@@ -313,6 +313,11 @@ struct be_vf_cfg {
|
||||
u32 tx_rate;
|
||||
};
|
||||
|
||||
+enum vf_state {
|
||||
+ ENABLED = 0,
|
||||
+ ASSIGNED = 1
|
||||
+};
|
||||
+
|
||||
#define BE_FLAGS_LINK_STATUS_INIT 1
|
||||
#define BE_FLAGS_WORKER_SCHEDULED (1 << 3)
|
||||
#define BE_UC_PMAC_COUNT 30
|
||||
@@ -403,8 +408,9 @@ struct be_adapter {
|
||||
u32 flash_status;
|
||||
struct completion flash_compl;
|
||||
|
||||
- u32 num_vfs;
|
||||
- u8 is_virtfn;
|
||||
+ u32 num_vfs; /* Number of VFs provisioned by PF driver */
|
||||
+ u32 dev_num_vfs; /* Number of VFs supported by HW */
|
||||
+ u8 virtfn;
|
||||
struct be_vf_cfg *vf_cfg;
|
||||
bool be3_native;
|
||||
u32 sli_family;
|
||||
@@ -417,8 +423,10 @@ struct be_adapter {
|
||||
u32 uc_macs; /* Count of secondary UC MAC programmed */
|
||||
};
|
||||
|
||||
-#define be_physfn(adapter) (!adapter->is_virtfn)
|
||||
+#define be_physfn(adapter) (!adapter->virtfn)
|
||||
#define sriov_enabled(adapter) (adapter->num_vfs > 0)
|
||||
+#define sriov_want(adapter) (adapter->dev_num_vfs && num_vfs && \
|
||||
+ be_physfn(adapter))
|
||||
#define for_all_vfs(adapter, vf_cfg, i) \
|
||||
for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \
|
||||
i++, vf_cfg++)
|
||||
@@ -547,14 +555,6 @@ static inline u8 is_udp_pkt(struct sk_buff *skb)
|
||||
return val;
|
||||
}
|
||||
|
||||
-static inline void be_check_sriov_fn_type(struct be_adapter *adapter)
|
||||
-{
|
||||
- u32 sli_intf;
|
||||
-
|
||||
- pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
|
||||
- adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
|
||||
-}
|
||||
-
|
||||
static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
|
||||
{
|
||||
u32 addr;
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
|
||||
index 0949aa6..f38b58c 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
|
||||
@@ -58,6 +58,8 @@
|
||||
|
||||
#define SLI_PORT_CONTROL_IP_MASK 0x08000000
|
||||
|
||||
+#define PCICFG_CUST_SCRATCHPAD_CSR 0x1EC
|
||||
+
|
||||
/********* Memory BAR register ************/
|
||||
#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc
|
||||
/* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
|
||||
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
index 3492dc8..910bae8 100644
|
||||
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
||||
@@ -1041,6 +1041,29 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
|
||||
return status;
|
||||
}
|
||||
|
||||
+static int be_find_vfs(struct be_adapter *adapter, int vf_state)
|
||||
+{
|
||||
+ struct pci_dev *dev, *pdev = adapter->pdev;
|
||||
+ int vfs = 0, assigned_vfs = 0, pos, vf_fn;
|
||||
+ u16 offset, stride;
|
||||
+
|
||||
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
|
||||
+ pci_read_config_word(pdev, pos + PCI_SRIOV_VF_OFFSET, &offset);
|
||||
+ pci_read_config_word(pdev, pos + PCI_SRIOV_VF_STRIDE, &stride);
|
||||
+
|
||||
+ dev = pci_get_device(pdev->vendor, PCI_ANY_ID, NULL);
|
||||
+ while (dev) {
|
||||
+ vf_fn = (pdev->devfn + offset + stride * vfs) & 0xFFFF;
|
||||
+ if (dev->is_virtfn && dev->devfn == vf_fn) {
|
||||
+ vfs++;
|
||||
+ if (dev->dev_flags & PCI_DEV_FLAGS_ASSIGNED)
|
||||
+ assigned_vfs++;
|
||||
+ }
|
||||
+ dev = pci_get_device(pdev->vendor, PCI_ANY_ID, dev);
|
||||
+ }
|
||||
+ return (vf_state == ASSIGNED) ? assigned_vfs : vfs;
|
||||
+}
|
||||
+
|
||||
static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo)
|
||||
{
|
||||
struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]);
|
||||
@@ -1781,9 +1804,9 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
|
||||
|
||||
static int be_num_txqs_want(struct be_adapter *adapter)
|
||||
{
|
||||
- if (sriov_enabled(adapter) || be_is_mc(adapter) ||
|
||||
- lancer_chip(adapter) || !be_physfn(adapter) ||
|
||||
- adapter->generation == BE_GEN2)
|
||||
+ if (sriov_want(adapter) || be_is_mc(adapter) ||
|
||||
+ lancer_chip(adapter) || !be_physfn(adapter) ||
|
||||
+ adapter->generation == BE_GEN2)
|
||||
return 1;
|
||||
else
|
||||
return MAX_TX_QS;
|
||||
@@ -2110,7 +2133,7 @@ static void be_msix_disable(struct be_adapter *adapter)
|
||||
static uint be_num_rss_want(struct be_adapter *adapter)
|
||||
{
|
||||
if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
|
||||
- adapter->num_vfs == 0 && be_physfn(adapter) &&
|
||||
+ !sriov_want(adapter) && be_physfn(adapter) &&
|
||||
!be_is_mc(adapter))
|
||||
return (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
|
||||
else
|
||||
@@ -2144,53 +2167,6 @@ done:
|
||||
return;
|
||||
}
|
||||
|
||||
-static int be_sriov_enable(struct be_adapter *adapter)
|
||||
-{
|
||||
- be_check_sriov_fn_type(adapter);
|
||||
-
|
||||
-#ifdef CONFIG_PCI_IOV
|
||||
- if (be_physfn(adapter) && num_vfs) {
|
||||
- int status, pos;
|
||||
- u16 dev_vfs;
|
||||
-
|
||||
- pos = pci_find_ext_capability(adapter->pdev,
|
||||
- PCI_EXT_CAP_ID_SRIOV);
|
||||
- pci_read_config_word(adapter->pdev,
|
||||
- pos + PCI_SRIOV_TOTAL_VF, &dev_vfs);
|
||||
-
|
||||
- adapter->num_vfs = min_t(u16, num_vfs, dev_vfs);
|
||||
- if (adapter->num_vfs != num_vfs)
|
||||
- dev_info(&adapter->pdev->dev,
|
||||
- "Device supports %d VFs and not %d\n",
|
||||
- adapter->num_vfs, num_vfs);
|
||||
-
|
||||
- status = pci_enable_sriov(adapter->pdev, adapter->num_vfs);
|
||||
- if (status)
|
||||
- adapter->num_vfs = 0;
|
||||
-
|
||||
- if (adapter->num_vfs) {
|
||||
- adapter->vf_cfg = kcalloc(num_vfs,
|
||||
- sizeof(struct be_vf_cfg),
|
||||
- GFP_KERNEL);
|
||||
- if (!adapter->vf_cfg)
|
||||
- return -ENOMEM;
|
||||
- }
|
||||
- }
|
||||
-#endif
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void be_sriov_disable(struct be_adapter *adapter)
|
||||
-{
|
||||
-#ifdef CONFIG_PCI_IOV
|
||||
- if (sriov_enabled(adapter)) {
|
||||
- pci_disable_sriov(adapter->pdev);
|
||||
- kfree(adapter->vf_cfg);
|
||||
- adapter->num_vfs = 0;
|
||||
- }
|
||||
-#endif
|
||||
-}
|
||||
-
|
||||
static inline int be_msix_vec_get(struct be_adapter *adapter,
|
||||
struct be_eq_obj *eqo)
|
||||
{
|
||||
@@ -2492,6 +2468,11 @@ static void be_vf_clear(struct be_adapter *adapter)
|
||||
struct be_vf_cfg *vf_cfg;
|
||||
u32 vf;
|
||||
|
||||
+ if (be_find_vfs(adapter, ASSIGNED)) {
|
||||
+ dev_warn(&adapter->pdev->dev, "VFs are assigned to VMs\n");
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
for_all_vfs(adapter, vf_cfg, vf) {
|
||||
if (lancer_chip(adapter))
|
||||
be_cmd_set_mac_list(adapter, NULL, 0, vf + 1);
|
||||
@@ -2501,6 +2482,10 @@ static void be_vf_clear(struct be_adapter *adapter)
|
||||
|
||||
be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1);
|
||||
}
|
||||
+ pci_disable_sriov(adapter->pdev);
|
||||
+done:
|
||||
+ kfree(adapter->vf_cfg);
|
||||
+ adapter->num_vfs = 0;
|
||||
}
|
||||
|
||||
static int be_clear(struct be_adapter *adapter)
|
||||
@@ -2530,29 +2515,60 @@ static int be_clear(struct be_adapter *adapter)
|
||||
be_cmd_fw_clean(adapter);
|
||||
|
||||
be_msix_disable(adapter);
|
||||
- kfree(adapter->pmac_id);
|
||||
+ pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void be_vf_setup_init(struct be_adapter *adapter)
|
||||
+static int be_vf_setup_init(struct be_adapter *adapter)
|
||||
{
|
||||
struct be_vf_cfg *vf_cfg;
|
||||
int vf;
|
||||
|
||||
+ adapter->vf_cfg = kcalloc(adapter->num_vfs, sizeof(*vf_cfg),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!adapter->vf_cfg)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
for_all_vfs(adapter, vf_cfg, vf) {
|
||||
vf_cfg->if_handle = -1;
|
||||
vf_cfg->pmac_id = -1;
|
||||
}
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int be_vf_setup(struct be_adapter *adapter)
|
||||
{
|
||||
struct be_vf_cfg *vf_cfg;
|
||||
+ struct device *dev = &adapter->pdev->dev;
|
||||
u32 cap_flags, en_flags, vf;
|
||||
u16 def_vlan, lnk_speed;
|
||||
- int status;
|
||||
+ int status, enabled_vfs;
|
||||
+
|
||||
+ enabled_vfs = be_find_vfs(adapter, ENABLED);
|
||||
+ if (enabled_vfs) {
|
||||
+ dev_warn(dev, "%d VFs are already enabled\n", enabled_vfs);
|
||||
+ dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs);
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
- be_vf_setup_init(adapter);
|
||||
+ if (num_vfs > adapter->dev_num_vfs) {
|
||||
+ dev_warn(dev, "Device supports %d VFs and not %d\n",
|
||||
+ adapter->dev_num_vfs, num_vfs);
|
||||
+ num_vfs = adapter->dev_num_vfs;
|
||||
+ }
|
||||
+
|
||||
+ status = pci_enable_sriov(adapter->pdev, num_vfs);
|
||||
+ if (!status) {
|
||||
+ adapter->num_vfs = num_vfs;
|
||||
+ } else {
|
||||
+ /* Platform doesn't support SRIOV though device supports it */
|
||||
+ dev_warn(dev, "SRIOV enable failed\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ status = be_vf_setup_init(adapter);
|
||||
+ if (status)
|
||||
+ goto err;
|
||||
|
||||
cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
|
||||
BE_IF_FLAGS_MULTICAST;
|
||||
@@ -2563,9 +2579,11 @@ static int be_vf_setup(struct be_adapter *adapter)
|
||||
goto err;
|
||||
}
|
||||
|
||||
- status = be_vf_eth_addr_config(adapter);
|
||||
- if (status)
|
||||
- goto err;
|
||||
+ if (!enabled_vfs) {
|
||||
+ status = be_vf_eth_addr_config(adapter);
|
||||
+ if (status)
|
||||
+ goto err;
|
||||
+ }
|
||||
|
||||
for_all_vfs(adapter, vf_cfg, vf) {
|
||||
status = be_cmd_link_status_query(adapter, NULL, &lnk_speed,
|
||||
@@ -2622,9 +2640,25 @@ do_none:
|
||||
return status;
|
||||
}
|
||||
|
||||
+/* Routine to query per function resource limits */
|
||||
+static int be_get_config(struct be_adapter *adapter)
|
||||
+{
|
||||
+ int pos;
|
||||
+ u16 dev_num_vfs;
|
||||
+
|
||||
+ pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV);
|
||||
+ if (pos) {
|
||||
+ pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF,
|
||||
+ &dev_num_vfs);
|
||||
+ adapter->dev_num_vfs = dev_num_vfs;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int be_setup(struct be_adapter *adapter)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
+ struct device *dev = &adapter->pdev->dev;
|
||||
u32 cap_flags, en_flags;
|
||||
u32 tx_fc, rx_fc;
|
||||
int status;
|
||||
@@ -2632,6 +2666,8 @@ static int be_setup(struct be_adapter *adapter)
|
||||
|
||||
be_setup_init(adapter);
|
||||
|
||||
+ be_get_config(adapter);
|
||||
+
|
||||
be_cmd_req_native_mode(adapter);
|
||||
|
||||
be_msix_enable(adapter);
|
||||
@@ -2710,10 +2746,11 @@ static int be_setup(struct be_adapter *adapter)
|
||||
|
||||
pcie_set_readrq(adapter->pdev, 4096);
|
||||
|
||||
- if (sriov_enabled(adapter)) {
|
||||
- status = be_vf_setup(adapter);
|
||||
- if (status)
|
||||
- goto err;
|
||||
+ if (be_physfn(adapter) && num_vfs) {
|
||||
+ if (adapter->dev_num_vfs)
|
||||
+ be_vf_setup(adapter);
|
||||
+ else
|
||||
+ dev_warn(dev, "device doesn't support SRIOV\n");
|
||||
}
|
||||
|
||||
be_cmd_get_phy_info(adapter);
|
||||
@@ -2723,6 +2760,7 @@ static int be_setup(struct be_adapter *adapter)
|
||||
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
|
||||
adapter->flags |= BE_FLAGS_WORKER_SCHEDULED;
|
||||
|
||||
+ pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 1);
|
||||
return 0;
|
||||
err:
|
||||
be_clear(adapter);
|
||||
@@ -3344,8 +3382,6 @@ static void __devexit be_remove(struct pci_dev *pdev)
|
||||
|
||||
be_ctrl_cleanup(adapter);
|
||||
|
||||
- be_sriov_disable(adapter);
|
||||
-
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
@@ -3359,7 +3395,7 @@ bool be_is_wol_supported(struct be_adapter *adapter)
|
||||
!be_is_wol_excluded(adapter)) ? true : false;
|
||||
}
|
||||
|
||||
-static int be_get_config(struct be_adapter *adapter)
|
||||
+static int be_get_initial_config(struct be_adapter *adapter)
|
||||
{
|
||||
int status;
|
||||
|
||||
@@ -3402,7 +3438,7 @@ static int be_get_config(struct be_adapter *adapter)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int be_dev_family_check(struct be_adapter *adapter)
|
||||
+static int be_dev_type_check(struct be_adapter *adapter)
|
||||
{
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
u32 sli_intf = 0, if_type;
|
||||
@@ -3435,6 +3471,9 @@ static int be_dev_family_check(struct be_adapter *adapter)
|
||||
default:
|
||||
adapter->generation = 0;
|
||||
}
|
||||
+
|
||||
+ pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
|
||||
+ adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3578,6 +3617,14 @@ reschedule:
|
||||
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
+static bool be_reset_required(struct be_adapter *adapter)
|
||||
+{
|
||||
+ u32 reg;
|
||||
+
|
||||
+ pci_read_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, ®);
|
||||
+ return reg;
|
||||
+}
|
||||
+
|
||||
static int __devinit be_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *pdev_id)
|
||||
{
|
||||
@@ -3603,7 +3650,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
|
||||
adapter->pdev = pdev;
|
||||
pci_set_drvdata(pdev, adapter);
|
||||
|
||||
- status = be_dev_family_check(adapter);
|
||||
+ status = be_dev_type_check(adapter);
|
||||
if (status)
|
||||
goto free_netdev;
|
||||
|
||||
@@ -3621,13 +3668,9 @@ static int __devinit be_probe(struct pci_dev *pdev,
|
||||
}
|
||||
}
|
||||
|
||||
- status = be_sriov_enable(adapter);
|
||||
- if (status)
|
||||
- goto free_netdev;
|
||||
-
|
||||
status = be_ctrl_init(adapter);
|
||||
if (status)
|
||||
- goto disable_sriov;
|
||||
+ goto free_netdev;
|
||||
|
||||
if (lancer_chip(adapter)) {
|
||||
status = lancer_wait_ready(adapter);
|
||||
@@ -3654,9 +3697,11 @@ static int __devinit be_probe(struct pci_dev *pdev,
|
||||
if (status)
|
||||
goto ctrl_clean;
|
||||
|
||||
- status = be_cmd_reset_function(adapter);
|
||||
- if (status)
|
||||
- goto ctrl_clean;
|
||||
+ if (be_reset_required(adapter)) {
|
||||
+ status = be_cmd_reset_function(adapter);
|
||||
+ if (status)
|
||||
+ goto ctrl_clean;
|
||||
+ }
|
||||
|
||||
/* The INTR bit may be set in the card when probed by a kdump kernel
|
||||
* after a crash.
|
||||
@@ -3668,7 +3713,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
|
||||
if (status)
|
||||
goto ctrl_clean;
|
||||
|
||||
- status = be_get_config(adapter);
|
||||
+ status = be_get_initial_config(adapter);
|
||||
if (status)
|
||||
goto stats_clean;
|
||||
|
||||
@@ -3697,8 +3742,6 @@ stats_clean:
|
||||
be_stats_cleanup(adapter);
|
||||
ctrl_clean:
|
||||
be_ctrl_cleanup(adapter);
|
||||
-disable_sriov:
|
||||
- be_sriov_disable(adapter);
|
||||
free_netdev:
|
||||
free_netdev(netdev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,771 +0,0 @@
|
|||
From: Eric Dumazet <edumazet@google.com>
|
||||
Date: Thu, 10 May 2012 07:51:25 +0000
|
||||
Subject: [PATCH 1/7] codel: Controlled Delay AQM
|
||||
|
||||
commit 76e3cc126bb223013a6b9a0e2a51238d1ef2e409 upstream.
|
||||
|
||||
An implementation of CoDel AQM, from Kathleen Nichols and Van Jacobson.
|
||||
|
||||
http://queue.acm.org/detail.cfm?id=2209336
|
||||
|
||||
This AQM main input is no longer queue size in bytes or packets, but the
|
||||
delay packets stay in (FIFO) queue.
|
||||
|
||||
As we don't have infinite memory, we still can drop packets in enqueue()
|
||||
in case of massive load, but mean of CoDel is to drop packets in
|
||||
dequeue(), using a control law based on two simple parameters :
|
||||
|
||||
target : target sojourn time (default 5ms)
|
||||
interval : width of moving time window (default 100ms)
|
||||
|
||||
Based on initial work from Dave Taht.
|
||||
|
||||
Refactored to help future codel inclusion as a plugin for other linux
|
||||
qdisc (FQ_CODEL, ...), like RED.
|
||||
|
||||
include/net/codel.h contains codel algorithm as close as possible than
|
||||
Kathleen reference.
|
||||
|
||||
net/sched/sch_codel.c contains the linux qdisc specific glue.
|
||||
|
||||
Separate structures permit a memory efficient implementation of fq_codel
|
||||
(to be sent as a separate work) : Each flow has its own struct
|
||||
codel_vars.
|
||||
|
||||
timestamps are taken at enqueue() time with 1024 ns precision, allowing
|
||||
a range of 2199 seconds in queue, and 100Gb links support. iproute2 uses
|
||||
usec as base unit.
|
||||
|
||||
Selected packets are dropped, unless ECN is enabled and packets can get
|
||||
ECN mark instead.
|
||||
|
||||
Tested from 2Mb to 10Gb speeds with no particular problems, on ixgbe and
|
||||
tg3 drivers (BQL enabled).
|
||||
|
||||
Usage: tc qdisc ... codel [ limit PACKETS ] [ target TIME ]
|
||||
[ interval TIME ] [ ecn ]
|
||||
|
||||
qdisc codel 10: parent 1:1 limit 2000p target 3.0ms interval 60.0ms ecn
|
||||
Sent 13347099587 bytes 8815805 pkt (dropped 0, overlimits 0 requeues 0)
|
||||
rate 202365Kbit 16708pps backlog 113550b 75p requeues 0
|
||||
count 116 lastcount 98 ldelay 4.3ms dropping drop_next 816us
|
||||
maxpacket 1514 ecn_mark 84399 drop_overlimit 0
|
||||
|
||||
CoDel must be seen as a base module, and should be used keeping in mind
|
||||
there is still a FIFO queue. So a typical setup will probably need a
|
||||
hierarchy of several qdiscs and packet classifiers to be able to meet
|
||||
whatever constraints a user might have.
|
||||
|
||||
One possible example would be to use fq_codel, which combines Fair
|
||||
Queueing and CoDel, in replacement of sfq / sfq_red.
|
||||
|
||||
Signed-off-by: Eric Dumazet <edumazet@google.com>
|
||||
Signed-off-by: Dave Taht <dave.taht@bufferbloat.net>
|
||||
Cc: Kathleen Nichols <nichols@pollere.com>
|
||||
Cc: Van Jacobson <van@pollere.net>
|
||||
Cc: Tom Herbert <therbert@google.com>
|
||||
Cc: Matt Mathis <mattmathis@google.com>
|
||||
Cc: Yuchung Cheng <ycheng@google.com>
|
||||
Cc: Stephen Hemminger <shemminger@vyatta.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
include/linux/pkt_sched.h | 26 ++++
|
||||
include/net/codel.h | 332 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
net/sched/Kconfig | 11 ++
|
||||
net/sched/Makefile | 1 +
|
||||
net/sched/sch_codel.c | 275 +++++++++++++++++++++++++++++++++++++
|
||||
5 files changed, 645 insertions(+)
|
||||
create mode 100644 include/net/codel.h
|
||||
create mode 100644 net/sched/sch_codel.c
|
||||
|
||||
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
|
||||
index ffe975c..cde56c2 100644
|
||||
--- a/include/linux/pkt_sched.h
|
||||
+++ b/include/linux/pkt_sched.h
|
||||
@@ -655,4 +655,30 @@ struct tc_qfq_stats {
|
||||
__u32 lmax;
|
||||
};
|
||||
|
||||
+/* CODEL */
|
||||
+
|
||||
+enum {
|
||||
+ TCA_CODEL_UNSPEC,
|
||||
+ TCA_CODEL_TARGET,
|
||||
+ TCA_CODEL_LIMIT,
|
||||
+ TCA_CODEL_INTERVAL,
|
||||
+ TCA_CODEL_ECN,
|
||||
+ __TCA_CODEL_MAX
|
||||
+};
|
||||
+
|
||||
+#define TCA_CODEL_MAX (__TCA_CODEL_MAX - 1)
|
||||
+
|
||||
+struct tc_codel_xstats {
|
||||
+ __u32 maxpacket; /* largest packet we've seen so far */
|
||||
+ __u32 count; /* how many drops we've done since the last time we
|
||||
+ * entered dropping state
|
||||
+ */
|
||||
+ __u32 lastcount; /* count at entry to dropping state */
|
||||
+ __u32 ldelay; /* in-queue delay seen by most recently dequeued packet */
|
||||
+ __s32 drop_next; /* time to drop next packet */
|
||||
+ __u32 drop_overlimit; /* number of time max qdisc packet limit was hit */
|
||||
+ __u32 ecn_mark; /* number of packets we ECN marked instead of dropped */
|
||||
+ __u32 dropping; /* are we in dropping state ? */
|
||||
+};
|
||||
+
|
||||
#endif
|
||||
diff --git a/include/net/codel.h b/include/net/codel.h
|
||||
new file mode 100644
|
||||
index 0000000..bce2cef
|
||||
--- /dev/null
|
||||
+++ b/include/net/codel.h
|
||||
@@ -0,0 +1,332 @@
|
||||
+#ifndef __NET_SCHED_CODEL_H
|
||||
+#define __NET_SCHED_CODEL_H
|
||||
+
|
||||
+/*
|
||||
+ * Codel - The Controlled-Delay Active Queue Management algorithm
|
||||
+ *
|
||||
+ * Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
|
||||
+ * Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
|
||||
+ * Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
|
||||
+ * Copyright (C) 2012 Eric Dumazet <edumazet@google.com>
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions, and the following disclaimer,
|
||||
+ * without modification.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 3. The names of the authors may not be used to endorse or promote products
|
||||
+ * derived from this software without specific prior written permission.
|
||||
+ *
|
||||
+ * Alternatively, provided that this notice is retained in full, this
|
||||
+ * software may be distributed under the terms of the GNU General
|
||||
+ * Public License ("GPL") version 2, in which case the provisions of the
|
||||
+ * GPL apply INSTEAD OF those given above.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
+ * DAMAGE.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/ktime.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <net/pkt_sched.h>
|
||||
+#include <net/inet_ecn.h>
|
||||
+
|
||||
+/* Controlling Queue Delay (CoDel) algorithm
|
||||
+ * =========================================
|
||||
+ * Source : Kathleen Nichols and Van Jacobson
|
||||
+ * http://queue.acm.org/detail.cfm?id=2209336
|
||||
+ *
|
||||
+ * Implemented on linux by Dave Taht and Eric Dumazet
|
||||
+ */
|
||||
+
|
||||
+
|
||||
+/* CoDel uses a 1024 nsec clock, encoded in u32
|
||||
+ * This gives a range of 2199 seconds, because of signed compares
|
||||
+ */
|
||||
+typedef u32 codel_time_t;
|
||||
+typedef s32 codel_tdiff_t;
|
||||
+#define CODEL_SHIFT 10
|
||||
+#define MS2TIME(a) ((a * NSEC_PER_MSEC) >> CODEL_SHIFT)
|
||||
+
|
||||
+static inline codel_time_t codel_get_time(void)
|
||||
+{
|
||||
+ u64 ns = ktime_to_ns(ktime_get());
|
||||
+
|
||||
+ return ns >> CODEL_SHIFT;
|
||||
+}
|
||||
+
|
||||
+#define codel_time_after(a, b) ((s32)(a) - (s32)(b) > 0)
|
||||
+#define codel_time_after_eq(a, b) ((s32)(a) - (s32)(b) >= 0)
|
||||
+#define codel_time_before(a, b) ((s32)(a) - (s32)(b) < 0)
|
||||
+#define codel_time_before_eq(a, b) ((s32)(a) - (s32)(b) <= 0)
|
||||
+
|
||||
+/* Qdiscs using codel plugin must use codel_skb_cb in their own cb[] */
|
||||
+struct codel_skb_cb {
|
||||
+ codel_time_t enqueue_time;
|
||||
+};
|
||||
+
|
||||
+static struct codel_skb_cb *get_codel_cb(const struct sk_buff *skb)
|
||||
+{
|
||||
+ qdisc_cb_private_validate(skb, sizeof(struct codel_skb_cb));
|
||||
+ return (struct codel_skb_cb *)qdisc_skb_cb(skb)->data;
|
||||
+}
|
||||
+
|
||||
+static codel_time_t codel_get_enqueue_time(const struct sk_buff *skb)
|
||||
+{
|
||||
+ return get_codel_cb(skb)->enqueue_time;
|
||||
+}
|
||||
+
|
||||
+static void codel_set_enqueue_time(struct sk_buff *skb)
|
||||
+{
|
||||
+ get_codel_cb(skb)->enqueue_time = codel_get_time();
|
||||
+}
|
||||
+
|
||||
+static inline u32 codel_time_to_us(codel_time_t val)
|
||||
+{
|
||||
+ u64 valns = ((u64)val << CODEL_SHIFT);
|
||||
+
|
||||
+ do_div(valns, NSEC_PER_USEC);
|
||||
+ return (u32)valns;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * struct codel_params - contains codel parameters
|
||||
+ * @target: target queue size (in time units)
|
||||
+ * @interval: width of moving time window
|
||||
+ * @ecn: is Explicit Congestion Notification enabled
|
||||
+ */
|
||||
+struct codel_params {
|
||||
+ codel_time_t target;
|
||||
+ codel_time_t interval;
|
||||
+ bool ecn;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct codel_vars - contains codel variables
|
||||
+ * @count: how many drops we've done since the last time we
|
||||
+ * entered dropping state
|
||||
+ * @lastcount: count at entry to dropping state
|
||||
+ * @dropping: set to true if in dropping state
|
||||
+ * @first_above_time: when we went (or will go) continuously above target
|
||||
+ * for interval
|
||||
+ * @drop_next: time to drop next packet, or when we dropped last
|
||||
+ * @ldelay: sojourn time of last dequeued packet
|
||||
+ */
|
||||
+struct codel_vars {
|
||||
+ u32 count;
|
||||
+ u32 lastcount;
|
||||
+ bool dropping;
|
||||
+ codel_time_t first_above_time;
|
||||
+ codel_time_t drop_next;
|
||||
+ codel_time_t ldelay;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct codel_stats - contains codel shared variables and stats
|
||||
+ * @maxpacket: largest packet we've seen so far
|
||||
+ * @drop_count: temp count of dropped packets in dequeue()
|
||||
+ * ecn_mark: number of packets we ECN marked instead of dropping
|
||||
+ */
|
||||
+struct codel_stats {
|
||||
+ u32 maxpacket;
|
||||
+ u32 drop_count;
|
||||
+ u32 ecn_mark;
|
||||
+};
|
||||
+
|
||||
+static void codel_params_init(struct codel_params *params)
|
||||
+{
|
||||
+ params->interval = MS2TIME(100);
|
||||
+ params->target = MS2TIME(5);
|
||||
+ params->ecn = false;
|
||||
+}
|
||||
+
|
||||
+static void codel_vars_init(struct codel_vars *vars)
|
||||
+{
|
||||
+ vars->drop_next = 0;
|
||||
+ vars->first_above_time = 0;
|
||||
+ vars->dropping = false; /* exit dropping state */
|
||||
+ vars->count = 0;
|
||||
+ vars->lastcount = 0;
|
||||
+}
|
||||
+
|
||||
+static void codel_stats_init(struct codel_stats *stats)
|
||||
+{
|
||||
+ stats->maxpacket = 256;
|
||||
+}
|
||||
+
|
||||
+/* return interval/sqrt(x) with good precision
|
||||
+ * relies on int_sqrt(unsigned long x) kernel implementation
|
||||
+ */
|
||||
+static u32 codel_inv_sqrt(u32 _interval, u32 _x)
|
||||
+{
|
||||
+ u64 interval = _interval;
|
||||
+ unsigned long x = _x;
|
||||
+
|
||||
+ /* Scale operands for max precision */
|
||||
+
|
||||
+#if BITS_PER_LONG == 64
|
||||
+ x <<= 32; /* On 64bit arches, we can prescale x by 32bits */
|
||||
+ interval <<= 16;
|
||||
+#endif
|
||||
+
|
||||
+ while (x < (1UL << (BITS_PER_LONG - 2))) {
|
||||
+ x <<= 2;
|
||||
+ interval <<= 1;
|
||||
+ }
|
||||
+ do_div(interval, int_sqrt(x));
|
||||
+ return (u32)interval;
|
||||
+}
|
||||
+
|
||||
+static codel_time_t codel_control_law(codel_time_t t,
|
||||
+ codel_time_t interval,
|
||||
+ u32 count)
|
||||
+{
|
||||
+ return t + codel_inv_sqrt(interval, count);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static bool codel_should_drop(struct sk_buff *skb,
|
||||
+ unsigned int *backlog,
|
||||
+ struct codel_vars *vars,
|
||||
+ struct codel_params *params,
|
||||
+ struct codel_stats *stats,
|
||||
+ codel_time_t now)
|
||||
+{
|
||||
+ bool ok_to_drop;
|
||||
+
|
||||
+ if (!skb) {
|
||||
+ vars->first_above_time = 0;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ vars->ldelay = now - codel_get_enqueue_time(skb);
|
||||
+ *backlog -= qdisc_pkt_len(skb);
|
||||
+
|
||||
+ if (unlikely(qdisc_pkt_len(skb) > stats->maxpacket))
|
||||
+ stats->maxpacket = qdisc_pkt_len(skb);
|
||||
+
|
||||
+ if (codel_time_before(vars->ldelay, params->target) ||
|
||||
+ *backlog <= stats->maxpacket) {
|
||||
+ /* went below - stay below for at least interval */
|
||||
+ vars->first_above_time = 0;
|
||||
+ return false;
|
||||
+ }
|
||||
+ ok_to_drop = false;
|
||||
+ if (vars->first_above_time == 0) {
|
||||
+ /* just went above from below. If we stay above
|
||||
+ * for at least interval we'll say it's ok to drop
|
||||
+ */
|
||||
+ vars->first_above_time = now + params->interval;
|
||||
+ } else if (codel_time_after(now, vars->first_above_time)) {
|
||||
+ ok_to_drop = true;
|
||||
+ }
|
||||
+ return ok_to_drop;
|
||||
+}
|
||||
+
|
||||
+typedef struct sk_buff * (*codel_skb_dequeue_t)(struct codel_vars *vars,
|
||||
+ struct Qdisc *sch);
|
||||
+
|
||||
+static struct sk_buff *codel_dequeue(struct Qdisc *sch,
|
||||
+ struct codel_params *params,
|
||||
+ struct codel_vars *vars,
|
||||
+ struct codel_stats *stats,
|
||||
+ codel_skb_dequeue_t dequeue_func,
|
||||
+ u32 *backlog)
|
||||
+{
|
||||
+ struct sk_buff *skb = dequeue_func(vars, sch);
|
||||
+ codel_time_t now;
|
||||
+ bool drop;
|
||||
+
|
||||
+ if (!skb) {
|
||||
+ vars->dropping = false;
|
||||
+ return skb;
|
||||
+ }
|
||||
+ now = codel_get_time();
|
||||
+ drop = codel_should_drop(skb, backlog, vars, params, stats, now);
|
||||
+ if (vars->dropping) {
|
||||
+ if (!drop) {
|
||||
+ /* sojourn time below target - leave dropping state */
|
||||
+ vars->dropping = false;
|
||||
+ } else if (codel_time_after_eq(now, vars->drop_next)) {
|
||||
+ /* It's time for the next drop. Drop the current
|
||||
+ * packet and dequeue the next. The dequeue might
|
||||
+ * take us out of dropping state.
|
||||
+ * If not, schedule the next drop.
|
||||
+ * A large backlog might result in drop rates so high
|
||||
+ * that the next drop should happen now,
|
||||
+ * hence the while loop.
|
||||
+ */
|
||||
+ while (vars->dropping &&
|
||||
+ codel_time_after_eq(now, vars->drop_next)) {
|
||||
+ if (++vars->count == 0) /* avoid zero divides */
|
||||
+ vars->count = ~0U;
|
||||
+ if (params->ecn && INET_ECN_set_ce(skb)) {
|
||||
+ stats->ecn_mark++;
|
||||
+ vars->drop_next =
|
||||
+ codel_control_law(vars->drop_next,
|
||||
+ params->interval,
|
||||
+ vars->count);
|
||||
+ goto end;
|
||||
+ }
|
||||
+ qdisc_drop(skb, sch);
|
||||
+ stats->drop_count++;
|
||||
+ skb = dequeue_func(vars, sch);
|
||||
+ if (!codel_should_drop(skb, backlog,
|
||||
+ vars, params, stats, now)) {
|
||||
+ /* leave dropping state */
|
||||
+ vars->dropping = false;
|
||||
+ } else {
|
||||
+ /* and schedule the next drop */
|
||||
+ vars->drop_next =
|
||||
+ codel_control_law(vars->drop_next,
|
||||
+ params->interval,
|
||||
+ vars->count);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ } else if (drop) {
|
||||
+ if (params->ecn && INET_ECN_set_ce(skb)) {
|
||||
+ stats->ecn_mark++;
|
||||
+ } else {
|
||||
+ qdisc_drop(skb, sch);
|
||||
+ stats->drop_count++;
|
||||
+
|
||||
+ skb = dequeue_func(vars, sch);
|
||||
+ drop = codel_should_drop(skb, backlog, vars, params,
|
||||
+ stats, now);
|
||||
+ }
|
||||
+ vars->dropping = true;
|
||||
+ /* if min went above target close to when we last went below it
|
||||
+ * assume that the drop rate that controlled the queue on the
|
||||
+ * last cycle is a good starting point to control it now.
|
||||
+ */
|
||||
+ if (codel_time_before(now - vars->drop_next,
|
||||
+ 16 * params->interval)) {
|
||||
+ vars->count = (vars->count - vars->lastcount) | 1;
|
||||
+ } else {
|
||||
+ vars->count = 1;
|
||||
+ }
|
||||
+ vars->lastcount = vars->count;
|
||||
+ vars->drop_next = codel_control_law(now, params->interval,
|
||||
+ vars->count);
|
||||
+ }
|
||||
+end:
|
||||
+ return skb;
|
||||
+}
|
||||
+#endif
|
||||
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
|
||||
index 75b58f8..fadd252 100644
|
||||
--- a/net/sched/Kconfig
|
||||
+++ b/net/sched/Kconfig
|
||||
@@ -250,6 +250,17 @@ config NET_SCH_QFQ
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
+config NET_SCH_CODEL
|
||||
+ tristate "Controlled Delay AQM (CODEL)"
|
||||
+ help
|
||||
+ Say Y here if you want to use the Controlled Delay (CODEL)
|
||||
+ packet scheduling algorithm.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the module
|
||||
+ will be called sch_codel.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
config NET_SCH_INGRESS
|
||||
tristate "Ingress Qdisc"
|
||||
depends on NET_CLS_ACT
|
||||
diff --git a/net/sched/Makefile b/net/sched/Makefile
|
||||
index 8cdf4e2..30fab03 100644
|
||||
--- a/net/sched/Makefile
|
||||
+++ b/net/sched/Makefile
|
||||
@@ -37,6 +37,7 @@ obj-$(CONFIG_NET_SCH_PLUG) += sch_plug.o
|
||||
obj-$(CONFIG_NET_SCH_MQPRIO) += sch_mqprio.o
|
||||
obj-$(CONFIG_NET_SCH_CHOKE) += sch_choke.o
|
||||
obj-$(CONFIG_NET_SCH_QFQ) += sch_qfq.o
|
||||
+obj-$(CONFIG_NET_SCH_CODEL) += sch_codel.o
|
||||
|
||||
obj-$(CONFIG_NET_CLS_U32) += cls_u32.o
|
||||
obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o
|
||||
diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c
|
||||
new file mode 100644
|
||||
index 0000000..b4a1a81
|
||||
--- /dev/null
|
||||
+++ b/net/sched/sch_codel.c
|
||||
@@ -0,0 +1,275 @@
|
||||
+/*
|
||||
+ * Codel - The Controlled-Delay Active Queue Management algorithm
|
||||
+ *
|
||||
+ * Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
|
||||
+ * Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
|
||||
+ *
|
||||
+ * Implemented on linux by :
|
||||
+ * Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
|
||||
+ * Copyright (C) 2012 Eric Dumazet <edumazet@google.com>
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions, and the following disclaimer,
|
||||
+ * without modification.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 3. The names of the authors may not be used to endorse or promote products
|
||||
+ * derived from this software without specific prior written permission.
|
||||
+ *
|
||||
+ * Alternatively, provided that this notice is retained in full, this
|
||||
+ * software may be distributed under the terms of the GNU General
|
||||
+ * Public License ("GPL") version 2, in which case the provisions of the
|
||||
+ * GPL apply INSTEAD OF those given above.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
+ * DAMAGE.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <net/pkt_sched.h>
|
||||
+#include <net/codel.h>
|
||||
+
|
||||
+
|
||||
+#define DEFAULT_CODEL_LIMIT 1000
|
||||
+
|
||||
+struct codel_sched_data {
|
||||
+ struct codel_params params;
|
||||
+ struct codel_vars vars;
|
||||
+ struct codel_stats stats;
|
||||
+ u32 drop_overlimit;
|
||||
+};
|
||||
+
|
||||
+/* This is the specific function called from codel_dequeue()
|
||||
+ * to dequeue a packet from queue. Note: backlog is handled in
|
||||
+ * codel, we dont need to reduce it here.
|
||||
+ */
|
||||
+static struct sk_buff *dequeue(struct codel_vars *vars, struct Qdisc *sch)
|
||||
+{
|
||||
+ struct sk_buff *skb = __skb_dequeue(&sch->q);
|
||||
+
|
||||
+ prefetch(&skb->end); /* we'll need skb_shinfo() */
|
||||
+ return skb;
|
||||
+}
|
||||
+
|
||||
+static struct sk_buff *codel_qdisc_dequeue(struct Qdisc *sch)
|
||||
+{
|
||||
+ struct codel_sched_data *q = qdisc_priv(sch);
|
||||
+ struct sk_buff *skb;
|
||||
+
|
||||
+ skb = codel_dequeue(sch, &q->params, &q->vars, &q->stats,
|
||||
+ dequeue, &sch->qstats.backlog);
|
||||
+ /* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
|
||||
+ * or HTB crashes. Defer it for next round.
|
||||
+ */
|
||||
+ if (q->stats.drop_count && sch->q.qlen) {
|
||||
+ qdisc_tree_decrease_qlen(sch, q->stats.drop_count);
|
||||
+ q->stats.drop_count = 0;
|
||||
+ }
|
||||
+ if (skb)
|
||||
+ qdisc_bstats_update(sch, skb);
|
||||
+ return skb;
|
||||
+}
|
||||
+
|
||||
+static int codel_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
|
||||
+{
|
||||
+ struct codel_sched_data *q;
|
||||
+
|
||||
+ if (likely(qdisc_qlen(sch) < sch->limit)) {
|
||||
+ codel_set_enqueue_time(skb);
|
||||
+ return qdisc_enqueue_tail(skb, sch);
|
||||
+ }
|
||||
+ q = qdisc_priv(sch);
|
||||
+ q->drop_overlimit++;
|
||||
+ return qdisc_drop(skb, sch);
|
||||
+}
|
||||
+
|
||||
+static const struct nla_policy codel_policy[TCA_CODEL_MAX + 1] = {
|
||||
+ [TCA_CODEL_TARGET] = { .type = NLA_U32 },
|
||||
+ [TCA_CODEL_LIMIT] = { .type = NLA_U32 },
|
||||
+ [TCA_CODEL_INTERVAL] = { .type = NLA_U32 },
|
||||
+ [TCA_CODEL_ECN] = { .type = NLA_U32 },
|
||||
+};
|
||||
+
|
||||
+static int codel_change(struct Qdisc *sch, struct nlattr *opt)
|
||||
+{
|
||||
+ struct codel_sched_data *q = qdisc_priv(sch);
|
||||
+ struct nlattr *tb[TCA_CODEL_MAX + 1];
|
||||
+ unsigned int qlen;
|
||||
+ int err;
|
||||
+
|
||||
+ if (!opt)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ err = nla_parse_nested(tb, TCA_CODEL_MAX, opt, codel_policy);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ sch_tree_lock(sch);
|
||||
+
|
||||
+ if (tb[TCA_CODEL_TARGET]) {
|
||||
+ u32 target = nla_get_u32(tb[TCA_CODEL_TARGET]);
|
||||
+
|
||||
+ q->params.target = ((u64)target * NSEC_PER_USEC) >> CODEL_SHIFT;
|
||||
+ }
|
||||
+
|
||||
+ if (tb[TCA_CODEL_INTERVAL]) {
|
||||
+ u32 interval = nla_get_u32(tb[TCA_CODEL_INTERVAL]);
|
||||
+
|
||||
+ q->params.interval = ((u64)interval * NSEC_PER_USEC) >> CODEL_SHIFT;
|
||||
+ }
|
||||
+
|
||||
+ if (tb[TCA_CODEL_LIMIT])
|
||||
+ sch->limit = nla_get_u32(tb[TCA_CODEL_LIMIT]);
|
||||
+
|
||||
+ if (tb[TCA_CODEL_ECN])
|
||||
+ q->params.ecn = !!nla_get_u32(tb[TCA_CODEL_ECN]);
|
||||
+
|
||||
+ qlen = sch->q.qlen;
|
||||
+ while (sch->q.qlen > sch->limit) {
|
||||
+ struct sk_buff *skb = __skb_dequeue(&sch->q);
|
||||
+
|
||||
+ sch->qstats.backlog -= qdisc_pkt_len(skb);
|
||||
+ qdisc_drop(skb, sch);
|
||||
+ }
|
||||
+ qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
|
||||
+
|
||||
+ sch_tree_unlock(sch);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int codel_init(struct Qdisc *sch, struct nlattr *opt)
|
||||
+{
|
||||
+ struct codel_sched_data *q = qdisc_priv(sch);
|
||||
+
|
||||
+ sch->limit = DEFAULT_CODEL_LIMIT;
|
||||
+
|
||||
+ codel_params_init(&q->params);
|
||||
+ codel_vars_init(&q->vars);
|
||||
+ codel_stats_init(&q->stats);
|
||||
+
|
||||
+ if (opt) {
|
||||
+ int err = codel_change(sch, opt);
|
||||
+
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ if (sch->limit >= 1)
|
||||
+ sch->flags |= TCQ_F_CAN_BYPASS;
|
||||
+ else
|
||||
+ sch->flags &= ~TCQ_F_CAN_BYPASS;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int codel_dump(struct Qdisc *sch, struct sk_buff *skb)
|
||||
+{
|
||||
+ struct codel_sched_data *q = qdisc_priv(sch);
|
||||
+ struct nlattr *opts;
|
||||
+
|
||||
+ opts = nla_nest_start(skb, TCA_OPTIONS);
|
||||
+ if (opts == NULL)
|
||||
+ goto nla_put_failure;
|
||||
+
|
||||
+ if (nla_put_u32(skb, TCA_CODEL_TARGET,
|
||||
+ codel_time_to_us(q->params.target)) ||
|
||||
+ nla_put_u32(skb, TCA_CODEL_LIMIT,
|
||||
+ sch->limit) ||
|
||||
+ nla_put_u32(skb, TCA_CODEL_INTERVAL,
|
||||
+ codel_time_to_us(q->params.interval)) ||
|
||||
+ nla_put_u32(skb, TCA_CODEL_ECN,
|
||||
+ q->params.ecn))
|
||||
+ goto nla_put_failure;
|
||||
+
|
||||
+ return nla_nest_end(skb, opts);
|
||||
+
|
||||
+nla_put_failure:
|
||||
+ nla_nest_cancel(skb, opts);
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static int codel_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
|
||||
+{
|
||||
+ const struct codel_sched_data *q = qdisc_priv(sch);
|
||||
+ struct tc_codel_xstats st = {
|
||||
+ .maxpacket = q->stats.maxpacket,
|
||||
+ .count = q->vars.count,
|
||||
+ .lastcount = q->vars.lastcount,
|
||||
+ .drop_overlimit = q->drop_overlimit,
|
||||
+ .ldelay = codel_time_to_us(q->vars.ldelay),
|
||||
+ .dropping = q->vars.dropping,
|
||||
+ .ecn_mark = q->stats.ecn_mark,
|
||||
+ };
|
||||
+
|
||||
+ if (q->vars.dropping) {
|
||||
+ codel_tdiff_t delta = q->vars.drop_next - codel_get_time();
|
||||
+
|
||||
+ if (delta >= 0)
|
||||
+ st.drop_next = codel_time_to_us(delta);
|
||||
+ else
|
||||
+ st.drop_next = -codel_time_to_us(-delta);
|
||||
+ }
|
||||
+
|
||||
+ return gnet_stats_copy_app(d, &st, sizeof(st));
|
||||
+}
|
||||
+
|
||||
+static void codel_reset(struct Qdisc *sch)
|
||||
+{
|
||||
+ struct codel_sched_data *q = qdisc_priv(sch);
|
||||
+
|
||||
+ qdisc_reset_queue(sch);
|
||||
+ codel_vars_init(&q->vars);
|
||||
+}
|
||||
+
|
||||
+static struct Qdisc_ops codel_qdisc_ops __read_mostly = {
|
||||
+ .id = "codel",
|
||||
+ .priv_size = sizeof(struct codel_sched_data),
|
||||
+
|
||||
+ .enqueue = codel_qdisc_enqueue,
|
||||
+ .dequeue = codel_qdisc_dequeue,
|
||||
+ .peek = qdisc_peek_dequeued,
|
||||
+ .init = codel_init,
|
||||
+ .reset = codel_reset,
|
||||
+ .change = codel_change,
|
||||
+ .dump = codel_dump,
|
||||
+ .dump_stats = codel_dump_stats,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static int __init codel_module_init(void)
|
||||
+{
|
||||
+ return register_qdisc(&codel_qdisc_ops);
|
||||
+}
|
||||
+
|
||||
+static void __exit codel_module_exit(void)
|
||||
+{
|
||||
+ unregister_qdisc(&codel_qdisc_ops);
|
||||
+}
|
||||
+
|
||||
+module_init(codel_module_init)
|
||||
+module_exit(codel_module_exit)
|
||||
+
|
||||
+MODULE_DESCRIPTION("Controlled Delay queue discipline");
|
||||
+MODULE_AUTHOR("Dave Taht");
|
||||
+MODULE_AUTHOR("Eric Dumazet");
|
||||
+MODULE_LICENSE("Dual BSD/GPL");
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,189 +0,0 @@
|
|||
From: Eric Dumazet <edumazet@google.com>
|
||||
Date: Sat, 12 May 2012 03:32:13 +0000
|
||||
Subject: [PATCH 2/7] codel: use Newton method instead of sqrt() and divides
|
||||
|
||||
commit 536edd67109df5e0cdb2c4ee759e9bade7976367 upstream.
|
||||
|
||||
As Van pointed out, interval/sqrt(count) can be implemented using
|
||||
multiplies only.
|
||||
|
||||
http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
|
||||
|
||||
This patch implements the Newton method and reciprocal divide.
|
||||
|
||||
Total cost is 15 cycles instead of 120 on my Corei5 machine (64bit
|
||||
kernel).
|
||||
|
||||
There is a small 'error' for count values < 5, but we don't really care.
|
||||
|
||||
I reuse a hole in struct codel_vars :
|
||||
- pack the dropping boolean into one bit
|
||||
- use 31bit to store the reciprocal value of sqrt(count).
|
||||
|
||||
Suggested-by: Van Jacobson <van@pollere.net>
|
||||
Signed-off-by: Eric Dumazet <edumazet@google.com>
|
||||
Cc: Dave Taht <dave.taht@bufferbloat.net>
|
||||
Cc: Kathleen Nichols <nichols@pollere.com>
|
||||
Cc: Tom Herbert <therbert@google.com>
|
||||
Cc: Matt Mathis <mattmathis@google.com>
|
||||
Cc: Yuchung Cheng <ycheng@google.com>
|
||||
Cc: Nandita Dukkipati <nanditad@google.com>
|
||||
Cc: Stephen Hemminger <shemminger@vyatta.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
include/net/codel.h | 68 ++++++++++++++++++++++++++++-----------------------
|
||||
1 file changed, 37 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/include/net/codel.h b/include/net/codel.h
|
||||
index bce2cef..bd8747c 100644
|
||||
--- a/include/net/codel.h
|
||||
+++ b/include/net/codel.h
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/inet_ecn.h>
|
||||
+#include <linux/reciprocal_div.h>
|
||||
|
||||
/* Controlling Queue Delay (CoDel) algorithm
|
||||
* =========================================
|
||||
@@ -123,6 +124,7 @@ struct codel_params {
|
||||
* entered dropping state
|
||||
* @lastcount: count at entry to dropping state
|
||||
* @dropping: set to true if in dropping state
|
||||
+ * @rec_inv_sqrt: reciprocal value of sqrt(count) >> 1
|
||||
* @first_above_time: when we went (or will go) continuously above target
|
||||
* for interval
|
||||
* @drop_next: time to drop next packet, or when we dropped last
|
||||
@@ -131,7 +133,8 @@ struct codel_params {
|
||||
struct codel_vars {
|
||||
u32 count;
|
||||
u32 lastcount;
|
||||
- bool dropping;
|
||||
+ bool dropping:1;
|
||||
+ u32 rec_inv_sqrt:31;
|
||||
codel_time_t first_above_time;
|
||||
codel_time_t drop_next;
|
||||
codel_time_t ldelay;
|
||||
@@ -158,11 +161,7 @@ static void codel_params_init(struct codel_params *params)
|
||||
|
||||
static void codel_vars_init(struct codel_vars *vars)
|
||||
{
|
||||
- vars->drop_next = 0;
|
||||
- vars->first_above_time = 0;
|
||||
- vars->dropping = false; /* exit dropping state */
|
||||
- vars->count = 0;
|
||||
- vars->lastcount = 0;
|
||||
+ memset(vars, 0, sizeof(*vars));
|
||||
}
|
||||
|
||||
static void codel_stats_init(struct codel_stats *stats)
|
||||
@@ -170,38 +169,37 @@ static void codel_stats_init(struct codel_stats *stats)
|
||||
stats->maxpacket = 256;
|
||||
}
|
||||
|
||||
-/* return interval/sqrt(x) with good precision
|
||||
- * relies on int_sqrt(unsigned long x) kernel implementation
|
||||
+/*
|
||||
+ * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
|
||||
+ * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2)
|
||||
+ *
|
||||
+ * Here, invsqrt is a fixed point number (< 1.0), 31bit mantissa)
|
||||
*/
|
||||
-static u32 codel_inv_sqrt(u32 _interval, u32 _x)
|
||||
+static void codel_Newton_step(struct codel_vars *vars)
|
||||
{
|
||||
- u64 interval = _interval;
|
||||
- unsigned long x = _x;
|
||||
+ u32 invsqrt = vars->rec_inv_sqrt;
|
||||
+ u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 31;
|
||||
+ u64 val = (3LL << 31) - ((u64)vars->count * invsqrt2);
|
||||
|
||||
- /* Scale operands for max precision */
|
||||
-
|
||||
-#if BITS_PER_LONG == 64
|
||||
- x <<= 32; /* On 64bit arches, we can prescale x by 32bits */
|
||||
- interval <<= 16;
|
||||
-#endif
|
||||
+ val = (val * invsqrt) >> 32;
|
||||
|
||||
- while (x < (1UL << (BITS_PER_LONG - 2))) {
|
||||
- x <<= 2;
|
||||
- interval <<= 1;
|
||||
- }
|
||||
- do_div(interval, int_sqrt(x));
|
||||
- return (u32)interval;
|
||||
+ vars->rec_inv_sqrt = val;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * CoDel control_law is t + interval/sqrt(count)
|
||||
+ * We maintain in rec_inv_sqrt the reciprocal value of sqrt(count) to avoid
|
||||
+ * both sqrt() and divide operation.
|
||||
+ */
|
||||
static codel_time_t codel_control_law(codel_time_t t,
|
||||
codel_time_t interval,
|
||||
- u32 count)
|
||||
+ u32 rec_inv_sqrt)
|
||||
{
|
||||
- return t + codel_inv_sqrt(interval, count);
|
||||
+ return t + reciprocal_divide(interval, rec_inv_sqrt << 1);
|
||||
}
|
||||
|
||||
|
||||
-static bool codel_should_drop(struct sk_buff *skb,
|
||||
+static bool codel_should_drop(const struct sk_buff *skb,
|
||||
unsigned int *backlog,
|
||||
struct codel_vars *vars,
|
||||
struct codel_params *params,
|
||||
@@ -274,14 +272,16 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
|
||||
*/
|
||||
while (vars->dropping &&
|
||||
codel_time_after_eq(now, vars->drop_next)) {
|
||||
- if (++vars->count == 0) /* avoid zero divides */
|
||||
- vars->count = ~0U;
|
||||
+ vars->count++; /* dont care of possible wrap
|
||||
+ * since there is no more divide
|
||||
+ */
|
||||
+ codel_Newton_step(vars);
|
||||
if (params->ecn && INET_ECN_set_ce(skb)) {
|
||||
stats->ecn_mark++;
|
||||
vars->drop_next =
|
||||
codel_control_law(vars->drop_next,
|
||||
params->interval,
|
||||
- vars->count);
|
||||
+ vars->rec_inv_sqrt);
|
||||
goto end;
|
||||
}
|
||||
qdisc_drop(skb, sch);
|
||||
@@ -296,7 +296,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
|
||||
vars->drop_next =
|
||||
codel_control_law(vars->drop_next,
|
||||
params->interval,
|
||||
- vars->count);
|
||||
+ vars->rec_inv_sqrt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -319,12 +319,18 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
|
||||
if (codel_time_before(now - vars->drop_next,
|
||||
16 * params->interval)) {
|
||||
vars->count = (vars->count - vars->lastcount) | 1;
|
||||
+ /* we dont care if rec_inv_sqrt approximation
|
||||
+ * is not very precise :
|
||||
+ * Next Newton steps will correct it quadratically.
|
||||
+ */
|
||||
+ codel_Newton_step(vars);
|
||||
} else {
|
||||
vars->count = 1;
|
||||
+ vars->rec_inv_sqrt = 0x7fffffff;
|
||||
}
|
||||
vars->lastcount = vars->count;
|
||||
vars->drop_next = codel_control_law(now, params->interval,
|
||||
- vars->count);
|
||||
+ vars->rec_inv_sqrt);
|
||||
}
|
||||
end:
|
||||
return skb;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,850 +0,0 @@
|
|||
From: Eric Dumazet <edumazet@google.com>
|
||||
Date: Fri, 11 May 2012 09:30:50 +0000
|
||||
Subject: [PATCH 3/7] fq_codel: Fair Queue Codel AQM
|
||||
|
||||
commit 4b549a2ef4bef9965d97cbd992ba67930cd3e0fe upstream.
|
||||
|
||||
Fair Queue Codel packet scheduler
|
||||
|
||||
Principles :
|
||||
|
||||
- Packets are classified (internal classifier or external) on flows.
|
||||
- This is a Stochastic model (as we use a hash, several flows might
|
||||
be hashed on same slot)
|
||||
- Each flow has a CoDel managed queue.
|
||||
- Flows are linked onto two (Round Robin) lists,
|
||||
so that new flows have priority on old ones.
|
||||
|
||||
- For a given flow, packets are not reordered (CoDel uses a FIFO)
|
||||
- head drops only.
|
||||
- ECN capability is on by default.
|
||||
- Very low memory footprint (64 bytes per flow)
|
||||
|
||||
tc qdisc ... fq_codel [ limit PACKETS ] [ flows number ]
|
||||
[ target TIME ] [ interval TIME ] [ noecn ]
|
||||
[ quantum BYTES ]
|
||||
|
||||
defaults : 1024 flows, 10240 packets limit, quantum : device MTU
|
||||
target : 5ms (CoDel default)
|
||||
interval : 100ms (CoDel default)
|
||||
|
||||
Impressive results on load :
|
||||
|
||||
class htb 1:1 root leaf 10: prio 0 quantum 1514 rate 200000Kbit ceil 200000Kbit burst 1475b/8 mpu 0b overhead 0b cburst 1475b/8 mpu 0b overhead 0b level 0
|
||||
Sent 43304920109 bytes 33063109 pkt (dropped 0, overlimits 0 requeues 0)
|
||||
rate 201691Kbit 28595pps backlog 0b 312p requeues 0
|
||||
lended: 33063109 borrowed: 0 giants: 0
|
||||
tokens: -912 ctokens: -912
|
||||
|
||||
class fq_codel 10:1735 parent 10:
|
||||
(dropped 1292, overlimits 0 requeues 0)
|
||||
backlog 15140b 10p requeues 0
|
||||
deficit 1514 count 1 lastcount 1 ldelay 7.1ms
|
||||
class fq_codel 10:4524 parent 10:
|
||||
(dropped 1291, overlimits 0 requeues 0)
|
||||
backlog 16654b 11p requeues 0
|
||||
deficit 1514 count 1 lastcount 1 ldelay 7.1ms
|
||||
class fq_codel 10:4e74 parent 10:
|
||||
(dropped 1290, overlimits 0 requeues 0)
|
||||
backlog 6056b 4p requeues 0
|
||||
deficit 1514 count 1 lastcount 1 ldelay 6.4ms dropping drop_next 92.0ms
|
||||
class fq_codel 10:628a parent 10:
|
||||
(dropped 1289, overlimits 0 requeues 0)
|
||||
backlog 7570b 5p requeues 0
|
||||
deficit 1514 count 1 lastcount 1 ldelay 5.4ms dropping drop_next 90.9ms
|
||||
class fq_codel 10:a4b3 parent 10:
|
||||
(dropped 302, overlimits 0 requeues 0)
|
||||
backlog 16654b 11p requeues 0
|
||||
deficit 1514 count 1 lastcount 1 ldelay 7.1ms
|
||||
class fq_codel 10:c3c2 parent 10:
|
||||
(dropped 1284, overlimits 0 requeues 0)
|
||||
backlog 13626b 9p requeues 0
|
||||
deficit 1514 count 1 lastcount 1 ldelay 5.9ms
|
||||
class fq_codel 10:d331 parent 10:
|
||||
(dropped 299, overlimits 0 requeues 0)
|
||||
backlog 15140b 10p requeues 0
|
||||
deficit 1514 count 1 lastcount 1 ldelay 7.0ms
|
||||
class fq_codel 10:d526 parent 10:
|
||||
(dropped 12160, overlimits 0 requeues 0)
|
||||
backlog 35870b 211p requeues 0
|
||||
deficit 1508 count 12160 lastcount 1 ldelay 15.3ms dropping drop_next 247us
|
||||
class fq_codel 10:e2c6 parent 10:
|
||||
(dropped 1288, overlimits 0 requeues 0)
|
||||
backlog 15140b 10p requeues 0
|
||||
deficit 1514 count 1 lastcount 1 ldelay 7.1ms
|
||||
class fq_codel 10:eab5 parent 10:
|
||||
(dropped 1285, overlimits 0 requeues 0)
|
||||
backlog 16654b 11p requeues 0
|
||||
deficit 1514 count 1 lastcount 1 ldelay 5.9ms
|
||||
class fq_codel 10:f220 parent 10:
|
||||
(dropped 1289, overlimits 0 requeues 0)
|
||||
backlog 15140b 10p requeues 0
|
||||
deficit 1514 count 1 lastcount 1 ldelay 7.1ms
|
||||
|
||||
qdisc htb 1: root refcnt 6 r2q 10 default 1 direct_packets_stat 0 ver 3.17
|
||||
Sent 43331086547 bytes 33092812 pkt (dropped 0, overlimits 66063544 requeues 71)
|
||||
rate 201697Kbit 28602pps backlog 0b 260p requeues 71
|
||||
qdisc fq_codel 10: parent 1:1 limit 10240p flows 65536 target 5.0ms interval 100.0ms ecn
|
||||
Sent 43331086547 bytes 33092812 pkt (dropped 949359, overlimits 0 requeues 0)
|
||||
rate 201697Kbit 28602pps backlog 189352b 260p requeues 0
|
||||
maxpacket 1514 drop_overlimit 0 new_flow_count 5582 ecn_mark 125593
|
||||
new_flows_len 0 old_flows_len 11
|
||||
|
||||
PING 172.30.42.18 (172.30.42.18) 56(84) bytes of data.
|
||||
64 bytes from 172.30.42.18: icmp_req=1 ttl=64 time=0.227 ms
|
||||
64 bytes from 172.30.42.18: icmp_req=2 ttl=64 time=0.165 ms
|
||||
64 bytes from 172.30.42.18: icmp_req=3 ttl=64 time=0.166 ms
|
||||
64 bytes from 172.30.42.18: icmp_req=4 ttl=64 time=0.151 ms
|
||||
64 bytes from 172.30.42.18: icmp_req=5 ttl=64 time=0.164 ms
|
||||
64 bytes from 172.30.42.18: icmp_req=6 ttl=64 time=0.172 ms
|
||||
64 bytes from 172.30.42.18: icmp_req=7 ttl=64 time=0.175 ms
|
||||
64 bytes from 172.30.42.18: icmp_req=8 ttl=64 time=0.183 ms
|
||||
64 bytes from 172.30.42.18: icmp_req=9 ttl=64 time=0.158 ms
|
||||
64 bytes from 172.30.42.18: icmp_req=10 ttl=64 time=0.200 ms
|
||||
|
||||
10 packets transmitted, 10 received, 0% packet loss, time 8999ms
|
||||
rtt min/avg/max/mdev = 0.151/0.176/0.227/0.022 ms
|
||||
|
||||
Much better than SFQ because of priority given to new flows, and fast
|
||||
path dirtying less cache lines.
|
||||
|
||||
Signed-off-by: Eric Dumazet <edumazet@google.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
include/linux/pkt_sched.h | 54 ++++
|
||||
net/sched/Kconfig | 11 +
|
||||
net/sched/Makefile | 1 +
|
||||
net/sched/sch_fq_codel.c | 624 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 690 insertions(+)
|
||||
create mode 100644 net/sched/sch_fq_codel.c
|
||||
|
||||
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
|
||||
index cde56c2..32aef0a 100644
|
||||
--- a/include/linux/pkt_sched.h
|
||||
+++ b/include/linux/pkt_sched.h
|
||||
@@ -681,4 +681,58 @@ struct tc_codel_xstats {
|
||||
__u32 dropping; /* are we in dropping state ? */
|
||||
};
|
||||
|
||||
+/* FQ_CODEL */
|
||||
+
|
||||
+enum {
|
||||
+ TCA_FQ_CODEL_UNSPEC,
|
||||
+ TCA_FQ_CODEL_TARGET,
|
||||
+ TCA_FQ_CODEL_LIMIT,
|
||||
+ TCA_FQ_CODEL_INTERVAL,
|
||||
+ TCA_FQ_CODEL_ECN,
|
||||
+ TCA_FQ_CODEL_FLOWS,
|
||||
+ TCA_FQ_CODEL_QUANTUM,
|
||||
+ __TCA_FQ_CODEL_MAX
|
||||
+};
|
||||
+
|
||||
+#define TCA_FQ_CODEL_MAX (__TCA_FQ_CODEL_MAX - 1)
|
||||
+
|
||||
+enum {
|
||||
+ TCA_FQ_CODEL_XSTATS_QDISC,
|
||||
+ TCA_FQ_CODEL_XSTATS_CLASS,
|
||||
+};
|
||||
+
|
||||
+struct tc_fq_codel_qd_stats {
|
||||
+ __u32 maxpacket; /* largest packet we've seen so far */
|
||||
+ __u32 drop_overlimit; /* number of time max qdisc
|
||||
+ * packet limit was hit
|
||||
+ */
|
||||
+ __u32 ecn_mark; /* number of packets we ECN marked
|
||||
+ * instead of being dropped
|
||||
+ */
|
||||
+ __u32 new_flow_count; /* number of time packets
|
||||
+ * created a 'new flow'
|
||||
+ */
|
||||
+ __u32 new_flows_len; /* count of flows in new list */
|
||||
+ __u32 old_flows_len; /* count of flows in old list */
|
||||
+};
|
||||
+
|
||||
+struct tc_fq_codel_cl_stats {
|
||||
+ __s32 deficit;
|
||||
+ __u32 ldelay; /* in-queue delay seen by most recently
|
||||
+ * dequeued packet
|
||||
+ */
|
||||
+ __u32 count;
|
||||
+ __u32 lastcount;
|
||||
+ __u32 dropping;
|
||||
+ __s32 drop_next;
|
||||
+};
|
||||
+
|
||||
+struct tc_fq_codel_xstats {
|
||||
+ __u32 type;
|
||||
+ union {
|
||||
+ struct tc_fq_codel_qd_stats qdisc_stats;
|
||||
+ struct tc_fq_codel_cl_stats class_stats;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
#endif
|
||||
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
|
||||
index fadd252..e7a8976 100644
|
||||
--- a/net/sched/Kconfig
|
||||
+++ b/net/sched/Kconfig
|
||||
@@ -261,6 +261,17 @@ config NET_SCH_CODEL
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
+config NET_SCH_FQ_CODEL
|
||||
+ tristate "Fair Queue Controlled Delay AQM (FQ_CODEL)"
|
||||
+ help
|
||||
+ Say Y here if you want to use the FQ Controlled Delay (FQ_CODEL)
|
||||
+ packet scheduling algorithm.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the module
|
||||
+ will be called sch_fq_codel.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
config NET_SCH_INGRESS
|
||||
tristate "Ingress Qdisc"
|
||||
depends on NET_CLS_ACT
|
||||
diff --git a/net/sched/Makefile b/net/sched/Makefile
|
||||
index 30fab03..5940a19 100644
|
||||
--- a/net/sched/Makefile
|
||||
+++ b/net/sched/Makefile
|
||||
@@ -38,6 +38,7 @@ obj-$(CONFIG_NET_SCH_MQPRIO) += sch_mqprio.o
|
||||
obj-$(CONFIG_NET_SCH_CHOKE) += sch_choke.o
|
||||
obj-$(CONFIG_NET_SCH_QFQ) += sch_qfq.o
|
||||
obj-$(CONFIG_NET_SCH_CODEL) += sch_codel.o
|
||||
+obj-$(CONFIG_NET_SCH_FQ_CODEL) += sch_fq_codel.o
|
||||
|
||||
obj-$(CONFIG_NET_CLS_U32) += cls_u32.o
|
||||
obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o
|
||||
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
|
||||
new file mode 100644
|
||||
index 0000000..a7b3754
|
||||
--- /dev/null
|
||||
+++ b/net/sched/sch_fq_codel.c
|
||||
@@ -0,0 +1,624 @@
|
||||
+/*
|
||||
+ * Fair Queue CoDel discipline
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License
|
||||
+ * as published by the Free Software Foundation; either version
|
||||
+ * 2 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * Copyright (C) 2012 Eric Dumazet <edumazet@google.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/jiffies.h>
|
||||
+#include <linux/string.h>
|
||||
+#include <linux/in.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <linux/jhash.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/vmalloc.h>
|
||||
+#include <net/netlink.h>
|
||||
+#include <net/pkt_sched.h>
|
||||
+#include <net/flow_keys.h>
|
||||
+#include <net/codel.h>
|
||||
+
|
||||
+/* Fair Queue CoDel.
|
||||
+ *
|
||||
+ * Principles :
|
||||
+ * Packets are classified (internal classifier or external) on flows.
|
||||
+ * This is a Stochastic model (as we use a hash, several flows
|
||||
+ * might be hashed on same slot)
|
||||
+ * Each flow has a CoDel managed queue.
|
||||
+ * Flows are linked onto two (Round Robin) lists,
|
||||
+ * so that new flows have priority on old ones.
|
||||
+ *
|
||||
+ * For a given flow, packets are not reordered (CoDel uses a FIFO)
|
||||
+ * head drops only.
|
||||
+ * ECN capability is on by default.
|
||||
+ * Low memory footprint (64 bytes per flow)
|
||||
+ */
|
||||
+
|
||||
+struct fq_codel_flow {
|
||||
+ struct sk_buff *head;
|
||||
+ struct sk_buff *tail;
|
||||
+ struct list_head flowchain;
|
||||
+ int deficit;
|
||||
+ u32 dropped; /* number of drops (or ECN marks) on this flow */
|
||||
+ struct codel_vars cvars;
|
||||
+}; /* please try to keep this structure <= 64 bytes */
|
||||
+
|
||||
+struct fq_codel_sched_data {
|
||||
+ struct tcf_proto *filter_list; /* optional external classifier */
|
||||
+ struct fq_codel_flow *flows; /* Flows table [flows_cnt] */
|
||||
+ u32 *backlogs; /* backlog table [flows_cnt] */
|
||||
+ u32 flows_cnt; /* number of flows */
|
||||
+ u32 perturbation; /* hash perturbation */
|
||||
+ u32 quantum; /* psched_mtu(qdisc_dev(sch)); */
|
||||
+ struct codel_params cparams;
|
||||
+ struct codel_stats cstats;
|
||||
+ u32 drop_overlimit;
|
||||
+ u32 new_flow_count;
|
||||
+
|
||||
+ struct list_head new_flows; /* list of new flows */
|
||||
+ struct list_head old_flows; /* list of old flows */
|
||||
+};
|
||||
+
|
||||
+static unsigned int fq_codel_hash(const struct fq_codel_sched_data *q,
|
||||
+ const struct sk_buff *skb)
|
||||
+{
|
||||
+ struct flow_keys keys;
|
||||
+ unsigned int hash;
|
||||
+
|
||||
+ skb_flow_dissect(skb, &keys);
|
||||
+ hash = jhash_3words((__force u32)keys.dst,
|
||||
+ (__force u32)keys.src ^ keys.ip_proto,
|
||||
+ (__force u32)keys.ports, q->perturbation);
|
||||
+ return ((u64)hash * q->flows_cnt) >> 32;
|
||||
+}
|
||||
+
|
||||
+static unsigned int fq_codel_classify(struct sk_buff *skb, struct Qdisc *sch,
|
||||
+ int *qerr)
|
||||
+{
|
||||
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
+ struct tcf_result res;
|
||||
+ int result;
|
||||
+
|
||||
+ if (TC_H_MAJ(skb->priority) == sch->handle &&
|
||||
+ TC_H_MIN(skb->priority) > 0 &&
|
||||
+ TC_H_MIN(skb->priority) <= q->flows_cnt)
|
||||
+ return TC_H_MIN(skb->priority);
|
||||
+
|
||||
+ if (!q->filter_list)
|
||||
+ return fq_codel_hash(q, skb) + 1;
|
||||
+
|
||||
+ *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
|
||||
+ result = tc_classify(skb, q->filter_list, &res);
|
||||
+ if (result >= 0) {
|
||||
+#ifdef CONFIG_NET_CLS_ACT
|
||||
+ switch (result) {
|
||||
+ case TC_ACT_STOLEN:
|
||||
+ case TC_ACT_QUEUED:
|
||||
+ *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
|
||||
+ case TC_ACT_SHOT:
|
||||
+ return 0;
|
||||
+ }
|
||||
+#endif
|
||||
+ if (TC_H_MIN(res.classid) <= q->flows_cnt)
|
||||
+ return TC_H_MIN(res.classid);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* helper functions : might be changed when/if skb use a standard list_head */
|
||||
+
|
||||
+/* remove one skb from head of slot queue */
|
||||
+static inline struct sk_buff *dequeue_head(struct fq_codel_flow *flow)
|
||||
+{
|
||||
+ struct sk_buff *skb = flow->head;
|
||||
+
|
||||
+ flow->head = skb->next;
|
||||
+ skb->next = NULL;
|
||||
+ return skb;
|
||||
+}
|
||||
+
|
||||
+/* add skb to flow queue (tail add) */
|
||||
+static inline void flow_queue_add(struct fq_codel_flow *flow,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ if (flow->head == NULL)
|
||||
+ flow->head = skb;
|
||||
+ else
|
||||
+ flow->tail->next = skb;
|
||||
+ flow->tail = skb;
|
||||
+ skb->next = NULL;
|
||||
+}
|
||||
+
|
||||
+static unsigned int fq_codel_drop(struct Qdisc *sch)
|
||||
+{
|
||||
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
+ struct sk_buff *skb;
|
||||
+ unsigned int maxbacklog = 0, idx = 0, i, len;
|
||||
+ struct fq_codel_flow *flow;
|
||||
+
|
||||
+ /* Queue is full! Find the fat flow and drop packet from it.
|
||||
+ * This might sound expensive, but with 1024 flows, we scan
|
||||
+ * 4KB of memory, and we dont need to handle a complex tree
|
||||
+ * in fast path (packet queue/enqueue) with many cache misses.
|
||||
+ */
|
||||
+ for (i = 0; i < q->flows_cnt; i++) {
|
||||
+ if (q->backlogs[i] > maxbacklog) {
|
||||
+ maxbacklog = q->backlogs[i];
|
||||
+ idx = i;
|
||||
+ }
|
||||
+ }
|
||||
+ flow = &q->flows[idx];
|
||||
+ skb = dequeue_head(flow);
|
||||
+ len = qdisc_pkt_len(skb);
|
||||
+ q->backlogs[idx] -= len;
|
||||
+ kfree_skb(skb);
|
||||
+ sch->q.qlen--;
|
||||
+ sch->qstats.drops++;
|
||||
+ sch->qstats.backlog -= len;
|
||||
+ flow->dropped++;
|
||||
+ return idx;
|
||||
+}
|
||||
+
|
||||
+static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
|
||||
+{
|
||||
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
+ unsigned int idx;
|
||||
+ struct fq_codel_flow *flow;
|
||||
+ int uninitialized_var(ret);
|
||||
+
|
||||
+ idx = fq_codel_classify(skb, sch, &ret);
|
||||
+ if (idx == 0) {
|
||||
+ if (ret & __NET_XMIT_BYPASS)
|
||||
+ sch->qstats.drops++;
|
||||
+ kfree_skb(skb);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ idx--;
|
||||
+
|
||||
+ codel_set_enqueue_time(skb);
|
||||
+ flow = &q->flows[idx];
|
||||
+ flow_queue_add(flow, skb);
|
||||
+ q->backlogs[idx] += qdisc_pkt_len(skb);
|
||||
+ sch->qstats.backlog += qdisc_pkt_len(skb);
|
||||
+
|
||||
+ if (list_empty(&flow->flowchain)) {
|
||||
+ list_add_tail(&flow->flowchain, &q->new_flows);
|
||||
+ codel_vars_init(&flow->cvars);
|
||||
+ q->new_flow_count++;
|
||||
+ flow->deficit = q->quantum;
|
||||
+ flow->dropped = 0;
|
||||
+ }
|
||||
+ if (++sch->q.qlen < sch->limit)
|
||||
+ return NET_XMIT_SUCCESS;
|
||||
+
|
||||
+ q->drop_overlimit++;
|
||||
+ /* Return Congestion Notification only if we dropped a packet
|
||||
+ * from this flow.
|
||||
+ */
|
||||
+ if (fq_codel_drop(sch) == idx)
|
||||
+ return NET_XMIT_CN;
|
||||
+
|
||||
+ /* As we dropped a packet, better let upper stack know this */
|
||||
+ qdisc_tree_decrease_qlen(sch, 1);
|
||||
+ return NET_XMIT_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+/* This is the specific function called from codel_dequeue()
|
||||
+ * to dequeue a packet from queue. Note: backlog is handled in
|
||||
+ * codel, we dont need to reduce it here.
|
||||
+ */
|
||||
+static struct sk_buff *dequeue(struct codel_vars *vars, struct Qdisc *sch)
|
||||
+{
|
||||
+ struct fq_codel_flow *flow;
|
||||
+ struct sk_buff *skb = NULL;
|
||||
+
|
||||
+ flow = container_of(vars, struct fq_codel_flow, cvars);
|
||||
+ if (flow->head) {
|
||||
+ skb = dequeue_head(flow);
|
||||
+ sch->qstats.backlog -= qdisc_pkt_len(skb);
|
||||
+ sch->q.qlen--;
|
||||
+ }
|
||||
+ return skb;
|
||||
+}
|
||||
+
|
||||
+static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch)
|
||||
+{
|
||||
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
+ struct sk_buff *skb;
|
||||
+ struct fq_codel_flow *flow;
|
||||
+ struct list_head *head;
|
||||
+ u32 prev_drop_count, prev_ecn_mark;
|
||||
+
|
||||
+begin:
|
||||
+ head = &q->new_flows;
|
||||
+ if (list_empty(head)) {
|
||||
+ head = &q->old_flows;
|
||||
+ if (list_empty(head))
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ flow = list_first_entry(head, struct fq_codel_flow, flowchain);
|
||||
+
|
||||
+ if (flow->deficit <= 0) {
|
||||
+ flow->deficit += q->quantum;
|
||||
+ list_move_tail(&flow->flowchain, &q->old_flows);
|
||||
+ goto begin;
|
||||
+ }
|
||||
+
|
||||
+ prev_drop_count = q->cstats.drop_count;
|
||||
+ prev_ecn_mark = q->cstats.ecn_mark;
|
||||
+
|
||||
+ skb = codel_dequeue(sch, &q->cparams, &flow->cvars, &q->cstats,
|
||||
+ dequeue, &q->backlogs[flow - q->flows]);
|
||||
+
|
||||
+ flow->dropped += q->cstats.drop_count - prev_drop_count;
|
||||
+ flow->dropped += q->cstats.ecn_mark - prev_ecn_mark;
|
||||
+
|
||||
+ if (!skb) {
|
||||
+ /* force a pass through old_flows to prevent starvation */
|
||||
+ if ((head == &q->new_flows) && !list_empty(&q->old_flows))
|
||||
+ list_move_tail(&flow->flowchain, &q->old_flows);
|
||||
+ else
|
||||
+ list_del_init(&flow->flowchain);
|
||||
+ goto begin;
|
||||
+ }
|
||||
+ qdisc_bstats_update(sch, skb);
|
||||
+ flow->deficit -= qdisc_pkt_len(skb);
|
||||
+ /* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
|
||||
+ * or HTB crashes. Defer it for next round.
|
||||
+ */
|
||||
+ if (q->cstats.drop_count && sch->q.qlen) {
|
||||
+ qdisc_tree_decrease_qlen(sch, q->cstats.drop_count);
|
||||
+ q->cstats.drop_count = 0;
|
||||
+ }
|
||||
+ return skb;
|
||||
+}
|
||||
+
|
||||
+static void fq_codel_reset(struct Qdisc *sch)
|
||||
+{
|
||||
+ struct sk_buff *skb;
|
||||
+
|
||||
+ while ((skb = fq_codel_dequeue(sch)) != NULL)
|
||||
+ kfree_skb(skb);
|
||||
+}
|
||||
+
|
||||
+static const struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = {
|
||||
+ [TCA_FQ_CODEL_TARGET] = { .type = NLA_U32 },
|
||||
+ [TCA_FQ_CODEL_LIMIT] = { .type = NLA_U32 },
|
||||
+ [TCA_FQ_CODEL_INTERVAL] = { .type = NLA_U32 },
|
||||
+ [TCA_FQ_CODEL_ECN] = { .type = NLA_U32 },
|
||||
+ [TCA_FQ_CODEL_FLOWS] = { .type = NLA_U32 },
|
||||
+ [TCA_FQ_CODEL_QUANTUM] = { .type = NLA_U32 },
|
||||
+};
|
||||
+
|
||||
+static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt)
|
||||
+{
|
||||
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
+ struct nlattr *tb[TCA_FQ_CODEL_MAX + 1];
|
||||
+ int err;
|
||||
+
|
||||
+ if (!opt)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ err = nla_parse_nested(tb, TCA_FQ_CODEL_MAX, opt, fq_codel_policy);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+ if (tb[TCA_FQ_CODEL_FLOWS]) {
|
||||
+ if (q->flows)
|
||||
+ return -EINVAL;
|
||||
+ q->flows_cnt = nla_get_u32(tb[TCA_FQ_CODEL_FLOWS]);
|
||||
+ if (!q->flows_cnt ||
|
||||
+ q->flows_cnt > 65536)
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ sch_tree_lock(sch);
|
||||
+
|
||||
+ if (tb[TCA_FQ_CODEL_TARGET]) {
|
||||
+ u64 target = nla_get_u32(tb[TCA_FQ_CODEL_TARGET]);
|
||||
+
|
||||
+ q->cparams.target = (target * NSEC_PER_USEC) >> CODEL_SHIFT;
|
||||
+ }
|
||||
+
|
||||
+ if (tb[TCA_FQ_CODEL_INTERVAL]) {
|
||||
+ u64 interval = nla_get_u32(tb[TCA_FQ_CODEL_INTERVAL]);
|
||||
+
|
||||
+ q->cparams.interval = (interval * NSEC_PER_USEC) >> CODEL_SHIFT;
|
||||
+ }
|
||||
+
|
||||
+ if (tb[TCA_FQ_CODEL_LIMIT])
|
||||
+ sch->limit = nla_get_u32(tb[TCA_FQ_CODEL_LIMIT]);
|
||||
+
|
||||
+ if (tb[TCA_FQ_CODEL_ECN])
|
||||
+ q->cparams.ecn = !!nla_get_u32(tb[TCA_FQ_CODEL_ECN]);
|
||||
+
|
||||
+ if (tb[TCA_FQ_CODEL_QUANTUM])
|
||||
+ q->quantum = max(256U, nla_get_u32(tb[TCA_FQ_CODEL_QUANTUM]));
|
||||
+
|
||||
+ while (sch->q.qlen > sch->limit) {
|
||||
+ struct sk_buff *skb = fq_codel_dequeue(sch);
|
||||
+
|
||||
+ kfree_skb(skb);
|
||||
+ q->cstats.drop_count++;
|
||||
+ }
|
||||
+ qdisc_tree_decrease_qlen(sch, q->cstats.drop_count);
|
||||
+ q->cstats.drop_count = 0;
|
||||
+
|
||||
+ sch_tree_unlock(sch);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void *fq_codel_zalloc(size_t sz)
|
||||
+{
|
||||
+ void *ptr = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN);
|
||||
+
|
||||
+ if (!ptr)
|
||||
+ ptr = vzalloc(sz);
|
||||
+ return ptr;
|
||||
+}
|
||||
+
|
||||
+static void fq_codel_free(void *addr)
|
||||
+{
|
||||
+ if (addr) {
|
||||
+ if (is_vmalloc_addr(addr))
|
||||
+ vfree(addr);
|
||||
+ else
|
||||
+ kfree(addr);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void fq_codel_destroy(struct Qdisc *sch)
|
||||
+{
|
||||
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
+
|
||||
+ tcf_destroy_chain(&q->filter_list);
|
||||
+ fq_codel_free(q->backlogs);
|
||||
+ fq_codel_free(q->flows);
|
||||
+}
|
||||
+
|
||||
+static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt)
|
||||
+{
|
||||
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
+ int i;
|
||||
+
|
||||
+ sch->limit = 10*1024;
|
||||
+ q->flows_cnt = 1024;
|
||||
+ q->quantum = psched_mtu(qdisc_dev(sch));
|
||||
+ q->perturbation = net_random();
|
||||
+ INIT_LIST_HEAD(&q->new_flows);
|
||||
+ INIT_LIST_HEAD(&q->old_flows);
|
||||
+ codel_params_init(&q->cparams);
|
||||
+ codel_stats_init(&q->cstats);
|
||||
+ q->cparams.ecn = true;
|
||||
+
|
||||
+ if (opt) {
|
||||
+ int err = fq_codel_change(sch, opt);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ if (!q->flows) {
|
||||
+ q->flows = fq_codel_zalloc(q->flows_cnt *
|
||||
+ sizeof(struct fq_codel_flow));
|
||||
+ if (!q->flows)
|
||||
+ return -ENOMEM;
|
||||
+ q->backlogs = fq_codel_zalloc(q->flows_cnt * sizeof(u32));
|
||||
+ if (!q->backlogs) {
|
||||
+ fq_codel_free(q->flows);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ for (i = 0; i < q->flows_cnt; i++) {
|
||||
+ struct fq_codel_flow *flow = q->flows + i;
|
||||
+
|
||||
+ INIT_LIST_HEAD(&flow->flowchain);
|
||||
+ }
|
||||
+ }
|
||||
+ if (sch->limit >= 1)
|
||||
+ sch->flags |= TCQ_F_CAN_BYPASS;
|
||||
+ else
|
||||
+ sch->flags &= ~TCQ_F_CAN_BYPASS;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int fq_codel_dump(struct Qdisc *sch, struct sk_buff *skb)
|
||||
+{
|
||||
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
+ struct nlattr *opts;
|
||||
+
|
||||
+ opts = nla_nest_start(skb, TCA_OPTIONS);
|
||||
+ if (opts == NULL)
|
||||
+ goto nla_put_failure;
|
||||
+
|
||||
+ if (nla_put_u32(skb, TCA_FQ_CODEL_TARGET,
|
||||
+ codel_time_to_us(q->cparams.target)) ||
|
||||
+ nla_put_u32(skb, TCA_FQ_CODEL_LIMIT,
|
||||
+ sch->limit) ||
|
||||
+ nla_put_u32(skb, TCA_FQ_CODEL_INTERVAL,
|
||||
+ codel_time_to_us(q->cparams.interval)) ||
|
||||
+ nla_put_u32(skb, TCA_FQ_CODEL_ECN,
|
||||
+ q->cparams.ecn) ||
|
||||
+ nla_put_u32(skb, TCA_FQ_CODEL_QUANTUM,
|
||||
+ q->quantum) ||
|
||||
+ nla_put_u32(skb, TCA_FQ_CODEL_FLOWS,
|
||||
+ q->flows_cnt))
|
||||
+ goto nla_put_failure;
|
||||
+
|
||||
+ nla_nest_end(skb, opts);
|
||||
+ return skb->len;
|
||||
+
|
||||
+nla_put_failure:
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static int fq_codel_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
|
||||
+{
|
||||
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
+ struct tc_fq_codel_xstats st = {
|
||||
+ .type = TCA_FQ_CODEL_XSTATS_QDISC,
|
||||
+ .qdisc_stats.maxpacket = q->cstats.maxpacket,
|
||||
+ .qdisc_stats.drop_overlimit = q->drop_overlimit,
|
||||
+ .qdisc_stats.ecn_mark = q->cstats.ecn_mark,
|
||||
+ .qdisc_stats.new_flow_count = q->new_flow_count,
|
||||
+ };
|
||||
+ struct list_head *pos;
|
||||
+
|
||||
+ list_for_each(pos, &q->new_flows)
|
||||
+ st.qdisc_stats.new_flows_len++;
|
||||
+
|
||||
+ list_for_each(pos, &q->old_flows)
|
||||
+ st.qdisc_stats.old_flows_len++;
|
||||
+
|
||||
+ return gnet_stats_copy_app(d, &st, sizeof(st));
|
||||
+}
|
||||
+
|
||||
+static struct Qdisc *fq_codel_leaf(struct Qdisc *sch, unsigned long arg)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static unsigned long fq_codel_get(struct Qdisc *sch, u32 classid)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static unsigned long fq_codel_bind(struct Qdisc *sch, unsigned long parent,
|
||||
+ u32 classid)
|
||||
+{
|
||||
+ /* we cannot bypass queue discipline anymore */
|
||||
+ sch->flags &= ~TCQ_F_CAN_BYPASS;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void fq_codel_put(struct Qdisc *q, unsigned long cl)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static struct tcf_proto **fq_codel_find_tcf(struct Qdisc *sch, unsigned long cl)
|
||||
+{
|
||||
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
+
|
||||
+ if (cl)
|
||||
+ return NULL;
|
||||
+ return &q->filter_list;
|
||||
+}
|
||||
+
|
||||
+static int fq_codel_dump_class(struct Qdisc *sch, unsigned long cl,
|
||||
+ struct sk_buff *skb, struct tcmsg *tcm)
|
||||
+{
|
||||
+ tcm->tcm_handle |= TC_H_MIN(cl);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int fq_codel_dump_class_stats(struct Qdisc *sch, unsigned long cl,
|
||||
+ struct gnet_dump *d)
|
||||
+{
|
||||
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
+ u32 idx = cl - 1;
|
||||
+ struct gnet_stats_queue qs = { 0 };
|
||||
+ struct tc_fq_codel_xstats xstats;
|
||||
+
|
||||
+ if (idx < q->flows_cnt) {
|
||||
+ const struct fq_codel_flow *flow = &q->flows[idx];
|
||||
+ const struct sk_buff *skb = flow->head;
|
||||
+
|
||||
+ memset(&xstats, 0, sizeof(xstats));
|
||||
+ xstats.type = TCA_FQ_CODEL_XSTATS_CLASS;
|
||||
+ xstats.class_stats.deficit = flow->deficit;
|
||||
+ xstats.class_stats.ldelay =
|
||||
+ codel_time_to_us(flow->cvars.ldelay);
|
||||
+ xstats.class_stats.count = flow->cvars.count;
|
||||
+ xstats.class_stats.lastcount = flow->cvars.lastcount;
|
||||
+ xstats.class_stats.dropping = flow->cvars.dropping;
|
||||
+ if (flow->cvars.dropping) {
|
||||
+ codel_tdiff_t delta = flow->cvars.drop_next -
|
||||
+ codel_get_time();
|
||||
+
|
||||
+ xstats.class_stats.drop_next = (delta >= 0) ?
|
||||
+ codel_time_to_us(delta) :
|
||||
+ -codel_time_to_us(-delta);
|
||||
+ }
|
||||
+ while (skb) {
|
||||
+ qs.qlen++;
|
||||
+ skb = skb->next;
|
||||
+ }
|
||||
+ qs.backlog = q->backlogs[idx];
|
||||
+ qs.drops = flow->dropped;
|
||||
+ }
|
||||
+ if (gnet_stats_copy_queue(d, &qs) < 0)
|
||||
+ return -1;
|
||||
+ if (idx < q->flows_cnt)
|
||||
+ return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void fq_codel_walk(struct Qdisc *sch, struct qdisc_walker *arg)
|
||||
+{
|
||||
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ if (arg->stop)
|
||||
+ return;
|
||||
+
|
||||
+ for (i = 0; i < q->flows_cnt; i++) {
|
||||
+ if (list_empty(&q->flows[i].flowchain) ||
|
||||
+ arg->count < arg->skip) {
|
||||
+ arg->count++;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (arg->fn(sch, i + 1, arg) < 0) {
|
||||
+ arg->stop = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ arg->count++;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static const struct Qdisc_class_ops fq_codel_class_ops = {
|
||||
+ .leaf = fq_codel_leaf,
|
||||
+ .get = fq_codel_get,
|
||||
+ .put = fq_codel_put,
|
||||
+ .tcf_chain = fq_codel_find_tcf,
|
||||
+ .bind_tcf = fq_codel_bind,
|
||||
+ .unbind_tcf = fq_codel_put,
|
||||
+ .dump = fq_codel_dump_class,
|
||||
+ .dump_stats = fq_codel_dump_class_stats,
|
||||
+ .walk = fq_codel_walk,
|
||||
+};
|
||||
+
|
||||
+static struct Qdisc_ops fq_codel_qdisc_ops __read_mostly = {
|
||||
+ .cl_ops = &fq_codel_class_ops,
|
||||
+ .id = "fq_codel",
|
||||
+ .priv_size = sizeof(struct fq_codel_sched_data),
|
||||
+ .enqueue = fq_codel_enqueue,
|
||||
+ .dequeue = fq_codel_dequeue,
|
||||
+ .peek = qdisc_peek_dequeued,
|
||||
+ .drop = fq_codel_drop,
|
||||
+ .init = fq_codel_init,
|
||||
+ .reset = fq_codel_reset,
|
||||
+ .destroy = fq_codel_destroy,
|
||||
+ .change = fq_codel_change,
|
||||
+ .dump = fq_codel_dump,
|
||||
+ .dump_stats = fq_codel_dump_stats,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static int __init fq_codel_module_init(void)
|
||||
+{
|
||||
+ return register_qdisc(&fq_codel_qdisc_ops);
|
||||
+}
|
||||
+
|
||||
+static void __exit fq_codel_module_exit(void)
|
||||
+{
|
||||
+ unregister_qdisc(&fq_codel_qdisc_ops);
|
||||
+}
|
||||
+
|
||||
+module_init(fq_codel_module_init)
|
||||
+module_exit(fq_codel_module_exit)
|
||||
+MODULE_AUTHOR("Eric Dumazet");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
From: Geert Uytterhoeven <geert@linux-m68k.org>
|
||||
Date: Mon, 14 May 2012 09:47:05 +0000
|
||||
Subject: [PATCH 4/7] net/codel: Add missing #include <linux/prefetch.h>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
commit ce5b4b977127ee20c3f9c3fd3637cd3796f649f5 upstream.
|
||||
|
||||
m68k allmodconfig:
|
||||
|
||||
net/sched/sch_codel.c: In function ‘dequeue’:
|
||||
net/sched/sch_codel.c:70: error: implicit declaration of function ‘prefetch’
|
||||
make[1]: *** [net/sched/sch_codel.o] Error 1
|
||||
|
||||
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
|
||||
Acked-by: Eric Dumazet <edumazet@google.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
net/sched/sch_codel.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c
|
||||
index b4a1a81..213ef60 100644
|
||||
--- a/net/sched/sch_codel.c
|
||||
+++ b/net/sched/sch_codel.c
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/skbuff.h>
|
||||
+#include <linux/prefetch.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/codel.h>
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
From: Sasha Levin <levinsasha928@gmail.com>
|
||||
Date: Mon, 14 May 2012 11:57:06 +0000
|
||||
Subject: [PATCH 5/7] net: codel: fix build errors
|
||||
|
||||
commit 669d67bf777def468970f2dcba1537edf3b2d329 upstream.
|
||||
|
||||
Fix the following build error:
|
||||
|
||||
net/sched/sch_fq_codel.c: In function 'fq_codel_dump_stats':
|
||||
net/sched/sch_fq_codel.c:464:3: error: unknown field 'qdisc_stats' specified in initializer
|
||||
net/sched/sch_fq_codel.c:464:3: warning: missing braces around initializer
|
||||
net/sched/sch_fq_codel.c:464:3: warning: (near initialization for 'st.<anonymous>')
|
||||
net/sched/sch_fq_codel.c:465:3: error: unknown field 'qdisc_stats' specified in initializer
|
||||
net/sched/sch_fq_codel.c:465:3: warning: excess elements in struct initializer
|
||||
net/sched/sch_fq_codel.c:465:3: warning: (near initialization for 'st')
|
||||
net/sched/sch_fq_codel.c:466:3: error: unknown field 'qdisc_stats' specified in initializer
|
||||
net/sched/sch_fq_codel.c:466:3: warning: excess elements in struct initializer
|
||||
net/sched/sch_fq_codel.c:466:3: warning: (near initialization for 'st')
|
||||
net/sched/sch_fq_codel.c:467:3: error: unknown field 'qdisc_stats' specified in initializer
|
||||
net/sched/sch_fq_codel.c:467:3: warning: excess elements in struct initializer
|
||||
net/sched/sch_fq_codel.c:467:3: warning: (near initialization for 'st')
|
||||
make[1]: *** [net/sched/sch_fq_codel.o] Error 1
|
||||
|
||||
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
net/sched/sch_fq_codel.c | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
|
||||
index a7b3754..337ff20 100644
|
||||
--- a/net/sched/sch_fq_codel.c
|
||||
+++ b/net/sched/sch_fq_codel.c
|
||||
@@ -461,13 +461,14 @@ static int fq_codel_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
|
||||
struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
struct tc_fq_codel_xstats st = {
|
||||
.type = TCA_FQ_CODEL_XSTATS_QDISC,
|
||||
- .qdisc_stats.maxpacket = q->cstats.maxpacket,
|
||||
- .qdisc_stats.drop_overlimit = q->drop_overlimit,
|
||||
- .qdisc_stats.ecn_mark = q->cstats.ecn_mark,
|
||||
- .qdisc_stats.new_flow_count = q->new_flow_count,
|
||||
};
|
||||
struct list_head *pos;
|
||||
|
||||
+ st.qdisc_stats.maxpacket = q->cstats.maxpacket;
|
||||
+ st.qdisc_stats.drop_overlimit = q->drop_overlimit;
|
||||
+ st.qdisc_stats.ecn_mark = q->cstats.ecn_mark;
|
||||
+ st.qdisc_stats.new_flow_count = q->new_flow_count;
|
||||
+
|
||||
list_for_each(pos, &q->new_flows)
|
||||
st.qdisc_stats.new_flows_len++;
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
From: Eric Dumazet <eric.dumazet@gmail.com>
|
||||
Date: Sat, 12 May 2012 21:23:23 +0000
|
||||
Subject: [PATCH 6/7] codel: use u16 field instead of 31bits for rec_inv_sqrt
|
||||
|
||||
commit 6ff272c9ad65eda219cd975b9da2dbc31cc812ee upstream.
|
||||
|
||||
David pointed out gcc might generate poor code with 31bit fields.
|
||||
|
||||
Using u16 is more than enough and permits a better code output.
|
||||
|
||||
Also make the code intent more readable using constants, fixed point arithmetic
|
||||
not being trivial for everybody.
|
||||
|
||||
Suggested-by: David Miller <davem@davemloft.net>
|
||||
Signed-off-by: Eric Dumazet <edumazet@google.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
include/net/codel.h | 25 +++++++++++++++----------
|
||||
1 file changed, 15 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/include/net/codel.h b/include/net/codel.h
|
||||
index bd8747c..7546517 100644
|
||||
--- a/include/net/codel.h
|
||||
+++ b/include/net/codel.h
|
||||
@@ -133,13 +133,17 @@ struct codel_params {
|
||||
struct codel_vars {
|
||||
u32 count;
|
||||
u32 lastcount;
|
||||
- bool dropping:1;
|
||||
- u32 rec_inv_sqrt:31;
|
||||
+ bool dropping;
|
||||
+ u16 rec_inv_sqrt;
|
||||
codel_time_t first_above_time;
|
||||
codel_time_t drop_next;
|
||||
codel_time_t ldelay;
|
||||
};
|
||||
|
||||
+#define REC_INV_SQRT_BITS (8 * sizeof(u16)) /* or sizeof_in_bits(rec_inv_sqrt) */
|
||||
+/* needed shift to get a Q0.32 number from rec_inv_sqrt */
|
||||
+#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS)
|
||||
+
|
||||
/**
|
||||
* struct codel_stats - contains codel shared variables and stats
|
||||
* @maxpacket: largest packet we've seen so far
|
||||
@@ -173,17 +177,18 @@ static void codel_stats_init(struct codel_stats *stats)
|
||||
* http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
|
||||
* new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2)
|
||||
*
|
||||
- * Here, invsqrt is a fixed point number (< 1.0), 31bit mantissa)
|
||||
+ * Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32
|
||||
*/
|
||||
static void codel_Newton_step(struct codel_vars *vars)
|
||||
{
|
||||
- u32 invsqrt = vars->rec_inv_sqrt;
|
||||
- u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 31;
|
||||
- u64 val = (3LL << 31) - ((u64)vars->count * invsqrt2);
|
||||
+ u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT;
|
||||
+ u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32;
|
||||
+ u64 val = (3LL << 32) - ((u64)vars->count * invsqrt2);
|
||||
|
||||
- val = (val * invsqrt) >> 32;
|
||||
+ val >>= 2; /* avoid overflow in following multiply */
|
||||
+ val = (val * invsqrt) >> (32 - 2 + 1);
|
||||
|
||||
- vars->rec_inv_sqrt = val;
|
||||
+ vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -195,7 +200,7 @@ static codel_time_t codel_control_law(codel_time_t t,
|
||||
codel_time_t interval,
|
||||
u32 rec_inv_sqrt)
|
||||
{
|
||||
- return t + reciprocal_divide(interval, rec_inv_sqrt << 1);
|
||||
+ return t + reciprocal_divide(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT);
|
||||
}
|
||||
|
||||
|
||||
@@ -326,7 +331,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
|
||||
codel_Newton_step(vars);
|
||||
} else {
|
||||
vars->count = 1;
|
||||
- vars->rec_inv_sqrt = 0x7fffffff;
|
||||
+ vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT;
|
||||
}
|
||||
vars->lastcount = vars->count;
|
||||
vars->drop_next = codel_control_law(now, params->interval,
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
From: Eric Dumazet <edumazet@google.com>
|
||||
Date: Wed, 16 May 2012 04:39:09 +0000
|
||||
Subject: [PATCH 7/7] fq_codel: should use qdisc backlog as threshold
|
||||
|
||||
commit 865ec5523dadbedefbc5710a68969f686a28d928 upstream.
|
||||
|
||||
codel_should_drop() logic allows a packet being not dropped if queue
|
||||
size is under max packet size.
|
||||
|
||||
In fq_codel, we have two possible backlogs : The qdisc global one, and
|
||||
the flow local one.
|
||||
|
||||
The meaningful one for codel_should_drop() should be the global backlog,
|
||||
not the per flow one, so that thin flows can have a non zero drop/mark
|
||||
probability.
|
||||
|
||||
Signed-off-by: Eric Dumazet <edumazet@google.com>
|
||||
Cc: Dave Taht <dave.taht@bufferbloat.net>
|
||||
Cc: Kathleen Nichols <nichols@pollere.com>
|
||||
Cc: Van Jacobson <van@pollere.net>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
include/net/codel.h | 15 +++++++--------
|
||||
net/sched/sch_codel.c | 4 ++--
|
||||
net/sched/sch_fq_codel.c | 5 +++--
|
||||
3 files changed, 12 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/include/net/codel.h b/include/net/codel.h
|
||||
index 7546517..550debf 100644
|
||||
--- a/include/net/codel.h
|
||||
+++ b/include/net/codel.h
|
||||
@@ -205,7 +205,7 @@ static codel_time_t codel_control_law(codel_time_t t,
|
||||
|
||||
|
||||
static bool codel_should_drop(const struct sk_buff *skb,
|
||||
- unsigned int *backlog,
|
||||
+ struct Qdisc *sch,
|
||||
struct codel_vars *vars,
|
||||
struct codel_params *params,
|
||||
struct codel_stats *stats,
|
||||
@@ -219,13 +219,13 @@ static bool codel_should_drop(const struct sk_buff *skb,
|
||||
}
|
||||
|
||||
vars->ldelay = now - codel_get_enqueue_time(skb);
|
||||
- *backlog -= qdisc_pkt_len(skb);
|
||||
+ sch->qstats.backlog -= qdisc_pkt_len(skb);
|
||||
|
||||
if (unlikely(qdisc_pkt_len(skb) > stats->maxpacket))
|
||||
stats->maxpacket = qdisc_pkt_len(skb);
|
||||
|
||||
if (codel_time_before(vars->ldelay, params->target) ||
|
||||
- *backlog <= stats->maxpacket) {
|
||||
+ sch->qstats.backlog <= stats->maxpacket) {
|
||||
/* went below - stay below for at least interval */
|
||||
vars->first_above_time = 0;
|
||||
return false;
|
||||
@@ -249,8 +249,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
|
||||
struct codel_params *params,
|
||||
struct codel_vars *vars,
|
||||
struct codel_stats *stats,
|
||||
- codel_skb_dequeue_t dequeue_func,
|
||||
- u32 *backlog)
|
||||
+ codel_skb_dequeue_t dequeue_func)
|
||||
{
|
||||
struct sk_buff *skb = dequeue_func(vars, sch);
|
||||
codel_time_t now;
|
||||
@@ -261,7 +260,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
|
||||
return skb;
|
||||
}
|
||||
now = codel_get_time();
|
||||
- drop = codel_should_drop(skb, backlog, vars, params, stats, now);
|
||||
+ drop = codel_should_drop(skb, sch, vars, params, stats, now);
|
||||
if (vars->dropping) {
|
||||
if (!drop) {
|
||||
/* sojourn time below target - leave dropping state */
|
||||
@@ -292,7 +291,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
|
||||
qdisc_drop(skb, sch);
|
||||
stats->drop_count++;
|
||||
skb = dequeue_func(vars, sch);
|
||||
- if (!codel_should_drop(skb, backlog,
|
||||
+ if (!codel_should_drop(skb, sch,
|
||||
vars, params, stats, now)) {
|
||||
/* leave dropping state */
|
||||
vars->dropping = false;
|
||||
@@ -313,7 +312,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
|
||||
stats->drop_count++;
|
||||
|
||||
skb = dequeue_func(vars, sch);
|
||||
- drop = codel_should_drop(skb, backlog, vars, params,
|
||||
+ drop = codel_should_drop(skb, sch, vars, params,
|
||||
stats, now);
|
||||
}
|
||||
vars->dropping = true;
|
||||
diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c
|
||||
index 213ef60..2f9ab17 100644
|
||||
--- a/net/sched/sch_codel.c
|
||||
+++ b/net/sched/sch_codel.c
|
||||
@@ -77,8 +77,8 @@ static struct sk_buff *codel_qdisc_dequeue(struct Qdisc *sch)
|
||||
struct codel_sched_data *q = qdisc_priv(sch);
|
||||
struct sk_buff *skb;
|
||||
|
||||
- skb = codel_dequeue(sch, &q->params, &q->vars, &q->stats,
|
||||
- dequeue, &sch->qstats.backlog);
|
||||
+ skb = codel_dequeue(sch, &q->params, &q->vars, &q->stats, dequeue);
|
||||
+
|
||||
/* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
|
||||
* or HTB crashes. Defer it for next round.
|
||||
*/
|
||||
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
|
||||
index 337ff20..9fc1c62 100644
|
||||
--- a/net/sched/sch_fq_codel.c
|
||||
+++ b/net/sched/sch_fq_codel.c
|
||||
@@ -217,13 +217,14 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
|
||||
*/
|
||||
static struct sk_buff *dequeue(struct codel_vars *vars, struct Qdisc *sch)
|
||||
{
|
||||
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
|
||||
struct fq_codel_flow *flow;
|
||||
struct sk_buff *skb = NULL;
|
||||
|
||||
flow = container_of(vars, struct fq_codel_flow, cvars);
|
||||
if (flow->head) {
|
||||
skb = dequeue_head(flow);
|
||||
- sch->qstats.backlog -= qdisc_pkt_len(skb);
|
||||
+ q->backlogs[flow - q->flows] -= qdisc_pkt_len(skb);
|
||||
sch->q.qlen--;
|
||||
}
|
||||
return skb;
|
||||
@@ -256,7 +257,7 @@ begin:
|
||||
prev_ecn_mark = q->cstats.ecn_mark;
|
||||
|
||||
skb = codel_dequeue(sch, &q->cparams, &flow->cvars, &q->cstats,
|
||||
- dequeue, &q->backlogs[flow - q->flows]);
|
||||
+ dequeue);
|
||||
|
||||
flow->dropped += q->cstats.drop_count - prev_drop_count;
|
||||
flow->dropped += q->cstats.ecn_mark - prev_ecn_mark;
|
||||
--
|
||||
1.7.10
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
From: Jason Gerecke <killertofu@gmail.com>
|
||||
Date: Tue, 3 Apr 2012 15:47:22 -0700
|
||||
Subject: Input: wacom - add basic Intuos5 support
|
||||
|
||||
commit 9fee619505bdb202c9f54b58ec996884160cdbf2 upstream.
|
||||
|
||||
This patch adds support for the basic pen functions of Intuos5
|
||||
tablets.
|
||||
|
||||
Signed-off-by: Jason Gerecke <killertofu@gmail.com>
|
||||
Reviewed-by: Chris Bagwell <chris@cnpbagwell.com>
|
||||
Reviewed-by: Ping Cheng <pingc@wacom.com>
|
||||
Tested-by: Timo Aaltonen <tjaalton@ubuntu.com>
|
||||
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
|
||||
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
|
||||
---
|
||||
drivers/input/tablet/wacom_wac.c | 36 +++++++++++++++++++++++++++++++++---
|
||||
drivers/input/tablet/wacom_wac.h | 3 +++
|
||||
2 files changed, 36 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
|
||||
index cecd35c8f0b3..f159e9d90d4a 100644
|
||||
--- a/drivers/input/tablet/wacom_wac.c
|
||||
+++ b/drivers/input/tablet/wacom_wac.c
|
||||
@@ -452,6 +452,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
|
||||
if ((data[1] & 0xb8) == 0xa0) {
|
||||
t = (data[6] << 2) | ((data[7] >> 6) & 3);
|
||||
if ((features->type >= INTUOS4S && features->type <= INTUOS4L) ||
|
||||
+ (features->type >= INTUOS5S && features->type <= INTUOS5L) ||
|
||||
features->type == WACOM_21UX2 || features->type == WACOM_24HD) {
|
||||
t = (t << 1) | (data[1] & 1);
|
||||
}
|
||||
@@ -632,7 +633,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
|
||||
(features->type == INTUOS3 ||
|
||||
features->type == INTUOS3S ||
|
||||
features->type == INTUOS4 ||
|
||||
- features->type == INTUOS4S)) {
|
||||
+ features->type == INTUOS4S ||
|
||||
+ features->type == INTUOS5 ||
|
||||
+ features->type == INTUOS5S)) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -685,7 +688,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
|
||||
|
||||
} else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
|
||||
/* I4 mouse */
|
||||
- if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
|
||||
+ if ((features->type >= INTUOS4S && features->type <= INTUOS4L) ||
|
||||
+ (features->type >= INTUOS5S && features->type <= INTUOS5L)) {
|
||||
input_report_key(input, BTN_LEFT, data[6] & 0x01);
|
||||
input_report_key(input, BTN_MIDDLE, data[6] & 0x02);
|
||||
input_report_key(input, BTN_RIGHT, data[6] & 0x04);
|
||||
@@ -712,7 +716,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
|
||||
}
|
||||
}
|
||||
} else if ((features->type < INTUOS3S || features->type == INTUOS3L ||
|
||||
- features->type == INTUOS4L) &&
|
||||
+ features->type == INTUOS4L || features->type == INTUOS5L) &&
|
||||
wacom->tool[idx] == BTN_TOOL_LENS) {
|
||||
/* Lens cursor packets */
|
||||
input_report_key(input, BTN_LEFT, data[8] & 0x01);
|
||||
@@ -1107,6 +1111,9 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
|
||||
case INTUOS4S:
|
||||
case INTUOS4:
|
||||
case INTUOS4L:
|
||||
+ case INTUOS5S:
|
||||
+ case INTUOS5:
|
||||
+ case INTUOS5L:
|
||||
case CINTIQ:
|
||||
case WACOM_BEE:
|
||||
case WACOM_21UX2:
|
||||
@@ -1355,12 +1362,15 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
wacom_setup_intuos(wacom_wac);
|
||||
break;
|
||||
|
||||
+ case INTUOS5:
|
||||
+ case INTUOS5L:
|
||||
case INTUOS4:
|
||||
case INTUOS4L:
|
||||
__set_bit(BTN_7, input_dev->keybit);
|
||||
__set_bit(BTN_8, input_dev->keybit);
|
||||
/* fall through */
|
||||
|
||||
+ case INTUOS5S:
|
||||
case INTUOS4S:
|
||||
for (i = 0; i < 7; i++)
|
||||
__set_bit(BTN_0 + i, input_dev->keybit);
|
||||
@@ -1629,6 +1639,21 @@ static const struct wacom_features wacom_features_0xBB =
|
||||
static const struct wacom_features wacom_features_0xBC =
|
||||
{ "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40840, 25400, 2047,
|
||||
63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
+static const struct wacom_features wacom_features_0x26 =
|
||||
+ { "Wacom Intuos5 touch S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047,
|
||||
+ 63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
+static const struct wacom_features wacom_features_0x27 =
|
||||
+ { "Wacom Intuos5 touch M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047,
|
||||
+ 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
+static const struct wacom_features wacom_features_0x28 =
|
||||
+ { "Wacom Intuos5 touch L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047,
|
||||
+ 63, INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
+static const struct wacom_features wacom_features_0x29 =
|
||||
+ { "Wacom Intuos5 S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047,
|
||||
+ 63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
+static const struct wacom_features wacom_features_0x2A =
|
||||
+ { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047,
|
||||
+ 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
static const struct wacom_features wacom_features_0xF4 =
|
||||
{ "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047,
|
||||
63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
@@ -1801,6 +1826,11 @@ const struct usb_device_id wacom_ids[] = {
|
||||
{ USB_DEVICE_WACOM(0xBA) },
|
||||
{ USB_DEVICE_WACOM(0xBB) },
|
||||
{ USB_DEVICE_WACOM(0xBC) },
|
||||
+ { USB_DEVICE_WACOM(0x26) },
|
||||
+ { USB_DEVICE_WACOM(0x27) },
|
||||
+ { USB_DEVICE_WACOM(0x28) },
|
||||
+ { USB_DEVICE_WACOM(0x29) },
|
||||
+ { USB_DEVICE_WACOM(0x2A) },
|
||||
{ USB_DEVICE_WACOM(0x3F) },
|
||||
{ USB_DEVICE_WACOM(0xC5) },
|
||||
{ USB_DEVICE_WACOM(0xC6) },
|
||||
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
|
||||
index ba5a334e54d6..0aa00ce5fd7d 100644
|
||||
--- a/drivers/input/tablet/wacom_wac.h
|
||||
+++ b/drivers/input/tablet/wacom_wac.h
|
||||
@@ -65,6 +65,9 @@ enum {
|
||||
INTUOS4S,
|
||||
INTUOS4,
|
||||
INTUOS4L,
|
||||
+ INTUOS5S,
|
||||
+ INTUOS5,
|
||||
+ INTUOS5L,
|
||||
WACOM_24HD,
|
||||
WACOM_21UX2,
|
||||
CINTIQ,
|
||||
--
|
||||
1.7.10.1
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
From: Jason Gerecke <killertofu@gmail.com>
|
||||
Date: Tue, 3 Apr 2012 15:48:35 -0700
|
||||
Subject: Input: wacom - add Intuos5 Touch Ring/ExpressKey support
|
||||
|
||||
commit f860e581fd473250c6dcbd3e13d576b6197e4694 upstream.
|
||||
|
||||
Intuos5 uses a new report type for Touch Ring and ExpressKey data.
|
||||
Note that data from the capacitive sensors present on the ExpressKeys
|
||||
will be ignored until a proper way is found to expose it.
|
||||
|
||||
Signed-off-by: Jason Gerecke <killertofu@gmail.com>
|
||||
Reviewed-by: Chris Bagwell <chris@cnpbagwell.com>
|
||||
Reviewed-by: Ping Cheng <pingc@wacom.com>
|
||||
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
|
||||
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
|
||||
---
|
||||
drivers/input/tablet/wacom_wac.c | 33 +++++++++++++++++++++++++++++++--
|
||||
drivers/input/tablet/wacom_wac.h | 1 +
|
||||
2 files changed, 32 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
|
||||
index f159e9d90d4a..b5176a073c83 100644
|
||||
--- a/drivers/input/tablet/wacom_wac.c
|
||||
+++ b/drivers/input/tablet/wacom_wac.c
|
||||
@@ -484,7 +484,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
|
||||
int idx = 0, result;
|
||||
|
||||
if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_INTUOSREAD
|
||||
- && data[0] != WACOM_REPORT_INTUOSWRITE && data[0] != WACOM_REPORT_INTUOSPAD) {
|
||||
+ && data[0] != WACOM_REPORT_INTUOSWRITE && data[0] != WACOM_REPORT_INTUOSPAD
|
||||
+ && data[0] != WACOM_REPORT_INTUOS5PAD) {
|
||||
dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
|
||||
return 0;
|
||||
}
|
||||
@@ -494,7 +495,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
|
||||
idx = data[1] & 0x01;
|
||||
|
||||
/* pad packets. Works as a second tool and is always in prox */
|
||||
- if (data[0] == WACOM_REPORT_INTUOSPAD) {
|
||||
+ if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD) {
|
||||
if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
|
||||
input_report_key(input, BTN_0, (data[2] & 0x01));
|
||||
input_report_key(input, BTN_1, (data[3] & 0x01));
|
||||
@@ -570,6 +571,34 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
|
||||
input_report_key(input, wacom->tool[1], 0);
|
||||
input_report_abs(input, ABS_MISC, 0);
|
||||
}
|
||||
+ } else if (features->type >= INTUOS5S && features->type <= INTUOS5L) {
|
||||
+ int i;
|
||||
+
|
||||
+ /* Touch ring mode switch has no capacitive sensor */
|
||||
+ input_report_key(input, BTN_0, (data[3] & 0x01));
|
||||
+
|
||||
+ /*
|
||||
+ * ExpressKeys on Intuos5 have a capacitive sensor in
|
||||
+ * addition to the mechanical switch. Switch data is
|
||||
+ * stored in data[4], capacitive data in data[5].
|
||||
+ */
|
||||
+ for (i = 0; i < 8; i++)
|
||||
+ input_report_key(input, BTN_1 + i, data[4] & (1 << i));
|
||||
+
|
||||
+ if (data[2] & 0x80) {
|
||||
+ input_report_abs(input, ABS_WHEEL, (data[2] & 0x7f));
|
||||
+ } else {
|
||||
+ /* Out of proximity, clear wheel value. */
|
||||
+ input_report_abs(input, ABS_WHEEL, 0);
|
||||
+ }
|
||||
+
|
||||
+ if (data[2] | (data[3] & 0x01) | data[4]) {
|
||||
+ input_report_key(input, wacom->tool[1], 1);
|
||||
+ input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
|
||||
+ } else {
|
||||
+ input_report_key(input, wacom->tool[1], 0);
|
||||
+ input_report_abs(input, ABS_MISC, 0);
|
||||
+ }
|
||||
} else {
|
||||
if (features->type == WACOM_21UX2) {
|
||||
input_report_key(input, BTN_0, (data[5] & 0x01));
|
||||
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
|
||||
index 0aa00ce5fd7d..17ba1868f0cd 100644
|
||||
--- a/drivers/input/tablet/wacom_wac.h
|
||||
+++ b/drivers/input/tablet/wacom_wac.h
|
||||
@@ -38,6 +38,7 @@
|
||||
#define WACOM_REPORT_INTUOSREAD 5
|
||||
#define WACOM_REPORT_INTUOSWRITE 6
|
||||
#define WACOM_REPORT_INTUOSPAD 12
|
||||
+#define WACOM_REPORT_INTUOS5PAD 3
|
||||
#define WACOM_REPORT_TPC1FG 6
|
||||
#define WACOM_REPORT_TPC2FG 13
|
||||
#define WACOM_REPORT_TPCHID 15
|
||||
--
|
||||
1.7.10.1
|
||||
|
|
@ -1,163 +0,0 @@
|
|||
From: Jason Gerecke <killertofu@gmail.com>
|
||||
Date: Tue, 3 Apr 2012 15:50:37 -0700
|
||||
Subject: Input: wacom - add Intuos5 Touch Ring LED support
|
||||
|
||||
commit 9b5b95dd516a13d53ecf9217672d2116f05097bc upstream.
|
||||
|
||||
The Touch Ring LEDs on Intuos5 tablets use a different report
|
||||
format which supports only 4 levels of brightness. We remap
|
||||
the 7-bit value obtained from sysfs to an appropriate value
|
||||
for the tablet. Control of the crop mark LEDs (new to the I5)
|
||||
is left for a later patch.
|
||||
|
||||
Signed-off-by: Jason Gerecke <killertofu@gmail.com>
|
||||
Reviewed-by: Ping Cheng <pingc@wacom.com>
|
||||
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
|
||||
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
|
||||
---
|
||||
Documentation/ABI/testing/sysfs-driver-wacom | 15 +++---
|
||||
drivers/input/tablet/wacom_sys.c | 67 ++++++++++++++++++++++----
|
||||
2 files changed, 65 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/Documentation/ABI/testing/sysfs-driver-wacom b/Documentation/ABI/testing/sysfs-driver-wacom
|
||||
index 0130d6683c14..5e9cbdc7486e 100644
|
||||
--- a/Documentation/ABI/testing/sysfs-driver-wacom
|
||||
+++ b/Documentation/ABI/testing/sysfs-driver-wacom
|
||||
@@ -15,9 +15,10 @@ Contact: linux-input@vger.kernel.org
|
||||
Description:
|
||||
Attribute group for control of the status LEDs and the OLEDs.
|
||||
This attribute group is only available for Intuos 4 M, L,
|
||||
- and XL (with LEDs and OLEDs) and Cintiq 21UX2 and Cintiq 24HD
|
||||
- (LEDs only). Therefore its presence implicitly signifies the
|
||||
- presence of said LEDs and OLEDs on the tablet device.
|
||||
+ and XL (with LEDs and OLEDs), Intuos 5 (LEDs only), and Cintiq
|
||||
+ 21UX2 and Cintiq 24HD (LEDs only). Therefore its presence
|
||||
+ implicitly signifies the presence of said LEDs and OLEDs on the
|
||||
+ tablet device.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status0_luminance
|
||||
Date: August 2011
|
||||
@@ -40,10 +41,10 @@ What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led0
|
||||
Date: August 2011
|
||||
Contact: linux-input@vger.kernel.org
|
||||
Description:
|
||||
- Writing to this file sets which one of the four (for Intuos 4)
|
||||
- or of the right four (for Cintiq 21UX2 and Cintiq 24HD) status
|
||||
- LEDs is active (0..3). The other three LEDs on the same side are
|
||||
- always inactive.
|
||||
+ Writing to this file sets which one of the four (for Intuos 4
|
||||
+ and Intuos 5) or of the right four (for Cintiq 21UX2 and Cintiq
|
||||
+ 24HD) status LEDs is active (0..3). The other three LEDs on the
|
||||
+ same side are always inactive.
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led1_select
|
||||
Date: September 2011
|
||||
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
|
||||
index 8a5fad186140..f470e41d23e7 100644
|
||||
--- a/drivers/input/tablet/wacom_sys.c
|
||||
+++ b/drivers/input/tablet/wacom_sys.c
|
||||
@@ -574,23 +574,39 @@ static void wacom_remove_shared_data(struct wacom_wac *wacom)
|
||||
static int wacom_led_control(struct wacom *wacom)
|
||||
{
|
||||
unsigned char *buf;
|
||||
- int retval, led = 0;
|
||||
+ int retval;
|
||||
|
||||
buf = kzalloc(9, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
- if (wacom->wacom_wac.features.type == WACOM_21UX2 ||
|
||||
- wacom->wacom_wac.features.type == WACOM_24HD)
|
||||
- led = (wacom->led.select[1] << 4) | 0x40;
|
||||
+ if (wacom->wacom_wac.features.type >= INTUOS5S &&
|
||||
+ wacom->wacom_wac.features.type <= INTUOS5L) {
|
||||
+ /*
|
||||
+ * Touch Ring and crop mark LED luminance may take on
|
||||
+ * one of four values:
|
||||
+ * 0 = Low; 1 = Medium; 2 = High; 3 = Off
|
||||
+ */
|
||||
+ int ring_led = wacom->led.select[0] & 0x03;
|
||||
+ int ring_lum = (((wacom->led.llv & 0x60) >> 5) - 1) & 0x03;
|
||||
+ int crop_lum = 0;
|
||||
|
||||
- led |= wacom->led.select[0] | 0x4;
|
||||
+ buf[0] = WAC_CMD_LED_CONTROL;
|
||||
+ buf[1] = (crop_lum << 4) | (ring_lum << 2) | (ring_led);
|
||||
+ }
|
||||
+ else {
|
||||
+ int led = wacom->led.select[0] | 0x4;
|
||||
|
||||
- buf[0] = WAC_CMD_LED_CONTROL;
|
||||
- buf[1] = led;
|
||||
- buf[2] = wacom->led.llv;
|
||||
- buf[3] = wacom->led.hlv;
|
||||
- buf[4] = wacom->led.img_lum;
|
||||
+ if (wacom->wacom_wac.features.type == WACOM_21UX2 ||
|
||||
+ wacom->wacom_wac.features.type == WACOM_24HD)
|
||||
+ led |= (wacom->led.select[1] << 4) | 0x40;
|
||||
+
|
||||
+ buf[0] = WAC_CMD_LED_CONTROL;
|
||||
+ buf[1] = led;
|
||||
+ buf[2] = wacom->led.llv;
|
||||
+ buf[3] = wacom->led.hlv;
|
||||
+ buf[4] = wacom->led.img_lum;
|
||||
+ }
|
||||
|
||||
retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL,
|
||||
buf, 9, WAC_CMD_RETRIES);
|
||||
@@ -783,6 +799,17 @@ static struct attribute_group intuos4_led_attr_group = {
|
||||
.attrs = intuos4_led_attrs,
|
||||
};
|
||||
|
||||
+static struct attribute *intuos5_led_attrs[] = {
|
||||
+ &dev_attr_status0_luminance.attr,
|
||||
+ &dev_attr_status_led0_select.attr,
|
||||
+ NULL
|
||||
+};
|
||||
+
|
||||
+static struct attribute_group intuos5_led_attr_group = {
|
||||
+ .name = "wacom_led",
|
||||
+ .attrs = intuos5_led_attrs,
|
||||
+};
|
||||
+
|
||||
static int wacom_initialize_leds(struct wacom *wacom)
|
||||
{
|
||||
int error;
|
||||
@@ -812,6 +839,19 @@ static int wacom_initialize_leds(struct wacom *wacom)
|
||||
&cintiq_led_attr_group);
|
||||
break;
|
||||
|
||||
+ case INTUOS5S:
|
||||
+ case INTUOS5:
|
||||
+ case INTUOS5L:
|
||||
+ wacom->led.select[0] = 0;
|
||||
+ wacom->led.select[1] = 0;
|
||||
+ wacom->led.llv = 32;
|
||||
+ wacom->led.hlv = 0;
|
||||
+ wacom->led.img_lum = 0;
|
||||
+
|
||||
+ error = sysfs_create_group(&wacom->intf->dev.kobj,
|
||||
+ &intuos5_led_attr_group);
|
||||
+ break;
|
||||
+
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -840,6 +880,13 @@ static void wacom_destroy_leds(struct wacom *wacom)
|
||||
sysfs_remove_group(&wacom->intf->dev.kobj,
|
||||
&cintiq_led_attr_group);
|
||||
break;
|
||||
+
|
||||
+ case INTUOS5S:
|
||||
+ case INTUOS5:
|
||||
+ case INTUOS5L:
|
||||
+ sysfs_remove_group(&wacom->intf->dev.kobj,
|
||||
+ &intuos5_led_attr_group);
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10.1
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
From: Jason Gerecke <killertofu@gmail.com>
|
||||
Date: Tue, 3 Apr 2012 15:50:40 -0700
|
||||
Subject: Input: wacom - add Intuos5 multitouch sensor support
|
||||
|
||||
commit ae584ca473289377dd7fd8c61439db4bfab5489a upstream.
|
||||
|
||||
Intuos5 tablets with PTH-* model numbers include a multitouch sensor
|
||||
which use the same touch reports as the 3rd-generation Bamboo. No
|
||||
useful information is in the HID descriptor for the touch interface
|
||||
so hardcoded values are used during setup.
|
||||
|
||||
Signed-off-by: Jason Gerecke <killertofu@gmail.com>
|
||||
Reviewed-by: Chris Bagwell <chris@cnpbagwell.com>
|
||||
Reviewed-by: Ping Cheng <pingc@wacom.com>
|
||||
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
|
||||
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
|
||||
---
|
||||
drivers/input/tablet/wacom_sys.c | 25 +++++++++++++++
|
||||
drivers/input/tablet/wacom_wac.c | 64 +++++++++++++++++++++++++++++++++++---
|
||||
2 files changed, 84 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
|
||||
index f470e41d23e7..4d52e5924801 100644
|
||||
--- a/drivers/input/tablet/wacom_sys.c
|
||||
+++ b/drivers/input/tablet/wacom_sys.c
|
||||
@@ -233,6 +233,9 @@ static int wacom_parse_logical_collection(unsigned char *report,
|
||||
* 3rd gen Bamboo Touch no longer define a Digitizer-Finger Pysical
|
||||
* Collection. Instead they define a Logical Collection with a single
|
||||
* Logical Maximum for both X and Y.
|
||||
+ *
|
||||
+ * Intuos5 touch interface does not contain useful data. We deal with
|
||||
+ * this after returning from this function.
|
||||
*/
|
||||
static int wacom_parse_hid(struct usb_interface *intf,
|
||||
struct hid_descriptor *hid_desc,
|
||||
@@ -1087,6 +1090,28 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
if (error)
|
||||
goto fail3;
|
||||
|
||||
+ /*
|
||||
+ * Intuos5 has no useful data about its touch interface in its
|
||||
+ * HID descriptor. If this is the touch interface (wMaxPacketSize
|
||||
+ * of WACOM_PKGLEN_BBTOUCH3), override the table values.
|
||||
+ */
|
||||
+ if (features->type >= INTUOS5S && features->type <= INTUOS5L) {
|
||||
+ if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) {
|
||||
+ features->device_type = BTN_TOOL_FINGER;
|
||||
+ features->pktlen = WACOM_PKGLEN_BBTOUCH3;
|
||||
+
|
||||
+ features->x_phy =
|
||||
+ (features->x_max * 100) / features->x_resolution;
|
||||
+ features->y_phy =
|
||||
+ (features->y_max * 100) / features->y_resolution;
|
||||
+
|
||||
+ features->x_max = 4096;
|
||||
+ features->y_max = 4096;
|
||||
+ } else {
|
||||
+ features->device_type = BTN_TOOL_PEN;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
wacom_setup_device_quirks(features);
|
||||
|
||||
strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
|
||||
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
|
||||
index b5176a073c83..d96e186f71dc 100644
|
||||
--- a/drivers/input/tablet/wacom_wac.c
|
||||
+++ b/drivers/input/tablet/wacom_wac.c
|
||||
@@ -321,6 +321,9 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
|
||||
|
||||
/* Enter report */
|
||||
if ((data[1] & 0xfc) == 0xc0) {
|
||||
+ if (features->type >= INTUOS5S && features->type <= INTUOS5L)
|
||||
+ wacom->shared->stylus_in_proximity = true;
|
||||
+
|
||||
/* serial number of the tool */
|
||||
wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
|
||||
(data[4] << 20) + (data[5] << 12) +
|
||||
@@ -406,6 +409,9 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
|
||||
|
||||
/* Exit report */
|
||||
if ((data[1] & 0xfe) == 0x80) {
|
||||
+ if (features->type >= INTUOS5S && features->type <= INTUOS5L)
|
||||
+ wacom->shared->stylus_in_proximity = false;
|
||||
+
|
||||
/*
|
||||
* Reset all states otherwise we lose the initial states
|
||||
* when in-prox next time
|
||||
@@ -1140,9 +1146,6 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
|
||||
case INTUOS4S:
|
||||
case INTUOS4:
|
||||
case INTUOS4L:
|
||||
- case INTUOS5S:
|
||||
- case INTUOS5:
|
||||
- case INTUOS5L:
|
||||
case CINTIQ:
|
||||
case WACOM_BEE:
|
||||
case WACOM_21UX2:
|
||||
@@ -1150,6 +1153,15 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
|
||||
sync = wacom_intuos_irq(wacom_wac);
|
||||
break;
|
||||
|
||||
+ case INTUOS5S:
|
||||
+ case INTUOS5:
|
||||
+ case INTUOS5L:
|
||||
+ if (len == WACOM_PKGLEN_BBTOUCH3)
|
||||
+ sync = wacom_bpt3_touch(wacom_wac);
|
||||
+ else
|
||||
+ sync = wacom_intuos_irq(wacom_wac);
|
||||
+ break;
|
||||
+
|
||||
case TABLETPC:
|
||||
case TABLETPC2FG:
|
||||
sync = wacom_tpc_irq(wacom_wac, len);
|
||||
@@ -1224,7 +1236,8 @@ void wacom_setup_device_quirks(struct wacom_features *features)
|
||||
|
||||
/* these device have multiple inputs */
|
||||
if (features->type == TABLETPC || features->type == TABLETPC2FG ||
|
||||
- features->type == BAMBOO_PT || features->type == WIRELESS)
|
||||
+ features->type == BAMBOO_PT || features->type == WIRELESS ||
|
||||
+ (features->type >= INTUOS5S && features->type <= INTUOS5L))
|
||||
features->quirks |= WACOM_QUIRK_MULTI_INPUT;
|
||||
|
||||
/* quirk for bamboo touch with 2 low res touches */
|
||||
@@ -1393,13 +1406,54 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
|
||||
case INTUOS5:
|
||||
case INTUOS5L:
|
||||
+ if (features->device_type == BTN_TOOL_PEN) {
|
||||
+ __set_bit(BTN_7, input_dev->keybit);
|
||||
+ __set_bit(BTN_8, input_dev->keybit);
|
||||
+ }
|
||||
+ /* fall through */
|
||||
+
|
||||
+ case INTUOS5S:
|
||||
+ __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
|
||||
+
|
||||
+ if (features->device_type == BTN_TOOL_PEN) {
|
||||
+ for (i = 0; i < 7; i++)
|
||||
+ __set_bit(BTN_0 + i, input_dev->keybit);
|
||||
+
|
||||
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0,
|
||||
+ features->distance_max,
|
||||
+ 0, 0);
|
||||
+
|
||||
+ input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
|
||||
+
|
||||
+ wacom_setup_intuos(wacom_wac);
|
||||
+ } else if (features->device_type == BTN_TOOL_FINGER) {
|
||||
+ __clear_bit(ABS_MISC, input_dev->absbit);
|
||||
+
|
||||
+ __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
|
||||
+ __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
|
||||
+ __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
|
||||
+ __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
|
||||
+
|
||||
+ input_mt_init_slots(input_dev, 16);
|
||||
+
|
||||
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
|
||||
+ 0, 255, 0, 0);
|
||||
+
|
||||
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
|
||||
+ 0, features->x_max,
|
||||
+ features->x_fuzz, 0);
|
||||
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
|
||||
+ 0, features->y_max,
|
||||
+ features->y_fuzz, 0);
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
case INTUOS4:
|
||||
case INTUOS4L:
|
||||
__set_bit(BTN_7, input_dev->keybit);
|
||||
__set_bit(BTN_8, input_dev->keybit);
|
||||
/* fall through */
|
||||
|
||||
- case INTUOS5S:
|
||||
case INTUOS4S:
|
||||
for (i = 0; i < 7; i++)
|
||||
__set_bit(BTN_0 + i, input_dev->keybit);
|
||||
--
|
||||
1.7.10.1
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
From: Ping Cheng <pinglinux@gmail.com>
|
||||
Date: Sun, 29 Apr 2012 21:09:17 -0700
|
||||
Subject: Input: wacom - retrieve maximum number of touch points
|
||||
|
||||
commit f393ee2b814e3291c12565000210b3cf10aa5c1d upstream.
|
||||
|
||||
>From the HID usage table when it is supported.
|
||||
|
||||
Tested-by: Jason Gerecke <killertofu@gmail.com>
|
||||
Signed-off-by: Chris Bagwell <chris@cnpbagwell.com>
|
||||
Signed-off-by: Ping Cheng <pingc@wacom.com>
|
||||
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
|
||||
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
|
||||
---
|
||||
drivers/input/tablet/wacom_sys.c | 29 ++++++++++++++++++-
|
||||
drivers/input/tablet/wacom_wac.c | 59 +++++++++++++++++++++++---------------
|
||||
drivers/input/tablet/wacom_wac.h | 1 +
|
||||
3 files changed, 65 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
|
||||
index 4d52e5924801..53598c2065cf 100644
|
||||
--- a/drivers/input/tablet/wacom_sys.c
|
||||
+++ b/drivers/input/tablet/wacom_sys.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#define HID_USAGE_Y_TILT 0x3e
|
||||
#define HID_USAGE_FINGER 0x22
|
||||
#define HID_USAGE_STYLUS 0x20
|
||||
+#define HID_USAGE_CONTACTMAX 0x55
|
||||
#define HID_COLLECTION 0xa1
|
||||
#define HID_COLLECTION_LOGICAL 0x02
|
||||
#define HID_COLLECTION_END 0xc0
|
||||
@@ -201,6 +202,27 @@ static int wacom_parse_logical_collection(unsigned char *report,
|
||||
return length;
|
||||
}
|
||||
|
||||
+static void wacom_retrieve_report_data(struct usb_interface *intf,
|
||||
+ struct wacom_features *features)
|
||||
+{
|
||||
+ int result = 0;
|
||||
+ unsigned char *rep_data;
|
||||
+
|
||||
+ rep_data = kmalloc(2, GFP_KERNEL);
|
||||
+ if (rep_data) {
|
||||
+
|
||||
+ rep_data[0] = 12;
|
||||
+ result = wacom_get_report(intf, WAC_HID_FEATURE_REPORT,
|
||||
+ rep_data[0], &rep_data, 2,
|
||||
+ WAC_MSG_RETRIES);
|
||||
+
|
||||
+ if (result >= 0 && rep_data[1] > 2)
|
||||
+ features->touch_max = rep_data[1];
|
||||
+
|
||||
+ kfree(rep_data);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Interface Descriptor of wacom devices can be incomplete and
|
||||
* inconsistent so wacom_features table is used to store stylus
|
||||
@@ -377,6 +399,11 @@ static int wacom_parse_hid(struct usb_interface *intf,
|
||||
pen = 1;
|
||||
i++;
|
||||
break;
|
||||
+
|
||||
+ case HID_USAGE_CONTACTMAX:
|
||||
+ wacom_retrieve_report_data(intf, features);
|
||||
+ i++;
|
||||
+ break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1085,7 +1112,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
|
||||
endpoint = &intf->cur_altsetting->endpoint[0].desc;
|
||||
|
||||
- /* Retrieve the physical and logical size for OEM devices */
|
||||
+ /* Retrieve the physical and logical size for touch devices */
|
||||
error = wacom_retrieve_hid_descriptor(intf, features);
|
||||
if (error)
|
||||
goto fail3;
|
||||
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
|
||||
index d96e186f71dc..e5cd0e57d178 100644
|
||||
--- a/drivers/input/tablet/wacom_wac.c
|
||||
+++ b/drivers/input/tablet/wacom_wac.c
|
||||
@@ -1434,7 +1434,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
|
||||
__set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
|
||||
|
||||
- input_mt_init_slots(input_dev, 16);
|
||||
+ input_mt_init_slots(input_dev, features->touch_max);
|
||||
|
||||
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
|
||||
0, 255, 0, 0);
|
||||
@@ -1467,7 +1467,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
case TABLETPC2FG:
|
||||
if (features->device_type == BTN_TOOL_FINGER) {
|
||||
|
||||
- input_mt_init_slots(input_dev, 2);
|
||||
+ input_mt_init_slots(input_dev, features->touch_max);
|
||||
input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
|
||||
0, MT_TOOL_MAX, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
|
||||
@@ -1522,6 +1522,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
|
||||
__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
|
||||
__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
|
||||
+ input_mt_init_slots(input_dev, features->touch_max);
|
||||
|
||||
if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
|
||||
__set_bit(BTN_TOOL_TRIPLETAP,
|
||||
@@ -1529,13 +1530,9 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
__set_bit(BTN_TOOL_QUADTAP,
|
||||
input_dev->keybit);
|
||||
|
||||
- input_mt_init_slots(input_dev, 16);
|
||||
-
|
||||
input_set_abs_params(input_dev,
|
||||
ABS_MT_TOUCH_MAJOR,
|
||||
0, 255, 0, 0);
|
||||
- } else {
|
||||
- input_mt_init_slots(input_dev, 2);
|
||||
}
|
||||
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
|
||||
@@ -1724,13 +1721,16 @@ static const struct wacom_features wacom_features_0xBC =
|
||||
63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
static const struct wacom_features wacom_features_0x26 =
|
||||
{ "Wacom Intuos5 touch S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047,
|
||||
- 63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
+ 63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
+ .touch_max = 16 };
|
||||
static const struct wacom_features wacom_features_0x27 =
|
||||
{ "Wacom Intuos5 touch M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047,
|
||||
- 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
+ 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
+ .touch_max = 16 };
|
||||
static const struct wacom_features wacom_features_0x28 =
|
||||
{ "Wacom Intuos5 touch L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047,
|
||||
- 63, INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
+ 63, INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
|
||||
+ .touch_max = 16 };
|
||||
static const struct wacom_features wacom_features_0x29 =
|
||||
{ "Wacom Intuos5 S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047,
|
||||
63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
|
||||
@@ -1778,13 +1778,16 @@ static const struct wacom_features wacom_features_0x9F =
|
||||
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
static const struct wacom_features wacom_features_0xE2 =
|
||||
{ "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255,
|
||||
- 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
+ 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
+ .touch_max = 2 };
|
||||
static const struct wacom_features wacom_features_0xE3 =
|
||||
{ "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255,
|
||||
- 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
+ 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
+ .touch_max = 2 };
|
||||
static const struct wacom_features wacom_features_0xE6 =
|
||||
{ "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255,
|
||||
- 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
+ 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
+ .touch_max = 2 };
|
||||
static const struct wacom_features wacom_features_0xEC =
|
||||
{ "Wacom ISDv4 EC", WACOM_PKGLEN_GRAPHIRE, 25710, 14500, 255,
|
||||
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
@@ -1793,19 +1796,22 @@ static const struct wacom_features wacom_features_0x47 =
|
||||
31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
static const struct wacom_features wacom_features_0x84 =
|
||||
{ "Wacom Wireless Receiver", WACOM_PKGLEN_WIRELESS, 0, 0, 0,
|
||||
- 0, WIRELESS, 0, 0 };
|
||||
+ 0, WIRELESS, 0, 0, .touch_max = 16 };
|
||||
static const struct wacom_features wacom_features_0xD0 =
|
||||
{ "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
|
||||
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
+ .touch_max = 2 };
|
||||
static const struct wacom_features wacom_features_0xD1 =
|
||||
{ "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
|
||||
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
+ .touch_max = 2 };
|
||||
static const struct wacom_features wacom_features_0xD2 =
|
||||
{ "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
|
||||
31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
static const struct wacom_features wacom_features_0xD3 =
|
||||
{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
|
||||
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
+ .touch_max = 2 };
|
||||
static const struct wacom_features wacom_features_0xD4 =
|
||||
{ "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
|
||||
31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
@@ -1814,28 +1820,35 @@ static const struct wacom_features wacom_features_0xD5 =
|
||||
31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
static const struct wacom_features wacom_features_0xD6 =
|
||||
{ "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
|
||||
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
+ .touch_max = 2 };
|
||||
static const struct wacom_features wacom_features_0xD7 =
|
||||
{ "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
|
||||
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
+ .touch_max = 2 };
|
||||
static const struct wacom_features wacom_features_0xD8 =
|
||||
{ "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
|
||||
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
+ .touch_max = 2 };
|
||||
static const struct wacom_features wacom_features_0xDA =
|
||||
{ "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
|
||||
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
+ .touch_max = 2 };
|
||||
static struct wacom_features wacom_features_0xDB =
|
||||
{ "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
|
||||
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
+ .touch_max = 2 };
|
||||
static const struct wacom_features wacom_features_0xDD =
|
||||
{ "Wacom Bamboo Connect", WACOM_PKGLEN_BBPEN, 14720, 9200, 1023,
|
||||
31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
static const struct wacom_features wacom_features_0xDE =
|
||||
{ "Wacom Bamboo 16FG 4x5", WACOM_PKGLEN_BBPEN, 14720, 9200, 1023,
|
||||
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
+ .touch_max = 16 };
|
||||
static const struct wacom_features wacom_features_0xDF =
|
||||
{ "Wacom Bamboo 16FG 6x8", WACOM_PKGLEN_BBPEN, 21648, 13700, 1023,
|
||||
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
+ .touch_max = 16 };
|
||||
static const struct wacom_features wacom_features_0x6004 =
|
||||
{ "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255,
|
||||
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
|
||||
index 17ba1868f0cd..321269c1ac4c 100644
|
||||
--- a/drivers/input/tablet/wacom_wac.h
|
||||
+++ b/drivers/input/tablet/wacom_wac.h
|
||||
@@ -99,6 +99,7 @@ struct wacom_features {
|
||||
int pressure_fuzz;
|
||||
int distance_fuzz;
|
||||
unsigned quirks;
|
||||
+ unsigned touch_max;
|
||||
};
|
||||
|
||||
struct wacom_shared {
|
||||
--
|
||||
1.7.10.1
|
||||
|
|
@ -1,430 +0,0 @@
|
|||
From: Ping Cheng <pinglinux@gmail.com>
|
||||
Date: Sun, 29 Apr 2012 21:09:18 -0700
|
||||
Subject: Input: wacom - add 0xE5 (MT device) support
|
||||
|
||||
commit 1963518b9b1b8019d33b4b08deee6f873ffa2730 upstream.
|
||||
|
||||
Main part of patch is adding support for a new Wacom MT touch
|
||||
packet and labels these devices using MTSCREEN type.
|
||||
|
||||
Other items of interest:
|
||||
|
||||
Delete some duplicate code in HID parsing for Y info since
|
||||
its already done in X path.
|
||||
|
||||
In wacom_query_tablet_data(), only invoke the set report
|
||||
that requests tablets to send Wacom Touch packets for
|
||||
Finger interfaces. Mostly, this is to make code intent clear.
|
||||
|
||||
Tested-by: Jason Gerecke <killertofu@gmail.com>
|
||||
Signed-off-by: Chris Bagwell <chris@cnpbagwell.com>
|
||||
Signed-off-by: Ping Cheng <pingc@wacom.com>
|
||||
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
|
||||
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
|
||||
---
|
||||
drivers/input/tablet/wacom.h | 4 +-
|
||||
drivers/input/tablet/wacom_sys.c | 91 ++++++++++++++++++++---------------
|
||||
drivers/input/tablet/wacom_wac.c | 99 ++++++++++++++++++++++++++++++++++++--
|
||||
drivers/input/tablet/wacom_wac.h | 8 +++
|
||||
4 files changed, 157 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
|
||||
index b4842d0e61dd..b79d45198d82 100644
|
||||
--- a/drivers/input/tablet/wacom.h
|
||||
+++ b/drivers/input/tablet/wacom.h
|
||||
@@ -135,6 +135,6 @@ extern const struct usb_device_id wacom_ids[];
|
||||
|
||||
void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
|
||||
void wacom_setup_device_quirks(struct wacom_features *features);
|
||||
-void wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
- struct wacom_wac *wacom_wac);
|
||||
+int wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
+ struct wacom_wac *wacom_wac);
|
||||
#endif
|
||||
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
|
||||
index 53598c2065cf..734671aeb572 100644
|
||||
--- a/drivers/input/tablet/wacom_sys.c
|
||||
+++ b/drivers/input/tablet/wacom_sys.c
|
||||
@@ -317,6 +317,10 @@ static int wacom_parse_hid(struct usb_interface *intf,
|
||||
/* need to reset back */
|
||||
features->pktlen = WACOM_PKGLEN_TPC2FG;
|
||||
}
|
||||
+
|
||||
+ if (features->type == MTSCREEN)
|
||||
+ features->pktlen = WACOM_PKGLEN_MTOUCH;
|
||||
+
|
||||
if (features->type == BAMBOO_PT) {
|
||||
/* need to reset back */
|
||||
features->pktlen = WACOM_PKGLEN_BBTOUCH;
|
||||
@@ -349,18 +353,15 @@ static int wacom_parse_hid(struct usb_interface *intf,
|
||||
case HID_USAGE_Y:
|
||||
if (usage == WCM_DESKTOP) {
|
||||
if (finger) {
|
||||
- features->device_type = BTN_TOOL_FINGER;
|
||||
- if (features->type == TABLETPC2FG) {
|
||||
- /* need to reset back */
|
||||
- features->pktlen = WACOM_PKGLEN_TPC2FG;
|
||||
+ int type = features->type;
|
||||
+
|
||||
+ if (type == TABLETPC2FG || type == MTSCREEN) {
|
||||
features->y_max =
|
||||
get_unaligned_le16(&report[i + 3]);
|
||||
features->y_phy =
|
||||
get_unaligned_le16(&report[i + 6]);
|
||||
i += 7;
|
||||
- } else if (features->type == BAMBOO_PT) {
|
||||
- /* need to reset back */
|
||||
- features->pktlen = WACOM_PKGLEN_BBTOUCH;
|
||||
+ } else if (type == BAMBOO_PT) {
|
||||
features->y_phy =
|
||||
get_unaligned_le16(&report[i + 3]);
|
||||
features->y_max =
|
||||
@@ -374,10 +375,6 @@ static int wacom_parse_hid(struct usb_interface *intf,
|
||||
i += 4;
|
||||
}
|
||||
} else if (pen) {
|
||||
- /* penabled only accepts exact bytes of data */
|
||||
- if (features->type == TABLETPC2FG)
|
||||
- features->pktlen = WACOM_PKGLEN_GRAPHIRE;
|
||||
- features->device_type = BTN_TOOL_PEN;
|
||||
features->y_max =
|
||||
get_unaligned_le16(&report[i + 3]);
|
||||
i += 4;
|
||||
@@ -440,22 +437,29 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
|
||||
if (!rep_data)
|
||||
return error;
|
||||
|
||||
- /* ask to report tablet data if it is MT Tablet PC or
|
||||
- * not a Tablet PC */
|
||||
- if (features->type == TABLETPC2FG) {
|
||||
- do {
|
||||
- rep_data[0] = 3;
|
||||
- rep_data[1] = 4;
|
||||
- rep_data[2] = 0;
|
||||
- rep_data[3] = 0;
|
||||
- report_id = 3;
|
||||
- error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
|
||||
- report_id, rep_data, 4, 1);
|
||||
- if (error >= 0)
|
||||
- error = wacom_get_report(intf,
|
||||
- WAC_HID_FEATURE_REPORT,
|
||||
- report_id, rep_data, 4, 1);
|
||||
- } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES);
|
||||
+ /* ask to report Wacom data */
|
||||
+ if (features->device_type == BTN_TOOL_FINGER) {
|
||||
+ /* if it is an MT Tablet PC touch */
|
||||
+ if (features->type == TABLETPC2FG ||
|
||||
+ features->type == MTSCREEN) {
|
||||
+ do {
|
||||
+ rep_data[0] = 3;
|
||||
+ rep_data[1] = 4;
|
||||
+ rep_data[2] = 0;
|
||||
+ rep_data[3] = 0;
|
||||
+ report_id = 3;
|
||||
+ error = wacom_set_report(intf,
|
||||
+ WAC_HID_FEATURE_REPORT,
|
||||
+ report_id,
|
||||
+ rep_data, 4, 1);
|
||||
+ if (error >= 0)
|
||||
+ error = wacom_get_report(intf,
|
||||
+ WAC_HID_FEATURE_REPORT,
|
||||
+ report_id,
|
||||
+ rep_data, 4, 1);
|
||||
+ } while ((error < 0 || rep_data[1] != 4) &&
|
||||
+ limit++ < WAC_MSG_RETRIES);
|
||||
+ }
|
||||
} else if (features->type != TABLETPC &&
|
||||
features->type != WIRELESS &&
|
||||
features->device_type == BTN_TOOL_PEN) {
|
||||
@@ -477,7 +481,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
|
||||
}
|
||||
|
||||
static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
|
||||
- struct wacom_features *features)
|
||||
+ struct wacom_features *features)
|
||||
{
|
||||
int error = 0;
|
||||
struct usb_host_interface *interface = intf->cur_altsetting;
|
||||
@@ -505,10 +509,13 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
|
||||
}
|
||||
}
|
||||
|
||||
- /* only Tablet PCs and Bamboo P&T need to retrieve the info */
|
||||
- if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) &&
|
||||
- (features->type != BAMBOO_PT))
|
||||
+ /* only devices that support touch need to retrieve the info */
|
||||
+ if (features->type != TABLETPC &&
|
||||
+ features->type != TABLETPC2FG &&
|
||||
+ features->type != BAMBOO_PT &&
|
||||
+ features->type != MTSCREEN) {
|
||||
goto out;
|
||||
+ }
|
||||
|
||||
if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
|
||||
if (usb_get_extra_descriptor(&interface->endpoint[0],
|
||||
@@ -978,8 +985,10 @@ static int wacom_register_input(struct wacom *wacom)
|
||||
int error;
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
- if (!input_dev)
|
||||
- return -ENOMEM;
|
||||
+ if (!input_dev) {
|
||||
+ error = -ENOMEM;
|
||||
+ goto fail1;
|
||||
+ }
|
||||
|
||||
input_dev->name = wacom_wac->name;
|
||||
input_dev->dev.parent = &intf->dev;
|
||||
@@ -989,14 +998,20 @@ static int wacom_register_input(struct wacom *wacom)
|
||||
input_set_drvdata(input_dev, wacom);
|
||||
|
||||
wacom_wac->input = input_dev;
|
||||
- wacom_setup_input_capabilities(input_dev, wacom_wac);
|
||||
+ error = wacom_setup_input_capabilities(input_dev, wacom_wac);
|
||||
+ if (error)
|
||||
+ goto fail1;
|
||||
|
||||
error = input_register_device(input_dev);
|
||||
- if (error) {
|
||||
- input_free_device(input_dev);
|
||||
- wacom_wac->input = NULL;
|
||||
- }
|
||||
+ if (error)
|
||||
+ goto fail2;
|
||||
|
||||
+ return 0;
|
||||
+
|
||||
+fail2:
|
||||
+ input_free_device(input_dev);
|
||||
+ wacom_wac->input = NULL;
|
||||
+fail1:
|
||||
return error;
|
||||
}
|
||||
|
||||
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
|
||||
index e5cd0e57d178..10e5cf870359 100644
|
||||
--- a/drivers/input/tablet/wacom_wac.c
|
||||
+++ b/drivers/input/tablet/wacom_wac.c
|
||||
@@ -768,6 +768,72 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid)
|
||||
+{
|
||||
+ int touch_max = wacom->features.touch_max;
|
||||
+ int i;
|
||||
+
|
||||
+ if (!wacom->slots)
|
||||
+ return -1;
|
||||
+
|
||||
+ for (i = 0; i < touch_max; ++i) {
|
||||
+ if (wacom->slots[i] == contactid)
|
||||
+ return i;
|
||||
+ }
|
||||
+ for (i = 0; i < touch_max; ++i) {
|
||||
+ if (wacom->slots[i] == -1)
|
||||
+ return i;
|
||||
+ }
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static int wacom_mt_touch(struct wacom_wac *wacom)
|
||||
+{
|
||||
+ struct input_dev *input = wacom->input;
|
||||
+ char *data = wacom->data;
|
||||
+ int i;
|
||||
+ int current_num_contacts = data[2];
|
||||
+ int contacts_to_send = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * First packet resets the counter since only the first
|
||||
+ * packet in series will have non-zero current_num_contacts.
|
||||
+ */
|
||||
+ if (current_num_contacts)
|
||||
+ wacom->num_contacts_left = current_num_contacts;
|
||||
+
|
||||
+ /* There are at most 5 contacts per packet */
|
||||
+ contacts_to_send = min(5, wacom->num_contacts_left);
|
||||
+
|
||||
+ for (i = 0; i < contacts_to_send; i++) {
|
||||
+ int offset = (WACOM_BYTES_PER_MT_PACKET * i) + 3;
|
||||
+ bool touch = data[offset] & 0x1;
|
||||
+ int id = le16_to_cpup((__le16 *)&data[offset + 1]);
|
||||
+ int slot = find_slot_from_contactid(wacom, id);
|
||||
+
|
||||
+ if (slot < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ input_mt_slot(input, slot);
|
||||
+ input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
|
||||
+ if (touch) {
|
||||
+ int x = le16_to_cpup((__le16 *)&data[offset + 7]);
|
||||
+ int y = le16_to_cpup((__le16 *)&data[offset + 9]);
|
||||
+ input_report_abs(input, ABS_MT_POSITION_X, x);
|
||||
+ input_report_abs(input, ABS_MT_POSITION_Y, y);
|
||||
+ }
|
||||
+ wacom->slots[slot] = touch ? id : -1;
|
||||
+ }
|
||||
+
|
||||
+ input_mt_report_pointer_emulation(input, true);
|
||||
+
|
||||
+ wacom->num_contacts_left -= contacts_to_send;
|
||||
+ if (wacom->num_contacts_left < 0)
|
||||
+ wacom->num_contacts_left = 0;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
|
||||
{
|
||||
struct input_dev *input = wacom->input;
|
||||
@@ -806,6 +872,9 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
|
||||
bool prox;
|
||||
int x = 0, y = 0;
|
||||
|
||||
+ if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG)
|
||||
+ return 0;
|
||||
+
|
||||
if (!wacom->shared->stylus_in_proximity) {
|
||||
if (len == WACOM_PKGLEN_TPC1FG) {
|
||||
prox = data[0] & 0x01;
|
||||
@@ -873,10 +942,10 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
|
||||
|
||||
switch (len) {
|
||||
case WACOM_PKGLEN_TPC1FG:
|
||||
- return wacom_tpc_single_touch(wacom, len);
|
||||
+ return wacom_tpc_single_touch(wacom, len);
|
||||
|
||||
case WACOM_PKGLEN_TPC2FG:
|
||||
- return wacom_tpc_mt_touch(wacom);
|
||||
+ return wacom_tpc_mt_touch(wacom);
|
||||
|
||||
default:
|
||||
switch (data[0]) {
|
||||
@@ -885,6 +954,9 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
|
||||
case WACOM_REPORT_TPCST:
|
||||
return wacom_tpc_single_touch(wacom, len);
|
||||
|
||||
+ case WACOM_REPORT_TPCMT:
|
||||
+ return wacom_mt_touch(wacom);
|
||||
+
|
||||
case WACOM_REPORT_PENABLED:
|
||||
return wacom_tpc_pen(wacom);
|
||||
}
|
||||
@@ -1164,6 +1236,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
|
||||
|
||||
case TABLETPC:
|
||||
case TABLETPC2FG:
|
||||
+ case MTSCREEN:
|
||||
sync = wacom_tpc_irq(wacom_wac, len);
|
||||
break;
|
||||
|
||||
@@ -1237,7 +1310,8 @@ void wacom_setup_device_quirks(struct wacom_features *features)
|
||||
/* these device have multiple inputs */
|
||||
if (features->type == TABLETPC || features->type == TABLETPC2FG ||
|
||||
features->type == BAMBOO_PT || features->type == WIRELESS ||
|
||||
- (features->type >= INTUOS5S && features->type <= INTUOS5L))
|
||||
+ (features->type >= INTUOS5S && features->type <= INTUOS5L) ||
|
||||
+ features->type == MTSCREEN)
|
||||
features->quirks |= WACOM_QUIRK_MULTI_INPUT;
|
||||
|
||||
/* quirk for bamboo touch with 2 low res touches */
|
||||
@@ -1268,8 +1342,8 @@ static unsigned int wacom_calculate_touch_res(unsigned int logical_max,
|
||||
return (logical_max * 100) / physical_max;
|
||||
}
|
||||
|
||||
-void wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
- struct wacom_wac *wacom_wac)
|
||||
+int wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
+ struct wacom_wac *wacom_wac)
|
||||
{
|
||||
struct wacom_features *features = &wacom_wac->features;
|
||||
int i;
|
||||
@@ -1465,8 +1539,18 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
break;
|
||||
|
||||
case TABLETPC2FG:
|
||||
+ case MTSCREEN:
|
||||
if (features->device_type == BTN_TOOL_FINGER) {
|
||||
|
||||
+ wacom_wac->slots = kmalloc(features->touch_max *
|
||||
+ sizeof(int),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!wacom_wac->slots)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ for (i = 0; i < features->touch_max; i++)
|
||||
+ wacom_wac->slots[i] = -1;
|
||||
+
|
||||
input_mt_init_slots(input_dev, features->touch_max);
|
||||
input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
|
||||
0, MT_TOOL_MAX, 0, 0);
|
||||
@@ -1552,6 +1636,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
}
|
||||
break;
|
||||
}
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static const struct wacom_features wacom_features_0x00 =
|
||||
@@ -1784,6 +1869,9 @@ static const struct wacom_features wacom_features_0xE3 =
|
||||
{ "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255,
|
||||
0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
.touch_max = 2 };
|
||||
+static const struct wacom_features wacom_features_0xE5 =
|
||||
+ { "Wacom ISDv4 E5", WACOM_PKGLEN_MTOUCH, 26202, 16325, 255,
|
||||
+ 0, MTSCREEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
static const struct wacom_features wacom_features_0xE6 =
|
||||
{ "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255,
|
||||
0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
@@ -1962,6 +2050,7 @@ const struct usb_device_id wacom_ids[] = {
|
||||
{ USB_DEVICE_WACOM(0x9F) },
|
||||
{ USB_DEVICE_WACOM(0xE2) },
|
||||
{ USB_DEVICE_WACOM(0xE3) },
|
||||
+ { USB_DEVICE_WACOM(0xE5) },
|
||||
{ USB_DEVICE_WACOM(0xE6) },
|
||||
{ USB_DEVICE_WACOM(0xEC) },
|
||||
{ USB_DEVICE_WACOM(0x47) },
|
||||
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
|
||||
index 321269c1ac4c..78fbd3f42009 100644
|
||||
--- a/drivers/input/tablet/wacom_wac.h
|
||||
+++ b/drivers/input/tablet/wacom_wac.h
|
||||
@@ -25,6 +25,10 @@
|
||||
#define WACOM_PKGLEN_BBTOUCH3 64
|
||||
#define WACOM_PKGLEN_BBPEN 10
|
||||
#define WACOM_PKGLEN_WIRELESS 32
|
||||
+#define WACOM_PKGLEN_MTOUCH 62
|
||||
+
|
||||
+/* wacom data size per MT contact */
|
||||
+#define WACOM_BYTES_PER_MT_PACKET 11
|
||||
|
||||
/* device IDs */
|
||||
#define STYLUS_DEVICE_ID 0x02
|
||||
@@ -41,6 +45,7 @@
|
||||
#define WACOM_REPORT_INTUOS5PAD 3
|
||||
#define WACOM_REPORT_TPC1FG 6
|
||||
#define WACOM_REPORT_TPC2FG 13
|
||||
+#define WACOM_REPORT_TPCMT 13
|
||||
#define WACOM_REPORT_TPCHID 15
|
||||
#define WACOM_REPORT_TPCST 16
|
||||
|
||||
@@ -76,6 +81,7 @@ enum {
|
||||
WACOM_MO,
|
||||
TABLETPC,
|
||||
TABLETPC2FG,
|
||||
+ MTSCREEN,
|
||||
MAX_TYPE
|
||||
};
|
||||
|
||||
@@ -118,6 +124,8 @@ struct wacom_wac {
|
||||
struct input_dev *input;
|
||||
int pid;
|
||||
int battery_capacity;
|
||||
+ int num_contacts_left;
|
||||
+ int *slots;
|
||||
};
|
||||
|
||||
#endif
|
||||
--
|
||||
1.7.10.1
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
|
||||
Date: Wed, 2 May 2012 00:13:38 -0700
|
||||
Subject: [PATCH 26/26] Input: wacom - return proper error if
|
||||
usb_get_extra_descriptor() fails
|
||||
|
||||
commit a882c932a628cbab17752fc8b1c94692f95bbf9a upstream.
|
||||
|
||||
Instead of returning 1 (which is not even negative) let's capture and return
|
||||
error codde returned by usb_get_extra_descriptor().
|
||||
|
||||
Reviewed-by: Chris Bagwell <chris@cnpbagwell.com>
|
||||
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
|
||||
---
|
||||
drivers/input/tablet/wacom_sys.c | 11 ++++++-----
|
||||
1 file changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
|
||||
index 364f2c343..8f3b30b 100644
|
||||
--- a/drivers/input/tablet/wacom_sys.c
|
||||
+++ b/drivers/input/tablet/wacom_sys.c
|
||||
@@ -517,11 +517,12 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
|
||||
- if (usb_get_extra_descriptor(&interface->endpoint[0],
|
||||
- HID_DEVICET_REPORT, &hid_desc)) {
|
||||
- printk("wacom: can not retrieve extra class descriptor\n");
|
||||
- error = 1;
|
||||
+ error = usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc);
|
||||
+ if (error) {
|
||||
+ error = usb_get_extra_descriptor(&interface->endpoint[0],
|
||||
+ HID_DEVICET_REPORT, &hid_desc);
|
||||
+ if (error) {
|
||||
+ printk(KERN_ERR "wacom: can not retrieve extra class descriptor\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
From: Ping Cheng <pinglinux@gmail.com>
|
||||
Date: Sun, 24 Jun 2012 09:48:03 -0500
|
||||
Subject: wacom: do not crash when retrieving touch_max
|
||||
Bug-Debian: http://bugs.debian.org/678798
|
||||
|
||||
When rep_data was an array
|
||||
|
||||
unsigned char rep_data[2];
|
||||
|
||||
spelling its address as &rep_data was perfectly valid, but now that
|
||||
it is dynamically allocated
|
||||
|
||||
unsigned char *rep_data = kmalloc(2, GFP_KERNEL);
|
||||
|
||||
that expression returns a pointer to the pointer rather than to the
|
||||
array itself. Regression introduced by commit f393ee2b814e (Input:
|
||||
wacom - retrieve maximum number of touch points, 2012-04-29).
|
||||
|
||||
[jn: from mailing list discussion, with new description.
|
||||
This change is also available as part of a larger commit in the
|
||||
input-wacom repository.]
|
||||
|
||||
Signed-off-by: Ping Cheng <pingc@wacom.com>
|
||||
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
|
||||
---
|
||||
drivers/input/tablet/wacom_sys.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
|
||||
index cad5602d3ce4..6b1cd71ba320 100644
|
||||
--- a/drivers/input/tablet/wacom_sys.c
|
||||
+++ b/drivers/input/tablet/wacom_sys.c
|
||||
@@ -216,7 +216,7 @@ static void wacom_retrieve_report_data(struct usb_interface *intf,
|
||||
|
||||
rep_data[0] = 12;
|
||||
result = wacom_get_report(intf, WAC_HID_FEATURE_REPORT,
|
||||
- rep_data[0], &rep_data, 2,
|
||||
+ rep_data[0], rep_data, 2,
|
||||
WAC_MSG_RETRIES);
|
||||
|
||||
if (result >= 0 && rep_data[1] > 2)
|
||||
--
|
||||
1.7.11.rc3
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
From: Ping Cheng <pinglinux@gmail.com>
|
||||
Date: Sun, 24 Jun 2012 23:00:29 -0500
|
||||
Subject: wacom: leave touch_max as is if predefined
|
||||
Bug-Debian: http://bugs.debian.org/677164
|
||||
|
||||
Another fixup to f393ee2b814e (Input: wacom - retrieve maximum number
|
||||
of touch points, 2012-04-29). The 0xE6 tablet in the Thinkpad x220t
|
||||
reports the wrong value for MAXCONTACTS so the hardcoded value must
|
||||
take precedence.
|
||||
|
||||
[jn: extracted from a larger commit in the input-wacom repository,
|
||||
with new description]
|
||||
|
||||
Signed-off-by: Ping Cheng <pingc@wacom.com>
|
||||
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
|
||||
---
|
||||
drivers/input/tablet/wacom_sys.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
|
||||
index 6b1cd71ba320..8b31473a81fe 100644
|
||||
--- a/drivers/input/tablet/wacom_sys.c
|
||||
+++ b/drivers/input/tablet/wacom_sys.c
|
||||
@@ -401,7 +401,9 @@ static int wacom_parse_hid(struct usb_interface *intf,
|
||||
break;
|
||||
|
||||
case HID_USAGE_CONTACTMAX:
|
||||
- wacom_retrieve_report_data(intf, features);
|
||||
+ /* leave touch_max as is if predefined */
|
||||
+ if (!features->touch_max)
|
||||
+ wacom_retrieve_report_data(intf, features);
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
--
|
||||
1.7.11.rc3
|
||||
|
|
@ -1,285 +0,0 @@
|
|||
commit c06cd9bfcad4960023bac1f052da748824e24961
|
||||
Author: Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
|
||||
Date: Wed Apr 18 23:16:41 2012 +0200
|
||||
|
||||
kirkwood: Add iconnect support
|
||||
|
||||
Add support for Iomega Iconnect system.
|
||||
|
||||
Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
|
||||
Tested-By: Adam Baker <linux@baker-net.org.uk>
|
||||
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
|
||||
|
||||
Index: sid/arch/arm/boot/dts/kirkwood-iconnect.dts
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ sid/arch/arm/boot/dts/kirkwood-iconnect.dts 2012-06-10 01:24:28.300087489 +0200
|
||||
@@ -0,0 +1,26 @@
|
||||
+/dts-v1/;
|
||||
+
|
||||
+/include/ "kirkwood.dtsi"
|
||||
+
|
||||
+/ {
|
||||
+ model = "Iomega Iconnect";
|
||||
+ compatible = "iom,iconnect-1.1", "iom,iconnect", "mrvl,kirkwood-88f6281", "mrvl,kirkwood";
|
||||
+
|
||||
+ memory {
|
||||
+ device_type = "memory";
|
||||
+ reg = <0x00000000 0x10000000>;
|
||||
+ };
|
||||
+
|
||||
+ chosen {
|
||||
+ bootargs = "console=ttyS0,115200n8 earlyprintk mtdparts=orion_nand:0xc0000@0x0(uboot),0x20000@0xa0000(env),0x300000@0x100000(zImage),0x300000@0x540000(initrd),0x1f400000@0x980000(boot)";
|
||||
+ linux,initrd-start = <0x4500040>;
|
||||
+ linux,initrd-end = <0x4800000>;
|
||||
+ };
|
||||
+
|
||||
+ ocp@f1000000 {
|
||||
+ serial@12000 {
|
||||
+ clock-frequency = <200000000>;
|
||||
+ status = "ok";
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
Index: sid/arch/arm/mach-kirkwood/Kconfig
|
||||
===================================================================
|
||||
--- sid.orig/arch/arm/mach-kirkwood/Kconfig 2012-06-10 01:13:01.000000000 +0200
|
||||
+++ sid/arch/arm/mach-kirkwood/Kconfig 2012-06-10 01:24:28.300087489 +0200
|
||||
@@ -58,6 +58,12 @@ config MACH_DREAMPLUG_DT
|
||||
Say 'Y' here if you want your kernel to support the
|
||||
Marvell DreamPlug (Flattened Device Tree).
|
||||
|
||||
+config MACH_ICONNECT_DT
|
||||
+ bool "Iomega Iconnect (Flattened Device Tree)"
|
||||
+ select ARCH_KIRKWOOD_DT
|
||||
+ help
|
||||
+ Say 'Y' here to enable Iomega Iconnect support.
|
||||
+
|
||||
config MACH_TS219
|
||||
bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
|
||||
help
|
||||
Index: sid/arch/arm/mach-kirkwood/Makefile
|
||||
===================================================================
|
||||
--- sid.orig/arch/arm/mach-kirkwood/Makefile 2012-06-10 01:13:58.000000000 +0200
|
||||
+++ sid/arch/arm/mach-kirkwood/Makefile 2012-06-10 01:24:28.300087489 +0200
|
||||
@@ -22,3 +22,4 @@ obj-$(CONFIG_MACH_T5325) += t5325-setup
|
||||
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
|
||||
obj-$(CONFIG_ARCH_KIRKWOOD_DT) += board-dt.o
|
||||
obj-$(CONFIG_MACH_DREAMPLUG_DT) += board-dreamplug.o
|
||||
+obj-$(CONFIG_MACH_ICONNECT_DT) += board-iconnect.o
|
||||
Index: sid/arch/arm/mach-kirkwood/Makefile.boot
|
||||
===================================================================
|
||||
--- sid.orig/arch/arm/mach-kirkwood/Makefile.boot 2012-06-10 01:13:01.000000000 +0200
|
||||
+++ sid/arch/arm/mach-kirkwood/Makefile.boot 2012-06-10 01:24:28.300087489 +0200
|
||||
@@ -3,3 +3,4 @@ params_phys-y := 0x00000100
|
||||
initrd_phys-y := 0x00800000
|
||||
|
||||
dtb-$(CONFIG_MACH_DREAMPLUG_DT) += kirkwood-dreamplug.dtb
|
||||
+dtb-$(CONFIG_MACH_ICONNECT_DT) += kirkwood-iconnect.dtb
|
||||
Index: sid/arch/arm/mach-kirkwood/board-dt.c
|
||||
===================================================================
|
||||
--- sid.orig/arch/arm/mach-kirkwood/board-dt.c 2012-06-10 01:14:30.000000000 +0200
|
||||
+++ sid/arch/arm/mach-kirkwood/board-dt.c 2012-06-10 01:24:28.300087489 +0200
|
||||
@@ -56,11 +56,15 @@ static void __init kirkwood_dt_init(void
|
||||
if (of_machine_is_compatible("globalscale,dreamplug"))
|
||||
dreamplug_init();
|
||||
|
||||
+ if (of_machine_is_compatible("iom,iconnect"))
|
||||
+ iconnect_init();
|
||||
+
|
||||
of_platform_populate(NULL, kirkwood_dt_match_table, NULL, NULL);
|
||||
}
|
||||
|
||||
static const char *kirkwood_dt_board_compat[] = {
|
||||
"globalscale,dreamplug",
|
||||
+ "iom,iconnect",
|
||||
NULL
|
||||
};
|
||||
|
||||
Index: sid/arch/arm/mach-kirkwood/board-iconnect.c
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ sid/arch/arm/mach-kirkwood/board-iconnect.c 2012-06-10 01:24:28.300087489 +0200
|
||||
@@ -0,0 +1,165 @@
|
||||
+/*
|
||||
+ * arch/arm/mach-kirkwood/board-iconnect.c
|
||||
+ *
|
||||
+ * Iomega i-connect Board Setup
|
||||
+ *
|
||||
+ * This file is licensed under the terms of the GNU General Public
|
||||
+ * License version 2. This program is licensed "as is" without any
|
||||
+ * warranty of any kind, whether express or implied.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/of_fdt.h>
|
||||
+#include <linux/of_irq.h>
|
||||
+#include <linux/of_platform.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
+#include <linux/mv643xx_eth.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/leds.h>
|
||||
+#include <linux/spi/flash.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/spi/orion_spi.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/input.h>
|
||||
+#include <linux/gpio_keys.h>
|
||||
+#include <asm/mach/arch.h>
|
||||
+#include <mach/kirkwood.h>
|
||||
+#include "common.h"
|
||||
+#include "mpp.h"
|
||||
+
|
||||
+static struct mv643xx_eth_platform_data iconnect_ge00_data = {
|
||||
+ .phy_addr = MV643XX_ETH_PHY_ADDR(11),
|
||||
+};
|
||||
+
|
||||
+static struct gpio_led iconnect_led_pins[] = {
|
||||
+ {
|
||||
+ .name = "led_level",
|
||||
+ .gpio = 41,
|
||||
+ .default_trigger = "default-on",
|
||||
+ }, {
|
||||
+ .name = "power:blue",
|
||||
+ .gpio = 42,
|
||||
+ .default_trigger = "timer",
|
||||
+ }, {
|
||||
+ .name = "power:red",
|
||||
+ .gpio = 43,
|
||||
+ }, {
|
||||
+ .name = "usb1:blue",
|
||||
+ .gpio = 44,
|
||||
+ }, {
|
||||
+ .name = "usb2:blue",
|
||||
+ .gpio = 45,
|
||||
+ }, {
|
||||
+ .name = "usb3:blue",
|
||||
+ .gpio = 46,
|
||||
+ }, {
|
||||
+ .name = "usb4:blue",
|
||||
+ .gpio = 47,
|
||||
+ }, {
|
||||
+ .name = "otb:blue",
|
||||
+ .gpio = 48,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct gpio_led_platform_data iconnect_led_data = {
|
||||
+ .leds = iconnect_led_pins,
|
||||
+ .num_leds = ARRAY_SIZE(iconnect_led_pins),
|
||||
+ .gpio_blink_set = orion_gpio_led_blink_set,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device iconnect_leds = {
|
||||
+ .name = "leds-gpio",
|
||||
+ .id = -1,
|
||||
+ .dev = {
|
||||
+ .platform_data = &iconnect_led_data,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static unsigned int iconnect_mpp_config[] __initdata = {
|
||||
+ MPP12_GPIO,
|
||||
+ MPP35_GPIO,
|
||||
+ MPP41_GPIO,
|
||||
+ MPP42_GPIO,
|
||||
+ MPP43_GPIO,
|
||||
+ MPP44_GPIO,
|
||||
+ MPP45_GPIO,
|
||||
+ MPP46_GPIO,
|
||||
+ MPP47_GPIO,
|
||||
+ MPP48_GPIO,
|
||||
+ 0
|
||||
+};
|
||||
+
|
||||
+static struct i2c_board_info __initdata iconnect_board_info[] = {
|
||||
+ {
|
||||
+ I2C_BOARD_INFO("lm63", 0x4c),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct mtd_partition iconnect_nand_parts[] = {
|
||||
+ {
|
||||
+ .name = "flash",
|
||||
+ .offset = 0,
|
||||
+ .size = MTDPART_SIZ_FULL,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+/* yikes... theses are the original input buttons */
|
||||
+/* but I'm not convinced by the sw event choices */
|
||||
+static struct gpio_keys_button iconnect_buttons[] = {
|
||||
+ {
|
||||
+ .type = EV_SW,
|
||||
+ .code = SW_LID,
|
||||
+ .gpio = 12,
|
||||
+ .desc = "Reset Button",
|
||||
+ .active_low = 1,
|
||||
+ .debounce_interval = 100,
|
||||
+ }, {
|
||||
+ .type = EV_SW,
|
||||
+ .code = SW_TABLET_MODE,
|
||||
+ .gpio = 35,
|
||||
+ .desc = "OTB Button",
|
||||
+ .active_low = 1,
|
||||
+ .debounce_interval = 100,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct gpio_keys_platform_data iconnect_button_data = {
|
||||
+ .buttons = iconnect_buttons,
|
||||
+ .nbuttons = ARRAY_SIZE(iconnect_buttons),
|
||||
+};
|
||||
+
|
||||
+static struct platform_device iconnect_button_device = {
|
||||
+ .name = "gpio-keys",
|
||||
+ .id = -1,
|
||||
+ .num_resources = 0,
|
||||
+ .dev = {
|
||||
+ .platform_data = &iconnect_button_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+void __init iconnect_init(void)
|
||||
+{
|
||||
+ kirkwood_mpp_conf(iconnect_mpp_config);
|
||||
+ kirkwood_nand_init(ARRAY_AND_SIZE(iconnect_nand_parts), 25);
|
||||
+ kirkwood_i2c_init();
|
||||
+ i2c_register_board_info(0, iconnect_board_info,
|
||||
+ ARRAY_SIZE(iconnect_board_info));
|
||||
+
|
||||
+ kirkwood_ehci_init();
|
||||
+ kirkwood_ge00_init(&iconnect_ge00_data);
|
||||
+
|
||||
+ platform_device_register(&iconnect_button_device);
|
||||
+ platform_device_register(&iconnect_leds);
|
||||
+}
|
||||
+
|
||||
+static int __init iconnect_pci_init(void)
|
||||
+{
|
||||
+ if (of_machine_is_compatible("iom,iconnect"))
|
||||
+ kirkwood_pcie_init(KW_PCIE0);
|
||||
+ return 0;
|
||||
+}
|
||||
+subsys_initcall(iconnect_pci_init);
|
||||
Index: sid/arch/arm/mach-kirkwood/common.h
|
||||
===================================================================
|
||||
--- sid.orig/arch/arm/mach-kirkwood/common.h 2012-06-10 01:14:15.000000000 +0200
|
||||
+++ sid/arch/arm/mach-kirkwood/common.h 2012-06-10 01:24:28.300087489 +0200
|
||||
@@ -58,6 +58,12 @@ void dreamplug_init(void);
|
||||
static inline void dreamplug_init(void) {};
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_MACH_ICONNECT_DT
|
||||
+void iconnect_init(void);
|
||||
+#else
|
||||
+static inline void iconnect_init(void) {};
|
||||
+#endif
|
||||
+
|
||||
/* early init functions not converted to fdt yet */
|
||||
char *kirkwood_id(void);
|
||||
void kirkwood_l2_init(void);
|
|
@ -1,116 +0,0 @@
|
|||
commit ff3e660b5a881b401b2b6735aa5334f433237dcb
|
||||
Author: Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
|
||||
Date: Wed Apr 18 23:16:40 2012 +0200
|
||||
|
||||
orion/kirkwood: create a generic function for gpio led blinking
|
||||
|
||||
dns323 and (at least) iconnect platforms are using hw led blinking, so,
|
||||
instead of having 2 identicals .gpio_blink_set gpio-led hooks, move
|
||||
dns323 code into gpio.c
|
||||
|
||||
Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
|
||||
Tested-By: Adam Baker <linux@baker-net.org.uk>
|
||||
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
|
||||
|
||||
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
|
||||
index c3ed15b..13d2bec 100644
|
||||
--- a/arch/arm/mach-orion5x/dns323-setup.c
|
||||
+++ b/arch/arm/mach-orion5x/dns323-setup.c
|
||||
@@ -253,27 +253,6 @@ error_fail:
|
||||
* GPIO LEDs (simple - doesn't use hardware blinking support)
|
||||
*/
|
||||
|
||||
-#define ORION_BLINK_HALF_PERIOD 100 /* ms */
|
||||
-
|
||||
-static int dns323_gpio_blink_set(unsigned gpio, int state,
|
||||
- unsigned long *delay_on, unsigned long *delay_off)
|
||||
-{
|
||||
-
|
||||
- if (delay_on && delay_off && !*delay_on && !*delay_off)
|
||||
- *delay_on = *delay_off = ORION_BLINK_HALF_PERIOD;
|
||||
-
|
||||
- switch(state) {
|
||||
- case GPIO_LED_NO_BLINK_LOW:
|
||||
- case GPIO_LED_NO_BLINK_HIGH:
|
||||
- orion_gpio_set_blink(gpio, 0);
|
||||
- gpio_set_value(gpio, state);
|
||||
- break;
|
||||
- case GPIO_LED_BLINK:
|
||||
- orion_gpio_set_blink(gpio, 1);
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static struct gpio_led dns323ab_leds[] = {
|
||||
{
|
||||
.name = "power:blue",
|
||||
@@ -312,13 +291,13 @@ static struct gpio_led dns323c_leds[] = {
|
||||
static struct gpio_led_platform_data dns323ab_led_data = {
|
||||
.num_leds = ARRAY_SIZE(dns323ab_leds),
|
||||
.leds = dns323ab_leds,
|
||||
- .gpio_blink_set = dns323_gpio_blink_set,
|
||||
+ .gpio_blink_set = orion_gpio_led_blink_set,
|
||||
};
|
||||
|
||||
static struct gpio_led_platform_data dns323c_led_data = {
|
||||
.num_leds = ARRAY_SIZE(dns323c_leds),
|
||||
.leds = dns323c_leds,
|
||||
- .gpio_blink_set = dns323_gpio_blink_set,
|
||||
+ .gpio_blink_set = orion_gpio_led_blink_set,
|
||||
};
|
||||
|
||||
static struct platform_device dns323_gpio_leds = {
|
||||
diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
|
||||
index d3401e7..af95af2 100644
|
||||
--- a/arch/arm/plat-orion/gpio.c
|
||||
+++ b/arch/arm/plat-orion/gpio.c
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
+#include <linux/leds.h>
|
||||
|
||||
/*
|
||||
* GPIO unit register offsets.
|
||||
@@ -295,6 +296,28 @@ void orion_gpio_set_blink(unsigned pin, int blink)
|
||||
}
|
||||
EXPORT_SYMBOL(orion_gpio_set_blink);
|
||||
|
||||
+#define ORION_BLINK_HALF_PERIOD 100 /* ms */
|
||||
+
|
||||
+int orion_gpio_led_blink_set(unsigned gpio, int state,
|
||||
+ unsigned long *delay_on, unsigned long *delay_off)
|
||||
+{
|
||||
+
|
||||
+ if (delay_on && delay_off && !*delay_on && !*delay_off)
|
||||
+ *delay_on = *delay_off = ORION_BLINK_HALF_PERIOD;
|
||||
+
|
||||
+ switch (state) {
|
||||
+ case GPIO_LED_NO_BLINK_LOW:
|
||||
+ case GPIO_LED_NO_BLINK_HIGH:
|
||||
+ orion_gpio_set_blink(gpio, 0);
|
||||
+ gpio_set_value(gpio, state);
|
||||
+ break;
|
||||
+ case GPIO_LED_BLINK:
|
||||
+ orion_gpio_set_blink(gpio, 1);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(orion_gpio_led_blink_set);
|
||||
+
|
||||
|
||||
/*****************************************************************************
|
||||
* Orion GPIO IRQ
|
||||
diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h
|
||||
index 3abf304..bec0c98 100644
|
||||
--- a/arch/arm/plat-orion/include/plat/gpio.h
|
||||
+++ b/arch/arm/plat-orion/include/plat/gpio.h
|
||||
@@ -19,6 +19,8 @@
|
||||
*/
|
||||
void orion_gpio_set_unused(unsigned pin);
|
||||
void orion_gpio_set_blink(unsigned pin, int blink);
|
||||
+int orion_gpio_led_blink_set(unsigned gpio, int state,
|
||||
+ unsigned long *delay_on, unsigned long *delay_off);
|
||||
|
||||
#define GPIO_INPUT_OK (1 << 0)
|
||||
#define GPIO_OUTPUT_OK (1 << 1)
|
|
@ -1,29 +0,0 @@
|
|||
commit 92a486eabefadca1169fbf15d737feeaf2bda844
|
||||
Author: Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
|
||||
Date: Wed Apr 18 23:16:39 2012 +0200
|
||||
|
||||
kirkwood/orion: fix orion_gpio_set_blink
|
||||
|
||||
gpio registers are for 32 gpios. Given that orion_gpio_set_blink is called
|
||||
directly and not through gpiolib, it needs to make sure that the pin value
|
||||
given to the internal functions are between 0 and 31.
|
||||
|
||||
Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
|
||||
Tested-By: Adam Baker <linux@baker-net.org.uk>
|
||||
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
|
||||
|
||||
diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
|
||||
index 10d1608..d3401e7 100644
|
||||
--- a/arch/arm/plat-orion/gpio.c
|
||||
+++ b/arch/arm/plat-orion/gpio.c
|
||||
@@ -289,8 +289,8 @@ void orion_gpio_set_blink(unsigned pin, int blink)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&ochip->lock, flags);
|
||||
- __set_level(ochip, pin, 0);
|
||||
- __set_blinking(ochip, pin, blink);
|
||||
+ __set_level(ochip, pin & 31, 0);
|
||||
+ __set_blinking(ochip, pin & 31, blink);
|
||||
spin_unlock_irqrestore(&ochip->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(orion_gpio_set_blink);
|
|
@ -1,79 +0,0 @@
|
|||
From: Sam Ravnborg <sam@ravnborg.org>
|
||||
Date: Mon, 21 May 2012 20:45:37 +0200
|
||||
Subject: net: drop NET dependency from HAVE_BPF_JIT
|
||||
|
||||
commit e47b65b032f2997aa0a7392ecdf656c86d4d7561 upstream.
|
||||
|
||||
There is no point having the NET dependency on the select target, as it
|
||||
forces all users to depend on NET to tell they support BPF_JIT. Move
|
||||
the config option to the bottom of the file - this could be a nice place
|
||||
also for future "selectable" config symbols.
|
||||
|
||||
Fix up all users to drop the dependency on NET now that it is not
|
||||
required to supress warnings for non-NET builds.
|
||||
|
||||
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
|
||||
Acked-by: David Miller <davem@davemloft.net>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
---
|
||||
arch/arm/Kconfig | 2 +-
|
||||
arch/powerpc/Kconfig | 2 +-
|
||||
arch/sparc/Kconfig | 2 +-
|
||||
arch/x86/Kconfig | 2 +-
|
||||
net/Kconfig | 7 ++++---
|
||||
5 files changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -33,7 +33,7 @@
|
||||
select GENERIC_IRQ_SHOW
|
||||
select CPU_PM if (SUSPEND || CPU_IDLE)
|
||||
select GENERIC_PCI_IOMAP
|
||||
- select HAVE_BPF_JIT if NET
|
||||
+ select HAVE_BPF_JIT
|
||||
help
|
||||
The ARM series is a line of low-power-consumption RISC chip designs
|
||||
licensed by ARM Ltd and targeted at embedded applications and
|
||||
--- a/arch/powerpc/Kconfig
|
||||
+++ b/arch/powerpc/Kconfig
|
||||
@@ -141,7 +141,7 @@
|
||||
select IRQ_FORCED_THREADING
|
||||
select HAVE_RCU_TABLE_FREE if SMP
|
||||
select HAVE_SYSCALL_TRACEPOINTS
|
||||
- select HAVE_BPF_JIT if (PPC64 && NET)
|
||||
+ select HAVE_BPF_JIT if PPC64
|
||||
select HAVE_ARCH_JUMP_LABEL
|
||||
select ARCH_HAVE_NMI_SAFE_CMPXCHG
|
||||
|
||||
--- a/arch/x86/Kconfig
|
||||
+++ b/arch/x86/Kconfig
|
||||
@@ -77,7 +77,7 @@
|
||||
select GENERIC_CLOCKEVENTS_MIN_ADJUST
|
||||
select IRQ_FORCED_THREADING
|
||||
select USE_GENERIC_SMP_HELPERS if SMP
|
||||
- select HAVE_BPF_JIT if (X86_64 && NET)
|
||||
+ select HAVE_BPF_JIT if X86_64
|
||||
select CLKEVT_I8253
|
||||
select ARCH_HAVE_NMI_SAFE_CMPXCHG
|
||||
select GENERIC_IOMAP
|
||||
--- a/net/Kconfig
|
||||
+++ b/net/Kconfig
|
||||
@@ -246,9 +246,6 @@
|
||||
select DQL
|
||||
default y
|
||||
|
||||
-config HAVE_BPF_JIT
|
||||
- bool
|
||||
-
|
||||
config BPF_JIT
|
||||
bool "enable BPF Just In Time compiler"
|
||||
depends on HAVE_BPF_JIT
|
||||
@@ -340,3 +337,7 @@
|
||||
|
||||
|
||||
endif # if NET
|
||||
+
|
||||
+# Used by archs to tell that they support BPF_JIT
|
||||
+config HAVE_BPF_JIT
|
||||
+ bool
|
|
@ -8,14 +8,14 @@ features/all/sound-pci-cs46xx-request_firmware.patch
|
|||
|
||||
# Patches and source files from aufs3 repository, imported with
|
||||
# debian/patches/features/all/aufs3/gen-patch.
|
||||
features/all/aufs3/aufs3-base.patch
|
||||
features/all/aufs3/aufs3-standalone.patch
|
||||
features/all/aufs3/aufs3-kbuild.patch
|
||||
features/all/aufs3/aufs3-add.patch
|
||||
#features/all/aufs3/aufs3-base.patch
|
||||
#features/all/aufs3/aufs3-standalone.patch
|
||||
#features/all/aufs3/aufs3-kbuild.patch
|
||||
#features/all/aufs3/aufs3-add.patch
|
||||
# mark as staging/crap
|
||||
features/all/aufs3/mark-as-staging.patch
|
||||
#features/all/aufs3/mark-as-staging.patch
|
||||
# fix added exports from security/device_cgroup.c
|
||||
features/all/aufs3/aufs3-fix-export-__devcgroup_inode_permission.patch
|
||||
#features/all/aufs3/aufs3-fix-export-__devcgroup_inode_permission.patch
|
||||
|
||||
bugfix/ia64/hardcode-arch-script-output.patch
|
||||
bugfix/mips/disable-advansys.patch
|
||||
|
@ -41,7 +41,6 @@ debian/cgroups-Document-the-Debian-memory-resource-controll.patch
|
|||
bugfix/ia64/nouveau-ACPI-support-is-dependent-on-X86.patch
|
||||
bugfix/arm/ixp4xx_iobe.patch
|
||||
debian/x86-memtest-WARN-if-bad-RAM-found.patch
|
||||
bugfix/alpha/alpha-add-io-read-write-16-32-be-functions.patch
|
||||
|
||||
features/all/fs-symlink-restrictions-on-sticky-directories.patch
|
||||
features/all/fs-symlink-restrictions-on-sticky-directories-fix-2.patch
|
||||
|
@ -49,65 +48,8 @@ features/all/fs-hardlink-creation-restrictions.patch
|
|||
features/all/fs-hardlink-creation-restrictions-fix.patch
|
||||
features/all/fs-hardlink-creation-restriction-cleanup.patch
|
||||
|
||||
# Update wacom driver to 3.5ish
|
||||
features/all/wacom/0020-Input-wacom-add-basic-Intuos5-support.patch
|
||||
features/all/wacom/0021-Input-wacom-add-Intuos5-Touch-Ring-ExpressKey-suppor.patch
|
||||
features/all/wacom/0022-Input-wacom-add-Intuos5-Touch-Ring-LED-support.patch
|
||||
features/all/wacom/0023-Input-wacom-add-Intuos5-multitouch-sensor-support.patch
|
||||
features/all/wacom/0024-Input-wacom-retrieve-maximum-number-of-touch-points.patch
|
||||
features/all/wacom/0025-Input-wacom-add-0xE5-MT-device-support.patch
|
||||
features/all/wacom/0026-Input-wacom-return-proper-error-if-usb_get_extra_des.patch
|
||||
features/all/wacom/0027-wacom-do-not-crash-when-retrieving-touch_max.patch
|
||||
features/all/wacom/0028-wacom-leave-touch_max-as-is-if-predefined.patch
|
||||
features/all/wacom/0029-wacom-do-not-request-tablet-data-on-MT-Tablet-PC-pen.patch
|
||||
features/all/wacom/0030-wacom-ignore-new-style-Wacom-multi-touch-packets-on-.patch
|
||||
|
||||
# Update be2net driver to 3.5ish
|
||||
features/all/be2net/0043-be2net-fix-ethtool-get-settings.patch
|
||||
features/all/be2net/0044-be2net-Fix-VLAN-multicast-packet-reception.patch
|
||||
features/all/be2net/0045-be2net-Fix-FW-download-in-Lancer.patch
|
||||
features/all/be2net/0046-be2net-Fix-ethtool-self-test-for-Lancer.patch
|
||||
features/all/be2net/0047-be2net-Fix-traffic-stall-INTx-mode.patch
|
||||
features/all/be2net/0048-be2net-Fix-Lancer-statistics.patch
|
||||
features/all/be2net/0049-be2net-Fix-wrong-status-getting-returned-for-MCC-com.patch
|
||||
features/all/be2net/0050-be2net-Fix-FW-download-for-BE.patch
|
||||
features/all/be2net/0051-be2net-Ignore-status-of-some-ioctls-during-driver-lo.patch
|
||||
features/all/be2net/0052-be2net-fix-speed-displayed-by-ethtool-on-certain-SKU.patch
|
||||
features/all/be2net/0053-be2net-update-the-driver-version.patch
|
||||
features/all/be2net/0054-be2net-Fix-to-not-set-link-speed-for-disabled-functi.patch
|
||||
features/all/be2net/0055-be2net-Fix-to-apply-duplex-value-as-unknown-when-lin.patch
|
||||
features/all/be2net/0056-be2net-Record-receive-queue-index-in-skb-to-aid-RPS.patch
|
||||
features/all/be2net/0057-be2net-Fix-EEH-error-reset-before-a-flash-dump-compl.patch
|
||||
features/all/be2net/0058-be2net-avoid-disabling-sriov-while-VFs-are-assigned.patch
|
||||
|
||||
# Add CoDel from 3.5, and prerequisites
|
||||
features/all/codel/0001-codel-Controlled-Delay-AQM.patch
|
||||
features/all/codel/0002-codel-use-Newton-method-instead-of-sqrt-and-divides.patch
|
||||
features/all/codel/0003-fq_codel-Fair-Queue-Codel-AQM.patch
|
||||
features/all/codel/0004-net-codel-Add-missing-include-linux-prefetch.h.patch
|
||||
features/all/codel/0005-net-codel-fix-build-errors.patch
|
||||
features/all/codel/0006-codel-use-u16-field-instead-of-31bits-for-rec_inv_sq.patch
|
||||
features/all/codel/0007-fq_codel-should-use-qdisc-backlog-as-threshold.patch
|
||||
|
||||
bugfix/x86/mm-pmd_read_atomic-fix-32bit-pae-pmd-walk-vs-pmd_populate-smp-race.patch
|
||||
bugfix/x86/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch
|
||||
|
||||
bugfix/ia64/IA64-Export-asm-cmpxchg.h-to-userland.patch
|
||||
bugfix/all/net-sock-validate-data_len-before-allocating-skb-in-.patch
|
||||
|
||||
bugfix/all/macvtap-zerocopy-fix-offset-calculation-when-buildin.patch
|
||||
bugfix/all/macvtap-zerocopy-fix-truesize-underestimation.patch
|
||||
bugfix/all/macvtap-zerocopy-put-page-when-fail-to-get-all-reque.patch
|
||||
bugfix/all/macvtap-zerocopy-set-SKBTX_DEV_ZEROCOPY-only-when-sk.patch
|
||||
bugfix/all/macvtap-zerocopy-validate-vectors-before-building-sk.patch
|
||||
|
||||
bugfix/all/KVM-Fix-buffer-overflow-in-kvm_set_irq.patch
|
||||
bugfix/x86/zsmalloc-Finish-conversion-to-a-separate-module.patch
|
||||
|
||||
features/all/cpu-devices/Partially-revert-cpufreq-Add-support-for-x86-cpuinfo.patch
|
||||
|
||||
features/arm/kirkwood-fix-orion_gpio_set_blink.patch
|
||||
features/arm/kirkwood-create-a-generic-function-for-gpio-led-blinking.patch
|
||||
features/arm/kirkwood-add-iconnect-support.patch
|
||||
|
||||
features/arm/net-drop-NET-dependency-from-HAVE_BPF_JIT.patch
|
||||
|
|
Loading…
Reference in New Issue