diff options
author | Dimitris Michailidis <dm@chelsio.com> | 2010-04-01 11:28:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-01 22:29:15 -0400 |
commit | 625ba2c2eed763fad9c3f51318cbe8e1917b9fc8 (patch) | |
tree | df65a644c11c7566de5390c9ae13284d25d5ec13 /drivers | |
parent | fd3a47900b6f9fa72a4074ecb630f9dae62f1a95 (diff) |
cxgb4: Add remaining driver headers and L2T management
Signed-off-by: Dimitris Michailidis <dm@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/cxgb4/cxgb4.h | 741 | ||||
-rw-r--r-- | drivers/net/cxgb4/cxgb4_uld.h | 239 | ||||
-rw-r--r-- | drivers/net/cxgb4/l2t.c | 624 | ||||
-rw-r--r-- | drivers/net/cxgb4/l2t.h | 110 |
4 files changed, 1714 insertions, 0 deletions
diff --git a/drivers/net/cxgb4/cxgb4.h b/drivers/net/cxgb4/cxgb4.h new file mode 100644 index 000000000000..3d8ff4889b56 --- /dev/null +++ b/drivers/net/cxgb4/cxgb4.h | |||
@@ -0,0 +1,741 @@ | |||
1 | /* | ||
2 | * This file is part of the Chelsio T4 Ethernet driver for Linux. | ||
3 | * | ||
4 | * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved. | ||
5 | * | ||
6 | * This software is available to you under a choice of one of two | ||
7 | * licenses. You may choose to be licensed under the terms of the GNU | ||
8 | * General Public License (GPL) Version 2, available from the file | ||
9 | * COPYING in the main directory of this source tree, or the | ||
10 | * OpenIB.org BSD license below: | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or | ||
13 | * without modification, are permitted provided that the following | ||
14 | * conditions are met: | ||
15 | * | ||
16 | * - Redistributions of source code must retain the above | ||
17 | * copyright notice, this list of conditions and the following | ||
18 | * disclaimer. | ||
19 | * | ||
20 | * - Redistributions in binary form must reproduce the above | ||
21 | * copyright notice, this list of conditions and the following | ||
22 | * disclaimer in the documentation and/or other materials | ||
23 | * provided with the distribution. | ||
24 | * | ||
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
29 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
30 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
32 | * SOFTWARE. | ||
33 | */ | ||
34 | |||
35 | #ifndef __CXGB4_H__ | ||
36 | #define __CXGB4_H__ | ||
37 | |||
38 | #include <linux/bitops.h> | ||
39 | #include <linux/cache.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | #include <linux/list.h> | ||
42 | #include <linux/netdevice.h> | ||
43 | #include <linux/pci.h> | ||
44 | #include <linux/spinlock.h> | ||
45 | #include <linux/timer.h> | ||
46 | #include <asm/io.h> | ||
47 | #include "cxgb4_uld.h" | ||
48 | #include "t4_hw.h" | ||
49 | |||
50 | #define FW_VERSION_MAJOR 1 | ||
51 | #define FW_VERSION_MINOR 1 | ||
52 | #define FW_VERSION_MICRO 0 | ||
53 | |||
54 | enum { | ||
55 | MAX_NPORTS = 4, /* max # of ports */ | ||
56 | SERNUM_LEN = 16, /* Serial # length */ | ||
57 | EC_LEN = 16, /* E/C length */ | ||
58 | ID_LEN = 16, /* ID length */ | ||
59 | }; | ||
60 | |||
61 | enum { | ||
62 | MEM_EDC0, | ||
63 | MEM_EDC1, | ||
64 | MEM_MC | ||
65 | }; | ||
66 | |||
67 | enum dev_master { | ||
68 | MASTER_CANT, | ||
69 | MASTER_MAY, | ||
70 | MASTER_MUST | ||
71 | }; | ||
72 | |||
73 | enum dev_state { | ||
74 | DEV_STATE_UNINIT, | ||
75 | DEV_STATE_INIT, | ||
76 | DEV_STATE_ERR | ||
77 | }; | ||
78 | |||
79 | enum { | ||
80 | PAUSE_RX = 1 << 0, | ||
81 | PAUSE_TX = 1 << 1, | ||
82 | PAUSE_AUTONEG = 1 << 2 | ||
83 | }; | ||
84 | |||
85 | struct port_stats { | ||
86 | u64 tx_octets; /* total # of octets in good frames */ | ||
87 | u64 tx_frames; /* all good frames */ | ||
88 | u64 tx_bcast_frames; /* all broadcast frames */ | ||
89 | u64 tx_mcast_frames; /* all multicast frames */ | ||
90 | u64 tx_ucast_frames; /* all unicast frames */ | ||
91 | u64 tx_error_frames; /* all error frames */ | ||
92 | |||
93 | u64 tx_frames_64; /* # of Tx frames in a particular range */ | ||
94 | u64 tx_frames_65_127; | ||
95 | u64 tx_frames_128_255; | ||
96 | u64 tx_frames_256_511; | ||
97 | u64 tx_frames_512_1023; | ||
98 | u64 tx_frames_1024_1518; | ||
99 | u64 tx_frames_1519_max; | ||
100 | |||
101 | u64 tx_drop; /* # of dropped Tx frames */ | ||
102 | u64 tx_pause; /* # of transmitted pause frames */ | ||
103 | u64 tx_ppp0; /* # of transmitted PPP prio 0 frames */ | ||
104 | u64 tx_ppp1; /* # of transmitted PPP prio 1 frames */ | ||
105 | u64 tx_ppp2; /* # of transmitted PPP prio 2 frames */ | ||
106 | u64 tx_ppp3; /* # of transmitted PPP prio 3 frames */ | ||
107 | u64 tx_ppp4; /* # of transmitted PPP prio 4 frames */ | ||
108 | u64 tx_ppp5; /* # of transmitted PPP prio 5 frames */ | ||
109 | u64 tx_ppp6; /* # of transmitted PPP prio 6 frames */ | ||
110 | u64 tx_ppp7; /* # of transmitted PPP prio 7 frames */ | ||
111 | |||
112 | u64 rx_octets; /* total # of octets in good frames */ | ||
113 | u64 rx_frames; /* all good frames */ | ||
114 | u64 rx_bcast_frames; /* all broadcast frames */ | ||
115 | u64 rx_mcast_frames; /* all multicast frames */ | ||
116 | u64 rx_ucast_frames; /* all unicast frames */ | ||
117 | u64 rx_too_long; /* # of frames exceeding MTU */ | ||
118 | u64 rx_jabber; /* # of jabber frames */ | ||
119 | u64 rx_fcs_err; /* # of received frames with bad FCS */ | ||
120 | u64 rx_len_err; /* # of received frames with length error */ | ||
121 | u64 rx_symbol_err; /* symbol errors */ | ||
122 | u64 rx_runt; /* # of short frames */ | ||
123 | |||
124 | u64 rx_frames_64; /* # of Rx frames in a particular range */ | ||
125 | u64 rx_frames_65_127; | ||
126 | u64 rx_frames_128_255; | ||
127 | u64 rx_frames_256_511; | ||
128 | u64 rx_frames_512_1023; | ||
129 | u64 rx_frames_1024_1518; | ||
130 | u64 rx_frames_1519_max; | ||
131 | |||
132 | u64 rx_pause; /* # of received pause frames */ | ||
133 | u64 rx_ppp0; /* # of received PPP prio 0 frames */ | ||
134 | u64 rx_ppp1; /* # of received PPP prio 1 frames */ | ||
135 | u64 rx_ppp2; /* # of received PPP prio 2 frames */ | ||
136 | u64 rx_ppp3; /* # of received PPP prio 3 frames */ | ||
137 | u64 rx_ppp4; /* # of received PPP prio 4 frames */ | ||
138 | u64 rx_ppp5; /* # of received PPP prio 5 frames */ | ||
139 | u64 rx_ppp6; /* # of received PPP prio 6 frames */ | ||
140 | u64 rx_ppp7; /* # of received PPP prio 7 frames */ | ||
141 | |||
142 | u64 rx_ovflow0; /* drops due to buffer-group 0 overflows */ | ||
143 | u64 rx_ovflow1; /* drops due to buffer-group 1 overflows */ | ||
144 | u64 rx_ovflow2; /* drops due to buffer-group 2 overflows */ | ||
145 | u64 rx_ovflow3; /* drops due to buffer-group 3 overflows */ | ||
146 | u64 rx_trunc0; /* buffer-group 0 truncated packets */ | ||
147 | u64 rx_trunc1; /* buffer-group 1 truncated packets */ | ||
148 | u64 rx_trunc2; /* buffer-group 2 truncated packets */ | ||
149 | u64 rx_trunc3; /* buffer-group 3 truncated packets */ | ||
150 | }; | ||
151 | |||
152 | struct lb_port_stats { | ||
153 | u64 octets; | ||
154 | u64 frames; | ||
155 | u64 bcast_frames; | ||
156 | u64 mcast_frames; | ||
157 | u64 ucast_frames; | ||
158 | u64 error_frames; | ||
159 | |||
160 | u64 frames_64; | ||
161 | u64 frames_65_127; | ||
162 | u64 frames_128_255; | ||
163 | u64 frames_256_511; | ||
164 | u64 frames_512_1023; | ||
165 | u64 frames_1024_1518; | ||
166 | u64 frames_1519_max; | ||
167 | |||
168 | u64 drop; | ||
169 | |||
170 | u64 ovflow0; | ||
171 | u64 ovflow1; | ||
172 | u64 ovflow2; | ||
173 | u64 ovflow3; | ||
174 | u64 trunc0; | ||
175 | u64 trunc1; | ||
176 | u64 trunc2; | ||
177 | u64 trunc3; | ||
178 | }; | ||
179 | |||
180 | struct tp_tcp_stats { | ||
181 | u32 tcpOutRsts; | ||
182 | u64 tcpInSegs; | ||
183 | u64 tcpOutSegs; | ||
184 | u64 tcpRetransSegs; | ||
185 | }; | ||
186 | |||
187 | struct tp_err_stats { | ||
188 | u32 macInErrs[4]; | ||
189 | u32 hdrInErrs[4]; | ||
190 | u32 tcpInErrs[4]; | ||
191 | u32 tnlCongDrops[4]; | ||
192 | u32 ofldChanDrops[4]; | ||
193 | u32 tnlTxDrops[4]; | ||
194 | u32 ofldVlanDrops[4]; | ||
195 | u32 tcp6InErrs[4]; | ||
196 | u32 ofldNoNeigh; | ||
197 | u32 ofldCongDefer; | ||
198 | }; | ||
199 | |||
200 | struct tp_params { | ||
201 | unsigned int ntxchan; /* # of Tx channels */ | ||
202 | unsigned int tre; /* log2 of core clocks per TP tick */ | ||
203 | }; | ||
204 | |||
205 | struct vpd_params { | ||
206 | unsigned int cclk; | ||
207 | u8 ec[EC_LEN + 1]; | ||
208 | u8 sn[SERNUM_LEN + 1]; | ||
209 | u8 id[ID_LEN + 1]; | ||
210 | }; | ||
211 | |||
212 | struct pci_params { | ||
213 | unsigned char speed; | ||
214 | unsigned char width; | ||
215 | }; | ||
216 | |||
217 | struct adapter_params { | ||
218 | struct tp_params tp; | ||
219 | struct vpd_params vpd; | ||
220 | struct pci_params pci; | ||
221 | |||
222 | unsigned int fw_vers; | ||
223 | unsigned int tp_vers; | ||
224 | u8 api_vers[7]; | ||
225 | |||
226 | unsigned short mtus[NMTUS]; | ||
227 | unsigned short a_wnd[NCCTRL_WIN]; | ||
228 | unsigned short b_wnd[NCCTRL_WIN]; | ||
229 | |||
230 | unsigned char nports; /* # of ethernet ports */ | ||
231 | unsigned char portvec; | ||
232 | unsigned char rev; /* chip revision */ | ||
233 | unsigned char offload; | ||
234 | |||
235 | unsigned int ofldq_wr_cred; | ||
236 | }; | ||
237 | |||
238 | struct trace_params { | ||
239 | u32 data[TRACE_LEN / 4]; | ||
240 | u32 mask[TRACE_LEN / 4]; | ||
241 | unsigned short snap_len; | ||
242 | unsigned short min_len; | ||
243 | unsigned char skip_ofst; | ||
244 | unsigned char skip_len; | ||
245 | unsigned char invert; | ||
246 | unsigned char port; | ||
247 | }; | ||
248 | |||
249 | struct link_config { | ||
250 | unsigned short supported; /* link capabilities */ | ||
251 | unsigned short advertising; /* advertised capabilities */ | ||
252 | unsigned short requested_speed; /* speed user has requested */ | ||
253 | unsigned short speed; /* actual link speed */ | ||
254 | unsigned char requested_fc; /* flow control user has requested */ | ||
255 | unsigned char fc; /* actual link flow control */ | ||
256 | unsigned char autoneg; /* autonegotiating? */ | ||
257 | unsigned char link_ok; /* link up? */ | ||
258 | }; | ||
259 | |||
260 | #define FW_LEN16(fw_struct) FW_CMD_LEN16(sizeof(fw_struct) / 16) | ||
261 | |||
262 | enum { | ||
263 | MAX_ETH_QSETS = 32, /* # of Ethernet Tx/Rx queue sets */ | ||
264 | MAX_OFLD_QSETS = 16, /* # of offload Tx/Rx queue sets */ | ||
265 | MAX_CTRL_QUEUES = NCHAN, /* # of control Tx queues */ | ||
266 | MAX_RDMA_QUEUES = NCHAN, /* # of streaming RDMA Rx queues */ | ||
267 | }; | ||
268 | |||
269 | enum { | ||
270 | MAX_EGRQ = 128, /* max # of egress queues, including FLs */ | ||
271 | MAX_INGQ = 64 /* max # of interrupt-capable ingress queues */ | ||
272 | }; | ||
273 | |||
274 | struct adapter; | ||
275 | struct vlan_group; | ||
276 | struct sge_rspq; | ||
277 | |||
278 | struct port_info { | ||
279 | struct adapter *adapter; | ||
280 | struct vlan_group *vlan_grp; | ||
281 | u16 viid; | ||
282 | s16 xact_addr_filt; /* index of exact MAC address filter */ | ||
283 | u16 rss_size; /* size of VI's RSS table slice */ | ||
284 | s8 mdio_addr; | ||
285 | u8 port_type; | ||
286 | u8 mod_type; | ||
287 | u8 port_id; | ||
288 | u8 tx_chan; | ||
289 | u8 lport; /* associated offload logical port */ | ||
290 | u8 rx_offload; /* CSO, etc */ | ||
291 | u8 nqsets; /* # of qsets */ | ||
292 | u8 first_qset; /* index of first qset */ | ||
293 | struct link_config link_cfg; | ||
294 | }; | ||
295 | |||
296 | /* port_info.rx_offload flags */ | ||
297 | enum { | ||
298 | RX_CSO = 1 << 0, | ||
299 | }; | ||
300 | |||
301 | struct dentry; | ||
302 | struct work_struct; | ||
303 | |||
304 | enum { /* adapter flags */ | ||
305 | FULL_INIT_DONE = (1 << 0), | ||
306 | USING_MSI = (1 << 1), | ||
307 | USING_MSIX = (1 << 2), | ||
308 | QUEUES_BOUND = (1 << 3), | ||
309 | FW_OK = (1 << 4), | ||
310 | }; | ||
311 | |||
312 | struct rx_sw_desc; | ||
313 | |||
314 | struct sge_fl { /* SGE free-buffer queue state */ | ||
315 | unsigned int avail; /* # of available Rx buffers */ | ||
316 | unsigned int pend_cred; /* new buffers since last FL DB ring */ | ||
317 | unsigned int cidx; /* consumer index */ | ||
318 | unsigned int pidx; /* producer index */ | ||
319 | unsigned long alloc_failed; /* # of times buffer allocation failed */ | ||
320 | unsigned long large_alloc_failed; | ||
321 | unsigned long starving; | ||
322 | /* RO fields */ | ||
323 | unsigned int cntxt_id; /* SGE context id for the free list */ | ||
324 | unsigned int size; /* capacity of free list */ | ||
325 | struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */ | ||
326 | __be64 *desc; /* address of HW Rx descriptor ring */ | ||
327 | dma_addr_t addr; /* bus address of HW ring start */ | ||
328 | }; | ||
329 | |||
330 | /* A packet gather list */ | ||
331 | struct pkt_gl { | ||
332 | skb_frag_t frags[MAX_SKB_FRAGS]; | ||
333 | void *va; /* virtual address of first byte */ | ||
334 | unsigned int nfrags; /* # of fragments */ | ||
335 | unsigned int tot_len; /* total length of fragments */ | ||
336 | }; | ||
337 | |||
338 | typedef int (*rspq_handler_t)(struct sge_rspq *q, const __be64 *rsp, | ||
339 | const struct pkt_gl *gl); | ||
340 | |||
341 | struct sge_rspq { /* state for an SGE response queue */ | ||
342 | struct napi_struct napi; | ||
343 | const __be64 *cur_desc; /* current descriptor in queue */ | ||
344 | unsigned int cidx; /* consumer index */ | ||
345 | u8 gen; /* current generation bit */ | ||
346 | u8 intr_params; /* interrupt holdoff parameters */ | ||
347 | u8 next_intr_params; /* holdoff params for next interrupt */ | ||
348 | u8 pktcnt_idx; /* interrupt packet threshold */ | ||
349 | u8 uld; /* ULD handling this queue */ | ||
350 | u8 idx; /* queue index within its group */ | ||
351 | int offset; /* offset into current Rx buffer */ | ||
352 | u16 cntxt_id; /* SGE context id for the response q */ | ||
353 | u16 abs_id; /* absolute SGE id for the response q */ | ||
354 | __be64 *desc; /* address of HW response ring */ | ||
355 | dma_addr_t phys_addr; /* physical address of the ring */ | ||
356 | unsigned int iqe_len; /* entry size */ | ||
357 | unsigned int size; /* capacity of response queue */ | ||
358 | struct adapter *adap; | ||
359 | struct net_device *netdev; /* associated net device */ | ||
360 | rspq_handler_t handler; | ||
361 | }; | ||
362 | |||
363 | struct sge_eth_stats { /* Ethernet queue statistics */ | ||
364 | unsigned long pkts; /* # of ethernet packets */ | ||
365 | unsigned long lro_pkts; /* # of LRO super packets */ | ||
366 | unsigned long lro_merged; /* # of wire packets merged by LRO */ | ||
367 | unsigned long rx_cso; /* # of Rx checksum offloads */ | ||
368 | unsigned long vlan_ex; /* # of Rx VLAN extractions */ | ||
369 | unsigned long rx_drops; /* # of packets dropped due to no mem */ | ||
370 | }; | ||
371 | |||
372 | struct sge_eth_rxq { /* SW Ethernet Rx queue */ | ||
373 | struct sge_rspq rspq; | ||
374 | struct sge_fl fl; | ||
375 | struct sge_eth_stats stats; | ||
376 | } ____cacheline_aligned_in_smp; | ||
377 | |||
378 | struct sge_ofld_stats { /* offload queue statistics */ | ||
379 | unsigned long pkts; /* # of packets */ | ||
380 | unsigned long imm; /* # of immediate-data packets */ | ||
381 | unsigned long an; /* # of asynchronous notifications */ | ||
382 | unsigned long nomem; /* # of responses deferred due to no mem */ | ||
383 | }; | ||
384 | |||
385 | struct sge_ofld_rxq { /* SW offload Rx queue */ | ||
386 | struct sge_rspq rspq; | ||
387 | struct sge_fl fl; | ||
388 | struct sge_ofld_stats stats; | ||
389 | } ____cacheline_aligned_in_smp; | ||
390 | |||
391 | struct tx_desc { | ||
392 | __be64 flit[8]; | ||
393 | }; | ||
394 | |||
395 | struct tx_sw_desc; | ||
396 | |||
397 | struct sge_txq { | ||
398 | unsigned int in_use; /* # of in-use Tx descriptors */ | ||
399 | unsigned int size; /* # of descriptors */ | ||
400 | unsigned int cidx; /* SW consumer index */ | ||
401 | unsigned int pidx; /* producer index */ | ||
402 | unsigned long stops; /* # of times q has been stopped */ | ||
403 | unsigned long restarts; /* # of queue restarts */ | ||
404 | unsigned int cntxt_id; /* SGE context id for the Tx q */ | ||
405 | struct tx_desc *desc; /* address of HW Tx descriptor ring */ | ||
406 | struct tx_sw_desc *sdesc; /* address of SW Tx descriptor ring */ | ||
407 | struct sge_qstat *stat; /* queue status entry */ | ||
408 | dma_addr_t phys_addr; /* physical address of the ring */ | ||
409 | }; | ||
410 | |||
411 | struct sge_eth_txq { /* state for an SGE Ethernet Tx queue */ | ||
412 | struct sge_txq q; | ||
413 | struct netdev_queue *txq; /* associated netdev TX queue */ | ||
414 | unsigned long tso; /* # of TSO requests */ | ||
415 | unsigned long tx_cso; /* # of Tx checksum offloads */ | ||
416 | unsigned long vlan_ins; /* # of Tx VLAN insertions */ | ||
417 | unsigned long mapping_err; /* # of I/O MMU packet mapping errors */ | ||
418 | } ____cacheline_aligned_in_smp; | ||
419 | |||
420 | struct sge_ofld_txq { /* state for an SGE offload Tx queue */ | ||
421 | struct sge_txq q; | ||
422 | struct adapter *adap; | ||
423 | struct sk_buff_head sendq; /* list of backpressured packets */ | ||
424 | struct tasklet_struct qresume_tsk; /* restarts the queue */ | ||
425 | u8 full; /* the Tx ring is full */ | ||
426 | unsigned long mapping_err; /* # of I/O MMU packet mapping errors */ | ||
427 | } ____cacheline_aligned_in_smp; | ||
428 | |||
429 | struct sge_ctrl_txq { /* state for an SGE control Tx queue */ | ||
430 | struct sge_txq q; | ||
431 | struct adapter *adap; | ||
432 | struct sk_buff_head sendq; /* list of backpressured packets */ | ||
433 | struct tasklet_struct qresume_tsk; /* restarts the queue */ | ||
434 | u8 full; /* the Tx ring is full */ | ||
435 | } ____cacheline_aligned_in_smp; | ||
436 | |||
437 | struct sge { | ||
438 | struct sge_eth_txq ethtxq[MAX_ETH_QSETS]; | ||
439 | struct sge_ofld_txq ofldtxq[MAX_OFLD_QSETS]; | ||
440 | struct sge_ctrl_txq ctrlq[MAX_CTRL_QUEUES]; | ||
441 | |||
442 | struct sge_eth_rxq ethrxq[MAX_ETH_QSETS]; | ||
443 | struct sge_ofld_rxq ofldrxq[MAX_OFLD_QSETS]; | ||
444 | struct sge_ofld_rxq rdmarxq[MAX_RDMA_QUEUES]; | ||
445 | struct sge_rspq fw_evtq ____cacheline_aligned_in_smp; | ||
446 | |||
447 | struct sge_rspq intrq ____cacheline_aligned_in_smp; | ||
448 | spinlock_t intrq_lock; | ||
449 | |||
450 | u16 max_ethqsets; /* # of available Ethernet queue sets */ | ||
451 | u16 ethqsets; /* # of active Ethernet queue sets */ | ||
452 | u16 ethtxq_rover; /* Tx queue to clean up next */ | ||
453 | u16 ofldqsets; /* # of active offload queue sets */ | ||
454 | u16 rdmaqs; /* # of available RDMA Rx queues */ | ||
455 | u16 ofld_rxq[MAX_OFLD_QSETS]; | ||
456 | u16 rdma_rxq[NCHAN]; | ||
457 | u16 timer_val[SGE_NTIMERS]; | ||
458 | u8 counter_val[SGE_NCOUNTERS]; | ||
459 | unsigned int starve_thres; | ||
460 | u8 idma_state[2]; | ||
461 | void *egr_map[MAX_EGRQ]; /* qid->queue egress queue map */ | ||
462 | struct sge_rspq *ingr_map[MAX_INGQ]; /* qid->queue ingress queue map */ | ||
463 | DECLARE_BITMAP(starving_fl, MAX_EGRQ); | ||
464 | DECLARE_BITMAP(txq_maperr, MAX_EGRQ); | ||
465 | struct timer_list rx_timer; /* refills starving FLs */ | ||
466 | struct timer_list tx_timer; /* checks Tx queues */ | ||
467 | }; | ||
468 | |||
469 | #define for_each_ethrxq(sge, i) for (i = 0; i < (sge)->ethqsets; i++) | ||
470 | #define for_each_ofldrxq(sge, i) for (i = 0; i < (sge)->ofldqsets; i++) | ||
471 | #define for_each_rdmarxq(sge, i) for (i = 0; i < (sge)->rdmaqs; i++) | ||
472 | |||
473 | struct l2t_data; | ||
474 | |||
475 | struct adapter { | ||
476 | void __iomem *regs; | ||
477 | struct pci_dev *pdev; | ||
478 | struct device *pdev_dev; | ||
479 | unsigned long registered_device_map; | ||
480 | unsigned long open_device_map; | ||
481 | unsigned long flags; | ||
482 | |||
483 | const char *name; | ||
484 | int msg_enable; | ||
485 | |||
486 | struct adapter_params params; | ||
487 | struct cxgb4_virt_res vres; | ||
488 | unsigned int swintr; | ||
489 | |||
490 | unsigned int wol; | ||
491 | |||
492 | struct { | ||
493 | unsigned short vec; | ||
494 | char desc[14]; | ||
495 | } msix_info[MAX_INGQ + 1]; | ||
496 | |||
497 | struct sge sge; | ||
498 | |||
499 | struct net_device *port[MAX_NPORTS]; | ||
500 | u8 chan_map[NCHAN]; /* channel -> port map */ | ||
501 | |||
502 | struct l2t_data *l2t; | ||
503 | void *uld_handle[CXGB4_ULD_MAX]; | ||
504 | struct list_head list_node; | ||
505 | |||
506 | struct tid_info tids; | ||
507 | void **tid_release_head; | ||
508 | spinlock_t tid_release_lock; | ||
509 | struct work_struct tid_release_task; | ||
510 | bool tid_release_task_busy; | ||
511 | |||
512 | struct dentry *debugfs_root; | ||
513 | |||
514 | spinlock_t stats_lock; | ||
515 | }; | ||
516 | |||
517 | static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr) | ||
518 | { | ||
519 | return readl(adap->regs + reg_addr); | ||
520 | } | ||
521 | |||
522 | static inline void t4_write_reg(struct adapter *adap, u32 reg_addr, u32 val) | ||
523 | { | ||
524 | writel(val, adap->regs + reg_addr); | ||
525 | } | ||
526 | |||
527 | #ifndef readq | ||
528 | static inline u64 readq(const volatile void __iomem *addr) | ||
529 | { | ||
530 | return readl(addr) + ((u64)readl(addr + 4) << 32); | ||
531 | } | ||
532 | |||
533 | static inline void writeq(u64 val, volatile void __iomem *addr) | ||
534 | { | ||
535 | writel(val, addr); | ||
536 | writel(val >> 32, addr + 4); | ||
537 | } | ||
538 | #endif | ||
539 | |||
540 | static inline u64 t4_read_reg64(struct adapter *adap, u32 reg_addr) | ||
541 | { | ||
542 | return readq(adap->regs + reg_addr); | ||
543 | } | ||
544 | |||
545 | static inline void t4_write_reg64(struct adapter *adap, u32 reg_addr, u64 val) | ||
546 | { | ||
547 | writeq(val, adap->regs + reg_addr); | ||
548 | } | ||
549 | |||
550 | /** | ||
551 | * netdev2pinfo - return the port_info structure associated with a net_device | ||
552 | * @dev: the netdev | ||
553 | * | ||
554 | * Return the struct port_info associated with a net_device | ||
555 | */ | ||
556 | static inline struct port_info *netdev2pinfo(const struct net_device *dev) | ||
557 | { | ||
558 | return netdev_priv(dev); | ||
559 | } | ||
560 | |||
561 | /** | ||
562 | * adap2pinfo - return the port_info of a port | ||
563 | * @adap: the adapter | ||
564 | * @idx: the port index | ||
565 | * | ||
566 | * Return the port_info structure for the port of the given index. | ||
567 | */ | ||
568 | static inline struct port_info *adap2pinfo(struct adapter *adap, int idx) | ||
569 | { | ||
570 | return netdev_priv(adap->port[idx]); | ||
571 | } | ||
572 | |||
573 | /** | ||
574 | * netdev2adap - return the adapter structure associated with a net_device | ||
575 | * @dev: the netdev | ||
576 | * | ||
577 | * Return the struct adapter associated with a net_device | ||
578 | */ | ||
579 | static inline struct adapter *netdev2adap(const struct net_device *dev) | ||
580 | { | ||
581 | return netdev2pinfo(dev)->adapter; | ||
582 | } | ||
583 | |||
584 | void t4_os_portmod_changed(const struct adapter *adap, int port_id); | ||
585 | void t4_os_link_changed(struct adapter *adap, int port_id, int link_stat); | ||
586 | |||
587 | void *t4_alloc_mem(size_t size); | ||
588 | void t4_free_mem(void *addr); | ||
589 | |||
590 | void t4_free_sge_resources(struct adapter *adap); | ||
591 | irq_handler_t t4_intr_handler(struct adapter *adap); | ||
592 | netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev); | ||
593 | int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp, | ||
594 | const struct pkt_gl *gl); | ||
595 | int t4_mgmt_tx(struct adapter *adap, struct sk_buff *skb); | ||
596 | int t4_ofld_send(struct adapter *adap, struct sk_buff *skb); | ||
597 | int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, | ||
598 | struct net_device *dev, int intr_idx, | ||
599 | struct sge_fl *fl, rspq_handler_t hnd); | ||
600 | int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq, | ||
601 | struct net_device *dev, struct netdev_queue *netdevq, | ||
602 | unsigned int iqid); | ||
603 | int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq, | ||
604 | struct net_device *dev, unsigned int iqid, | ||
605 | unsigned int cmplqid); | ||
606 | int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq, | ||
607 | struct net_device *dev, unsigned int iqid); | ||
608 | irqreturn_t t4_sge_intr_msix(int irq, void *cookie); | ||
609 | void t4_sge_init(struct adapter *adap); | ||
610 | void t4_sge_start(struct adapter *adap); | ||
611 | void t4_sge_stop(struct adapter *adap); | ||
612 | |||
613 | #define for_each_port(adapter, iter) \ | ||
614 | for (iter = 0; iter < (adapter)->params.nports; ++iter) | ||
615 | |||
616 | static inline unsigned int core_ticks_per_usec(const struct adapter *adap) | ||
617 | { | ||
618 | return adap->params.vpd.cclk / 1000; | ||
619 | } | ||
620 | |||
621 | static inline unsigned int us_to_core_ticks(const struct adapter *adap, | ||
622 | unsigned int us) | ||
623 | { | ||
624 | return (us * adap->params.vpd.cclk) / 1000; | ||
625 | } | ||
626 | |||
627 | void t4_set_reg_field(struct adapter *adap, unsigned int addr, u32 mask, | ||
628 | u32 val); | ||
629 | |||
630 | int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size, | ||
631 | void *rpl, bool sleep_ok); | ||
632 | |||
633 | static inline int t4_wr_mbox(struct adapter *adap, int mbox, const void *cmd, | ||
634 | int size, void *rpl) | ||
635 | { | ||
636 | return t4_wr_mbox_meat(adap, mbox, cmd, size, rpl, true); | ||
637 | } | ||
638 | |||
639 | static inline int t4_wr_mbox_ns(struct adapter *adap, int mbox, const void *cmd, | ||
640 | int size, void *rpl) | ||
641 | { | ||
642 | return t4_wr_mbox_meat(adap, mbox, cmd, size, rpl, false); | ||
643 | } | ||
644 | |||
645 | void t4_intr_enable(struct adapter *adapter); | ||
646 | void t4_intr_disable(struct adapter *adapter); | ||
647 | void t4_intr_clear(struct adapter *adapter); | ||
648 | int t4_slow_intr_handler(struct adapter *adapter); | ||
649 | |||
650 | int t4_link_start(struct adapter *adap, unsigned int mbox, unsigned int port, | ||
651 | struct link_config *lc); | ||
652 | int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port); | ||
653 | int t4_seeprom_wp(struct adapter *adapter, bool enable); | ||
654 | int t4_read_flash(struct adapter *adapter, unsigned int addr, | ||
655 | unsigned int nwords, u32 *data, int byte_oriented); | ||
656 | int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size); | ||
657 | int t4_check_fw_version(struct adapter *adapter); | ||
658 | int t4_prep_adapter(struct adapter *adapter); | ||
659 | int t4_port_init(struct adapter *adap, int mbox, int pf, int vf); | ||
660 | void t4_fatal_err(struct adapter *adapter); | ||
661 | void t4_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on); | ||
662 | int t4_set_trace_filter(struct adapter *adapter, const struct trace_params *tp, | ||
663 | int filter_index, int enable); | ||
664 | void t4_get_trace_filter(struct adapter *adapter, struct trace_params *tp, | ||
665 | int filter_index, int *enabled); | ||
666 | int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid, | ||
667 | int start, int n, const u16 *rspq, unsigned int nrspq); | ||
668 | int t4_config_glbl_rss(struct adapter *adapter, int mbox, unsigned int mode, | ||
669 | unsigned int flags); | ||
670 | int t4_read_rss(struct adapter *adapter, u16 *entries); | ||
671 | int t4_mc_read(struct adapter *adap, u32 addr, __be32 *data, u64 *parity); | ||
672 | int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, | ||
673 | u64 *parity); | ||
674 | |||
675 | void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p); | ||
676 | void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p); | ||
677 | |||
678 | void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log); | ||
679 | void t4_tp_get_err_stats(struct adapter *adap, struct tp_err_stats *st); | ||
680 | void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4, | ||
681 | struct tp_tcp_stats *v6); | ||
682 | void t4_load_mtus(struct adapter *adap, const unsigned short *mtus, | ||
683 | const unsigned short *alpha, const unsigned short *beta); | ||
684 | |||
685 | void t4_wol_magic_enable(struct adapter *adap, unsigned int port, | ||
686 | const u8 *addr); | ||
687 | int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, | ||
688 | u64 mask0, u64 mask1, unsigned int crc, bool enable); | ||
689 | |||
690 | int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox, | ||
691 | enum dev_master master, enum dev_state *state); | ||
692 | int t4_fw_bye(struct adapter *adap, unsigned int mbox); | ||
693 | int t4_early_init(struct adapter *adap, unsigned int mbox); | ||
694 | int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset); | ||
695 | int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf, | ||
696 | unsigned int vf, unsigned int nparams, const u32 *params, | ||
697 | u32 *val); | ||
698 | int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf, | ||
699 | unsigned int vf, unsigned int nparams, const u32 *params, | ||
700 | const u32 *val); | ||
701 | int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf, | ||
702 | unsigned int vf, unsigned int txq, unsigned int txq_eth_ctrl, | ||
703 | unsigned int rxqi, unsigned int rxq, unsigned int tc, | ||
704 | unsigned int vi, unsigned int cmask, unsigned int pmask, | ||
705 | unsigned int nexact, unsigned int rcaps, unsigned int wxcaps); | ||
706 | int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port, | ||
707 | unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac, | ||
708 | unsigned int *rss_size); | ||
709 | int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf, | ||
710 | unsigned int vf, unsigned int viid); | ||
711 | int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid, | ||
712 | int mtu, int promisc, int all_multi, int bcast, bool sleep_ok); | ||
713 | int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox, | ||
714 | unsigned int viid, bool free, unsigned int naddr, | ||
715 | const u8 **addr, u16 *idx, u64 *hash, bool sleep_ok); | ||
716 | int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid, | ||
717 | int idx, const u8 *addr, bool persist, bool add_smt); | ||
718 | int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid, | ||
719 | bool ucast, u64 vec, bool sleep_ok); | ||
720 | int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid, | ||
721 | bool rx_en, bool tx_en); | ||
722 | int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid, | ||
723 | unsigned int nblinks); | ||
724 | int t4_mdio_rd(struct adapter *adap, unsigned int mbox, unsigned int phy_addr, | ||
725 | unsigned int mmd, unsigned int reg, u16 *valp); | ||
726 | int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr, | ||
727 | unsigned int mmd, unsigned int reg, u16 val); | ||
728 | int t4_iq_start_stop(struct adapter *adap, unsigned int mbox, bool start, | ||
729 | unsigned int pf, unsigned int vf, unsigned int iqid, | ||
730 | unsigned int fl0id, unsigned int fl1id); | ||
731 | int t4_iq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, | ||
732 | unsigned int vf, unsigned int iqtype, unsigned int iqid, | ||
733 | unsigned int fl0id, unsigned int fl1id); | ||
734 | int t4_eth_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, | ||
735 | unsigned int vf, unsigned int eqid); | ||
736 | int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, | ||
737 | unsigned int vf, unsigned int eqid); | ||
738 | int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, | ||
739 | unsigned int vf, unsigned int eqid); | ||
740 | int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl); | ||
741 | #endif /* __CXGB4_H__ */ | ||
diff --git a/drivers/net/cxgb4/cxgb4_uld.h b/drivers/net/cxgb4/cxgb4_uld.h new file mode 100644 index 000000000000..5b98546ac92d --- /dev/null +++ b/drivers/net/cxgb4/cxgb4_uld.h | |||
@@ -0,0 +1,239 @@ | |||
1 | /* | ||
2 | * This file is part of the Chelsio T4 Ethernet driver for Linux. | ||
3 | * | ||
4 | * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved. | ||
5 | * | ||
6 | * This software is available to you under a choice of one of two | ||
7 | * licenses. You may choose to be licensed under the terms of the GNU | ||
8 | * General Public License (GPL) Version 2, available from the file | ||
9 | * COPYING in the main directory of this source tree, or the | ||
10 | * OpenIB.org BSD license below: | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or | ||
13 | * without modification, are permitted provided that the following | ||
14 | * conditions are met: | ||
15 | * | ||
16 | * - Redistributions of source code must retain the above | ||
17 | * copyright notice, this list of conditions and the following | ||
18 | * disclaimer. | ||
19 | * | ||
20 | * - Redistributions in binary form must reproduce the above | ||
21 | * copyright notice, this list of conditions and the following | ||
22 | * disclaimer in the documentation and/or other materials | ||
23 | * provided with the distribution. | ||
24 | * | ||
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
29 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
30 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
32 | * SOFTWARE. | ||
33 | */ | ||
34 | |||
35 | #ifndef __CXGB4_OFLD_H | ||
36 | #define __CXGB4_OFLD_H | ||
37 | |||
38 | #include <linux/cache.h> | ||
39 | #include <linux/spinlock.h> | ||
40 | #include <linux/skbuff.h> | ||
41 | #include <asm/atomic.h> | ||
42 | |||
43 | /* CPL message priority levels */ | ||
44 | enum { | ||
45 | CPL_PRIORITY_DATA = 0, /* data messages */ | ||
46 | CPL_PRIORITY_SETUP = 1, /* connection setup messages */ | ||
47 | CPL_PRIORITY_TEARDOWN = 0, /* connection teardown messages */ | ||
48 | CPL_PRIORITY_LISTEN = 1, /* listen start/stop messages */ | ||
49 | CPL_PRIORITY_ACK = 1, /* RX ACK messages */ | ||
50 | CPL_PRIORITY_CONTROL = 1 /* control messages */ | ||
51 | }; | ||
52 | |||
53 | #define INIT_TP_WR(w, tid) do { \ | ||
54 | (w)->wr.wr_hi = htonl(FW_WR_OP(FW_TP_WR) | \ | ||
55 | FW_WR_IMMDLEN(sizeof(*w) - sizeof(w->wr))); \ | ||
56 | (w)->wr.wr_mid = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*w), 16)) | \ | ||
57 | FW_WR_FLOWID(tid)); \ | ||
58 | (w)->wr.wr_lo = cpu_to_be64(0); \ | ||
59 | } while (0) | ||
60 | |||
61 | #define INIT_TP_WR_CPL(w, cpl, tid) do { \ | ||
62 | INIT_TP_WR(w, tid); \ | ||
63 | OPCODE_TID(w) = htonl(MK_OPCODE_TID(cpl, tid)); \ | ||
64 | } while (0) | ||
65 | |||
66 | #define INIT_ULPTX_WR(w, wrlen, atomic, tid) do { \ | ||
67 | (w)->wr.wr_hi = htonl(FW_WR_OP(FW_ULPTX_WR) | FW_WR_ATOMIC(atomic)); \ | ||
68 | (w)->wr.wr_mid = htonl(FW_WR_LEN16(DIV_ROUND_UP(wrlen, 16)) | \ | ||
69 | FW_WR_FLOWID(tid)); \ | ||
70 | (w)->wr.wr_lo = cpu_to_be64(0); \ | ||
71 | } while (0) | ||
72 | |||
73 | /* Special asynchronous notification message */ | ||
74 | #define CXGB4_MSG_AN ((void *)1) | ||
75 | |||
76 | struct serv_entry { | ||
77 | void *data; | ||
78 | }; | ||
79 | |||
80 | union aopen_entry { | ||
81 | void *data; | ||
82 | union aopen_entry *next; | ||
83 | }; | ||
84 | |||
85 | /* | ||
86 | * Holds the size, base address, free list start, etc of the TID, server TID, | ||
87 | * and active-open TID tables. The tables themselves are allocated dynamically. | ||
88 | */ | ||
89 | struct tid_info { | ||
90 | void **tid_tab; | ||
91 | unsigned int ntids; | ||
92 | |||
93 | struct serv_entry *stid_tab; | ||
94 | unsigned long *stid_bmap; | ||
95 | unsigned int nstids; | ||
96 | unsigned int stid_base; | ||
97 | |||
98 | union aopen_entry *atid_tab; | ||
99 | unsigned int natids; | ||
100 | |||
101 | unsigned int nftids; | ||
102 | unsigned int ftid_base; | ||
103 | |||
104 | spinlock_t atid_lock ____cacheline_aligned_in_smp; | ||
105 | union aopen_entry *afree; | ||
106 | unsigned int atids_in_use; | ||
107 | |||
108 | spinlock_t stid_lock; | ||
109 | unsigned int stids_in_use; | ||
110 | |||
111 | atomic_t tids_in_use; | ||
112 | }; | ||
113 | |||
114 | static inline void *lookup_tid(const struct tid_info *t, unsigned int tid) | ||
115 | { | ||
116 | return tid < t->ntids ? t->tid_tab[tid] : NULL; | ||
117 | } | ||
118 | |||
119 | static inline void *lookup_atid(const struct tid_info *t, unsigned int atid) | ||
120 | { | ||
121 | return atid < t->natids ? t->atid_tab[atid].data : NULL; | ||
122 | } | ||
123 | |||
124 | static inline void *lookup_stid(const struct tid_info *t, unsigned int stid) | ||
125 | { | ||
126 | stid -= t->stid_base; | ||
127 | return stid < t->nstids ? t->stid_tab[stid].data : NULL; | ||
128 | } | ||
129 | |||
130 | static inline void cxgb4_insert_tid(struct tid_info *t, void *data, | ||
131 | unsigned int tid) | ||
132 | { | ||
133 | t->tid_tab[tid] = data; | ||
134 | atomic_inc(&t->tids_in_use); | ||
135 | } | ||
136 | |||
137 | int cxgb4_alloc_atid(struct tid_info *t, void *data); | ||
138 | int cxgb4_alloc_stid(struct tid_info *t, int family, void *data); | ||
139 | void cxgb4_free_atid(struct tid_info *t, unsigned int atid); | ||
140 | void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family); | ||
141 | void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid); | ||
142 | void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan, | ||
143 | unsigned int tid); | ||
144 | |||
145 | struct in6_addr; | ||
146 | |||
147 | int cxgb4_create_server(const struct net_device *dev, unsigned int stid, | ||
148 | __be32 sip, __be16 sport, unsigned int queue); | ||
149 | int cxgb4_create_server6(const struct net_device *dev, unsigned int stid, | ||
150 | const struct in6_addr *sip, __be16 sport, | ||
151 | unsigned int queue); | ||
152 | |||
153 | static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue) | ||
154 | { | ||
155 | skb_set_queue_mapping(skb, (queue << 1) | prio); | ||
156 | } | ||
157 | |||
158 | enum cxgb4_uld { | ||
159 | CXGB4_ULD_RDMA, | ||
160 | CXGB4_ULD_ISCSI, | ||
161 | CXGB4_ULD_MAX | ||
162 | }; | ||
163 | |||
164 | enum cxgb4_state { | ||
165 | CXGB4_STATE_UP, | ||
166 | CXGB4_STATE_START_RECOVERY, | ||
167 | CXGB4_STATE_DOWN, | ||
168 | CXGB4_STATE_DETACH | ||
169 | }; | ||
170 | |||
171 | struct pci_dev; | ||
172 | struct l2t_data; | ||
173 | struct net_device; | ||
174 | struct pkt_gl; | ||
175 | struct tp_tcp_stats; | ||
176 | |||
177 | struct cxgb4_range { | ||
178 | unsigned int start; | ||
179 | unsigned int size; | ||
180 | }; | ||
181 | |||
182 | struct cxgb4_virt_res { /* virtualized HW resources */ | ||
183 | struct cxgb4_range ddp; | ||
184 | struct cxgb4_range iscsi; | ||
185 | struct cxgb4_range stag; | ||
186 | struct cxgb4_range rq; | ||
187 | struct cxgb4_range pbl; | ||
188 | }; | ||
189 | |||
190 | /* | ||
191 | * Block of information the LLD provides to ULDs attaching to a device. | ||
192 | */ | ||
193 | struct cxgb4_lld_info { | ||
194 | struct pci_dev *pdev; /* associated PCI device */ | ||
195 | struct l2t_data *l2t; /* L2 table */ | ||
196 | struct tid_info *tids; /* TID table */ | ||
197 | struct net_device **ports; /* device ports */ | ||
198 | const struct cxgb4_virt_res *vr; /* assorted HW resources */ | ||
199 | const unsigned short *mtus; /* MTU table */ | ||
200 | const unsigned short *rxq_ids; /* the ULD's Rx queue ids */ | ||
201 | unsigned short nrxq; /* # of Rx queues */ | ||
202 | unsigned short ntxq; /* # of Tx queues */ | ||
203 | unsigned char nchan:4; /* # of channels */ | ||
204 | unsigned char nports:4; /* # of ports */ | ||
205 | unsigned char wr_cred; /* WR 16-byte credits */ | ||
206 | unsigned char adapter_type; /* type of adapter */ | ||
207 | unsigned char fw_api_ver; /* FW API version */ | ||
208 | unsigned int fw_vers; /* FW version */ | ||
209 | unsigned int iscsi_iolen; /* iSCSI max I/O length */ | ||
210 | unsigned short udb_density; /* # of user DB/page */ | ||
211 | unsigned short ucq_density; /* # of user CQs/page */ | ||
212 | void __iomem *gts_reg; /* address of GTS register */ | ||
213 | void __iomem *db_reg; /* address of kernel doorbell */ | ||
214 | }; | ||
215 | |||
216 | struct cxgb4_uld_info { | ||
217 | const char *name; | ||
218 | void *(*add)(const struct cxgb4_lld_info *p); | ||
219 | int (*rx_handler)(void *handle, const __be64 *rsp, | ||
220 | const struct pkt_gl *gl); | ||
221 | int (*state_change)(void *handle, enum cxgb4_state new_state); | ||
222 | }; | ||
223 | |||
224 | int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p); | ||
225 | int cxgb4_unregister_uld(enum cxgb4_uld type); | ||
226 | int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb); | ||
227 | unsigned int cxgb4_port_chan(const struct net_device *dev); | ||
228 | unsigned int cxgb4_port_viid(const struct net_device *dev); | ||
229 | unsigned int cxgb4_port_idx(const struct net_device *dev); | ||
230 | struct net_device *cxgb4_netdev_by_hwid(struct pci_dev *pdev, unsigned int id); | ||
231 | unsigned int cxgb4_best_mtu(const unsigned short *mtus, unsigned short mtu, | ||
232 | unsigned int *idx); | ||
233 | void cxgb4_get_tcp_stats(struct pci_dev *pdev, struct tp_tcp_stats *v4, | ||
234 | struct tp_tcp_stats *v6); | ||
235 | void cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask, | ||
236 | const unsigned int *pgsz_order); | ||
237 | struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl, | ||
238 | unsigned int skb_len, unsigned int pull_len); | ||
239 | #endif /* !__CXGB4_OFLD_H */ | ||
diff --git a/drivers/net/cxgb4/l2t.c b/drivers/net/cxgb4/l2t.c new file mode 100644 index 000000000000..9f96724a133a --- /dev/null +++ b/drivers/net/cxgb4/l2t.c | |||
@@ -0,0 +1,624 @@ | |||
1 | /* | ||
2 | * This file is part of the Chelsio T4 Ethernet driver for Linux. | ||
3 | * | ||
4 | * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved. | ||
5 | * | ||
6 | * This software is available to you under a choice of one of two | ||
7 | * licenses. You may choose to be licensed under the terms of the GNU | ||
8 | * General Public License (GPL) Version 2, available from the file | ||
9 | * COPYING in the main directory of this source tree, or the | ||
10 | * OpenIB.org BSD license below: | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or | ||
13 | * without modification, are permitted provided that the following | ||
14 | * conditions are met: | ||
15 | * | ||
16 | * - Redistributions of source code must retain the above | ||
17 | * copyright notice, this list of conditions and the following | ||
18 | * disclaimer. | ||
19 | * | ||
20 | * - Redistributions in binary form must reproduce the above | ||
21 | * copyright notice, this list of conditions and the following | ||
22 | * disclaimer in the documentation and/or other materials | ||
23 | * provided with the distribution. | ||
24 | * | ||
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
29 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
30 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
32 | * SOFTWARE. | ||
33 | */ | ||
34 | |||
35 | #include <linux/skbuff.h> | ||
36 | #include <linux/netdevice.h> | ||
37 | #include <linux/if.h> | ||
38 | #include <linux/if_vlan.h> | ||
39 | #include <linux/jhash.h> | ||
40 | #include <net/neighbour.h> | ||
41 | #include "cxgb4.h" | ||
42 | #include "l2t.h" | ||
43 | #include "t4_msg.h" | ||
44 | #include "t4fw_api.h" | ||
45 | |||
46 | #define VLAN_NONE 0xfff | ||
47 | |||
48 | /* identifies sync vs async L2T_WRITE_REQs */ | ||
49 | #define F_SYNC_WR (1 << 12) | ||
50 | |||
51 | enum { | ||
52 | L2T_STATE_VALID, /* entry is up to date */ | ||
53 | L2T_STATE_STALE, /* entry may be used but needs revalidation */ | ||
54 | L2T_STATE_RESOLVING, /* entry needs address resolution */ | ||
55 | L2T_STATE_SYNC_WRITE, /* synchronous write of entry underway */ | ||
56 | |||
57 | /* when state is one of the below the entry is not hashed */ | ||
58 | L2T_STATE_SWITCHING, /* entry is being used by a switching filter */ | ||
59 | L2T_STATE_UNUSED /* entry not in use */ | ||
60 | }; | ||
61 | |||
62 | struct l2t_data { | ||
63 | rwlock_t lock; | ||
64 | atomic_t nfree; /* number of free entries */ | ||
65 | struct l2t_entry *rover; /* starting point for next allocation */ | ||
66 | struct l2t_entry l2tab[L2T_SIZE]; | ||
67 | }; | ||
68 | |||
69 | static inline unsigned int vlan_prio(const struct l2t_entry *e) | ||
70 | { | ||
71 | return e->vlan >> 13; | ||
72 | } | ||
73 | |||
74 | static inline void l2t_hold(struct l2t_data *d, struct l2t_entry *e) | ||
75 | { | ||
76 | if (atomic_add_return(1, &e->refcnt) == 1) /* 0 -> 1 transition */ | ||
77 | atomic_dec(&d->nfree); | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * To avoid having to check address families we do not allow v4 and v6 | ||
82 | * neighbors to be on the same hash chain. We keep v4 entries in the first | ||
83 | * half of available hash buckets and v6 in the second. | ||
84 | */ | ||
85 | enum { | ||
86 | L2T_SZ_HALF = L2T_SIZE / 2, | ||
87 | L2T_HASH_MASK = L2T_SZ_HALF - 1 | ||
88 | }; | ||
89 | |||
90 | static inline unsigned int arp_hash(const u32 *key, int ifindex) | ||
91 | { | ||
92 | return jhash_2words(*key, ifindex, 0) & L2T_HASH_MASK; | ||
93 | } | ||
94 | |||
95 | static inline unsigned int ipv6_hash(const u32 *key, int ifindex) | ||
96 | { | ||
97 | u32 xor = key[0] ^ key[1] ^ key[2] ^ key[3]; | ||
98 | |||
99 | return L2T_SZ_HALF + (jhash_2words(xor, ifindex, 0) & L2T_HASH_MASK); | ||
100 | } | ||
101 | |||
102 | static unsigned int addr_hash(const u32 *addr, int addr_len, int ifindex) | ||
103 | { | ||
104 | return addr_len == 4 ? arp_hash(addr, ifindex) : | ||
105 | ipv6_hash(addr, ifindex); | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * Checks if an L2T entry is for the given IP/IPv6 address. It does not check | ||
110 | * whether the L2T entry and the address are of the same address family. | ||
111 | * Callers ensure an address is only checked against L2T entries of the same | ||
112 | * family, something made trivial by the separation of IP and IPv6 hash chains | ||
113 | * mentioned above. Returns 0 if there's a match, | ||
114 | */ | ||
115 | static int addreq(const struct l2t_entry *e, const u32 *addr) | ||
116 | { | ||
117 | if (e->v6) | ||
118 | return (e->addr[0] ^ addr[0]) | (e->addr[1] ^ addr[1]) | | ||
119 | (e->addr[2] ^ addr[2]) | (e->addr[3] ^ addr[3]); | ||
120 | return e->addr[0] ^ addr[0]; | ||
121 | } | ||
122 | |||
123 | static void neigh_replace(struct l2t_entry *e, struct neighbour *n) | ||
124 | { | ||
125 | neigh_hold(n); | ||
126 | if (e->neigh) | ||
127 | neigh_release(e->neigh); | ||
128 | e->neigh = n; | ||
129 | } | ||
130 | |||
131 | /* | ||
132 | * Write an L2T entry. Must be called with the entry locked. | ||
133 | * The write may be synchronous or asynchronous. | ||
134 | */ | ||
135 | static int write_l2e(struct adapter *adap, struct l2t_entry *e, int sync) | ||
136 | { | ||
137 | struct sk_buff *skb; | ||
138 | struct cpl_l2t_write_req *req; | ||
139 | |||
140 | skb = alloc_skb(sizeof(*req), GFP_ATOMIC); | ||
141 | if (!skb) | ||
142 | return -ENOMEM; | ||
143 | |||
144 | req = (struct cpl_l2t_write_req *)__skb_put(skb, sizeof(*req)); | ||
145 | INIT_TP_WR(req, 0); | ||
146 | |||
147 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, | ||
148 | e->idx | (sync ? F_SYNC_WR : 0) | | ||
149 | TID_QID(adap->sge.fw_evtq.abs_id))); | ||
150 | req->params = htons(L2T_W_PORT(e->lport) | L2T_W_NOREPLY(!sync)); | ||
151 | req->l2t_idx = htons(e->idx); | ||
152 | req->vlan = htons(e->vlan); | ||
153 | if (e->neigh) | ||
154 | memcpy(e->dmac, e->neigh->ha, sizeof(e->dmac)); | ||
155 | memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac)); | ||
156 | |||
157 | set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0); | ||
158 | t4_ofld_send(adap, skb); | ||
159 | |||
160 | if (sync && e->state != L2T_STATE_SWITCHING) | ||
161 | e->state = L2T_STATE_SYNC_WRITE; | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Send packets waiting in an L2T entry's ARP queue. Must be called with the | ||
167 | * entry locked. | ||
168 | */ | ||
169 | static void send_pending(struct adapter *adap, struct l2t_entry *e) | ||
170 | { | ||
171 | while (e->arpq_head) { | ||
172 | struct sk_buff *skb = e->arpq_head; | ||
173 | |||
174 | e->arpq_head = skb->next; | ||
175 | skb->next = NULL; | ||
176 | t4_ofld_send(adap, skb); | ||
177 | } | ||
178 | e->arpq_tail = NULL; | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * Process a CPL_L2T_WRITE_RPL. Wake up the ARP queue if it completes a | ||
183 | * synchronous L2T_WRITE. Note that the TID in the reply is really the L2T | ||
184 | * index it refers to. | ||
185 | */ | ||
186 | void do_l2t_write_rpl(struct adapter *adap, const struct cpl_l2t_write_rpl *rpl) | ||
187 | { | ||
188 | unsigned int tid = GET_TID(rpl); | ||
189 | unsigned int idx = tid & (L2T_SIZE - 1); | ||
190 | |||
191 | if (unlikely(rpl->status != CPL_ERR_NONE)) { | ||
192 | dev_err(adap->pdev_dev, | ||
193 | "Unexpected L2T_WRITE_RPL status %u for entry %u\n", | ||
194 | rpl->status, idx); | ||
195 | return; | ||
196 | } | ||
197 | |||
198 | if (tid & F_SYNC_WR) { | ||
199 | struct l2t_entry *e = &adap->l2t->l2tab[idx]; | ||
200 | |||
201 | spin_lock(&e->lock); | ||
202 | if (e->state != L2T_STATE_SWITCHING) { | ||
203 | send_pending(adap, e); | ||
204 | e->state = (e->neigh->nud_state & NUD_STALE) ? | ||
205 | L2T_STATE_STALE : L2T_STATE_VALID; | ||
206 | } | ||
207 | spin_unlock(&e->lock); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * Add a packet to an L2T entry's queue of packets awaiting resolution. | ||
213 | * Must be called with the entry's lock held. | ||
214 | */ | ||
215 | static inline void arpq_enqueue(struct l2t_entry *e, struct sk_buff *skb) | ||
216 | { | ||
217 | skb->next = NULL; | ||
218 | if (e->arpq_head) | ||
219 | e->arpq_tail->next = skb; | ||
220 | else | ||
221 | e->arpq_head = skb; | ||
222 | e->arpq_tail = skb; | ||
223 | } | ||
224 | |||
225 | int cxgb4_l2t_send(struct net_device *dev, struct sk_buff *skb, | ||
226 | struct l2t_entry *e) | ||
227 | { | ||
228 | struct adapter *adap = netdev2adap(dev); | ||
229 | |||
230 | again: | ||
231 | switch (e->state) { | ||
232 | case L2T_STATE_STALE: /* entry is stale, kick off revalidation */ | ||
233 | neigh_event_send(e->neigh, NULL); | ||
234 | spin_lock_bh(&e->lock); | ||
235 | if (e->state == L2T_STATE_STALE) | ||
236 | e->state = L2T_STATE_VALID; | ||
237 | spin_unlock_bh(&e->lock); | ||
238 | case L2T_STATE_VALID: /* fast-path, send the packet on */ | ||
239 | return t4_ofld_send(adap, skb); | ||
240 | case L2T_STATE_RESOLVING: | ||
241 | case L2T_STATE_SYNC_WRITE: | ||
242 | spin_lock_bh(&e->lock); | ||
243 | if (e->state != L2T_STATE_SYNC_WRITE && | ||
244 | e->state != L2T_STATE_RESOLVING) { | ||
245 | spin_unlock_bh(&e->lock); | ||
246 | goto again; | ||
247 | } | ||
248 | arpq_enqueue(e, skb); | ||
249 | spin_unlock_bh(&e->lock); | ||
250 | |||
251 | if (e->state == L2T_STATE_RESOLVING && | ||
252 | !neigh_event_send(e->neigh, NULL)) { | ||
253 | spin_lock_bh(&e->lock); | ||
254 | if (e->state == L2T_STATE_RESOLVING && e->arpq_head) | ||
255 | write_l2e(adap, e, 1); | ||
256 | spin_unlock_bh(&e->lock); | ||
257 | } | ||
258 | } | ||
259 | return 0; | ||
260 | } | ||
261 | EXPORT_SYMBOL(cxgb4_l2t_send); | ||
262 | |||
263 | /* | ||
264 | * Allocate a free L2T entry. Must be called with l2t_data.lock held. | ||
265 | */ | ||
266 | static struct l2t_entry *alloc_l2e(struct l2t_data *d) | ||
267 | { | ||
268 | struct l2t_entry *end, *e, **p; | ||
269 | |||
270 | if (!atomic_read(&d->nfree)) | ||
271 | return NULL; | ||
272 | |||
273 | /* there's definitely a free entry */ | ||
274 | for (e = d->rover, end = &d->l2tab[L2T_SIZE]; e != end; ++e) | ||
275 | if (atomic_read(&e->refcnt) == 0) | ||
276 | goto found; | ||
277 | |||
278 | for (e = d->l2tab; atomic_read(&e->refcnt); ++e) | ||
279 | ; | ||
280 | found: | ||
281 | d->rover = e + 1; | ||
282 | atomic_dec(&d->nfree); | ||
283 | |||
284 | /* | ||
285 | * The entry we found may be an inactive entry that is | ||
286 | * presently in the hash table. We need to remove it. | ||
287 | */ | ||
288 | if (e->state < L2T_STATE_SWITCHING) | ||
289 | for (p = &d->l2tab[e->hash].first; *p; p = &(*p)->next) | ||
290 | if (*p == e) { | ||
291 | *p = e->next; | ||
292 | e->next = NULL; | ||
293 | break; | ||
294 | } | ||
295 | |||
296 | e->state = L2T_STATE_UNUSED; | ||
297 | return e; | ||
298 | } | ||
299 | |||
300 | /* | ||
301 | * Called when an L2T entry has no more users. | ||
302 | */ | ||
303 | static void t4_l2e_free(struct l2t_entry *e) | ||
304 | { | ||
305 | struct l2t_data *d; | ||
306 | |||
307 | spin_lock_bh(&e->lock); | ||
308 | if (atomic_read(&e->refcnt) == 0) { /* hasn't been recycled */ | ||
309 | if (e->neigh) { | ||
310 | neigh_release(e->neigh); | ||
311 | e->neigh = NULL; | ||
312 | } | ||
313 | } | ||
314 | spin_unlock_bh(&e->lock); | ||
315 | |||
316 | d = container_of(e, struct l2t_data, l2tab[e->idx]); | ||
317 | atomic_inc(&d->nfree); | ||
318 | } | ||
319 | |||
320 | void cxgb4_l2t_release(struct l2t_entry *e) | ||
321 | { | ||
322 | if (atomic_dec_and_test(&e->refcnt)) | ||
323 | t4_l2e_free(e); | ||
324 | } | ||
325 | EXPORT_SYMBOL(cxgb4_l2t_release); | ||
326 | |||
327 | /* | ||
328 | * Update an L2T entry that was previously used for the same next hop as neigh. | ||
329 | * Must be called with softirqs disabled. | ||
330 | */ | ||
331 | static void reuse_entry(struct l2t_entry *e, struct neighbour *neigh) | ||
332 | { | ||
333 | unsigned int nud_state; | ||
334 | |||
335 | spin_lock(&e->lock); /* avoid race with t4_l2t_free */ | ||
336 | if (neigh != e->neigh) | ||
337 | neigh_replace(e, neigh); | ||
338 | nud_state = neigh->nud_state; | ||
339 | if (memcmp(e->dmac, neigh->ha, sizeof(e->dmac)) || | ||
340 | !(nud_state & NUD_VALID)) | ||
341 | e->state = L2T_STATE_RESOLVING; | ||
342 | else if (nud_state & NUD_CONNECTED) | ||
343 | e->state = L2T_STATE_VALID; | ||
344 | else | ||
345 | e->state = L2T_STATE_STALE; | ||
346 | spin_unlock(&e->lock); | ||
347 | } | ||
348 | |||
349 | struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh, | ||
350 | const struct net_device *physdev, | ||
351 | unsigned int priority) | ||
352 | { | ||
353 | u8 lport; | ||
354 | u16 vlan; | ||
355 | struct l2t_entry *e; | ||
356 | int addr_len = neigh->tbl->key_len; | ||
357 | u32 *addr = (u32 *)neigh->primary_key; | ||
358 | int ifidx = neigh->dev->ifindex; | ||
359 | int hash = addr_hash(addr, addr_len, ifidx); | ||
360 | |||
361 | if (neigh->dev->flags & IFF_LOOPBACK) | ||
362 | lport = netdev2pinfo(physdev)->tx_chan + 4; | ||
363 | else | ||
364 | lport = netdev2pinfo(physdev)->lport; | ||
365 | |||
366 | if (neigh->dev->priv_flags & IFF_802_1Q_VLAN) | ||
367 | vlan = vlan_dev_vlan_id(neigh->dev); | ||
368 | else | ||
369 | vlan = VLAN_NONE; | ||
370 | |||
371 | write_lock_bh(&d->lock); | ||
372 | for (e = d->l2tab[hash].first; e; e = e->next) | ||
373 | if (!addreq(e, addr) && e->ifindex == ifidx && | ||
374 | e->vlan == vlan && e->lport == lport) { | ||
375 | l2t_hold(d, e); | ||
376 | if (atomic_read(&e->refcnt) == 1) | ||
377 | reuse_entry(e, neigh); | ||
378 | goto done; | ||
379 | } | ||
380 | |||
381 | /* Need to allocate a new entry */ | ||
382 | e = alloc_l2e(d); | ||
383 | if (e) { | ||
384 | spin_lock(&e->lock); /* avoid race with t4_l2t_free */ | ||
385 | e->state = L2T_STATE_RESOLVING; | ||
386 | memcpy(e->addr, addr, addr_len); | ||
387 | e->ifindex = ifidx; | ||
388 | e->hash = hash; | ||
389 | e->lport = lport; | ||
390 | e->v6 = addr_len == 16; | ||
391 | atomic_set(&e->refcnt, 1); | ||
392 | neigh_replace(e, neigh); | ||
393 | e->vlan = vlan; | ||
394 | e->next = d->l2tab[hash].first; | ||
395 | d->l2tab[hash].first = e; | ||
396 | spin_unlock(&e->lock); | ||
397 | } | ||
398 | done: | ||
399 | write_unlock_bh(&d->lock); | ||
400 | return e; | ||
401 | } | ||
402 | EXPORT_SYMBOL(cxgb4_l2t_get); | ||
403 | |||
404 | /* | ||
405 | * Called when address resolution fails for an L2T entry to handle packets | ||
406 | * on the arpq head. If a packet specifies a failure handler it is invoked, | ||
407 | * otherwise the packet is sent to the device. | ||
408 | */ | ||
409 | static void handle_failed_resolution(struct adapter *adap, struct sk_buff *arpq) | ||
410 | { | ||
411 | while (arpq) { | ||
412 | struct sk_buff *skb = arpq; | ||
413 | const struct l2t_skb_cb *cb = L2T_SKB_CB(skb); | ||
414 | |||
415 | arpq = skb->next; | ||
416 | skb->next = NULL; | ||
417 | if (cb->arp_err_handler) | ||
418 | cb->arp_err_handler(cb->handle, skb); | ||
419 | else | ||
420 | t4_ofld_send(adap, skb); | ||
421 | } | ||
422 | } | ||
423 | |||
424 | /* | ||
425 | * Called when the host's neighbor layer makes a change to some entry that is | ||
426 | * loaded into the HW L2 table. | ||
427 | */ | ||
428 | void t4_l2t_update(struct adapter *adap, struct neighbour *neigh) | ||
429 | { | ||
430 | struct l2t_entry *e; | ||
431 | struct sk_buff *arpq = NULL; | ||
432 | struct l2t_data *d = adap->l2t; | ||
433 | int addr_len = neigh->tbl->key_len; | ||
434 | u32 *addr = (u32 *) neigh->primary_key; | ||
435 | int ifidx = neigh->dev->ifindex; | ||
436 | int hash = addr_hash(addr, addr_len, ifidx); | ||
437 | |||
438 | read_lock_bh(&d->lock); | ||
439 | for (e = d->l2tab[hash].first; e; e = e->next) | ||
440 | if (!addreq(e, addr) && e->ifindex == ifidx) { | ||
441 | spin_lock(&e->lock); | ||
442 | if (atomic_read(&e->refcnt)) | ||
443 | goto found; | ||
444 | spin_unlock(&e->lock); | ||
445 | break; | ||
446 | } | ||
447 | read_unlock_bh(&d->lock); | ||
448 | return; | ||
449 | |||
450 | found: | ||
451 | read_unlock(&d->lock); | ||
452 | |||
453 | if (neigh != e->neigh) | ||
454 | neigh_replace(e, neigh); | ||
455 | |||
456 | if (e->state == L2T_STATE_RESOLVING) { | ||
457 | if (neigh->nud_state & NUD_FAILED) { | ||
458 | arpq = e->arpq_head; | ||
459 | e->arpq_head = e->arpq_tail = NULL; | ||
460 | } else if ((neigh->nud_state & (NUD_CONNECTED | NUD_STALE)) && | ||
461 | e->arpq_head) { | ||
462 | write_l2e(adap, e, 1); | ||
463 | } | ||
464 | } else { | ||
465 | e->state = neigh->nud_state & NUD_CONNECTED ? | ||
466 | L2T_STATE_VALID : L2T_STATE_STALE; | ||
467 | if (memcmp(e->dmac, neigh->ha, sizeof(e->dmac))) | ||
468 | write_l2e(adap, e, 0); | ||
469 | } | ||
470 | |||
471 | spin_unlock_bh(&e->lock); | ||
472 | |||
473 | if (arpq) | ||
474 | handle_failed_resolution(adap, arpq); | ||
475 | } | ||
476 | |||
477 | /* | ||
478 | * Allocate an L2T entry for use by a switching rule. Such entries need to be | ||
479 | * explicitly freed and while busy they are not on any hash chain, so normal | ||
480 | * address resolution updates do not see them. | ||
481 | */ | ||
482 | struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d) | ||
483 | { | ||
484 | struct l2t_entry *e; | ||
485 | |||
486 | write_lock_bh(&d->lock); | ||
487 | e = alloc_l2e(d); | ||
488 | if (e) { | ||
489 | spin_lock(&e->lock); /* avoid race with t4_l2t_free */ | ||
490 | e->state = L2T_STATE_SWITCHING; | ||
491 | atomic_set(&e->refcnt, 1); | ||
492 | spin_unlock(&e->lock); | ||
493 | } | ||
494 | write_unlock_bh(&d->lock); | ||
495 | return e; | ||
496 | } | ||
497 | |||
498 | /* | ||
499 | * Sets/updates the contents of a switching L2T entry that has been allocated | ||
500 | * with an earlier call to @t4_l2t_alloc_switching. | ||
501 | */ | ||
502 | int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan, | ||
503 | u8 port, u8 *eth_addr) | ||
504 | { | ||
505 | e->vlan = vlan; | ||
506 | e->lport = port; | ||
507 | memcpy(e->dmac, eth_addr, ETH_ALEN); | ||
508 | return write_l2e(adap, e, 0); | ||
509 | } | ||
510 | |||
511 | struct l2t_data *t4_init_l2t(void) | ||
512 | { | ||
513 | int i; | ||
514 | struct l2t_data *d; | ||
515 | |||
516 | d = t4_alloc_mem(sizeof(*d)); | ||
517 | if (!d) | ||
518 | return NULL; | ||
519 | |||
520 | d->rover = d->l2tab; | ||
521 | atomic_set(&d->nfree, L2T_SIZE); | ||
522 | rwlock_init(&d->lock); | ||
523 | |||
524 | for (i = 0; i < L2T_SIZE; ++i) { | ||
525 | d->l2tab[i].idx = i; | ||
526 | d->l2tab[i].state = L2T_STATE_UNUSED; | ||
527 | spin_lock_init(&d->l2tab[i].lock); | ||
528 | atomic_set(&d->l2tab[i].refcnt, 0); | ||
529 | } | ||
530 | return d; | ||
531 | } | ||
532 | |||
533 | #include <linux/module.h> | ||
534 | #include <linux/debugfs.h> | ||
535 | #include <linux/seq_file.h> | ||
536 | |||
537 | static inline void *l2t_get_idx(struct seq_file *seq, loff_t pos) | ||
538 | { | ||
539 | struct l2t_entry *l2tab = seq->private; | ||
540 | |||
541 | return pos >= L2T_SIZE ? NULL : &l2tab[pos]; | ||
542 | } | ||
543 | |||
544 | static void *l2t_seq_start(struct seq_file *seq, loff_t *pos) | ||
545 | { | ||
546 | return *pos ? l2t_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; | ||
547 | } | ||
548 | |||
549 | static void *l2t_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
550 | { | ||
551 | v = l2t_get_idx(seq, *pos); | ||
552 | if (v) | ||
553 | ++*pos; | ||
554 | return v; | ||
555 | } | ||
556 | |||
557 | static void l2t_seq_stop(struct seq_file *seq, void *v) | ||
558 | { | ||
559 | } | ||
560 | |||
561 | static char l2e_state(const struct l2t_entry *e) | ||
562 | { | ||
563 | switch (e->state) { | ||
564 | case L2T_STATE_VALID: return 'V'; | ||
565 | case L2T_STATE_STALE: return 'S'; | ||
566 | case L2T_STATE_SYNC_WRITE: return 'W'; | ||
567 | case L2T_STATE_RESOLVING: return e->arpq_head ? 'A' : 'R'; | ||
568 | case L2T_STATE_SWITCHING: return 'X'; | ||
569 | default: | ||
570 | return 'U'; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | static int l2t_seq_show(struct seq_file *seq, void *v) | ||
575 | { | ||
576 | if (v == SEQ_START_TOKEN) | ||
577 | seq_puts(seq, " Idx IP address " | ||
578 | "Ethernet address VLAN/P LP State Users Port\n"); | ||
579 | else { | ||
580 | char ip[60]; | ||
581 | struct l2t_entry *e = v; | ||
582 | |||
583 | spin_lock_bh(&e->lock); | ||
584 | if (e->state == L2T_STATE_SWITCHING) | ||
585 | ip[0] = '\0'; | ||
586 | else | ||
587 | sprintf(ip, e->v6 ? "%pI6c" : "%pI4", e->addr); | ||
588 | seq_printf(seq, "%4u %-25s %17pM %4d %u %2u %c %5u %s\n", | ||
589 | e->idx, ip, e->dmac, | ||
590 | e->vlan & VLAN_VID_MASK, vlan_prio(e), e->lport, | ||
591 | l2e_state(e), atomic_read(&e->refcnt), | ||
592 | e->neigh ? e->neigh->dev->name : ""); | ||
593 | spin_unlock_bh(&e->lock); | ||
594 | } | ||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | static const struct seq_operations l2t_seq_ops = { | ||
599 | .start = l2t_seq_start, | ||
600 | .next = l2t_seq_next, | ||
601 | .stop = l2t_seq_stop, | ||
602 | .show = l2t_seq_show | ||
603 | }; | ||
604 | |||
605 | static int l2t_seq_open(struct inode *inode, struct file *file) | ||
606 | { | ||
607 | int rc = seq_open(file, &l2t_seq_ops); | ||
608 | |||
609 | if (!rc) { | ||
610 | struct adapter *adap = inode->i_private; | ||
611 | struct seq_file *seq = file->private_data; | ||
612 | |||
613 | seq->private = adap->l2t->l2tab; | ||
614 | } | ||
615 | return rc; | ||
616 | } | ||
617 | |||
618 | const struct file_operations t4_l2t_fops = { | ||
619 | .owner = THIS_MODULE, | ||
620 | .open = l2t_seq_open, | ||
621 | .read = seq_read, | ||
622 | .llseek = seq_lseek, | ||
623 | .release = seq_release, | ||
624 | }; | ||
diff --git a/drivers/net/cxgb4/l2t.h b/drivers/net/cxgb4/l2t.h new file mode 100644 index 000000000000..643f27ed3cf4 --- /dev/null +++ b/drivers/net/cxgb4/l2t.h | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * This file is part of the Chelsio T4 Ethernet driver for Linux. | ||
3 | * | ||
4 | * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved. | ||
5 | * | ||
6 | * This software is available to you under a choice of one of two | ||
7 | * licenses. You may choose to be licensed under the terms of the GNU | ||
8 | * General Public License (GPL) Version 2, available from the file | ||
9 | * COPYING in the main directory of this source tree, or the | ||
10 | * OpenIB.org BSD license below: | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or | ||
13 | * without modification, are permitted provided that the following | ||
14 | * conditions are met: | ||
15 | * | ||
16 | * - Redistributions of source code must retain the above | ||
17 | * copyright notice, this list of conditions and the following | ||
18 | * disclaimer. | ||
19 | * | ||
20 | * - Redistributions in binary form must reproduce the above | ||
21 | * copyright notice, this list of conditions and the following | ||
22 | * disclaimer in the documentation and/or other materials | ||
23 | * provided with the distribution. | ||
24 | * | ||
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
29 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
30 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
32 | * SOFTWARE. | ||
33 | */ | ||
34 | |||
35 | #ifndef __CXGB4_L2T_H | ||
36 | #define __CXGB4_L2T_H | ||
37 | |||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/if_ether.h> | ||
40 | #include <asm/atomic.h> | ||
41 | |||
42 | struct adapter; | ||
43 | struct l2t_data; | ||
44 | struct neighbour; | ||
45 | struct net_device; | ||
46 | struct file_operations; | ||
47 | struct cpl_l2t_write_rpl; | ||
48 | |||
49 | /* | ||
50 | * Each L2T entry plays multiple roles. First of all, it keeps state for the | ||
51 | * corresponding entry of the HW L2 table and maintains a queue of offload | ||
52 | * packets awaiting address resolution. Second, it is a node of a hash table | ||
53 | * chain, where the nodes of the chain are linked together through their next | ||
54 | * pointer. Finally, each node is a bucket of a hash table, pointing to the | ||
55 | * first element in its chain through its first pointer. | ||
56 | */ | ||
57 | struct l2t_entry { | ||
58 | u16 state; /* entry state */ | ||
59 | u16 idx; /* entry index */ | ||
60 | u32 addr[4]; /* next hop IP or IPv6 address */ | ||
61 | int ifindex; /* neighbor's net_device's ifindex */ | ||
62 | struct neighbour *neigh; /* associated neighbour */ | ||
63 | struct l2t_entry *first; /* start of hash chain */ | ||
64 | struct l2t_entry *next; /* next l2t_entry on chain */ | ||
65 | struct sk_buff *arpq_head; /* queue of packets awaiting resolution */ | ||
66 | struct sk_buff *arpq_tail; | ||
67 | spinlock_t lock; | ||
68 | atomic_t refcnt; /* entry reference count */ | ||
69 | u16 hash; /* hash bucket the entry is on */ | ||
70 | u16 vlan; /* VLAN TCI (id: bits 0-11, prio: 13-15 */ | ||
71 | u8 v6; /* whether entry is for IPv6 */ | ||
72 | u8 lport; /* associated offload logical interface */ | ||
73 | u8 dmac[ETH_ALEN]; /* neighbour's MAC address */ | ||
74 | }; | ||
75 | |||
76 | typedef void (*arp_err_handler_t)(void *handle, struct sk_buff *skb); | ||
77 | |||
78 | /* | ||
79 | * Callback stored in an skb to handle address resolution failure. | ||
80 | */ | ||
81 | struct l2t_skb_cb { | ||
82 | void *handle; | ||
83 | arp_err_handler_t arp_err_handler; | ||
84 | }; | ||
85 | |||
86 | #define L2T_SKB_CB(skb) ((struct l2t_skb_cb *)(skb)->cb) | ||
87 | |||
88 | static inline void t4_set_arp_err_handler(struct sk_buff *skb, void *handle, | ||
89 | arp_err_handler_t handler) | ||
90 | { | ||
91 | L2T_SKB_CB(skb)->handle = handle; | ||
92 | L2T_SKB_CB(skb)->arp_err_handler = handler; | ||
93 | } | ||
94 | |||
95 | void cxgb4_l2t_release(struct l2t_entry *e); | ||
96 | int cxgb4_l2t_send(struct net_device *dev, struct sk_buff *skb, | ||
97 | struct l2t_entry *e); | ||
98 | struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh, | ||
99 | const struct net_device *physdev, | ||
100 | unsigned int priority); | ||
101 | |||
102 | void t4_l2t_update(struct adapter *adap, struct neighbour *neigh); | ||
103 | struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d); | ||
104 | int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan, | ||
105 | u8 port, u8 *eth_addr); | ||
106 | struct l2t_data *t4_init_l2t(void); | ||
107 | void do_l2t_write_rpl(struct adapter *p, const struct cpl_l2t_write_rpl *rpl); | ||
108 | |||
109 | extern const struct file_operations t4_l2t_fops; | ||
110 | #endif /* __CXGB4_L2T_H */ | ||