aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-01-15 18:59:55 -0500
committerDavid S. Miller <davem@davemloft.net>2015-01-15 18:59:55 -0500
commit615612dc4e583ae5eeb8eb1ece2d3c70be72296d (patch)
tree214142887368fb130259e85cd136388b8754deb1
parent5055c371bfd53fd369b895051b541318c2bad495 (diff)
parent211a84e3c188c67bfa22f1e7e1cd228709f6299b (diff)
Merge branch 'cxgb4-next'
Anish Bhatt says: ==================== cxgb4/cxgb4i : Update & use ipv6 handling api This patch series consolidates and updates the ipv6 api, as well as exports it for use by upper level drivers dependent on cxgb4 v2: Fix formatting issues in clip_tbl.c ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/Makefile2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c314
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/clip_tbl.h41
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c19
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c228
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h3
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.c23
8 files changed, 469 insertions, 164 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/Makefile b/drivers/net/ethernet/chelsio/cxgb4/Makefile
index b85280775997..ae50cd72358c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/Makefile
+++ b/drivers/net/ethernet/chelsio/cxgb4/Makefile
@@ -4,6 +4,6 @@
4 4
5obj-$(CONFIG_CHELSIO_T4) += cxgb4.o 5obj-$(CONFIG_CHELSIO_T4) += cxgb4.o
6 6
7cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o 7cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o clip_tbl.o
8cxgb4-$(CONFIG_CHELSIO_T4_DCB) += cxgb4_dcb.o 8cxgb4-$(CONFIG_CHELSIO_T4_DCB) += cxgb4_dcb.o
9cxgb4-$(CONFIG_DEBUG_FS) += cxgb4_debugfs.o 9cxgb4-$(CONFIG_DEBUG_FS) += cxgb4_debugfs.o
diff --git a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
new file mode 100644
index 000000000000..2b407b6a35a8
--- /dev/null
+++ b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
@@ -0,0 +1,314 @@
1/*
2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
3 * Copyright (C) 2003-2014 Chelsio Communications. All rights reserved.
4 *
5 * Written by Deepak (deepak.s@chelsio.com)
6 *
7 * This program is distributed in the hope that it will be useful, but WITHOUT
8 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9 * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this
10 * release for licensing terms and conditions.
11 */
12
13#include <linux/module.h>
14#include <linux/netdevice.h>
15#include <linux/jhash.h>
16#include <linux/if_vlan.h>
17#include <net/addrconf.h>
18#include "cxgb4.h"
19#include "clip_tbl.h"
20
21static inline unsigned int ipv4_clip_hash(struct clip_tbl *c, const u32 *key)
22{
23 unsigned int clipt_size_half = c->clipt_size / 2;
24
25 return jhash_1word(*key, 0) % clipt_size_half;
26}
27
28static inline unsigned int ipv6_clip_hash(struct clip_tbl *d, const u32 *key)
29{
30 unsigned int clipt_size_half = d->clipt_size / 2;
31 u32 xor = key[0] ^ key[1] ^ key[2] ^ key[3];
32
33 return clipt_size_half +
34 (jhash_1word(xor, 0) % clipt_size_half);
35}
36
37static unsigned int clip_addr_hash(struct clip_tbl *ctbl, const u32 *addr,
38 int addr_len)
39{
40 return addr_len == 4 ? ipv4_clip_hash(ctbl, addr) :
41 ipv6_clip_hash(ctbl, addr);
42}
43
44static int clip6_get_mbox(const struct net_device *dev,
45 const struct in6_addr *lip)
46{
47 struct adapter *adap = netdev2adap(dev);
48 struct fw_clip_cmd c;
49
50 memset(&c, 0, sizeof(c));
51 c.op_to_write = htonl(FW_CMD_OP_V(FW_CLIP_CMD) |
52 FW_CMD_REQUEST_F | FW_CMD_WRITE_F);
53 c.alloc_to_len16 = htonl(FW_CLIP_CMD_ALLOC_F | FW_LEN16(c));
54 *(__be64 *)&c.ip_hi = *(__be64 *)(lip->s6_addr);
55 *(__be64 *)&c.ip_lo = *(__be64 *)(lip->s6_addr + 8);
56 return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
57}
58
59static int clip6_release_mbox(const struct net_device *dev,
60 const struct in6_addr *lip)
61{
62 struct adapter *adap = netdev2adap(dev);
63 struct fw_clip_cmd c;
64
65 memset(&c, 0, sizeof(c));
66 c.op_to_write = htonl(FW_CMD_OP_V(FW_CLIP_CMD) |
67 FW_CMD_REQUEST_F | FW_CMD_READ_F);
68 c.alloc_to_len16 = htonl(FW_CLIP_CMD_FREE_F | FW_LEN16(c));
69 *(__be64 *)&c.ip_hi = *(__be64 *)(lip->s6_addr);
70 *(__be64 *)&c.ip_lo = *(__be64 *)(lip->s6_addr + 8);
71 return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
72}
73
74int cxgb4_clip_get(const struct net_device *dev, const u32 *lip, u8 v6)
75{
76 struct adapter *adap = netdev2adap(dev);
77 struct clip_tbl *ctbl = adap->clipt;
78 struct clip_entry *ce, *cte;
79 u32 *addr = (u32 *)lip;
80 int hash;
81 int addr_len;
82 int ret = 0;
83
84 if (v6)
85 addr_len = 16;
86 else
87 addr_len = 4;
88
89 hash = clip_addr_hash(ctbl, addr, addr_len);
90
91 read_lock_bh(&ctbl->lock);
92 list_for_each_entry(cte, &ctbl->hash_list[hash], list) {
93 if (addr_len == cte->addr_len &&
94 memcmp(lip, cte->addr, cte->addr_len) == 0) {
95 ce = cte;
96 read_unlock_bh(&ctbl->lock);
97 goto found;
98 }
99 }
100 read_unlock_bh(&ctbl->lock);
101
102 write_lock_bh(&ctbl->lock);
103 if (!list_empty(&ctbl->ce_free_head)) {
104 ce = list_first_entry(&ctbl->ce_free_head,
105 struct clip_entry, list);
106 list_del(&ce->list);
107 INIT_LIST_HEAD(&ce->list);
108 spin_lock_init(&ce->lock);
109 atomic_set(&ce->refcnt, 0);
110 atomic_dec(&ctbl->nfree);
111 ce->addr_len = addr_len;
112 memcpy(ce->addr, lip, addr_len);
113 list_add_tail(&ce->list, &ctbl->hash_list[hash]);
114 if (v6) {
115 ret = clip6_get_mbox(dev, (const struct in6_addr *)lip);
116 if (ret) {
117 write_unlock_bh(&ctbl->lock);
118 return ret;
119 }
120 }
121 } else {
122 write_unlock_bh(&ctbl->lock);
123 return -ENOMEM;
124 }
125 write_unlock_bh(&ctbl->lock);
126found:
127 atomic_inc(&ce->refcnt);
128
129 return 0;
130}
131EXPORT_SYMBOL(cxgb4_clip_get);
132
133void cxgb4_clip_release(const struct net_device *dev, const u32 *lip, u8 v6)
134{
135 struct adapter *adap = netdev2adap(dev);
136 struct clip_tbl *ctbl = adap->clipt;
137 struct clip_entry *ce, *cte;
138 u32 *addr = (u32 *)lip;
139 int hash;
140 int addr_len;
141
142 if (v6)
143 addr_len = 16;
144 else
145 addr_len = 4;
146
147 hash = clip_addr_hash(ctbl, addr, addr_len);
148
149 read_lock_bh(&ctbl->lock);
150 list_for_each_entry(cte, &ctbl->hash_list[hash], list) {
151 if (addr_len == cte->addr_len &&
152 memcmp(lip, cte->addr, cte->addr_len) == 0) {
153 ce = cte;
154 read_unlock_bh(&ctbl->lock);
155 goto found;
156 }
157 }
158 read_unlock_bh(&ctbl->lock);
159