]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.xen/sfc-resource-driver
Updated xen patches taken from suse.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.xen / sfc-resource-driver
1 From: David Riddoch <driddoch@solarflare.com>
2 # replaces http://xenbits.xensource.com/linux-2.6.18-xen.hg c/s 421:
3 # HG changeset patch
4 # User Keir Fraser <keir.fraser@citrix.com>
5 # Date 1203330569 0
6 # Node ID e4dd072db2595c420bb21d9e835416f4fd543526
7 # Parent fc90e9b2c12b316b5460ece28f013e6de881af1a
8 Subject: Solarflare: Resource driver.
9 References: FATE#303479
10 Acked-by: jbeulich@novell.com
11
12 Index: head-2008-07-15/drivers/net/sfc/Kconfig
13 ===================================================================
14 --- head-2008-07-15.orig/drivers/net/sfc/Kconfig 2008-07-17 16:17:36.000000000 +0200
15 +++ head-2008-07-15/drivers/net/sfc/Kconfig 2008-07-17 16:18:07.000000000 +0200
16 @@ -12,3 +12,9 @@ config SFC
17
18 To compile this driver as a module, choose M here. The module
19 will be called sfc.
20 +
21 +config SFC_RESOURCE
22 + depends on SFC && X86
23 + tristate "Solarflare Solarstorm SFC4000 resource driver"
24 + help
25 + This module provides the SFC resource manager driver.
26 Index: head-2008-07-15/drivers/net/sfc/Makefile
27 ===================================================================
28 --- head-2008-07-15.orig/drivers/net/sfc/Makefile 2008-07-17 16:17:53.000000000 +0200
29 +++ head-2008-07-15/drivers/net/sfc/Makefile 2008-07-17 16:18:07.000000000 +0200
30 @@ -3,3 +3,5 @@ sfc-y += efx.o falcon.o tx.o rx.o falc
31 mdio_10g.o tenxpress.o boards.o sfe4001.o \
32 driverlink.o
33 obj-$(CONFIG_SFC) += sfc.o
34 +
35 +obj-$(CONFIG_SFC_RESOURCE) += sfc_resource/
36 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/Makefile
37 ===================================================================
38 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
39 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/Makefile 2008-07-17 16:18:07.000000000 +0200
40 @@ -0,0 +1,14 @@
41 +obj-$(CONFIG_SFC_RESOURCE) := sfc_resource.o
42 +
43 +EXTRA_CFLAGS += -D__CI_HARDWARE_CONFIG_FALCON__
44 +EXTRA_CFLAGS += -D__ci_driver__
45 +EXTRA_CFLAGS += -Werror
46 +EXTRA_CFLAGS += -Idrivers/net/sfc -Idrivers/net/sfc/sfc_resource
47 +
48 +sfc_resource-objs := resource_driver.o iopage.o efx_vi_shm.o \
49 + driverlink_new.o kernel_proc.o kfifo.o \
50 + nic.o eventq.o falcon.o falcon_hash.o \
51 + assert_valid.o buddy.o buffer_table.o filter_resource.o \
52 + iobufset_resource.o resource_manager.o resources.o \
53 + vi_resource_alloc.o vi_resource_event.o vi_resource_flush.o \
54 + vi_resource_manager.o driver_object.o kernel_compat.o
55 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/assert_valid.c
56 ===================================================================
57 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
58 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/assert_valid.c 2008-07-17 16:18:07.000000000 +0200
59 @@ -0,0 +1,92 @@
60 +/****************************************************************************
61 + * Driver for Solarflare network controllers -
62 + * resource management for Xen backend, OpenOnload, etc
63 + * (including support for SFE4001 10GBT NIC)
64 + *
65 + * This file contains functions to assert validness of resources and
66 + * resource manager in DEBUG build of the resource driver.
67 + *
68 + * Copyright 2005-2007: Solarflare Communications Inc,
69 + * 9501 Jeronimo Road, Suite 250,
70 + * Irvine, CA 92618, USA
71 + *
72 + * Developed and maintained by Solarflare Communications:
73 + * <linux-xen-drivers@solarflare.com>
74 + * <onload-dev@solarflare.com>
75 + *
76 + * Certain parts of the driver were implemented by
77 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
78 + * OKTET Labs Ltd, Russia,
79 + * http://oktetlabs.ru, <info@oktetlabs.ru>
80 + * by request of Solarflare Communications
81 + *
82 + *
83 + * This program is free software; you can redistribute it and/or modify it
84 + * under the terms of the GNU General Public License version 2 as published
85 + * by the Free Software Foundation, incorporated herein by reference.
86 + *
87 + * This program is distributed in the hope that it will be useful,
88 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
89 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
90 + * GNU General Public License for more details.
91 + *
92 + * You should have received a copy of the GNU General Public License
93 + * along with this program; if not, write to the Free Software
94 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
95 + ****************************************************************************
96 + */
97 +
98 +#include <ci/efrm/sysdep.h>
99 +
100 +#ifndef NDEBUG
101 +#include <ci/efrm/resource.h>
102 +#include <ci/efrm/driver_private.h>
103 +#include <ci/efrm/debug.h>
104 +
105 +void
106 +efrm_resource_manager_assert_valid(struct efrm_resource_manager *rm,
107 + const char *file, int line)
108 +{
109 + _EFRM_ASSERT(rm, file, line);
110 + _EFRM_ASSERT(rm->rm_name, file, line);
111 + _EFRM_ASSERT(rm->rm_type < EFRM_RESOURCE_NUM, file, line);
112 + _EFRM_ASSERT(rm->rm_dtor, file, line);
113 +}
114 +EXPORT_SYMBOL(efrm_resource_manager_assert_valid);
115 +
116 +/*
117 + * \param rs resource to validate
118 + * \param ref_count_is_zero One of 3 values
119 + * > 0 - check ref count is zero
120 + * = 0 - check ref count is non-zero
121 + * < 0 - ref count could be any value
122 + */
123 +void
124 +efrm_resource_assert_valid(struct efrm_resource *rs, int ref_count_is_zero,
125 + const char *file, int line)
126 +{
127 + struct efrm_resource_manager *rm;
128 +
129 + _EFRM_ASSERT(rs, file, line);
130 +
131 + if (ref_count_is_zero >= 0) {
132 + if (!(ref_count_is_zero || rs->rs_ref_count > 0)
133 + || !(!ref_count_is_zero || rs->rs_ref_count == 0))
134 + EFRM_WARN("%s: check %szero ref=%d " EFRM_RESOURCE_FMT,
135 + __func__,
136 + ref_count_is_zero == 0 ? "non-" : "",
137 + rs->rs_ref_count,
138 + EFRM_RESOURCE_PRI_ARG(rs->rs_handle));
139 +
140 + _EFRM_ASSERT(!(ref_count_is_zero == 0) ||
141 + rs->rs_ref_count != 0, file, line);
142 + _EFRM_ASSERT(!(ref_count_is_zero > 0) ||
143 + rs->rs_ref_count == 0, file, line);
144 + }
145 +
146 + rm = efrm_rm_table[EFRM_RESOURCE_TYPE(rs->rs_handle)];
147 + efrm_resource_manager_assert_valid(rm, file, line);
148 +}
149 +EXPORT_SYMBOL(efrm_resource_assert_valid);
150 +
151 +#endif
152 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/buddy.c
153 ===================================================================
154 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
155 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/buddy.c 2008-07-17 16:18:07.000000000 +0200
156 @@ -0,0 +1,220 @@
157 +
158 +/****************************************************************************
159 + * Driver for Solarflare network controllers -
160 + * resource management for Xen backend, OpenOnload, etc
161 + * (including support for SFE4001 10GBT NIC)
162 + *
163 + * This file contains implementation of a buddy allocator.
164 + *
165 + * Copyright 2005-2007: Solarflare Communications Inc,
166 + * 9501 Jeronimo Road, Suite 250,
167 + * Irvine, CA 92618, USA
168 + *
169 + * Developed and maintained by Solarflare Communications:
170 + * <linux-xen-drivers@solarflare.com>
171 + * <onload-dev@solarflare.com>
172 + *
173 + * Certain parts of the driver were implemented by
174 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
175 + * OKTET Labs Ltd, Russia,
176 + * http://oktetlabs.ru, <info@oktetlabs.ru>
177 + * by request of Solarflare Communications
178 + *
179 + *
180 + * This program is free software; you can redistribute it and/or modify it
181 + * under the terms of the GNU General Public License version 2 as published
182 + * by the Free Software Foundation, incorporated herein by reference.
183 + *
184 + * This program is distributed in the hope that it will be useful,
185 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
186 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
187 + * GNU General Public License for more details.
188 + *
189 + * You should have received a copy of the GNU General Public License
190 + * along with this program; if not, write to the Free Software
191 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
192 + ****************************************************************************
193 + */
194 +
195 +#include <ci/efhw/common.h> /* get uintXX types on win32 */
196 +#include <ci/efrm/sysdep.h>
197 +#include <ci/efrm/buddy.h>
198 +#include <ci/efrm/debug.h>
199 +
200 +#if 1
201 +#define DEBUG_ALLOC(x)
202 +#else
203 +#define DEBUG_ALLOC(x) x
204 +
205 +static inline void efrm_buddy_dump(struct efrm_buddy_allocator *b)
206 +{
207 + unsigned o;
208 +
209 + EFRM_NOTICE("%s: dump allocator with order %u",
210 + __func__, b->order);
211 + for (o = 0; o <= b->order; o++) {
212 + struct list_head *l = &b->free_lists[o];
213 + while (l->next != &b->free_lists[o]) {
214 + l = l->next;
215 + EFRM_NOTICE("%s: order %x: %zx", __func__, o,
216 + l - b->links);
217 + }
218 + }
219 +}
220 +#endif
221 +
222 +/*
223 + * The purpose of the following inline functions is to give the
224 + * understandable names to the simple actions.
225 + */
226 +static inline void
227 +efrm_buddy_free_list_add(struct efrm_buddy_allocator *b,
228 + unsigned order, unsigned addr)
229 +{
230 + list_add(&b->links[addr], &b->free_lists[order]);
231 + b->orders[addr] = (uint8_t) order;
232 +}
233 +static inline void
234 +efrm_buddy_free_list_del(struct efrm_buddy_allocator *b, unsigned addr)
235 +{
236 + list_del(&b->links[addr]);
237 + b->links[addr].next = NULL;
238 +}
239 +static inline int
240 +efrm_buddy_free_list_empty(struct efrm_buddy_allocator *b, unsigned order)
241 +{
242 + return list_empty(&b->free_lists[order]);
243 +}
244 +static inline unsigned
245 +efrm_buddy_free_list_pop(struct efrm_buddy_allocator *b, unsigned order)
246 +{
247 + struct list_head *l = list_pop(&b->free_lists[order]);
248 + l->next = NULL;
249 + return (unsigned)(l - b->links);
250 +}
251 +static inline int
252 +efrm_buddy_addr_in_free_list(struct efrm_buddy_allocator *b, unsigned addr)
253 +{
254 + return b->links[addr].next != NULL;
255 +}
256 +static inline unsigned
257 +efrm_buddy_free_list_first(struct efrm_buddy_allocator *b, unsigned order)
258 +{
259 + return (unsigned)(b->free_lists[order].next - b->links);
260 +}
261 +
262 +int efrm_buddy_ctor(struct efrm_buddy_allocator *b, unsigned order)
263 +{
264 + unsigned o;
265 + unsigned size = 1 << order;
266 +
267 + DEBUG_ALLOC(EFRM_NOTICE("%s(%u)", __func__, order));
268 + EFRM_ASSERT(b);
269 + EFRM_ASSERT(order <= sizeof(unsigned) * 8 - 1);
270 +
271 + b->order = order;
272 + b->free_lists = vmalloc((order + 1) * sizeof(struct list_head));
273 + if (b->free_lists == NULL)
274 + goto fail1;
275 +
276 + b->links = vmalloc(size * sizeof(struct list_head));
277 + if (b->links == NULL)
278 + goto fail2;
279 +
280 + b->orders = vmalloc(size);
281 + if (b->orders == NULL)
282 + goto fail3;
283 +
284 + memset(b->links, 0, size * sizeof(struct list_head));
285 +
286 + for (o = 0; o <= b->order; ++o)
287 + INIT_LIST_HEAD(b->free_lists + o);
288 +
289 + efrm_buddy_free_list_add(b, b->order, 0);
290 +
291 + return 0;
292 +
293 +fail3:
294 + vfree(b->links);
295 +fail2:
296 + vfree(b->free_lists);
297 +fail1:
298 + return -ENOMEM;
299 +}
300 +
301 +void efrm_buddy_dtor(struct efrm_buddy_allocator *b)
302 +{
303 + EFRM_ASSERT(b);
304 +
305 + vfree(b->free_lists);
306 + vfree(b->links);
307 + vfree(b->orders);
308 +}
309 +
310 +int efrm_buddy_alloc(struct efrm_buddy_allocator *b, unsigned order)
311 +{
312 + unsigned smallest;
313 + unsigned addr;
314 +
315 + DEBUG_ALLOC(EFRM_NOTICE("%s(%u)", __func__, order));
316 + EFRM_ASSERT(b);
317 +
318 + /* Find smallest chunk that is big enough. ?? Can optimise this by
319 + ** keeping array of pointers to smallest chunk for each order.
320 + */
321 + smallest = order;
322 + while (smallest <= b->order &&
323 + efrm_buddy_free_list_empty(b, smallest))
324 + ++smallest;
325 +
326 + if (smallest > b->order) {
327 + DEBUG_ALLOC(EFRM_NOTICE
328 + ("buddy - alloc order %d failed - max order %d",
329 + order, b->order););
330 + return -ENOMEM;
331 + }
332 +
333 + /* Split blocks until we get one of the correct size. */
334 + addr = efrm_buddy_free_list_pop(b, smallest);
335 +
336 + DEBUG_ALLOC(EFRM_NOTICE("buddy - alloc %x order %d cut from order %d",
337 + addr, order, smallest););
338 + while (smallest-- > order)
339 + efrm_buddy_free_list_add(b, smallest, addr + (1 << smallest));
340 +
341 + EFRM_DO_DEBUG(b->orders[addr] = (uint8_t) order);
342 +
343 + EFRM_ASSERT(addr < 1u << b->order);
344 + return addr;
345 +}
346 +
347 +void
348 +efrm_buddy_free(struct efrm_buddy_allocator *b, unsigned addr,
349 + unsigned order)
350 +{
351 + unsigned buddy_addr;
352 +
353 + DEBUG_ALLOC(EFRM_NOTICE("%s(%u, %u)", __func__, addr, order));
354 + EFRM_ASSERT(b);
355 + EFRM_ASSERT(order <= b->order);
356 + EFRM_ASSERT((unsigned long)addr + ((unsigned long)1 << order) <=
357 + (unsigned long)1 << b->order);
358 + EFRM_ASSERT(!efrm_buddy_addr_in_free_list(b, addr));
359 + EFRM_ASSERT(b->orders[addr] == order);
360 +
361 + /* merge free blocks */
362 + while (order < b->order) {
363 + buddy_addr = addr ^ (1 << order);
364 + if (!efrm_buddy_addr_in_free_list(b, buddy_addr) ||
365 + b->orders[buddy_addr] != order)
366 + break;
367 + efrm_buddy_free_list_del(b, buddy_addr);
368 + if (buddy_addr < addr)
369 + addr = buddy_addr;
370 + ++order;
371 + }
372 +
373 + DEBUG_ALLOC(EFRM_NOTICE
374 + ("buddy - free %x merged into order %d", addr, order););
375 + efrm_buddy_free_list_add(b, order, addr);
376 +}
377 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/buffer_table.c
378 ===================================================================
379 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
380 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/buffer_table.c 2008-07-17 16:18:07.000000000 +0200
381 @@ -0,0 +1,209 @@
382 +/****************************************************************************
383 + * Driver for Solarflare network controllers -
384 + * resource management for Xen backend, OpenOnload, etc
385 + * (including support for SFE4001 10GBT NIC)
386 + *
387 + * This file contains abstraction of the buffer table on the NIC.
388 + *
389 + * Copyright 2005-2007: Solarflare Communications Inc,
390 + * 9501 Jeronimo Road, Suite 250,
391 + * Irvine, CA 92618, USA
392 + *
393 + * Developed and maintained by Solarflare Communications:
394 + * <linux-xen-drivers@solarflare.com>
395 + * <onload-dev@solarflare.com>
396 + *
397 + *
398 + * This program is free software; you can redistribute it and/or modify it
399 + * under the terms of the GNU General Public License version 2 as published
400 + * by the Free Software Foundation, incorporated herein by reference.
401 + *
402 + * This program is distributed in the hope that it will be useful,
403 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
404 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
405 + * GNU General Public License for more details.
406 + *
407 + * You should have received a copy of the GNU General Public License
408 + * along with this program; if not, write to the Free Software
409 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
410 + ****************************************************************************
411 + */
412 +
413 +/*
414 +** Might be worth keeping a bitmap of which entries are clear. Then we
415 +** wouldn't need to clear them all again when we free an allocation.
416 +*/
417 +
418 +#include <ci/efrm/debug.h>
419 +#include <ci/driver/efab/hardware.h>
420 +#include <ci/efrm/nic_table.h>
421 +#include <ci/efrm/buffer_table.h>
422 +#include <ci/efrm/buddy.h>
423 +
424 +/*! Comment? */
425 +struct efrm_buffer_table {
426 + spinlock_t lock;
427 + struct efrm_buddy_allocator buddy;
428 +};
429 +
430 +/* Efab buffer state. */
431 +static struct efrm_buffer_table efrm_buffers;
432 +
433 +int efrm_buffer_table_ctor(unsigned low, unsigned high)
434 +{
435 + int log2_n_entries, rc, i;
436 +
437 + EFRM_ASSERT(high > 0);
438 + EFRM_ASSERT(low < high);
439 +
440 + EFRM_TRACE("%s: low=%u high=%u", __func__, low, high);
441 + EFRM_NOTICE("%s: low=%u high=%u", __func__, low, high);
442 +
443 + log2_n_entries = fls(high - 1);
444 +
445 + rc = efrm_buddy_ctor(&efrm_buffers.buddy, log2_n_entries);
446 + if (rc < 0) {
447 + EFRM_ERR("efrm_buffer_table_ctor: efrm_buddy_ctor(%d) "
448 + "failed (%d)", log2_n_entries, rc);
449 + return rc;
450 + }
451 + for (i = 0; i < (1 << log2_n_entries); ++i) {
452 + rc = efrm_buddy_alloc(&efrm_buffers.buddy, 0);
453 + EFRM_ASSERT(rc >= 0);
454 + EFRM_ASSERT(rc < (1 << log2_n_entries));
455 + }
456 + for (i = low; i < (int) high; ++i)
457 + efrm_buddy_free(&efrm_buffers.buddy, i, 0);
458 +
459 + spin_lock_init(&efrm_buffers.lock);
460 +
461 + EFRM_TRACE("%s: done", __func__);
462 +
463 + return 0;
464 +}
465 +
466 +void efrm_buffer_table_dtor(void)
467 +{
468 + /* ?? debug check that all allocations have been freed? */
469 +
470 + spin_lock_destroy(&efrm_buffers.lock);
471 + efrm_buddy_dtor(&efrm_buffers.buddy);
472 +
473 + EFRM_TRACE("%s: done", __func__);
474 +}
475 +
476 +/**********************************************************************/
477 +
478 +int
479 +efrm_buffer_table_alloc(unsigned order,
480 + struct efhw_buffer_table_allocation *a)
481 +{
482 + irq_flags_t lock_flags;
483 + int rc;
484 +
485 + EFRM_ASSERT(&efrm_buffers.buddy);
486 + EFRM_ASSERT(a);
487 +
488 + /* Round up to multiple of two, as the buffer clear logic works in
489 + * pairs when not in "full" mode. */
490 + order = max_t(unsigned, order, 1);
491 +
492 + spin_lock_irqsave(&efrm_buffers.lock, lock_flags);
493 + rc = efrm_buddy_alloc(&efrm_buffers.buddy, order);
494 + spin_unlock_irqrestore(&efrm_buffers.lock, lock_flags);
495 +
496 + if (rc < 0) {
497 + EFRM_ERR("efrm_buffer_table_alloc: failed (n=%ld) rc %d",
498 + 1ul << order, rc);
499 + return rc;
500 + }
501 +
502 + EFRM_TRACE("efrm_buffer_table_alloc: base=%d n=%ld",
503 + rc, 1ul << order);
504 + a->order = order;
505 + a->base = (unsigned)rc;
506 + return 0;
507 +}
508 +
509 +void efrm_buffer_table_free(struct efhw_buffer_table_allocation *a)
510 +{
511 + irq_flags_t lock_flags;
512 + struct efhw_nic *nic;
513 + int nic_i;
514 +
515 + EFRM_ASSERT(&efrm_buffers.buddy);
516 + EFRM_ASSERT(a);
517 + EFRM_ASSERT(a->base != -1);
518 + EFRM_ASSERT((unsigned long)a->base + (1ul << a->order) <=
519 + efrm_buddy_size(&efrm_buffers.buddy));
520 +
521 + EFRM_TRACE("efrm_buffer_table_free: base=%d n=%ld",
522 + a->base, (1ul << a->order));
523 +
524 + EFRM_FOR_EACH_NIC(nic_i, nic)
525 + efhw_nic_buffer_table_clear(nic, a->base, 1ul << a->order);
526 +
527 + spin_lock_irqsave(&efrm_buffers.lock, lock_flags);
528 + efrm_buddy_free(&efrm_buffers.buddy, a->base, a->order);
529 + spin_unlock_irqrestore(&efrm_buffers.lock, lock_flags);
530 +
531 + EFRM_DO_DEBUG(a->base = a->order = -1);
532 +}
533 +
534 +/**********************************************************************/
535 +
536 +void
537 +efrm_buffer_table_set(struct efhw_buffer_table_allocation *a,
538 + struct efhw_nic *nic,
539 + unsigned i, dma_addr_t dma_addr, int owner)
540 +{
541 + EFRM_ASSERT(a);
542 + EFRM_ASSERT(i < (unsigned)1 << a->order);
543 +
544 + efhw_nic_buffer_table_set(nic, dma_addr, EFHW_NIC_PAGE_SIZE,
545 + 0, owner, a->base + i);
546 +}
547 +
548 +
549 +int efrm_buffer_table_size(void)
550 +{
551 + return efrm_buddy_size(&efrm_buffers.buddy);
552 +}
553 +
554 +/**********************************************************************/
555 +
556 +int
557 +efrm_page_register(struct efhw_nic *nic, dma_addr_t dma_addr, int owner,
558 + efhw_buffer_addr_t *buf_addr_out)
559 +{
560 + struct efhw_buffer_table_allocation alloc;
561 + int rc;
562 +
563 + rc = efrm_buffer_table_alloc(0, &alloc);
564 + if (rc == 0) {
565 + efrm_buffer_table_set(&alloc, nic, 0, dma_addr, owner);
566 + efrm_buffer_table_commit();
567 + *buf_addr_out = EFHW_BUFFER_ADDR(alloc.base, 0);
568 + }
569 + return rc;
570 +}
571 +EXPORT_SYMBOL(efrm_page_register);
572 +
573 +void efrm_page_unregister(efhw_buffer_addr_t buf_addr)
574 +{
575 + struct efhw_buffer_table_allocation alloc;
576 +
577 + alloc.order = 0;
578 + alloc.base = EFHW_BUFFER_PAGE(buf_addr);
579 + efrm_buffer_table_free(&alloc);
580 +}
581 +EXPORT_SYMBOL(efrm_page_unregister);
582 +
583 +void efrm_buffer_table_commit(void)
584 +{
585 + struct efhw_nic *nic;
586 + int nic_i;
587 +
588 + EFRM_FOR_EACH_NIC(nic_i, nic)
589 + efhw_nic_buffer_table_commit(nic);
590 +}
591 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware.h
592 ===================================================================
593 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
594 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware.h 2008-07-17 16:18:07.000000000 +0200
595 @@ -0,0 +1,188 @@
596 +/****************************************************************************
597 + * Driver for Solarflare network controllers -
598 + * resource management for Xen backend, OpenOnload, etc
599 + * (including support for SFE4001 10GBT NIC)
600 + *
601 + * This file provides EtherFabric NIC hardware interface.
602 + *
603 + * Copyright 2005-2007: Solarflare Communications Inc,
604 + * 9501 Jeronimo Road, Suite 250,
605 + * Irvine, CA 92618, USA
606 + *
607 + * Developed and maintained by Solarflare Communications:
608 + * <linux-xen-drivers@solarflare.com>
609 + * <onload-dev@solarflare.com>
610 + *
611 + * Certain parts of the driver were implemented by
612 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
613 + * OKTET Labs Ltd, Russia,
614 + * http://oktetlabs.ru, <info@oktetlabs.ru>
615 + * by request of Solarflare Communications
616 + *
617 + *
618 + * This program is free software; you can redistribute it and/or modify it
619 + * under the terms of the GNU General Public License version 2 as published
620 + * by the Free Software Foundation, incorporated herein by reference.
621 + *
622 + * This program is distributed in the hope that it will be useful,
623 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
624 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
625 + * GNU General Public License for more details.
626 + *
627 + * You should have received a copy of the GNU General Public License
628 + * along with this program; if not, write to the Free Software
629 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
630 + ****************************************************************************
631 + */
632 +
633 +#ifndef __CI_DRIVER_EFAB_HARDWARE_H__
634 +#define __CI_DRIVER_EFAB_HARDWARE_H__
635 +
636 +#include "ci/driver/efab/hardware/workarounds.h"
637 +#include <ci/efhw/hardware_sysdep.h>
638 +
639 +
640 +/*----------------------------------------------------------------------------
641 + *
642 + * Common EtherFabric definitions
643 + *
644 + *---------------------------------------------------------------------------*/
645 +
646 +#include <ci/efhw/debug.h>
647 +#include <ci/efhw/common.h>
648 +#include <ci/driver/efab/hardware/common.h>
649 +
650 +/*----------------------------------------------------------------------------
651 + *
652 + * EtherFabric varients
653 + *
654 + *---------------------------------------------------------------------------*/
655 +
656 +#include <ci/driver/efab/hardware/falcon.h>
657 +
658 +/*----------------------------------------------------------------------------
659 + *
660 + * EtherFabric Portable Hardware Layer defines
661 + *
662 + *---------------------------------------------------------------------------*/
663 +
664 + /*-------------- Initialisation ------------ */
665 +#define efhw_nic_close_hardware(nic) \
666 + ((nic)->efhw_func->close_hardware(nic))
667 +
668 +#define efhw_nic_init_hardware(nic, ev_handlers, mac_addr, non_irq_evq) \
669 + ((nic)->efhw_func->init_hardware((nic), (ev_handlers), (mac_addr), \
670 + (non_irq_evq)))
671 +
672 +/*-------------- Interrupt support ------------ */
673 +/** Handle interrupt. Return 0 if not handled, 1 if handled. */
674 +#define efhw_nic_interrupt(nic) \
675 + ((nic)->efhw_func->interrupt(nic))
676 +
677 +#define efhw_nic_interrupt_enable(nic) \
678 + ((nic)->efhw_func->interrupt_enable(nic))
679 +
680 +#define efhw_nic_interrupt_disable(nic) \
681 + ((nic)->efhw_func->interrupt_disable(nic))
682 +
683 +#define efhw_nic_set_interrupt_moderation(nic, evq, val) \
684 + ((nic)->efhw_func->set_interrupt_moderation(nic, evq, val))
685 +
686 +/*-------------- Event support ------------ */
687 +
688 +#define efhw_nic_event_queue_enable(nic, evq, size, q_base, buf_base, \
689 + interrupting) \
690 + ((nic)->efhw_func->event_queue_enable((nic), (evq), (size), (q_base), \
691 + (buf_base), (interrupting)))
692 +
693 +#define efhw_nic_event_queue_disable(nic, evq, timer_only) \
694 + ((nic)->efhw_func->event_queue_disable(nic, evq, timer_only))
695 +
696 +#define efhw_nic_wakeup_request(nic, q_base, index, evq) \
697 + ((nic)->efhw_func->wakeup_request(nic, q_base, index, evq))
698 +
699 +#define efhw_nic_sw_event(nic, data, ev) \
700 + ((nic)->efhw_func->sw_event(nic, data, ev))
701 +
702 +/*-------------- Filter support ------------ */
703 +#define efhw_nic_ipfilter_set(nic, type, index, dmaq, \
704 + saddr, sport, daddr, dport) \
705 + ((nic)->efhw_func->ipfilter_set(nic, type, index, dmaq, \
706 + saddr, sport, daddr, dport))
707 +
708 +#define efhw_nic_ipfilter_clear(nic, index) \
709 + ((nic)->efhw_func->ipfilter_clear(nic, index))
710 +
711 +/*-------------- DMA support ------------ */
712 +#define efhw_nic_dmaq_tx_q_init(nic, dmaq, evq, owner, tag, \
713 + dmaq_size, index, flags) \
714 + ((nic)->efhw_func->dmaq_tx_q_init(nic, dmaq, evq, owner, tag, \
715 + dmaq_size, index, flags))
716 +
717 +#define efhw_nic_dmaq_rx_q_init(nic, dmaq, evq, owner, tag, \
718 + dmaq_size, index, flags) \
719 + ((nic)->efhw_func->dmaq_rx_q_init(nic, dmaq, evq, owner, tag, \
720 + dmaq_size, index, flags))
721 +
722 +#define efhw_nic_dmaq_tx_q_disable(nic, dmaq) \
723 + ((nic)->efhw_func->dmaq_tx_q_disable(nic, dmaq))
724 +
725 +#define efhw_nic_dmaq_rx_q_disable(nic, dmaq) \
726 + ((nic)->efhw_func->dmaq_rx_q_disable(nic, dmaq))
727 +
728 +#define efhw_nic_flush_tx_dma_channel(nic, dmaq) \
729 + ((nic)->efhw_func->flush_tx_dma_channel(nic, dmaq))
730 +
731 +#define efhw_nic_flush_rx_dma_channel(nic, dmaq) \
732 + ((nic)->efhw_func->flush_rx_dma_channel(nic, dmaq))
733 +
734 +/*-------------- MAC Low level interface ---- */
735 +#define efhw_gmac_get_mac_addr(nic) \
736 + ((nic)->gmac->get_mac_addr((nic)->gmac))
737 +
738 +/*-------------- Buffer table -------------- */
739 +#define efhw_nic_buffer_table_set(nic, addr, bufsz, region, \
740 + own_id, buf_id) \
741 + ((nic)->efhw_func->buffer_table_set(nic, addr, bufsz, region, \
742 + own_id, buf_id))
743 +
744 +#define efhw_nic_buffer_table_set_n(nic, buf_id, addr, bufsz, \
745 + region, n_pages, own_id) \
746 + ((nic)->efhw_func->buffer_table_set_n(nic, buf_id, addr, bufsz, \
747 + region, n_pages, own_id))
748 +
749 +#define efhw_nic_buffer_table_clear(nic, id, num) \
750 + ((nic)->efhw_func->buffer_table_clear(nic, id, num))
751 +
752 +#define efhw_nic_buffer_table_commit(nic) \
753 + ((nic)->efhw_func->buffer_table_commit(nic))
754 +
755 +/*-------------- New filter API ------------ */
756 +#define efhw_nic_filter_set(nic, spec, index_out) \
757 + ((nic)->efhw_func->filter_set(nic, spec, index_out))
758 +
759 +#define efhw_nic_filter_clear(nic, type, index_out) \
760 + ((nic)->efhw_func->filter_clear(nic, type, index_out))
761 +
762 +
763 +/* --- DMA --- */
764 +#define EFHW_DMA_ADDRMASK (0xffffffffffffffffULL)
765 +
766 +/* --- Buffers --- */
767 +#define EFHW_BUFFER_ADDR FALCON_BUFFER_4K_ADDR
768 +#define EFHW_BUFFER_PAGE FALCON_BUFFER_4K_PAGE
769 +#define EFHW_BUFFER_OFF FALCON_BUFFER_4K_OFF
770 +
771 +/* --- Filters --- */
772 +#define EFHW_IP_FILTER_NUM FALCON_FILTER_TBL_NUM
773 +
774 +#define EFHW_MAX_PAGE_SIZE FALCON_MAX_PAGE_SIZE
775 +
776 +#if PAGE_SIZE <= EFHW_MAX_PAGE_SIZE
777 +#define EFHW_NIC_PAGE_SIZE PAGE_SIZE
778 +#else
779 +#define EFHW_NIC_PAGE_SIZE EFHW_MAX_PAGE_SIZE
780 +#endif
781 +#define EFHW_NIC_PAGE_MASK (~(EFHW_NIC_PAGE_SIZE-1))
782 +
783 +#endif /* __CI_DRIVER_EFAB_HARDWARE_H__ */
784 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/common.h
785 ===================================================================
786 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
787 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/common.h 2008-07-17 16:18:07.000000000 +0200
788 @@ -0,0 +1,68 @@
789 +/****************************************************************************
790 + * Driver for Solarflare network controllers -
791 + * resource management for Xen backend, OpenOnload, etc
792 + * (including support for SFE4001 10GBT NIC)
793 + *
794 + * This file provides EtherFabric NIC hardware interface common
795 + * definitions.
796 + *
797 + * Copyright 2005-2007: Solarflare Communications Inc,
798 + * 9501 Jeronimo Road, Suite 250,
799 + * Irvine, CA 92618, USA
800 + *
801 + * Developed and maintained by Solarflare Communications:
802 + * <linux-xen-drivers@solarflare.com>
803 + * <onload-dev@solarflare.com>
804 + *
805 + *
806 + * This program is free software; you can redistribute it and/or modify it
807 + * under the terms of the GNU General Public License version 2 as published
808 + * by the Free Software Foundation, incorporated herein by reference.
809 + *
810 + * This program is distributed in the hope that it will be useful,
811 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
812 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
813 + * GNU General Public License for more details.
814 + *
815 + * You should have received a copy of the GNU General Public License
816 + * along with this program; if not, write to the Free Software
817 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
818 + ****************************************************************************
819 + */
820 +
821 +#ifndef __CI_DRIVER_EFAB_HARDWARE_COMMON_H__
822 +#define __CI_DRIVER_EFAB_HARDWARE_COMMON_H__
823 +
824 +/*----------------------------------------------------------------------------
825 + *
826 + * EtherFabric constants
827 + *
828 + *---------------------------------------------------------------------------*/
829 +
830 +#define EFHW_1K 0x00000400u
831 +#define EFHW_2K 0x00000800u
832 +#define EFHW_4K 0x00001000u
833 +#define EFHW_8K 0x00002000u
834 +#define EFHW_16K 0x00004000u
835 +#define EFHW_32K 0x00008000u
836 +#define EFHW_64K 0x00010000u
837 +#define EFHW_128K 0x00020000u
838 +#define EFHW_256K 0x00040000u
839 +#define EFHW_512K 0x00080000u
840 +#define EFHW_1M 0x00100000u
841 +#define EFHW_2M 0x00200000u
842 +#define EFHW_4M 0x00400000u
843 +#define EFHW_8M 0x00800000u
844 +#define EFHW_16M 0x01000000u
845 +#define EFHW_32M 0x02000000u
846 +#define EFHW_48M 0x03000000u
847 +#define EFHW_64M 0x04000000u
848 +#define EFHW_128M 0x08000000u
849 +#define EFHW_256M 0x10000000u
850 +#define EFHW_512M 0x20000000u
851 +#define EFHW_1G 0x40000000u
852 +#define EFHW_2G 0x80000000u
853 +#define EFHW_4G 0x100000000ULL
854 +#define EFHW_8G 0x200000000ULL
855 +
856 +#endif /* __CI_DRIVER_EFAB_HARDWARE_COMMON_H__ */
857 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon.h
858 ===================================================================
859 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
860 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon.h 2008-07-17 16:18:07.000000000 +0200
861 @@ -0,0 +1,422 @@
862 +/****************************************************************************
863 + * Driver for Solarflare network controllers -
864 + * resource management for Xen backend, OpenOnload, etc
865 + * (including support for SFE4001 10GBT NIC)
866 + *
867 + * This file provides EtherFabric NIC - EFXXXX (aka Falcon) specific
868 + * definitions.
869 + *
870 + * Copyright 2005-2007: Solarflare Communications Inc,
871 + * 9501 Jeronimo Road, Suite 250,
872 + * Irvine, CA 92618, USA
873 + *
874 + * Developed and maintained by Solarflare Communications:
875 + * <linux-xen-drivers@solarflare.com>
876 + * <onload-dev@solarflare.com>
877 + *
878 + *
879 + * This program is free software; you can redistribute it and/or modify it
880 + * under the terms of the GNU General Public License version 2 as published
881 + * by the Free Software Foundation, incorporated herein by reference.
882 + *
883 + * This program is distributed in the hope that it will be useful,
884 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
885 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
886 + * GNU General Public License for more details.
887 + *
888 + * You should have received a copy of the GNU General Public License
889 + * along with this program; if not, write to the Free Software
890 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
891 + ****************************************************************************
892 + */
893 +
894 +#ifndef __CI_DRIVER_EFAB_HARDWARE_FALCON_H__
895 +#define __CI_DRIVER_EFAB_HARDWARE_FALCON_H__
896 +
897 +/*----------------------------------------------------------------------------
898 + * Compile options
899 + *---------------------------------------------------------------------------*/
900 +
901 +/* Falcon has an 8K maximum page size. */
902 +#define FALCON_MAX_PAGE_SIZE EFHW_8K
903 +
904 +/* include the register definitions */
905 +#include <ci/driver/efab/hardware/falcon/falcon_core.h>
906 +#include <ci/driver/efab/hardware/falcon/falcon_desc.h>
907 +#include <ci/driver/efab/hardware/falcon/falcon_event.h>
908 +#include <ci/driver/efab/hardware/falcon/falcon_intr_vec.h>
909 +
910 +#define FALCON_DMA_TX_DESC_BYTES 8
911 +#define FALCON_DMA_RX_PHYS_DESC_BYTES 8
912 +#define FALCON_DMA_RX_BUF_DESC_BYTES 4
913 +
914 +
915 +/* ---- efhw_event_t helpers --- */
916 +
917 +#ifndef EFHW_IS_LITTLE_ENDIAN
918 +#error This needs lots of cpu_to_le64s() in
919 +#endif
920 +
921 +/*!\ TODO look at whether there is an efficiency gain to be had by
922 + treating the event codes to 32bit masks as is done for EF1
923 +
924 + These masks apply to the full 64 bits of the event to extract the
925 + event code - followed by the common event codes to expect
926 + */
927 +#define __FALCON_OPEN_MASK(WIDTH) ((((uint64_t)1) << (WIDTH)) - 1)
928 +#define FALCON_EVENT_CODE_MASK \
929 + (__FALCON_OPEN_MASK(EV_CODE_WIDTH) << EV_CODE_LBN)
930 +#define FALCON_EVENT_EV_Q_ID_MASK \
931 + (__FALCON_OPEN_MASK(DRIVER_EV_EVQ_ID_WIDTH) << DRIVER_EV_EVQ_ID_LBN)
932 +#define FALCON_EVENT_TX_FLUSH_Q_ID_MASK \
933 + (__FALCON_OPEN_MASK(DRIVER_EV_TX_DESCQ_ID_WIDTH) << \
934 + DRIVER_EV_TX_DESCQ_ID_LBN)
935 +#define FALCON_EVENT_RX_FLUSH_Q_ID_MASK \
936 + (__FALCON_OPEN_MASK(DRIVER_EV_RX_DESCQ_ID_WIDTH) << \
937 + DRIVER_EV_RX_DESCQ_ID_LBN)
938 +#define FALCON_EVENT_DRV_SUBCODE_MASK \
939 + (__FALCON_OPEN_MASK(DRIVER_EV_SUB_CODE_WIDTH) << \
940 + DRIVER_EV_SUB_CODE_LBN)
941 +
942 +#define FALCON_EVENT_FMT "[ev:%x:%08x:%08x]"
943 +#define FALCON_EVENT_PRI_ARG(e) \
944 + ((unsigned)(((e).u64 & FALCON_EVENT_CODE_MASK) >> EV_CODE_LBN)), \
945 + ((unsigned)((e).u64 >> 32)), ((unsigned)((e).u64 & 0xFFFFFFFF))
946 +
947 +#define FALCON_EVENT_CODE(evp) ((evp)->u64 & FALCON_EVENT_CODE_MASK)
948 +#define FALCON_EVENT_WAKE_EVQ_ID(evp) \
949 + (((evp)->u64 & FALCON_EVENT_EV_Q_ID_MASK) >> DRIVER_EV_EVQ_ID_LBN)
950 +#define FALCON_EVENT_TX_FLUSH_Q_ID(evp) \
951 + (((evp)->u64 & FALCON_EVENT_TX_FLUSH_Q_ID_MASK) >> \
952 + DRIVER_EV_TX_DESCQ_ID_LBN)
953 +#define FALCON_EVENT_RX_FLUSH_Q_ID(evp) \
954 + (((evp)->u64 & FALCON_EVENT_RX_FLUSH_Q_ID_MASK) >> \
955 + DRIVER_EV_RX_DESCQ_ID_LBN)
956 +#define FALCON_EVENT_DRIVER_SUBCODE(evp) \
957 + (((evp)->u64 & FALCON_EVENT_DRV_SUBCODE_MASK) >> \
958 + DRIVER_EV_SUB_CODE_LBN)
959 +
960 +#define FALCON_EVENT_CODE_CHAR ((uint64_t)DRIVER_EV_DECODE << EV_CODE_LBN)
961 +#define FALCON_EVENT_CODE_SW ((uint64_t)DRV_GEN_EV_DECODE << EV_CODE_LBN)
962 +
963 +
964 +/* so this is the size in bytes of an awful lot of things */
965 +#define FALCON_REGISTER128 (16)
966 +
967 +/* we define some unique dummy values as a debug aid */
968 +#ifdef _WIN32
969 +#define FALCON_ATOMIC_BASE 0xdeadbeef00000000ui64
970 +#else
971 +#define FALCON_ATOMIC_BASE 0xdeadbeef00000000ULL
972 +#endif
973 +#define FALCON_ATOMIC_UPD_REG (FALCON_ATOMIC_BASE | 0x1)
974 +#define FALCON_ATOMIC_PTR_TBL_REG (FALCON_ATOMIC_BASE | 0x2)
975 +#define FALCON_ATOMIC_SRPM_UDP_EVQ_REG (FALCON_ATOMIC_BASE | 0x3)
976 +#define FALCON_ATOMIC_RX_FLUSH_DESCQ (FALCON_ATOMIC_BASE | 0x4)
977 +#define FALCON_ATOMIC_TX_FLUSH_DESCQ (FALCON_ATOMIC_BASE | 0x5)
978 +#define FALCON_ATOMIC_INT_EN_REG (FALCON_ATOMIC_BASE | 0x6)
979 +#define FALCON_ATOMIC_TIMER_CMD_REG (FALCON_ATOMIC_BASE | 0x7)
980 +#define FALCON_ATOMIC_PACE_REG (FALCON_ATOMIC_BASE | 0x8)
981 +#define FALCON_ATOMIC_INT_ACK_REG (FALCON_ATOMIC_BASE | 0x9)
982 +/* XXX It crashed with odd value in FALCON_ATOMIC_INT_ADR_REG */
983 +#define FALCON_ATOMIC_INT_ADR_REG (FALCON_ATOMIC_BASE | 0xa)
984 +
985 +/*----------------------------------------------------------------------------
986 + *
987 + * PCI control blocks for Falcon -
988 + * (P) primary is for NET
989 + * (S) secondary is for CHAR
990 + *
991 + *---------------------------------------------------------------------------*/
992 +
993 +#define FALCON_P_CTR_AP_BAR 2
994 +#define FALCON_S_CTR_AP_BAR 0
995 +#define FALCON_S_DEVID 0x6703
996 +
997 +
998 +/*----------------------------------------------------------------------------
999 + *
1000 + * Falcon constants
1001 + *
1002 + *---------------------------------------------------------------------------*/
1003 +
1004 +/* Note: the following constants have moved to values in struct efhw_nic:
1005 + * FALCON_EVQ_TBL_NUM -> nic->num_evqs
1006 + * FALCON_DMAQ_NUM -> nic->num_dmaqs
1007 + * FALCON_TIMERS_NUM -> nic->num_times
1008 + * These replacement constants are used as sanity checks in assertions in
1009 + * certain functions that don't have access to struct efhw_nic.
1010 + */
1011 +#define FALCON_DMAQ_NUM_SANITY (EFHW_4K)
1012 +#define FALCON_EVQ_TBL_NUM_SANITY (EFHW_4K)
1013 +#define FALCON_TIMERS_NUM_SANITY (EFHW_4K)
1014 +
1015 +/* This value is an upper limit on the total number of filter table
1016 + * entries. The actual size of filter table is determined at runtime, as
1017 + * it can vary.
1018 + */
1019 +#define FALCON_FILTER_TBL_NUM (EFHW_8K)
1020 +
1021 +/* max number of buffers which can be pushed before commiting */
1022 +#define FALCON_BUFFER_UPD_MAX (128)
1023 +
1024 +/* We can tell falcon to write its RX buffers in 32 byte quantums,
1025 + and since we pad packets 2 bytes to the right we can't use
1026 + a full page (not unless we use jumbo mode for all queues)
1027 +
1028 + NOTE: tests/nic/dma.c assumes that the value here is the real NIC
1029 + value, so we explicitly round it down to the nearest 32 bytes */
1030 +
1031 +/* #define FALCON_RX_USR_BUF_SIZE round_down(4096-2,32) */
1032 +#define FALCON_RX_USR_BUF_SIZE 4064
1033 +
1034 +#define FALCON_EVQ_RPTR_REG_P0 0x400
1035 +
1036 +/*----------------------------------------------------------------------------
1037 + *
1038 + * Falcon requires user-space descriptor pushes to be:
1039 + * dword[0-2]; wiob(); dword[3]
1040 + *
1041 + * Driver register access must be locked against other threads from
1042 + * the same driver but can be in any order: i.e dword[0-3]; wiob()
1043 + *
1044 + * The following helpers ensure that valid dword orderings are exercised
1045 + *
1046 + *---------------------------------------------------------------------------*/
1047 +
1048 +/* A union to allow writting 64bit values as 32bit values, without
1049 + * hitting the compilers aliasing rules. We hope the compiler optimises
1050 + * away the copy's anyway */
1051 +union __u64to32 {
1052 + uint64_t u64;
1053 + struct {
1054 +#ifdef EFHW_IS_LITTLE_ENDIAN
1055 + uint32_t a;
1056 + uint32_t b;
1057 +#else
1058 + uint32_t b;
1059 + uint32_t a;
1060 +#endif
1061 + } s;
1062 +};
1063 +
1064 +static inline void
1065 +falcon_write_ddd_d(volatile char __iomem *kva,
1066 + uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3)
1067 +{
1068 + writel(d0, kva + 0);
1069 + writel(d1, kva + 4);
1070 + writel(d2, kva + 8);
1071 + mmiowb();
1072 + writel(d3, kva + 12);
1073 +}
1074 +
1075 +static inline void falcon_write_q(volatile char __iomem *kva, uint64_t q)
1076 +{
1077 + union __u64to32 u;
1078 + u.u64 = q;
1079 +
1080 + writel(u.s.a, kva);
1081 + mmiowb();
1082 + writel(u.s.b, kva + 4);
1083 +}
1084 +
1085 +static inline void falcon_read_q(volatile char __iomem *addr, uint64_t *q0)
1086 +{
1087 + /* It is essential that we read dword0 first, so that
1088 + * the shadow register is updated with the latest value
1089 + * and we get a self consistent value.
1090 + */
1091 + union __u64to32 u;
1092 + u.s.a = readl(addr);
1093 + rmb();
1094 + u.s.b = readl(addr + 4);
1095 +
1096 + *q0 = u.u64;
1097 +}
1098 +
1099 +static inline void
1100 +falcon_write_qq(volatile char __iomem *kva, uint64_t q0, uint64_t q1)
1101 +{
1102 + writeq(q0, kva + 0);
1103 + falcon_write_q(kva + 8, q1);
1104 +}
1105 +
1106 +static inline void
1107 +falcon_read_qq(volatile char __iomem *addr, uint64_t *q0, uint64_t *q1)
1108 +{
1109 + falcon_read_q(addr, q0);
1110 + *q1 = readq(addr + 8);
1111 +}
1112 +
1113 +
1114 +
1115 +/*----------------------------------------------------------------------------
1116 + *
1117 + * Buffer virtual addresses (4K buffers)
1118 + *
1119 + *---------------------------------------------------------------------------*/
1120 +
1121 +/* Form a buffer virtual address from buffer ID and offset. If the offset
1122 +** is larger than the buffer size, then the buffer indexed will be
1123 +** calculated appropriately. It is the responsibility of the caller to
1124 +** ensure that they have valid buffers programmed at that address.
1125 +*/
1126 +#define FALCON_VADDR_8K_S (13)
1127 +#define FALCON_VADDR_4K_S (12)
1128 +#define FALCON_VADDR_M 0xfffff /* post shift mask */
1129 +
1130 +#define FALCON_BUFFER_8K_ADDR(id, off) (((id) << FALCON_VADDR_8K_S) + (off))
1131 +#define FALCON_BUFFER_8K_PAGE(vaddr) \
1132 + (((vaddr) >> FALCON_VADDR_8K_S) & FALCON_VADDR_M)
1133 +#define FALCON_BUFFER_8K_OFF(vaddr) \
1134 + ((vaddr) & __FALCON_MASK32(FALCON_VADDR_8K_S))
1135 +
1136 +#define FALCON_BUFFER_4K_ADDR(id, off) (((id) << FALCON_VADDR_4K_S) + (off))
1137 +#define FALCON_BUFFER_4K_PAGE(vaddr) \
1138 + (((vaddr) >> FALCON_VADDR_4K_S) & FALCON_VADDR_M)
1139 +#define FALCON_BUFFER_4K_OFF(vaddr) \
1140 + ((vaddr) & __FALCON_MASK32(FALCON_VADDR_4K_S))
1141 +
1142 +/*----------------------------------------------------------------------------
1143 + *
1144 + * Timer helpers
1145 + *
1146 + *---------------------------------------------------------------------------*/
1147 +
1148 +static inline int falcon_timer_page_addr(uint idx)
1149 +{
1150 +
1151 + EFHW_ASSERT(TIMER_CMD_REG_KER_OFST ==
1152 + (TIMER_CMD_REG_PAGE4_OFST - 4 * EFHW_8K));
1153 +
1154 + EFHW_ASSERT(idx < FALCON_TIMERS_NUM_SANITY);
1155 +
1156 + if (idx < 4)
1157 + return TIMER_CMD_REG_KER_OFST + (idx * EFHW_8K);
1158 + else if (idx < 1024)
1159 + return TIMER_CMD_REG_PAGE4_OFST + ((idx - 4) * EFHW_8K);
1160 + else
1161 + return TIMER_CMD_REG_PAGE123K_OFST + ((idx - 1024) * EFHW_8K);
1162 +}
1163 +
1164 +#define FALCON_TIMER_PAGE_MASK (EFHW_8K-1)
1165 +
1166 +static inline int falcon_timer_page_offset(uint idx)
1167 +{
1168 + return falcon_timer_page_addr(idx) & FALCON_TIMER_PAGE_MASK;
1169 +}
1170 +
1171 +/*----------------------------------------------------------------------------
1172 + *
1173 + * DMA Queue helpers
1174 + *
1175 + *---------------------------------------------------------------------------*/
1176 +
1177 +/* iSCSI queue for A1; see bug 5427 for more details. */
1178 +#define FALCON_A1_ISCSI_DMAQ 4
1179 +
1180 +/*! returns an address within a bar of the TX DMA doorbell */
1181 +static inline uint falcon_tx_dma_page_addr(uint dmaq_idx)
1182 +{
1183 + uint page;
1184 +
1185 + EFHW_ASSERT((((TX_DESC_UPD_REG_PAGE123K_OFST) & (EFHW_8K - 1)) ==
1186 + (((TX_DESC_UPD_REG_PAGE4_OFST) & (EFHW_8K - 1)))));
1187 +
1188 + EFHW_ASSERT(dmaq_idx < FALCON_DMAQ_NUM_SANITY);
1189 +
1190 + if (dmaq_idx < 1024)
1191 + page = TX_DESC_UPD_REG_PAGE4_OFST + ((dmaq_idx - 4) * EFHW_8K);
1192 + else
1193 + page =
1194 + TX_DESC_UPD_REG_PAGE123K_OFST +
1195 + ((dmaq_idx - 1024) * EFHW_8K);
1196 +
1197 + return page;
1198 +}
1199 +
1200 +/*! returns an address within a bar of the RX DMA doorbell */
1201 +static inline uint falcon_rx_dma_page_addr(uint dmaq_idx)
1202 +{
1203 + uint page;
1204 +
1205 + EFHW_ASSERT((((RX_DESC_UPD_REG_PAGE123K_OFST) & (EFHW_8K - 1)) ==
1206 + ((RX_DESC_UPD_REG_PAGE4_OFST) & (EFHW_8K - 1))));
1207 +
1208 + EFHW_ASSERT(dmaq_idx < FALCON_DMAQ_NUM_SANITY);
1209 +
1210 + if (dmaq_idx < 1024)
1211 + page = RX_DESC_UPD_REG_PAGE4_OFST + ((dmaq_idx - 4) * EFHW_8K);
1212 + else
1213 + page =
1214 + RX_DESC_UPD_REG_PAGE123K_OFST +
1215 + ((dmaq_idx - 1024) * EFHW_8K);
1216 +
1217 + return page;
1218 +}
1219 +
1220 +/*! "page"=NIC-dependent register set size */
1221 +#define FALCON_DMA_PAGE_MASK (EFHW_8K-1)
1222 +
1223 +/*! returns an address within a bar of the start of the "page"
1224 + containing the TX DMA doorbell */
1225 +static inline int falcon_tx_dma_page_base(uint dma_idx)
1226 +{
1227 + return falcon_tx_dma_page_addr(dma_idx) & ~FALCON_DMA_PAGE_MASK;
1228 +}
1229 +
1230 +/*! returns an address within a bar of the start of the "page"
1231 + containing the RX DMA doorbell */
1232 +static inline int falcon_rx_dma_page_base(uint dma_idx)
1233 +{
1234 + return falcon_rx_dma_page_addr(dma_idx) & ~FALCON_DMA_PAGE_MASK;
1235 +}
1236 +
1237 +/*! returns an offset within a "page" of the TX DMA doorbell */
1238 +static inline int falcon_tx_dma_page_offset(uint dma_idx)
1239 +{
1240 + return falcon_tx_dma_page_addr(dma_idx) & FALCON_DMA_PAGE_MASK;
1241 +}
1242 +
1243 +/*! returns an offset within a "page" of the RX DMA doorbell */
1244 +static inline int falcon_rx_dma_page_offset(uint dma_idx)
1245 +{
1246 + return falcon_rx_dma_page_addr(dma_idx) & FALCON_DMA_PAGE_MASK;
1247 +}
1248 +
1249 +/*----------------------------------------------------------------------------
1250 + *
1251 + * Events
1252 + *
1253 + *---------------------------------------------------------------------------*/
1254 +
1255 +/* Falcon nails down the event queue mappings */
1256 +#define FALCON_EVQ_KERNEL0 (0) /* hardwired for net driver */
1257 +#define FALCON_EVQ_CHAR (4) /* char driver's event queue */
1258 +
1259 +/* reserved by the drivers */
1260 +#define FALCON_EVQ_TBL_RESERVED (8)
1261 +
1262 +/* default DMA-Q sizes */
1263 +#define FALCON_DMA_Q_DEFAULT_TX_SIZE 512
1264 +
1265 +#define FALCON_DMA_Q_DEFAULT_RX_SIZE 512
1266 +
1267 +#define FALCON_DMA_Q_DEFAULT_MMAP \
1268 + (FALCON_DMA_Q_DEFAULT_TX_SIZE * (FALCON_DMA_TX_DESC_BYTES * 2))
1269 +
1270 +/*----------------------------------------------------------------------------
1271 + *
1272 + * DEBUG - Analyser trigger
1273 + *
1274 + *---------------------------------------------------------------------------*/
1275 +
1276 +static inline void
1277 +falcon_deadbeef(volatile char __iomem *efhw_kva, unsigned what)
1278 +{
1279 + writel(what, efhw_kva + 0x300);
1280 + mmiowb();
1281 +}
1282 +#endif /* __CI_DRIVER_EFAB_HARDWARE_FALCON_H__ */
1283 +/*! \cidoxg_end */
1284 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_core.h
1285 ===================================================================
1286 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
1287 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_core.h 2008-07-17 16:18:07.000000000 +0200
1288 @@ -0,0 +1,1147 @@
1289 +/****************************************************************************
1290 + * Driver for Solarflare network controllers -
1291 + * resource management for Xen backend, OpenOnload, etc
1292 + * (including support for SFE4001 10GBT NIC)
1293 + *
1294 + * This file provides EtherFabric NIC - EFXXXX (aka Falcon) core register
1295 + * definitions.
1296 + *
1297 + * Copyright 2005-2007: Solarflare Communications Inc,
1298 + * 9501 Jeronimo Road, Suite 250,
1299 + * Irvine, CA 92618, USA
1300 + *
1301 + * Developed and maintained by Solarflare Communications:
1302 + * <linux-xen-drivers@solarflare.com>
1303 + * <onload-dev@solarflare.com>
1304 + *
1305 + *
1306 + * This program is free software; you can redistribute it and/or modify it
1307 + * under the terms of the GNU General Public License version 2 as published
1308 + * by the Free Software Foundation, incorporated herein by reference.
1309 + *
1310 + * This program is distributed in the hope that it will be useful,
1311 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1312 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1313 + * GNU General Public License for more details.
1314 + *
1315 + * You should have received a copy of the GNU General Public License
1316 + * along with this program; if not, write to the Free Software
1317 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1318 + ****************************************************************************
1319 + */
1320 +
1321 +#define FALCON_EXTENDED_P_BAR 1
1322 +
1323 +/*************---- Bus Interface Unit Registers C Header ----*************/
1324 +#define IOM_IND_ADR_REG_OFST 0x0 /* IO-mapped indirect access address
1325 + register */
1326 + #define IOM_AUTO_ADR_INC_EN_LBN 16
1327 + #define IOM_AUTO_ADR_INC_EN_WIDTH 1
1328 + #define IOM_IND_ADR_LBN 0
1329 + #define IOM_IND_ADR_WIDTH 16
1330 +#define IOM_IND_DAT_REG_OFST 0x4 /* IO-mapped indirect access data register */
1331 + #define IOM_IND_DAT_LBN 0
1332 + #define IOM_IND_DAT_WIDTH 32
1333 +#define ADR_REGION_REG_KER_OFST 0x0 /* Address region register */
1334 +#define ADR_REGION_REG_OFST 0x0 /* Address region register */
1335 + #define ADR_REGION3_LBN 96
1336 + #define ADR_REGION3_WIDTH 18
1337 + #define ADR_REGION2_LBN 64
1338 + #define ADR_REGION2_WIDTH 18
1339 + #define ADR_REGION1_LBN 32
1340 + #define ADR_REGION1_WIDTH 18
1341 + #define ADR_REGION0_LBN 0
1342 + #define ADR_REGION0_WIDTH 18
1343 +#define INT_EN_REG_KER_OFST 0x10 /* Kernel driver Interrupt enable register */
1344 + #define KER_INT_CHAR_LBN 4
1345 + #define KER_INT_CHAR_WIDTH 1
1346 + #define KER_INT_KER_LBN 3
1347 + #define KER_INT_KER_WIDTH 1
1348 + #define ILL_ADR_ERR_INT_EN_KER_LBN 2
1349 + #define ILL_ADR_ERR_INT_EN_KER_WIDTH 1
1350 + #define SRM_PERR_INT_EN_KER_LBN 1
1351 + #define SRM_PERR_INT_EN_KER_WIDTH 1
1352 + #define DRV_INT_EN_KER_LBN 0
1353 + #define DRV_INT_EN_KER_WIDTH 1
1354 +#define INT_EN_REG_CHAR_OFST 0x20 /* Char Driver interrupt enable register */
1355 + #define CHAR_INT_CHAR_LBN 4
1356 + #define CHAR_INT_CHAR_WIDTH 1
1357 + #define CHAR_INT_KER_LBN 3
1358 + #define CHAR_INT_KER_WIDTH 1
1359 + #define ILL_ADR_ERR_INT_EN_CHAR_LBN 2
1360 + #define ILL_ADR_ERR_INT_EN_CHAR_WIDTH 1
1361 + #define SRM_PERR_INT_EN_CHAR_LBN 1
1362 + #define SRM_PERR_INT_EN_CHAR_WIDTH 1
1363 + #define DRV_INT_EN_CHAR_LBN 0
1364 + #define DRV_INT_EN_CHAR_WIDTH 1
1365 +#define INT_ADR_REG_KER_OFST 0x30 /* Interrupt host address for Kernel driver */
1366 + #define INT_ADR_KER_LBN 0
1367 + #define INT_ADR_KER_WIDTH 64
1368 + #define DRV_INT_KER_LBN 32
1369 + #define DRV_INT_KER_WIDTH 1
1370 + #define EV_FF_HALF_INT_KER_LBN 3
1371 + #define EV_FF_HALF_INT_KER_WIDTH 1
1372 + #define EV_FF_FULL_INT_KER_LBN 2
1373 + #define EV_FF_FULL_INT_KER_WIDTH 1
1374 + #define ILL_ADR_ERR_INT_KER_LBN 1
1375 + #define ILL_ADR_ERR_INT_KER_WIDTH 1
1376 + #define SRAM_PERR_INT_KER_LBN 0
1377 + #define SRAM_PERR_INT_KER_WIDTH 1
1378 +#define INT_ADR_REG_CHAR_OFST 0x40 /* Interrupt host address for Char driver */
1379 + #define INT_ADR_CHAR_LBN 0
1380 + #define INT_ADR_CHAR_WIDTH 64
1381 + #define DRV_INT_CHAR_LBN 32
1382 + #define DRV_INT_CHAR_WIDTH 1
1383 + #define EV_FF_HALF_INT_CHAR_LBN 3
1384 + #define EV_FF_HALF_INT_CHAR_WIDTH 1
1385 + #define EV_FF_FULL_INT_CHAR_LBN 2
1386 + #define EV_FF_FULL_INT_CHAR_WIDTH 1
1387 + #define ILL_ADR_ERR_INT_CHAR_LBN 1
1388 + #define ILL_ADR_ERR_INT_CHAR_WIDTH 1
1389 + #define SRAM_PERR_INT_CHAR_LBN 0
1390 + #define SRAM_PERR_INT_CHAR_WIDTH 1
1391 +#define INT_ISR0_B0_OFST 0x90 /* B0 only */
1392 +#define INT_ISR1_B0_OFST 0xA0
1393 +#define INT_ACK_REG_KER_A1_OFST 0x50 /* Kernel interrupt acknowledge register */
1394 + #define RESERVED_LBN 0
1395 + #define RESERVED_WIDTH 32
1396 +#define INT_ACK_REG_CHAR_A1_OFST 0x60 /* CHAR interrupt acknowledge register */
1397 + #define RESERVED_LBN 0
1398 + #define RESERVED_WIDTH 32
1399 +/*************---- Global CSR Registers C Header ----*************/
1400 +#define NIC_STAT_REG_KER_OFST 0x200 /* ASIC strap status register */
1401 +#define NIC_STAT_REG_OFST 0x200 /* ASIC strap status register */
1402 + #define ONCHIP_SRAM_LBN 16
1403 + #define ONCHIP_SRAM_WIDTH 0
1404 + #define STRAP_PINS_LBN 0
1405 + #define STRAP_PINS_WIDTH 3
1406 +#define GPIO_CTL_REG_KER_OFST 0x210 /* GPIO control register */
1407 +#define GPIO_CTL_REG_OFST 0x210 /* GPIO control register */
1408 + #define GPIO_OEN_LBN 24
1409 + #define GPIO_OEN_WIDTH 4
1410 + #define GPIO_OUT_LBN 16
1411 + #define GPIO_OUT_WIDTH 4
1412 + #define GPIO_IN_LBN 8
1413 + #define GPIO_IN_WIDTH 4
1414 + #define GPIO_PWRUP_VALUE_LBN 0
1415 + #define GPIO_PWRUP_VALUE_WIDTH 4
1416 +#define GLB_CTL_REG_KER_OFST 0x220 /* Global control register */
1417 +#define GLB_CTL_REG_OFST 0x220 /* Global control register */
1418 + #define SWRST_LBN 0
1419 + #define SWRST_WIDTH 1
1420 +#define FATAL_INTR_REG_KER_OFST 0x230 /* Fatal interrupt register for Kernel */
1421 + #define PCI_BUSERR_INT_KER_EN_LBN 43
1422 + #define PCI_BUSERR_INT_KER_EN_WIDTH 1
1423 + #define SRAM_OOB_INT_KER_EN_LBN 42
1424 + #define SRAM_OOB_INT_KER_EN_WIDTH 1
1425 + #define BUFID_OOB_INT_KER_EN_LBN 41
1426 + #define BUFID_OOB_INT_KER_EN_WIDTH 1
1427 + #define MEM_PERR_INT_KER_EN_LBN 40
1428 + #define MEM_PERR_INT_KER_EN_WIDTH 1
1429 + #define RBUF_OWN_INT_KER_EN_LBN 39
1430 + #define RBUF_OWN_INT_KER_EN_WIDTH 1
1431 + #define TBUF_OWN_INT_KER_EN_LBN 38
1432 + #define TBUF_OWN_INT_KER_EN_WIDTH 1
1433 + #define RDESCQ_OWN_INT_KER_EN_LBN 37
1434 + #define RDESCQ_OWN_INT_KER_EN_WIDTH 1
1435 + #define TDESCQ_OWN_INT_KER_EN_LBN 36
1436 + #define TDESCQ_OWN_INT_KER_EN_WIDTH 1
1437 + #define EVQ_OWN_INT_KER_EN_LBN 35
1438 + #define EVQ_OWN_INT_KER_EN_WIDTH 1
1439 + #define EVFF_OFLO_INT_KER_EN_LBN 34
1440 + #define EVFF_OFLO_INT_KER_EN_WIDTH 1
1441 + #define ILL_ADR_INT_KER_EN_LBN 33
1442 + #define ILL_ADR_INT_KER_EN_WIDTH 1
1443 + #define SRM_PERR_INT_KER_EN_LBN 32
1444 + #define SRM_PERR_INT_KER_EN_WIDTH 1
1445 + #define PCI_BUSERR_INT_KER_LBN 11
1446 + #define PCI_BUSERR_INT_KER_WIDTH 1
1447 + #define SRAM_OOB_INT_KER_LBN 10
1448 + #define SRAM_OOB_INT_KER_WIDTH 1
1449 + #define BUFID_OOB_INT_KER_LBN 9
1450 + #define BUFID_OOB_INT_KER_WIDTH 1
1451 + #define MEM_PERR_INT_KER_LBN 8
1452 + #define MEM_PERR_INT_KER_WIDTH 1
1453 + #define RBUF_OWN_INT_KER_LBN 7
1454 + #define RBUF_OWN_INT_KER_WIDTH 1
1455 + #define TBUF_OWN_INT_KER_LBN 6
1456 + #define TBUF_OWN_INT_KER_WIDTH 1
1457 + #define RDESCQ_OWN_INT_KER_LBN 5
1458 + #define RDESCQ_OWN_INT_KER_WIDTH 1
1459 + #define TDESCQ_OWN_INT_KER_LBN 4
1460 + #define TDESCQ_OWN_INT_KER_WIDTH 1
1461 + #define EVQ_OWN_INT_KER_LBN 3
1462 + #define EVQ_OWN_INT_KER_WIDTH 1
1463 + #define EVFF_OFLO_INT_KER_LBN 2
1464 + #define EVFF_OFLO_INT_KER_WIDTH 1
1465 + #define ILL_ADR_INT_KER_LBN 1
1466 + #define ILL_ADR_INT_KER_WIDTH 1
1467 + #define SRM_PERR_INT_KER_LBN 0
1468 + #define SRM_PERR_INT_KER_WIDTH 1
1469 +#define FATAL_INTR_REG_OFST 0x240 /* Fatal interrupt register for Char */
1470 + #define PCI_BUSERR_INT_CHAR_EN_LBN 43
1471 + #define PCI_BUSERR_INT_CHAR_EN_WIDTH 1
1472 + #define SRAM_OOB_INT_CHAR_EN_LBN 42
1473 + #define SRAM_OOB_INT_CHAR_EN_WIDTH 1
1474 + #define BUFID_OOB_INT_CHAR_EN_LBN 41
1475 + #define BUFID_OOB_INT_CHAR_EN_WIDTH 1
1476 + #define MEM_PERR_INT_CHAR_EN_LBN 40
1477 + #define MEM_PERR_INT_CHAR_EN_WIDTH 1
1478 + #define RBUF_OWN_INT_CHAR_EN_LBN 39
1479 + #define RBUF_OWN_INT_CHAR_EN_WIDTH 1
1480 + #define TBUF_OWN_INT_CHAR_EN_LBN 38
1481 + #define TBUF_OWN_INT_CHAR_EN_WIDTH 1
1482 + #define RDESCQ_OWN_INT_CHAR_EN_LBN 37
1483 + #define RDESCQ_OWN_INT_CHAR_EN_WIDTH 1
1484 + #define TDESCQ_OWN_INT_CHAR_EN_LBN 36
1485 + #define TDESCQ_OWN_INT_CHAR_EN_WIDTH 1
1486 + #define EVQ_OWN_INT_CHAR_EN_LBN 35
1487 + #define EVQ_OWN_INT_CHAR_EN_WIDTH 1
1488 + #define EVFF_OFLO_INT_CHAR_EN_LBN 34
1489 + #define EVFF_OFLO_INT_CHAR_EN_WIDTH 1
1490 + #define ILL_ADR_INT_CHAR_EN_LBN 33
1491 + #define ILL_ADR_INT_CHAR_EN_WIDTH 1
1492 + #define SRM_PERR_INT_CHAR_EN_LBN 32
1493 + #define SRM_PERR_INT_CHAR_EN_WIDTH 1
1494 + #define FATAL_INTR_REG_EN_BITS 0xffffffffffffffffULL
1495 + #define PCI_BUSERR_INT_CHAR_LBN 11
1496 + #define PCI_BUSERR_INT_CHAR_WIDTH 1
1497 + #define SRAM_OOB_INT_CHAR_LBN 10
1498 + #define SRAM_OOB_INT_CHAR_WIDTH 1
1499 + #define BUFID_OOB_INT_CHAR_LBN 9
1500 + #define BUFID_OOB_INT_CHAR_WIDTH 1
1501 + #define MEM_PERR_INT_CHAR_LBN 8
1502 + #define MEM_PERR_INT_CHAR_WIDTH 1
1503 + #define RBUF_OWN_INT_CHAR_LBN 7
1504 + #define RBUF_OWN_INT_CHAR_WIDTH 1
1505 + #define TBUF_OWN_INT_CHAR_LBN 6
1506 + #define TBUF_OWN_INT_CHAR_WIDTH 1
1507 + #define RDESCQ_OWN_INT_CHAR_LBN 5
1508 + #define RDESCQ_OWN_INT_CHAR_WIDTH 1
1509 + #define TDESCQ_OWN_INT_CHAR_LBN 4
1510 + #define TDESCQ_OWN_INT_CHAR_WIDTH 1
1511 + #define EVQ_OWN_INT_CHAR_LBN 3
1512 + #define EVQ_OWN_INT_CHAR_WIDTH 1
1513 + #define EVFF_OFLO_INT_CHAR_LBN 2
1514 + #define EVFF_OFLO_INT_CHAR_WIDTH 1
1515 + #define ILL_ADR_INT_CHAR_LBN 1
1516 + #define ILL_ADR_INT_CHAR_WIDTH 1
1517 + #define SRM_PERR_INT_CHAR_LBN 0
1518 + #define SRM_PERR_INT_CHAR_WIDTH 1
1519 +#define DP_CTRL_REG_OFST 0x250 /* Datapath control register */
1520 + #define FLS_EVQ_ID_LBN 0
1521 + #define FLS_EVQ_ID_WIDTH 12
1522 +#define MEM_STAT_REG_KER_OFST 0x260 /* Memory status register */
1523 +#define MEM_STAT_REG_OFST 0x260 /* Memory status register */
1524 + #define MEM_PERR_VEC_LBN 53
1525 + #define MEM_PERR_VEC_WIDTH 38
1526 + #define MBIST_CORR_LBN 38
1527 + #define MBIST_CORR_WIDTH 15
1528 + #define MBIST_ERR_LBN 0
1529 + #define MBIST_ERR_WIDTH 38
1530 +#define DEBUG_REG_KER_OFST 0x270 /* Debug register */
1531 +#define DEBUG_REG_OFST 0x270 /* Debug register */
1532 + #define DEBUG_BLK_SEL2_LBN 47
1533 + #define DEBUG_BLK_SEL2_WIDTH 3
1534 + #define DEBUG_BLK_SEL1_LBN 44
1535 + #define DEBUG_BLK_SEL1_WIDTH 3
1536 + #define DEBUG_BLK_SEL0_LBN 41
1537 + #define DEBUG_BLK_SEL0_WIDTH 3
1538 + #define MISC_DEBUG_ADDR_LBN 36
1539 + #define MISC_DEBUG_ADDR_WIDTH 5
1540 + #define SERDES_DEBUG_ADDR_LBN 31
1541 + #define SERDES_DEBUG_ADDR_WIDTH 5
1542 + #define EM_DEBUG_ADDR_LBN 26
1543 + #define EM_DEBUG_ADDR_WIDTH 5
1544 + #define SR_DEBUG_ADDR_LBN 21
1545 + #define SR_DEBUG_ADDR_WIDTH 5
1546 + #define EV_DEBUG_ADDR_LBN 16
1547 + #define EV_DEBUG_ADDR_WIDTH 5
1548 + #define RX_DEBUG_ADDR_LBN 11
1549 + #define RX_DEBUG_ADDR_WIDTH 5
1550 + #define TX_DEBUG_ADDR_LBN 6
1551 + #define TX_DEBUG_ADDR_WIDTH 5
1552 + #define BIU_DEBUG_ADDR_LBN 1
1553 + #define BIU_DEBUG_ADDR_WIDTH 5
1554 + #define DEBUG_EN_LBN 0
1555 + #define DEBUG_EN_WIDTH 1
1556 +#define DRIVER_REG0_KER_OFST 0x280 /* Driver scratch register 0 */
1557 +#define DRIVER_REG0_OFST 0x280 /* Driver scratch register 0 */
1558 + #define DRIVER_DW0_LBN 0
1559 + #define DRIVER_DW0_WIDTH 32
1560 +#define DRIVER_REG1_KER_OFST 0x290 /* Driver scratch register 1 */
1561 +#define DRIVER_REG1_OFST 0x290 /* Driver scratch register 1 */
1562 + #define DRIVER_DW1_LBN 0
1563 + #define DRIVER_DW1_WIDTH 32
1564 +#define DRIVER_REG2_KER_OFST 0x2A0 /* Driver scratch register 2 */
1565 +#define DRIVER_REG2_OFST 0x2A0 /* Driver scratch register 2 */
1566 + #define DRIVER_DW2_LBN 0
1567 + #define DRIVER_DW2_WIDTH 32
1568 +#define DRIVER_REG3_KER_OFST 0x2B0 /* Driver scratch register 3 */
1569 +#define DRIVER_REG3_OFST 0x2B0 /* Driver scratch register 3 */
1570 + #define DRIVER_DW3_LBN 0
1571 + #define DRIVER_DW3_WIDTH 32
1572 +#define DRIVER_REG4_KER_OFST 0x2C0 /* Driver scratch register 4 */
1573 +#define DRIVER_REG4_OFST 0x2C0 /* Driver scratch register 4 */
1574 + #define DRIVER_DW4_LBN 0
1575 + #define DRIVER_DW4_WIDTH 32
1576 +#define DRIVER_REG5_KER_OFST 0x2D0 /* Driver scratch register 5 */
1577 +#define DRIVER_REG5_OFST 0x2D0 /* Driver scratch register 5 */
1578 + #define DRIVER_DW5_LBN 0
1579 + #define DRIVER_DW5_WIDTH 32
1580 +#define DRIVER_REG6_KER_OFST 0x2E0 /* Driver scratch register 6 */
1581 +#define DRIVER_REG6_OFST 0x2E0 /* Driver scratch register 6 */
1582 + #define DRIVER_DW6_LBN 0
1583 + #define DRIVER_DW6_WIDTH 32
1584 +#define DRIVER_REG7_KER_OFST 0x2F0 /* Driver scratch register 7 */
1585 +#define DRIVER_REG7_OFST 0x2F0 /* Driver scratch register 7 */
1586 + #define DRIVER_DW7_LBN 0
1587 + #define DRIVER_DW7_WIDTH 32
1588 +#define ALTERA_BUILD_REG_OFST 0x300 /* Altera build register */
1589 +#define ALTERA_BUILD_REG_OFST 0x300 /* Altera build register */
1590 + #define ALTERA_BUILD_VER_LBN 0
1591 + #define ALTERA_BUILD_VER_WIDTH 32
1592 +
1593 +/* so called CSR spare register
1594 + - contains separate parity enable bits for the various internal memory
1595 + blocks */
1596 +#define MEM_PARITY_ERR_EN_REG_KER 0x310
1597 +#define MEM_PARITY_ALL_BLOCKS_EN_LBN 64
1598 +#define MEM_PARITY_ALL_BLOCKS_EN_WIDTH 38
1599 +#define MEM_PARITY_TX_DATA_EN_LBN 72
1600 +#define MEM_PARITY_TX_DATA_EN_WIDTH 2
1601 +
1602 +/*************---- Event & Timer Module Registers C Header ----*************/
1603 +
1604 +#if FALCON_EXTENDED_P_BAR
1605 +#define EVQ_RPTR_REG_KER_OFST 0x11B00 /* Event queue read pointer register */
1606 +#else
1607 +#define EVQ_RPTR_REG_KER_OFST 0x1B00 /* Event queue read pointer register */
1608 +#endif
1609 +
1610 +#define EVQ_RPTR_REG_OFST 0xFA0000 /* Event queue read pointer register
1611 + array. */
1612 + #define EVQ_RPTR_LBN 0
1613 + #define EVQ_RPTR_WIDTH 15
1614 +
1615 +#if FALCON_EXTENDED_P_BAR
1616 +#define EVQ_PTR_TBL_KER_OFST 0x11A00 /* Event queue pointer table for kernel
1617 + access */
1618 +#else
1619 +#define EVQ_PTR_TBL_KER_OFST 0x1A00 /* Event queue pointer table for kernel
1620 + access */
1621 +#endif
1622 +
1623 +#define EVQ_PTR_TBL_CHAR_OFST 0xF60000 /* Event queue pointer table for char
1624 + direct access */
1625 + #define EVQ_WKUP_OR_INT_EN_LBN 39
1626 + #define EVQ_WKUP_OR_INT_EN_WIDTH 1
1627 + #define EVQ_NXT_WPTR_LBN 24
1628 + #define EVQ_NXT_WPTR_WIDTH 15
1629 + #define EVQ_EN_LBN 23
1630 + #define EVQ_EN_WIDTH 1
1631 + #define EVQ_SIZE_LBN 20
1632 + #define EVQ_SIZE_WIDTH 3
1633 + #define EVQ_BUF_BASE_ID_LBN 0
1634 + #define EVQ_BUF_BASE_ID_WIDTH 20
1635 +#define TIMER_CMD_REG_KER_OFST 0x420 /* Timer table for kernel access.
1636 + Page-mapped */
1637 +#define TIMER_CMD_REG_PAGE4_OFST 0x8420 /* Timer table for user-level access.
1638 + Page-mapped. For lowest 1K queues.
1639 + */
1640 +#define TIMER_CMD_REG_PAGE123K_OFST 0x1000420 /* Timer table for user-level
1641 + access. Page-mapped.
1642 + For upper 3K queues. */
1643 +#define TIMER_TBL_OFST 0xF70000 /* Timer table for char driver direct access */
1644 + #define TIMER_MODE_LBN 12
1645 + #define TIMER_MODE_WIDTH 2
1646 + #define TIMER_VAL_LBN 0
1647 + #define TIMER_VAL_WIDTH 12
1648 + #define TIMER_MODE_INT_HLDOFF 2
1649 + #define EVQ_BUF_SIZE_LBN 0
1650 + #define EVQ_BUF_SIZE_WIDTH 1
1651 +#define DRV_EV_REG_KER_OFST 0x440 /* Driver generated event register */
1652 +#define DRV_EV_REG_OFST 0x440 /* Driver generated event register */
1653 + #define DRV_EV_QID_LBN 64
1654 + #define DRV_EV_QID_WIDTH 12
1655 + #define DRV_EV_DATA_LBN 0
1656 + #define DRV_EV_DATA_WIDTH 64
1657 +#define EVQ_CTL_REG_KER_OFST 0x450 /* Event queue control register */
1658 +#define EVQ_CTL_REG_OFST 0x450 /* Event queue control register */
1659 + #define RX_EVQ_WAKEUP_MASK_B0_LBN 15
1660 + #define RX_EVQ_WAKEUP_MASK_B0_WIDTH 6
1661 + #define EVQ_OWNERR_CTL_LBN 14
1662 + #define EVQ_OWNERR_CTL_WIDTH 1
1663 + #define EVQ_FIFO_AF_TH_LBN 8
1664 + #define EVQ_FIFO_AF_TH_WIDTH 6
1665 + #define EVQ_FIFO_NOTAF_TH_LBN 0
1666 + #define EVQ_FIFO_NOTAF_TH_WIDTH 6
1667 +/*************---- SRAM Module Registers C Header ----*************/
1668 +#define BUF_TBL_CFG_REG_KER_OFST 0x600 /* Buffer table configuration register */
1669 +#define BUF_TBL_CFG_REG_OFST 0x600 /* Buffer table configuration register */
1670 + #define BUF_TBL_MODE_LBN 3
1671 + #define BUF_TBL_MODE_WIDTH 1
1672 +#define SRM_RX_DC_CFG_REG_KER_OFST 0x610 /* SRAM receive descriptor cache
1673 + configuration register */
1674 +#define SRM_RX_DC_CFG_REG_OFST 0x610 /* SRAM receive descriptor cache
1675 + configuration register */
1676 + #define SRM_RX_DC_BASE_ADR_LBN 0
1677 + #define SRM_RX_DC_BASE_ADR_WIDTH 21
1678 +#define SRM_TX_DC_CFG_REG_KER_OFST 0x620 /* SRAM transmit descriptor cache
1679 + configuration register */
1680 +#define SRM_TX_DC_CFG_REG_OFST 0x620 /* SRAM transmit descriptor cache
1681 + configuration register */
1682 + #define SRM_TX_DC_BASE_ADR_LBN 0
1683 + #define SRM_TX_DC_BASE_ADR_WIDTH 21
1684 +#define SRM_CFG_REG_KER_OFST 0x630 /* SRAM configuration register */
1685 +#define SRM_CFG_REG_OFST 0x630 /* SRAM configuration register */
1686 + #define SRAM_OOB_ADR_INTEN_LBN 5
1687 + #define SRAM_OOB_ADR_INTEN_WIDTH 1
1688 + #define SRAM_OOB_BUF_INTEN_LBN 4
1689 + #define SRAM_OOB_BUF_INTEN_WIDTH 1
1690 + #define SRAM_BT_INIT_EN_LBN 3
1691 + #define SRAM_BT_INIT_EN_WIDTH 1
1692 + #define SRM_NUM_BANK_LBN 2
1693 + #define SRM_NUM_BANK_WIDTH 1
1694 + #define SRM_BANK_SIZE_LBN 0
1695 + #define SRM_BANK_SIZE_WIDTH 2
1696 +#define BUF_TBL_UPD_REG_KER_OFST 0x650 /* Buffer table update register */
1697 +#define BUF_TBL_UPD_REG_OFST 0x650 /* Buffer table update register */
1698 + #define BUF_UPD_CMD_LBN 63
1699 + #define BUF_UPD_CMD_WIDTH 1
1700 + #define BUF_CLR_CMD_LBN 62
1701 + #define BUF_CLR_CMD_WIDTH 1
1702 + #define BUF_CLR_END_ID_LBN 32
1703 + #define BUF_CLR_END_ID_WIDTH 20
1704 + #define BUF_CLR_START_ID_LBN 0
1705 + #define BUF_CLR_START_ID_WIDTH 20
1706 +#define SRM_UPD_EVQ_REG_KER_OFST 0x660 /* Buffer table update register */
1707 +#define SRM_UPD_EVQ_REG_OFST 0x660 /* Buffer table update register */
1708 + #define SRM_UPD_EVQ_ID_LBN 0
1709 + #define SRM_UPD_EVQ_ID_WIDTH 12
1710 +#define SRAM_PARITY_REG_KER_OFST 0x670 /* SRAM parity register. */
1711 +#define SRAM_PARITY_REG_OFST 0x670 /* SRAM parity register. */
1712 + #define FORCE_SRAM_PERR_LBN 0
1713 + #define FORCE_SRAM_PERR_WIDTH 1
1714 +
1715 +#if FALCON_EXTENDED_P_BAR
1716 +#define BUF_HALF_TBL_KER_OFST 0x18000 /* Buffer table in half buffer table
1717 + mode direct access by kernel driver */
1718 +#else
1719 +#define BUF_HALF_TBL_KER_OFST 0x8000 /* Buffer table in half buffer table
1720 + mode direct access by kernel driver */
1721 +#endif
1722 +
1723 +
1724 +#define BUF_HALF_TBL_OFST 0x800000 /* Buffer table in half buffer table mode
1725 + direct access by char driver */
1726 + #define BUF_ADR_HBUF_ODD_LBN 44
1727 + #define BUF_ADR_HBUF_ODD_WIDTH 20
1728 + #define BUF_OWNER_ID_HBUF_ODD_LBN 32
1729 + #define BUF_OWNER_ID_HBUF_ODD_WIDTH 12
1730 + #define BUF_ADR_HBUF_EVEN_LBN 12
1731 + #define BUF_ADR_HBUF_EVEN_WIDTH 20
1732 + #define BUF_OWNER_ID_HBUF_EVEN_LBN 0
1733 + #define BUF_OWNER_ID_HBUF_EVEN_WIDTH 12
1734 +
1735 +
1736 +#if FALCON_EXTENDED_P_BAR
1737 +#define BUF_FULL_TBL_KER_OFST 0x18000 /* Buffer table in full buffer table
1738 + mode direct access by kernel driver */
1739 +#else
1740 +#define BUF_FULL_TBL_KER_OFST 0x8000 /* Buffer table in full buffer table mode
1741 + direct access by kernel driver */
1742 +#endif
1743 +
1744 +
1745 +
1746 +
1747 +#define BUF_FULL_TBL_OFST 0x800000 /* Buffer table in full buffer table mode
1748 + direct access by char driver */
1749 + #define IP_DAT_BUF_SIZE_LBN 50
1750 + #define IP_DAT_BUF_SIZE_WIDTH 1
1751 + #define BUF_ADR_REGION_LBN 48
1752 + #define BUF_ADR_REGION_WIDTH 2
1753 + #define BUF_ADR_FBUF_LBN 14
1754 + #define BUF_ADR_FBUF_WIDTH 34
1755 + #define BUF_OWNER_ID_FBUF_LBN 0
1756 + #define BUF_OWNER_ID_FBUF_WIDTH 14
1757 +#define SRM_DBG_REG_OFST 0x3000000 /* SRAM debug access */
1758 + #define SRM_DBG_LBN 0
1759 + #define SRM_DBG_WIDTH 64
1760 +/*************---- RX Datapath Registers C Header ----*************/
1761 +
1762 +#define RX_CFG_REG_KER_OFST 0x800 /* Receive configuration register */
1763 +#define RX_CFG_REG_OFST 0x800 /* Receive configuration register */
1764 +
1765 +#if !defined(FALCON_64K_RXFIFO) && !defined(FALCON_PRE_02020029)
1766 +# if !defined(FALCON_128K_RXFIFO)
1767 +# define FALCON_128K_RXFIFO
1768 +# endif
1769 +#endif
1770 +
1771 +#if defined(FALCON_128K_RXFIFO)
1772 +
1773 +/* new for B0 */
1774 + #define RX_TOEP_TCP_SUPPRESS_B0_LBN 48
1775 + #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1
1776 + #define RX_INGR_EN_B0_LBN 47
1777 + #define RX_INGR_EN_B0_WIDTH 1
1778 + #define RX_TOEP_IPV4_B0_LBN 46
1779 + #define RX_TOEP_IPV4_B0_WIDTH 1
1780 + #define RX_HASH_ALG_B0_LBN 45
1781 + #define RX_HASH_ALG_B0_WIDTH 1
1782 + #define RX_HASH_INSERT_HDR_B0_LBN 44
1783 + #define RX_HASH_INSERT_HDR_B0_WIDTH 1
1784 +/* moved for B0 */
1785 + #define RX_DESC_PUSH_EN_B0_LBN 43
1786 + #define RX_DESC_PUSH_EN_B0_WIDTH 1
1787 + #define RX_RDW_PATCH_EN_LBN 42 /* Non head of line blocking */
1788 + #define RX_RDW_PATCH_EN_WIDTH 1
1789 + #define RX_PCI_BURST_SIZE_B0_LBN 39
1790 + #define RX_PCI_BURST_SIZE_B0_WIDTH 3
1791 + #define RX_OWNERR_CTL_B0_LBN 38
1792 + #define RX_OWNERR_CTL_B0_WIDTH 1
1793 + #define RX_XON_TX_TH_B0_LBN 33
1794 + #define RX_XON_TX_TH_B0_WIDTH 5
1795 + #define RX_XOFF_TX_TH_B0_LBN 28
1796 + #define RX_XOFF_TX_TH_B0_WIDTH 5
1797 + #define RX_USR_BUF_SIZE_B0_LBN 19
1798 + #define RX_USR_BUF_SIZE_B0_WIDTH 9
1799 + #define RX_XON_MAC_TH_B0_LBN 10
1800 + #define RX_XON_MAC_TH_B0_WIDTH 9
1801 + #define RX_XOFF_MAC_TH_B0_LBN 1
1802 + #define RX_XOFF_MAC_TH_B0_WIDTH 9
1803 + #define RX_XOFF_MAC_EN_B0_LBN 0
1804 + #define RX_XOFF_MAC_EN_B0_WIDTH 1
1805 +
1806 +#elif !defined(FALCON_PRE_02020029)
1807 +/* new for B0 */
1808 + #define RX_TOEP_TCP_SUPPRESS_B0_LBN 46
1809 + #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1
1810 + #define RX_INGR_EN_B0_LBN 45
1811 + #define RX_INGR_EN_B0_WIDTH 1
1812 + #define RX_TOEP_IPV4_B0_LBN 44
1813 + #define RX_TOEP_IPV4_B0_WIDTH 1
1814 + #define RX_HASH_ALG_B0_LBN 43
1815 + #define RX_HASH_ALG_B0_WIDTH 41
1816 + #define RX_HASH_INSERT_HDR_B0_LBN 42
1817 + #define RX_HASH_INSERT_HDR_B0_WIDTH 1
1818 +/* moved for B0 */
1819 + #define RX_DESC_PUSH_EN_B0_LBN 41
1820 + #define RX_DESC_PUSH_EN_B0_WIDTH 1
1821 + #define RX_PCI_BURST_SIZE_B0_LBN 37
1822 + #define RX_PCI_BURST_SIZE_B0_WIDTH 3
1823 + #define RX_OWNERR_CTL_B0_LBN 36
1824 + #define RX_OWNERR_CTL_B0_WIDTH 1
1825 + #define RX_XON_TX_TH_B0_LBN 31
1826 + #define RX_XON_TX_TH_B0_WIDTH 5
1827 + #define RX_XOFF_TX_TH_B0_LBN 26
1828 + #define RX_XOFF_TX_TH_B0_WIDTH 5
1829 + #define RX_USR_BUF_SIZE_B0_LBN 17
1830 + #define RX_USR_BUF_SIZE_B0_WIDTH 9
1831 + #define RX_XON_MAC_TH_B0_LBN 9
1832 + #define RX_XON_MAC_TH_B0_WIDTH 8
1833 + #define RX_XOFF_MAC_TH_B0_LBN 1
1834 + #define RX_XOFF_MAC_TH_B0_WIDTH 8
1835 + #define RX_XOFF_MAC_EN_B0_LBN 0
1836 + #define RX_XOFF_MAC_EN_B0_WIDTH 1
1837 +
1838 +#else
1839 +/* new for B0 */
1840 + #define RX_TOEP_TCP_SUPPRESS_B0_LBN 44
1841 + #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1
1842 + #define RX_INGR_EN_B0_LBN 43
1843 + #define RX_INGR_EN_B0_WIDTH 1
1844 + #define RX_TOEP_IPV4_B0_LBN 42
1845 + #define RX_TOEP_IPV4_B0_WIDTH 1
1846 + #define RX_HASH_ALG_B0_LBN 41
1847 + #define RX_HASH_ALG_B0_WIDTH 41
1848 + #define RX_HASH_INSERT_HDR_B0_LBN 40
1849 + #define RX_HASH_INSERT_HDR_B0_WIDTH 1
1850 +/* moved for B0 */
1851 + #define RX_DESC_PUSH_EN_B0_LBN 35
1852 + #define RX_DESC_PUSH_EN_B0_WIDTH 1
1853 + #define RX_PCI_BURST_SIZE_B0_LBN 35
1854 + #define RX_PCI_BURST_SIZE_B0_WIDTH 2
1855 + #define RX_OWNERR_CTL_B0_LBN 34
1856 + #define RX_OWNERR_CTL_B0_WIDTH 1
1857 + #define RX_XON_TX_TH_B0_LBN 29
1858 + #define RX_XON_TX_TH_B0_WIDTH 5
1859 + #define RX_XOFF_TX_TH_B0_LBN 24
1860 + #define RX_XOFF_TX_TH_B0_WIDTH 5
1861 + #define RX_USR_BUF_SIZE_B0_LBN 15
1862 + #define RX_USR_BUF_SIZE_B0_WIDTH 9
1863 + #define RX_XON_MAC_TH_B0_LBN 8
1864 + #define RX_XON_MAC_TH_B0_WIDTH 7
1865 + #define RX_XOFF_MAC_TH_B0_LBN 1
1866 + #define RX_XOFF_MAC_TH_B0_WIDTH 7
1867 + #define RX_XOFF_MAC_EN_B0_LBN 0
1868 + #define RX_XOFF_MAC_EN_B0_WIDTH 1
1869 +
1870 +#endif
1871 +
1872 +/* A0/A1 */
1873 + #define RX_PUSH_EN_A1_LBN 35
1874 + #define RX_PUSH_EN_A1_WIDTH 1
1875 + #define RX_PCI_BURST_SIZE_A1_LBN 31
1876 + #define RX_PCI_BURST_SIZE_A1_WIDTH 3
1877 + #define RX_OWNERR_CTL_A1_LBN 30
1878 + #define RX_OWNERR_CTL_A1_WIDTH 1
1879 + #define RX_XON_TX_TH_A1_LBN 25
1880 + #define RX_XON_TX_TH_A1_WIDTH 5
1881 + #define RX_XOFF_TX_TH_A1_LBN 20
1882 + #define RX_XOFF_TX_TH_A1_WIDTH 5
1883 + #define RX_USR_BUF_SIZE_A1_LBN 11
1884 + #define RX_USR_BUF_SIZE_A1_WIDTH 9
1885 + #define RX_XON_MAC_TH_A1_LBN 6
1886 + #define RX_XON_MAC_TH_A1_WIDTH 5
1887 + #define RX_XOFF_MAC_TH_A1_LBN 1
1888 + #define RX_XOFF_MAC_TH_A1_WIDTH 5
1889 + #define RX_XOFF_MAC_EN_A1_LBN 0
1890 + #define RX_XOFF_MAC_EN_A1_WIDTH 1
1891 +
1892 +#define RX_FILTER_CTL_REG_OFST 0x810 /* Receive filter control registers */
1893 + #define SCATTER_ENBL_NO_MATCH_Q_B0_LBN 40
1894 + #define SCATTER_ENBL_NO_MATCH_Q_B0_WIDTH 1
1895 + #define UDP_FULL_SRCH_LIMIT_LBN 32
1896 + #define UDP_FULL_SRCH_LIMIT_WIDTH 8
1897 + #define NUM_KER_LBN 24
1898 + #define NUM_KER_WIDTH 2
1899 + #define UDP_WILD_SRCH_LIMIT_LBN 16
1900 + #define UDP_WILD_SRCH_LIMIT_WIDTH 8
1901 + #define TCP_WILD_SRCH_LIMIT_LBN 8
1902 + #define TCP_WILD_SRCH_LIMIT_WIDTH 8
1903 + #define TCP_FULL_SRCH_LIMIT_LBN 0
1904 + #define TCP_FULL_SRCH_LIMIT_WIDTH 8
1905 +#define RX_FLUSH_DESCQ_REG_KER_OFST 0x820 /* Receive flush descriptor queue
1906 + register */
1907 +#define RX_FLUSH_DESCQ_REG_OFST 0x820 /* Receive flush descriptor queue
1908 + register */
1909 + #define RX_FLUSH_DESCQ_CMD_LBN 24
1910 + #define RX_FLUSH_DESCQ_CMD_WIDTH 1
1911 + #define RX_FLUSH_EVQ_ID_LBN 12
1912 + #define RX_FLUSH_EVQ_ID_WIDTH 12
1913 + #define RX_FLUSH_DESCQ_LBN 0
1914 + #define RX_FLUSH_DESCQ_WIDTH 12
1915 +#define RX_DESC_UPD_REG_KER_OFST 0x830 /* Kernel receive descriptor update
1916 + register. Page-mapped */
1917 +#define RX_DESC_UPD_REG_PAGE4_OFST 0x8830 /* Char & user receive descriptor
1918 + update register. Page-mapped.
1919 + For lowest 1K queues. */
1920 +#define RX_DESC_UPD_REG_PAGE123K_OFST 0x1000830 /* Char & user receive
1921 + descriptor update register.
1922 + Page-mapped. For upper
1923 + 3K queues. */
1924 + #define RX_DESC_WPTR_LBN 96
1925 + #define RX_DESC_WPTR_WIDTH 12
1926 + #define RX_DESC_PUSH_CMD_LBN 95
1927 + #define RX_DESC_PUSH_CMD_WIDTH 1
1928 + #define RX_DESC_LBN 0
1929 + #define RX_DESC_WIDTH 64
1930 + #define RX_KER_DESC_LBN 0
1931 + #define RX_KER_DESC_WIDTH 64
1932 + #define RX_USR_DESC_LBN 0
1933 + #define RX_USR_DESC_WIDTH 32
1934 +#define RX_DC_CFG_REG_KER_OFST 0x840 /* Receive descriptor cache
1935 + configuration register */
1936 +#define RX_DC_CFG_REG_OFST 0x840 /* Receive descriptor cache
1937 + configuration register */
1938 + #define RX_DC_SIZE_LBN 0
1939 + #define RX_DC_SIZE_WIDTH 2
1940 +#define RX_DC_PF_WM_REG_KER_OFST 0x850 /* Receive descriptor cache pre-fetch
1941 + watermark register */
1942 +#define RX_DC_PF_WM_REG_OFST 0x850 /* Receive descriptor cache pre-fetch
1943 + watermark register */
1944 + #define RX_DC_PF_LWM_LO_LBN 0
1945 + #define RX_DC_PF_LWM_LO_WIDTH 6
1946 +
1947 +#define RX_RSS_TKEY_B0_OFST 0x860 /* RSS Toeplitz hash key (B0 only) */
1948 +
1949 +#define RX_NODESC_DROP_REG 0x880
1950 + #define RX_NODESC_DROP_CNT_LBN 0
1951 + #define RX_NODESC_DROP_CNT_WIDTH 16
1952 +
1953 +#define XM_TX_CFG_REG_OFST 0x1230
1954 + #define XM_AUTO_PAD_LBN 5
1955 + #define XM_AUTO_PAD_WIDTH 1
1956 +
1957 +#define RX_FILTER_TBL0_OFST 0xF00000 /* Receive filter table - even entries */
1958 + #define RSS_EN_0_B0_LBN 110
1959 + #define RSS_EN_0_B0_WIDTH 1
1960 + #define SCATTER_EN_0_B0_LBN 109
1961 + #define SCATTER_EN_0_B0_WIDTH 1
1962 + #define TCP_UDP_0_LBN 108
1963 + #define TCP_UDP_0_WIDTH 1
1964 + #define RXQ_ID_0_LBN 96
1965 + #define RXQ_ID_0_WIDTH 12
1966 + #define DEST_IP_0_LBN 64
1967 + #define DEST_IP_0_WIDTH 32
1968 + #define DEST_PORT_TCP_0_LBN 48
1969 + #define DEST_PORT_TCP_0_WIDTH 16
1970 + #define SRC_IP_0_LBN 16
1971 + #define SRC_IP_0_WIDTH 32
1972 + #define SRC_TCP_DEST_UDP_0_LBN 0
1973 + #define SRC_TCP_DEST_UDP_0_WIDTH 16
1974 +#define RX_FILTER_TBL1_OFST 0xF00010 /* Receive filter table - odd entries */
1975 + #define RSS_EN_1_B0_LBN 110
1976 + #define RSS_EN_1_B0_WIDTH 1
1977 + #define SCATTER_EN_1_B0_LBN 109
1978 + #define SCATTER_EN_1_B0_WIDTH 1
1979 + #define TCP_UDP_1_LBN 108
1980 + #define TCP_UDP_1_WIDTH 1
1981 + #define RXQ_ID_1_LBN 96
1982 + #define RXQ_ID_1_WIDTH 12
1983 + #define DEST_IP_1_LBN 64
1984 + #define DEST_IP_1_WIDTH 32
1985 + #define DEST_PORT_TCP_1_LBN 48
1986 + #define DEST_PORT_TCP_1_WIDTH 16
1987 + #define SRC_IP_1_LBN 16
1988 + #define SRC_IP_1_WIDTH 32
1989 + #define SRC_TCP_DEST_UDP_1_LBN 0
1990 + #define SRC_TCP_DEST_UDP_1_WIDTH 16
1991 +
1992 +#if FALCON_EXTENDED_P_BAR
1993 +#define RX_DESC_PTR_TBL_KER_OFST 0x11800 /* Receive descriptor pointer
1994 + kernel access */
1995 +#else
1996 +#define RX_DESC_PTR_TBL_KER_OFST 0x1800 /* Receive descriptor pointer
1997 + kernel access */
1998 +#endif
1999 +
2000 +
2001 +#define RX_DESC_PTR_TBL_OFST 0xF40000 /* Receive descriptor pointer table */
2002 + #define RX_ISCSI_DDIG_EN_LBN 88
2003 + #define RX_ISCSI_DDIG_EN_WIDTH 1
2004 + #define RX_ISCSI_HDIG_EN_LBN 87
2005 + #define RX_ISCSI_HDIG_EN_WIDTH 1
2006 + #define RX_DESC_PREF_ACT_LBN 86
2007 + #define RX_DESC_PREF_ACT_WIDTH 1
2008 + #define RX_DC_HW_RPTR_LBN 80
2009 + #define RX_DC_HW_RPTR_WIDTH 6
2010 + #define RX_DESCQ_HW_RPTR_LBN 68
2011 + #define RX_DESCQ_HW_RPTR_WIDTH 12
2012 + #define RX_DESCQ_SW_WPTR_LBN 56
2013 + #define RX_DESCQ_SW_WPTR_WIDTH 12
2014 + #define RX_DESCQ_BUF_BASE_ID_LBN 36
2015 + #define RX_DESCQ_BUF_BASE_ID_WIDTH 20
2016 + #define RX_DESCQ_EVQ_ID_LBN 24
2017 + #define RX_DESCQ_EVQ_ID_WIDTH 12
2018 + #define RX_DESCQ_OWNER_ID_LBN 10
2019 + #define RX_DESCQ_OWNER_ID_WIDTH 14
2020 + #define RX_DESCQ_LABEL_LBN 5
2021 + #define RX_DESCQ_LABEL_WIDTH 5
2022 + #define RX_DESCQ_SIZE_LBN 3
2023 + #define RX_DESCQ_SIZE_WIDTH 2
2024 + #define RX_DESCQ_TYPE_LBN 2
2025 + #define RX_DESCQ_TYPE_WIDTH 1
2026 + #define RX_DESCQ_JUMBO_LBN 1
2027 + #define RX_DESCQ_JUMBO_WIDTH 1
2028 + #define RX_DESCQ_EN_LBN 0
2029 + #define RX_DESCQ_EN_WIDTH 1
2030 +
2031 +
2032 +#define RX_RSS_INDIR_TBL_B0_OFST 0xFB0000 /* RSS indirection table (B0 only) */
2033 + #define RX_RSS_INDIR_ENT_B0_LBN 0
2034 + #define RX_RSS_INDIR_ENT_B0_WIDTH 6
2035 +
2036 +/*************---- TX Datapath Registers C Header ----*************/
2037 +#define TX_FLUSH_DESCQ_REG_KER_OFST 0xA00 /* Transmit flush descriptor
2038 + queue register */
2039 +#define TX_FLUSH_DESCQ_REG_OFST 0xA00 /* Transmit flush descriptor queue
2040 + register */
2041 + #define TX_FLUSH_DESCQ_CMD_LBN 12
2042 + #define TX_FLUSH_DESCQ_CMD_WIDTH 1
2043 + #define TX_FLUSH_DESCQ_LBN 0
2044 + #define TX_FLUSH_DESCQ_WIDTH 12
2045 +#define TX_DESC_UPD_REG_KER_OFST 0xA10 /* Kernel transmit descriptor update
2046 + register. Page-mapped */
2047 +#define TX_DESC_UPD_REG_PAGE4_OFST 0x8A10 /* Char & user transmit descriptor
2048 + update register. Page-mapped */
2049 +#define TX_DESC_UPD_REG_PAGE123K_OFST 0x1000A10 /* Char & user transmit
2050 + descriptor update register.
2051 + Page-mapped */
2052 + #define TX_DESC_WPTR_LBN 96
2053 + #define TX_DESC_WPTR_WIDTH 12
2054 + #define TX_DESC_PUSH_CMD_LBN 95
2055 + #define TX_DESC_PUSH_CMD_WIDTH 1
2056 + #define TX_DESC_LBN 0
2057 + #define TX_DESC_WIDTH 95
2058 + #define TX_KER_DESC_LBN 0
2059 + #define TX_KER_DESC_WIDTH 64
2060 + #define TX_USR_DESC_LBN 0
2061 + #define TX_USR_DESC_WIDTH 64
2062 +#define TX_DC_CFG_REG_KER_OFST 0xA20 /* Transmit descriptor cache
2063 + configuration register */
2064 +#define TX_DC_CFG_REG_OFST 0xA20 /* Transmit descriptor cache configuration
2065 + register */
2066 + #define TX_DC_SIZE_LBN 0
2067 + #define TX_DC_SIZE_WIDTH 2
2068 +
2069 +#if FALCON_EXTENDED_P_BAR
2070 +#define TX_DESC_PTR_TBL_KER_OFST 0x11900 /* Transmit descriptor pointer. */
2071 +#else
2072 +#define TX_DESC_PTR_TBL_KER_OFST 0x1900 /* Transmit descriptor pointer. */
2073 +#endif
2074 +
2075 +
2076 +#define TX_DESC_PTR_TBL_OFST 0xF50000 /* Transmit descriptor pointer */
2077 + #define TX_NON_IP_DROP_DIS_B0_LBN 91
2078 + #define TX_NON_IP_DROP_DIS_B0_WIDTH 1
2079 + #define TX_IP_CHKSM_DIS_B0_LBN 90
2080 + #define TX_IP_CHKSM_DIS_B0_WIDTH 1
2081 + #define TX_TCP_CHKSM_DIS_B0_LBN 89
2082 + #define TX_TCP_CHKSM_DIS_B0_WIDTH 1
2083 + #define TX_DESCQ_EN_LBN 88
2084 + #define TX_DESCQ_EN_WIDTH 1
2085 + #define TX_ISCSI_DDIG_EN_LBN 87
2086 + #define TX_ISCSI_DDIG_EN_WIDTH 1
2087 + #define TX_ISCSI_HDIG_EN_LBN 86
2088 + #define TX_ISCSI_HDIG_EN_WIDTH 1
2089 + #define TX_DC_HW_RPTR_LBN 80
2090 + #define TX_DC_HW_RPTR_WIDTH 6
2091 + #define TX_DESCQ_HW_RPTR_LBN 68
2092 + #define TX_DESCQ_HW_RPTR_WIDTH 12
2093 + #define TX_DESCQ_SW_WPTR_LBN 56
2094 + #define TX_DESCQ_SW_WPTR_WIDTH 12
2095 + #define TX_DESCQ_BUF_BASE_ID_LBN 36
2096 + #define TX_DESCQ_BUF_BASE_ID_WIDTH 20
2097 + #define TX_DESCQ_EVQ_ID_LBN 24
2098 + #define TX_DESCQ_EVQ_ID_WIDTH 12
2099 + #define TX_DESCQ_OWNER_ID_LBN 10
2100 + #define TX_DESCQ_OWNER_ID_WIDTH 14
2101 + #define TX_DESCQ_LABEL_LBN 5
2102 + #define TX_DESCQ_LABEL_WIDTH 5
2103 + #define TX_DESCQ_SIZE_LBN 3
2104 + #define TX_DESCQ_SIZE_WIDTH 2
2105 + #define TX_DESCQ_TYPE_LBN 1
2106 + #define TX_DESCQ_TYPE_WIDTH 2
2107 + #define TX_DESCQ_FLUSH_LBN 0
2108 + #define TX_DESCQ_FLUSH_WIDTH 1
2109 +#define TX_CFG_REG_KER_OFST 0xA50 /* Transmit configuration register */
2110 +#define TX_CFG_REG_OFST 0xA50 /* Transmit configuration register */
2111 + #define TX_IP_ID_P1_OFS_LBN 32
2112 + #define TX_IP_ID_P1_OFS_WIDTH 15
2113 + #define TX_IP_ID_P0_OFS_LBN 16
2114 + #define TX_IP_ID_P0_OFS_WIDTH 15
2115 + #define TX_TURBO_EN_LBN 3
2116 + #define TX_TURBO_EN_WIDTH 1
2117 + #define TX_OWNERR_CTL_LBN 2
2118 + #define TX_OWNERR_CTL_WIDTH 2
2119 + #define TX_NON_IP_DROP_DIS_LBN 1
2120 + #define TX_NON_IP_DROP_DIS_WIDTH 1
2121 + #define TX_IP_ID_REP_EN_LBN 0
2122 + #define TX_IP_ID_REP_EN_WIDTH 1
2123 +#define TX_RESERVED_REG_KER_OFST 0xA80 /* Transmit configuration register */
2124 +#define TX_RESERVED_REG_OFST 0xA80 /* Transmit configuration register */
2125 + #define TX_CSR_PUSH_EN_LBN 89
2126 + #define TX_CSR_PUSH_EN_WIDTH 1
2127 + #define TX_RX_SPACER_LBN 64
2128 + #define TX_RX_SPACER_WIDTH 8
2129 + #define TX_SW_EV_EN_LBN 59
2130 + #define TX_SW_EV_EN_WIDTH 1
2131 + #define TX_RX_SPACER_EN_LBN 57
2132 + #define TX_RX_SPACER_EN_WIDTH 1
2133 + #define TX_CSR_PREF_WD_TMR_LBN 24
2134 + #define TX_CSR_PREF_WD_TMR_WIDTH 16
2135 + #define TX_CSR_ONLY1TAG_LBN 21
2136 + #define TX_CSR_ONLY1TAG_WIDTH 1
2137 + #define TX_PREF_THRESHOLD_LBN 19
2138 + #define TX_PREF_THRESHOLD_WIDTH 2
2139 + #define TX_ONE_PKT_PER_Q_LBN 18
2140 + #define TX_ONE_PKT_PER_Q_WIDTH 1
2141 + #define TX_DIS_NON_IP_EV_LBN 17
2142 + #define TX_DIS_NON_IP_EV_WIDTH 1
2143 + #define TX_DMA_SPACER_LBN 8
2144 + #define TX_DMA_SPACER_WIDTH 8
2145 + #define TX_FLUSH_MIN_LEN_EN_B0_LBN 7
2146 + #define TX_FLUSH_MIN_LEN_EN_B0_WIDTH 1
2147 + #define TX_TCP_DIS_A1_LBN 7
2148 + #define TX_TCP_DIS_A1_WIDTH 1
2149 + #define TX_IP_DIS_A1_LBN 6
2150 + #define TX_IP_DIS_A1_WIDTH 1
2151 + #define TX_MAX_CPL_LBN 2
2152 + #define TX_MAX_CPL_WIDTH 2
2153 + #define TX_MAX_PREF_LBN 0
2154 + #define TX_MAX_PREF_WIDTH 2
2155 +#define TX_VLAN_REG_OFST 0xAE0 /* Transmit VLAN tag register */
2156 + #define TX_VLAN_EN_LBN 127
2157 + #define TX_VLAN_EN_WIDTH 1
2158 + #define TX_VLAN7_PORT1_EN_LBN 125
2159 + #define TX_VLAN7_PORT1_EN_WIDTH 1
2160 + #define TX_VLAN7_PORT0_EN_LBN 124
2161 + #define TX_VLAN7_PORT0_EN_WIDTH 1
2162 + #define TX_VLAN7_LBN 112
2163 + #define TX_VLAN7_WIDTH 12
2164 + #define TX_VLAN6_PORT1_EN_LBN 109
2165 + #define TX_VLAN6_PORT1_EN_WIDTH 1
2166 + #define TX_VLAN6_PORT0_EN_LBN 108
2167 + #define TX_VLAN6_PORT0_EN_WIDTH 1
2168 + #define TX_VLAN6_LBN 96
2169 + #define TX_VLAN6_WIDTH 12
2170 + #define TX_VLAN5_PORT1_EN_LBN 93
2171 + #define TX_VLAN5_PORT1_EN_WIDTH 1
2172 + #define TX_VLAN5_PORT0_EN_LBN 92
2173 + #define TX_VLAN5_PORT0_EN_WIDTH 1
2174 + #define TX_VLAN5_LBN 80
2175 + #define TX_VLAN5_WIDTH 12
2176 + #define TX_VLAN4_PORT1_EN_LBN 77
2177 + #define TX_VLAN4_PORT1_EN_WIDTH 1
2178 + #define TX_VLAN4_PORT0_EN_LBN 76
2179 + #define TX_VLAN4_PORT0_EN_WIDTH 1
2180 + #define TX_VLAN4_LBN 64
2181 + #define TX_VLAN4_WIDTH 12
2182 + #define TX_VLAN3_PORT1_EN_LBN 61
2183 + #define TX_VLAN3_PORT1_EN_WIDTH 1
2184 + #define TX_VLAN3_PORT0_EN_LBN 60
2185 + #define TX_VLAN3_PORT0_EN_WIDTH 1
2186 + #define TX_VLAN3_LBN 48
2187 + #define TX_VLAN3_WIDTH 12
2188 + #define TX_VLAN2_PORT1_EN_LBN 45
2189 + #define TX_VLAN2_PORT1_EN_WIDTH 1
2190 + #define TX_VLAN2_PORT0_EN_LBN 44
2191 + #define TX_VLAN2_PORT0_EN_WIDTH 1
2192 + #define TX_VLAN2_LBN 32
2193 + #define TX_VLAN2_WIDTH 12
2194 + #define TX_VLAN1_PORT1_EN_LBN 29
2195 + #define TX_VLAN1_PORT1_EN_WIDTH 1
2196 + #define TX_VLAN1_PORT0_EN_LBN 28
2197 + #define TX_VLAN1_PORT0_EN_WIDTH 1
2198 + #define TX_VLAN1_LBN 16
2199 + #define TX_VLAN1_WIDTH 12
2200 + #define TX_VLAN0_PORT1_EN_LBN 13
2201 + #define TX_VLAN0_PORT1_EN_WIDTH 1
2202 + #define TX_VLAN0_PORT0_EN_LBN 12
2203 + #define TX_VLAN0_PORT0_EN_WIDTH 1
2204 + #define TX_VLAN0_LBN 0
2205 + #define TX_VLAN0_WIDTH 12
2206 +#define TX_FIL_CTL_REG_OFST 0xAF0 /* Transmit filter control register */
2207 + #define TX_MADR1_FIL_EN_LBN 65
2208 + #define TX_MADR1_FIL_EN_WIDTH 1
2209 + #define TX_MADR0_FIL_EN_LBN 64
2210 + #define TX_MADR0_FIL_EN_WIDTH 1
2211 + #define TX_IPFIL31_PORT1_EN_LBN 63
2212 + #define TX_IPFIL31_PORT1_EN_WIDTH 1
2213 + #define TX_IPFIL31_PORT0_EN_LBN 62
2214 + #define TX_IPFIL31_PORT0_EN_WIDTH 1
2215 + #define TX_IPFIL30_PORT1_EN_LBN 61
2216 + #define TX_IPFIL30_PORT1_EN_WIDTH 1
2217 + #define TX_IPFIL30_PORT0_EN_LBN 60
2218 + #define TX_IPFIL30_PORT0_EN_WIDTH 1
2219 + #define TX_IPFIL29_PORT1_EN_LBN 59
2220 + #define TX_IPFIL29_PORT1_EN_WIDTH 1
2221 + #define TX_IPFIL29_PORT0_EN_LBN 58
2222 + #define TX_IPFIL29_PORT0_EN_WIDTH 1
2223 + #define TX_IPFIL28_PORT1_EN_LBN 57
2224 + #define TX_IPFIL28_PORT1_EN_WIDTH 1
2225 + #define TX_IPFIL28_PORT0_EN_LBN 56
2226 + #define TX_IPFIL28_PORT0_EN_WIDTH 1
2227 + #define TX_IPFIL27_PORT1_EN_LBN 55
2228 + #define TX_IPFIL27_PORT1_EN_WIDTH 1
2229 + #define TX_IPFIL27_PORT0_EN_LBN 54
2230 + #define TX_IPFIL27_PORT0_EN_WIDTH 1
2231 + #define TX_IPFIL26_PORT1_EN_LBN 53
2232 + #define TX_IPFIL26_PORT1_EN_WIDTH 1
2233 + #define TX_IPFIL26_PORT0_EN_LBN 52
2234 + #define TX_IPFIL26_PORT0_EN_WIDTH 1
2235 + #define TX_IPFIL25_PORT1_EN_LBN 51
2236 + #define TX_IPFIL25_PORT1_EN_WIDTH 1
2237 + #define TX_IPFIL25_PORT0_EN_LBN 50
2238 + #define TX_IPFIL25_PORT0_EN_WIDTH 1
2239 + #define TX_IPFIL24_PORT1_EN_LBN 49
2240 + #define TX_IPFIL24_PORT1_EN_WIDTH 1
2241 + #define TX_IPFIL24_PORT0_EN_LBN 48
2242 + #define TX_IPFIL24_PORT0_EN_WIDTH 1
2243 + #define TX_IPFIL23_PORT1_EN_LBN 47
2244 + #define TX_IPFIL23_PORT1_EN_WIDTH 1
2245 + #define TX_IPFIL23_PORT0_EN_LBN 46
2246 + #define TX_IPFIL23_PORT0_EN_WIDTH 1
2247 + #define TX_IPFIL22_PORT1_EN_LBN 45
2248 + #define TX_IPFIL22_PORT1_EN_WIDTH 1
2249 + #define TX_IPFIL22_PORT0_EN_LBN 44
2250 + #define TX_IPFIL22_PORT0_EN_WIDTH 1
2251 + #define TX_IPFIL21_PORT1_EN_LBN 43
2252 + #define TX_IPFIL21_PORT1_EN_WIDTH 1
2253 + #define TX_IPFIL21_PORT0_EN_LBN 42
2254 + #define TX_IPFIL21_PORT0_EN_WIDTH 1
2255 + #define TX_IPFIL20_PORT1_EN_LBN 41
2256 + #define TX_IPFIL20_PORT1_EN_WIDTH 1
2257 + #define TX_IPFIL20_PORT0_EN_LBN 40
2258 + #define TX_IPFIL20_PORT0_EN_WIDTH 1
2259 + #define TX_IPFIL19_PORT1_EN_LBN 39
2260 + #define TX_IPFIL19_PORT1_EN_WIDTH 1
2261 + #define TX_IPFIL19_PORT0_EN_LBN 38
2262 + #define TX_IPFIL19_PORT0_EN_WIDTH 1
2263 + #define TX_IPFIL18_PORT1_EN_LBN 37
2264 + #define TX_IPFIL18_PORT1_EN_WIDTH 1
2265 + #define TX_IPFIL18_PORT0_EN_LBN 36
2266 + #define TX_IPFIL18_PORT0_EN_WIDTH 1
2267 + #define TX_IPFIL17_PORT1_EN_LBN 35
2268 + #define TX_IPFIL17_PORT1_EN_WIDTH 1
2269 + #define TX_IPFIL17_PORT0_EN_LBN 34
2270 + #define TX_IPFIL17_PORT0_EN_WIDTH 1
2271 + #define TX_IPFIL16_PORT1_EN_LBN 33
2272 + #define TX_IPFIL16_PORT1_EN_WIDTH 1
2273 + #define TX_IPFIL16_PORT0_EN_LBN 32
2274 + #define TX_IPFIL16_PORT0_EN_WIDTH 1
2275 + #define TX_IPFIL15_PORT1_EN_LBN 31
2276 + #define TX_IPFIL15_PORT1_EN_WIDTH 1
2277 + #define TX_IPFIL15_PORT0_EN_LBN 30
2278 + #define TX_IPFIL15_PORT0_EN_WIDTH 1
2279 + #define TX_IPFIL14_PORT1_EN_LBN 29
2280 + #define TX_IPFIL14_PORT1_EN_WIDTH 1
2281 + #define TX_IPFIL14_PORT0_EN_LBN 28
2282 + #define TX_IPFIL14_PORT0_EN_WIDTH 1
2283 + #define TX_IPFIL13_PORT1_EN_LBN 27
2284 + #define TX_IPFIL13_PORT1_EN_WIDTH 1
2285 + #define TX_IPFIL13_PORT0_EN_LBN 26
2286 + #define TX_IPFIL13_PORT0_EN_WIDTH 1
2287 + #define TX_IPFIL12_PORT1_EN_LBN 25
2288 + #define TX_IPFIL12_PORT1_EN_WIDTH 1
2289 + #define TX_IPFIL12_PORT0_EN_LBN 24
2290 + #define TX_IPFIL12_PORT0_EN_WIDTH 1
2291 + #define TX_IPFIL11_PORT1_EN_LBN 23
2292 + #define TX_IPFIL11_PORT1_EN_WIDTH 1
2293 + #define TX_IPFIL11_PORT0_EN_LBN 22
2294 + #define TX_IPFIL11_PORT0_EN_WIDTH 1
2295 + #define TX_IPFIL10_PORT1_EN_LBN 21
2296 + #define TX_IPFIL10_PORT1_EN_WIDTH 1
2297 + #define TX_IPFIL10_PORT0_EN_LBN 20
2298 + #define TX_IPFIL10_PORT0_EN_WIDTH 1
2299 + #define TX_IPFIL9_PORT1_EN_LBN 19
2300 + #define TX_IPFIL9_PORT1_EN_WIDTH 1
2301 + #define TX_IPFIL9_PORT0_EN_LBN 18
2302 + #define TX_IPFIL9_PORT0_EN_WIDTH 1
2303 + #define TX_IPFIL8_PORT1_EN_LBN 17
2304 + #define TX_IPFIL8_PORT1_EN_WIDTH 1
2305 + #define TX_IPFIL8_PORT0_EN_LBN 16
2306 + #define TX_IPFIL8_PORT0_EN_WIDTH 1
2307 + #define TX_IPFIL7_PORT1_EN_LBN 15
2308 + #define TX_IPFIL7_PORT1_EN_WIDTH 1
2309 + #define TX_IPFIL7_PORT0_EN_LBN 14
2310 + #define TX_IPFIL7_PORT0_EN_WIDTH 1
2311 + #define TX_IPFIL6_PORT1_EN_LBN 13
2312 + #define TX_IPFIL6_PORT1_EN_WIDTH 1
2313 + #define TX_IPFIL6_PORT0_EN_LBN 12
2314 + #define TX_IPFIL6_PORT0_EN_WIDTH 1
2315 + #define TX_IPFIL5_PORT1_EN_LBN 11
2316 + #define TX_IPFIL5_PORT1_EN_WIDTH 1
2317 + #define TX_IPFIL5_PORT0_EN_LBN 10
2318 + #define TX_IPFIL5_PORT0_EN_WIDTH 1
2319 + #define TX_IPFIL4_PORT1_EN_LBN 9
2320 + #define TX_IPFIL4_PORT1_EN_WIDTH 1
2321 + #define TX_IPFIL4_PORT0_EN_LBN 8
2322 + #define TX_IPFIL4_PORT0_EN_WIDTH 1
2323 + #define TX_IPFIL3_PORT1_EN_LBN 7
2324 + #define TX_IPFIL3_PORT1_EN_WIDTH 1
2325 + #define TX_IPFIL3_PORT0_EN_LBN 6
2326 + #define TX_IPFIL3_PORT0_EN_WIDTH 1
2327 + #define TX_IPFIL2_PORT1_EN_LBN 5
2328 + #define TX_IPFIL2_PORT1_EN_WIDTH 1
2329 + #define TX_IPFIL2_PORT0_EN_LBN 4
2330 + #define TX_IPFIL2_PORT0_EN_WIDTH 1
2331 + #define TX_IPFIL1_PORT1_EN_LBN 3
2332 + #define TX_IPFIL1_PORT1_EN_WIDTH 1
2333 + #define TX_IPFIL1_PORT0_EN_LBN 2
2334 + #define TX_IPFIL1_PORT0_EN_WIDTH 1
2335 + #define TX_IPFIL0_PORT1_EN_LBN 1
2336 + #define TX_IPFIL0_PORT1_EN_WIDTH 1
2337 + #define TX_IPFIL0_PORT0_EN_LBN 0
2338 + #define TX_IPFIL0_PORT0_EN_WIDTH 1
2339 +#define TX_IPFIL_TBL_OFST 0xB00 /* Transmit IP source address filter table */
2340 + #define TX_IPFIL_MASK_LBN 32
2341 + #define TX_IPFIL_MASK_WIDTH 32
2342 + #define TX_IP_SRC_ADR_LBN 0
2343 + #define TX_IP_SRC_ADR_WIDTH 32
2344 +#define TX_PACE_REG_A1_OFST 0xF80000 /* Transmit pace control register */
2345 +#define TX_PACE_REG_B0_OFST 0xA90 /* Transmit pace control register */
2346 + #define TX_PACE_SB_NOTAF_LBN 19
2347 + #define TX_PACE_SB_NOTAF_WIDTH 10
2348 + #define TX_PACE_SB_AF_LBN 9
2349 + #define TX_PACE_SB_AF_WIDTH 10
2350 + #define TX_PACE_FB_BASE_LBN 5
2351 + #define TX_PACE_FB_BASE_WIDTH 4
2352 + #define TX_PACE_BIN_TH_LBN 0
2353 + #define TX_PACE_BIN_TH_WIDTH 5
2354 +#define TX_PACE_TBL_A1_OFST 0xF80040 /* Transmit pacing table */
2355 +#define TX_PACE_TBL_FIRST_QUEUE_A1 4
2356 +#define TX_PACE_TBL_B0_OFST 0xF80000 /* Transmit pacing table */
2357 +#define TX_PACE_TBL_FIRST_QUEUE_B0 0
2358 + #define TX_PACE_LBN 0
2359 + #define TX_PACE_WIDTH 5
2360 +
2361 +/*************---- EE/Flash Registers C Header ----*************/
2362 +#define EE_SPI_HCMD_REG_KER_OFST 0x100 /* SPI host command register */
2363 +#define EE_SPI_HCMD_REG_OFST 0x100 /* SPI host command register */
2364 + #define EE_SPI_HCMD_CMD_EN_LBN 31
2365 + #define EE_SPI_HCMD_CMD_EN_WIDTH 1
2366 + #define EE_WR_TIMER_ACTIVE_LBN 28
2367 + #define EE_WR_TIMER_ACTIVE_WIDTH 1
2368 + #define EE_SPI_HCMD_SF_SEL_LBN 24
2369 + #define EE_SPI_HCMD_SF_SEL_WIDTH 1
2370 + #define EE_SPI_HCMD_DABCNT_LBN 16
2371 + #define EE_SPI_HCMD_DABCNT_WIDTH 5
2372 + #define EE_SPI_HCMD_READ_LBN 15
2373 + #define EE_SPI_HCMD_READ_WIDTH 1
2374 + #define EE_SPI_HCMD_DUBCNT_LBN 12
2375 + #define EE_SPI_HCMD_DUBCNT_WIDTH 2
2376 + #define EE_SPI_HCMD_ADBCNT_LBN 8
2377 + #define EE_SPI_HCMD_ADBCNT_WIDTH 2
2378 + #define EE_SPI_HCMD_ENC_LBN 0
2379 + #define EE_SPI_HCMD_ENC_WIDTH 8
2380 +#define EE_SPI_HADR_REG_KER_OFST 0X110 /* SPI host address register */
2381 +#define EE_SPI_HADR_REG_OFST 0X110 /* SPI host address register */
2382 + #define EE_SPI_HADR_DUBYTE_LBN 24
2383 + #define EE_SPI_HADR_DUBYTE_WIDTH 8
2384 + #define EE_SPI_HADR_ADR_LBN 0
2385 + #define EE_SPI_HADR_ADR_WIDTH 24
2386 +#define EE_SPI_HDATA_REG_KER_OFST 0x120 /* SPI host data register */
2387 +#define EE_SPI_HDATA_REG_OFST 0x120 /* SPI host data register */
2388 + #define EE_SPI_HDATA3_LBN 96
2389 + #define EE_SPI_HDATA3_WIDTH 32
2390 + #define EE_SPI_HDATA2_LBN 64
2391 + #define EE_SPI_HDATA2_WIDTH 32
2392 + #define EE_SPI_HDATA1_LBN 32
2393 + #define EE_SPI_HDATA1_WIDTH 32
2394 + #define EE_SPI_HDATA0_LBN 0
2395 + #define EE_SPI_HDATA0_WIDTH 32
2396 +#define EE_BASE_PAGE_REG_KER_OFST 0x130 /* Expansion ROM base mirror register */
2397 +#define EE_BASE_PAGE_REG_OFST 0x130 /* Expansion ROM base mirror register */
2398 + #define EE_EXP_ROM_WINDOW_BASE_LBN 16
2399 + #define EE_EXP_ROM_WINDOW_BASE_WIDTH 13
2400 + #define EE_EXPROM_MASK_LBN 0
2401 + #define EE_EXPROM_MASK_WIDTH 13
2402 +#define EE_VPD_CFG0_REG_KER_OFST 0X140 /* SPI/VPD configuration register */
2403 +#define EE_VPD_CFG0_REG_OFST 0X140 /* SPI/VPD configuration register */
2404 + #define EE_SF_FASTRD_EN_LBN 127
2405 + #define EE_SF_FASTRD_EN_WIDTH 1
2406 + #define EE_SF_CLOCK_DIV_LBN 120
2407 + #define EE_SF_CLOCK_DIV_WIDTH 7
2408 + #define EE_VPD_WIP_POLL_LBN 119
2409 + #define EE_VPD_WIP_POLL_WIDTH 1
2410 + #define EE_VPDW_LENGTH_LBN 80
2411 + #define EE_VPDW_LENGTH_WIDTH 15
2412 + #define EE_VPDW_BASE_LBN 64
2413 + #define EE_VPDW_BASE_WIDTH 15
2414 + #define EE_VPD_WR_CMD_EN_LBN 56
2415 + #define EE_VPD_WR_CMD_EN_WIDTH 8
2416 + #define EE_VPD_BASE_LBN 32
2417 + #define EE_VPD_BASE_WIDTH 24
2418 + #define EE_VPD_LENGTH_LBN 16
2419 + #define EE_VPD_LENGTH_WIDTH 13
2420 + #define EE_VPD_AD_SIZE_LBN 8
2421 + #define EE_VPD_AD_SIZE_WIDTH 5
2422 + #define EE_VPD_ACCESS_ON_LBN 5
2423 + #define EE_VPD_ACCESS_ON_WIDTH 1
2424 +#define EE_VPD_SW_CNTL_REG_KER_OFST 0X150 /* VPD access SW control register */
2425 +#define EE_VPD_SW_CNTL_REG_OFST 0X150 /* VPD access SW control register */
2426 + #define EE_VPD_CYCLE_PENDING_LBN 31
2427 + #define EE_VPD_CYCLE_PENDING_WIDTH 1
2428 + #define EE_VPD_CYC_WRITE_LBN 28
2429 + #define EE_VPD_CYC_WRITE_WIDTH 1
2430 + #define EE_VPD_CYC_ADR_LBN 0
2431 + #define EE_VPD_CYC_ADR_WIDTH 15
2432 +#define EE_VPD_SW_DATA_REG_KER_OFST 0x160 /* VPD access SW data register */
2433 +#define EE_VPD_SW_DATA_REG_OFST 0x160 /* VPD access SW data register */
2434 + #define EE_VPD_CYC_DAT_LBN 0
2435 + #define EE_VPD_CYC_DAT_WIDTH 32
2436 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_desc.h
2437 ===================================================================
2438 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
2439 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_desc.h 2008-07-17 16:18:07.000000000 +0200
2440 @@ -0,0 +1,75 @@
2441 +/****************************************************************************
2442 + * Driver for Solarflare network controllers -
2443 + * resource management for Xen backend, OpenOnload, etc
2444 + * (including support for SFE4001 10GBT NIC)
2445 + *
2446 + * This file provides EtherFabric NIC - EFXXXX (aka Falcon) descriptor
2447 + * definitions.
2448 + *
2449 + * Copyright 2005-2007: Solarflare Communications Inc,
2450 + * 9501 Jeronimo Road, Suite 250,
2451 + * Irvine, CA 92618, USA
2452 + *
2453 + * Developed and maintained by Solarflare Communications:
2454 + * <linux-xen-drivers@solarflare.com>
2455 + * <onload-dev@solarflare.com>
2456 + *
2457 + *
2458 + * This program is free software; you can redistribute it and/or modify it
2459 + * under the terms of the GNU General Public License version 2 as published
2460 + * by the Free Software Foundation, incorporated herein by reference.
2461 + *
2462 + * This program is distributed in the hope that it will be useful,
2463 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2464 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2465 + * GNU General Public License for more details.
2466 + *
2467 + * You should have received a copy of the GNU General Public License
2468 + * along with this program; if not, write to the Free Software
2469 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2470 + ****************************************************************************
2471 + */
2472 +
2473 +/*************---- Descriptors C Headers ----*************/
2474 +/* Receive Kernel IP Descriptor */
2475 + #define RX_KER_BUF_SIZE_LBN 48
2476 + #define RX_KER_BUF_SIZE_WIDTH 14
2477 + #define RX_KER_BUF_REGION_LBN 46
2478 + #define RX_KER_BUF_REGION_WIDTH 2
2479 + #define RX_KER_BUF_REGION0_DECODE 0
2480 + #define RX_KER_BUF_REGION1_DECODE 1
2481 + #define RX_KER_BUF_REGION2_DECODE 2
2482 + #define RX_KER_BUF_REGION3_DECODE 3
2483 + #define RX_KER_BUF_ADR_LBN 0
2484 + #define RX_KER_BUF_ADR_WIDTH 46
2485 +/* Receive User IP Descriptor */
2486 + #define RX_USR_2BYTE_OFS_LBN 20
2487 + #define RX_USR_2BYTE_OFS_WIDTH 12
2488 + #define RX_USR_BUF_ID_LBN 0
2489 + #define RX_USR_BUF_ID_WIDTH 20
2490 +/* Transmit Kernel IP Descriptor */
2491 + #define TX_KER_PORT_LBN 63
2492 + #define TX_KER_PORT_WIDTH 1
2493 + #define TX_KER_CONT_LBN 62
2494 + #define TX_KER_CONT_WIDTH 1
2495 + #define TX_KER_BYTE_CNT_LBN 48
2496 + #define TX_KER_BYTE_CNT_WIDTH 14
2497 + #define TX_KER_BUF_REGION_LBN 46
2498 + #define TX_KER_BUF_REGION_WIDTH 2
2499 + #define TX_KER_BUF_REGION0_DECODE 0
2500 + #define TX_KER_BUF_REGION1_DECODE 1
2501 + #define TX_KER_BUF_REGION2_DECODE 2
2502 + #define TX_KER_BUF_REGION3_DECODE 3
2503 + #define TX_KER_BUF_ADR_LBN 0
2504 + #define TX_KER_BUF_ADR_WIDTH 46
2505 +/* Transmit User IP Descriptor */
2506 + #define TX_USR_PORT_LBN 47
2507 + #define TX_USR_PORT_WIDTH 1
2508 + #define TX_USR_CONT_LBN 46
2509 + #define TX_USR_CONT_WIDTH 1
2510 + #define TX_USR_BYTE_CNT_LBN 33
2511 + #define TX_USR_BYTE_CNT_WIDTH 13
2512 + #define TX_USR_BUF_ID_LBN 13
2513 + #define TX_USR_BUF_ID_WIDTH 20
2514 + #define TX_USR_BYTE_OFS_LBN 0
2515 + #define TX_USR_BYTE_OFS_WIDTH 13
2516 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_event.h
2517 ===================================================================
2518 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
2519 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_event.h 2008-07-17 16:18:07.000000000 +0200
2520 @@ -0,0 +1,155 @@
2521 +/****************************************************************************
2522 + * Driver for Solarflare network controllers -
2523 + * resource management for Xen backend, OpenOnload, etc
2524 + * (including support for SFE4001 10GBT NIC)
2525 + *
2526 + * This file provides EtherFabric NIC - EFXXXX (aka Falcon) event
2527 + * definitions.
2528 + *
2529 + * Copyright 2005-2007: Solarflare Communications Inc,
2530 + * 9501 Jeronimo Road, Suite 250,
2531 + * Irvine, CA 92618, USA
2532 + *
2533 + * Developed and maintained by Solarflare Communications:
2534 + * <linux-xen-drivers@solarflare.com>
2535 + * <onload-dev@solarflare.com>
2536 + *
2537 + *
2538 + * This program is free software; you can redistribute it and/or modify it
2539 + * under the terms of the GNU General Public License version 2 as published
2540 + * by the Free Software Foundation, incorporated herein by reference.
2541 + *
2542 + * This program is distributed in the hope that it will be useful,
2543 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2544 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2545 + * GNU General Public License for more details.
2546 + *
2547 + * You should have received a copy of the GNU General Public License
2548 + * along with this program; if not, write to the Free Software
2549 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2550 + ****************************************************************************
2551 + */
2552 +
2553 +/*************---- Events Format C Header ----*************/
2554 +/*************---- Event entry ----*************/
2555 + #define EV_CODE_LBN 60
2556 + #define EV_CODE_WIDTH 4
2557 + #define RX_IP_EV_DECODE 0
2558 + #define TX_IP_EV_DECODE 2
2559 + #define DRIVER_EV_DECODE 5
2560 + #define GLOBAL_EV_DECODE 6
2561 + #define DRV_GEN_EV_DECODE 7
2562 + #define EV_DATA_LBN 0
2563 + #define EV_DATA_WIDTH 60
2564 +/******---- Receive IP events for both Kernel & User event queues ----******/
2565 + #define RX_EV_PKT_OK_LBN 56
2566 + #define RX_EV_PKT_OK_WIDTH 1
2567 + #define RX_EV_BUF_OWNER_ID_ERR_LBN 54
2568 + #define RX_EV_BUF_OWNER_ID_ERR_WIDTH 1
2569 + #define RX_EV_IP_HDR_CHKSUM_ERR_LBN 52
2570 + #define RX_EV_IP_HDR_CHKSUM_ERR_WIDTH 1
2571 + #define RX_EV_TCP_UDP_CHKSUM_ERR_LBN 51
2572 + #define RX_EV_TCP_UDP_CHKSUM_ERR_WIDTH 1
2573 + #define RX_EV_ETH_CRC_ERR_LBN 50
2574 + #define RX_EV_ETH_CRC_ERR_WIDTH 1
2575 + #define RX_EV_FRM_TRUNC_LBN 49
2576 + #define RX_EV_FRM_TRUNC_WIDTH 1
2577 + #define RX_EV_DRIB_NIB_LBN 48
2578 + #define RX_EV_DRIB_NIB_WIDTH 1
2579 + #define RX_EV_TOBE_DISC_LBN 47
2580 + #define RX_EV_TOBE_DISC_WIDTH 1
2581 + #define RX_EV_PKT_TYPE_LBN 44
2582 + #define RX_EV_PKT_TYPE_WIDTH 3
2583 + #define RX_EV_PKT_TYPE_ETH_DECODE 0
2584 + #define RX_EV_PKT_TYPE_LLC_DECODE 1
2585 + #define RX_EV_PKT_TYPE_JUMBO_DECODE 2
2586 + #define RX_EV_PKT_TYPE_VLAN_DECODE 3
2587 + #define RX_EV_PKT_TYPE_VLAN_LLC_DECODE 4
2588 + #define RX_EV_PKT_TYPE_VLAN_JUMBO_DECODE 5
2589 + #define RX_EV_HDR_TYPE_LBN 42
2590 + #define RX_EV_HDR_TYPE_WIDTH 2
2591 + #define RX_EV_HDR_TYPE_TCP_IPV4_DECODE 0
2592 + #define RX_EV_HDR_TYPE_UDP_IPV4_DECODE 1
2593 + #define RX_EV_HDR_TYPE_OTHER_IP_DECODE 2
2594 + #define RX_EV_HDR_TYPE_NON_IP_DECODE 3
2595 + #define RX_EV_DESC_Q_EMPTY_LBN 41
2596 + #define RX_EV_DESC_Q_EMPTY_WIDTH 1
2597 + #define RX_EV_MCAST_HASH_MATCH_LBN 40
2598 + #define RX_EV_MCAST_HASH_MATCH_WIDTH 1
2599 + #define RX_EV_MCAST_PKT_LBN 39
2600 + #define RX_EV_MCAST_PKT_WIDTH 1
2601 + #define RX_EV_Q_LABEL_LBN 32
2602 + #define RX_EV_Q_LABEL_WIDTH 5
2603 + #define RX_JUMBO_CONT_LBN 31
2604 + #define RX_JUMBO_CONT_WIDTH 1
2605 + #define RX_SOP_LBN 15
2606 + #define RX_SOP_WIDTH 1
2607 + #define RX_PORT_LBN 30
2608 + #define RX_PORT_WIDTH 1
2609 + #define RX_EV_BYTE_CNT_LBN 16
2610 + #define RX_EV_BYTE_CNT_WIDTH 14
2611 + #define RX_iSCSI_PKT_OK_LBN 14
2612 + #define RX_iSCSI_PKT_OK_WIDTH 1
2613 + #define RX_ISCSI_DDIG_ERR_LBN 13
2614 + #define RX_ISCSI_DDIG_ERR_WIDTH 1
2615 + #define RX_ISCSI_HDIG_ERR_LBN 12
2616 + #define RX_ISCSI_HDIG_ERR_WIDTH 1
2617 + #define RX_EV_DESC_PTR_LBN 0
2618 + #define RX_EV_DESC_PTR_WIDTH 12
2619 +/******---- Transmit IP events for both Kernel & User event queues ----******/
2620 + #define TX_EV_PKT_ERR_LBN 38
2621 + #define TX_EV_PKT_ERR_WIDTH 1
2622 + #define TX_EV_PKT_TOO_BIG_LBN 37
2623 + #define TX_EV_PKT_TOO_BIG_WIDTH 1
2624 + #define TX_EV_Q_LABEL_LBN 32
2625 + #define TX_EV_Q_LABEL_WIDTH 5
2626 + #define TX_EV_PORT_LBN 16
2627 + #define TX_EV_PORT_WIDTH 1
2628 + #define TX_EV_WQ_FF_FULL_LBN 15
2629 + #define TX_EV_WQ_FF_FULL_WIDTH 1
2630 + #define TX_EV_BUF_OWNER_ID_ERR_LBN 14
2631 + #define TX_EV_BUF_OWNER_ID_ERR_WIDTH 1
2632 + #define TX_EV_COMP_LBN 12
2633 + #define TX_EV_COMP_WIDTH 1
2634 + #define TX_EV_DESC_PTR_LBN 0
2635 + #define TX_EV_DESC_PTR_WIDTH 12
2636 +/*************---- Char or Kernel driver events ----*************/
2637 + #define DRIVER_EV_SUB_CODE_LBN 56
2638 + #define DRIVER_EV_SUB_CODE_WIDTH 4
2639 + #define TX_DESCQ_FLS_DONE_EV_DECODE 0x0
2640 + #define RX_DESCQ_FLS_DONE_EV_DECODE 0x1
2641 + #define EVQ_INIT_DONE_EV_DECODE 0x2
2642 + #define EVQ_NOT_EN_EV_DECODE 0x3
2643 + #define RX_DESCQ_FLSFF_OVFL_EV_DECODE 0x4
2644 + #define SRM_UPD_DONE_EV_DECODE 0x5
2645 + #define WAKE_UP_EV_DECODE 0x6
2646 + #define TX_PKT_NON_TCP_UDP_DECODE 0x9
2647 + #define TIMER_EV_DECODE 0xA
2648 + #define RX_DSC_ERROR_EV_DECODE 0xE
2649 + #define DRIVER_EV_TX_DESCQ_ID_LBN 0
2650 + #define DRIVER_EV_TX_DESCQ_ID_WIDTH 12
2651 + #define DRIVER_EV_RX_DESCQ_ID_LBN 0
2652 + #define DRIVER_EV_RX_DESCQ_ID_WIDTH 12
2653 + #define DRIVER_EV_EVQ_ID_LBN 0
2654 + #define DRIVER_EV_EVQ_ID_WIDTH 12
2655 + #define DRIVER_TMR_ID_LBN 0
2656 + #define DRIVER_TMR_ID_WIDTH 12
2657 + #define DRIVER_EV_SRM_UPD_LBN 0
2658 + #define DRIVER_EV_SRM_UPD_WIDTH 2
2659 + #define SRM_CLR_EV_DECODE 0
2660 + #define SRM_UPD_EV_DECODE 1
2661 + #define SRM_ILLCLR_EV_DECODE 2
2662 +/********---- Global events. Sent to both event queue 0 and 4. ----********/
2663 + #define XFP_PHY_INTR_LBN 10
2664 + #define XFP_PHY_INTR_WIDTH 1
2665 + #define XG_PHY_INTR_LBN 9
2666 + #define XG_PHY_INTR_WIDTH 1
2667 + #define G_PHY1_INTR_LBN 8
2668 + #define G_PHY1_INTR_WIDTH 1
2669 + #define G_PHY0_INTR_LBN 7
2670 + #define G_PHY0_INTR_WIDTH 1
2671 +/*************---- Driver generated events ----*************/
2672 + #define DRV_GEN_EV_CODE_LBN 60
2673 + #define DRV_GEN_EV_CODE_WIDTH 4
2674 + #define DRV_GEN_EV_DATA_LBN 0
2675 + #define DRV_GEN_EV_DATA_WIDTH 60
2676 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_intr_vec.h
2677 ===================================================================
2678 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
2679 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_intr_vec.h 2008-07-17 16:18:07.000000000 +0200
2680 @@ -0,0 +1,44 @@
2681 +/****************************************************************************
2682 + * Driver for Solarflare network controllers -
2683 + * resource management for Xen backend, OpenOnload, etc
2684 + * (including support for SFE4001 10GBT NIC)
2685 + *
2686 + * This file provides EtherFabric NIC - EFXXXX (aka Falcon) interrupt
2687 + * vector definitions.
2688 + *
2689 + * Copyright 2005-2007: Solarflare Communications Inc,
2690 + * 9501 Jeronimo Road, Suite 250,
2691 + * Irvine, CA 92618, USA
2692 + *
2693 + * Developed and maintained by Solarflare Communications:
2694 + * <linux-xen-drivers@solarflare.com>
2695 + * <onload-dev@solarflare.com>
2696 + *
2697 + *
2698 + * This program is free software; you can redistribute it and/or modify it
2699 + * under the terms of the GNU General Public License version 2 as published
2700 + * by the Free Software Foundation, incorporated herein by reference.
2701 + *
2702 + * This program is distributed in the hope that it will be useful,
2703 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2704 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2705 + * GNU General Public License for more details.
2706 + *
2707 + * You should have received a copy of the GNU General Public License
2708 + * along with this program; if not, write to the Free Software
2709 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2710 + ****************************************************************************
2711 + */
2712 +
2713 +/*************---- Interrupt Vector Format C Header ----*************/
2714 +#define DW0_OFST 0x0 /* Double-word 0: Event queue FIFO interrupts */
2715 + #define EVQ_FIFO_HF_LBN 1
2716 + #define EVQ_FIFO_HF_WIDTH 1
2717 + #define EVQ_FIFO_AF_LBN 0
2718 + #define EVQ_FIFO_AF_WIDTH 1
2719 +#define DW1_OFST 0x4 /* Double-word 1: Interrupt indicator */
2720 + #define INT_FLAG_LBN 0
2721 + #define INT_FLAG_WIDTH 1
2722 +#define DW2_OFST 0x8 /* Double-word 2: Fatal interrupts */
2723 + #define FATAL_INT_LBN 0
2724 + #define FATAL_INT_WIDTH 1
2725 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/workarounds.h
2726 ===================================================================
2727 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
2728 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/workarounds.h 2008-07-17 16:18:07.000000000 +0200
2729 @@ -0,0 +1,67 @@
2730 +/****************************************************************************
2731 + * Driver for Solarflare network controllers -
2732 + * resource management for Xen backend, OpenOnload, etc
2733 + * (including support for SFE4001 10GBT NIC)
2734 + *
2735 + * This file provides workaround settings for EtherFabric NICs.
2736 + *
2737 + * Copyright 2005-2007: Solarflare Communications Inc,
2738 + * 9501 Jeronimo Road, Suite 250,
2739 + * Irvine, CA 92618, USA
2740 + *
2741 + * Developed and maintained by Solarflare Communications:
2742 + * <linux-xen-drivers@solarflare.com>
2743 + * <onload-dev@solarflare.com>
2744 + *
2745 + *
2746 + * This program is free software; you can redistribute it and/or modify it
2747 + * under the terms of the GNU General Public License version 2 as published
2748 + * by the Free Software Foundation, incorporated herein by reference.
2749 + *
2750 + * This program is distributed in the hope that it will be useful,
2751 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2752 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2753 + * GNU General Public License for more details.
2754 + *
2755 + * You should have received a copy of the GNU General Public License
2756 + * along with this program; if not, write to the Free Software
2757 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2758 + ****************************************************************************
2759 + */
2760 +
2761 +#ifndef __CI_DRIVER_EFAB_WORKAROUNDS_H__
2762 +#define __CI_DRIVER_EFAB_WORKAROUNDS_H__
2763 +
2764 +/*----------------------------------------------------------------------------
2765 + *
2766 + * Hardware workarounds which have global scope
2767 + *
2768 + *---------------------------------------------------------------------------*/
2769 +
2770 +#if defined(__CI_HARDWARE_CONFIG_FALCON_B0__)
2771 +/*------------------------------- B0 ---------------------------------------*/
2772 +
2773 +#define BUG2175_WORKAROUND 0 /* TX event batching for dual port operation.
2774 + This removes the effect (dup TX events)
2775 + of the fix
2776 + (TX event per packet + batch events) */
2777 +#define BUG5302_WORKAROUND 0 /* unstick TX DMAQ after out-of-range wr ptr */
2778 +#define BUG5762_WORKAROUND 0 /* Set all queues to jumbo mode */
2779 +#define BUG5391_WORKAROUND 0 /* Misaligned TX can't span 512-byte boundary */
2780 +#define BUG7916_WORKAROUND 0 /* RX flush gets lost */
2781 +
2782 +#else
2783 +/*------------------------------- A0/A1 ------------------------------------*/
2784 +
2785 +#define BUG2175_WORKAROUND 1 /* TX event batching for dual port operation.
2786 + This removes the effect (dup TX events)
2787 + of the fix
2788 + (TX event per packet + batch events) */
2789 +#define BUG5302_WORKAROUND 1 /* unstick TX DMAQ after out-of-range wr ptr */
2790 +#define BUG5762_WORKAROUND 1 /* Set all queues to jumbo mode */
2791 +#define BUG5391_WORKAROUND 1 /* Misaligned TX can't span 512-byte boundary */
2792 +#define BUG7916_WORKAROUND 1 /* RX flush gets lost */
2793 +
2794 +#endif /* B0/A01 */
2795 +
2796 +#endif /* __CI_DRIVER_EFAB_WORKAROUNDS_H__ */
2797 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/resource/efx_vi.h
2798 ===================================================================
2799 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
2800 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/resource/efx_vi.h 2008-07-17 16:18:07.000000000 +0200
2801 @@ -0,0 +1,273 @@
2802 +/****************************************************************************
2803 + * Driver for Solarflare network controllers -
2804 + * resource management for Xen backend, OpenOnload, etc
2805 + * (including support for SFE4001 10GBT NIC)
2806 + *
2807 + * This file contains public EFX VI API to Solarflare resource manager.
2808 + *
2809 + * Copyright 2005-2007: Solarflare Communications Inc,
2810 + * 9501 Jeronimo Road, Suite 250,
2811 + * Irvine, CA 92618, USA
2812 + *
2813 + * Developed and maintained by Solarflare Communications:
2814 + * <linux-xen-drivers@solarflare.com>
2815 + * <onload-dev@solarflare.com>
2816 + *
2817 + *
2818 + * This program is free software; you can redistribute it and/or modify it
2819 + * under the terms of the GNU General Public License version 2 as published
2820 + * by the Free Software Foundation, incorporated herein by reference.
2821 + *
2822 + * This program is distributed in the hope that it will be useful,
2823 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2824 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2825 + * GNU General Public License for more details.
2826 + *
2827 + * You should have received a copy of the GNU General Public License
2828 + * along with this program; if not, write to the Free Software
2829 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2830 + ****************************************************************************
2831 + */
2832 +
2833 +#ifndef __CI_DRIVER_RESOURCE_EFX_VI_H__
2834 +#define __CI_DRIVER_RESOURCE_EFX_VI_H__
2835 +
2836 +/* Default size of event queue in the efx_vi resource. Copied from
2837 + * CI_CFG_NETIF_EVENTQ_SIZE */
2838 +#define EFX_VI_EVENTQ_SIZE_DEFAULT 1024
2839 +
2840 +extern int efx_vi_eventq_size;
2841 +
2842 +/**************************************************************************
2843 + * efx_vi_state types, allocation and free
2844 + **************************************************************************/
2845 +
2846 +/*! Handle for refering to a efx_vi */
2847 +struct efx_vi_state;
2848 +
2849 +/*!
2850 + * Allocate an efx_vi, including event queue and pt_endpoint
2851 + *
2852 + * \param vih_out Pointer to a handle that is set on success
2853 + * \param ifindex Index of the network interface desired
2854 + * \return Zero on success (and vih_out set), non-zero on failure.
2855 + */
2856 +extern int
2857 +efx_vi_alloc(struct efx_vi_state **vih_out, int ifindex);
2858 +
2859 +/*!
2860 + * Free a previously allocated efx_vi
2861 + *
2862 + * \param vih The handle of the efx_vi to free
2863 + */
2864 +extern void
2865 +efx_vi_free(struct efx_vi_state *vih);
2866 +
2867 +/*!
2868 + * Reset a previously allocated efx_vi
2869 + *
2870 + * \param vih The handle of the efx_vi to reset
2871 + */
2872 +extern void
2873 +efx_vi_reset(struct efx_vi_state *vih);
2874 +
2875 +/**************************************************************************
2876 + * efx_vi_eventq types and functions
2877 + **************************************************************************/
2878 +
2879 +/*!
2880 + * Register a function to receive callbacks when event queue timeouts
2881 + * or wakeups occur. Only one function per efx_vi can be registered
2882 + * at once.
2883 + *
2884 + * \param vih The handle to identify the efx_vi
2885 + * \param callback The function to callback
2886 + * \param context An argument to pass to the callback function
2887 + * \return Zero on success, non-zero on failure.
2888 + */
2889 +extern int
2890 +efx_vi_eventq_register_callback(struct efx_vi_state *vih,
2891 + void (*callback)(void *context, int is_timeout),
2892 + void *context);
2893 +
2894 +/*!
2895 + * Remove the current eventq timeout or wakeup callback function
2896 + *
2897 + * \param vih The handle to identify the efx_vi
2898 + * \return Zero on success, non-zero on failure
2899 + */
2900 +extern int
2901 +efx_vi_eventq_kill_callback(struct efx_vi_state *vih);
2902 +
2903 +/**************************************************************************
2904 + * efx_vi_dma_map types and functions
2905 + **************************************************************************/
2906 +
2907 +/*!
2908 + * Handle for refering to a efx_vi
2909 + */
2910 +struct efx_vi_dma_map_state;
2911 +
2912 +/*!
2913 + * Map a list of buffer pages so they are registered with the hardware
2914 + *
2915 + * \param vih The handle to identify the efx_vi
2916 + * \param addrs An array of page pointers to map
2917 + * \param n_addrs Length of the page pointer array. Must be a power of two.
2918 + * \param dmh_out Set on success to a handle used to refer to this mapping
2919 + * \return Zero on success, non-zero on failure.
2920 + */
2921 +extern int
2922 +efx_vi_dma_map_pages(struct efx_vi_state *vih, struct page **pages,
2923 + int n_pages, struct efx_vi_dma_map_state **dmh_out);
2924 +extern int
2925 +efx_vi_dma_map_addrs(struct efx_vi_state *vih,
2926 + unsigned long long *dev_bus_addrs, int n_pages,
2927 + struct efx_vi_dma_map_state **dmh_out);
2928 +
2929 +/*!
2930 + * Unmap a previously mapped set of pages so they are no longer registered
2931 + * with the hardware.
2932 + *
2933 + * \param vih The handle to identify the efx_vi
2934 + * \param dmh The handle to identify the dma mapping
2935 + */
2936 +extern void
2937 +efx_vi_dma_unmap_pages(struct efx_vi_state *vih,
2938 + struct efx_vi_dma_map_state *dmh);
2939 +extern void
2940 +efx_vi_dma_unmap_addrs(struct efx_vi_state *vih,
2941 + struct efx_vi_dma_map_state *dmh);
2942 +
2943 +/*!
2944 + * Retrieve the buffer address of the mapping
2945 + *
2946 + * \param vih The handle to identify the efx_vi
2947 + * \param dmh The handle to identify the buffer mapping
2948 + * \return The buffer address on success, or zero on failure
2949 + */
2950 +extern unsigned
2951 +efx_vi_dma_get_map_addr(struct efx_vi_state *vih,
2952 + struct efx_vi_dma_map_state *dmh);
2953 +
2954 +/**************************************************************************
2955 + * efx_vi filter functions
2956 + **************************************************************************/
2957 +
2958 +#define EFX_VI_STATIC_FILTERS 32
2959 +
2960 +/*! Handle to refer to a filter instance */
2961 +struct filter_resource_t;
2962 +
2963 +/*!
2964 + * Allocate and add a filter
2965 + *
2966 + * \param vih The handle to identify the efx_vi
2967 + * \param protocol The protocol of the new filter: UDP or TCP
2968 + * \param ip_addr_be32 The local ip address of the filter
2969 + * \param port_le16 The local port of the filter
2970 + * \param fh_out Set on success to be a handle to refer to this filter
2971 + * \return Zero on success, non-zero on failure.
2972 + */
2973 +extern int
2974 +efx_vi_filter(struct efx_vi_state *vih, int protocol, unsigned ip_addr_be32,
2975 + int port_le16, struct filter_resource_t **fh_out);
2976 +
2977 +/*!
2978 + * Remove a filter and free resources associated with it
2979 + *
2980 + * \param vih The handle to identify the efx_vi
2981 + * \param fh The handle to identify the filter
2982 + * \return Zero on success, non-zero on failure
2983 + */
2984 +extern int
2985 +efx_vi_filter_stop(struct efx_vi_state *vih, struct filter_resource_t *fh);
2986 +
2987 +/**************************************************************************
2988 + * efx_vi hw resources types and functions
2989 + **************************************************************************/
2990 +
2991 +/*! Constants for the type field in efx_vi_hw_resource */
2992 +#define EFX_VI_HW_RESOURCE_TXDMAQ 0x0 /* PFN of TX DMA Q */
2993 +#define EFX_VI_HW_RESOURCE_RXDMAQ 0x1 /* PFN of RX DMA Q */
2994 +#define EFX_VI_HW_RESOURCE_EVQTIMER 0x4 /* Address of event q timer */
2995 +
2996 +/* Address of event q pointer (EF1) */
2997 +#define EFX_VI_HW_RESOURCE_EVQPTR 0x5
2998 +/* Address of register pointer (Falcon A) */
2999 +#define EFX_VI_HW_RESOURCE_EVQRPTR 0x6
3000 +/* Offset of register pointer (Falcon B) */
3001 +#define EFX_VI_HW_RESOURCE_EVQRPTR_OFFSET 0x7
3002 +/* Address of mem KVA */
3003 +#define EFX_VI_HW_RESOURCE_EVQMEMKVA 0x8
3004 +/* PFN of doorbell page (Falcon) */
3005 +#define EFX_VI_HW_RESOURCE_BELLPAGE 0x9
3006 +
3007 +/*! How large an array to allocate for the get_() functions - smaller
3008 + than the total number of constants as some are mutually exclusive */
3009 +#define EFX_VI_HW_RESOURCE_MAXSIZE 0x7
3010 +
3011 +/*! Constants for the mem_type field in efx_vi_hw_resource */
3012 +#define EFX_VI_HW_RESOURCE_IOBUFFER 0 /* Host memory */
3013 +#define EFX_VI_HW_RESOURCE_PERIPHERAL 1 /* Card memory/registers */
3014 +
3015 +/*!
3016 + * Data structure providing information on a hardware resource mapping
3017 + */
3018 +struct efx_vi_hw_resource {
3019 + u8 type; /*!< What this resource represents */
3020 + u8 mem_type; /*!< What type of memory is it in, eg,
3021 + * host or iomem */
3022 + u8 more_to_follow; /*!< Is this part of a multi-region resource */
3023 + u32 length; /*!< Length of the resource in bytes */
3024 + unsigned long address; /*!< Address of this resource */
3025 +};
3026 +
3027 +/*!
3028 + * Metadata concerning the list of hardware resource mappings
3029 + */
3030 +struct efx_vi_hw_resource_metadata {
3031 + int evq_order;
3032 + int evq_offs;
3033 + int evq_capacity;
3034 + int instance;
3035 + unsigned rx_capacity;
3036 + unsigned tx_capacity;
3037 + int nic_arch;
3038 + int nic_revision;
3039 + char nic_variant;
3040 +};
3041 +
3042 +/*!
3043 + * Obtain a list of hardware resource mappings, using virtual addresses
3044 + *
3045 + * \param vih The handle to identify the efx_vi
3046 + * \param mdata Pointer to a structure to receive the metadata
3047 + * \param hw_res_array An array to receive the list of hardware resources
3048 + * \param length The length of hw_res_array. Updated on success to contain
3049 + * the number of entries in the supplied array that were used.
3050 + * \return Zero on success, non-zero on failure
3051 + */
3052 +extern int
3053 +efx_vi_hw_resource_get_virt(struct efx_vi_state *vih,
3054 + struct efx_vi_hw_resource_metadata *mdata,
3055 + struct efx_vi_hw_resource *hw_res_array,
3056 + int *length);
3057 +
3058 +/*!
3059 + * Obtain a list of hardware resource mappings, using physical addresses
3060 + *
3061 + * \param vih The handle to identify the efx_vi
3062 + * \param mdata Pointer to a structure to receive the metadata
3063 + * \param hw_res_array An array to receive the list of hardware resources
3064 + * \param length The length of hw_res_array. Updated on success to contain
3065 + * the number of entries in the supplied array that were used.
3066 + * \return Zero on success, non-zero on failure
3067 + */
3068 +extern int
3069 +efx_vi_hw_resource_get_phys(struct efx_vi_state *vih,
3070 + struct efx_vi_hw_resource_metadata *mdata,
3071 + struct efx_vi_hw_resource *hw_res_array,
3072 + int *length);
3073 +
3074 +#endif /* __CI_DRIVER_RESOURCE_EFX_VI_H__ */
3075 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/resource/linux_efhw_nic.h
3076 ===================================================================
3077 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
3078 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/resource/linux_efhw_nic.h 2008-07-17 16:18:07.000000000 +0200
3079 @@ -0,0 +1,69 @@
3080 +/****************************************************************************
3081 + * Driver for Solarflare network controllers -
3082 + * resource management for Xen backend, OpenOnload, etc
3083 + * (including support for SFE4001 10GBT NIC)
3084 + *
3085 + * This file contains definition of the public type struct linux_efhw_nic.
3086 + *
3087 + * Copyright 2005-2007: Solarflare Communications Inc,
3088 + * 9501 Jeronimo Road, Suite 250,
3089 + * Irvine, CA 92618, USA
3090 + *
3091 + * Developed and maintained by Solarflare Communications:
3092 + * <linux-xen-drivers@solarflare.com>
3093 + * <onload-dev@solarflare.com>
3094 + *
3095 + * Certain parts of the driver were implemented by
3096 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
3097 + * OKTET Labs Ltd, Russia,
3098 + * http://oktetlabs.ru, <info@oktetlabs.ru>
3099 + * by request of Solarflare Communications
3100 + *
3101 + *
3102 + * This program is free software; you can redistribute it and/or modify it
3103 + * under the terms of the GNU General Public License version 2 as published
3104 + * by the Free Software Foundation, incorporated herein by reference.
3105 + *
3106 + * This program is distributed in the hope that it will be useful,
3107 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3108 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3109 + * GNU General Public License for more details.
3110 + *
3111 + * You should have received a copy of the GNU General Public License
3112 + * along with this program; if not, write to the Free Software
3113 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3114 + ****************************************************************************
3115 + */
3116 +
3117 +#ifndef __CI_DRIVER_RESOURCE_LINUX_RESOURCE__
3118 +#define __CI_DRIVER_RESOURCE_LINUX_RESOURCE__
3119 +
3120 +#include <ci/efrm/efrm_nic.h>
3121 +#include <linux/interrupt.h>
3122 +
3123 +
3124 +/************************************************************************
3125 + * Per-nic structure in the resource driver *
3126 + ************************************************************************/
3127 +
3128 +struct linux_efhw_nic {
3129 + struct efrm_nic efrm_nic;
3130 +
3131 + struct pci_dev *pci_dev; /*!< pci descriptor */
3132 + struct tasklet_struct tasklet; /*!< for interrupt bottom half */
3133 +
3134 + /* Physical addresses of the control aperture bar. */
3135 + unsigned long ctr_ap_pci_addr;
3136 +
3137 + /*! Callbacks for driverlink, when needed. */
3138 + struct efx_dl_callbacks *dl_callbacks;
3139 +
3140 + /*! Event handlers. */
3141 + struct efhw_ev_handler *ev_handlers;
3142 +
3143 +};
3144 +
3145 +#define linux_efhw_nic(_efhw_nic) \
3146 + container_of(_efhw_nic, struct linux_efhw_nic, efrm_nic.efhw_nic)
3147 +
3148 +#endif /* __CI_DRIVER_RESOURCE_LINUX_RESOURCE__ */
3149 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/checks.h
3150 ===================================================================
3151 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
3152 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/checks.h 2008-07-17 16:18:07.000000000 +0200
3153 @@ -0,0 +1,118 @@
3154 +/****************************************************************************
3155 + * Driver for Solarflare network controllers -
3156 + * resource management for Xen backend, OpenOnload, etc
3157 + * (including support for SFE4001 10GBT NIC)
3158 + *
3159 + * This file provides helpers to turn bit shifts into dword shifts and
3160 + * check that the bit fields haven't overflown the dword etc.
3161 + *
3162 + * Copyright 2005-2007: Solarflare Communications Inc,
3163 + * 9501 Jeronimo Road, Suite 250,
3164 + * Irvine, CA 92618, USA
3165 + *
3166 + * Developed and maintained by Solarflare Communications:
3167 + * <linux-xen-drivers@solarflare.com>
3168 + * <onload-dev@solarflare.com>
3169 + *
3170 + *
3171 + * This program is free software; you can redistribute it and/or modify it
3172 + * under the terms of the GNU General Public License version 2 as published
3173 + * by the Free Software Foundation, incorporated herein by reference.
3174 + *
3175 + * This program is distributed in the hope that it will be useful,
3176 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3177 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3178 + * GNU General Public License for more details.
3179 + *
3180 + * You should have received a copy of the GNU General Public License
3181 + * along with this program; if not, write to the Free Software
3182 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3183 + ****************************************************************************
3184 + */
3185 +
3186 +#ifndef __CI_EFHW_CHECK_H__
3187 +#define __CI_EFHW_CHECK_H__
3188 +
3189 +/*----------------------------------------------------------------------------
3190 + *
3191 + * Helpers to turn bit shifts into dword shifts and check that the bit fields
3192 + * haven't overflown the dword etc. Aim is to preserve consistency with the
3193 + * autogenerated headers - once stable we could hard code.
3194 + *
3195 + *---------------------------------------------------------------------------*/
3196 +
3197 +/* mask constructors */
3198 +#define __FALCON_MASK(WIDTH, T) ((((T)1) << (WIDTH)) - 1)
3199 +#define __FALCON_MASK32(WIDTH) __FALCON_MASK((WIDTH), uint32_t)
3200 +#define __FALCON_MASK64(WIDTH) __FALCON_MASK((WIDTH), uint64_t)
3201 +
3202 +#define __FALCON_MASKFIELD32(LBN, WIDTH) \
3203 + ((uint32_t)(__FALCON_MASK32(WIDTH) << (LBN)))
3204 +
3205 +/* constructors for fields which span the first and second dwords */
3206 +#define __LW(LBN) (32 - LBN)
3207 +#define __LOW(v, LBN, WIDTH) \
3208 + ((uint32_t)(((v) & __FALCON_MASK64(__LW((LBN)))) << (LBN)))
3209 +#define __HIGH(v, LBN, WIDTH) \
3210 + ((uint32_t)(((v) >> __LW((LBN))) & \
3211 + __FALCON_MASK64((WIDTH - __LW((LBN))))))
3212 +/* constructors for fields within the second dword */
3213 +#define __DW2(LBN) ((LBN) - 32)
3214 +
3215 +/* constructors for fields which span the second and third dwords */
3216 +#define __LW2(LBN) (64 - LBN)
3217 +#define __LOW2(v, LBN, WIDTH) \
3218 + ((uint32_t)(((v) & __FALCON_MASK64(__LW2((LBN)))) << ((LBN) - 32)))
3219 +#define __HIGH2(v, LBN, WIDTH) \
3220 + ((uint32_t)(((v) >> __LW2((LBN))) & \
3221 + __FALCON_MASK64((WIDTH - __LW2((LBN))))))
3222 +
3223 +/* constructors for fields within the third dword */
3224 +#define __DW3(LBN) ((LBN) - 64)
3225 +
3226 +/* constructors for fields which span the third and fourth dwords */
3227 +#define __LW3(LBN) (96 - LBN)
3228 +#define __LOW3(v, LBN, WIDTH) \
3229 + ((uint32_t)(((v) & __FALCON_MASK64(__LW3((LBN)))) << ((LBN) - 64)))
3230 +#define __HIGH3(v, LBN, WIDTH) \
3231 + ((ci_unit32)(((v) >> __LW3((LBN))) & \
3232 + __FALCON_MASK64((WIDTH - __LW3((LBN))))))
3233 +
3234 +/* constructors for fields within the fourth dword */
3235 +#define __DW4(LBN) ((LBN) - 96)
3236 +
3237 +/* checks that the autogenerated headers are consistent with our model */
3238 +#define __WIDTHCHCK(a, b) EFHW_ASSERT((a) == (b))
3239 +#define __RANGECHCK(v, WIDTH) \
3240 + EFHW_ASSERT(((uint64_t)(v) & ~(__FALCON_MASK64((WIDTH)))) == 0)
3241 +
3242 +/* fields within the first dword */
3243 +#define __DWCHCK(LBN, WIDTH) \
3244 + EFHW_ASSERT(((LBN) >= 0) && (((LBN)+(WIDTH)) <= 32))
3245 +
3246 +/* fields which span the first and second dwords */
3247 +#define __LWCHK(LBN, WIDTH) EFHW_ASSERT(WIDTH >= __LW(LBN))
3248 +
3249 +/* fields within the second dword */
3250 +#define __DW2CHCK(LBN, WIDTH) \
3251 + EFHW_ASSERT(((LBN) >= 32) && (((LBN)+(WIDTH)) <= 64))
3252 +
3253 +/* fields which span the second and third dwords */
3254 +#define __LW2CHK(LBN, WIDTH) EFHW_ASSERT(WIDTH >= __LW2(LBN))
3255 +
3256 +/* fields within the third dword */
3257 +#define __DW3CHCK(LBN, WIDTH) \
3258 + EFHW_ASSERT(((LBN) >= 64) && (((LBN)+(WIDTH)) <= 96))
3259 +
3260 +/* fields which span the third and fourth dwords */
3261 +#define __LW3CHK(LBN, WIDTH) EFHW_ASSERT(WIDTH >= __LW3(LBN))
3262 +
3263 +/* fields within the fourth dword */
3264 +#define __DW4CHCK(LBN, WIDTH) \
3265 + EFHW_ASSERT(((LBN) >= 96) && (((LBN)+(WIDTH)) <= 128))
3266 +
3267 +/* fields in the first qword */
3268 +#define __QWCHCK(LBN, WIDTH) \
3269 + EFHW_ASSERT(((LBN) >= 0) && (((LBN)+(WIDTH)) <= 64))
3270 +
3271 +#endif /* __CI_EFHW_CHECK_H__ */
3272 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/common.h
3273 ===================================================================
3274 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
3275 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/common.h 2008-07-17 16:18:07.000000000 +0200
3276 @@ -0,0 +1,93 @@
3277 +/****************************************************************************
3278 + * Driver for Solarflare network controllers -
3279 + * resource management for Xen backend, OpenOnload, etc
3280 + * (including support for SFE4001 10GBT NIC)
3281 + *
3282 + * This file provides API of the efhw library which may be used both from
3283 + * the kernel and from the user-space code.
3284 + *
3285 + * Copyright 2005-2007: Solarflare Communications Inc,
3286 + * 9501 Jeronimo Road, Suite 250,
3287 + * Irvine, CA 92618, USA
3288 + *
3289 + * Developed and maintained by Solarflare Communications:
3290 + * <linux-xen-drivers@solarflare.com>
3291 + * <onload-dev@solarflare.com>
3292 + *
3293 + * Certain parts of the driver were implemented by
3294 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
3295 + * OKTET Labs Ltd, Russia,
3296 + * http://oktetlabs.ru, <info@oktetlabs.ru>
3297 + * by request of Solarflare Communications
3298 + *
3299 + *
3300 + * This program is free software; you can redistribute it and/or modify it
3301 + * under the terms of the GNU General Public License version 2 as published
3302 + * by the Free Software Foundation, incorporated herein by reference.
3303 + *
3304 + * This program is distributed in the hope that it will be useful,
3305 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3306 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3307 + * GNU General Public License for more details.
3308 + *
3309 + * You should have received a copy of the GNU General Public License
3310 + * along with this program; if not, write to the Free Software
3311 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3312 + ****************************************************************************
3313 + */
3314 +
3315 +#ifndef __CI_EFHW_COMMON_H__
3316 +#define __CI_EFHW_COMMON_H__
3317 +
3318 +#include <ci/efhw/common_sysdep.h>
3319 +
3320 +typedef uint32_t efhw_buffer_addr_t;
3321 +#define EFHW_BUFFER_ADDR_FMT "[ba:%"PRIx32"]"
3322 +
3323 +/*! Comment? */
3324 +typedef union {
3325 + uint64_t u64;
3326 + struct {
3327 + uint32_t a;
3328 + uint32_t b;
3329 + } opaque;
3330 +} efhw_event_t;
3331 +
3332 +/* Flags for TX/RX queues */
3333 +#define EFHW_VI_JUMBO_EN 0x01 /*! scatter RX over multiple desc */
3334 +#define EFHW_VI_ISCSI_RX_HDIG_EN 0x02 /*! iscsi rx header digest */
3335 +#define EFHW_VI_ISCSI_TX_HDIG_EN 0x04 /*! iscsi tx header digest */
3336 +#define EFHW_VI_ISCSI_RX_DDIG_EN 0x08 /*! iscsi rx data digest */
3337 +#define EFHW_VI_ISCSI_TX_DDIG_EN 0x10 /*! iscsi tx data digest */
3338 +#define EFHW_VI_TX_PHYS_ADDR_EN 0x20 /*! TX physical address mode */
3339 +#define EFHW_VI_RX_PHYS_ADDR_EN 0x40 /*! RX physical address mode */
3340 +#define EFHW_VI_RM_WITH_INTERRUPT 0x80 /*! VI with an interrupt */
3341 +#define EFHW_VI_TX_IP_CSUM_DIS 0x100 /*! enable ip checksum generation */
3342 +#define EFHW_VI_TX_TCPUDP_CSUM_DIS 0x200 /*! enable tcp/udp checksum
3343 + generation */
3344 +#define EFHW_VI_TX_TCPUDP_ONLY 0x400 /*! drop non-tcp/udp packets */
3345 +
3346 +/* Types of hardware filter */
3347 +/* Each of these values implicitly selects scatter filters on B0 - or in
3348 + EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK if a non-scatter filter is required */
3349 +#define EFHW_IP_FILTER_TYPE_UDP_WILDCARD (0) /* dest host only */
3350 +#define EFHW_IP_FILTER_TYPE_UDP_FULL (1) /* dest host and port */
3351 +#define EFHW_IP_FILTER_TYPE_TCP_WILDCARD (2) /* dest based filter */
3352 +#define EFHW_IP_FILTER_TYPE_TCP_FULL (3) /* src filter */
3353 +/* Same again, but with RSS (for B0 only) */
3354 +#define EFHW_IP_FILTER_TYPE_UDP_WILDCARD_RSS_B0 (4)
3355 +#define EFHW_IP_FILTER_TYPE_UDP_FULL_RSS_B0 (5)
3356 +#define EFHW_IP_FILTER_TYPE_TCP_WILDCARD_RSS_B0 (6)
3357 +#define EFHW_IP_FILTER_TYPE_TCP_FULL_RSS_B0 (7)
3358 +
3359 +#define EFHW_IP_FILTER_TYPE_FULL_MASK (0x1) /* Mask for full / wildcard */
3360 +#define EFHW_IP_FILTER_TYPE_TCP_MASK (0x2) /* Mask for TCP type */
3361 +#define EFHW_IP_FILTER_TYPE_RSS_B0_MASK (0x4) /* Mask for B0 RSS enable */
3362 +#define EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK (0x8) /* Mask for B0 SCATTER dsbl */
3363 +
3364 +#define EFHW_IP_FILTER_TYPE_MASK (0xffff) /* Mask of types above */
3365 +
3366 +#define EFHW_IP_FILTER_BROADCAST (0x10000) /* driverlink filter
3367 + support */
3368 +
3369 +#endif /* __CI_EFHW_COMMON_H__ */
3370 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/common_sysdep.h
3371 ===================================================================
3372 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
3373 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/common_sysdep.h 2008-07-17 16:18:07.000000000 +0200
3374 @@ -0,0 +1,61 @@
3375 +/****************************************************************************
3376 + * Driver for Solarflare network controllers -
3377 + * resource management for Xen backend, OpenOnload, etc
3378 + * (including support for SFE4001 10GBT NIC)
3379 + *
3380 + * This file provides version-independent Linux kernel API for
3381 + * userland-to-kernel interfaces.
3382 + * Only kernels >=2.6.9 are supported.
3383 + *
3384 + * Copyright 2005-2007: Solarflare Communications Inc,
3385 + * 9501 Jeronimo Road, Suite 250,
3386 + * Irvine, CA 92618, USA
3387 + *
3388 + * Developed and maintained by Solarflare Communications:
3389 + * <linux-xen-drivers@solarflare.com>
3390 + * <onload-dev@solarflare.com>
3391 + *
3392 + * Certain parts of the driver were implemented by
3393 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
3394 + * OKTET Labs Ltd, Russia,
3395 + * http://oktetlabs.ru, <info@oktetlabs.ru>
3396 + * by request of Solarflare Communications
3397 + *
3398 + *
3399 + * This program is free software; you can redistribute it and/or modify it
3400 + * under the terms of the GNU General Public License version 2 as published
3401 + * by the Free Software Foundation, incorporated herein by reference.
3402 + *
3403 + * This program is distributed in the hope that it will be useful,
3404 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3405 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3406 + * GNU General Public License for more details.
3407 + *
3408 + * You should have received a copy of the GNU General Public License
3409 + * along with this program; if not, write to the Free Software
3410 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3411 + ****************************************************************************
3412 + */
3413 +
3414 +#ifndef __CI_EFHW_COMMON_LINUX_H__
3415 +#define __CI_EFHW_COMMON_LINUX_H__
3416 +
3417 +#include <linux/types.h>
3418 +
3419 +/* Dirty hack, but Linux kernel does not provide DMA_ADDR_T_FMT */
3420 +#if BITS_PER_LONG == 64 || defined(CONFIG_HIGHMEM64G)
3421 +#define DMA_ADDR_T_FMT "%llx"
3422 +#else
3423 +#define DMA_ADDR_T_FMT "%x"
3424 +#endif
3425 +
3426 +/* Linux kernel also does not provide PRIx32... Sigh. */
3427 +#define PRIx32 "x"
3428 +
3429 +#ifdef __ia64__
3430 +# define PRIx64 "lx"
3431 +#else
3432 +# define PRIx64 "llx"
3433 +#endif
3434 +
3435 +#endif /* __CI_EFHW_COMMON_LINUX_H__ */
3436 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/debug.h
3437 ===================================================================
3438 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
3439 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/debug.h 2008-07-17 16:18:07.000000000 +0200
3440 @@ -0,0 +1,84 @@
3441 +/****************************************************************************
3442 + * Driver for Solarflare network controllers -
3443 + * resource management for Xen backend, OpenOnload, etc
3444 + * (including support for SFE4001 10GBT NIC)
3445 + *
3446 + * This file provides debug-related API for efhw library using Linux kernel
3447 + * primitives.
3448 + *
3449 + * Copyright 2005-2007: Solarflare Communications Inc,
3450 + * 9501 Jeronimo Road, Suite 250,
3451 + * Irvine, CA 92618, USA
3452 + *
3453 + * Developed and maintained by Solarflare Communications:
3454 + * <linux-xen-drivers@solarflare.com>
3455 + * <onload-dev@solarflare.com>
3456 + *
3457 + * Certain parts of the driver were implemented by
3458 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
3459 + * OKTET Labs Ltd, Russia,
3460 + * http://oktetlabs.ru, <info@oktetlabs.ru>
3461 + * by request of Solarflare Communications
3462 + *
3463 + *
3464 + * This program is free software; you can redistribute it and/or modify it
3465 + * under the terms of the GNU General Public License version 2 as published
3466 + * by the Free Software Foundation, incorporated herein by reference.
3467 + *
3468 + * This program is distributed in the hope that it will be useful,
3469 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3470 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3471 + * GNU General Public License for more details.
3472 + *
3473 + * You should have received a copy of the GNU General Public License
3474 + * along with this program; if not, write to the Free Software
3475 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3476 + ****************************************************************************
3477 + */
3478 +
3479 +#ifndef __CI_EFHW_DEBUG_LINUX_H__
3480 +#define __CI_EFHW_DEBUG_LINUX_H__
3481 +
3482 +#define EFHW_PRINTK_PREFIX "[sfc efhw] "
3483 +
3484 +#define EFHW_PRINTK(level, fmt, ...) \
3485 + printk(level EFHW_PRINTK_PREFIX fmt "\n", __VA_ARGS__)
3486 +
3487 +/* Following macros should be used with non-zero format parameters
3488 + * due to __VA_ARGS__ limitations. Use "%s" with __func__ if you can't
3489 + * find better parameters. */
3490 +#define EFHW_ERR(fmt, ...) EFHW_PRINTK(KERN_ERR, fmt, __VA_ARGS__)
3491 +#define EFHW_WARN(fmt, ...) EFHW_PRINTK(KERN_WARNING, fmt, __VA_ARGS__)
3492 +#define EFHW_NOTICE(fmt, ...) EFHW_PRINTK(KERN_NOTICE, fmt, __VA_ARGS__)
3493 +#if 0 && !defined(NDEBUG)
3494 +#define EFHW_TRACE(fmt, ...) EFHW_PRINTK(KERN_DEBUG, fmt, __VA_ARGS__)
3495 +#else
3496 +#define EFHW_TRACE(fmt, ...)
3497 +#endif
3498 +
3499 +#ifndef NDEBUG
3500 +#define EFHW_ASSERT(cond) BUG_ON((cond) == 0)
3501 +#define EFHW_DO_DEBUG(expr) expr
3502 +#else
3503 +#define EFHW_ASSERT(cond)
3504 +#define EFHW_DO_DEBUG(expr)
3505 +#endif
3506 +
3507 +#define EFHW_TEST(expr) \
3508 + do { \
3509 + if (unlikely(!(expr))) \
3510 + BUG(); \
3511 + } while (0)
3512 +
3513 +/* Build time asserts. We paste the line number into the type name
3514 + * so that the macro can be used more than once per file even if the
3515 + * compiler objects to multiple identical typedefs. Collisions
3516 + * between use in different header files is still possible. */
3517 +#ifndef EFHW_BUILD_ASSERT
3518 +#define __EFHW_BUILD_ASSERT_NAME(_x) __EFHW_BUILD_ASSERT_ILOATHECPP(_x)
3519 +#define __EFHW_BUILD_ASSERT_ILOATHECPP(_x) __EFHW_BUILD_ASSERT__ ##_x
3520 +#define EFHW_BUILD_ASSERT(e) \
3521 + typedef char __EFHW_BUILD_ASSERT_NAME(__LINE__)[(e) ? 1 : -1]
3522 +#endif
3523 +
3524 +#endif /* __CI_EFHW_DEBUG_LINUX_H__ */
3525 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/efhw_config.h
3526 ===================================================================
3527 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
3528 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/efhw_config.h 2008-07-17 16:18:07.000000000 +0200
3529 @@ -0,0 +1,43 @@
3530 +/****************************************************************************
3531 + * Driver for Solarflare network controllers -
3532 + * resource management for Xen backend, OpenOnload, etc
3533 + * (including support for SFE4001 10GBT NIC)
3534 + *
3535 + * This file provides some limits used in both kernel and userland code.
3536 + *
3537 + * Copyright 2005-2007: Solarflare Communications Inc,
3538 + * 9501 Jeronimo Road, Suite 250,
3539 + * Irvine, CA 92618, USA
3540 + *
3541 + * Developed and maintained by Solarflare Communications:
3542 + * <linux-xen-drivers@solarflare.com>
3543 + * <onload-dev@solarflare.com>
3544 + *
3545 + * Certain parts of the driver were implemented by
3546 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
3547 + * OKTET Labs Ltd, Russia,
3548 + * http://oktetlabs.ru, <info@oktetlabs.ru>
3549 + * by request of Solarflare Communications
3550 + *
3551 + *
3552 + * This program is free software; you can redistribute it and/or modify it
3553 + * under the terms of the GNU General Public License version 2 as published
3554 + * by the Free Software Foundation, incorporated herein by reference.
3555 + *
3556 + * This program is distributed in the hope that it will be useful,
3557 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3558 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3559 + * GNU General Public License for more details.
3560 + *
3561 + * You should have received a copy of the GNU General Public License
3562 + * along with this program; if not, write to the Free Software
3563 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3564 + ****************************************************************************
3565 + */
3566 +
3567 +#ifndef __CI_EFHW_EFAB_CONFIG_H__
3568 +#define __CI_EFHW_EFAB_CONFIG_H__
3569 +
3570 +#define EFHW_MAX_NR_DEVS 5 /* max number of efhw devices supported */
3571 +
3572 +#endif /* __CI_EFHW_EFAB_CONFIG_H__ */
3573 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/efhw_types.h
3574 ===================================================================
3575 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
3576 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/efhw_types.h 2008-07-17 16:18:07.000000000 +0200
3577 @@ -0,0 +1,382 @@
3578 +/****************************************************************************
3579 + * Driver for Solarflare network controllers -
3580 + * resource management for Xen backend, OpenOnload, etc
3581 + * (including support for SFE4001 10GBT NIC)
3582 + *
3583 + * This file provides struct efhw_nic and some related types.
3584 + *
3585 + * Copyright 2005-2007: Solarflare Communications Inc,
3586 + * 9501 Jeronimo Road, Suite 250,
3587 + * Irvine, CA 92618, USA
3588 + *
3589 + * Developed and maintained by Solarflare Communications:
3590 + * <linux-xen-drivers@solarflare.com>
3591 + * <onload-dev@solarflare.com>
3592 + *
3593 + * Certain parts of the driver were implemented by
3594 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
3595 + * OKTET Labs Ltd, Russia,
3596 + * http://oktetlabs.ru, <info@oktetlabs.ru>
3597 + * by request of Solarflare Communications
3598 + *
3599 + *
3600 + * This program is free software; you can redistribute it and/or modify it
3601 + * under the terms of the GNU General Public License version 2 as published
3602 + * by the Free Software Foundation, incorporated herein by reference.
3603 + *
3604 + * This program is distributed in the hope that it will be useful,
3605 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3606 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3607 + * GNU General Public License for more details.
3608 + *
3609 + * You should have received a copy of the GNU General Public License
3610 + * along with this program; if not, write to the Free Software
3611 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3612 + ****************************************************************************
3613 + */
3614 +
3615 +#ifndef __CI_EFHW_EFAB_TYPES_H__
3616 +#define __CI_EFHW_EFAB_TYPES_H__
3617 +
3618 +#include <ci/efhw/efhw_config.h>
3619 +#include <ci/efhw/hardware_sysdep.h>
3620 +#include <ci/efhw/iopage_types.h>
3621 +#include <ci/efhw/sysdep.h>
3622 +
3623 +/*--------------------------------------------------------------------
3624 + *
3625 + * forward type declarations
3626 + *
3627 + *--------------------------------------------------------------------*/
3628 +
3629 +struct efhw_nic;
3630 +
3631 +/*--------------------------------------------------------------------
3632 + *
3633 + * Managed interface
3634 + *
3635 + *--------------------------------------------------------------------*/
3636 +
3637 +struct efhw_buffer_table_allocation{
3638 + unsigned base;
3639 + unsigned order;
3640 +};
3641 +
3642 +struct eventq_resource_hardware {
3643 + /*!iobuffer allocated for eventq - can be larger than eventq */
3644 + struct efhw_iopages iobuff;
3645 + unsigned iobuff_off;
3646 + struct efhw_buffer_table_allocation buf_tbl_alloc;
3647 + int capacity; /*!< capacity of event queue */
3648 +};
3649 +
3650 +/*--------------------------------------------------------------------
3651 + *
3652 + * event queues and event driven callbacks
3653 + *
3654 + *--------------------------------------------------------------------*/
3655 +
3656 +struct efhw_keventq {
3657 + int lock;
3658 + caddr_t evq_base;
3659 + int32_t evq_ptr;
3660 + uint32_t evq_mask;
3661 + unsigned instance;
3662 + struct eventq_resource_hardware hw;
3663 + struct efhw_ev_handler *ev_handlers;
3664 +};
3665 +
3666 +/*--------------------------------------------------------------------
3667 + *
3668 + * filters
3669 + *
3670 + *--------------------------------------------------------------------*/
3671 +
3672 +struct efhw_filter_spec {
3673 + uint dmaq_id;
3674 + uint32_t saddr_le32;
3675 + uint32_t daddr_le32;
3676 + uint16_t sport_le16;
3677 + uint16_t dport_le16;
3678 + unsigned tcp : 1;
3679 + unsigned full : 1;
3680 + unsigned rss : 1; /* not supported on A1 */
3681 + unsigned scatter : 1; /* not supported on A1 */
3682 +};
3683 +
3684 +struct efhw_filter_depth {
3685 + unsigned needed;
3686 + unsigned max;
3687 +};
3688 +
3689 +struct efhw_filter_search_limits {
3690 + unsigned tcp_full;
3691 + unsigned tcp_wild;
3692 + unsigned udp_full;
3693 + unsigned udp_wild;
3694 +};
3695 +
3696 +
3697 +/**********************************************************************
3698 + * Portable HW interface. ***************************************
3699 + **********************************************************************/
3700 +
3701 +/*--------------------------------------------------------------------
3702 + *
3703 + * EtherFabric Functional units - configuration and control
3704 + *
3705 + *--------------------------------------------------------------------*/
3706 +
3707 +struct efhw_func_ops {
3708 +
3709 + /*-------------- Initialisation ------------ */
3710 +
3711 + /*! close down all hardware functional units - leaves NIC in a safe
3712 + state for driver unload */
3713 + void (*close_hardware) (struct efhw_nic *nic);
3714 +
3715 + /*! initialise all hardware functional units */
3716 + int (*init_hardware) (struct efhw_nic *nic,
3717 + struct efhw_ev_handler *,
3718 + const uint8_t *mac_addr, int non_irq_evq);
3719 +
3720 + /*-------------- Interrupt support ------------ */
3721 +
3722 + /*! Main interrupt routine
3723 + ** This function returns,
3724 + ** - zero, if the IRQ was not generated by EF1
3725 + ** - non-zero, if EF1 was the source of the IRQ
3726 + **
3727 + **
3728 + ** opaque is an OS provided pointer for use by the OS callbacks
3729 + ** e.g in Windows used to indicate DPC scheduled
3730 + */
3731 + int (*interrupt) (struct efhw_nic *nic);
3732 +
3733 + /*! Enable the interrupt */
3734 + void (*interrupt_enable) (struct efhw_nic *nic);
3735 +
3736 + /*! Disable the interrupt */
3737 + void (*interrupt_disable) (struct efhw_nic *nic);
3738 +
3739 + /*! Set interrupt moderation strategy for the given IRQ unit
3740 + ** val is in usec
3741 + */
3742 + void (*set_interrupt_moderation)(struct efhw_nic *nic, int evq,
3743 + uint val);
3744 +
3745 + /*-------------- Event support ------------ */
3746 +
3747 + /*! Enable the given event queue
3748 + depending on the underlying implementation (EF1 or Falcon) then
3749 + either a q_base_addr in host memory, or a buffer base id should
3750 + be proivded
3751 + */
3752 + void (*event_queue_enable) (struct efhw_nic *nic,
3753 + uint evq, /* evnt queue index */
3754 + uint evq_size, /* units of #entries */
3755 + dma_addr_t q_base_addr, uint buf_base_id,
3756 + int interrupting);
3757 +
3758 + /*! Disable the given event queue (and any associated timer) */
3759 + void (*event_queue_disable) (struct efhw_nic *nic, uint evq,
3760 + int timer_only);
3761 +
3762 + /*! request wakeup from the NIC on a given event Q */
3763 + void (*wakeup_request) (struct efhw_nic *nic, dma_addr_t q_base_addr,
3764 + int next_i, int evq);
3765 +
3766 + /*! Push a SW event on a given eventQ */
3767 + void (*sw_event) (struct efhw_nic *nic, int data, int evq);
3768 +
3769 + /*-------------- IP Filter API ------------ */
3770 +
3771 + /*! Setup a given filter - The software can request a filter_i,
3772 + * but some EtherFabric implementations will override with
3773 + * a more suitable index
3774 + */
3775 + int (*ipfilter_set) (struct efhw_nic *nic, int type,
3776 + int *filter_i, int dmaq,
3777 + unsigned saddr_be32, unsigned sport_be16,
3778 + unsigned daddr_be32, unsigned dport_be16);
3779 +
3780 + /*! Clear down a given filter */
3781 + void (*ipfilter_clear) (struct efhw_nic *nic, int filter_idx);
3782 +
3783 + /*-------------- DMA support ------------ */
3784 +
3785 + /*! Initialise NIC state for a given TX DMAQ */
3786 + void (*dmaq_tx_q_init) (struct efhw_nic *nic,
3787 + uint dmaq, uint evq, uint owner, uint tag,
3788 + uint dmaq_size, uint buf_idx, uint flags);
3789 +
3790 + /*! Initialise NIC state for a given RX DMAQ */
3791 + void (*dmaq_rx_q_init) (struct efhw_nic *nic,
3792 + uint dmaq, uint evq, uint owner, uint tag,
3793 + uint dmaq_size, uint buf_idx, uint flags);
3794 +
3795 + /*! Disable a given TX DMAQ */
3796 + void (*dmaq_tx_q_disable) (struct efhw_nic *nic, uint dmaq);
3797 +
3798 + /*! Disable a given RX DMAQ */
3799 + void (*dmaq_rx_q_disable) (struct efhw_nic *nic, uint dmaq);
3800 +
3801 + /*! Flush a given TX DMA channel */
3802 + int (*flush_tx_dma_channel) (struct efhw_nic *nic, uint dmaq);
3803 +
3804 + /*! Flush a given RX DMA channel */
3805 + int (*flush_rx_dma_channel) (struct efhw_nic *nic, uint dmaq);
3806 +
3807 + /*-------------- Buffer table Support ------------ */
3808 +
3809 + /*! Initialise a buffer table page */
3810 + void (*buffer_table_set) (struct efhw_nic *nic,
3811 + dma_addr_t dma_addr,
3812 + uint bufsz, uint region,
3813 + int own_id, int buffer_id);
3814 +
3815 + /*! Initialise a block of buffer table pages */
3816 + void (*buffer_table_set_n) (struct efhw_nic *nic, int buffer_id,
3817 + dma_addr_t dma_addr,
3818 + uint bufsz, uint region,
3819 + int n_pages, int own_id);
3820 +
3821 + /*! Clear a block of buffer table pages */
3822 + void (*buffer_table_clear) (struct efhw_nic *nic, int buffer_id,
3823 + int num);
3824 +
3825 + /*! Commit a buffer table update */
3826 + void (*buffer_table_commit) (struct efhw_nic *nic);
3827 +
3828 + /*-------------- New filter API ------------ */
3829 +
3830 + /*! Set a given filter */
3831 + int (*filter_set) (struct efhw_nic *nic, struct efhw_filter_spec *spec,
3832 + int *filter_idx_out);
3833 +
3834 + /*! Clear a given filter */
3835 + void (*filter_clear) (struct efhw_nic *nic, int filter_idx);
3836 +};
3837 +
3838 +
3839 +/*----------------------------------------------------------------------------
3840 + *
3841 + * NIC type
3842 + *
3843 + *---------------------------------------------------------------------------*/
3844 +
3845 +struct efhw_device_type {
3846 + int arch; /* enum efhw_arch */
3847 + char variant; /* 'A', 'B', ... */
3848 + int revision; /* 0, 1, ... */
3849 +};
3850 +
3851 +
3852 +/*----------------------------------------------------------------------------
3853 + *
3854 + * EtherFabric NIC instance - nic.c for HW independent functions
3855 + *
3856 + *---------------------------------------------------------------------------*/
3857 +
3858 +/*! */
3859 +struct efhw_nic {
3860 + /*! zero base index in efrm_nic_tablep->nic array */
3861 + int index;
3862 + int ifindex; /*!< OS level nic index */
3863 + struct net *nd_net;
3864 +
3865 + struct efhw_device_type devtype;
3866 +
3867 + /*! Options that can be set by user. */
3868 + unsigned options;
3869 +# define NIC_OPT_EFTEST 0x1 /* owner is an eftest app */
3870 +
3871 +# define NIC_OPT_DEFAULT 0
3872 +
3873 + /*! Internal flags that indicate hardware properties at runtime. */
3874 + unsigned flags;
3875 +# define NIC_FLAG_NO_INTERRUPT 0x01 /* to be set at init time only */
3876 +# define NIC_FLAG_TRY_MSI 0x02
3877 +# define NIC_FLAG_MSI 0x04
3878 +# define NIC_FLAG_OS_IRQ_EN 0x08
3879 +
3880 + unsigned mtu; /*!< MAC MTU (includes MAC hdr) */
3881 +
3882 + /* hardware resources */
3883 +
3884 + /*! I/O address of the start of the bar */
3885 + volatile char __iomem *bar_ioaddr;
3886 +
3887 + /*! Bar number of control aperture. */
3888 + unsigned ctr_ap_bar;
3889 + /*! Length of control aperture in bytes. */
3890 + unsigned ctr_ap_bytes;
3891 +
3892 + uint8_t mac_addr[ETH_ALEN]; /*!< mac address */
3893 +
3894 + /*! EtherFabric Functional Units -- functions */
3895 + const struct efhw_func_ops *efhw_func;
3896 +
3897 + /*! This lock protects a number of misc NIC resources. It should
3898 + * only be used for things that can be at the bottom of the lock
3899 + * order. ie. You mustn't attempt to grab any other lock while
3900 + * holding this one.
3901 + */
3902 + spinlock_t *reg_lock;
3903 + spinlock_t the_reg_lock;
3904 +
3905 + int buf_commit_outstanding; /*!< outstanding buffer commits */
3906 +
3907 + /*! interrupt callbacks (hard-irq) */
3908 + void (*irq_handler) (struct efhw_nic *, int unit);
3909 +
3910 + /*! event queues per driver */
3911 + struct efhw_keventq interrupting_evq;
3912 +
3913 +/* for marking when we are not using an IRQ unit
3914 + - 0 is a valid offset to an IRQ unit on EF1! */
3915 +#define EFHW_IRQ_UNIT_UNUSED 0xffff
3916 + /*! interrupt unit in use for the interrupting event queue */
3917 + unsigned int irq_unit;
3918 +
3919 + struct efhw_keventq non_interrupting_evq;
3920 +
3921 + struct efhw_iopage irq_iobuff; /*!< Falcon SYSERR interrupt */
3922 +
3923 + /* The new driverlink infrastructure. */
3924 + struct efx_dl_device *net_driver_dev;
3925 + struct efx_dlfilt_cb_s *dlfilter_cb;
3926 +
3927 + /*! Bit masks of the sizes of event queues and dma queues supported
3928 + * by the nic. */
3929 + unsigned evq_sizes;
3930 + unsigned rxq_sizes;
3931 + unsigned txq_sizes;
3932 +
3933 + /* Size of filter table. */
3934 + unsigned ip_filter_tbl_size;
3935 +
3936 + /* Number of filters currently used */
3937 + unsigned ip_filter_tbl_used;
3938 +
3939 + /* Dynamically allocated filter state. */
3940 + uint8_t *filter_in_use;
3941 + struct efhw_filter_spec *filter_spec_cache;
3942 +
3943 + /* Currently required and maximum filter table search depths. */
3944 + struct efhw_filter_depth tcp_full_srch;
3945 + struct efhw_filter_depth tcp_wild_srch;
3946 + struct efhw_filter_depth udp_full_srch;
3947 + struct efhw_filter_depth udp_wild_srch;
3948 +
3949 + /* Number of event queues, DMA queues and timers. */
3950 + unsigned num_evqs;
3951 + unsigned num_dmaqs;
3952 + unsigned num_timers;
3953 +};
3954 +
3955 +
3956 +#define EFHW_KVA(nic) ((nic)->bar_ioaddr)
3957 +
3958 +
3959 +#endif /* __CI_EFHW_EFHW_TYPES_H__ */
3960 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/eventq.h
3961 ===================================================================
3962 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
3963 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/eventq.h 2008-07-17 16:18:07.000000000 +0200
3964 @@ -0,0 +1,72 @@
3965 +/****************************************************************************
3966 + * Driver for Solarflare network controllers -
3967 + * resource management for Xen backend, OpenOnload, etc
3968 + * (including support for SFE4001 10GBT NIC)
3969 + *
3970 + * This file contains API provided by efhw/eventq.c file. This file is not
3971 + * designed for use outside of the SFC resource driver.
3972 + *
3973 + * Copyright 2005-2007: Solarflare Communications Inc,
3974 + * 9501 Jeronimo Road, Suite 250,
3975 + * Irvine, CA 92618, USA
3976 + *
3977 + * Developed and maintained by Solarflare Communications:
3978 + * <linux-xen-drivers@solarflare.com>
3979 + * <onload-dev@solarflare.com>
3980 + *
3981 + * Certain parts of the driver were implemented by
3982 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
3983 + * OKTET Labs Ltd, Russia,
3984 + * http://oktetlabs.ru, <info@oktetlabs.ru>
3985 + * by request of Solarflare Communications
3986 + *
3987 + *
3988 + * This program is free software; you can redistribute it and/or modify it
3989 + * under the terms of the GNU General Public License version 2 as published
3990 + * by the Free Software Foundation, incorporated herein by reference.
3991 + *
3992 + * This program is distributed in the hope that it will be useful,
3993 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3994 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3995 + * GNU General Public License for more details.
3996 + *
3997 + * You should have received a copy of the GNU General Public License
3998 + * along with this program; if not, write to the Free Software
3999 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4000 + ****************************************************************************
4001 + */
4002 +
4003 +#ifndef __CI_EFHW_EVENTQ_H__
4004 +#define __CI_EFHW_EVENTQ_H__
4005 +
4006 +#include <ci/efhw/efhw_types.h>
4007 +#include <ci/efhw/eventq_macros.h>
4008 +
4009 +/*! Poll the event queue. */
4010 +extern int efhw_keventq_poll(struct efhw_nic *, struct efhw_keventq *);
4011 +
4012 +/*! Callbacks for handling events. */
4013 +struct efhw_ev_handler {
4014 + void (*wakeup_fn)(struct efhw_nic *nic, unsigned);
4015 + void (*timeout_fn)(struct efhw_nic *nic, unsigned);
4016 + void (*dmaq_flushed_fn) (struct efhw_nic *, unsigned, int);
4017 +};
4018 +
4019 +extern int efhw_keventq_ctor(struct efhw_nic *, int instance,
4020 + struct efhw_keventq *, struct efhw_ev_handler *);
4021 +extern void efhw_keventq_dtor(struct efhw_nic *, struct efhw_keventq *);
4022 +
4023 +extern void efhw_handle_txdmaq_flushed(struct efhw_nic *,
4024 + struct efhw_ev_handler *,
4025 + efhw_event_t *);
4026 +extern void efhw_handle_rxdmaq_flushed(struct efhw_nic *,
4027 + struct efhw_ev_handler *,
4028 + efhw_event_t *);
4029 +extern void efhw_handle_wakeup_event(struct efhw_nic *,
4030 + struct efhw_ev_handler *,
4031 + efhw_event_t *);
4032 +extern void efhw_handle_timeout_event(struct efhw_nic *,
4033 + struct efhw_ev_handler *,
4034 + efhw_event_t *);
4035 +
4036 +#endif /* __CI_EFHW_EVENTQ_H__ */
4037 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/eventq_macros.h
4038 ===================================================================
4039 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4040 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/eventq_macros.h 2008-07-17 16:18:07.000000000 +0200
4041 @@ -0,0 +1,77 @@
4042 +/****************************************************************************
4043 + * Driver for Solarflare network controllers -
4044 + * resource management for Xen backend, OpenOnload, etc
4045 + * (including support for SFE4001 10GBT NIC)
4046 + *
4047 + * This file provides some event-related macros. This file is designed for
4048 + * use from kernel and from the userland contexts.
4049 + *
4050 + * Copyright 2005-2007: Solarflare Communications Inc,
4051 + * 9501 Jeronimo Road, Suite 250,
4052 + * Irvine, CA 92618, USA
4053 + *
4054 + * Developed and maintained by Solarflare Communications:
4055 + * <linux-xen-drivers@solarflare.com>
4056 + * <onload-dev@solarflare.com>
4057 + *
4058 + * Certain parts of the driver were implemented by
4059 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
4060 + * OKTET Labs Ltd, Russia,
4061 + * http://oktetlabs.ru, <info@oktetlabs.ru>
4062 + * by request of Solarflare Communications
4063 + *
4064 + *
4065 + * This program is free software; you can redistribute it and/or modify it
4066 + * under the terms of the GNU General Public License version 2 as published
4067 + * by the Free Software Foundation, incorporated herein by reference.
4068 + *
4069 + * This program is distributed in the hope that it will be useful,
4070 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4071 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4072 + * GNU General Public License for more details.
4073 + *
4074 + * You should have received a copy of the GNU General Public License
4075 + * along with this program; if not, write to the Free Software
4076 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4077 + ****************************************************************************
4078 + */
4079 +
4080 +#ifndef __CI_EFHW_EVENTQ_MACROS_H__
4081 +#define __CI_EFHW_EVENTQ_MACROS_H__
4082 +
4083 +#include <ci/efhw/common.h>
4084 +
4085 +/*--------------------------------------------------------------------
4086 + *
4087 + * Event Queue manipulation
4088 + *
4089 + *--------------------------------------------------------------------*/
4090 +
4091 +#define EFHW_EVENT_OFFSET(q, s, i) \
4092 + (((s)->evq_ptr - (i) * (int32_t)sizeof(efhw_event_t)) \
4093 + & (q)->evq_mask)
4094 +
4095 +#define EFHW_EVENT_PTR(q, s, i) \
4096 + ((efhw_event_t *)((q)->evq_base + EFHW_EVENT_OFFSET(q, s, i)))
4097 +
4098 +#define EFHW_EVENTQ_NEXT(s) \
4099 + do { ((s)->evq_ptr += sizeof(efhw_event_t)); } while (0)
4100 +
4101 +#define EFHW_EVENTQ_PREV(s) \
4102 + do { ((s)->evq_ptr -= sizeof(efhw_event_t)); } while (0)
4103 +
4104 +/* Be worried about this on byteswapped machines */
4105 +/* Due to crazy chipsets, we see the event words being written in
4106 +** arbitrary order (bug4539). So test for presence of event must ensure
4107 +** that both halves have changed from the null.
4108 +*/
4109 +#define EFHW_IS_EVENT(evp) \
4110 + (((evp)->opaque.a != (uint32_t)-1) && \
4111 + ((evp)->opaque.b != (uint32_t)-1))
4112 +#define EFHW_CLEAR_EVENT(evp) ((evp)->u64 = (uint64_t)-1)
4113 +#define EFHW_CLEAR_EVENT_VALUE 0xff
4114 +
4115 +#define EFHW_EVENT_OVERFLOW(evq, s) \
4116 + (EFHW_IS_EVENT(EFHW_EVENT_PTR(evq, s, 1)))
4117 +
4118 +#endif /* __CI_EFHW_EVENTQ_MACROS_H__ */
4119 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/falcon.h
4120 ===================================================================
4121 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4122 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/falcon.h 2008-07-17 16:18:07.000000000 +0200
4123 @@ -0,0 +1,94 @@
4124 +/****************************************************************************
4125 + * Driver for Solarflare network controllers -
4126 + * resource management for Xen backend, OpenOnload, etc
4127 + * (including support for SFE4001 10GBT NIC)
4128 + *
4129 + * This file contains API provided by efhw/falcon.c file. This file is not
4130 + * designed for use outside of the SFC resource driver.
4131 + *
4132 + * Copyright 2005-2007: Solarflare Communications Inc,
4133 + * 9501 Jeronimo Road, Suite 250,
4134 + * Irvine, CA 92618, USA
4135 + *
4136 + * Developed and maintained by Solarflare Communications:
4137 + * <linux-xen-drivers@solarflare.com>
4138 + * <onload-dev@solarflare.com>
4139 + *
4140 + * Certain parts of the driver were implemented by
4141 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
4142 + * OKTET Labs Ltd, Russia,
4143 + * http://oktetlabs.ru, <info@oktetlabs.ru>
4144 + * by request of Solarflare Communications
4145 + *
4146 + *
4147 + * This program is free software; you can redistribute it and/or modify it
4148 + * under the terms of the GNU General Public License version 2 as published
4149 + * by the Free Software Foundation, incorporated herein by reference.
4150 + *
4151 + * This program is distributed in the hope that it will be useful,
4152 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4153 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4154 + * GNU General Public License for more details.
4155 + *
4156 + * You should have received a copy of the GNU General Public License
4157 + * along with this program; if not, write to the Free Software
4158 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4159 + ****************************************************************************
4160 + */
4161 +
4162 +#ifndef __CI_EFHW_FALCON_H__
4163 +#define __CI_EFHW_FALCON_H__
4164 +
4165 +#include <ci/efhw/efhw_types.h>
4166 +#include <ci/efhw/common.h>
4167 +
4168 +/*----------------------------------------------------------------------------
4169 + *
4170 + * Locks - unfortunately required
4171 + *
4172 + *---------------------------------------------------------------------------*/
4173 +
4174 +#define FALCON_LOCK_DECL irq_flags_t lock_state
4175 +#define FALCON_LOCK_LOCK(nic) \
4176 + spin_lock_irqsave((nic)->reg_lock, lock_state)
4177 +#define FALCON_LOCK_UNLOCK(nic) \
4178 + spin_unlock_irqrestore((nic)->reg_lock, lock_state)
4179 +
4180 +extern struct efhw_func_ops falcon_char_functional_units;
4181 +
4182 +/*! specify a pace value for a TX DMA Queue */
4183 +extern void falcon_nic_pace(struct efhw_nic *nic, uint dmaq, uint pace);
4184 +
4185 +/*! configure the pace engine */
4186 +extern void falcon_nic_pace_cfg(struct efhw_nic *nic, int fb_base,
4187 + int bin_thresh);
4188 +
4189 +/*! confirm buffer table updates - should be used for items where
4190 + loss of data would be unacceptable. E.g for the buffers that back
4191 + an event or DMA queue */
4192 +extern void falcon_nic_buffer_table_confirm(struct efhw_nic *nic);
4193 +
4194 +/*! Reset the all the TX DMA queue pointers. */
4195 +extern void falcon_clobber_tx_dma_ptrs(struct efhw_nic *nic, uint dmaq);
4196 +
4197 +extern int
4198 +falcon_handle_char_event(struct efhw_nic *nic,
4199 + struct efhw_ev_handler *h, efhw_event_t *evp);
4200 +
4201 +/*! Acknowledge to HW that processing is complete on a given event queue */
4202 +extern void falcon_nic_evq_ack(struct efhw_nic *nic, uint evq, /* evq id */
4203 + uint rptr, /* new read pointer update */
4204 + bool wakeup /* request a wakeup event if
4205 + ptr's != */
4206 + );
4207 +
4208 +extern void
4209 +falcon_nic_buffer_table_set_n(struct efhw_nic *nic, int buffer_id,
4210 + dma_addr_t dma_addr, uint bufsz, uint region,
4211 + int n_pages, int own_id);
4212 +
4213 +extern int falcon_nic_filter_ctor(struct efhw_nic *nic);
4214 +
4215 +extern void falcon_nic_filter_dtor(struct efhw_nic *nic);
4216 +
4217 +#endif /* __CI_EFHW_FALCON_H__ */
4218 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/falcon_hash.h
4219 ===================================================================
4220 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4221 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/falcon_hash.h 2008-07-17 16:18:07.000000000 +0200
4222 @@ -0,0 +1,58 @@
4223 +/****************************************************************************
4224 + * Driver for Solarflare network controllers -
4225 + * resource management for Xen backend, OpenOnload, etc
4226 + * (including support for SFE4001 10GBT NIC)
4227 + *
4228 + * This file contains API provided by efhw/falcon_hash.c file.
4229 + * Function declared in this file are not exported from the Linux
4230 + * sfc_resource driver.
4231 + *
4232 + * Copyright 2005-2007: Solarflare Communications Inc,
4233 + * 9501 Jeronimo Road, Suite 250,
4234 + * Irvine, CA 92618, USA
4235 + *
4236 + * Developed and maintained by Solarflare Communications:
4237 + * <linux-xen-drivers@solarflare.com>
4238 + * <onload-dev@solarflare.com>
4239 + *
4240 + * Certain parts of the driver were implemented by
4241 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
4242 + * OKTET Labs Ltd, Russia,
4243 + * http://oktetlabs.ru, <info@oktetlabs.ru>
4244 + * by request of Solarflare Communications
4245 + *
4246 + *
4247 + * This program is free software; you can redistribute it and/or modify it
4248 + * under the terms of the GNU General Public License version 2 as published
4249 + * by the Free Software Foundation, incorporated herein by reference.
4250 + *
4251 + * This program is distributed in the hope that it will be useful,
4252 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4253 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4254 + * GNU General Public License for more details.
4255 + *
4256 + * You should have received a copy of the GNU General Public License
4257 + * along with this program; if not, write to the Free Software
4258 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4259 + ****************************************************************************
4260 + */
4261 +
4262 +#ifndef __CI_EFHW_FALCON_HASH_H__
4263 +#define __CI_EFHW_FALCON_HASH_H__
4264 +
4265 +extern unsigned int
4266 +falcon_hash_get_ip_key(unsigned int src_ip, unsigned int src_port,
4267 + unsigned int dest_ip, unsigned int dest_port,
4268 + int tcp, int full);
4269 +
4270 +extern unsigned int
4271 +falcon_hash_function1(unsigned int key, unsigned int nfilters);
4272 +
4273 +extern unsigned int
4274 +falcon_hash_function2(unsigned int key, unsigned int nfilters);
4275 +
4276 +extern unsigned int
4277 +falcon_hash_iterator(unsigned int hash1, unsigned int hash2,
4278 + unsigned int n_search, unsigned int nfilters);
4279 +
4280 +#endif /* __CI_EFHW_FALCON_HASH_H__ */
4281 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h
4282 ===================================================================
4283 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4284 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h 2008-07-17 16:18:07.000000000 +0200
4285 @@ -0,0 +1,69 @@
4286 +/****************************************************************************
4287 + * Driver for Solarflare network controllers -
4288 + * resource management for Xen backend, OpenOnload, etc
4289 + * (including support for SFE4001 10GBT NIC)
4290 + *
4291 + * This file provides version-independent Linux kernel API for header files
4292 + * with hardware-related definitions (in ci/driver/efab/hardware*).
4293 + * Only kernels >=2.6.9 are supported.
4294 + *
4295 + * Copyright 2005-2007: Solarflare Communications Inc,
4296 + * 9501 Jeronimo Road, Suite 250,
4297 + * Irvine, CA 92618, USA
4298 + *
4299 + * Developed and maintained by Solarflare Communications:
4300 + * <linux-xen-drivers@solarflare.com>
4301 + * <onload-dev@solarflare.com>
4302 + *
4303 + * Certain parts of the driver were implemented by
4304 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
4305 + * OKTET Labs Ltd, Russia,
4306 + * http://oktetlabs.ru, <info@oktetlabs.ru>
4307 + * by request of Solarflare Communications
4308 + *
4309 + *
4310 + * This program is free software; you can redistribute it and/or modify it
4311 + * under the terms of the GNU General Public License version 2 as published
4312 + * by the Free Software Foundation, incorporated herein by reference.
4313 + *
4314 + * This program is distributed in the hope that it will be useful,
4315 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4316 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4317 + * GNU General Public License for more details.
4318 + *
4319 + * You should have received a copy of the GNU General Public License
4320 + * along with this program; if not, write to the Free Software
4321 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4322 + ****************************************************************************
4323 + */
4324 +
4325 +#ifndef __CI_EFHW_HARDWARE_LINUX_H__
4326 +#define __CI_EFHW_HARDWARE_LINUX_H__
4327 +
4328 +#include <linux/io.h>
4329 +
4330 +#ifdef __LITTLE_ENDIAN
4331 +#define EFHW_IS_LITTLE_ENDIAN
4332 +#elif __BIG_ENDIAN
4333 +#define EFHW_IS_BIG_ENDIAN
4334 +#else
4335 +#error Unknown endianness
4336 +#endif
4337 +
4338 +#ifndef readq
4339 +static inline uint64_t __readq(volatile void __iomem *addr)
4340 +{
4341 + return *(volatile uint64_t *)addr;
4342 +}
4343 +#define readq(x) __readq(x)
4344 +#endif
4345 +
4346 +#ifndef writeq
4347 +static inline void __writeq(uint64_t v, volatile void __iomem *addr)
4348 +{
4349 + *(volatile uint64_t *)addr = v;
4350 +}
4351 +#define writeq(val, addr) __writeq((val), (addr))
4352 +#endif
4353 +
4354 +#endif /* __CI_EFHW_HARDWARE_LINUX_H__ */
4355 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/iopage.h
4356 ===================================================================
4357 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4358 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/iopage.h 2008-07-17 16:18:07.000000000 +0200
4359 @@ -0,0 +1,58 @@
4360 +/****************************************************************************
4361 + * Driver for Solarflare network controllers -
4362 + * resource management for Xen backend, OpenOnload, etc
4363 + * (including support for SFE4001 10GBT NIC)
4364 + *
4365 + * This file contains OS-independent API for allocating iopage types.
4366 + * The implementation of these functions is highly OS-dependent.
4367 + * This file is not designed for use outside of the SFC resource driver.
4368 + *
4369 + * Copyright 2005-2007: Solarflare Communications Inc,
4370 + * 9501 Jeronimo Road, Suite 250,
4371 + * Irvine, CA 92618, USA
4372 + *
4373 + * Developed and maintained by Solarflare Communications:
4374 + * <linux-xen-drivers@solarflare.com>
4375 + * <onload-dev@solarflare.com>
4376 + *
4377 + * Certain parts of the driver were implemented by
4378 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
4379 + * OKTET Labs Ltd, Russia,
4380 + * http://oktetlabs.ru, <info@oktetlabs.ru>
4381 + * by request of Solarflare Communications
4382 + *
4383 + *
4384 + * This program is free software; you can redistribute it and/or modify it
4385 + * under the terms of the GNU General Public License version 2 as published
4386 + * by the Free Software Foundation, incorporated herein by reference.
4387 + *
4388 + * This program is distributed in the hope that it will be useful,
4389 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4390 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4391 + * GNU General Public License for more details.
4392 + *
4393 + * You should have received a copy of the GNU General Public License
4394 + * along with this program; if not, write to the Free Software
4395 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4396 + ****************************************************************************
4397 + */
4398 +
4399 +#ifndef __CI_DRIVER_RESOURCE_IOPAGE_H__
4400 +#define __CI_DRIVER_RESOURCE_IOPAGE_H__
4401 +
4402 +#include <ci/efhw/efhw_types.h>
4403 +
4404 +/*--------------------------------------------------------------------
4405 + *
4406 + * memory allocation
4407 + *
4408 + *--------------------------------------------------------------------*/
4409 +
4410 +extern int efhw_iopage_alloc(struct efhw_nic *, struct efhw_iopage *p);
4411 +extern void efhw_iopage_free(struct efhw_nic *, struct efhw_iopage *p);
4412 +
4413 +extern int efhw_iopages_alloc(struct efhw_nic *, struct efhw_iopages *p,
4414 + unsigned order);
4415 +extern void efhw_iopages_free(struct efhw_nic *, struct efhw_iopages *p);
4416 +
4417 +#endif /* __CI_DRIVER_RESOURCE_IOPAGE_H__ */
4418 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/iopage_types.h
4419 ===================================================================
4420 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4421 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/iopage_types.h 2008-07-17 16:18:07.000000000 +0200
4422 @@ -0,0 +1,190 @@
4423 +/****************************************************************************
4424 + * Driver for Solarflare network controllers -
4425 + * resource management for Xen backend, OpenOnload, etc
4426 + * (including support for SFE4001 10GBT NIC)
4427 + *
4428 + * This file provides struct efhw_page and struct efhw_iopage for Linux
4429 + * kernel.
4430 + *
4431 + * Copyright 2005-2007: Solarflare Communications Inc,
4432 + * 9501 Jeronimo Road, Suite 250,
4433 + * Irvine, CA 92618, USA
4434 + *
4435 + * Developed and maintained by Solarflare Communications:
4436 + * <linux-xen-drivers@solarflare.com>
4437 + * <onload-dev@solarflare.com>
4438 + *
4439 + * Certain parts of the driver were implemented by
4440 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
4441 + * OKTET Labs Ltd, Russia,
4442 + * http://oktetlabs.ru, <info@oktetlabs.ru>
4443 + * by request of Solarflare Communications
4444 + *
4445 + *
4446 + * This program is free software; you can redistribute it and/or modify it
4447 + * under the terms of the GNU General Public License version 2 as published
4448 + * by the Free Software Foundation, incorporated herein by reference.
4449 + *
4450 + * This program is distributed in the hope that it will be useful,
4451 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4452 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4453 + * GNU General Public License for more details.
4454 + *
4455 + * You should have received a copy of the GNU General Public License
4456 + * along with this program; if not, write to the Free Software
4457 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4458 + ****************************************************************************
4459 + */
4460 +
4461 +#ifndef __CI_EFHW_IOPAGE_LINUX_H__
4462 +#define __CI_EFHW_IOPAGE_LINUX_H__
4463 +
4464 +#include <linux/gfp.h>
4465 +#include <linux/hardirq.h>
4466 +#include <linux/errno.h>
4467 +#include <ci/efhw/debug.h>
4468 +
4469 +/*--------------------------------------------------------------------
4470 + *
4471 + * struct efhw_page: A single page of memory. Directly mapped in the
4472 + * driver, and can be mapped to userlevel.
4473 + *
4474 + *--------------------------------------------------------------------*/
4475 +
4476 +struct efhw_page {
4477 + unsigned long kva;
4478 +};
4479 +
4480 +static inline int efhw_page_alloc(struct efhw_page *p)
4481 +{
4482 + p->kva = __get_free_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
4483 + return p->kva ? 0 : -ENOMEM;
4484 +}
4485 +
4486 +static inline int efhw_page_alloc_zeroed(struct efhw_page *p)
4487 +{
4488 + p->kva = get_zeroed_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
4489 + return p->kva ? 0 : -ENOMEM;
4490 +}
4491 +
4492 +static inline void efhw_page_free(struct efhw_page *p)
4493 +{
4494 + free_page(p->kva);
4495 + EFHW_DO_DEBUG(memset(p, 0, sizeof(*p)));
4496 +}
4497 +
4498 +static inline char *efhw_page_ptr(struct efhw_page *p)
4499 +{
4500 + return (char *)p->kva;
4501 +}
4502 +
4503 +static inline unsigned efhw_page_pfn(struct efhw_page *p)
4504 +{
4505 + return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
4506 +}
4507 +
4508 +static inline void efhw_page_mark_invalid(struct efhw_page *p)
4509 +{
4510 + p->kva = 0;
4511 +}
4512 +
4513 +static inline int efhw_page_is_valid(struct efhw_page *p)
4514 +{
4515 + return p->kva != 0;
4516 +}
4517 +
4518 +static inline void efhw_page_init_from_va(struct efhw_page *p, void *va)
4519 +{
4520 + p->kva = (unsigned long)va;
4521 +}
4522 +
4523 +/*--------------------------------------------------------------------
4524 + *
4525 + * struct efhw_iopage: A single page of memory. Directly mapped in the driver,
4526 + * and can be mapped to userlevel. Can also be accessed by the NIC.
4527 + *
4528 + *--------------------------------------------------------------------*/
4529 +
4530 +struct efhw_iopage {
4531 + struct efhw_page p;
4532 + dma_addr_t dma_addr;
4533 +};
4534 +
4535 +static inline dma_addr_t efhw_iopage_dma_addr(struct efhw_iopage *p)
4536 +{
4537 + return p->dma_addr;
4538 +}
4539 +
4540 +#define efhw_iopage_ptr(iop) efhw_page_ptr(&(iop)->p)
4541 +#define efhw_iopage_pfn(iop) efhw_page_pfn(&(iop)->p)
4542 +#define efhw_iopage_mark_invalid(iop) efhw_page_mark_invalid(&(iop)->p)
4543 +#define efhw_iopage_is_valid(iop) efhw_page_is_valid(&(iop)->p)
4544 +
4545 +/*--------------------------------------------------------------------
4546 + *
4547 + * struct efhw_iopages: A set of pages that are contiguous in physical
4548 + * memory. Directly mapped in the driver, and can be mapped to userlevel.
4549 + * Can also be accessed by the NIC.
4550 + *
4551 + * NB. The O/S may be unwilling to allocate many, or even any of these. So
4552 + * only use this type where the NIC really needs a physically contiguous
4553 + * buffer.
4554 + *
4555 + *--------------------------------------------------------------------*/
4556 +
4557 +struct efhw_iopages {
4558 + caddr_t kva;
4559 + unsigned order;
4560 + dma_addr_t dma_addr;
4561 +};
4562 +
4563 +static inline caddr_t efhw_iopages_ptr(struct efhw_iopages *p)
4564 +{
4565 + return p->kva;
4566 +}
4567 +
4568 +static inline unsigned efhw_iopages_pfn(struct efhw_iopages *p)
4569 +{
4570 + return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
4571 +}
4572 +
4573 +static inline dma_addr_t efhw_iopages_dma_addr(struct efhw_iopages *p)
4574 +{
4575 + return p->dma_addr;
4576 +}
4577 +
4578 +static inline unsigned efhw_iopages_size(struct efhw_iopages *p)
4579 +{
4580 + return 1u << (p->order + PAGE_SHIFT);
4581 +}
4582 +
4583 +/* struct efhw_iopage <-> struct efhw_iopages conversions for handling
4584 + * physically contiguous allocations in iobufsets for iSCSI. This allows
4585 + * the essential information about contiguous allocations from
4586 + * efhw_iopages_alloc() to be saved away in the struct efhw_iopage array in
4587 + * an iobufset. (Changing the iobufset resource to use a union type would
4588 + * involve a lot of code changes, and make the iobufset's metadata larger
4589 + * which could be bad as it's supposed to fit into a single page on some
4590 + * platforms.)
4591 + */
4592 +static inline void
4593 +efhw_iopage_init_from_iopages(struct efhw_iopage *iopage,
4594 + struct efhw_iopages *iopages, unsigned pageno)
4595 +{
4596 + iopage->p.kva = ((unsigned long)efhw_iopages_ptr(iopages))
4597 + + (pageno * PAGE_SIZE);
4598 + iopage->dma_addr = efhw_iopages_dma_addr(iopages) +
4599 + (pageno * PAGE_SIZE);
4600 +}
4601 +
4602 +static inline void
4603 +efhw_iopages_init_from_iopage(struct efhw_iopages *iopages,
4604 + struct efhw_iopage *iopage, unsigned order)
4605 +{
4606 + iopages->kva = (caddr_t) efhw_iopage_ptr(iopage);
4607 + EFHW_ASSERT(iopages->kva);
4608 + iopages->order = order;
4609 + iopages->dma_addr = efhw_iopage_dma_addr(iopage);
4610 +}
4611 +
4612 +#endif /* __CI_EFHW_IOPAGE_LINUX_H__ */
4613 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/nic.h
4614 ===================================================================
4615 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4616 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/nic.h 2008-07-17 16:18:07.000000000 +0200
4617 @@ -0,0 +1,62 @@
4618 +/****************************************************************************
4619 + * Driver for Solarflare network controllers -
4620 + * resource management for Xen backend, OpenOnload, etc
4621 + * (including support for SFE4001 10GBT NIC)
4622 + *
4623 + * This file contains API provided by efhw/nic.c file. This file is not
4624 + * designed for use outside of the SFC resource driver.
4625 + *
4626 + * Copyright 2005-2007: Solarflare Communications Inc,
4627 + * 9501 Jeronimo Road, Suite 250,
4628 + * Irvine, CA 92618, USA
4629 + *
4630 + * Developed and maintained by Solarflare Communications:
4631 + * <linux-xen-drivers@solarflare.com>
4632 + * <onload-dev@solarflare.com>
4633 + *
4634 + * Certain parts of the driver were implemented by
4635 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
4636 + * OKTET Labs Ltd, Russia,
4637 + * http://oktetlabs.ru, <info@oktetlabs.ru>
4638 + * by request of Solarflare Communications
4639 + *
4640 + *
4641 + * This program is free software; you can redistribute it and/or modify it
4642 + * under the terms of the GNU General Public License version 2 as published
4643 + * by the Free Software Foundation, incorporated herein by reference.
4644 + *
4645 + * This program is distributed in the hope that it will be useful,
4646 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4647 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4648 + * GNU General Public License for more details.
4649 + *
4650 + * You should have received a copy of the GNU General Public License
4651 + * along with this program; if not, write to the Free Software
4652 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4653 + ****************************************************************************
4654 + */
4655 +
4656 +#ifndef __CI_EFHW_NIC_H__
4657 +#define __CI_EFHW_NIC_H__
4658 +
4659 +#include <ci/efhw/efhw_types.h>
4660 +#include <ci/efhw/public.h>
4661 +
4662 +
4663 +/* Convert PCI info to device type. Returns false when device is not
4664 + * recognised.
4665 + */
4666 +extern int efhw_device_type_init(struct efhw_device_type *dt,
4667 + int vendor_id, int device_id, int revision);
4668 +
4669 +/* Initialise fields that do not involve touching hardware. */
4670 +extern void efhw_nic_init(struct efhw_nic *nic, unsigned flags,
4671 + unsigned options, struct efhw_device_type dev_type);
4672 +
4673 +/*! Destruct NIC resources */
4674 +extern void efhw_nic_dtor(struct efhw_nic *nic);
4675 +
4676 +/*! Shutdown interrupts */
4677 +extern void efhw_nic_close_interrupts(struct efhw_nic *nic);
4678 +
4679 +#endif /* __CI_EFHW_NIC_H__ */
4680 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/public.h
4681 ===================================================================
4682 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4683 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/public.h 2008-07-17 16:18:07.000000000 +0200
4684 @@ -0,0 +1,104 @@
4685 +/****************************************************************************
4686 + * Driver for Solarflare network controllers -
4687 + * resource management for Xen backend, OpenOnload, etc
4688 + * (including support for SFE4001 10GBT NIC)
4689 + *
4690 + * This file provides public API of efhw library exported from the SFC
4691 + * resource driver.
4692 + *
4693 + * Copyright 2005-2007: Solarflare Communications Inc,
4694 + * 9501 Jeronimo Road, Suite 250,
4695 + * Irvine, CA 92618, USA
4696 + *
4697 + * Developed and maintained by Solarflare Communications:
4698 + * <linux-xen-drivers@solarflare.com>
4699 + * <onload-dev@solarflare.com>
4700 + *
4701 + * Certain parts of the driver were implemented by
4702 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
4703 + * OKTET Labs Ltd, Russia,
4704 + * http://oktetlabs.ru, <info@oktetlabs.ru>
4705 + * by request of Solarflare Communications
4706 + *
4707 + *
4708 + * This program is free software; you can redistribute it and/or modify it
4709 + * under the terms of the GNU General Public License version 2 as published
4710 + * by the Free Software Foundation, incorporated herein by reference.
4711 + *
4712 + * This program is distributed in the hope that it will be useful,
4713 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4714 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4715 + * GNU General Public License for more details.
4716 + *
4717 + * You should have received a copy of the GNU General Public License
4718 + * along with this program; if not, write to the Free Software
4719 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4720 + ****************************************************************************
4721 + */
4722 +
4723 +#ifndef __CI_EFHW_PUBLIC_H__
4724 +#define __CI_EFHW_PUBLIC_H__
4725 +
4726 +#include <ci/efhw/common.h>
4727 +#include <ci/efhw/efhw_types.h>
4728 +
4729 +/*! Returns true if we have some EtherFabric functional units -
4730 + whether configured or not */
4731 +static inline int efhw_nic_have_functional_units(struct efhw_nic *nic)
4732 +{
4733 + return nic->efhw_func != 0;
4734 +}
4735 +
4736 +/*! Returns true if the EtherFabric functional units have been configured */
4737 +static inline int efhw_nic_have_hw(struct efhw_nic *nic)
4738 +{
4739 + return efhw_nic_have_functional_units(nic) && (EFHW_KVA(nic) != 0);
4740 +}
4741 +
4742 +/*! Helper function to allocate the iobuffer needed by an eventq
4743 + * - it ensures the eventq has the correct alignment for the NIC
4744 + *
4745 + * \param rm Event-queue resource manager
4746 + * \param instance Event-queue instance (index)
4747 + * \param buf_bytes Requested size of eventq
4748 + * \return < 0 if iobuffer allocation fails
4749 + */
4750 +int efhw_nic_event_queue_alloc_iobuffer(struct efhw_nic *nic,
4751 + struct eventq_resource_hardware *h,
4752 + int evq_instance, unsigned buf_bytes);
4753 +
4754 +extern void falcon_nic_set_rx_usr_buf_size(struct efhw_nic *,
4755 + int rx_usr_buf_size);
4756 +
4757 +/*! Get RX filter search limits from RX_FILTER_CTL_REG.
4758 + * use_raw_values = 0 to get actual depth of search, or 1 to get raw values
4759 + * from register.
4760 + */
4761 +extern void
4762 +falcon_nic_get_rx_filter_search_limits(struct efhw_nic *nic,
4763 + struct efhw_filter_search_limits *lim,
4764 + int use_raw_values);
4765 +
4766 +/*! Set RX filter search limits in RX_FILTER_CTL_REG.
4767 + * use_raw_values = 0 if specifying actual depth of search, or 1 if specifying
4768 + * raw values to write to the register.
4769 + */
4770 +extern void
4771 +falcon_nic_set_rx_filter_search_limits(struct efhw_nic *nic,
4772 + struct efhw_filter_search_limits *lim,
4773 + int use_raw_values);
4774 +
4775 +
4776 +/*! Legacy RX IP filter search depth control interface */
4777 +extern void
4778 +falcon_nic_rx_filter_ctl_set(struct efhw_nic *nic, uint32_t tcp_full,
4779 + uint32_t tcp_wild,
4780 + uint32_t udp_full, uint32_t udp_wild);
4781 +
4782 +/*! Legacy RX IP filter search depth control interface */
4783 +extern void
4784 +falcon_nic_rx_filter_ctl_get(struct efhw_nic *nic, uint32_t *tcp_full,
4785 + uint32_t *tcp_wild,
4786 + uint32_t *udp_full, uint32_t *udp_wild);
4787 +
4788 +#endif /* __CI_EFHW_PUBLIC_H__ */
4789 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/sysdep.h
4790 ===================================================================
4791 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4792 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/sysdep.h 2008-07-17 16:18:07.000000000 +0200
4793 @@ -0,0 +1,55 @@
4794 +/****************************************************************************
4795 + * Driver for Solarflare network controllers -
4796 + * resource management for Xen backend, OpenOnload, etc
4797 + * (including support for SFE4001 10GBT NIC)
4798 + *
4799 + * This file provides version-independent Linux kernel API for efhw library.
4800 + * Only kernels >=2.6.9 are supported.
4801 + *
4802 + * Copyright 2005-2007: Solarflare Communications Inc,
4803 + * 9501 Jeronimo Road, Suite 250,
4804 + * Irvine, CA 92618, USA
4805 + *
4806 + * Developed and maintained by Solarflare Communications:
4807 + * <linux-xen-drivers@solarflare.com>
4808 + * <onload-dev@solarflare.com>
4809 + *
4810 + * Certain parts of the driver were implemented by
4811 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
4812 + * OKTET Labs Ltd, Russia,
4813 + * http://oktetlabs.ru, <info@oktetlabs.ru>
4814 + * by request of Solarflare Communications
4815 + *
4816 + *
4817 + * This program is free software; you can redistribute it and/or modify it
4818 + * under the terms of the GNU General Public License version 2 as published
4819 + * by the Free Software Foundation, incorporated herein by reference.
4820 + *
4821 + * This program is distributed in the hope that it will be useful,
4822 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4823 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4824 + * GNU General Public License for more details.
4825 + *
4826 + * You should have received a copy of the GNU General Public License
4827 + * along with this program; if not, write to the Free Software
4828 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4829 + ****************************************************************************
4830 + */
4831 +
4832 +#ifndef __CI_EFHW_SYSDEP_LINUX_H__
4833 +#define __CI_EFHW_SYSDEP_LINUX_H__
4834 +
4835 +#include <linux/module.h>
4836 +#include <linux/spinlock.h>
4837 +#include <linux/delay.h>
4838 +#include <linux/vmalloc.h>
4839 +#include <linux/if_ether.h>
4840 +
4841 +#include <linux/netdevice.h> /* necessary for etherdevice.h on some kernels */
4842 +#include <linux/etherdevice.h>
4843 +
4844 +typedef unsigned long irq_flags_t;
4845 +
4846 +#define spin_lock_destroy(l_) do {} while (0)
4847 +
4848 +#endif /* __CI_EFHW_SYSDEP_LINUX_H__ */
4849 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/buddy.h
4850 ===================================================================
4851 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4852 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/buddy.h 2008-07-17 16:18:07.000000000 +0200
4853 @@ -0,0 +1,68 @@
4854 +/****************************************************************************
4855 + * Driver for Solarflare network controllers -
4856 + * resource management for Xen backend, OpenOnload, etc
4857 + * (including support for SFE4001 10GBT NIC)
4858 + *
4859 + * This file provides private API for buddy allocator. This API is not
4860 + * designed for use outside of SFC resource driver.
4861 + *
4862 + * Copyright 2005-2007: Solarflare Communications Inc,
4863 + * 9501 Jeronimo Road, Suite 250,
4864 + * Irvine, CA 92618, USA
4865 + *
4866 + * Developed and maintained by Solarflare Communications:
4867 + * <linux-xen-drivers@solarflare.com>
4868 + * <onload-dev@solarflare.com>
4869 + *
4870 + * Certain parts of the driver were implemented by
4871 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
4872 + * OKTET Labs Ltd, Russia,
4873 + * http://oktetlabs.ru, <info@oktetlabs.ru>
4874 + * by request of Solarflare Communications
4875 + *
4876 + *
4877 + * This program is free software; you can redistribute it and/or modify it
4878 + * under the terms of the GNU General Public License version 2 as published
4879 + * by the Free Software Foundation, incorporated herein by reference.
4880 + *
4881 + * This program is distributed in the hope that it will be useful,
4882 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4883 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4884 + * GNU General Public License for more details.
4885 + *
4886 + * You should have received a copy of the GNU General Public License
4887 + * along with this program; if not, write to the Free Software
4888 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4889 + ****************************************************************************
4890 + */
4891 +
4892 +#ifndef __CI_EFRM_BUDDY_H__
4893 +#define __CI_EFRM_BUDDY_H__
4894 +
4895 +#include <ci/efrm/sysdep.h>
4896 +
4897 +/*! Comment? */
4898 +struct efrm_buddy_allocator {
4899 + struct list_head *free_lists; /* array[order+1] */
4900 + struct list_head *links; /* array[1<<order] */
4901 + uint8_t *orders; /* array[1<<order] */
4902 + unsigned order; /*!< total size == (1 << order) */
4903 + /* ?? Consider recording largest available order + for each order the
4904 + ** smallest available order that is big enough.
4905 + */
4906 +};
4907 +
4908 + /*! Returns total size of managed space. */
4909 +static inline unsigned long efrm_buddy_size(struct efrm_buddy_allocator *b)
4910 +{
4911 + return 1ul << b->order;
4912 +}
4913 +
4914 +int efrm_buddy_ctor(struct efrm_buddy_allocator *b, unsigned order);
4915 +void efrm_buddy_dtor(struct efrm_buddy_allocator *b);
4916 +int efrm_buddy_alloc(struct efrm_buddy_allocator *b, unsigned order);
4917 +void efrm_buddy_free(struct efrm_buddy_allocator *b, unsigned addr,
4918 + unsigned order);
4919 +
4920 +
4921 +#endif /* __CI_EFRM_BUDDY_H__ */
4922 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/buffer_table.h
4923 ===================================================================
4924 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4925 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/buffer_table.h 2008-07-17 16:18:07.000000000 +0200
4926 @@ -0,0 +1,81 @@
4927 +/****************************************************************************
4928 + * Driver for Solarflare network controllers -
4929 + * resource management for Xen backend, OpenOnload, etc
4930 + * (including support for SFE4001 10GBT NIC)
4931 + *
4932 + * This file provides private buffer table API. This API is not designed
4933 + * for use outside of SFC resource driver.
4934 + *
4935 + * Copyright 2005-2007: Solarflare Communications Inc,
4936 + * 9501 Jeronimo Road, Suite 250,
4937 + * Irvine, CA 92618, USA
4938 + *
4939 + * Developed and maintained by Solarflare Communications:
4940 + * <linux-xen-drivers@solarflare.com>
4941 + * <onload-dev@solarflare.com>
4942 + *
4943 + * Certain parts of the driver were implemented by
4944 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
4945 + * OKTET Labs Ltd, Russia,
4946 + * http://oktetlabs.ru, <info@oktetlabs.ru>
4947 + * by request of Solarflare Communications
4948 + *
4949 + *
4950 + * This program is free software; you can redistribute it and/or modify it
4951 + * under the terms of the GNU General Public License version 2 as published
4952 + * by the Free Software Foundation, incorporated herein by reference.
4953 + *
4954 + * This program is distributed in the hope that it will be useful,
4955 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4956 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4957 + * GNU General Public License for more details.
4958 + *
4959 + * You should have received a copy of the GNU General Public License
4960 + * along with this program; if not, write to the Free Software
4961 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4962 + ****************************************************************************
4963 + */
4964 +
4965 +#ifndef __CI_EFRM_BUFFER_TABLE_H__
4966 +#define __CI_EFRM_BUFFER_TABLE_H__
4967 +
4968 +#include <ci/efhw/efhw_types.h>
4969 +
4970 +/*--------------------------------------------------------------------
4971 + *
4972 + * NIC's buffer table.
4973 + *
4974 + *--------------------------------------------------------------------*/
4975 +
4976 +/*! Managed interface. */
4977 +
4978 +/*! construct a managed buffer table object, allocated over a region of
4979 + * the NICs buffer table space
4980 + */
4981 +extern int efrm_buffer_table_ctor(unsigned low, unsigned high);
4982 +/*! destructor for above */
4983 +extern void efrm_buffer_table_dtor(void);
4984 +
4985 +/*! allocate a contiguous region of buffer table space */
4986 +extern int efrm_buffer_table_alloc(unsigned order,
4987 + struct efhw_buffer_table_allocation *a);
4988 +
4989 +
4990 +/*--------------------------------------------------------------------
4991 + *
4992 + * buffer table operations through the HW independent API
4993 + *
4994 + *--------------------------------------------------------------------*/
4995 +
4996 +/*! free a previously allocated region of buffer table space */
4997 +extern void efrm_buffer_table_free(struct efhw_buffer_table_allocation *a);
4998 +
4999 +/*! commit the update of a buffer table entry to every NIC */
5000 +extern void efrm_buffer_table_commit(void);
5001 +
5002 +extern void efrm_buffer_table_set(struct efhw_buffer_table_allocation *,
5003 + struct efhw_nic *,
5004 + unsigned i, dma_addr_t dma_addr, int owner);
5005 +
5006 +
5007 +#endif /* __CI_EFRM_BUFFER_TABLE_H__ */
5008 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/debug.h
5009 ===================================================================
5010 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5011 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/debug.h 2008-07-17 16:18:07.000000000 +0200
5012 @@ -0,0 +1,78 @@
5013 +/****************************************************************************
5014 + * Driver for Solarflare network controllers -
5015 + * resource management for Xen backend, OpenOnload, etc
5016 + * (including support for SFE4001 10GBT NIC)
5017 + *
5018 + * This file provides debug-related API for efrm library using Linux kernel
5019 + * primitives.
5020 + *
5021 + * Copyright 2005-2007: Solarflare Communications Inc,
5022 + * 9501 Jeronimo Road, Suite 250,
5023 + * Irvine, CA 92618, USA
5024 + *
5025 + * Developed and maintained by Solarflare Communications:
5026 + * <linux-xen-drivers@solarflare.com>
5027 + * <onload-dev@solarflare.com>
5028 + *
5029 + * Certain parts of the driver were implemented by
5030 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
5031 + * OKTET Labs Ltd, Russia,
5032 + * http://oktetlabs.ru, <info@oktetlabs.ru>
5033 + * by request of Solarflare Communications
5034 + *
5035 + *
5036 + * This program is free software; you can redistribute it and/or modify it
5037 + * under the terms of the GNU General Public License version 2 as published
5038 + * by the Free Software Foundation, incorporated herein by reference.
5039 + *
5040 + * This program is distributed in the hope that it will be useful,
5041 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5042 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5043 + * GNU General Public License for more details.
5044 + *
5045 + * You should have received a copy of the GNU General Public License
5046 + * along with this program; if not, write to the Free Software
5047 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
5048 + ****************************************************************************
5049 + */
5050 +
5051 +#ifndef __CI_EFRM_DEBUG_LINUX_H__
5052 +#define __CI_EFRM_DEBUG_LINUX_H__
5053 +
5054 +#define EFRM_PRINTK_PREFIX "[sfc efrm] "
5055 +
5056 +#define EFRM_PRINTK(level, fmt, ...) \
5057 + printk(level EFRM_PRINTK_PREFIX fmt "\n", __VA_ARGS__)
5058 +
5059 +/* Following macros should be used with non-zero format parameters
5060 + * due to __VA_ARGS__ limitations. Use "%s" with __func__ if you can't
5061 + * find better parameters. */
5062 +#define EFRM_ERR(fmt, ...) EFRM_PRINTK(KERN_ERR, fmt, __VA_ARGS__)
5063 +#define EFRM_WARN(fmt, ...) EFRM_PRINTK(KERN_WARNING, fmt, __VA_ARGS__)
5064 +#define EFRM_NOTICE(fmt, ...) EFRM_PRINTK(KERN_NOTICE, fmt, __VA_ARGS__)
5065 +#if !defined(NDEBUG)
5066 +#define EFRM_TRACE(fmt, ...) EFRM_PRINTK(KERN_DEBUG, fmt, __VA_ARGS__)
5067 +#else
5068 +#define EFRM_TRACE(fmt, ...)
5069 +#endif
5070 +
5071 +#ifndef NDEBUG
5072 +#define EFRM_ASSERT(cond) BUG_ON((cond) == 0)
5073 +#define _EFRM_ASSERT(cond, file, line) \
5074 + do { \
5075 + if (unlikely(!(cond))) { \
5076 + EFRM_ERR("assertion \"%s\" failed at %s %d", \
5077 + #cond, file, line); \
5078 + BUG(); \
5079 + } \
5080 + } while (0)
5081 +
5082 +#define EFRM_DO_DEBUG(expr) expr
5083 +#define EFRM_VERIFY_EQ(expr, val) EFRM_ASSERT((expr) == (val))
5084 +#else
5085 +#define EFRM_ASSERT(cond)
5086 +#define EFRM_DO_DEBUG(expr)
5087 +#define EFRM_VERIFY_EQ(expr, val) expr
5088 +#endif
5089 +
5090 +#endif /* __CI_EFRM_DEBUG_LINUX_H__ */
5091 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/driver_private.h
5092 ===================================================================
5093 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5094 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/driver_private.h 2008-07-17 16:18:07.000000000 +0200
5095 @@ -0,0 +1,89 @@
5096 +/****************************************************************************
5097 + * Driver for Solarflare network controllers -
5098 + * resource management for Xen backend, OpenOnload, etc
5099 + * (including support for SFE4001 10GBT NIC)
5100 + *
5101 + * This file provides private API of efrm library to be used from the SFC
5102 + * resource driver.
5103 + *
5104 + * Copyright 2005-2007: Solarflare Communications Inc,
5105 + * 9501 Jeronimo Road, Suite 250,
5106 + * Irvine, CA 92618, USA
5107 + *
5108 + * Developed and maintained by Solarflare Communications:
5109 + * <linux-xen-drivers@solarflare.com>
5110 + * <onload-dev@solarflare.com>
5111 + *
5112 + * Certain parts of the driver were implemented by
5113 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
5114 + * OKTET Labs Ltd, Russia,
5115 + * http://oktetlabs.ru, <info@oktetlabs.ru>
5116 + * by request of Solarflare Communications
5117 + *
5118 + *
5119 + * This program is free software; you can redistribute it and/or modify it
5120 + * under the terms of the GNU General Public License version 2 as published
5121 + * by the Free Software Foundation, incorporated herein by reference.
5122 + *
5123 + * This program is distributed in the hope that it will be useful,
5124 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5125 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5126 + * GNU General Public License for more details.
5127 + *
5128 + * You should have received a copy of the GNU General Public License
5129 + * along with this program; if not, write to the Free Software
5130 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
5131 + ****************************************************************************
5132 + */
5133 +
5134 +#ifndef __CI_EFRM_DRIVER_PRIVATE_H__
5135 +#define __CI_EFRM_DRIVER_PRIVATE_H__
5136 +
5137 +#include <ci/efrm/resource.h>
5138 +#include <ci/efrm/sysdep.h>
5139 +
5140 +/*--------------------------------------------------------------------
5141 + *
5142 + * global variables
5143 + *
5144 + *--------------------------------------------------------------------*/
5145 +
5146 +/* Internal structure for resource driver */
5147 +extern struct efrm_resource_manager *efrm_rm_table[];
5148 +
5149 +/*--------------------------------------------------------------------
5150 + *
5151 + * efrm_nic_table handling
5152 + *
5153 + *--------------------------------------------------------------------*/
5154 +
5155 +struct efrm_nic;
5156 +
5157 +extern void efrm_driver_ctor(void);
5158 +extern void efrm_driver_dtor(void);
5159 +extern int efrm_driver_register_nic(struct efrm_nic *, int nic_index,
5160 + int ifindex);
5161 +extern int efrm_driver_unregister_nic(struct efrm_nic *);
5162 +
5163 +/*--------------------------------------------------------------------
5164 + *
5165 + * create/destroy resource managers
5166 + *
5167 + *--------------------------------------------------------------------*/
5168 +
5169 +struct vi_resource_dimensions {
5170 + unsigned evq_int_min, evq_int_lim;
5171 + unsigned evq_timer_min, evq_timer_lim;
5172 + unsigned rxq_min, rxq_lim;
5173 + unsigned txq_min, txq_lim;
5174 +};
5175 +
5176 +/*! Initialise resources */
5177 +extern int
5178 +efrm_resources_init(const struct vi_resource_dimensions *,
5179 + int buffer_table_min, int buffer_table_lim);
5180 +
5181 +/*! Tear down resources */
5182 +extern void efrm_resources_fini(void);
5183 +
5184 +#endif /* __CI_EFRM_DRIVER_PRIVATE_H__ */
5185 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/efrm_client.h
5186 ===================================================================
5187 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5188 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/efrm_client.h 2008-07-17 16:18:07.000000000 +0200
5189 @@ -0,0 +1,32 @@
5190 +#ifndef __EFRM_CLIENT_H__
5191 +#define __EFRM_CLIENT_H__
5192 +
5193 +
5194 +struct efrm_client;
5195 +
5196 +
5197 +struct efrm_client_callbacks {
5198 + /* Called before device is reset. Callee may block. */
5199 + void (*pre_reset)(struct efrm_client *, void *user_data);
5200 + void (*stop)(struct efrm_client *, void *user_data);
5201 + void (*restart)(struct efrm_client *, void *user_data);
5202 +};
5203 +
5204 +
5205 +#define EFRM_IFINDEX_DEFAULT -1
5206 +
5207 +
5208 +/* NB. Callbacks may be invoked even before this returns. */
5209 +extern int efrm_client_get(int ifindex, struct efrm_client_callbacks *,
5210 + void *user_data, struct efrm_client **client_out);
5211 +extern void efrm_client_put(struct efrm_client *);
5212 +
5213 +extern struct efhw_nic *efrm_client_get_nic(struct efrm_client *);
5214 +
5215 +#if 0
5216 +/* For each resource type... */
5217 +extern void efrm_x_resource_resume(struct x_resource *);
5218 +#endif
5219 +
5220 +
5221 +#endif /* __EFRM_CLIENT_H__ */
5222 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/efrm_nic.h
5223 ===================================================================
5224 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5225 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/efrm_nic.h 2008-07-17 16:18:07.000000000 +0200
5226 @@ -0,0 +1,26 @@
5227 +#ifndef __EFRM_NIC_H__
5228 +#define __EFRM_NIC_H__
5229 +
5230 +#include <ci/efhw/efhw_types.h>
5231 +
5232 +
5233 +struct efrm_nic_per_vi {
5234 + unsigned long state;
5235 + struct vi_resource *vi;
5236 +};
5237 +
5238 +
5239 +struct efrm_nic {
5240 + struct efhw_nic efhw_nic;
5241 + struct list_head link;
5242 + struct list_head clients;
5243 + struct efrm_nic_per_vi *vis;
5244 +};
5245 +
5246 +
5247 +#define efrm_nic(_efhw_nic) \
5248 + container_of(_efhw_nic, struct efrm_nic, efhw_nic)
5249 +
5250 +
5251 +
5252 +#endif /* __EFRM_NIC_H__ */
5253 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/filter.h
5254 ===================================================================
5255 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5256 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/filter.h 2008-07-17 16:18:07.000000000 +0200
5257 @@ -0,0 +1,122 @@
5258 +/****************************************************************************
5259 + * Driver for Solarflare network controllers -
5260 + * resource management for Xen backend, OpenOnload, etc
5261 + * (including support for SFE4001 10GBT NIC)
5262 + *
5263 + * This file provides public API for filter resource.
5264 + *
5265 + * Copyright 2005-2007: Solarflare Communications Inc,
5266 + * 9501 Jeronimo Road, Suite 250,
5267 + * Irvine, CA 92618, USA
5268 + *
5269 + * Developed and maintained by Solarflare Communications:
5270 + * <linux-xen-drivers@solarflare.com>
5271 + * <onload-dev@solarflare.com>
5272 + *
5273 + * Certain parts of the driver were implemented by
5274 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
5275 + * OKTET Labs Ltd, Russia,
5276 + * http://oktetlabs.ru, <info@oktetlabs.ru>
5277 + * by request of Solarflare Communications
5278 + *
5279 + *
5280 + * This program is free software; you can redistribute it and/or modify it
5281 + * under the terms of the GNU General Public License version 2 as published
5282 + * by the Free Software Foundation, incorporated herein by reference.
5283 + *
5284 + * This program is distributed in the hope that it will be useful,
5285 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5286 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5287 + * GNU General Public License for more details.
5288 + *
5289 + * You should have received a copy of the GNU General Public License
5290 + * along with this program; if not, write to the Free Software
5291 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
5292 + ****************************************************************************
5293 + */
5294 +
5295 +#ifndef __CI_EFRM_FILTER_H__
5296 +#define __CI_EFRM_FILTER_H__
5297 +
5298 +#include <ci/efrm/resource.h>
5299 +#include <ci/efhw/common.h>
5300 +
5301 +
5302 +struct filter_resource;
5303 +struct vi_resource;
5304 +struct efrm_client;
5305 +
5306 +
5307 +/*!
5308 + * Allocate filter resource.
5309 + *
5310 + * \param vi_parent VI resource to use as parent. The function takes
5311 + * reference to the VI resource on success.
5312 + * \param frs_out pointer to return the new filter resource
5313 + *
5314 + * \return status code; if non-zero, frs_out is unchanged
5315 + */
5316 +extern int
5317 +efrm_filter_resource_alloc(struct vi_resource *vi_parent,
5318 + struct filter_resource **frs_out);
5319 +
5320 +extern void
5321 +efrm_filter_resource_release(struct filter_resource *);
5322 +
5323 +
5324 +extern int efrm_filter_resource_clear(struct filter_resource *frs);
5325 +
5326 +extern int __efrm_filter_resource_set(struct filter_resource *frs, int type,
5327 + unsigned saddr_be32, uint16_t sport_be16,
5328 + unsigned daddr_be32, uint16_t dport_be16);
5329 +
5330 +static inline int
5331 +efrm_filter_resource_tcp_set(struct filter_resource *frs,
5332 + unsigned saddr, uint16_t sport,
5333 + unsigned daddr, uint16_t dport)
5334 +{
5335 + int type;
5336 +
5337 + EFRM_ASSERT((saddr && sport) || (!saddr && !sport));
5338 +
5339 + type =
5340 + saddr ? EFHW_IP_FILTER_TYPE_TCP_FULL :
5341 + EFHW_IP_FILTER_TYPE_TCP_WILDCARD;
5342 +
5343 + return __efrm_filter_resource_set(frs, type,
5344 + saddr, sport, daddr, dport);
5345 +}
5346 +
5347 +static inline int
5348 +efrm_filter_resource_udp_set(struct filter_resource *frs,
5349 + unsigned saddr, uint16_t sport,
5350 + unsigned daddr, uint16_t dport)
5351 +{
5352 + int type;
5353 +
5354 + EFRM_ASSERT((saddr && sport) || (!saddr && !sport));
5355 +
5356 + type =
5357 + saddr ? EFHW_IP_FILTER_TYPE_UDP_FULL :
5358 + EFHW_IP_FILTER_TYPE_UDP_WILDCARD;
5359 +
5360 + return __efrm_filter_resource_set(frs,
5361 + type, saddr, sport, daddr, dport);
5362 +}
5363 +
5364 +
5365 +extern int
5366 +efrm_filter_resource_instance(struct filter_resource *);
5367 +
5368 +extern struct efrm_resource *
5369 +efrm_filter_resource_to_resource(struct filter_resource *);
5370 +
5371 +extern struct filter_resource *
5372 +efrm_filter_resource_from_resource(struct efrm_resource *);
5373 +
5374 +extern void
5375 +efrm_filter_resource_free(struct filter_resource *);
5376 +
5377 +
5378 +#endif /* __CI_EFRM_FILTER_H__ */
5379 +/*! \cidoxg_end */
5380 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/iobufset.h
5381 ===================================================================
5382 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5383 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/iobufset.h 2008-07-17 16:18:07.000000000 +0200
5384 @@ -0,0 +1,110 @@
5385 +/****************************************************************************
5386 + * Driver for Solarflare network controllers -
5387 + * resource management for Xen backend, OpenOnload, etc
5388 + * (including support for SFE4001 10GBT NIC)
5389 + *
5390 + * This file provides public API for iobufset resource.
5391 + *
5392 + * Copyright 2005-2007: Solarflare Communications Inc,
5393 + * 9501 Jeronimo Road, Suite 250,
5394 + * Irvine, CA 92618, USA
5395 + *
5396 + * Developed and maintained by Solarflare Communications:
5397 + * <linux-xen-drivers@solarflare.com>
5398 + * <onload-dev@solarflare.com>
5399 + *
5400 + * Certain parts of the driver were implemented by
5401 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
5402 + * OKTET Labs Ltd, Russia,
5403 + * http://oktetlabs.ru, <info@oktetlabs.ru>
5404 + * by request of Solarflare Communications
5405 + *
5406 + *
5407 + * This program is free software; you can redistribute it and/or modify it
5408 + * under the terms of the GNU General Public License version 2 as published
5409 + * by the Free Software Foundation, incorporated herein by reference.
5410 + *
5411 + * This program is distributed in the hope that it will be useful,
5412 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5413 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5414 + * GNU General Public License for more details.
5415 + *
5416 + * You should have received a copy of the GNU General Public License
5417 + * along with this program; if not, write to the Free Software
5418 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
5419 + ****************************************************************************
5420 + */
5421 +
5422 +#ifndef __CI_EFRM_IOBUFSET_H__
5423 +#define __CI_EFRM_IOBUFSET_H__
5424 +
5425 +#include <ci/efrm/vi_resource.h>
5426 +
5427 +/*! Iobufset resource structture.
5428 + * Users should not access the structure fields directly, but use the API
5429 + * below.
5430 + * However, this structure should not be moved out of public headers,
5431 + * because part of API (ex. efrm_iobufset_dma_addr function) is inline and
5432 + * is used in the fast-path code.
5433 + */
5434 +struct iobufset_resource {
5435 + struct efrm_resource rs;
5436 + struct vi_resource *evq;
5437 + struct iobufset_resource *linked;
5438 + struct efhw_buffer_table_allocation buf_tbl_alloc;
5439 + unsigned int n_bufs;
5440 + unsigned int pages_per_contiguous_chunk;
5441 + unsigned chunk_order;
5442 + struct efhw_iopage bufs[1];
5443 + /*!< up to n_bufs can follow this, so this must be the last member */
5444 +};
5445 +
5446 +#define iobufset_resource(rs1) \
5447 + container_of((rs1), struct iobufset_resource, rs)
5448 +
5449 +/*!
5450 + * Allocate iobufset resource.
5451 + *
5452 + * \param vi VI that "owns" these buffers. Grabs a reference
5453 + * on success.
5454 + * \param linked Uses memory from an existing iobufset. Grabs a
5455 + * reference on success.
5456 + * \param iobrs_out pointer to return the new filter resource
5457 + *
5458 + * \return status code; if non-zero, frs_out is unchanged
5459 + */
5460 +extern int
5461 +efrm_iobufset_resource_alloc(int32_t n_pages,
5462 + int32_t pages_per_contiguous_chunk,
5463 + struct vi_resource *vi,
5464 + struct iobufset_resource *linked,
5465 + bool phys_addr_mode,
5466 + struct iobufset_resource **iobrs_out);
5467 +
5468 +extern void efrm_iobufset_resource_free(struct iobufset_resource *);
5469 +extern void efrm_iobufset_resource_release(struct iobufset_resource *);
5470 +
5471 +static inline char *
5472 +efrm_iobufset_ptr(struct iobufset_resource *rs, unsigned offs)
5473 +{
5474 + EFRM_ASSERT(offs < (unsigned)(rs->n_bufs << PAGE_SHIFT));
5475 + return efhw_iopage_ptr(&rs->bufs[offs >> PAGE_SHIFT])
5476 + + (offs & (PAGE_SIZE - 1));
5477 +}
5478 +
5479 +static inline char *efrm_iobufset_page_ptr(struct iobufset_resource *rs,
5480 + unsigned page_i)
5481 +{
5482 + EFRM_ASSERT(page_i < (unsigned)rs->n_bufs);
5483 + return efhw_iopage_ptr(&rs->bufs[page_i]);
5484 +}
5485 +
5486 +static inline dma_addr_t
5487 +efrm_iobufset_dma_addr(struct iobufset_resource *rs, unsigned offs)
5488 +{
5489 + EFRM_ASSERT(offs < (unsigned)(rs->n_bufs << PAGE_SHIFT));
5490 + return efhw_iopage_dma_addr(&rs->bufs[offs >> PAGE_SHIFT])
5491 + + (offs & (PAGE_SIZE - 1));
5492 +}
5493 +
5494 +#endif /* __CI_EFRM_IOBUFSET_H__ */
5495 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/nic_set.h
5496 ===================================================================
5497 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5498 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/nic_set.h 2008-07-17 16:18:07.000000000 +0200
5499 @@ -0,0 +1,104 @@
5500 +/****************************************************************************
5501 + * Driver for Solarflare network controllers -
5502 + * resource management for Xen backend, OpenOnload, etc
5503 + * (including support for SFE4001 10GBT NIC)
5504 + *
5505 + * This file provides public API for NIC sets.
5506 + *
5507 + * Copyright 2005-2007: Solarflare Communications Inc,
5508 + * 9501 Jeronimo Road, Suite 250,
5509 + * Irvine, CA 92618, USA
5510 + *
5511 + * Developed and maintained by Solarflare Communications:
5512 + * <linux-xen-drivers@solarflare.com>
5513 + * <onload-dev@solarflare.com>
5514 + *
5515 + * Certain parts of the driver were implemented by
5516 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
5517 + * OKTET Labs Ltd, Russia,
5518 + * http://oktetlabs.ru, <info@oktetlabs.ru>
5519 + * by request of Solarflare Communications
5520 + *
5521 + *
5522 + * This program is free software; you can redistribute it and/or modify it
5523 + * under the terms of the GNU General Public License version 2 as published
5524 + * by the Free Software Foundation, incorporated herein by reference.
5525 + *
5526 + * This program is distributed in the hope that it will be useful,
5527 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5528 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5529 + * GNU General Public License for more details.
5530 + *
5531 + * You should have received a copy of the GNU General Public License
5532 + * along with this program; if not, write to the Free Software
5533 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
5534 + ****************************************************************************
5535 + */
5536 +
5537 +#ifndef __CI_EFRM_NIC_SET_H__
5538 +#define __CI_EFRM_NIC_SET_H__
5539 +
5540 +#include <ci/efrm/debug.h>
5541 +#include <ci/efhw/common_sysdep.h>
5542 +#include <ci/efhw/efhw_config.h>
5543 +
5544 +/*--------------------------------------------------------------------
5545 + *
5546 + * efrm_nic_set_t - tracks which NICs something has been done on
5547 + *
5548 + *--------------------------------------------------------------------*/
5549 +
5550 +/* Internal suructure of efrm_nic_set_t should not be referenced outside of
5551 + * this file. Add a new accessor if you should do it. */
5552 +typedef struct {
5553 + uint32_t nics;
5554 +} efrm_nic_set_t;
5555 +
5556 +#if EFHW_MAX_NR_DEVS > 32
5557 +#error change efrm_nic_set to handle EFHW_MAX_NR_DEVS number of devices
5558 +#endif
5559 +
5560 +static inline bool
5561 +efrm_nic_set_read(const efrm_nic_set_t *nic_set, unsigned index)
5562 +{
5563 + EFRM_ASSERT(nic_set);
5564 + EFRM_ASSERT(index < EFHW_MAX_NR_DEVS && index < 32);
5565 + return (nic_set->nics & (1 << index)) ? true : false;
5566 +}
5567 +
5568 +static inline void
5569 +efrm_nic_set_write(efrm_nic_set_t *nic_set, unsigned index, bool value)
5570 +{
5571 + EFRM_ASSERT(nic_set);
5572 + EFRM_ASSERT(index < EFHW_MAX_NR_DEVS && index < 32);
5573 + EFRM_ASSERT(value == false || value == true);
5574 + nic_set->nics = (nic_set->nics & (~(1 << index))) + (value << index);
5575 +}
5576 +
5577 +static inline void efrm_nic_set_clear(efrm_nic_set_t *nic_set)
5578 +{
5579 + nic_set->nics = 0;
5580 +}
5581 +
5582 +static inline void efrm_nic_set_all(efrm_nic_set_t *nic_set)
5583 +{
5584 + nic_set->nics = 0xffffffff;
5585 +}
5586 +
5587 +static inline bool efrm_nic_set_is_all_clear(efrm_nic_set_t *nic_set)
5588 +{
5589 + return nic_set->nics == 0 ? true : false;
5590 +}
5591 +
5592 +#define EFRM_NIC_SET_FMT "%x"
5593 +
5594 +static inline uint32_t efrm_nic_set_pri_arg(efrm_nic_set_t *nic_set)
5595 +{
5596 + return nic_set->nics;
5597 +}
5598 +
5599 +#define EFRM_FOR_EACH_NIC_INDEX_IN_SET(_set, _nic_i) \
5600 + for ((_nic_i) = 0; (_nic_i) < EFHW_MAX_NR_DEVS; ++(_nic_i)) \
5601 + if (efrm_nic_set_read((_set), (_nic_i)))
5602 +
5603 +#endif /* __CI_EFRM_NIC_SET_H__ */
5604 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/nic_table.h
5605 ===================================================================
5606 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5607 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/nic_table.h 2008-07-17 16:18:07.000000000 +0200
5608 @@ -0,0 +1,98 @@
5609 +/****************************************************************************
5610 + * Driver for Solarflare network controllers -
5611 + * resource management for Xen backend, OpenOnload, etc
5612 + * (including support for SFE4001 10GBT NIC)
5613 + *
5614 + * This file provides public API for NIC table.
5615 + *
5616 + * Copyright 2005-2007: Solarflare Communications Inc,
5617 + * 9501 Jeronimo Road, Suite 250,
5618 + * Irvine, CA 92618, USA
5619 + *
5620 + * Developed and maintained by Solarflare Communications:
5621 + * <linux-xen-drivers@solarflare.com>
5622 + * <onload-dev@solarflare.com>
5623 + *
5624 + * Certain parts of the driver were implemented by
5625 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
5626 + * OKTET Labs Ltd, Russia,
5627 + * http://oktetlabs.ru, <info@oktetlabs.ru>
5628 + * by request of Solarflare Communications
5629 + *
5630 + *
5631 + * This program is free software; you can redistribute it and/or modify it
5632 + * under the terms of the GNU General Public License version 2 as published
5633 + * by the Free Software Foundation, incorporated herein by reference.
5634 + *
5635 + * This program is distributed in the hope that it will be useful,
5636 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5637 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5638 + * GNU General Public License for more details.
5639 + *
5640 + * You should have received a copy of the GNU General Public License
5641 + * along with this program; if not, write to the Free Software
5642 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
5643 + ****************************************************************************
5644 + */
5645 +
5646 +#ifndef __CI_EFRM_NIC_TABLE_H__
5647 +#define __CI_EFRM_NIC_TABLE_H__
5648 +
5649 +#include <ci/efhw/efhw_types.h>
5650 +#include <ci/efrm/sysdep.h>
5651 +
5652 +/*--------------------------------------------------------------------
5653 + *
5654 + * struct efrm_nic_table - top level driver object keeping all NICs -
5655 + * implemented in driver_object.c
5656 + *
5657 + *--------------------------------------------------------------------*/
5658 +
5659 +/*! Comment? */
5660 +struct efrm_nic_table {
5661 + /*! nics attached to this driver */
5662 + struct efhw_nic *nic[EFHW_MAX_NR_DEVS];
5663 + /*! pointer to an arbitrary struct efhw_nic if one exists;
5664 + * for code which does not care which NIC it wants but
5665 + * still needs one. Note you cannot assume nic[0] exists. */
5666 + struct efhw_nic *a_nic;
5667 + uint32_t nic_count; /*!< number of nics attached to this driver */
5668 + spinlock_t lock; /*!< lock for table modifications */
5669 + atomic_t ref_count; /*!< refcount for users of nic table */
5670 +};
5671 +
5672 +/* Resource driver structures used by other drivers as well */
5673 +extern struct efrm_nic_table *efrm_nic_tablep;
5674 +
5675 +static inline void efrm_nic_table_hold(void)
5676 +{
5677 + atomic_inc(&efrm_nic_tablep->ref_count);
5678 +}
5679 +
5680 +static inline void efrm_nic_table_rele(void)
5681 +{
5682 + atomic_dec(&efrm_nic_tablep->ref_count);
5683 +}
5684 +
5685 +static inline int efrm_nic_table_held(void)
5686 +{
5687 + return atomic_read(&efrm_nic_tablep->ref_count) != 0;
5688 +}
5689 +
5690 +/* Run code block _x multiple times with variable nic set to each
5691 + * registered NIC in turn.
5692 + * DO NOT "break" out of this loop early. */
5693 +#define EFRM_FOR_EACH_NIC(_nic_i, _nic) \
5694 + for ((_nic_i) = (efrm_nic_table_hold(), 0); \
5695 + (_nic_i) < EFHW_MAX_NR_DEVS || (efrm_nic_table_rele(), 0); \
5696 + (_nic_i)++) \
5697 + if (((_nic) = efrm_nic_tablep->nic[_nic_i]))
5698 +
5699 +#define EFRM_FOR_EACH_NIC_IN_SET(_set, _i, _nic) \
5700 + for ((_i) = (efrm_nic_table_hold(), 0); \
5701 + (_i) < EFHW_MAX_NR_DEVS || (efrm_nic_table_rele(), 0); \
5702 + ++(_i)) \
5703 + if (((_nic) = efrm_nic_tablep->nic[_i]) && \
5704 + efrm_nic_set_read((_set), (_i)))
5705 +
5706 +#endif /* __CI_EFRM_NIC_TABLE_H__ */
5707 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/private.h
5708 ===================================================================
5709 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5710 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/private.h 2008-07-17 16:18:07.000000000 +0200
5711 @@ -0,0 +1,118 @@
5712 +/****************************************************************************
5713 + * Driver for Solarflare network controllers -
5714 + * resource management for Xen backend, OpenOnload, etc
5715 + * (including support for SFE4001 10GBT NIC)
5716 + *
5717 + * This file provides private API of efrm library -- resource handling.
5718 + * This API is not designed for use outside of SFC resource driver.
5719 + *
5720 + * Copyright 2005-2007: Solarflare Communications Inc,
5721 + * 9501 Jeronimo Road, Suite 250,
5722 + * Irvine, CA 92618, USA
5723 + *
5724 + * Developed and maintained by Solarflare Communications:
5725 + * <linux-xen-drivers@solarflare.com>
5726 + * <onload-dev@solarflare.com>
5727 + *
5728 + * Certain parts of the driver were implemented by
5729 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
5730 + * OKTET Labs Ltd, Russia,
5731 + * http://oktetlabs.ru, <info@oktetlabs.ru>
5732 + * by request of Solarflare Communications
5733 + *
5734 + *
5735 + * This program is free software; you can redistribute it and/or modify it
5736 + * under the terms of the GNU General Public License version 2 as published
5737 + * by the Free Software Foundation, incorporated herein by reference.
5738 + *
5739 + * This program is distributed in the hope that it will be useful,
5740 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5741 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5742 + * GNU General Public License for more details.
5743 + *
5744 + * You should have received a copy of the GNU General Public License
5745 + * along with this program; if not, write to the Free Software
5746 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
5747 + ****************************************************************************
5748 + */
5749 +
5750 +#ifndef __CI_EFRM_PRIVATE_H__
5751 +#define __CI_EFRM_PRIVATE_H__
5752 +
5753 +#include <ci/efrm/resource.h>
5754 +#include <ci/efrm/driver_private.h>
5755 +#include <ci/efrm/sysdep.h>
5756 +#include <ci/efrm/debug.h>
5757 +
5758 +/*--------------------------------------------------------------------
5759 + *
5760 + * create resource managers
5761 + *
5762 + *--------------------------------------------------------------------*/
5763 +
5764 +/*! Create a resource manager for various types of resources
5765 + */
5766 +extern int
5767 +efrm_create_iobufset_resource_manager(struct efrm_resource_manager **out);
5768 +
5769 +extern int
5770 +efrm_create_filter_resource_manager(struct efrm_resource_manager **out);
5771 +
5772 +extern int
5773 +efrm_create_vi_resource_manager(struct efrm_resource_manager **out,
5774 + const struct vi_resource_dimensions *);
5775 +
5776 +
5777 +/*--------------------------------------------------------------------
5778 + *
5779 + * Instance pool management
5780 + *
5781 + *--------------------------------------------------------------------*/
5782 +
5783 +/*! Allocate instance pool. Use kfifo_vfree to destroy it. */
5784 +static inline int
5785 +efrm_kfifo_id_ctor(struct kfifo **ids_out,
5786 + unsigned int base, unsigned int limit, spinlock_t *lock)
5787 +{
5788 + unsigned int i;
5789 + struct kfifo *ids;
5790 + unsigned char *buffer;
5791 + unsigned int size = roundup_pow_of_two((limit - base) * sizeof(int));
5792 + EFRM_ASSERT(base <= limit);
5793 + buffer = vmalloc(size);
5794 + ids = kfifo_init(buffer, size, GFP_KERNEL, lock);
5795 + if (IS_ERR(ids))
5796 + return PTR_ERR(ids);
5797 + for (i = base; i < limit; i++)
5798 + EFRM_VERIFY_EQ(__kfifo_put(ids, (unsigned char *)&i,
5799 + sizeof(i)), sizeof(i));
5800 +
5801 + *ids_out = ids;
5802 + return 0;
5803 +}
5804 +
5805 +/*--------------------------------------------------------------------
5806 + *
5807 + * Various private functions
5808 + *
5809 + *--------------------------------------------------------------------*/
5810 +
5811 +/*! Initialize the fields in the provided resource manager memory area
5812 + * \param rm The area of memory to be initialized
5813 + * \param dtor A method to destroy the resource manager
5814 + * \param name A Textual name for the resource manager
5815 + * \param type The type of resource managed
5816 + * \param initial_table_size Initial size of the ID table
5817 + * \param auto_destroy Destroy resource manager on driver onload iff true
5818 + *
5819 + * A default table size is provided if the value 0 is provided.
5820 + */
5821 +extern int
5822 +efrm_resource_manager_ctor(struct efrm_resource_manager *rm,
5823 + void (*dtor)(struct efrm_resource_manager *),
5824 + const char *name, unsigned type);
5825 +
5826 +extern void efrm_resource_manager_dtor(struct efrm_resource_manager *rm);
5827 +
5828 +
5829 +#endif /* __CI_EFRM_PRIVATE_H__ */
5830 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/resource.h
5831 ===================================================================
5832 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5833 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/resource.h 2008-07-17 16:18:07.000000000 +0200
5834 @@ -0,0 +1,119 @@
5835 +/****************************************************************************
5836 + * Driver for Solarflare network controllers -
5837 + * resource management for Xen backend, OpenOnload, etc
5838 + * (including support for SFE4001 10GBT NIC)
5839 + *
5840 + * This file provides public interface of efrm library -- resource handling.
5841 + *
5842 + * Copyright 2005-2007: Solarflare Communications Inc,
5843 + * 9501 Jeronimo Road, Suite 250,
5844 + * Irvine, CA 92618, USA
5845 + *
5846 + * Developed and maintained by Solarflare Communications:
5847 + * <linux-xen-drivers@solarflare.com>
5848 + * <onload-dev@solarflare.com>
5849 + *
5850 + * Certain parts of the driver were implemented by
5851 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
5852 + * OKTET Labs Ltd, Russia,
5853 + * http://oktetlabs.ru, <info@oktetlabs.ru>
5854 + * by request of Solarflare Communications
5855 + *
5856 + *
5857 + * This program is free software; you can redistribute it and/or modify it
5858 + * under the terms of the GNU General Public License version 2 as published
5859 + * by the Free Software Foundation, incorporated herein by reference.
5860 + *
5861 + * This program is distributed in the hope that it will be useful,
5862 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5863 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5864 + * GNU General Public License for more details.
5865 + *
5866 + * You should have received a copy of the GNU General Public License
5867 + * along with this program; if not, write to the Free Software
5868 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
5869 + ****************************************************************************
5870 + */
5871 +
5872 +#ifndef __CI_EFRM_RESOURCE_H__
5873 +#define __CI_EFRM_RESOURCE_H__
5874 +
5875 +/*--------------------------------------------------------------------
5876 + *
5877 + * headers for type dependencies
5878 + *
5879 + *--------------------------------------------------------------------*/
5880 +
5881 +#include <ci/efhw/efhw_types.h>
5882 +#include <ci/efrm/resource_id.h>
5883 +#include <ci/efrm/sysdep.h>
5884 +#include <ci/efhw/common_sysdep.h>
5885 +
5886 +#ifndef __ci_driver__
5887 +#error "Driver-only file"
5888 +#endif
5889 +
5890 +/*--------------------------------------------------------------------
5891 + *
5892 + * struct efrm_resource - represents an allocated resource
5893 + * (eg. pinned pages of memory, or resource on a NIC)
5894 + *
5895 + *--------------------------------------------------------------------*/
5896 +
5897 +/*! Representation of an allocated resource */
5898 +struct efrm_resource {
5899 + int rs_ref_count;
5900 + efrm_resource_handle_t rs_handle;
5901 + struct efrm_client *rs_client;
5902 + struct list_head rs_client_link;
5903 + struct list_head rs_manager_link;
5904 +};
5905 +
5906 +/*--------------------------------------------------------------------
5907 + *
5908 + * managed resource abstraction
5909 + *
5910 + *--------------------------------------------------------------------*/
5911 +
5912 +/*! Factory for resources of a specific type */
5913 +struct efrm_resource_manager {
5914 + const char *rm_name; /*!< human readable only */
5915 + spinlock_t rm_lock;
5916 +#ifndef NDEBUG
5917 + unsigned rm_type;
5918 +#endif
5919 + int rm_resources;
5920 + int rm_resources_hiwat;
5921 + struct list_head rm_resources_list;
5922 + /**
5923 + * Destructor for the resource manager. Other resource managers
5924 + * might be already dead, although the system guarantees that
5925 + * managers are destructed in the order by which they were created
5926 + */
5927 + void (*rm_dtor)(struct efrm_resource_manager *);
5928 +};
5929 +
5930 +#ifdef NDEBUG
5931 +# define EFRM_RESOURCE_ASSERT_VALID(rs, rc_mbz)
5932 +# define EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm)
5933 +#else
5934 +/*! Check validity of resource and report on failure */
5935 +extern void efrm_resource_assert_valid(struct efrm_resource *,
5936 + int rc_may_be_zero,
5937 + const char *file, int line);
5938 +# define EFRM_RESOURCE_ASSERT_VALID(rs, rc_mbz) \
5939 + efrm_resource_assert_valid((rs), (rc_mbz), __FILE__, __LINE__)
5940 +
5941 +/*! Check validity of resource manager and report on failure */
5942 +extern void efrm_resource_manager_assert_valid(struct efrm_resource_manager *,
5943 + const char *file, int line);
5944 +# define EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm) \
5945 + efrm_resource_manager_assert_valid((rm), __FILE__, __LINE__)
5946 +#endif
5947 +
5948 +
5949 +extern void efrm_resource_ref(struct efrm_resource *rs);
5950 +extern int __efrm_resource_release(struct efrm_resource *);
5951 +
5952 +
5953 +#endif /* __CI_EFRM_RESOURCE_H__ */
5954 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/resource_id.h
5955 ===================================================================
5956 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5957 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/resource_id.h 2008-07-17 16:18:07.000000000 +0200
5958 @@ -0,0 +1,104 @@
5959 +/****************************************************************************
5960 + * Driver for Solarflare network controllers -
5961 + * resource management for Xen backend, OpenOnload, etc
5962 + * (including support for SFE4001 10GBT NIC)
5963 + *
5964 + * This file provides public type and definitions resource handle, and the
5965 + * definitions of resource types.
5966 + *
5967 + * Copyright 2005-2007: Solarflare Communications Inc,
5968 + * 9501 Jeronimo Road, Suite 250,
5969 + * Irvine, CA 92618, USA
5970 + *
5971 + * Developed and maintained by Solarflare Communications:
5972 + * <linux-xen-drivers@solarflare.com>
5973 + * <onload-dev@solarflare.com>
5974 + *
5975 + *
5976 + * This program is free software; you can redistribute it and/or modify it
5977 + * under the terms of the GNU General Public License version 2 as published
5978 + * by the Free Software Foundation, incorporated herein by reference.
5979 + *
5980 + * This program is distributed in the hope that it will be useful,
5981 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5982 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5983 + * GNU General Public License for more details.
5984 + *
5985 + * You should have received a copy of the GNU General Public License
5986 + * along with this program; if not, write to the Free Software
5987 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
5988 + ****************************************************************************
5989 + */
5990 +
5991 +#ifndef __CI_DRIVER_EFRM_RESOURCE_ID_H__
5992 +#define __CI_DRIVER_EFRM_RESOURCE_ID_H__
5993 +
5994 +/***********************************************************************
5995 + * Resource handles
5996 + *
5997 + * Resource handles are intended for identifying resources at kernel
5998 + * level, within the context of a particular NIC. particularly because
5999 + * for some resource types, the low 16 bites correspond to hardware
6000 + * IDs. They were historically also used at user level, with a nonce
6001 + * stored in the bits 16 to 27 (inclusive), but that approach is
6002 + * deprecated (but sill alive!).
6003 + *
6004 + * The handle value 0 is used to mean "no resource".
6005 + * Identify resources within the context of a file descriptor at user
6006 + * level.
6007 + ***********************************************************************/
6008 +
6009 +typedef struct {
6010 + uint32_t handle;
6011 +} efrm_resource_handle_t;
6012 +
6013 +/* You may think these following functions should all have
6014 + * _HANDLE_ in their names, but really we are providing an abstract set
6015 + * of methods on a (hypothetical) efrm_resource_t object, with
6016 + * efrm_resource_handle_t being just the reference one holds to access
6017 + * the object (aka "this" or "self").
6018 + */
6019 +
6020 +/* Below I use inline instead of macros where possible in order to get
6021 + * more type checking help from the compiler; hopefully we'll never
6022 + * have to rewrite these to use #define as we've found some horrible
6023 + * compiler on which we cannot make static inline do the Right Thing (tm).
6024 + *
6025 + * For consistency and to avoid pointless change I spell these
6026 + * routines as macro names (CAPTILIZE_UNDERSCORED), which also serves
6027 + * to remind people they are compact and inlined.
6028 + */
6029 +
6030 +#define EFRM_RESOURCE_FMT "[rs:%08x]"
6031 +
6032 +static inline unsigned EFRM_RESOURCE_PRI_ARG(efrm_resource_handle_t h)
6033 +{
6034 + return h.handle;
6035 +}
6036 +
6037 +static inline unsigned EFRM_RESOURCE_INSTANCE(efrm_resource_handle_t h)
6038 +{
6039 + return h.handle & 0x0000ffff;
6040 +}
6041 +
6042 +static inline unsigned EFRM_RESOURCE_TYPE(efrm_resource_handle_t h)
6043 +{
6044 + return (h.handle & 0xf0000000) >> 28;
6045 +}
6046 +
6047 +/***********************************************************************
6048 + * Resource type codes
6049 + ***********************************************************************/
6050 +
6051 +#define EFRM_RESOURCE_IOBUFSET 0x0
6052 +#define EFRM_RESOURCE_VI 0x1
6053 +#define EFRM_RESOURCE_FILTER 0x2
6054 +#define EFRM_RESOURCE_NUM 0x3 /* This isn't a resource! */
6055 +
6056 +#define EFRM_RESOURCE_NAME(type) \
6057 + ((type) == EFRM_RESOURCE_IOBUFSET? "IOBUFSET" : \
6058 + (type) == EFRM_RESOURCE_VI? "VI" : \
6059 + (type) == EFRM_RESOURCE_FILTER? "FILTER" : \
6060 + "<invalid>")
6061 +
6062 +#endif /* __CI_DRIVER_EFRM_RESOURCE_ID_H__ */
6063 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/sysdep.h
6064 ===================================================================
6065 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
6066 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/sysdep.h 2008-07-17 16:18:07.000000000 +0200
6067 @@ -0,0 +1,46 @@
6068 +/****************************************************************************
6069 + * Driver for Solarflare network controllers -
6070 + * resource management for Xen backend, OpenOnload, etc
6071 + * (including support for SFE4001 10GBT NIC)
6072 + *
6073 + * This file provides Linux-like system-independent API for efrm library.
6074 + *
6075 + * Copyright 2005-2007: Solarflare Communications Inc,
6076 + * 9501 Jeronimo Road, Suite 250,
6077 + * Irvine, CA 92618, USA
6078 + *
6079 + * Developed and maintained by Solarflare Communications:
6080 + * <linux-xen-drivers@solarflare.com>
6081 + * <onload-dev@solarflare.com>
6082 + *
6083 + * Certain parts of the driver were implemented by
6084 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
6085 + * OKTET Labs Ltd, Russia,
6086 + * http://oktetlabs.ru, <info@oktetlabs.ru>
6087 + * by request of Solarflare Communications
6088 + *
6089 + *
6090 + * This program is free software; you can redistribute it and/or modify it
6091 + * under the terms of the GNU General Public License version 2 as published
6092 + * by the Free Software Foundation, incorporated herein by reference.
6093 + *
6094 + * This program is distributed in the hope that it will be useful,
6095 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6096 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6097 + * GNU General Public License for more details.
6098 + *
6099 + * You should have received a copy of the GNU General Public License
6100 + * along with this program; if not, write to the Free Software
6101 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6102 + ****************************************************************************
6103 + */
6104 +
6105 +#ifndef __CI_EFRM_SYSDEP_H__
6106 +#define __CI_EFRM_SYSDEP_H__
6107 +
6108 +/* Spinlocks are defined in efhw/sysdep.h */
6109 +#include <ci/efhw/sysdep.h>
6110 +
6111 +#include <ci/efrm/sysdep_linux.h>
6112 +
6113 +#endif /* __CI_EFRM_SYSDEP_H__ */
6114 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/sysdep_linux.h
6115 ===================================================================
6116 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
6117 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/sysdep_linux.h 2008-07-17 16:18:07.000000000 +0200
6118 @@ -0,0 +1,93 @@
6119 +/****************************************************************************
6120 + * Driver for Solarflare network controllers -
6121 + * resource management for Xen backend, OpenOnload, etc
6122 + * (including support for SFE4001 10GBT NIC)
6123 + *
6124 + * This file provides version-independent Linux kernel API for efrm library.
6125 + * Only kernels >=2.6.9 are supported.
6126 + *
6127 + * Copyright 2005-2007: Solarflare Communications Inc,
6128 + * 9501 Jeronimo Road, Suite 250,
6129 + * Irvine, CA 92618, USA
6130 + *
6131 + * Kfifo API is partially stolen from linux-2.6.22/include/linux/list.h
6132 + * Copyright (C) 2004 Stelian Pop <stelian@popies.net>
6133 + *
6134 + * Developed and maintained by Solarflare Communications:
6135 + * <linux-xen-drivers@solarflare.com>
6136 + * <onload-dev@solarflare.com>
6137 + *
6138 + * Certain parts of the driver were implemented by
6139 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
6140 + * OKTET Labs Ltd, Russia,
6141 + * http://oktetlabs.ru, <info@oktetlabs.ru>
6142 + * by request of Solarflare Communications
6143 + *
6144 + *
6145 + * This program is free software; you can redistribute it and/or modify it
6146 + * under the terms of the GNU General Public License version 2 as published
6147 + * by the Free Software Foundation, incorporated herein by reference.
6148 + *
6149 + * This program is distributed in the hope that it will be useful,
6150 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6151 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6152 + * GNU General Public License for more details.
6153 + *
6154 + * You should have received a copy of the GNU General Public License
6155 + * along with this program; if not, write to the Free Software
6156 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6157 + ****************************************************************************
6158 + */
6159 +
6160 +#ifndef __CI_EFRM_SYSDEP_LINUX_H__
6161 +#define __CI_EFRM_SYSDEP_LINUX_H__
6162 +
6163 +#include <linux/list.h>
6164 +#include <linux/vmalloc.h>
6165 +#include <linux/errno.h>
6166 +#include <linux/string.h>
6167 +#include <linux/workqueue.h>
6168 +#include <linux/gfp.h>
6169 +#include <linux/slab.h>
6170 +#include <linux/hardirq.h>
6171 +#include <linux/kernel.h>
6172 +#include <linux/if_ether.h>
6173 +#include <linux/completion.h>
6174 +#include <linux/in.h>
6175 +#include <linux/log2.h>
6176 +#include <linux/kfifo.h>
6177 +
6178 +
6179 +/********************************************************************
6180 + *
6181 + * List API
6182 + *
6183 + ********************************************************************/
6184 +
6185 +static inline struct list_head *list_pop(struct list_head *list)
6186 +{
6187 + struct list_head *link = list->next;
6188 + list_del(link);
6189 + return link;
6190 +}
6191 +
6192 +static inline struct list_head *list_pop_tail(struct list_head *list)
6193 +{
6194 + struct list_head *link = list->prev;
6195 + list_del(link);
6196 + return link;
6197 +}
6198 +
6199 +/********************************************************************
6200 + *
6201 + * Kfifo API
6202 + *
6203 + ********************************************************************/
6204 +
6205 +static inline void kfifo_vfree(struct kfifo *fifo)
6206 +{
6207 + vfree(fifo->buffer);
6208 + kfree(fifo);
6209 +}
6210 +
6211 +#endif /* __CI_EFRM_SYSDEP_LINUX_H__ */
6212 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource.h
6213 ===================================================================
6214 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
6215 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource.h 2008-07-17 16:18:07.000000000 +0200
6216 @@ -0,0 +1,157 @@
6217 +/****************************************************************************
6218 + * Driver for Solarflare network controllers -
6219 + * resource management for Xen backend, OpenOnload, etc
6220 + * (including support for SFE4001 10GBT NIC)
6221 + *
6222 + * This file contains public API for VI resource.
6223 + *
6224 + * Copyright 2005-2007: Solarflare Communications Inc,
6225 + * 9501 Jeronimo Road, Suite 250,
6226 + * Irvine, CA 92618, USA
6227 + *
6228 + * Developed and maintained by Solarflare Communications:
6229 + * <linux-xen-drivers@solarflare.com>
6230 + * <onload-dev@solarflare.com>
6231 + *
6232 + * Certain parts of the driver were implemented by
6233 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
6234 + * OKTET Labs Ltd, Russia,
6235 + * http://oktetlabs.ru, <info@oktetlabs.ru>
6236 + * by request of Solarflare Communications
6237 + *
6238 + *
6239 + * This program is free software; you can redistribute it and/or modify it
6240 + * under the terms of the GNU General Public License version 2 as published
6241 + * by the Free Software Foundation, incorporated herein by reference.
6242 + *
6243 + * This program is distributed in the hope that it will be useful,
6244 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6245 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6246 + * GNU General Public License for more details.
6247 + *
6248 + * You should have received a copy of the GNU General Public License
6249 + * along with this program; if not, write to the Free Software
6250 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6251 + ****************************************************************************
6252 + */
6253 +
6254 +#ifndef __CI_EFRM_VI_RESOURCE_H__
6255 +#define __CI_EFRM_VI_RESOURCE_H__
6256 +
6257 +#include <ci/efhw/efhw_types.h>
6258 +#include <ci/efrm/resource.h>
6259 +#include <ci/efrm/debug.h>
6260 +
6261 +struct vi_resource;
6262 +
6263 +/* Make these inline instead of macros for type checking */
6264 +static inline struct vi_resource *
6265 +efrm_to_vi_resource(struct efrm_resource *rs)
6266 +{
6267 + EFRM_ASSERT(EFRM_RESOURCE_TYPE(rs->rs_handle) == EFRM_RESOURCE_VI);
6268 + return (struct vi_resource *) rs;
6269 +}
6270 +static inline struct
6271 +efrm_resource *efrm_from_vi_resource(struct vi_resource *rs)
6272 +{
6273 + return (struct efrm_resource *)rs;
6274 +}
6275 +
6276 +#define EFAB_VI_RESOURCE_INSTANCE(virs) \
6277 + EFRM_RESOURCE_INSTANCE(efrm_from_vi_resource(virs)->rs_handle)
6278 +
6279 +#define EFAB_VI_RESOURCE_PRI_ARG(virs) \
6280 + EFRM_RESOURCE_PRI_ARG(efrm_from_vi_resource(virs)->rs_handle)
6281 +
6282 +extern int
6283 +efrm_vi_resource_alloc(struct efrm_client *client,
6284 + struct vi_resource *evq_virs,
6285 + uint16_t vi_flags, int32_t evq_capacity,
6286 + int32_t txq_capacity, int32_t rxq_capacity,
6287 + uint8_t tx_q_tag, uint8_t rx_q_tag,
6288 + struct vi_resource **virs_in_out,
6289 + uint32_t *out_io_mmap_bytes,
6290 + uint32_t *out_mem_mmap_bytes,
6291 + uint32_t *out_txq_capacity,
6292 + uint32_t *out_rxq_capacity);
6293 +
6294 +extern void efrm_vi_resource_free(struct vi_resource *);
6295 +extern void efrm_vi_resource_release(struct vi_resource *);
6296 +
6297 +
6298 +/*--------------------------------------------------------------------
6299 + *
6300 + * eventq handling
6301 + *
6302 + *--------------------------------------------------------------------*/
6303 +
6304 +/*! Reset an event queue and clear any associated timers */
6305 +extern void efrm_eventq_reset(struct vi_resource *virs);
6306 +
6307 +/*! Register a kernel-level handler for the event queue. This function is
6308 + * called whenever a timer expires, or whenever the event queue is woken
6309 + * but no thread is blocked on it.
6310 + *
6311 + * This function returns -EBUSY if a callback is already installed.
6312 + *
6313 + * \param rs Event-queue resource
6314 + * \param handler Callback-handler
6315 + * \param arg Argument to pass to callback-handler
6316 + * \return Status code
6317 + */
6318 +extern int
6319 +efrm_eventq_register_callback(struct vi_resource *rs,
6320 + void (*handler)(void *arg, int is_timeout,
6321 + struct efhw_nic *nic),
6322 + void *arg);
6323 +
6324 +/*! Kill the kernel-level callback.
6325 + *
6326 + * This function stops the timer from running and unregisters the callback
6327 + * function. It waits for any running timeout handlers to complete before
6328 + * returning.
6329 + *
6330 + * \param rs Event-queue resource
6331 + * \return Nothing
6332 + */
6333 +extern void efrm_eventq_kill_callback(struct vi_resource *rs);
6334 +
6335 +/*! Ask the NIC to generate a wakeup when an event is next delivered. */
6336 +extern void efrm_eventq_request_wakeup(struct vi_resource *rs,
6337 + unsigned current_ptr);
6338 +
6339 +/*! Register a kernel-level handler for flush completions.
6340 + * \TODO Currently, it is unsafe to install a callback more than once.
6341 + *
6342 + * \param rs VI resource being flushed.
6343 + * \param handler Callback handler function.
6344 + * \param arg Argument to be passed to handler.
6345 + */
6346 +extern void
6347 +efrm_vi_register_flush_callback(struct vi_resource *rs,
6348 + void (*handler)(void *),
6349 + void *arg);
6350 +
6351 +int efrm_vi_resource_flush_retry(struct vi_resource *virs);
6352 +
6353 +/*! Comment? */
6354 +extern int efrm_pt_flush(struct vi_resource *);
6355 +
6356 +/*! Comment? */
6357 +extern int efrm_pt_pace(struct vi_resource *, unsigned int val);
6358 +
6359 +uint32_t efrm_vi_rm_txq_bytes(struct vi_resource *virs
6360 + /*,struct efhw_nic *nic */);
6361 +uint32_t efrm_vi_rm_rxq_bytes(struct vi_resource *virs
6362 + /*,struct efhw_nic *nic */);
6363 +uint32_t efrm_vi_rm_evq_bytes(struct vi_resource *virs
6364 + /*,struct efhw_nic *nic */);
6365 +
6366 +
6367 +/* Fill [out_vi_data] with information required to allow a VI to be init'd.
6368 + * [out_vi_data] must ref at least VI_MAPPINGS_SIZE bytes.
6369 + */
6370 +extern void efrm_vi_resource_mappings(struct vi_resource *, void *out_vi_data);
6371 +
6372 +
6373 +#endif /* __CI_EFRM_VI_RESOURCE_H__ */
6374 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_manager.h
6375 ===================================================================
6376 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
6377 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_manager.h 2008-07-17 16:18:07.000000000 +0200
6378 @@ -0,0 +1,155 @@
6379 +/****************************************************************************
6380 + * Driver for Solarflare network controllers -
6381 + * resource management for Xen backend, OpenOnload, etc
6382 + * (including support for SFE4001 10GBT NIC)
6383 + *
6384 + * This file contains type definitions for VI resource. These types
6385 + * may be used outside of the SFC resource driver, but such use is not
6386 + * recommended.
6387 + *
6388 + * Copyright 2005-2007: Solarflare Communications Inc,
6389 + * 9501 Jeronimo Road, Suite 250,
6390 + * Irvine, CA 92618, USA
6391 + *
6392 + * Developed and maintained by Solarflare Communications:
6393 + * <linux-xen-drivers@solarflare.com>
6394 + * <onload-dev@solarflare.com>
6395 + *
6396 + *
6397 + * This program is free software; you can redistribute it and/or modify it
6398 + * under the terms of the GNU General Public License version 2 as published
6399 + * by the Free Software Foundation, incorporated herein by reference.
6400 + *
6401 + * This program is distributed in the hope that it will be useful,
6402 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6403 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6404 + * GNU General Public License for more details.
6405 + *
6406 + * You should have received a copy of the GNU General Public License
6407 + * along with this program; if not, write to the Free Software
6408 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6409 + ****************************************************************************
6410 + */
6411 +
6412 +#ifndef __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__
6413 +#define __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__
6414 +
6415 +#include <ci/efhw/common.h>
6416 +#include <ci/efrm/vi_resource.h>
6417 +
6418 +
6419 +#define EFRM_VI_RM_DMA_QUEUE_COUNT 2
6420 +#define EFRM_VI_RM_DMA_QUEUE_TX 0
6421 +#define EFRM_VI_RM_DMA_QUEUE_RX 1
6422 +
6423 +/** Numbers of bits which can be set in the evq_state member of
6424 + * vi_resource_evq_info. */
6425 +enum {
6426 + /** This bit is set if a wakeup has been requested on the NIC. */
6427 + VI_RESOURCE_EVQ_STATE_WAKEUP_PENDING,
6428 + /** This bit is set if the wakeup is valid for the sleeping
6429 + * process. */
6430 + VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED,
6431 + /** This bit is set if a wakeup or timeout event is currently being
6432 + * processed. */
6433 + VI_RESOURCE_EVQ_STATE_BUSY,
6434 +};
6435 +#define VI_RESOURCE_EVQ_STATE(X) \
6436 + (((int32_t)1) << (VI_RESOURCE_EVQ_STATE_##X))
6437 +
6438 +
6439 +/*! Global information for the VI resource manager. */
6440 +struct vi_resource_manager {
6441 + struct efrm_resource_manager rm;
6442 +
6443 + struct kfifo *instances_with_timer;
6444 + int with_timer_base;
6445 + int with_timer_limit;
6446 + struct kfifo *instances_with_interrupt;
6447 + int with_interrupt_base;
6448 + int with_interrupt_limit;
6449 +
6450 + bool iscsi_dmaq_instance_is_free;
6451 +
6452 + /* We keep VI resources which need flushing on these lists. The VI
6453 + * is put on the outstanding list when the flush request is issued
6454 + * to the hardware and removed when the flush event arrives. The
6455 + * hardware can only handle a limited number of RX flush requests at
6456 + * once, so VIs are placed in the waiting list until the flush can
6457 + * be issued. Flushes can be requested by the client or internally
6458 + * by the VI resource manager. In the former case, the reference
6459 + * count must be non-zero for the duration of the flush and in the
6460 + * later case, the reference count must be zero. */
6461 + struct list_head rx_flush_waiting_list;
6462 + struct list_head rx_flush_outstanding_list;
6463 + struct list_head tx_flush_outstanding_list;
6464 + int rx_flush_outstanding_count;
6465 +
6466 + /* once the flush has happened we push the close into the work queue
6467 + * so its OK on Windows to free the resources (Bug 3469). Resources
6468 + * on this list have zero reference count.
6469 + */
6470 + struct list_head close_pending;
6471 + struct work_struct work_item;
6472 + struct workqueue_struct *workqueue;
6473 +};
6474 +
6475 +struct vi_resource_nic_info {
6476 + struct eventq_resource_hardware evq_pages;
6477 + struct efhw_iopages dmaq_pages[EFRM_VI_RM_DMA_QUEUE_COUNT];
6478 +};
6479 +
6480 +struct vi_resource {
6481 + /* Some macros make the assumption that the struct efrm_resource is
6482 + * the first member of a struct vi_resource. */
6483 + struct efrm_resource rs;
6484 + atomic_t evq_refs; /*!< Number of users of the event queue. */
6485 +
6486 + uint32_t bar_mmap_bytes;
6487 + uint32_t mem_mmap_bytes;
6488 +
6489 + int32_t evq_capacity;
6490 + int32_t dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_COUNT];
6491 +
6492 + uint8_t dmaq_tag[EFRM_VI_RM_DMA_QUEUE_COUNT];
6493 + uint16_t flags;
6494 +
6495 + /* we keep PT endpoints that have been destroyed on a list
6496 + * until we have seen their TX and RX DMAQs flush complete
6497 + * (see Bug 1217)
6498 + */
6499 + struct list_head rx_flush_link;
6500 + struct list_head tx_flush_link;
6501 + int rx_flushing;
6502 + int rx_flush_outstanding;
6503 + int tx_flushing;
6504 + uint64_t flush_time;
6505 + int flush_count;
6506 +
6507 + void (*flush_callback_fn)(void *);
6508 + void *flush_callback_arg;
6509 +
6510 + void (*evq_callback_fn) (void *arg, int is_timeout,
6511 + struct efhw_nic *nic);
6512 + void *evq_callback_arg;
6513 +
6514 + struct vi_resource *evq_virs; /*!< EVQ for DMA queues */
6515 +
6516 + struct efhw_buffer_table_allocation
6517 + dmaq_buf_tbl_alloc[EFRM_VI_RM_DMA_QUEUE_COUNT];
6518 +
6519 + struct vi_resource_nic_info nic_info;
6520 +};
6521 +
6522 +#undef vi_resource
6523 +#define vi_resource(rs1) container_of((rs1), struct vi_resource, rs)
6524 +
6525 +static inline dma_addr_t
6526 +efrm_eventq_dma_addr(struct vi_resource *virs)
6527 +{
6528 + struct eventq_resource_hardware *hw;
6529 + hw = &virs->nic_info.evq_pages;
6530 + return efhw_iopages_dma_addr(&hw->iobuff) + hw->iobuff_off;
6531 +}
6532 +
6533 +#endif /* __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__ */
6534 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_private.h
6535 ===================================================================
6536 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
6537 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_private.h 2008-07-17 16:18:07.000000000 +0200
6538 @@ -0,0 +1,65 @@
6539 +/****************************************************************************
6540 + * Driver for Solarflare network controllers -
6541 + * resource management for Xen backend, OpenOnload, etc
6542 + * (including support for SFE4001 10GBT NIC)
6543 + *
6544 + * This file contains private API for VI resource. The API is not designed
6545 + * to be used outside of the SFC resource driver.
6546 + *
6547 + * Copyright 2005-2007: Solarflare Communications Inc,
6548 + * 9501 Jeronimo Road, Suite 250,
6549 + * Irvine, CA 92618, USA
6550 + *
6551 + * Developed and maintained by Solarflare Communications:
6552 + * <linux-xen-drivers@solarflare.com>
6553 + * <onload-dev@solarflare.com>
6554 + *
6555 + *
6556 + * This program is free software; you can redistribute it and/or modify it
6557 + * under the terms of the GNU General Public License version 2 as published
6558 + * by the Free Software Foundation, incorporated herein by reference.
6559 + *
6560 + * This program is distributed in the hope that it will be useful,
6561 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6562 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6563 + * GNU General Public License for more details.
6564 + *
6565 + * You should have received a copy of the GNU General Public License
6566 + * along with this program; if not, write to the Free Software
6567 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6568 + ****************************************************************************
6569 + */
6570 +
6571 +#ifndef __CI_EFRM_VI_RESOURCE_PRIVATE_H__
6572 +#define __CI_EFRM_VI_RESOURCE_PRIVATE_H__
6573 +
6574 +#include <ci/efhw/common.h>
6575 +#include <ci/efrm/vi_resource_manager.h>
6576 +
6577 +extern struct vi_resource_manager *efrm_vi_manager;
6578 +
6579 +/*************************************************************************/
6580 +
6581 +extern void efrm_vi_rm_delayed_free(struct work_struct *data);
6582 +
6583 +extern void efrm_vi_rm_salvage_flushed_vis(void);
6584 +
6585 +void efrm_vi_rm_free_flushed_resource(struct vi_resource *virs);
6586 +
6587 +void efrm_vi_rm_init_dmaq(struct vi_resource *virs, int queue_index,
6588 + struct efhw_nic *nic);
6589 +
6590 +/*! Wakeup handler */
6591 +extern void efrm_handle_wakeup_event(struct efhw_nic *nic, unsigned id);
6592 +
6593 +/*! Timeout handler */
6594 +extern void efrm_handle_timeout_event(struct efhw_nic *nic, unsigned id);
6595 +
6596 +/*! DMA flush handler */
6597 +extern void efrm_handle_dmaq_flushed(struct efhw_nic *nic, unsigned id,
6598 + int rx_flush);
6599 +
6600 +/*! SRAM update handler */
6601 +extern void efrm_handle_sram_event(struct efhw_nic *nic);
6602 +
6603 +#endif /* __CI_EFRM_VI_RESOURCE_PRIVATE_H__ */
6604 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/driver_object.c
6605 ===================================================================
6606 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
6607 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/driver_object.c 2008-07-17 16:18:07.000000000 +0200
6608 @@ -0,0 +1,328 @@
6609 +/****************************************************************************
6610 + * Driver for Solarflare network controllers -
6611 + * resource management for Xen backend, OpenOnload, etc
6612 + * (including support for SFE4001 10GBT NIC)
6613 + *
6614 + * This file contains support for the global driver variables.
6615 + *
6616 + * Copyright 2005-2007: Solarflare Communications Inc,
6617 + * 9501 Jeronimo Road, Suite 250,
6618 + * Irvine, CA 92618, USA
6619 + *
6620 + * Developed and maintained by Solarflare Communications:
6621 + * <linux-xen-drivers@solarflare.com>
6622 + * <onload-dev@solarflare.com>
6623 + *
6624 + * Certain parts of the driver were implemented by
6625 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
6626 + * OKTET Labs Ltd, Russia,
6627 + * http://oktetlabs.ru, <info@oktetlabs.ru>
6628 + * by request of Solarflare Communications
6629 + *
6630 + *
6631 + * This program is free software; you can redistribute it and/or modify it
6632 + * under the terms of the GNU General Public License version 2 as published
6633 + * by the Free Software Foundation, incorporated herein by reference.
6634 + *
6635 + * This program is distributed in the hope that it will be useful,
6636 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6637 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6638 + * GNU General Public License for more details.
6639 + *
6640 + * You should have received a copy of the GNU General Public License
6641 + * along with this program; if not, write to the Free Software
6642 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6643 + ****************************************************************************
6644 + */
6645 +
6646 +#include <ci/efrm/nic_table.h>
6647 +#include <ci/efrm/resource.h>
6648 +#include <ci/efrm/debug.h>
6649 +#include <ci/efrm/efrm_client.h>
6650 +#include <ci/efrm/efrm_nic.h>
6651 +#include "efrm_internal.h"
6652 +
6653 +/* We use #define rather than static inline here so that the Windows
6654 + * "prefast" compiler can see its own locking primitive when these
6655 + * two function are used (and then perform extra checking where they
6656 + * are used)
6657 + *
6658 + * Both macros operate on an irq_flags_t
6659 +*/
6660 +
6661 +#define efrm_driver_lock(irqlock_state) \
6662 + spin_lock_irqsave(&efrm_nic_tablep->lock, irqlock_state)
6663 +
6664 +#define efrm_driver_unlock(irqlock_state) \
6665 + spin_unlock_irqrestore(&efrm_nic_tablep->lock, \
6666 + irqlock_state);
6667 +
6668 +/* These routines are all methods on the architecturally singleton
6669 + global variables: efrm_nic_table, efrm_rm_table.
6670 +
6671 + I hope we never find a driver model that does not allow global
6672 + structure variables :) (but that would break almost every driver I've
6673 + ever seen).
6674 +*/
6675 +
6676 +/*! Exported driver state */
6677 +static struct efrm_nic_table efrm_nic_table;
6678 +struct efrm_nic_table *efrm_nic_tablep;
6679 +EXPORT_SYMBOL(efrm_nic_tablep);
6680 +
6681 +
6682 +/* Internal table with resource managers.
6683 + * We'd like to not export it, but we are still using efrm_rm_table
6684 + * in the char driver. So, it is declared in the private header with
6685 + * a purpose. */
6686 +struct efrm_resource_manager *efrm_rm_table[EFRM_RESOURCE_NUM];
6687 +EXPORT_SYMBOL(efrm_rm_table);
6688 +
6689 +
6690 +/* List of registered nics. */
6691 +static LIST_HEAD(efrm_nics);
6692 +
6693 +
6694 +void efrm_driver_ctor(void)
6695 +{
6696 + efrm_nic_tablep = &efrm_nic_table;
6697 + spin_lock_init(&efrm_nic_tablep->lock);
6698 + EFRM_TRACE("%s: driver created", __func__);
6699 +}
6700 +
6701 +void efrm_driver_dtor(void)
6702 +{
6703 + EFRM_ASSERT(!efrm_nic_table_held());
6704 +
6705 + spin_lock_destroy(&efrm_nic_tablep->lock);
6706 + memset(&efrm_nic_table, 0, sizeof(efrm_nic_table));
6707 + memset(&efrm_rm_table, 0, sizeof(efrm_rm_table));
6708 + EFRM_TRACE("%s: driver deleted", __func__);
6709 +}
6710 +
6711 +int efrm_driver_register_nic(struct efrm_nic *rnic, int nic_index,
6712 + int ifindex)
6713 +{
6714 + struct efhw_nic *nic = &rnic->efhw_nic;
6715 + struct efrm_nic_per_vi *vis;
6716 + int max_vis, rc = 0;
6717 + irq_flags_t lock_flags;
6718 +
6719 + EFRM_ASSERT(nic_index >= 0);
6720 + EFRM_ASSERT(ifindex >= 0);
6721 +
6722 + max_vis = 4096; /* TODO: Get runtime value. */
6723 + vis = vmalloc(max_vis * sizeof(rnic->vis[0]));
6724 + if (vis == NULL) {
6725 + EFRM_ERR("%s: Out of memory", __func__);
6726 + return -ENOMEM;
6727 + }
6728 +
6729 + efrm_driver_lock(lock_flags);
6730 +
6731 + if (efrm_nic_table_held()) {
6732 + EFRM_ERR("%s: driver object is in use", __func__);
6733 + rc = -EBUSY;
6734 + goto done;
6735 + }
6736 +
6737 + if (efrm_nic_tablep->nic_count == EFHW_MAX_NR_DEVS) {
6738 + EFRM_ERR("%s: filled up NIC table size %d", __func__,
6739 + EFHW_MAX_NR_DEVS);
6740 + rc = -E2BIG;
6741 + goto done;
6742 + }
6743 +
6744 + rnic->vis = vis;
6745 +
6746 + EFRM_ASSERT(efrm_nic_tablep->nic[nic_index] == NULL);
6747 + efrm_nic_tablep->nic[nic_index] = nic;
6748 + nic->index = nic_index;
6749 + nic->ifindex = ifindex;
6750 +
6751 + if (efrm_nic_tablep->a_nic == NULL)
6752 + efrm_nic_tablep->a_nic = nic;
6753 +
6754 + efrm_nic_tablep->nic_count++;
6755 +
6756 + INIT_LIST_HEAD(&rnic->clients);
6757 + list_add(&rnic->link, &efrm_nics);
6758 +
6759 + efrm_driver_unlock(lock_flags);
6760 + return 0;
6761 +
6762 +done:
6763 + efrm_driver_unlock(lock_flags);
6764 + vfree(vis);
6765 + return rc;
6766 +}
6767 +
6768 +int efrm_driver_unregister_nic(struct efrm_nic *rnic)
6769 +{
6770 + struct efhw_nic *nic = &rnic->efhw_nic;
6771 + int rc = 0;
6772 + int nic_index = nic->index;
6773 + irq_flags_t lock_flags;
6774 +
6775 + EFRM_ASSERT(nic_index >= 0);
6776 +
6777 + efrm_driver_lock(lock_flags);
6778 +
6779 + if (efrm_nic_table_held()) {
6780 + EFRM_ERR("%s: driver object is in use", __func__);
6781 + rc = -EBUSY;
6782 + goto done;
6783 + }
6784 + if (!list_empty(&rnic->clients)) {
6785 + EFRM_ERR("%s: nic has active clients", __func__);
6786 + rc = -EBUSY;
6787 + goto done;
6788 + }
6789 +
6790 + EFRM_ASSERT(efrm_nic_tablep->nic[nic_index] == nic);
6791 + EFRM_ASSERT(list_empty(&rnic->clients));
6792 +
6793 + list_del(&rnic->link);
6794 +
6795 + nic->index = -1;
6796 + efrm_nic_tablep->nic[nic_index] = NULL;
6797 +
6798 + --efrm_nic_tablep->nic_count;
6799 +
6800 + if (efrm_nic_tablep->a_nic == nic) {
6801 + if (efrm_nic_tablep->nic_count == 0) {
6802 + efrm_nic_tablep->a_nic = NULL;
6803 + } else {
6804 + for (nic_index = 0; nic_index < EFHW_MAX_NR_DEVS;
6805 + nic_index++) {
6806 + if (efrm_nic_tablep->nic[nic_index] != NULL)
6807 + efrm_nic_tablep->a_nic =
6808 + efrm_nic_tablep->nic[nic_index];
6809 + }
6810 + EFRM_ASSERT(efrm_nic_tablep->a_nic);
6811 + }
6812 + }
6813 +
6814 +done:
6815 + efrm_driver_unlock(lock_flags);
6816 + return rc;
6817 +}
6818 +
6819 +
6820 +int efrm_nic_pre_reset(struct efhw_nic *nic)
6821 +{
6822 + struct efrm_nic *rnic = efrm_nic(nic);
6823 + struct efrm_client *client;
6824 + struct efrm_resource *rs;
6825 + struct list_head *client_link;
6826 + struct list_head *rs_link;
6827 + irq_flags_t lock_flags;
6828 +
6829 + spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
6830 + list_for_each(client_link, &rnic->clients) {
6831 + client = container_of(client_link, struct efrm_client, link);
6832 + EFRM_ERR("%s: client %p", __func__, client);
6833 + if (client->callbacks->pre_reset)
6834 + client->callbacks->pre_reset(client, client->user_data);
6835 + list_for_each(rs_link, &client->resources) {
6836 + rs = container_of(rs_link, struct efrm_resource,
6837 + rs_client_link);
6838 + EFRM_ERR("%s: resource %p", __func__, rs);
6839 + /* TODO: mark rs defunct */
6840 + }
6841 + }
6842 + spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
6843 +
6844 + return 0;
6845 +}
6846 +
6847 +
6848 +int efrm_nic_stop(struct efhw_nic *nic)
6849 +{
6850 + /* TODO */
6851 + return 0;
6852 +}
6853 +
6854 +
6855 +int efrm_nic_resume(struct efhw_nic *nic)
6856 +{
6857 + /* TODO */
6858 + return 0;
6859 +}
6860 +
6861 +
6862 +static void efrm_client_nullcb(struct efrm_client *client, void *user_data)
6863 +{
6864 +}
6865 +
6866 +static struct efrm_client_callbacks efrm_null_callbacks = {
6867 + efrm_client_nullcb,
6868 + efrm_client_nullcb,
6869 + efrm_client_nullcb
6870 +};
6871 +
6872 +
6873 +int efrm_client_get(int ifindex, struct efrm_client_callbacks *callbacks,
6874 + void *user_data, struct efrm_client **client_out)
6875 +{
6876 + struct efrm_nic *n, *rnic = NULL;
6877 + irq_flags_t lock_flags;
6878 + struct list_head *link;
6879 + struct efrm_client *client;
6880 +
6881 + if (callbacks == NULL)
6882 + callbacks = &efrm_null_callbacks;
6883 +
6884 + client = kmalloc(sizeof(*client), GFP_KERNEL);
6885 + if (client == NULL)
6886 + return -ENOMEM;
6887 +
6888 + spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
6889 + list_for_each(link, &efrm_nics) {
6890 + n = container_of(link, struct efrm_nic, link);
6891 + if (n->efhw_nic.ifindex == ifindex || ifindex < 0) {
6892 + rnic = n;
6893 + break;
6894 + }
6895 + }
6896 + if (rnic) {
6897 + client->user_data = user_data;
6898 + client->callbacks = callbacks;
6899 + client->nic = &rnic->efhw_nic;
6900 + client->ref_count = 1;
6901 + INIT_LIST_HEAD(&client->resources);
6902 + list_add(&client->link, &rnic->clients);
6903 + }
6904 + spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
6905 +
6906 + if (rnic == NULL)
6907 + return -ENODEV;
6908 +
6909 + *client_out = client;
6910 + return 0;
6911 +}
6912 +EXPORT_SYMBOL(efrm_client_get);
6913 +
6914 +
6915 +void efrm_client_put(struct efrm_client *client)
6916 +{
6917 + irq_flags_t lock_flags;
6918 +
6919 + EFRM_ASSERT(client->ref_count > 0);
6920 +
6921 + spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
6922 + if (--client->ref_count > 0)
6923 + client = NULL;
6924 + else
6925 + list_del(&client->link);
6926 + spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
6927 + kfree(client);
6928 +}
6929 +EXPORT_SYMBOL(efrm_client_put);
6930 +
6931 +
6932 +struct efhw_nic *efrm_client_get_nic(struct efrm_client *client)
6933 +{
6934 + return client->nic;
6935 +}
6936 +EXPORT_SYMBOL(efrm_client_get_nic);
6937 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/driverlink_new.c
6938 ===================================================================
6939 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
6940 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/driverlink_new.c 2008-07-17 16:18:07.000000000 +0200
6941 @@ -0,0 +1,260 @@
6942 +/****************************************************************************
6943 + * Driver for Solarflare network controllers -
6944 + * resource management for Xen backend, OpenOnload, etc
6945 + * (including support for SFE4001 10GBT NIC)
6946 + *
6947 + * This file contains driverlink code which interacts with the sfc network
6948 + * driver.
6949 + *
6950 + * Copyright 2005-2007: Solarflare Communications Inc,
6951 + * 9501 Jeronimo Road, Suite 250,
6952 + * Irvine, CA 92618, USA
6953 + *
6954 + * Developed and maintained by Solarflare Communications:
6955 + * <linux-xen-drivers@solarflare.com>
6956 + * <onload-dev@solarflare.com>
6957 + *
6958 + *
6959 + * This program is free software; you can redistribute it and/or modify it
6960 + * under the terms of the GNU General Public License version 2 as published
6961 + * by the Free Software Foundation, incorporated herein by reference.
6962 + *
6963 + * This program is distributed in the hope that it will be useful,
6964 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6965 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6966 + * GNU General Public License for more details.
6967 + *
6968 + * You should have received a copy of the GNU General Public License
6969 + * along with this program; if not, write to the Free Software
6970 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6971 + ****************************************************************************
6972 + */
6973 +
6974 +#include "linux_resource_internal.h"
6975 +#include "driverlink_api.h"
6976 +#include "kernel_compat.h"
6977 +#include <ci/efhw/falcon.h>
6978 +
6979 +#include <linux/rtnetlink.h>
6980 +#include <linux/netdevice.h>
6981 +#include <net/net_namespace.h>
6982 +
6983 +/* The DL driver and associated calls */
6984 +static int efrm_dl_probe(struct efx_dl_device *efrm_dev,
6985 + const struct net_device *net_dev,
6986 + const struct efx_dl_device_info *dev_info,
6987 + const char *silicon_rev);
6988 +
6989 +static void efrm_dl_remove(struct efx_dl_device *efrm_dev);
6990 +
6991 +static void efrm_dl_reset_suspend(struct efx_dl_device *efrm_dev);
6992 +
6993 +static void efrm_dl_reset_resume(struct efx_dl_device *efrm_dev, int ok);
6994 +
6995 +static void efrm_dl_mtu_changed(struct efx_dl_device *, int);
6996 +static void efrm_dl_event_falcon(struct efx_dl_device *efx_dev, void *p_event);
6997 +
6998 +static struct efx_dl_driver efrm_dl_driver = {
6999 + .name = "resource",
7000 + .probe = efrm_dl_probe,
7001 + .remove = efrm_dl_remove,
7002 + .reset_suspend = efrm_dl_reset_suspend,
7003 + .reset_resume = efrm_dl_reset_resume
7004 +};
7005 +
7006 +static void
7007 +init_vi_resource_dimensions(struct vi_resource_dimensions *rd,
7008 + const struct efx_dl_falcon_resources *res)
7009 +{
7010 + rd->evq_timer_min = res->evq_timer_min;
7011 + rd->evq_timer_lim = res->evq_timer_lim;
7012 + rd->evq_int_min = res->evq_int_min;
7013 + rd->evq_int_lim = res->evq_int_lim;
7014 + rd->rxq_min = res->rxq_min;
7015 + rd->rxq_lim = res->rxq_lim;
7016 + rd->txq_min = res->txq_min;
7017 + rd->txq_lim = res->txq_lim;
7018 + EFRM_TRACE
7019 + ("Using evq_int(%d-%d) evq_timer(%d-%d) RXQ(%d-%d) TXQ(%d-%d)",
7020 + res->evq_int_min, res->evq_int_lim, res->evq_timer_min,
7021 + res->evq_timer_lim, res->rxq_min, res->rxq_lim, res->txq_min,
7022 + res->txq_lim);
7023 +}
7024 +
7025 +static int
7026 +efrm_dl_probe(struct efx_dl_device *efrm_dev,
7027 + const struct net_device *net_dev,
7028 + const struct efx_dl_device_info *dev_info,
7029 + const char *silicon_rev)
7030 +{
7031 + struct vi_resource_dimensions res_dim;
7032 + struct efx_dl_falcon_resources *res;
7033 + struct linux_efhw_nic *lnic;
7034 + struct pci_dev *dev;
7035 + struct efhw_nic *nic;
7036 + unsigned probe_flags = 0;
7037 + int non_irq_evq;
7038 + int rc;
7039 +
7040 + efrm_dev->priv = NULL;
7041 +
7042 + efx_dl_search_device_info(dev_info, EFX_DL_FALCON_RESOURCES,
7043 + struct efx_dl_falcon_resources,
7044 + hdr, res);
7045 +
7046 + if (res == NULL) {
7047 + EFRM_ERR("%s: Unable to find falcon driverlink resources",
7048 + __func__);
7049 + return -EINVAL;
7050 + }
7051 +
7052 + if (res->flags & EFX_DL_FALCON_USE_MSI)
7053 + probe_flags |= NIC_FLAG_TRY_MSI;
7054 +
7055 + dev = efrm_dev->pci_dev;
7056 + if (res->flags & EFX_DL_FALCON_DUAL_FUNC) {
7057 + unsigned vendor = dev->vendor;
7058 + EFRM_ASSERT(dev->bus != NULL);
7059 + dev = NULL;
7060 +
7061 + while ((dev = pci_get_device(vendor, FALCON_S_DEVID, dev))
7062 + != NULL) {
7063 + EFRM_ASSERT(dev->bus != NULL);
7064 + /* With PCIe (since it's point to point)
7065 + * the slot ID is usually 0 and
7066 + * the bus ID changes NIC to NIC, so we really
7067 + * need to check both. */
7068 + if (PCI_SLOT(dev->devfn) ==
7069 + PCI_SLOT(efrm_dev->pci_dev->devfn)
7070 + && dev->bus->number ==
7071 + efrm_dev->pci_dev->bus->number)
7072 + break;
7073 + }
7074 + if (dev == NULL) {
7075 + EFRM_ERR("%s: Unable to find falcon secondary "
7076 + "PCI device.", __func__);
7077 + return -ENODEV;
7078 + }
7079 + pci_dev_put(dev);
7080 + }
7081 +
7082 + init_vi_resource_dimensions(&res_dim, res);
7083 +
7084 + EFRM_ASSERT(res_dim.evq_timer_lim > res_dim.evq_timer_min);
7085 + res_dim.evq_timer_lim--;
7086 + non_irq_evq = res_dim.evq_timer_lim;
7087 +
7088 + rc = efrm_nic_add(dev, probe_flags, net_dev->dev_addr, &lnic,
7089 + res->biu_lock,
7090 + res->buffer_table_min, res->buffer_table_lim,
7091 + non_irq_evq, &res_dim);
7092 + if (rc != 0)
7093 + return rc;
7094 +
7095 + nic = &lnic->efrm_nic.efhw_nic;
7096 + nic->mtu = net_dev->mtu + ETH_HLEN;
7097 + nic->net_driver_dev = efrm_dev;
7098 + nic->ifindex = net_dev->ifindex;
7099 +#ifdef CONFIG_NET_NS
7100 + nic->nd_net = net_dev->nd_net;
7101 +#endif
7102 + efrm_dev->priv = nic;
7103 +
7104 + /* Register a callback so we're told when MTU changes.
7105 + * We dynamically allocate efx_dl_callbacks, because
7106 + * the callbacks that we want depends on the NIC type.
7107 + */
7108 + lnic->dl_callbacks =
7109 + kmalloc(sizeof(struct efx_dl_callbacks), GFP_KERNEL);
7110 + if (!lnic->dl_callbacks) {
7111 + EFRM_ERR("Out of memory (%s)", __func__);
7112 + efrm_nic_del(lnic);
7113 + return -ENOMEM;
7114 + }
7115 + memset(lnic->dl_callbacks, 0, sizeof(*lnic->dl_callbacks));
7116 + lnic->dl_callbacks->mtu_changed = efrm_dl_mtu_changed;
7117 +
7118 + if ((res->flags & EFX_DL_FALCON_DUAL_FUNC) == 0) {
7119 + /* Net driver receives all management events.
7120 + * Register a callback to receive the ones
7121 + * we're interested in. */
7122 + lnic->dl_callbacks->event = efrm_dl_event_falcon;
7123 + }
7124 +
7125 + rc = efx_dl_register_callbacks(efrm_dev, lnic->dl_callbacks);
7126 + if (rc < 0) {
7127 + EFRM_ERR("%s: efx_dl_register_callbacks failed (%d)",
7128 + __func__, rc);
7129 + kfree(lnic->dl_callbacks);
7130 + efrm_nic_del(lnic);
7131 + return rc;
7132 + }
7133 +
7134 + return 0;
7135 +}
7136 +
7137 +/* When we unregister ourselves on module removal, this function will be
7138 + * called for all the devices we claimed */
7139 +static void efrm_dl_remove(struct efx_dl_device *efrm_dev)
7140 +{
7141 + struct efhw_nic *nic = efrm_dev->priv;
7142 + struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
7143 + EFRM_TRACE("%s called", __func__);
7144 + if (lnic->dl_callbacks) {
7145 + efx_dl_unregister_callbacks(efrm_dev, lnic->dl_callbacks);
7146 + kfree(lnic->dl_callbacks);
7147 + }
7148 + if (efrm_dev->priv)
7149 + efrm_nic_del(lnic);
7150 + EFRM_TRACE("%s OK", __func__);
7151 +}
7152 +
7153 +static void efrm_dl_reset_suspend(struct efx_dl_device *efrm_dev)
7154 +{
7155 + EFRM_NOTICE("%s:", __func__);
7156 +}
7157 +
7158 +static void efrm_dl_reset_resume(struct efx_dl_device *efrm_dev, int ok)
7159 +{
7160 + EFRM_NOTICE("%s: ok=%d", __func__, ok);
7161 +}
7162 +
7163 +int efrm_driverlink_register(void)
7164 +{
7165 + EFRM_TRACE("%s:", __func__);
7166 + return efx_dl_register_driver(&efrm_dl_driver);
7167 +}
7168 +
7169 +void efrm_driverlink_unregister(void)
7170 +{
7171 + EFRM_TRACE("%s:", __func__);
7172 + efx_dl_unregister_driver(&efrm_dl_driver);
7173 +}
7174 +
7175 +static void efrm_dl_mtu_changed(struct efx_dl_device *efx_dev, int mtu)
7176 +{
7177 + struct efhw_nic *nic = efx_dev->priv;
7178 +
7179 + ASSERT_RTNL(); /* Since we're looking at efx_dl_device::port_net_dev */
7180 +
7181 + EFRM_TRACE("%s: old=%d new=%d", __func__, nic->mtu, mtu + ETH_HLEN);
7182 + /* If this happened we must have agreed to it above */
7183 + nic->mtu = mtu + ETH_HLEN;
7184 +}
7185 +
7186 +static void efrm_dl_event_falcon(struct efx_dl_device *efx_dev, void *p_event)
7187 +{
7188 + struct efhw_nic *nic = efx_dev->priv;
7189 + struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
7190 + efhw_event_t *ev = p_event;
7191 +
7192 + switch (FALCON_EVENT_CODE(ev)) {
7193 + case FALCON_EVENT_CODE_CHAR:
7194 + falcon_handle_char_event(nic, lnic->ev_handlers, ev);
7195 + break;
7196 + default:
7197 + EFRM_WARN("%s: unknown event type=%x", __func__,
7198 + (unsigned)FALCON_EVENT_CODE(ev));
7199 + break;
7200 + }
7201 +}
7202 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/efrm_internal.h
7203 ===================================================================
7204 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
7205 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/efrm_internal.h 2008-07-17 16:18:07.000000000 +0200
7206 @@ -0,0 +1,41 @@
7207 +#ifndef __EFRM_INTERNAL_H__
7208 +#define __EFRM_INTERNAL_H__
7209 +
7210 +
7211 +struct filter_resource {
7212 + struct efrm_resource rs;
7213 + struct vi_resource *pt;
7214 + int filter_idx;
7215 +};
7216 +
7217 +#define filter_resource(rs1) container_of((rs1), struct filter_resource, rs)
7218 +
7219 +
7220 +struct efrm_client {
7221 + void *user_data;
7222 + struct list_head link;
7223 + struct efrm_client_callbacks *callbacks;
7224 + struct efhw_nic *nic;
7225 + int ref_count;
7226 + struct list_head resources;
7227 +};
7228 +
7229 +
7230 +extern void efrm_client_add_resource(struct efrm_client *,
7231 + struct efrm_resource *);
7232 +
7233 +extern int efrm_buffer_table_size(void);
7234 +
7235 +
7236 +static inline void efrm_resource_init(struct efrm_resource *rs,
7237 + int type, int instance)
7238 +{
7239 + EFRM_ASSERT(instance >= 0);
7240 + EFRM_ASSERT(type >= 0 && type < EFRM_RESOURCE_NUM);
7241 + rs->rs_ref_count = 1;
7242 + rs->rs_handle.handle = (type << 28u) |
7243 + (((unsigned)jiffies & 0xfff) << 16) | instance;
7244 +}
7245 +
7246 +
7247 +#endif /* __EFRM_INTERNAL_H__ */
7248 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/efx_vi_shm.c
7249 ===================================================================
7250 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
7251 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/efx_vi_shm.c 2008-07-17 16:18:07.000000000 +0200
7252 @@ -0,0 +1,707 @@
7253 +/****************************************************************************
7254 + * Driver for Solarflare network controllers -
7255 + * resource management for Xen backend, OpenOnload, etc
7256 + * (including support for SFE4001 10GBT NIC)
7257 + *
7258 + * This file provides implementation of EFX VI API, used from Xen
7259 + * acceleration driver.
7260 + *
7261 + * Copyright 2005-2007: Solarflare Communications Inc,
7262 + * 9501 Jeronimo Road, Suite 250,
7263 + * Irvine, CA 92618, USA
7264 + *
7265 + * Developed and maintained by Solarflare Communications:
7266 + * <linux-xen-drivers@solarflare.com>
7267 + * <onload-dev@solarflare.com>
7268 + *
7269 + *
7270 + * This program is free software; you can redistribute it and/or modify it
7271 + * under the terms of the GNU General Public License version 2 as published
7272 + * by the Free Software Foundation, incorporated herein by reference.
7273 + *
7274 + * This program is distributed in the hope that it will be useful,
7275 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7276 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7277 + * GNU General Public License for more details.
7278 + *
7279 + * You should have received a copy of the GNU General Public License
7280 + * along with this program; if not, write to the Free Software
7281 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7282 + ****************************************************************************
7283 + */
7284 +
7285 +#include "linux_resource_internal.h"
7286 +#include <ci/efrm/vi_resource_manager.h>
7287 +#include <ci/driver/resource/efx_vi.h>
7288 +#include <ci/efrm/filter.h>
7289 +#include <ci/efrm/buffer_table.h>
7290 +#include <ci/efrm/efrm_client.h>
7291 +#include <linux/pci.h>
7292 +#include "kernel_compat.h"
7293 +
7294 +#if EFX_VI_STATIC_FILTERS
7295 +struct filter_list_t {
7296 + struct filter_list_t *next;
7297 + struct filter_resource *fres;
7298 +};
7299 +#endif
7300 +
7301 +struct efx_vi_state {
7302 + struct vi_resource *vi_res;
7303 +
7304 + int ifindex;
7305 + struct efrm_client *efrm_client;
7306 + struct efhw_nic *nic;
7307 +
7308 + void (*callback_fn)(void *arg, int is_timeout);
7309 + void *callback_arg;
7310 +
7311 + struct completion flush_completion;
7312 +
7313 +#if EFX_VI_STATIC_FILTERS
7314 + struct filter_list_t fres[EFX_VI_STATIC_FILTERS];
7315 + struct filter_list_t *free_fres;
7316 + struct filter_list_t *used_fres;
7317 +#endif
7318 +};
7319 +
7320 +static void efx_vi_flush_complete(void *state_void)
7321 +{
7322 + struct efx_vi_state *state = (struct efx_vi_state *)state_void;
7323 +
7324 + complete(&state->flush_completion);
7325 +}
7326 +
7327 +static inline int alloc_ep(struct efx_vi_state *state)
7328 +{
7329 + int rc;
7330 +
7331 + rc = efrm_vi_resource_alloc(state->efrm_client, NULL, EFHW_VI_JUMBO_EN,
7332 + efx_vi_eventq_size,
7333 + FALCON_DMA_Q_DEFAULT_TX_SIZE,
7334 + FALCON_DMA_Q_DEFAULT_RX_SIZE,
7335 + 0, 0, &state->vi_res, NULL, NULL, NULL,
7336 + NULL);
7337 + if (rc < 0) {
7338 + EFRM_ERR("%s: ERROR efrm_vi_resource_alloc error %d",
7339 + __func__, rc);
7340 + return rc;
7341 + }
7342 +
7343 + efrm_vi_register_flush_callback(state->vi_res, &efx_vi_flush_complete,
7344 + (void *)state);
7345 +
7346 + return 0;
7347 +}
7348 +
7349 +static int free_ep(struct efx_vi_state *efx_state)
7350 +{
7351 + efrm_vi_resource_release(efx_state->vi_res);
7352 +
7353 + return 0;
7354 +}
7355 +
7356 +#if EFX_VI_STATIC_FILTERS
7357 +static int efx_vi_alloc_static_filters(struct efx_vi_state *efx_state)
7358 +{
7359 + int i;
7360 + int rc;
7361 +
7362 + efx_state->free_fres = efx_state->used_fres = NULL;
7363 +
7364 + for (i = 0; i < EFX_VI_STATIC_FILTERS; i++) {
7365 + rc = efrm_filter_resource_alloc(efx_state->vi_res,
7366 + &efx_state->fres[i].fres);
7367 + if (rc < 0) {
7368 + EFRM_ERR("%s: efrm_filter_resource_alloc failed: %d",
7369 + __func__, rc);
7370 + while (i > 0) {
7371 + i--;
7372 + efrm_filter_resource_release(efx_state->
7373 + fres[i].fres);
7374 + }
7375 + efx_state->free_fres = NULL;
7376 + return rc;
7377 + }
7378 + efx_state->fres[i].next = efx_state->free_fres;
7379 + efx_state->free_fres = &efx_state->fres[i];
7380 + }
7381 +
7382 + return 0;
7383 +}
7384 +#endif
7385 +
7386 +int efx_vi_alloc(struct efx_vi_state **vih_out, int ifindex)
7387 +{
7388 + struct efx_vi_state *efx_state;
7389 + int rc;
7390 +
7391 + efx_state = kmalloc(sizeof(struct efx_vi_state), GFP_KERNEL);
7392 +
7393 + if (!efx_state) {
7394 + EFRM_ERR("%s: failed to allocate memory for efx_vi_state",
7395 + __func__);
7396 + rc = -ENOMEM;
7397 + goto fail;
7398 + }
7399 +
7400 + efx_state->ifindex = ifindex;
7401 + rc = efrm_client_get(ifindex, NULL, NULL, &efx_state->efrm_client);
7402 + if (rc < 0) {
7403 + EFRM_ERR("%s: efrm_client_get(%d) failed: %d", __func__,
7404 + ifindex, rc);
7405 + rc = -ENODEV;
7406 + goto fail_no_ifindex;
7407 + }
7408 + efx_state->nic = efrm_client_get_nic(efx_state->efrm_client);
7409 +
7410 + init_completion(&efx_state->flush_completion);
7411 +
7412 + /* basically allocate_pt_endpoint() */
7413 + rc = alloc_ep(efx_state);
7414 + if (rc) {
7415 + EFRM_ERR("%s: alloc_ep failed: %d", __func__, rc);
7416 + goto fail_no_pt;
7417 + }
7418 +#if EFX_VI_STATIC_FILTERS
7419 + /* Statically allocate a set of filter resources - removes the
7420 + restriction on not being able to use efx_vi_filter() from
7421 + in_atomic() */
7422 + rc = efx_vi_alloc_static_filters(efx_state);
7423 + if (rc)
7424 + goto fail_no_filters;
7425 +#endif
7426 +
7427 + *vih_out = efx_state;
7428 +
7429 + return 0;
7430 +#if EFX_VI_STATIC_FILTERS
7431 +fail_no_filters:
7432 + free_ep(efx_state);
7433 +#endif
7434 +fail_no_pt:
7435 + efrm_client_put(efx_state->efrm_client);
7436 +fail_no_ifindex:
7437 + kfree(efx_state);
7438 +fail:
7439 + return rc;
7440 +}
7441 +EXPORT_SYMBOL(efx_vi_alloc);
7442 +
7443 +void efx_vi_free(struct efx_vi_state *vih)
7444 +{
7445 + struct efx_vi_state *efx_state = vih;
7446 +
7447 + /* TODO flush dma channels, init dma queues?. See ef_free_vnic() */
7448 +#if EFX_VI_STATIC_FILTERS
7449 + int i;
7450 +
7451 + for (i = 0; i < EFX_VI_STATIC_FILTERS; i++)
7452 + efrm_filter_resource_release(efx_state->fres[i].fres);
7453 +#endif
7454 +
7455 + if (efx_state->vi_res)
7456 + free_ep(efx_state);
7457 +
7458 + efrm_client_put(efx_state->efrm_client);
7459 +
7460 + kfree(efx_state);
7461 +}
7462 +EXPORT_SYMBOL(efx_vi_free);
7463 +
7464 +void efx_vi_reset(struct efx_vi_state *vih)
7465 +{
7466 + struct efx_vi_state *efx_state = vih;
7467 +
7468 + efrm_pt_flush(efx_state->vi_res);
7469 +
7470 + while (wait_for_completion_timeout(&efx_state->flush_completion, HZ)
7471 + == 0)
7472 + efrm_vi_resource_flush_retry(efx_state->vi_res);
7473 +
7474 + /* Bosch the eventq */
7475 + efrm_eventq_reset(efx_state->vi_res);
7476 + return;
7477 +}
7478 +EXPORT_SYMBOL(efx_vi_reset);
7479 +
7480 +static void
7481 +efx_vi_eventq_callback(void *context, int is_timeout, struct efhw_nic *nic)
7482 +{
7483 + struct efx_vi_state *efx_state = (struct efx_vi_state *)context;
7484 +
7485 + EFRM_ASSERT(efx_state->callback_fn);
7486 +
7487 + return efx_state->callback_fn(efx_state->callback_arg, is_timeout);
7488 +}
7489 +
7490 +int
7491 +efx_vi_eventq_register_callback(struct efx_vi_state *vih,
7492 + void (*callback)(void *context, int is_timeout),
7493 + void *context)
7494 +{
7495 + struct efx_vi_state *efx_state = vih;
7496 +
7497 + efx_state->callback_fn = callback;
7498 + efx_state->callback_arg = context;
7499 +
7500 + /* Register the eventq timeout event callback */
7501 + efrm_eventq_register_callback(efx_state->vi_res,
7502 + efx_vi_eventq_callback, efx_state);
7503 +
7504 + return 0;
7505 +}
7506 +EXPORT_SYMBOL(efx_vi_eventq_register_callback);
7507 +
7508 +int efx_vi_eventq_kill_callback(struct efx_vi_state *vih)
7509 +{
7510 + struct efx_vi_state *efx_state = vih;
7511 +
7512 + if (efx_state->vi_res->evq_callback_fn)
7513 + efrm_eventq_kill_callback(efx_state->vi_res);
7514 +
7515 + efx_state->callback_fn = NULL;
7516 + efx_state->callback_arg = NULL;
7517 +
7518 + return 0;
7519 +}
7520 +EXPORT_SYMBOL(efx_vi_eventq_kill_callback);
7521 +
7522 +struct efx_vi_dma_map_state {
7523 + struct efhw_buffer_table_allocation bt_handle;
7524 + int n_pages;
7525 + dma_addr_t *dma_addrs;
7526 +};
7527 +
7528 +int
7529 +efx_vi_dma_map_pages(struct efx_vi_state *vih, struct page **pages,
7530 + int n_pages, struct efx_vi_dma_map_state **dmh_out)
7531 +{
7532 + struct efx_vi_state *efx_state = vih;
7533 + int order = fls(n_pages - 1), rc, i, evq_id;
7534 + dma_addr_t dma_addr;
7535 + struct efx_vi_dma_map_state *dm_state;
7536 +
7537 + if (n_pages != (1 << order)) {
7538 + EFRM_WARN("%s: Can only allocate buffers in power of 2 "
7539 + "sizes (not %d)", __func__, n_pages);
7540 + return -EINVAL;
7541 + }
7542 +
7543 + dm_state = kmalloc(sizeof(struct efx_vi_dma_map_state), GFP_KERNEL);
7544 + if (!dm_state)
7545 + return -ENOMEM;
7546 +
7547 + dm_state->dma_addrs = kmalloc(sizeof(dma_addr_t) * n_pages,
7548 + GFP_KERNEL);
7549 + if (!dm_state->dma_addrs) {
7550 + kfree(dm_state);
7551 + return -ENOMEM;
7552 + }
7553 +
7554 + rc = efrm_buffer_table_alloc(order, &dm_state->bt_handle);
7555 + if (rc < 0) {
7556 + kfree(dm_state->dma_addrs);
7557 + kfree(dm_state);
7558 + return rc;
7559 + }
7560 +
7561 + evq_id = EFRM_RESOURCE_INSTANCE(efx_state->vi_res->rs.rs_handle);
7562 + for (i = 0; i < n_pages; i++) {
7563 + /* TODO do we need to get_page() here ? */
7564 +
7565 + dma_addr = pci_map_page(linux_efhw_nic(efx_state->nic)->
7566 + pci_dev, pages[i], 0, PAGE_SIZE,
7567 + PCI_DMA_TODEVICE);
7568 +
7569 + efrm_buffer_table_set(&dm_state->bt_handle, efx_state->nic,
7570 + i, dma_addr, evq_id);
7571 +
7572 + dm_state->dma_addrs[i] = dma_addr;
7573 +
7574 + /* Would be nice to not have to call commit each time, but
7575 + * comment says there are hardware restrictions on how often
7576 + * you can go without it, so do this to be safe */
7577 + efrm_buffer_table_commit();
7578 + }
7579 +
7580 + dm_state->n_pages = n_pages;
7581 +
7582 + *dmh_out = dm_state;
7583 +
7584 + return 0;
7585 +}
7586 +EXPORT_SYMBOL(efx_vi_dma_map_pages);
7587 +
7588 +/* Function needed as Xen can't get pages for grants in dom0, but can
7589 + get dma address */
7590 +int
7591 +efx_vi_dma_map_addrs(struct efx_vi_state *vih,
7592 + unsigned long long *bus_dev_addrs,
7593 + int n_pages, struct efx_vi_dma_map_state **dmh_out)
7594 +{
7595 + struct efx_vi_state *efx_state = vih;
7596 + int order = fls(n_pages - 1), rc, i, evq_id;
7597 + dma_addr_t dma_addr;
7598 + struct efx_vi_dma_map_state *dm_state;
7599 +
7600 + if (n_pages != (1 << order)) {
7601 + EFRM_WARN("%s: Can only allocate buffers in power of 2 "
7602 + "sizes (not %d)", __func__, n_pages);
7603 + return -EINVAL;
7604 + }
7605 +
7606 + dm_state = kmalloc(sizeof(struct efx_vi_dma_map_state), GFP_KERNEL);
7607 + if (!dm_state)
7608 + return -ENOMEM;
7609 +
7610 + dm_state->dma_addrs = kmalloc(sizeof(dma_addr_t) * n_pages,
7611 + GFP_KERNEL);
7612 + if (!dm_state->dma_addrs) {
7613 + kfree(dm_state);
7614 + return -ENOMEM;
7615 + }
7616 +
7617 + rc = efrm_buffer_table_alloc(order, &dm_state->bt_handle);
7618 + if (rc < 0) {
7619 + kfree(dm_state->dma_addrs);
7620 + kfree(dm_state);
7621 + return rc;
7622 + }
7623 +
7624 + evq_id = EFRM_RESOURCE_INSTANCE(efx_state->vi_res->rs.rs_handle);
7625 +#if 0
7626 + EFRM_WARN("%s: mapping %d pages to evq %d, bt_ids %d-%d\n",
7627 + __func__, n_pages, evq_id,
7628 + dm_state->bt_handle.base,
7629 + dm_state->bt_handle.base + n_pages);
7630 +#endif
7631 + for (i = 0; i < n_pages; i++) {
7632 +
7633 + dma_addr = (dma_addr_t)bus_dev_addrs[i];
7634 +
7635 + efrm_buffer_table_set(&dm_state->bt_handle, efx_state->nic,
7636 + i, dma_addr, evq_id);
7637 +
7638 + dm_state->dma_addrs[i] = dma_addr;
7639 +
7640 + /* Would be nice to not have to call commit each time, but
7641 + * comment says there are hardware restrictions on how often
7642 + * you can go without it, so do this to be safe */
7643 + efrm_buffer_table_commit();
7644 + }
7645 +
7646 + dm_state->n_pages = n_pages;
7647 +
7648 + *dmh_out = dm_state;
7649 +
7650 + return 0;
7651 +}
7652 +EXPORT_SYMBOL(efx_vi_dma_map_addrs);
7653 +
7654 +void
7655 +efx_vi_dma_unmap_pages(struct efx_vi_state *vih,
7656 + struct efx_vi_dma_map_state *dmh)
7657 +{
7658 + struct efx_vi_state *efx_state = vih;
7659 + struct efx_vi_dma_map_state *dm_state =
7660 + (struct efx_vi_dma_map_state *)dmh;
7661 + int i;
7662 +
7663 + efrm_buffer_table_free(&dm_state->bt_handle);
7664 +
7665 + for (i = 0; i < dm_state->n_pages; ++i)
7666 + pci_unmap_page(linux_efhw_nic(efx_state->nic)->pci_dev,
7667 + dm_state->dma_addrs[i], PAGE_SIZE,
7668 + PCI_DMA_TODEVICE);
7669 +
7670 + kfree(dm_state->dma_addrs);
7671 + kfree(dm_state);
7672 +
7673 + return;
7674 +}
7675 +EXPORT_SYMBOL(efx_vi_dma_unmap_pages);
7676 +
7677 +void
7678 +efx_vi_dma_unmap_addrs(struct efx_vi_state *vih,
7679 + struct efx_vi_dma_map_state *dmh)
7680 +{
7681 + struct efx_vi_dma_map_state *dm_state =
7682 + (struct efx_vi_dma_map_state *)dmh;
7683 +
7684 + efrm_buffer_table_free(&dm_state->bt_handle);
7685 +
7686 + kfree(dm_state->dma_addrs);
7687 + kfree(dm_state);
7688 +
7689 + return;
7690 +}
7691 +EXPORT_SYMBOL(efx_vi_dma_unmap_addrs);
7692 +
7693 +unsigned
7694 +efx_vi_dma_get_map_addr(struct efx_vi_state *vih,
7695 + struct efx_vi_dma_map_state *dmh)
7696 +{
7697 + struct efx_vi_dma_map_state *dm_state =
7698 + (struct efx_vi_dma_map_state *)dmh;
7699 +
7700 + return EFHW_BUFFER_ADDR(dm_state->bt_handle.base, 0);
7701 +}
7702 +EXPORT_SYMBOL(efx_vi_dma_get_map_addr);
7703 +
7704 +#if EFX_VI_STATIC_FILTERS
7705 +static int
7706 +get_filter(struct efx_vi_state *efx_state,
7707 + efrm_resource_handle_t pthandle, struct filter_resource **fres_out)
7708 +{
7709 + struct filter_list_t *flist;
7710 + if (efx_state->free_fres == NULL)
7711 + return -ENOMEM;
7712 + else {
7713 + flist = efx_state->free_fres;
7714 + efx_state->free_fres = flist->next;
7715 + flist->next = efx_state->used_fres;
7716 + efx_state->used_fres = flist;
7717 + *fres_out = flist->fres;
7718 + return 0;
7719 + }
7720 +}
7721 +#endif
7722 +
7723 +static void
7724 +release_filter(struct efx_vi_state *efx_state, struct filter_resource *fres)
7725 +{
7726 +#if EFX_VI_STATIC_FILTERS
7727 + struct filter_list_t *flist = efx_state->used_fres, *prev = NULL;
7728 + while (flist) {
7729 + if (flist->fres == fres) {
7730 + if (prev)
7731 + prev->next = flist->next;
7732 + else
7733 + efx_state->used_fres = flist->next;
7734 + flist->next = efx_state->free_fres;
7735 + efx_state->free_fres = flist;
7736 + return;
7737 + }
7738 + prev = flist;
7739 + flist = flist->next;
7740 + }
7741 + EFRM_ERR("%s: couldn't find filter", __func__);
7742 +#else
7743 + return efrm_filter_resource_release(fres);
7744 +#endif
7745 +}
7746 +
7747 +int
7748 +efx_vi_filter(struct efx_vi_state *vih, int protocol,
7749 + unsigned ip_addr_be32, int port_le16,
7750 + struct filter_resource_t **fh_out)
7751 +{
7752 + struct efx_vi_state *efx_state = vih;
7753 + struct filter_resource *uninitialized_var(frs);
7754 + int rc;
7755 +
7756 +#if EFX_VI_STATIC_FILTERS
7757 + rc = get_filter(efx_state, efx_state->vi_res->rs.rs_handle, &frs);
7758 +#else
7759 + rc = efrm_filter_resource_alloc(efx_state->vi_res, &frs);
7760 +#endif
7761 + if (rc < 0)
7762 + return rc;
7763 +
7764 + /* Add the hardware filter. We pass in the source port and address
7765 + * as 0 (wildcard) to minimise the number of filters needed. */
7766 + if (protocol == IPPROTO_TCP) {
7767 + rc = efrm_filter_resource_tcp_set(frs, 0, 0, ip_addr_be32,
7768 + port_le16);
7769 + } else {
7770 + rc = efrm_filter_resource_udp_set(frs, 0, 0, ip_addr_be32,
7771 + port_le16);
7772 + }
7773 +
7774 + *fh_out = (struct filter_resource_t *)frs;
7775 +
7776 + return rc;
7777 +}
7778 +EXPORT_SYMBOL(efx_vi_filter);
7779 +
7780 +int
7781 +efx_vi_filter_stop(struct efx_vi_state *vih, struct filter_resource_t *fh)
7782 +{
7783 + struct efx_vi_state *efx_state = vih;
7784 + struct filter_resource *frs = (struct filter_resource *)fh;
7785 + int rc;
7786 +
7787 + rc = efrm_filter_resource_clear(frs);
7788 + release_filter(efx_state, frs);
7789 +
7790 + return rc;
7791 +}
7792 +EXPORT_SYMBOL(efx_vi_filter_stop);
7793 +
7794 +int
7795 +efx_vi_hw_resource_get_virt(struct efx_vi_state *vih,
7796 + struct efx_vi_hw_resource_metadata *mdata,
7797 + struct efx_vi_hw_resource *hw_res_array,
7798 + int *length)
7799 +{
7800 + EFRM_NOTICE("%s: TODO!", __func__);
7801 +
7802 + return 0;
7803 +}
7804 +EXPORT_SYMBOL(efx_vi_hw_resource_get_virt);
7805 +
7806 +int
7807 +efx_vi_hw_resource_get_phys(struct efx_vi_state *vih,
7808 + struct efx_vi_hw_resource_metadata *mdata,
7809 + struct efx_vi_hw_resource *hw_res_array,
7810 + int *length)
7811 +{
7812 + struct efx_vi_state *efx_state = vih;
7813 + struct linux_efhw_nic *lnic = linux_efhw_nic(efx_state->nic);
7814 + unsigned long phys = lnic->ctr_ap_pci_addr;
7815 + struct efrm_resource *ep_res = &efx_state->vi_res->rs;
7816 + unsigned ep_mmap_bytes;
7817 + int i;
7818 +
7819 + if (*length < EFX_VI_HW_RESOURCE_MAXSIZE)
7820 + return -EINVAL;
7821 +
7822 + mdata->nic_arch = efx_state->nic->devtype.arch;
7823 + mdata->nic_variant = efx_state->nic->devtype.variant;
7824 + mdata->nic_revision = efx_state->nic->devtype.revision;
7825 +
7826 + mdata->evq_order =
7827 + efx_state->vi_res->nic_info.evq_pages.iobuff.order;
7828 + mdata->evq_offs = efx_state->vi_res->nic_info.evq_pages.iobuff_off;
7829 + mdata->evq_capacity = efx_vi_eventq_size;
7830 + mdata->instance = EFRM_RESOURCE_INSTANCE(ep_res->rs_handle);
7831 + mdata->rx_capacity = FALCON_DMA_Q_DEFAULT_RX_SIZE;
7832 + mdata->tx_capacity = FALCON_DMA_Q_DEFAULT_TX_SIZE;
7833 +
7834 + ep_mmap_bytes = FALCON_DMA_Q_DEFAULT_MMAP;
7835 + EFRM_ASSERT(ep_mmap_bytes == PAGE_SIZE * 2);
7836 +
7837 +#ifndef NDEBUG
7838 + {
7839 + /* Sanity about doorbells */
7840 + unsigned long tx_dma_page_addr, rx_dma_page_addr;
7841 +
7842 + /* get rx doorbell address */
7843 + rx_dma_page_addr =
7844 + phys + falcon_rx_dma_page_addr(mdata->instance);
7845 + /* get tx doorbell address */
7846 + tx_dma_page_addr =
7847 + phys + falcon_tx_dma_page_addr(mdata->instance);
7848 +
7849 + /* Check the lower bits of the TX doorbell will be
7850 + * consistent. */
7851 + EFRM_ASSERT((TX_DESC_UPD_REG_PAGE4_OFST &
7852 + FALCON_DMA_PAGE_MASK) ==
7853 + (TX_DESC_UPD_REG_PAGE123K_OFST &
7854 + FALCON_DMA_PAGE_MASK));
7855 +
7856 + /* Check the lower bits of the RX doorbell will be
7857 + * consistent. */
7858 + EFRM_ASSERT((RX_DESC_UPD_REG_PAGE4_OFST &
7859 + FALCON_DMA_PAGE_MASK) ==
7860 + (RX_DESC_UPD_REG_PAGE123K_OFST &
7861 + FALCON_DMA_PAGE_MASK));
7862 +
7863 + /* Check that the doorbells will be in the same page. */
7864 + EFRM_ASSERT((TX_DESC_UPD_REG_PAGE4_OFST & PAGE_MASK) ==
7865 + (RX_DESC_UPD_REG_PAGE4_OFST & PAGE_MASK));
7866 +
7867 + /* Check that the doorbells are in the same page. */
7868 + EFRM_ASSERT((tx_dma_page_addr & PAGE_MASK) ==
7869 + (rx_dma_page_addr & PAGE_MASK));
7870 +
7871 + /* Check that the TX doorbell offset is correct. */
7872 + EFRM_ASSERT((TX_DESC_UPD_REG_PAGE4_OFST & ~PAGE_MASK) ==
7873 + (tx_dma_page_addr & ~PAGE_MASK));
7874 +
7875 + /* Check that the RX doorbell offset is correct. */
7876 + EFRM_ASSERT((RX_DESC_UPD_REG_PAGE4_OFST & ~PAGE_MASK) ==
7877 + (rx_dma_page_addr & ~PAGE_MASK));
7878 + }
7879 +#endif
7880 +
7881 + i = 0;
7882 + hw_res_array[i].type = EFX_VI_HW_RESOURCE_TXDMAQ;
7883 + hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL;
7884 + hw_res_array[i].more_to_follow = 0;
7885 + hw_res_array[i].length = PAGE_SIZE;
7886 + hw_res_array[i].address =
7887 + (unsigned long)efx_state->vi_res->nic_info.
7888 + dmaq_pages[EFRM_VI_RM_DMA_QUEUE_TX].kva;
7889 +
7890 + i++;
7891 + hw_res_array[i].type = EFX_VI_HW_RESOURCE_RXDMAQ;
7892 + hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL;
7893 + hw_res_array[i].more_to_follow = 0;
7894 + hw_res_array[i].length = PAGE_SIZE;
7895 + hw_res_array[i].address =
7896 + (unsigned long)efx_state->vi_res->nic_info.
7897 + dmaq_pages[EFRM_VI_RM_DMA_QUEUE_RX].kva;
7898 +
7899 + i++;
7900 + hw_res_array[i].type = EFX_VI_HW_RESOURCE_EVQTIMER;
7901 + hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL;
7902 + hw_res_array[i].more_to_follow = 0;
7903 + hw_res_array[i].length = PAGE_SIZE;
7904 + hw_res_array[i].address =
7905 + (unsigned long)phys + falcon_timer_page_addr(mdata->instance);
7906 +
7907 + /* NB EFX_VI_HW_RESOURCE_EVQPTR not used on Falcon */
7908 +
7909 + i++;
7910 + switch (efx_state->nic->devtype.variant) {
7911 + case 'A':
7912 + hw_res_array[i].type = EFX_VI_HW_RESOURCE_EVQRPTR;
7913 + hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL;
7914 + hw_res_array[i].more_to_follow = 0;
7915 + hw_res_array[i].length = PAGE_SIZE;
7916 + hw_res_array[i].address = (unsigned long)phys +
7917 + EVQ_RPTR_REG_OFST +
7918 + (FALCON_REGISTER128 * mdata->instance);
7919 + break;
7920 + case 'B':
7921 + hw_res_array[i].type = EFX_VI_HW_RESOURCE_EVQRPTR_OFFSET;
7922 + hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL;
7923 + hw_res_array[i].more_to_follow = 0;
7924 + hw_res_array[i].length = PAGE_SIZE;
7925 + hw_res_array[i].address =
7926 + (unsigned long)FALCON_EVQ_RPTR_REG_P0;
7927 + break;
7928 + default:
7929 + EFRM_ASSERT(0);
7930 + break;
7931 + }
7932 +
7933 + i++;
7934 + hw_res_array[i].type = EFX_VI_HW_RESOURCE_EVQMEMKVA;
7935 + hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_IOBUFFER;
7936 + hw_res_array[i].more_to_follow = 0;
7937 + hw_res_array[i].length = PAGE_SIZE;
7938 + hw_res_array[i].address = (unsigned long)efx_state->vi_res->
7939 + nic_info.evq_pages.iobuff.kva;
7940 +
7941 + i++;
7942 + hw_res_array[i].type = EFX_VI_HW_RESOURCE_BELLPAGE;
7943 + hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL;
7944 + hw_res_array[i].more_to_follow = 0;
7945 + hw_res_array[i].length = PAGE_SIZE;
7946 + hw_res_array[i].address =
7947 + (unsigned long)(phys +
7948 + falcon_tx_dma_page_addr(mdata->instance))
7949 + >> PAGE_SHIFT;
7950 +
7951 + i++;
7952 +
7953 + EFRM_ASSERT(i <= *length);
7954 +
7955 + *length = i;
7956 +
7957 + return 0;
7958 +}
7959 +EXPORT_SYMBOL(efx_vi_hw_resource_get_phys);
7960 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/eventq.c
7961 ===================================================================
7962 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
7963 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/eventq.c 2008-07-17 16:18:07.000000000 +0200
7964 @@ -0,0 +1,321 @@
7965 +/****************************************************************************
7966 + * Driver for Solarflare network controllers -
7967 + * resource management for Xen backend, OpenOnload, etc
7968 + * (including support for SFE4001 10GBT NIC)
7969 + *
7970 + * This file contains event queue support.
7971 + *
7972 + * Copyright 2005-2007: Solarflare Communications Inc,
7973 + * 9501 Jeronimo Road, Suite 250,
7974 + * Irvine, CA 92618, USA
7975 + *
7976 + * Developed and maintained by Solarflare Communications:
7977 + * <linux-xen-drivers@solarflare.com>
7978 + * <onload-dev@solarflare.com>
7979 + *
7980 + *
7981 + * This program is free software; you can redistribute it and/or modify it
7982 + * under the terms of the GNU General Public License version 2 as published
7983 + * by the Free Software Foundation, incorporated herein by reference.
7984 + *
7985 + * This program is distributed in the hope that it will be useful,
7986 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7987 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7988 + * GNU General Public License for more details.
7989 + *
7990 + * You should have received a copy of the GNU General Public License
7991 + * along with this program; if not, write to the Free Software
7992 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7993 + ****************************************************************************
7994 + */
7995 +
7996 +#include <ci/efhw/debug.h>
7997 +#include <ci/efhw/iopage.h>
7998 +#include <ci/driver/efab/hardware.h>
7999 +#include <ci/efhw/eventq.h>
8000 +#include <ci/efhw/falcon.h>
8001 +#include <ci/efhw/nic.h>
8002 +
8003 +#define KEVENTQ_MAGIC 0x07111974
8004 +
8005 +/*! Helper function to allocate the iobuffer needed by an eventq
8006 + * - it ensures the eventq has the correct alignment for the NIC
8007 + *
8008 + * \param rm Event-queue resource manager
8009 + * \param instance Event-queue instance (index)
8010 + * \param buf_bytes Requested size of eventq
8011 + * \return < 0 if iobuffer allocation fails
8012 + */
8013 +int
8014 +efhw_nic_event_queue_alloc_iobuffer(struct efhw_nic *nic,
8015 + struct eventq_resource_hardware *h,
8016 + int evq_instance, unsigned buf_bytes)
8017 +{
8018 + unsigned int page_order;
8019 + int rc;
8020 +
8021 + /* Allocate an iobuffer. */
8022 + page_order = get_order(buf_bytes);
8023 +
8024 + h->iobuff_off = 0;
8025 +
8026 + EFHW_TRACE("allocating eventq size %x",
8027 + 1u << (page_order + PAGE_SHIFT));
8028 + rc = efhw_iopages_alloc(nic, &h->iobuff, page_order);
8029 + if (rc < 0) {
8030 + EFHW_WARN("%s: failed to allocate %u pages",
8031 + __func__, 1u << page_order);
8032 + return rc;
8033 + }
8034 +
8035 + /* Set the eventq pages to match EFHW_CLEAR_EVENT() */
8036 + if (EFHW_CLEAR_EVENT_VALUE)
8037 + memset(efhw_iopages_ptr(&h->iobuff) + h->iobuff_off,
8038 + EFHW_CLEAR_EVENT_VALUE, (1u << page_order) * PAGE_SIZE);
8039 +
8040 + EFHW_TRACE("%s: allocated %u pages", __func__, 1u << (page_order));
8041 +
8042 + /* For Falcon the NIC is programmed with the base buffer address of a
8043 + * contiguous region of buffer space. This means that larger than a
8044 + * PAGE event queues can be expected to allocate even when the host's
8045 + * physical memory is fragmented */
8046 + EFHW_ASSERT(efhw_nic_have_hw(nic));
8047 + EFHW_ASSERT(page_order <= h->buf_tbl_alloc.order);
8048 +
8049 + /* Initialise the buffer table entries. */
8050 + falcon_nic_buffer_table_set_n(nic, h->buf_tbl_alloc.base,
8051 + efhw_iopages_dma_addr(&h->iobuff) +
8052 + h->iobuff_off, EFHW_NIC_PAGE_SIZE, 0,
8053 + 1 << page_order, 0);
8054 +
8055 + if (evq_instance >= FALCON_EVQ_TBL_RESERVED)
8056 + falcon_nic_buffer_table_confirm(nic);
8057 + return 0;
8058 +}
8059 +
8060 +/**********************************************************************
8061 + * Kernel event queue management.
8062 + */
8063 +
8064 +/* Values for [struct efhw_keventq::lock] field. */
8065 +#define KEVQ_UNLOCKED 0
8066 +#define KEVQ_LOCKED 1
8067 +#define KEVQ_RECHECK 2
8068 +
8069 +int
8070 +efhw_keventq_ctor(struct efhw_nic *nic, int instance,
8071 + struct efhw_keventq *evq,
8072 + struct efhw_ev_handler *ev_handlers)
8073 +{
8074 + int rc;
8075 + unsigned buf_bytes = evq->hw.capacity * sizeof(efhw_event_t);
8076 +
8077 + evq->instance = instance;
8078 + evq->ev_handlers = ev_handlers;
8079 +
8080 + /* allocate an IObuffer for the eventq */
8081 + rc = efhw_nic_event_queue_alloc_iobuffer(nic, &evq->hw, evq->instance,
8082 + buf_bytes);
8083 + if (rc < 0)
8084 + return rc;
8085 +
8086 + /* Zero the timer-value for this queue.
8087 + AND Tell the nic about the event queue. */
8088 + efhw_nic_event_queue_enable(nic, evq->instance, evq->hw.capacity,
8089 + efhw_iopages_dma_addr(&evq->hw.iobuff) +
8090 + evq->hw.iobuff_off,
8091 + evq->hw.buf_tbl_alloc.base,
8092 + 1 /* interrupting */);
8093 +
8094 + evq->lock = KEVQ_UNLOCKED;
8095 + evq->evq_base = efhw_iopages_ptr(&evq->hw.iobuff) + evq->hw.iobuff_off;
8096 + evq->evq_ptr = 0;
8097 + evq->evq_mask = (evq->hw.capacity * sizeof(efhw_event_t)) - 1u;
8098 +
8099 + EFHW_TRACE("%s: [%d] base=%p end=%p", __func__, evq->instance,
8100 + evq->evq_base, evq->evq_base + buf_bytes);
8101 +
8102 + return 0;
8103 +}
8104 +
8105 +void efhw_keventq_dtor(struct efhw_nic *nic, struct efhw_keventq *evq)
8106 +{
8107 + EFHW_ASSERT(evq);
8108 +
8109 + EFHW_TRACE("%s: [%d]", __func__, evq->instance);
8110 +
8111 + /* Zero the timer-value for this queue.
8112 + And Tell NIC to stop using this event queue. */
8113 + efhw_nic_event_queue_disable(nic, evq->instance, 0);
8114 +
8115 + /* free the pages used by the eventq itself */
8116 + efhw_iopages_free(nic, &evq->hw.iobuff);
8117 +}
8118 +
8119 +void
8120 +efhw_handle_txdmaq_flushed(struct efhw_nic *nic, struct efhw_ev_handler *h,
8121 + efhw_event_t *evp)
8122 +{
8123 + int instance = (int)FALCON_EVENT_TX_FLUSH_Q_ID(evp);
8124 + EFHW_TRACE("%s: instance=%d", __func__, instance);
8125 +
8126 + if (!h->dmaq_flushed_fn) {
8127 + EFHW_WARN("%s: no handler registered", __func__);
8128 + return;
8129 + }
8130 +
8131 + h->dmaq_flushed_fn(nic, instance, false);
8132 +}
8133 +
8134 +void
8135 +efhw_handle_rxdmaq_flushed(struct efhw_nic *nic, struct efhw_ev_handler *h,
8136 + efhw_event_t *evp)
8137 +{
8138 + unsigned instance = (unsigned)FALCON_EVENT_RX_FLUSH_Q_ID(evp);
8139 + EFHW_TRACE("%s: instance=%d", __func__, instance);
8140 +
8141 + if (!h->dmaq_flushed_fn) {
8142 + EFHW_WARN("%s: no handler registered", __func__);
8143 + return;
8144 + }
8145 +
8146 + h->dmaq_flushed_fn(nic, instance, true);
8147 +}
8148 +
8149 +void
8150 +efhw_handle_wakeup_event(struct efhw_nic *nic, struct efhw_ev_handler *h,
8151 + efhw_event_t *evp)
8152 +{
8153 + unsigned instance = (unsigned)FALCON_EVENT_WAKE_EVQ_ID(evp);
8154 +
8155 + if (!h->wakeup_fn) {
8156 + EFHW_WARN("%s: no handler registered", __func__);
8157 + return;
8158 + }
8159 +
8160 + h->wakeup_fn(nic, instance);
8161 +}
8162 +
8163 +void
8164 +efhw_handle_timeout_event(struct efhw_nic *nic, struct efhw_ev_handler *h,
8165 + efhw_event_t *evp)
8166 +{
8167 + unsigned instance = (unsigned)FALCON_EVENT_WAKE_EVQ_ID(evp);
8168 +
8169 + if (!h->timeout_fn) {
8170 + EFHW_WARN("%s: no handler registered", __func__);
8171 + return;
8172 + }
8173 +
8174 + h->timeout_fn(nic, instance);
8175 +}
8176 +
8177 +/**********************************************************************
8178 + * Kernel event queue event handling.
8179 + */
8180 +
8181 +int efhw_keventq_poll(struct efhw_nic *nic, struct efhw_keventq *q)
8182 +{
8183 + efhw_event_t *ev;
8184 + int l, count = 0;
8185 +
8186 + EFHW_ASSERT(nic);
8187 + EFHW_ASSERT(q);
8188 + EFHW_ASSERT(q->ev_handlers);
8189 +
8190 + /* Acquire the lock, or mark the queue as needing re-checking. */
8191 + for (;;) {
8192 + l = q->lock;
8193 + if (l == KEVQ_UNLOCKED) {
8194 + if ((int)cmpxchg(&q->lock, l, KEVQ_LOCKED) == l)
8195 + break;
8196 + } else if (l == KEVQ_LOCKED) {
8197 + if ((int)cmpxchg(&q->lock, l, KEVQ_RECHECK) == l)
8198 + return 0;
8199 + } else { /* already marked for re-checking */
8200 + EFHW_ASSERT(l == KEVQ_RECHECK);
8201 + return 0;
8202 + }
8203 + }
8204 +
8205 + if (unlikely(EFHW_EVENT_OVERFLOW(q, q)))
8206 + goto overflow;
8207 +
8208 + ev = EFHW_EVENT_PTR(q, q, 0);
8209 +
8210 +#ifndef NDEBUG
8211 + if (!EFHW_IS_EVENT(ev))
8212 + EFHW_TRACE("%s: %d NO EVENTS!", __func__, q->instance);
8213 +#endif
8214 +
8215 + for (;;) {
8216 + /* Convention for return codes for handlers is:
8217 + ** 0 - no error, event consumed
8218 + ** 1 - no error, event not consumed
8219 + ** -ve - error, event not consumed
8220 + */
8221 + if (likely(EFHW_IS_EVENT(ev))) {
8222 + count++;
8223 +
8224 + switch (FALCON_EVENT_CODE(ev)) {
8225 +
8226 + case FALCON_EVENT_CODE_CHAR:
8227 + falcon_handle_char_event(nic, q->ev_handlers,
8228 + ev);
8229 + break;
8230 +
8231 + default:
8232 + EFHW_ERR("efhw_keventq_poll: [%d] UNEXPECTED "
8233 + "EVENT:"FALCON_EVENT_FMT,
8234 + q->instance,
8235 + FALCON_EVENT_PRI_ARG(*ev));
8236 + }
8237 +
8238 + EFHW_CLEAR_EVENT(ev);
8239 + EFHW_EVENTQ_NEXT(q);
8240 +
8241 + ev = EFHW_EVENT_PTR(q, q, 0);
8242 + } else {
8243 + /* No events left. Release the lock (checking if we
8244 + * need to re-poll to avoid race). */
8245 + l = q->lock;
8246 + if (l == KEVQ_LOCKED) {
8247 + if ((int)cmpxchg(&q->lock, l, KEVQ_UNLOCKED)
8248 + == l) {
8249 + EFHW_TRACE
8250 + ("efhw_keventq_poll: %d clean exit",
8251 + q->instance);
8252 + goto clean_exit;
8253 + }
8254 + }
8255 +
8256 + /* Potentially more work to do. */
8257 + l = q->lock;
8258 + EFHW_ASSERT(l == KEVQ_RECHECK);
8259 + EFHW_TEST((int)cmpxchg(&q->lock, l, KEVQ_LOCKED) == l);
8260 + EFHW_TRACE("efhw_keventq_poll: %d re-poll required",
8261 + q->instance);
8262 + }
8263 + }
8264 +
8265 + /* shouldn't get here */
8266 + EFHW_ASSERT(0);
8267 +
8268 +overflow:
8269 + /* ?? Oh dear. Should we poll everything that could have possibly
8270 + ** happened? Or merely cry out in anguish...
8271 + */
8272 + EFHW_WARN("efhw_keventq_poll: %d ***** OVERFLOW nic %d *****",
8273 + q->instance, nic->index);
8274 +
8275 + q->lock = KEVQ_UNLOCKED;
8276 + return count;
8277 +
8278 +clean_exit:
8279 + /* Ack the processed events so that this event queue can potentially
8280 + raise interrupts again */
8281 + falcon_nic_evq_ack(nic, q->instance,
8282 + (EFHW_EVENT_OFFSET(q, q, 0) / sizeof(efhw_event_t)),
8283 + false);
8284 + return count;
8285 +}
8286 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/falcon.c
8287 ===================================================================
8288 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
8289 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/falcon.c 2008-07-17 16:18:07.000000000 +0200
8290 @@ -0,0 +1,2525 @@
8291 +/****************************************************************************
8292 + * Driver for Solarflare network controllers -
8293 + * resource management for Xen backend, OpenOnload, etc
8294 + * (including support for SFE4001 10GBT NIC)
8295 + *
8296 + * This file contains Falcon hardware support.
8297 + *
8298 + * Copyright 2005-2007: Solarflare Communications Inc,
8299 + * 9501 Jeronimo Road, Suite 250,
8300 + * Irvine, CA 92618, USA
8301 + *
8302 + * Developed and maintained by Solarflare Communications:
8303 + * <linux-xen-drivers@solarflare.com>
8304 + * <onload-dev@solarflare.com>
8305 + *
8306 + *
8307 + * This program is free software; you can redistribute it and/or modify it
8308 + * under the terms of the GNU General Public License version 2 as published
8309 + * by the Free Software Foundation, incorporated herein by reference.
8310 + *
8311 + * This program is distributed in the hope that it will be useful,
8312 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8313 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8314 + * GNU General Public License for more details.
8315 + *
8316 + * You should have received a copy of the GNU General Public License
8317 + * along with this program; if not, write to the Free Software
8318 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8319 + ****************************************************************************
8320 + */
8321 +
8322 +#include <ci/driver/efab/hardware.h>
8323 +#include <ci/efhw/debug.h>
8324 +#include <ci/efhw/iopage.h>
8325 +#include <ci/efhw/falcon.h>
8326 +#include <ci/efhw/falcon_hash.h>
8327 +#include <ci/efhw/nic.h>
8328 +#include <ci/efhw/eventq.h>
8329 +#include <ci/efhw/checks.h>
8330 +
8331 +
8332 +/*----------------------------------------------------------------------------
8333 + *
8334 + * Workarounds and options
8335 + *
8336 + *---------------------------------------------------------------------------*/
8337 +
8338 +/* Keep a software copy of the filter table and check for duplicates. */
8339 +#define FALCON_FULL_FILTER_CACHE 1
8340 +
8341 +/* Read filters back from the hardware to detect corruption. */
8342 +#define FALCON_VERIFY_FILTERS 0
8343 +
8344 +/* Options */
8345 +#define RX_FILTER_CTL_SRCH_LIMIT_TCP_FULL 8 /* default search limit */
8346 +#define RX_FILTER_CTL_SRCH_LIMIT_TCP_WILD 8 /* default search limit */
8347 +#define RX_FILTER_CTL_SRCH_LIMIT_UDP_FULL 8 /* default search limit */
8348 +#define RX_FILTER_CTL_SRCH_LIMIT_UDP_WILD 8 /* default search limit */
8349 +
8350 +#define FALCON_MAC_SET_TYPE_BY_SPEED 0
8351 +
8352 +/* FIXME: We should detect mode at runtime. */
8353 +#define FALCON_BUFFER_TABLE_FULL_MODE 1
8354 +
8355 +/* "Fudge factors" - difference between programmed value and actual depth */
8356 +#define RX_FILTER_CTL_SRCH_FUDGE_WILD 3 /* increase the search limit */
8357 +#define RX_FILTER_CTL_SRCH_FUDGE_FULL 1 /* increase the search limit */
8358 +#define TX_FILTER_CTL_SRCH_FUDGE_WILD 3 /* increase the search limit */
8359 +#define TX_FILTER_CTL_SRCH_FUDGE_FULL 1 /* increase the search limit */
8360 +
8361 +/*----------------------------------------------------------------------------
8362 + *
8363 + * Debug Macros
8364 + *
8365 + *---------------------------------------------------------------------------*/
8366 +
8367 +#define _DEBUG_SYM_ static
8368 +
8369 + /*----------------------------------------------------------------------------
8370 + *
8371 + * Macros and forward declarations
8372 + *
8373 + *--------------------------------------------------------------------------*/
8374 +
8375 +#define FALCON_REGION_NUM 4 /* number of supported memory regions */
8376 +
8377 +#define FALCON_BUFFER_TBL_HALF_BYTES 4
8378 +#define FALCON_BUFFER_TBL_FULL_BYTES 8
8379 +
8380 +/* Shadow buffer table - hack for testing only */
8381 +#if FALCON_BUFFER_TABLE_FULL_MODE == 0
8382 +# define FALCON_USE_SHADOW_BUFFER_TABLE 1
8383 +#else
8384 +# define FALCON_USE_SHADOW_BUFFER_TABLE 0
8385 +#endif
8386 +
8387 +
8388 +/*----------------------------------------------------------------------------
8389 + *
8390 + * Header assertion checks
8391 + *
8392 + *---------------------------------------------------------------------------*/
8393 +
8394 +#define FALCON_ASSERT_VALID() /* nothing yet */
8395 +
8396 +/* Falcon has a 128bit register model but most registers have useful
8397 + defaults or only implement a small number of bits. Some registers
8398 + can be programmed 32bits UNLOCKED all others should be interlocked
8399 + against other threads within the same protection domain.
8400 +
8401 + Aim is for software to perform the minimum number of writes and
8402 + also to minimise the read-modify-write activity (which generally
8403 + indicates a lack of clarity in the use model).
8404 +
8405 + Registers which are programmed in this module are listed below
8406 + together with the method of access. Care must be taken to ensure
8407 + remain adequate if the register spec changes.
8408 +
8409 + All 128bits programmed
8410 + FALCON_BUFFER_TBL_HALF
8411 + RX_FILTER_TBL
8412 + TX_DESC_PTR_TBL
8413 + RX_DESC_PTR_TBL
8414 + DRV_EV_REG
8415 +
8416 + All 64bits programmed
8417 + FALCON_BUFFER_TBL_FULL
8418 +
8419 + 32 bits are programmed (UNLOCKED)
8420 + EVQ_RPTR_REG
8421 +
8422 + Low 64bits programmed remainder are written with a random number
8423 + RX_DC_CFG_REG
8424 + TX_DC_CFG_REG
8425 + SRM_RX_DC_CFG_REG
8426 + SRM_TX_DC_CFG_REG
8427 + BUF_TBL_CFG_REG
8428 + BUF_TBL_UPD_REG
8429 + SRM_UPD_EVQ_REG
8430 + EVQ_PTR_TBL
8431 + TIMER_CMD_REG
8432 + TX_PACE_TBL
8433 + FATAL_INTR_REG
8434 + INT_EN_REG (When enabling interrupts)
8435 + TX_FLUSH_DESCQ_REG
8436 + RX_FLUSH_DESCQ
8437 +
8438 + Read Modify Write on low 32bits remainder are written with a random number
8439 + INT_EN_REG (When sending a driver interrupt)
8440 + DRIVER_REGX
8441 +
8442 + Read Modify Write on low 64bits remainder are written with a random number
8443 + SRM_CFG_REG_OFST
8444 + RX_CFG_REG_OFST
8445 + RX_FILTER_CTL_REG
8446 +
8447 + Read Modify Write on full 128bits
8448 + TXDP_RESERVED_REG (aka TXDP_UNDOCUMENTED)
8449 + TX_CFG_REG
8450 +
8451 +*/
8452 +
8453 +
8454 +/*----------------------------------------------------------------------------
8455 + *
8456 + * DMAQ low-level register interface
8457 + *
8458 + *---------------------------------------------------------------------------*/
8459 +
8460 +static unsigned dmaq_sizes[] = {
8461 + 512,
8462 + EFHW_1K,
8463 + EFHW_2K,
8464 + EFHW_4K,
8465 +};
8466 +
8467 +#define N_DMAQ_SIZES (sizeof(dmaq_sizes) / sizeof(dmaq_sizes[0]))
8468 +
8469 +static inline ulong falcon_dma_tx_q_offset(struct efhw_nic *nic, unsigned dmaq)
8470 +{
8471 + EFHW_ASSERT(dmaq < nic->num_dmaqs);
8472 + return TX_DESC_PTR_TBL_OFST + dmaq * FALCON_REGISTER128;
8473 +}
8474 +
8475 +static inline uint falcon_dma_tx_q_size_index(uint dmaq_size)
8476 +{
8477 + uint i;
8478 +
8479 + /* size must be one of the various options, otherwise we assert */
8480 + for (i = 0; i < N_DMAQ_SIZES; i++) {
8481 + if (dmaq_size == dmaq_sizes[i])
8482 + break;
8483 + }
8484 + EFHW_ASSERT(i < N_DMAQ_SIZES);
8485 + return i;
8486 +}
8487 +
8488 +static void
8489 +falcon_dmaq_tx_q_init(struct efhw_nic *nic,
8490 + uint dmaq, uint evq_id, uint own_id,
8491 + uint tag, uint dmaq_size, uint buf_idx, uint flags)
8492 +{
8493 + FALCON_LOCK_DECL;
8494 + uint index, desc_type;
8495 + uint64_t val1, val2, val3;
8496 + ulong offset;
8497 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
8498 +
8499 + /* Q attributes */
8500 + int iscsi_hdig_en = ((flags & EFHW_VI_ISCSI_TX_HDIG_EN) != 0);
8501 + int iscsi_ddig_en = ((flags & EFHW_VI_ISCSI_TX_DDIG_EN) != 0);
8502 + int csum_ip_dis = ((flags & EFHW_VI_TX_IP_CSUM_DIS) != 0);
8503 + int csum_tcp_dis = ((flags & EFHW_VI_TX_TCPUDP_CSUM_DIS) != 0);
8504 + int non_ip_drop_dis = ((flags & EFHW_VI_TX_TCPUDP_ONLY) == 0);
8505 +
8506 + /* initialise the TX descriptor queue pointer table */
8507 +
8508 + /* NB physical vs buffer addressing is determined by the Queue ID. */
8509 +
8510 + offset = falcon_dma_tx_q_offset(nic, dmaq);
8511 + index = falcon_dma_tx_q_size_index(dmaq_size);
8512 +
8513 + /* allow VI flag to override this queue's descriptor type */
8514 + desc_type = (flags & EFHW_VI_TX_PHYS_ADDR_EN) ? 0 : 1;
8515 +
8516 + /* bug9403: It is dangerous to allow buffer-addressed queues to
8517 + * have owner_id=0. */
8518 + EFHW_ASSERT((own_id > 0) || desc_type == 0);
8519 +
8520 + /* dword 1 */
8521 + __DWCHCK(TX_DESCQ_FLUSH_LBN, TX_DESCQ_FLUSH_WIDTH);
8522 + __DWCHCK(TX_DESCQ_TYPE_LBN, TX_DESCQ_TYPE_WIDTH);
8523 + __DWCHCK(TX_DESCQ_SIZE_LBN, TX_DESCQ_SIZE_WIDTH);
8524 + __DWCHCK(TX_DESCQ_LABEL_LBN, TX_DESCQ_LABEL_WIDTH);
8525 + __DWCHCK(TX_DESCQ_OWNER_ID_LBN, TX_DESCQ_OWNER_ID_WIDTH);
8526 +
8527 + __LWCHK(TX_DESCQ_EVQ_ID_LBN, TX_DESCQ_EVQ_ID_WIDTH);
8528 +
8529 + __RANGECHCK(1, TX_DESCQ_FLUSH_WIDTH);
8530 + __RANGECHCK(desc_type, TX_DESCQ_TYPE_WIDTH);
8531 + __RANGECHCK(index, TX_DESCQ_SIZE_WIDTH);
8532 + __RANGECHCK(tag, TX_DESCQ_LABEL_WIDTH);
8533 + __RANGECHCK(own_id, TX_DESCQ_OWNER_ID_WIDTH);
8534 + __RANGECHCK(evq_id, TX_DESCQ_EVQ_ID_WIDTH);
8535 +
8536 + val1 = ((desc_type << TX_DESCQ_TYPE_LBN) |
8537 + (index << TX_DESCQ_SIZE_LBN) |
8538 + (tag << TX_DESCQ_LABEL_LBN) |
8539 + (own_id << TX_DESCQ_OWNER_ID_LBN) |
8540 + (__LOW(evq_id, TX_DESCQ_EVQ_ID_LBN, TX_DESCQ_EVQ_ID_WIDTH)));
8541 +
8542 + /* dword 2 */
8543 + __DW2CHCK(TX_DESCQ_BUF_BASE_ID_LBN, TX_DESCQ_BUF_BASE_ID_WIDTH);
8544 + __RANGECHCK(buf_idx, TX_DESCQ_BUF_BASE_ID_WIDTH);
8545 +
8546 + val2 = ((__HIGH(evq_id, TX_DESCQ_EVQ_ID_LBN, TX_DESCQ_EVQ_ID_WIDTH)) |
8547 + (buf_idx << __DW2(TX_DESCQ_BUF_BASE_ID_LBN)));
8548 +
8549 + /* dword 3 */
8550 + __DW3CHCK(TX_ISCSI_HDIG_EN_LBN, TX_ISCSI_HDIG_EN_WIDTH);
8551 + __DW3CHCK(TX_ISCSI_DDIG_EN_LBN, TX_ISCSI_DDIG_EN_WIDTH);
8552 + __RANGECHCK(iscsi_hdig_en, TX_ISCSI_HDIG_EN_WIDTH);
8553 + __RANGECHCK(iscsi_ddig_en, TX_ISCSI_DDIG_EN_WIDTH);
8554 +
8555 + val3 = ((iscsi_hdig_en << __DW3(TX_ISCSI_HDIG_EN_LBN)) |
8556 + (iscsi_ddig_en << __DW3(TX_ISCSI_DDIG_EN_LBN)) |
8557 + (1 << __DW3(TX_DESCQ_EN_LBN))); /* queue enable bit */
8558 +
8559 + switch (nic->devtype.variant) {
8560 + case 'B':
8561 + __DW3CHCK(TX_NON_IP_DROP_DIS_B0_LBN,
8562 + TX_NON_IP_DROP_DIS_B0_WIDTH);
8563 + __DW3CHCK(TX_IP_CHKSM_DIS_B0_LBN, TX_IP_CHKSM_DIS_B0_WIDTH);
8564 + __DW3CHCK(TX_TCP_CHKSM_DIS_B0_LBN, TX_TCP_CHKSM_DIS_B0_WIDTH);
8565 +
8566 + val3 |= ((non_ip_drop_dis << __DW3(TX_NON_IP_DROP_DIS_B0_LBN))|
8567 + (csum_ip_dis << __DW3(TX_IP_CHKSM_DIS_B0_LBN)) |
8568 + (csum_tcp_dis << __DW3(TX_TCP_CHKSM_DIS_B0_LBN)));
8569 + break;
8570 + case 'A':
8571 + if (csum_ip_dis || csum_tcp_dis || !non_ip_drop_dis)
8572 + EFHW_WARN
8573 + ("%s: bad settings for A1 csum_ip_dis=%d "
8574 + "csum_tcp_dis=%d non_ip_drop_dis=%d",
8575 + __func__, csum_ip_dis,
8576 + csum_tcp_dis, non_ip_drop_dis);
8577 + break;
8578 + default:
8579 + EFHW_ASSERT(0);
8580 + break;
8581 + }
8582 +
8583 + EFHW_TRACE("%s: txq %x evq %u tag %x id %x buf %x "
8584 + "%x:%x:%x->%" PRIx64 ":%" PRIx64 ":%" PRIx64,
8585 + __func__,
8586 + dmaq, evq_id, tag, own_id, buf_idx, dmaq_size,
8587 + iscsi_hdig_en, iscsi_ddig_en, val1, val2, val3);
8588 +
8589 + /* Falcon requires 128 bit atomic access for this register */
8590 + FALCON_LOCK_LOCK(nic);
8591 + falcon_write_qq(efhw_kva + offset, ((val2 << 32) | val1), val3);
8592 + mmiowb();
8593 + FALCON_LOCK_UNLOCK(nic);
8594 + return;
8595 +}
8596 +
8597 +static inline ulong
8598 +falcon_dma_rx_q_offset(struct efhw_nic *nic, unsigned dmaq)
8599 +{
8600 + EFHW_ASSERT(dmaq < nic->num_dmaqs);
8601 + return RX_DESC_PTR_TBL_OFST + dmaq * FALCON_REGISTER128;
8602 +}
8603 +
8604 +static void
8605 +falcon_dmaq_rx_q_init(struct efhw_nic *nic,
8606 + uint dmaq, uint evq_id, uint own_id,
8607 + uint tag, uint dmaq_size, uint buf_idx, uint flags)
8608 +{
8609 + FALCON_LOCK_DECL;
8610 + uint i, desc_type = 1;
8611 + uint64_t val1, val2, val3;
8612 + ulong offset;
8613 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
8614 +
8615 + /* Q attributes */
8616 +#if BUG5762_WORKAROUND
8617 + int jumbo = 1; /* Queues must not have mixed types */
8618 +#else
8619 + int jumbo = ((flags & EFHW_VI_JUMBO_EN) != 0);
8620 +#endif
8621 + int iscsi_hdig_en = ((flags & EFHW_VI_ISCSI_RX_HDIG_EN) != 0);
8622 + int iscsi_ddig_en = ((flags & EFHW_VI_ISCSI_RX_DDIG_EN) != 0);
8623 +
8624 + /* initialise the TX descriptor queue pointer table */
8625 + offset = falcon_dma_rx_q_offset(nic, dmaq);
8626 +
8627 + /* size must be one of the various options, otherwise we assert */
8628 + for (i = 0; i < N_DMAQ_SIZES; i++) {
8629 + if (dmaq_size == dmaq_sizes[i])
8630 + break;
8631 + }
8632 + EFHW_ASSERT(i < N_DMAQ_SIZES);
8633 +
8634 + /* allow VI flag to override this queue's descriptor type */
8635 + desc_type = (flags & EFHW_VI_RX_PHYS_ADDR_EN) ? 0 : 1;
8636 +
8637 + /* bug9403: It is dangerous to allow buffer-addressed queues to have
8638 + * owner_id=0 */
8639 + EFHW_ASSERT((own_id > 0) || desc_type == 0);
8640 +
8641 + /* dword 1 */
8642 + __DWCHCK(RX_DESCQ_EN_LBN, RX_DESCQ_EN_WIDTH);
8643 + __DWCHCK(RX_DESCQ_JUMBO_LBN, RX_DESCQ_JUMBO_WIDTH);
8644 + __DWCHCK(RX_DESCQ_TYPE_LBN, RX_DESCQ_TYPE_WIDTH);
8645 + __DWCHCK(RX_DESCQ_SIZE_LBN, RX_DESCQ_SIZE_WIDTH);
8646 + __DWCHCK(RX_DESCQ_LABEL_LBN, RX_DESCQ_LABEL_WIDTH);
8647 + __DWCHCK(RX_DESCQ_OWNER_ID_LBN, RX_DESCQ_OWNER_ID_WIDTH);
8648 +
8649 + __LWCHK(RX_DESCQ_EVQ_ID_LBN, RX_DESCQ_EVQ_ID_WIDTH);
8650 +
8651 + __RANGECHCK(1, RX_DESCQ_EN_WIDTH);
8652 + __RANGECHCK(jumbo, RX_DESCQ_JUMBO_WIDTH);
8653 + __RANGECHCK(desc_type, RX_DESCQ_TYPE_WIDTH);
8654 + __RANGECHCK(i, RX_DESCQ_SIZE_WIDTH);
8655 + __RANGECHCK(tag, RX_DESCQ_LABEL_WIDTH);
8656 + __RANGECHCK(own_id, RX_DESCQ_OWNER_ID_WIDTH);
8657 + __RANGECHCK(evq_id, RX_DESCQ_EVQ_ID_WIDTH);
8658 +
8659 + val1 = ((1 << RX_DESCQ_EN_LBN) |
8660 + (jumbo << RX_DESCQ_JUMBO_LBN) |
8661 + (desc_type << RX_DESCQ_TYPE_LBN) |
8662 + (i << RX_DESCQ_SIZE_LBN) |
8663 + (tag << RX_DESCQ_LABEL_LBN) |
8664 + (own_id << RX_DESCQ_OWNER_ID_LBN) |
8665 + (__LOW(evq_id, RX_DESCQ_EVQ_ID_LBN, RX_DESCQ_EVQ_ID_WIDTH)));
8666 +
8667 + /* dword 2 */
8668 + __DW2CHCK(RX_DESCQ_BUF_BASE_ID_LBN, RX_DESCQ_BUF_BASE_ID_WIDTH);
8669 + __RANGECHCK(buf_idx, RX_DESCQ_BUF_BASE_ID_WIDTH);
8670 +
8671 + val2 = ((__HIGH(evq_id, RX_DESCQ_EVQ_ID_LBN, RX_DESCQ_EVQ_ID_WIDTH)) |
8672 + (buf_idx << __DW2(RX_DESCQ_BUF_BASE_ID_LBN)));
8673 +
8674 + /* dword 3 */
8675 + __DW3CHCK(RX_ISCSI_HDIG_EN_LBN, RX_ISCSI_HDIG_EN_WIDTH);
8676 + __DW3CHCK(RX_ISCSI_DDIG_EN_LBN, RX_ISCSI_DDIG_EN_WIDTH);
8677 + __RANGECHCK(iscsi_hdig_en, RX_ISCSI_HDIG_EN_WIDTH);
8678 + __RANGECHCK(iscsi_ddig_en, RX_ISCSI_DDIG_EN_WIDTH);
8679 +
8680 + val3 = (iscsi_hdig_en << __DW3(RX_ISCSI_HDIG_EN_LBN)) |
8681 + (iscsi_ddig_en << __DW3(RX_ISCSI_DDIG_EN_LBN));
8682 +
8683 + EFHW_TRACE("%s: rxq %x evq %u tag %x id %x buf %x %s "
8684 + "%x:%x:%x -> %" PRIx64 ":%" PRIx64 ":%" PRIx64,
8685 + __func__,
8686 + dmaq, evq_id, tag, own_id, buf_idx,
8687 + jumbo ? "jumbo" : "normal", dmaq_size,
8688 + iscsi_hdig_en, iscsi_ddig_en, val1, val2, val3);
8689 +
8690 + /* Falcon requires 128 bit atomic access for this register */
8691 + FALCON_LOCK_LOCK(nic);
8692 + falcon_write_qq(efhw_kva + offset, ((val2 << 32) | val1), val3);
8693 + mmiowb();
8694 + FALCON_LOCK_UNLOCK(nic);
8695 + return;
8696 +}
8697 +
8698 +static void falcon_dmaq_tx_q_disable(struct efhw_nic *nic, uint dmaq)
8699 +{
8700 + FALCON_LOCK_DECL;
8701 + uint64_t val1, val2, val3;
8702 + ulong offset;
8703 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
8704 +
8705 + /* initialise the TX descriptor queue pointer table */
8706 +
8707 + offset = falcon_dma_tx_q_offset(nic, dmaq);
8708 +
8709 + /* dword 1 */
8710 + __DWCHCK(TX_DESCQ_TYPE_LBN, TX_DESCQ_TYPE_WIDTH);
8711 +
8712 + val1 = ((uint64_t) 1 << TX_DESCQ_TYPE_LBN);
8713 +
8714 + /* dword 2 */
8715 + val2 = 0;
8716 +
8717 + /* dword 3 */
8718 + val3 = (0 << __DW3(TX_DESCQ_EN_LBN)); /* queue enable bit */
8719 +
8720 + EFHW_TRACE("%s: %x->%" PRIx64 ":%" PRIx64 ":%" PRIx64,
8721 + __func__, dmaq, val1, val2, val3);
8722 +
8723 + /* Falcon requires 128 bit atomic access for this register */
8724 + FALCON_LOCK_LOCK(nic);
8725 + falcon_write_qq(efhw_kva + offset, ((val2 << 32) | val1), val3);
8726 + mmiowb();
8727 + FALCON_LOCK_UNLOCK(nic);
8728 + return;
8729 +}
8730 +
8731 +static void falcon_dmaq_rx_q_disable(struct efhw_nic *nic, uint dmaq)
8732 +{
8733 + FALCON_LOCK_DECL;
8734 + uint64_t val1, val2, val3;
8735 + ulong offset;
8736 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
8737 +
8738 + /* initialise the TX descriptor queue pointer table */
8739 + offset = falcon_dma_rx_q_offset(nic, dmaq);
8740 +
8741 + /* dword 1 */
8742 + __DWCHCK(RX_DESCQ_EN_LBN, RX_DESCQ_EN_WIDTH);
8743 + __DWCHCK(RX_DESCQ_TYPE_LBN, RX_DESCQ_TYPE_WIDTH);
8744 +
8745 + val1 = ((0 << RX_DESCQ_EN_LBN) | (1 << RX_DESCQ_TYPE_LBN));
8746 +
8747 + /* dword 2 */
8748 + val2 = 0;
8749 +
8750 + /* dword 3 */
8751 + val3 = 0;
8752 +
8753 + EFHW_TRACE("falcon_dmaq_rx_q_disable: %x->%"
8754 + PRIx64 ":%" PRIx64 ":%" PRIx64,
8755 + dmaq, val1, val2, val3);
8756 +
8757 + /* Falcon requires 128 bit atomic access for this register */
8758 + FALCON_LOCK_LOCK(nic);
8759 + falcon_write_qq(efhw_kva + offset, ((val2 << 32) | val1), val3);
8760 + mmiowb();
8761 + FALCON_LOCK_UNLOCK(nic);
8762 + return;
8763 +}
8764 +
8765 +
8766 +/*----------------------------------------------------------------------------
8767 + *
8768 + * Buffer Table low-level register interface
8769 + *
8770 + *---------------------------------------------------------------------------*/
8771 +
8772 +/*! Convert a (potentially) 64-bit physical address to 32-bits. Every use
8773 +** of this function is a place where we're not 64-bit clean.
8774 +*/
8775 +static inline uint32_t dma_addr_to_u32(dma_addr_t addr)
8776 +{
8777 + /* Top bits had better be zero! */
8778 + EFHW_ASSERT(addr == (addr & 0xffffffff));
8779 + return (uint32_t) addr;
8780 +}
8781 +
8782 +static inline uint32_t
8783 +falcon_nic_buffer_table_entry32_mk(dma_addr_t dma_addr, int own_id)
8784 +{
8785 + uint32_t dma_addr32 = FALCON_BUFFER_4K_PAGE(dma_addr_to_u32(dma_addr));
8786 +
8787 + /* don't do this to me */
8788 + EFHW_BUILD_ASSERT(BUF_ADR_HBUF_ODD_LBN == BUF_ADR_HBUF_EVEN_LBN + 32);
8789 + EFHW_BUILD_ASSERT(BUF_OWNER_ID_HBUF_ODD_LBN ==
8790 + BUF_OWNER_ID_HBUF_EVEN_LBN + 32);
8791 +
8792 + EFHW_BUILD_ASSERT(BUF_OWNER_ID_HBUF_ODD_WIDTH ==
8793 + BUF_OWNER_ID_HBUF_EVEN_WIDTH);
8794 + EFHW_BUILD_ASSERT(BUF_ADR_HBUF_ODD_WIDTH == BUF_ADR_HBUF_EVEN_WIDTH);
8795 +
8796 + __DWCHCK(BUF_ADR_HBUF_EVEN_LBN, BUF_ADR_HBUF_EVEN_WIDTH);
8797 + __DWCHCK(BUF_OWNER_ID_HBUF_EVEN_LBN, BUF_OWNER_ID_HBUF_EVEN_WIDTH);
8798 +
8799 + __RANGECHCK(dma_addr32, BUF_ADR_HBUF_EVEN_WIDTH);
8800 + __RANGECHCK(own_id, BUF_OWNER_ID_HBUF_EVEN_WIDTH);
8801 +
8802 + return (dma_addr32 << BUF_ADR_HBUF_EVEN_LBN) |
8803 + (own_id << BUF_OWNER_ID_HBUF_EVEN_LBN);
8804 +}
8805 +
8806 +static inline uint64_t
8807 +falcon_nic_buffer_table_entry64_mk(dma_addr_t dma_addr,
8808 + int bufsz, /* bytes */
8809 + int region, int own_id)
8810 +{
8811 + __DW2CHCK(IP_DAT_BUF_SIZE_LBN, IP_DAT_BUF_SIZE_WIDTH);
8812 + __DW2CHCK(BUF_ADR_REGION_LBN, BUF_ADR_REGION_WIDTH);
8813 + __LWCHK(BUF_ADR_FBUF_LBN, BUF_ADR_FBUF_WIDTH);
8814 + __DWCHCK(BUF_OWNER_ID_FBUF_LBN, BUF_OWNER_ID_FBUF_WIDTH);
8815 +
8816 + EFHW_ASSERT((bufsz == EFHW_4K) || (bufsz == EFHW_8K));
8817 +
8818 + dma_addr = (dma_addr >> 12) & __FALCON_MASK64(BUF_ADR_FBUF_WIDTH);
8819 +
8820 + __RANGECHCK(dma_addr, BUF_ADR_FBUF_WIDTH);
8821 + __RANGECHCK(1, IP_DAT_BUF_SIZE_WIDTH);
8822 + __RANGECHCK(region, BUF_ADR_REGION_WIDTH);
8823 + __RANGECHCK(own_id, BUF_OWNER_ID_FBUF_WIDTH);
8824 +
8825 + return ((uint64_t) (bufsz == EFHW_8K) << IP_DAT_BUF_SIZE_LBN) |
8826 + ((uint64_t) region << BUF_ADR_REGION_LBN) |
8827 + ((uint64_t) dma_addr << BUF_ADR_FBUF_LBN) |
8828 + ((uint64_t) own_id << BUF_OWNER_ID_FBUF_LBN);
8829 +}
8830 +
8831 +static inline void
8832 +_falcon_nic_buffer_table_set32(struct efhw_nic *nic,
8833 + dma_addr_t dma_addr, uint bufsz,
8834 + uint region, /* not used */
8835 + int own_id, int buffer_id)
8836 +{
8837 + /* programming the half table needs to be done in pairs. */
8838 + uint64_t entry, val, shift;
8839 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
8840 + volatile char __iomem *offset;
8841 +
8842 + EFHW_BUILD_ASSERT(BUF_ADR_HBUF_ODD_LBN == BUF_ADR_HBUF_EVEN_LBN + 32);
8843 + EFHW_BUILD_ASSERT(BUF_OWNER_ID_HBUF_ODD_LBN ==
8844 + BUF_OWNER_ID_HBUF_EVEN_LBN + 32);
8845 +
8846 + shift = (buffer_id & 1) ? 32 : 0;
8847 +
8848 + offset = (efhw_kva + BUF_HALF_TBL_OFST +
8849 + ((buffer_id & ~1) * FALCON_BUFFER_TBL_HALF_BYTES));
8850 +
8851 + entry = falcon_nic_buffer_table_entry32_mk(dma_addr_to_u32(dma_addr),
8852 + own_id);
8853 +
8854 +#if FALCON_USE_SHADOW_BUFFER_TABLE
8855 + val = _falcon_buffer_table[buffer_id & ~1];
8856 +#else
8857 + /* This will not work unless we've completed
8858 + * the buffer table updates */
8859 + falcon_read_q(offset, &val);
8860 +#endif
8861 + val &= ~(((uint64_t) 0xffffffff) << shift);
8862 + val |= (entry << shift);
8863 +
8864 + EFHW_TRACE("%s[%x]: %lx:%x:%" PRIx64 "->%x = %"
8865 + PRIx64, __func__, buffer_id, (unsigned long) dma_addr,
8866 + own_id, entry, (unsigned)(offset - efhw_kva), val);
8867 +
8868 + /* Falcon requires that access to this register is serialised */
8869 + falcon_write_q(offset, val);
8870 +
8871 + /* NB. No mmiowb(). Caller should do that e.g by calling commit */
8872 +
8873 +#if FALCON_USE_SHADOW_BUFFER_TABLE
8874 + _falcon_buffer_table[buffer_id & ~1] = val;
8875 +#endif
8876 +
8877 + /* Confirm the entry if the event queues haven't been set up. */
8878 + if (!nic->irq_handler) {
8879 + uint64_t new_val;
8880 + int count = 0;
8881 + while (1) {
8882 + mmiowb();
8883 + falcon_read_q(offset, &new_val);
8884 + if (new_val == val)
8885 + break;
8886 + count++;
8887 + if (count > 1000) {
8888 + EFHW_WARN("%s: poll Timeout", __func__);
8889 + break;
8890 + }
8891 + udelay(1);
8892 + }
8893 + }
8894 +}
8895 +
8896 +static inline void
8897 +_falcon_nic_buffer_table_set64(struct efhw_nic *nic,
8898 + dma_addr_t dma_addr, uint bufsz,
8899 + uint region, int own_id, int buffer_id)
8900 +{
8901 + volatile char __iomem *offset;
8902 + uint64_t entry;
8903 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
8904 +
8905 + EFHW_ASSERT(region < FALCON_REGION_NUM);
8906 +
8907 + EFHW_ASSERT((bufsz == EFHW_4K) ||
8908 + (bufsz == EFHW_8K && FALCON_BUFFER_TABLE_FULL_MODE));
8909 +
8910 + offset = (efhw_kva + BUF_FULL_TBL_OFST +
8911 + (buffer_id * FALCON_BUFFER_TBL_FULL_BYTES));
8912 +
8913 + entry = falcon_nic_buffer_table_entry64_mk(dma_addr, bufsz, region,
8914 + own_id);
8915 +
8916 + EFHW_TRACE("%s[%x]: %lx:bufsz=%x:region=%x:ownid=%x",
8917 + __func__, buffer_id, (unsigned long) dma_addr, bufsz,
8918 + region, own_id);
8919 +
8920 + EFHW_TRACE("%s: BUF[%x]:NIC[%x]->%" PRIx64,
8921 + __func__, buffer_id,
8922 + (unsigned int)(offset - efhw_kva), entry);
8923 +
8924 + /* Falcon requires that access to this register is serialised */
8925 + falcon_write_q(offset, entry);
8926 +
8927 + /* NB. No mmiowb(). Caller should do that e.g by calling commit */
8928 +
8929 + /* Confirm the entry if the event queues haven't been set up. */
8930 + if (!nic->irq_handler) {
8931 + uint64_t new_entry;
8932 + int count = 0;
8933 + while (1) {
8934 + mmiowb();
8935 + falcon_read_q(offset, &new_entry);
8936 + if (new_entry == entry)
8937 + return;
8938 + count++;
8939 + if (count > 1000) {
8940 + EFHW_WARN("%s: poll Timeout waiting for "
8941 + "value %"PRIx64
8942 + " (last was %"PRIx64")",
8943 + __func__, entry, new_entry);
8944 + break;
8945 + }
8946 + udelay(1);
8947 + }
8948 + }
8949 +}
8950 +
8951 +#if FALCON_BUFFER_TABLE_FULL_MODE
8952 +#define _falcon_nic_buffer_table_set _falcon_nic_buffer_table_set64
8953 +#else
8954 +#define _falcon_nic_buffer_table_set _falcon_nic_buffer_table_set32
8955 +#endif
8956 +
8957 +static inline void _falcon_nic_buffer_table_commit(struct efhw_nic *nic)
8958 +{
8959 + /* MUST be called holding the FALCON_LOCK */
8960 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
8961 + uint64_t cmd;
8962 +
8963 + EFHW_BUILD_ASSERT(BUF_TBL_UPD_REG_KER_OFST == BUF_TBL_UPD_REG_OFST);
8964 +
8965 + __DW2CHCK(BUF_UPD_CMD_LBN, BUF_UPD_CMD_WIDTH);
8966 + __RANGECHCK(1, BUF_UPD_CMD_WIDTH);
8967 +
8968 + cmd = ((uint64_t) 1 << BUF_UPD_CMD_LBN);
8969 +
8970 + /* Falcon requires 128 bit atomic access for this register */
8971 + falcon_write_qq(efhw_kva + BUF_TBL_UPD_REG_OFST,
8972 + cmd, FALCON_ATOMIC_UPD_REG);
8973 + mmiowb();
8974 +
8975 + nic->buf_commit_outstanding++;
8976 + EFHW_TRACE("COMMIT REQ out=%d", nic->buf_commit_outstanding);
8977 +}
8978 +
8979 +static void falcon_nic_buffer_table_commit(struct efhw_nic *nic)
8980 +{
8981 + /* nothing to do */
8982 +}
8983 +
8984 +static inline void
8985 +_falcon_nic_buffer_table_clear(struct efhw_nic *nic, int buffer_id, int num)
8986 +{
8987 + uint64_t cmd;
8988 + uint64_t start_id = buffer_id;
8989 + uint64_t end_id = buffer_id + num - 1;
8990 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
8991 +
8992 + volatile char __iomem *offset = (efhw_kva + BUF_TBL_UPD_REG_OFST);
8993 +
8994 + EFHW_BUILD_ASSERT(BUF_TBL_UPD_REG_KER_OFST == BUF_TBL_UPD_REG_OFST);
8995 +
8996 +#if !FALCON_BUFFER_TABLE_FULL_MODE
8997 + /* buffer_ids in half buffer mode reference pairs of buffers */
8998 + EFHW_ASSERT(buffer_id % 1 == 0);
8999 + EFHW_ASSERT(num % 1 == 0);
9000 + start_id = start_id >> 1;
9001 + end_id = end_id >> 1;
9002 +#endif
9003 +
9004 + EFHW_ASSERT(num >= 1);
9005 +
9006 + __DWCHCK(BUF_CLR_START_ID_LBN, BUF_CLR_START_ID_WIDTH);
9007 + __DW2CHCK(BUF_CLR_END_ID_LBN, BUF_CLR_END_ID_WIDTH);
9008 +
9009 + __DW2CHCK(BUF_CLR_CMD_LBN, BUF_CLR_CMD_WIDTH);
9010 + __RANGECHCK(1, BUF_CLR_CMD_WIDTH);
9011 +
9012 + __RANGECHCK(start_id, BUF_CLR_START_ID_WIDTH);
9013 + __RANGECHCK(end_id, BUF_CLR_END_ID_WIDTH);
9014 +
9015 + cmd = (((uint64_t) 1 << BUF_CLR_CMD_LBN) |
9016 + (start_id << BUF_CLR_START_ID_LBN) |
9017 + (end_id << BUF_CLR_END_ID_LBN));
9018 +
9019 + /* Falcon requires 128 bit atomic access for this register */
9020 + falcon_write_qq(offset, cmd, FALCON_ATOMIC_UPD_REG);
9021 + mmiowb();
9022 +
9023 + nic->buf_commit_outstanding++;
9024 + EFHW_TRACE("COMMIT CLEAR out=%d", nic->buf_commit_outstanding);
9025 +}
9026 +
9027 +/*----------------------------------------------------------------------------
9028 + *
9029 + * Events low-level register interface
9030 + *
9031 + *---------------------------------------------------------------------------*/
9032 +
9033 +static unsigned eventq_sizes[] = {
9034 + 512,
9035 + EFHW_1K,
9036 + EFHW_2K,
9037 + EFHW_4K,
9038 + EFHW_8K,
9039 + EFHW_16K,
9040 + EFHW_32K
9041 +};
9042 +
9043 +#define N_EVENTQ_SIZES (sizeof(eventq_sizes) / sizeof(eventq_sizes[0]))
9044 +
9045 +static inline void falcon_nic_srm_upd_evq(struct efhw_nic *nic, int evq)
9046 +{
9047 + /* set up the eventq which will receive events from the SRAM module.
9048 + * i.e buffer table updates and clears, TX and RX aperture table
9049 + * updates */
9050 +
9051 + FALCON_LOCK_DECL;
9052 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
9053 +
9054 + EFHW_BUILD_ASSERT(SRM_UPD_EVQ_REG_OFST == SRM_UPD_EVQ_REG_KER_OFST);
9055 +
9056 + __DWCHCK(SRM_UPD_EVQ_ID_LBN, SRM_UPD_EVQ_ID_WIDTH);
9057 + __RANGECHCK(evq, SRM_UPD_EVQ_ID_WIDTH);
9058 +
9059 + /* Falcon requires 128 bit atomic access for this register */
9060 + FALCON_LOCK_LOCK(nic);
9061 + falcon_write_qq(efhw_kva + SRM_UPD_EVQ_REG_OFST,
9062 + ((uint64_t) evq << SRM_UPD_EVQ_ID_LBN),
9063 + FALCON_ATOMIC_SRPM_UDP_EVQ_REG);
9064 + mmiowb();
9065 + FALCON_LOCK_UNLOCK(nic);
9066 +}
9067 +
9068 +static void
9069 +falcon_nic_evq_ptr_tbl(struct efhw_nic *nic,
9070 + uint evq, /* evq id */
9071 + uint enable, /* 1 to enable, 0 to disable */
9072 + uint buf_base_id,/* Buffer table base for EVQ */
9073 + uint evq_size /* Number of events */)
9074 +{
9075 + FALCON_LOCK_DECL;
9076 + uint i, val;
9077 + ulong offset;
9078 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
9079 +
9080 + /* size must be one of the various options, otherwise we assert */
9081 + for (i = 0; i < N_EVENTQ_SIZES; i++) {
9082 + if (evq_size <= eventq_sizes[i])
9083 + break;
9084 + }
9085 + EFHW_ASSERT(i < N_EVENTQ_SIZES);
9086 +
9087 + __DWCHCK(EVQ_BUF_BASE_ID_LBN, EVQ_BUF_BASE_ID_WIDTH);
9088 + __DWCHCK(EVQ_SIZE_LBN, EVQ_SIZE_WIDTH);
9089 + __DWCHCK(EVQ_EN_LBN, EVQ_EN_WIDTH);
9090 +
9091 + __RANGECHCK(i, EVQ_SIZE_WIDTH);
9092 + __RANGECHCK(buf_base_id, EVQ_BUF_BASE_ID_WIDTH);
9093 + __RANGECHCK(1, EVQ_EN_WIDTH);
9094 +
9095 + /* if !enable then only evq needs to be correct, although valid
9096 + * values need to be passed in for other arguments to prevent
9097 + * assertions */
9098 +
9099 + val = ((i << EVQ_SIZE_LBN) | (buf_base_id << EVQ_BUF_BASE_ID_LBN) |
9100 + (enable ? (1 << EVQ_EN_LBN) : 0));
9101 +
9102 + EFHW_ASSERT(evq < nic->num_evqs);
9103 +
9104 + offset = EVQ_PTR_TBL_CHAR_OFST;
9105 + offset += evq * FALCON_REGISTER128;
9106 +
9107 + EFHW_TRACE("%s: evq %u en=%x:buf=%x:size=%x->%x at %lx",
9108 + __func__, evq, enable, buf_base_id, evq_size, val,
9109 + offset);
9110 +
9111 + /* Falcon requires 128 bit atomic access for this register */
9112 + FALCON_LOCK_LOCK(nic);
9113 + falcon_write_qq(efhw_kva + offset, val, FALCON_ATOMIC_PTR_TBL_REG);
9114 + mmiowb();
9115 + FALCON_LOCK_UNLOCK(nic);
9116 +
9117 + /* caller must wait for an update done event before writing any more
9118 + table entries */
9119 +
9120 + return;
9121 +}
9122 +
9123 +void
9124 +falcon_nic_evq_ack(struct efhw_nic *nic,
9125 + uint evq, /* evq id */
9126 + uint rptr, /* new read pointer update */
9127 + bool wakeup /* request a wakeup event if ptr's != */
9128 + )
9129 +{
9130 + uint val;
9131 + ulong offset;
9132 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
9133 +
9134 + EFHW_BUILD_ASSERT(FALCON_EVQ_CHAR == 4);
9135 +
9136 + __DWCHCK(EVQ_RPTR_LBN, EVQ_RPTR_WIDTH);
9137 + __RANGECHCK(rptr, EVQ_RPTR_WIDTH);
9138 +
9139 + val = (rptr << EVQ_RPTR_LBN);
9140 +
9141 + EFHW_ASSERT(evq < nic->num_evqs);
9142 +
9143 + if (evq < FALCON_EVQ_CHAR) {
9144 + offset = EVQ_RPTR_REG_KER_OFST;
9145 + offset += evq * FALCON_REGISTER128;
9146 +
9147 + EFHW_ASSERT(!wakeup); /* don't try this at home */
9148 + } else {
9149 + offset = EVQ_RPTR_REG_OFST + (FALCON_EVQ_CHAR *
9150 + FALCON_REGISTER128);
9151 + offset += (evq - FALCON_EVQ_CHAR) * FALCON_REGISTER128;
9152 +
9153 + /* nothing to do for interruptless event queues which do
9154 + * not want a wakeup */
9155 + if (evq != FALCON_EVQ_CHAR && !wakeup)
9156 + return;
9157 + }
9158 +
9159 + EFHW_TRACE("%s: %x %x %x->%x", __func__, evq, rptr, wakeup, val);
9160 +
9161 + writel(val, efhw_kva + offset);
9162 + mmiowb();
9163 +}
9164 +
9165 +/*---------------------------------------------------------------------------*/
9166 +
9167 +static inline void
9168 +falcon_drv_ev(struct efhw_nic *nic, uint64_t data, uint qid)
9169 +{
9170 + FALCON_LOCK_DECL;
9171 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
9172 +
9173 + /* send an event from one driver to the other */
9174 + EFHW_BUILD_ASSERT(DRV_EV_REG_KER_OFST == DRV_EV_REG_OFST);
9175 + EFHW_BUILD_ASSERT(DRV_EV_DATA_LBN == 0);
9176 + EFHW_BUILD_ASSERT(DRV_EV_DATA_WIDTH == 64);
9177 + EFHW_BUILD_ASSERT(DRV_EV_QID_LBN == 64);
9178 + EFHW_BUILD_ASSERT(DRV_EV_QID_WIDTH == 12);
9179 +
9180 + FALCON_LOCK_LOCK(nic);
9181 + falcon_write_qq(efhw_kva + DRV_EV_REG_OFST, data, qid);
9182 + mmiowb();
9183 + FALCON_LOCK_UNLOCK(nic);
9184 +}
9185 +
9186 +_DEBUG_SYM_ void
9187 +falcon_ab_timer_tbl_set(struct efhw_nic *nic,
9188 + uint evq, /* timer id */
9189 + uint mode, /* mode bits */
9190 + uint countdown /* counting value to set */)
9191 +{
9192 + FALCON_LOCK_DECL;
9193 + uint val;
9194 + ulong offset;
9195 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
9196 +
9197 + EFHW_BUILD_ASSERT(TIMER_VAL_LBN == 0);
9198 +
9199 + __DWCHCK(TIMER_MODE_LBN, TIMER_MODE_WIDTH);
9200 + __DWCHCK(TIMER_VAL_LBN, TIMER_VAL_WIDTH);
9201 +
9202 + __RANGECHCK(mode, TIMER_MODE_WIDTH);
9203 + __RANGECHCK(countdown, TIMER_VAL_WIDTH);
9204 +
9205 + val = ((mode << TIMER_MODE_LBN) | (countdown << TIMER_VAL_LBN));
9206 +
9207 + if (evq < FALCON_EVQ_CHAR) {
9208 + offset = TIMER_CMD_REG_KER_OFST;
9209 + offset += evq * EFHW_8K; /* PAGE mapped register */
9210 + } else {
9211 + offset = TIMER_TBL_OFST;
9212 + offset += evq * FALCON_REGISTER128;
9213 + }
9214 + EFHW_ASSERT(evq < nic->num_evqs);
9215 +
9216 + EFHW_TRACE("%s: evq %u mode %x (%s) time %x -> %08x",
9217 + __func__, evq, mode,
9218 + mode == 0 ? "DISABLE" :
9219 + mode == 1 ? "IMMED" :
9220 + mode == 2 ? (evq < 5 ? "HOLDOFF" : "RX_TRIG") :
9221 + "<BAD>", countdown, val);
9222 +
9223 + /* Falcon requires 128 bit atomic access for this register when
9224 + * accessed from the driver. User access to timers is paged mapped
9225 + */
9226 + FALCON_LOCK_LOCK(nic);
9227 + falcon_write_qq(efhw_kva + offset, val, FALCON_ATOMIC_TIMER_CMD_REG);
9228 + mmiowb();
9229 + FALCON_LOCK_UNLOCK(nic);
9230 + return;
9231 +}
9232 +
9233 +
9234 +/*--------------------------------------------------------------------
9235 + *
9236 + * Rate pacing - Low level interface
9237 + *
9238 + *--------------------------------------------------------------------*/
9239 +void falcon_nic_pace(struct efhw_nic *nic, uint dmaq, uint pace)
9240 +{
9241 + /* Pace specified in 2^(units of microseconds). This is the minimum
9242 + additional delay imposed over and above the IPG.
9243 +
9244 + Pacing only available on the virtual interfaces
9245 + */
9246 + FALCON_LOCK_DECL;
9247 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
9248 + ulong offset;
9249 +
9250 + if (pace > 20)
9251 + pace = 20; /* maxm supported value */
9252 +
9253 + __DWCHCK(TX_PACE_LBN, TX_PACE_WIDTH);
9254 + __RANGECHCK(pace, TX_PACE_WIDTH);
9255 +
9256 + switch (nic->devtype.variant) {
9257 + case 'A':
9258 + EFHW_ASSERT(dmaq >= TX_PACE_TBL_FIRST_QUEUE_A1);
9259 + offset = TX_PACE_TBL_A1_OFST;
9260 + offset += (dmaq - TX_PACE_TBL_FIRST_QUEUE_A1) * 16;
9261 + break;
9262 + case 'B':
9263 + /* Would be nice to assert this, but as dmaq is unsigned and
9264 + * TX_PACE_TBL_FIRST_QUEUE_B0 is 0, it makes no sense
9265 + * EFHW_ASSERT(dmaq >= TX_PACE_TBL_FIRST_QUEUE_B0);
9266 + */
9267 + offset = TX_PACE_TBL_B0_OFST;
9268 + offset += (dmaq - TX_PACE_TBL_FIRST_QUEUE_B0) * 16;
9269 + break;
9270 + default:
9271 + EFHW_ASSERT(0);
9272 + offset = 0;
9273 + break;
9274 + }
9275 +
9276 + /* Falcon requires 128 bit atomic access for this register */
9277 + FALCON_LOCK_LOCK(nic);
9278 + falcon_write_qq(efhw_kva + offset, pace, FALCON_ATOMIC_PACE_REG);
9279 + mmiowb();
9280 + FALCON_LOCK_UNLOCK(nic);
9281 +
9282 + EFHW_TRACE("%s: txq %d offset=%lx pace=2^%x",
9283 + __func__, dmaq, offset, pace);
9284 +}
9285 +
9286 +/*--------------------------------------------------------------------
9287 + *
9288 + * Interrupt - Low level interface
9289 + *
9290 + *--------------------------------------------------------------------*/
9291 +
9292 +static void falcon_nic_handle_fatal_int(struct efhw_nic *nic)
9293 +{
9294 + FALCON_LOCK_DECL;
9295 + volatile char __iomem *offset;
9296 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
9297 + uint64_t val;
9298 +
9299 + offset = (efhw_kva + FATAL_INTR_REG_OFST);
9300 +
9301 + /* Falcon requires 32 bit atomic access for this register */
9302 + FALCON_LOCK_LOCK(nic);
9303 + val = readl(offset);
9304 + FALCON_LOCK_UNLOCK(nic);
9305 +
9306 + /* ?? BUG3249 - need to disable illegal address interrupt */
9307 + /* ?? BUG3114 - need to backport interrupt storm protection code */
9308 + EFHW_ERR("fatal interrupt: %s%s%s%s%s%s%s%s%s%s%s%s[%" PRIx64 "]",
9309 + val & (1 << PCI_BUSERR_INT_CHAR_LBN) ? "PCI-bus-error " : "",
9310 + val & (1 << SRAM_OOB_INT_CHAR_LBN) ? "SRAM-oob " : "",
9311 + val & (1 << BUFID_OOB_INT_CHAR_LBN) ? "bufid-oob " : "",
9312 + val & (1 << MEM_PERR_INT_CHAR_LBN) ? "int-parity " : "",
9313 + val & (1 << RBUF_OWN_INT_CHAR_LBN) ? "rx-bufid-own " : "",
9314 + val & (1 << TBUF_OWN_INT_CHAR_LBN) ? "tx-bufid-own " : "",
9315 + val & (1 << RDESCQ_OWN_INT_CHAR_LBN) ? "rx-desc-own " : "",
9316 + val & (1 << TDESCQ_OWN_INT_CHAR_LBN) ? "tx-desc-own " : "",
9317 + val & (1 << EVQ_OWN_INT_CHAR_LBN) ? "evq-own " : "",
9318 + val & (1 << EVFF_OFLO_INT_CHAR_LBN) ? "evq-fifo " : "",
9319 + val & (1 << ILL_ADR_INT_CHAR_LBN) ? "ill-addr " : "",
9320 + val & (1 << SRM_PERR_INT_CHAR_LBN) ? "sram-parity " : "", val);
9321 +}
9322 +
9323 +static void falcon_nic_interrupt_hw_enable(struct efhw_nic *nic)
9324 +{
9325 + FALCON_LOCK_DECL;
9326 + uint val;
9327 + volatile char __iomem *offset;
9328 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
9329 +
9330 + EFHW_BUILD_ASSERT(DRV_INT_EN_CHAR_WIDTH == 1);
9331 +
9332 + if (nic->flags & NIC_FLAG_NO_INTERRUPT)
9333 + return;
9334 +
9335 + offset = (efhw_kva + INT_EN_REG_CHAR_OFST);
9336 + val = 1 << DRV_INT_EN_CHAR_LBN;
9337 +
9338 + EFHW_NOTICE("%s: %x -> %x", __func__, (int)(offset - efhw_kva),
9339 + val);
9340 +
9341 + /* Falcon requires 128 bit atomic access for this register */
9342 + FALCON_LOCK_LOCK(nic);
9343 + falcon_write_qq(offset, val, FALCON_ATOMIC_INT_EN_REG);
9344 + mmiowb();
9345 + FALCON_LOCK_UNLOCK(nic);
9346 +}
9347 +
9348 +static void falcon_nic_interrupt_hw_disable(struct efhw_nic *nic)
9349 +{
9350 + FALCON_LOCK_DECL;
9351 + volatile char __iomem *offset;
9352 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
9353 +
9354 + EFHW_BUILD_ASSERT(SRAM_PERR_INT_KER_WIDTH == 1);
9355 + EFHW_BUILD_ASSERT(DRV_INT_EN_KER_LBN == 0);
9356 + EFHW_BUILD_ASSERT(SRAM_PERR_INT_CHAR_WIDTH == 1);
9357 + EFHW_BUILD_ASSERT(DRV_INT_EN_CHAR_LBN == 0);
9358 + EFHW_BUILD_ASSERT(SRAM_PERR_INT_KER_LBN == SRAM_PERR_INT_CHAR_LBN);
9359 + EFHW_BUILD_ASSERT(DRV_INT_EN_KER_LBN == DRV_INT_EN_CHAR_LBN);
9360 +
9361 + if (nic->flags & NIC_FLAG_NO_INTERRUPT)
9362 + return;
9363 +
9364 + offset = (efhw_kva + INT_EN_REG_CHAR_OFST);
9365 +
9366 + EFHW_NOTICE("%s: %x -> 0", __func__, (int)(offset - efhw_kva));
9367 +
9368 + /* Falcon requires 128 bit atomic access for this register */
9369 + FALCON_LOCK_LOCK(nic);
9370 + falcon_write_qq(offset, 0, FALCON_ATOMIC_INT_EN_REG);
9371 + mmiowb();
9372 + FALCON_LOCK_UNLOCK(nic);
9373 +}
9374 +
9375 +static void falcon_nic_irq_addr_set(struct efhw_nic *nic, dma_addr_t dma_addr)
9376 +{
9377 + FALCON_LOCK_DECL;
9378 + volatile char __iomem *offset;
9379 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
9380 +
9381 + offset = (efhw_kva + INT_ADR_REG_CHAR_OFST);
9382 +
9383 + EFHW_NOTICE("%s: %x -> " DMA_ADDR_T_FMT, __func__,
9384 + (int)(offset - efhw_kva), dma_addr);
9385 +
9386 + /* Falcon requires 128 bit atomic access for this register */
9387 + FALCON_LOCK_LOCK(nic);
9388 + falcon_write_qq(offset, dma_addr, FALCON_ATOMIC_INT_ADR_REG);
9389 + mmiowb();
9390 + FALCON_LOCK_UNLOCK(nic);
9391 +}
9392 +
9393 +
9394 +/*--------------------------------------------------------------------
9395 + *
9396 + * RXDP - low level interface
9397 + *
9398 + *--------------------------------------------------------------------*/
9399 +
9400 +void
9401 +falcon_nic_set_rx_usr_buf_size(struct efhw_nic *nic, int usr_buf_bytes)
9402 +{
9403 + FALCON_LOCK_DECL;
9404 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
9405 + uint64_t val, val2, usr_buf_size = usr_buf_bytes / 32;
9406 + int rubs_lbn, rubs_width, roec_lbn;
9407 +
9408 + EFHW_BUILD_ASSERT(RX_CFG_REG_OFST == RX_CFG_REG_KER_OFST);
9409 +
9410 + switch (nic->devtype.variant) {
9411 + default:
9412 + EFHW_ASSERT(0);
9413 + /* Fall-through to avoid compiler warnings. */
9414 + case 'A':
9415 + rubs_lbn = RX_USR_BUF_SIZE_A1_LBN;
9416 + rubs_width = RX_USR_BUF_SIZE_A1_WIDTH;
9417 + roec_lbn = RX_OWNERR_CTL_A1_LBN;
9418 + break;
9419 + case 'B':
9420 + rubs_lbn = RX_USR_BUF_SIZE_B0_LBN;
9421 + rubs_width = RX_USR_BUF_SIZE_B0_WIDTH;
9422 + roec_lbn = RX_OWNERR_CTL_B0_LBN;
9423 + break;
9424 + }
9425 +
9426 + __DWCHCK(rubs_lbn, rubs_width);
9427 + __QWCHCK(roec_lbn, 1);
9428 + __RANGECHCK(usr_buf_size, rubs_width);
9429 +
9430 + /* Falcon requires 128 bit atomic access for this register */
9431 + FALCON_LOCK_LOCK(nic);
9432 + falcon_read_qq(efhw_kva + RX_CFG_REG_OFST, &val, &val2);
9433 +
9434 + val &= ~((__FALCON_MASK64(rubs_width)) << rubs_lbn);
9435 + val |= (usr_buf_size << rubs_lbn);
9436 +
9437 + /* shouldn't be needed for a production driver */
9438 + val |= ((uint64_t) 1 << roec_lbn);
9439 +
9440 + falcon_write_qq(efhw_kva + RX_CFG_REG_OFST, val, val2);
9441 + mmiowb();
9442 + FALCON_LOCK_UNLOCK(nic);
9443 +}
9444 +EXPORT_SYMBOL(falcon_nic_set_rx_usr_buf_size);
9445 +
9446 +
9447 +/*--------------------------------------------------------------------
9448 + *
9449 + * TXDP - low level interface
9450 + *
9451 + *--------------------------------------------------------------------*/
9452 +
9453 +_DEBUG_SYM_ void falcon_nic_tx_cfg(struct efhw_nic *nic, int unlocked)
9454 +{
9455 + FALCON_LOCK_DECL;
9456 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
9457 + uint64_t val1, val2;
9458 +
9459 + EFHW_BUILD_ASSERT(TX_CFG_REG_OFST == TX_CFG_REG_KER_OFST);
9460 + __DWCHCK(TX_OWNERR_CTL_LBN, TX_OWNERR_CTL_WIDTH);
9461 + __DWCHCK(TX_NON_IP_DROP_DIS_LBN, TX_NON_IP_DROP_DIS_WIDTH);
9462 +
9463 + FALCON_LOCK_LOCK(nic);
9464 + falcon_read_qq(efhw_kva + TX_CFG_REG_OFST, &val1, &val2);
9465 +
9466 + /* Will flag fatal interrupts on owner id errors. This should not be
9467 + on for production code because there is otherwise a denial of
9468 + serivce attack possible */
9469 + val1 |= (1 << TX_OWNERR_CTL_LBN);
9470 +
9471 + /* Setup user queue TCP/UDP only packet security */
9472 + if (unlocked)
9473 + val1 |= (1 << TX_NON_IP_DROP_DIS_LBN);
9474 + else
9475 + val1 &= ~(1 << TX_NON_IP_DROP_DIS_LBN);
9476 +
9477 + falcon_write_qq(efhw_kva + TX_CFG_REG_OFST, val1, val2);
9478 + mmiowb();
9479 + FALCON_LOCK_UNLOCK(nic);
9480 +}
9481 +
9482 +/*--------------------------------------------------------------------
9483 + *
9484 + * Random thresholds - Low level interface (Would like these to be op
9485 + * defaults wherever possible)
9486 + *
9487 + *--------------------------------------------------------------------*/
9488 +
9489 +void falcon_nic_pace_cfg(struct efhw_nic *nic, int fb_base, int bin_thresh)
9490 +{
9491 + FALCON_LOCK_DECL;
9492 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
9493 + unsigned offset = 0;
9494 + uint64_t val;
9495 +
9496 + __DWCHCK(TX_PACE_FB_BASE_LBN, TX_PACE_FB_BASE_WIDTH);
9497 + __DWCHCK(TX_PACE_BIN_TH_LBN, TX_PACE_BIN_TH_WIDTH);
9498 +
9499 + switch (nic->devtype.variant) {
9500 + case 'A': offset = TX_PACE_REG_A1_OFST; break;
9501 + case 'B': offset = TX_PACE_REG_B0_OFST; break;
9502 + default: EFHW_ASSERT(0); break;
9503 + }
9504 +
9505 + val = (0x15 << TX_PACE_SB_NOTAF_LBN);
9506 + val |= (0xb << TX_PACE_SB_AF_LBN);
9507 +
9508 + val |= ((fb_base & __FALCON_MASK64(TX_PACE_FB_BASE_WIDTH)) <<
9509 + TX_PACE_FB_BASE_LBN);
9510 + val |= ((bin_thresh & __FALCON_MASK64(TX_PACE_BIN_TH_WIDTH)) <<
9511 + TX_PACE_BIN_TH_LBN);
9512 +
9513 + /* Falcon requires 128 bit atomic access for this register */
9514 + FALCON_LOCK_LOCK(nic);
9515 + falcon_write_qq(efhw_kva + offset, val, 0);
9516 + mmiowb();
9517 + FALCON_LOCK_UNLOCK(nic);
9518 +}
9519 +
9520 +
9521 +/**********************************************************************
9522 + * Implementation of the HAL. ********************************************
9523 + **********************************************************************/
9524 +
9525 +/*----------------------------------------------------------------------------
9526 + *
9527 + * Initialisation and configuration discovery
9528 + *
9529 + *---------------------------------------------------------------------------*/
9530 +
9531 +static int falcon_nic_init_irq_channel(struct efhw_nic *nic, int enable)
9532 +{
9533 + /* create a buffer for the irq channel */
9534 + int rc;
9535 +
9536 + if (enable) {
9537 + rc = efhw_iopage_alloc(nic, &nic->irq_iobuff);
9538 + if (rc < 0)
9539 + return rc;
9540 +
9541 + falcon_nic_irq_addr_set(nic,
9542 + efhw_iopage_dma_addr(&nic->irq_iobuff));
9543 + } else {
9544 + if (efhw_iopage_is_valid(&nic->irq_iobuff))
9545 + efhw_iopage_free(nic, &nic->irq_iobuff);
9546 +
9547 + efhw_iopage_mark_invalid(&nic->irq_iobuff);
9548 + falcon_nic_irq_addr_set(nic, 0);
9549 + }
9550 +
9551 + EFHW_TRACE("%s: %lx %sable", __func__,
9552 + (unsigned long) efhw_iopage_dma_addr(&nic->irq_iobuff),
9553 + enable ? "en" : "dis");
9554 +
9555 + return 0;
9556 +}
9557 +
9558 +static void falcon_nic_close_hardware(struct efhw_nic *nic)
9559 +{
9560 + /* check we are in possession of some hardware */
9561 + if (!efhw_nic_have_hw(nic))
9562 + return;
9563 +
9564 + falcon_nic_init_irq_channel(nic, 0);
9565 + falcon_nic_filter_dtor(nic);
9566 +
9567 + EFHW_NOTICE("%s:", __func__);
9568 +}
9569 +
9570 +static int
9571 +falcon_nic_init_hardware(struct efhw_nic *nic,
9572 + struct efhw_ev_handler *ev_handlers,
9573 + const uint8_t *mac_addr, int non_irq_evq)
9574 +{
9575 + int rc;
9576 +
9577 + /* header sanity checks */
9578 + FALCON_ASSERT_VALID();
9579 +
9580 + /* Initialise supporting modules */
9581 + rc = falcon_nic_filter_ctor(nic);
9582 + if (rc < 0)
9583 + return rc;
9584 +
9585 +#if FALCON_USE_SHADOW_BUFFER_TABLE
9586 + CI_ZERO_ARRAY(_falcon_buffer_table, FALCON_BUFFER_TBL_NUM);
9587 +#endif
9588 +
9589 + /* Initialise the top level hardware blocks */
9590 + memcpy(nic->mac_addr, mac_addr, ETH_ALEN);
9591 +
9592 + EFHW_TRACE("%s:", __func__);
9593 +
9594 + /* nic.c:efhw_nic_init marks all the interrupt units as unused.
9595 +
9596 + ?? TODO we should be able to request the non-interrupting event
9597 + queue and the net driver's (for a net driver that is using libefhw)
9598 + additional RSS queues here.
9599 +
9600 + Result would be that that net driver could call
9601 + nic.c:efhw_nic_allocate_common_hardware_resources() and that the
9602 + IFDEF FALCON's can be removed from
9603 + nic.c:efhw_nic_allocate_common_hardware_resources()
9604 + */
9605 + nic->irq_unit = INT_EN_REG_CHAR_OFST;
9606 +
9607 + /*****************************************************************
9608 + * The rest of this function deals with initialization of the NICs
9609 + * hardware (as opposed to the initialization of the
9610 + * struct efhw_nic data structure */
9611 +
9612 + /* char driver grabs SRM events onto the non interrupting
9613 + * event queue */
9614 + falcon_nic_srm_upd_evq(nic, non_irq_evq);
9615 +
9616 + /* RXDP tweaks */
9617 +
9618 + /* ?? bug2396 rx_cfg should be ok so long as the net driver
9619 + * always pushes buffers big enough for the link MTU */
9620 +
9621 + /* set the RX buffer cutoff size to be the same as PAGE_SIZE.
9622 + * Use this value when we think that there will be a lot of
9623 + * jumbo frames.
9624 + *
9625 + * The default value 1600 is useful when packets are small,
9626 + * but would means that jumbo frame RX queues would need more
9627 + * descriptors pushing */
9628 + falcon_nic_set_rx_usr_buf_size(nic, FALCON_RX_USR_BUF_SIZE);
9629 +
9630 + /* TXDP tweaks */
9631 + /* ?? bug2396 looks ok */
9632 + falcon_nic_tx_cfg(nic, /*unlocked(for non-UDP/TCP)= */ 0);
9633 + falcon_nic_pace_cfg(nic, 4, 2);
9634 +
9635 + /* ?? bug2396
9636 + * netdriver must load first or else must RMW this register */
9637 + falcon_nic_rx_filter_ctl_set(nic, RX_FILTER_CTL_SRCH_LIMIT_TCP_FULL,
9638 + RX_FILTER_CTL_SRCH_LIMIT_TCP_WILD,
9639 + RX_FILTER_CTL_SRCH_LIMIT_UDP_FULL,
9640 + RX_FILTER_CTL_SRCH_LIMIT_UDP_WILD);
9641 +
9642 + if (!(nic->flags & NIC_FLAG_NO_INTERRUPT)) {
9643 + rc = efhw_keventq_ctor(nic, FALCON_EVQ_CHAR,
9644 + &nic->interrupting_evq, ev_handlers);
9645 + if (rc < 0) {
9646 + EFHW_ERR("%s: efhw_keventq_ctor() failed (%d) evq=%d",
9647 + __func__, rc, FALCON_EVQ_CHAR);
9648 + return rc;
9649 + }
9650 + }
9651 + rc = efhw_keventq_ctor(nic, non_irq_evq,
9652 + &nic->non_interrupting_evq, NULL);
9653 + if (rc < 0) {
9654 + EFHW_ERR("%s: efhw_keventq_ctor() failed (%d) evq=%d",
9655 + __func__, rc, non_irq_evq);
9656 + return rc;
9657 + }
9658 +
9659 + /* allocate IRQ channel */
9660 + rc = falcon_nic_init_irq_channel(nic, 1);
9661 + /* ignore failure at user-level for eftest */
9662 + if ((rc < 0) && !(nic->options & NIC_OPT_EFTEST))
9663 + return rc;
9664 +
9665 + return 0;
9666 +}
9667 +
9668 +/*--------------------------------------------------------------------
9669 + *
9670 + * Interrupt
9671 + *
9672 + *--------------------------------------------------------------------*/
9673 +
9674 +static void
9675 +falcon_nic_interrupt_enable(struct efhw_nic *nic)
9676 +{
9677 + struct efhw_keventq *q;
9678 + unsigned rdptr;
9679 +
9680 + if (nic->flags & NIC_FLAG_NO_INTERRUPT)
9681 + return;
9682 +
9683 + /* Enable driver interrupts */
9684 + EFHW_NOTICE("%s: enable master interrupt", __func__);
9685 + falcon_nic_interrupt_hw_enable(nic);
9686 +
9687 + /* An interrupting eventq must start of day ack its read pointer */
9688 + q = &nic->interrupting_evq;
9689 + rdptr = EFHW_EVENT_OFFSET(q, q, 1) / sizeof(efhw_event_t);
9690 + falcon_nic_evq_ack(nic, FALCON_EVQ_CHAR, rdptr, false);
9691 + EFHW_NOTICE("%s: ACK evq[%d]:%x", __func__,
9692 + FALCON_EVQ_CHAR, rdptr);
9693 +}
9694 +
9695 +static void falcon_nic_interrupt_disable(struct efhw_nic *nic)
9696 +{
9697 + /* NB. No need to check for NIC_FLAG_NO_INTERRUPT, as
9698 + ** falcon_nic_interrupt_hw_disable() will do it. */
9699 + falcon_nic_interrupt_hw_disable(nic);
9700 +}
9701 +
9702 +static void
9703 +falcon_nic_set_interrupt_moderation(struct efhw_nic *nic, int evq,
9704 + uint32_t val)
9705 +{
9706 + if (evq < 0)
9707 + evq = FALCON_EVQ_CHAR;
9708 +
9709 + falcon_ab_timer_tbl_set(nic, evq, TIMER_MODE_INT_HLDOFF, val / 5);
9710 +}
9711 +
9712 +static inline void legacy_irq_ack(struct efhw_nic *nic)
9713 +{
9714 + EFHW_ASSERT(!(nic->flags & NIC_FLAG_NO_INTERRUPT));
9715 +
9716 + if (!(nic->flags & NIC_FLAG_MSI)) {
9717 + writel(1, EFHW_KVA(nic) + INT_ACK_REG_CHAR_A1_OFST);
9718 + mmiowb();
9719 + /* ?? FIXME: We should be doing a read here to ensure IRQ is
9720 + * thoroughly acked before we return from ISR. */
9721 + }
9722 +}
9723 +
9724 +static int falcon_nic_interrupt(struct efhw_nic *nic)
9725 +{
9726 + uint32_t *syserr_ptr =
9727 + (uint32_t *) efhw_iopage_ptr(&nic->irq_iobuff);
9728 + int handled = 0;
9729 + int done_ack = 0;
9730 +
9731 + EFHW_ASSERT(!(nic->flags & NIC_FLAG_NO_INTERRUPT));
9732 + EFHW_ASSERT(syserr_ptr);
9733 +
9734 + /* FIFO fill level interrupt - just log it. */
9735 + if (unlikely(*(syserr_ptr + (DW0_OFST / 4)))) {
9736 + EFHW_WARN("%s: *** FIFO *** %x", __func__,
9737 + *(syserr_ptr + (DW0_OFST / 4)));
9738 + *(syserr_ptr + (DW0_OFST / 4)) = 0;
9739 + handled++;
9740 + }
9741 +
9742 + /* Fatal interrupts. */
9743 + if (unlikely(*(syserr_ptr + (DW2_OFST / 4)))) {
9744 + *(syserr_ptr + (DW2_OFST / 4)) = 0;
9745 + falcon_nic_handle_fatal_int(nic);
9746 + handled++;
9747 + }
9748 +
9749 + /* Event queue interrupt. For legacy interrupts we have to check
9750 + * that the interrupt is for us, because it could be shared. */
9751 + if (*(syserr_ptr + (DW1_OFST / 4))) {
9752 + *(syserr_ptr + (DW1_OFST / 4)) = 0;
9753 + /* ACK must come before callback to handler fn. */
9754 + legacy_irq_ack(nic);
9755 + done_ack = 1;
9756 + handled++;
9757 + if (nic->irq_handler)
9758 + nic->irq_handler(nic, 0);
9759 + }
9760 +
9761 + if (unlikely(!done_ack)) {
9762 + if (!handled)
9763 + /* Shared interrupt line (hopefully). */
9764 + return 0;
9765 + legacy_irq_ack(nic);
9766 + }
9767 +
9768 + EFHW_TRACE("%s: handled %d", __func__, handled);
9769 + return 1;
9770 +}
9771 +
9772 +/*--------------------------------------------------------------------
9773 + *
9774 + * Event Management - and SW event posting
9775 + *
9776 + *--------------------------------------------------------------------*/
9777 +
9778 +static void
9779 +falcon_nic_event_queue_enable(struct efhw_nic *nic, uint evq, uint evq_size,
9780 + dma_addr_t q_base_addr, /* not used */
9781 + uint buf_base_id, int interrupting)
9782 +{
9783 + EFHW_ASSERT(nic);
9784 +
9785 + /* Whether or not queue has an interrupt depends on
9786 + * instance number and h/w variant, so [interrupting] is
9787 + * ignored.
9788 + */
9789 + falcon_ab_timer_tbl_set(nic, evq, 0/*disable*/, 0);
9790 +
9791 + falcon_nic_evq_ptr_tbl(nic, evq, 1, buf_base_id, evq_size);
9792 + EFHW_TRACE("%s: enable evq %u size %u", __func__, evq, evq_size);
9793 +}
9794 +
9795 +static void
9796 +falcon_nic_event_queue_disable(struct efhw_nic *nic, uint evq, int timer_only)
9797 +{
9798 + EFHW_ASSERT(nic);
9799 +
9800 + falcon_ab_timer_tbl_set(nic, evq, 0 /* disable */ , 0);
9801 +
9802 + if (!timer_only)
9803 + falcon_nic_evq_ptr_tbl(nic, evq, 0, 0, 0);
9804 + EFHW_TRACE("%s: disenable evq %u", __func__, evq);
9805 +}
9806 +
9807 +static void
9808 +falcon_nic_wakeup_request(struct efhw_nic *nic, dma_addr_t q_base_addr,
9809 + int next_i, int evq)
9810 +{
9811 + EFHW_ASSERT(evq > FALCON_EVQ_CHAR);
9812 + falcon_nic_evq_ack(nic, evq, next_i, true);
9813 + EFHW_TRACE("%s: evq %d next_i %d", __func__, evq, next_i);
9814 +}
9815 +
9816 +static void falcon_nic_sw_event(struct efhw_nic *nic, int data, int evq)
9817 +{
9818 + uint64_t ev_data = data;
9819 +
9820 + ev_data &= ~FALCON_EVENT_CODE_MASK;
9821 + ev_data |= FALCON_EVENT_CODE_SW;
9822 +
9823 + falcon_drv_ev(nic, ev_data, evq);
9824 + EFHW_NOTICE("%s: evq[%d]->%x", __func__, evq, data);
9825 +}
9826 +
9827 +
9828 +/*--------------------------------------------------------------------
9829 + *
9830 + * Buffer table - helpers
9831 + *
9832 + *--------------------------------------------------------------------*/
9833 +
9834 +#define FALCON_LAZY_COMMIT_HWM (FALCON_BUFFER_UPD_MAX - 16)
9835 +
9836 +/* Note re.:
9837 + * falcon_nic_buffer_table_lazy_commit(struct efhw_nic *nic)
9838 + * falcon_nic_buffer_table_update_poll(struct efhw_nic *nic)
9839 + * falcon_nic_buffer_table_confirm(struct efhw_nic *nic)
9840 + * -- these are no-ops in the user-level driver because it would need to
9841 + * coordinate with the real driver on the number of outstanding commits.
9842 + *
9843 + * An exception is made for eftest apps, which manage the hardware without
9844 + * using the char driver.
9845 + */
9846 +
9847 +static inline void falcon_nic_buffer_table_lazy_commit(struct efhw_nic *nic)
9848 +{
9849 + /* Do nothing if operating in synchronous mode. */
9850 + if (!nic->irq_handler)
9851 + return;
9852 +}
9853 +
9854 +static inline void falcon_nic_buffer_table_update_poll(struct efhw_nic *nic)
9855 +{
9856 + FALCON_LOCK_DECL;
9857 + int count = 0, rc = 0;
9858 +
9859 + /* We can be called here early days */
9860 + if (!nic->irq_handler)
9861 + return;
9862 +
9863 + /* If we need to gather buffer update events then poll the
9864 + non-interrupting event queue */
9865 +
9866 + /* For each _buffer_table_commit there will be an update done
9867 + event. We don't keep track of how many buffers each commit has
9868 + committed, just make sure that all the expected events have been
9869 + gathered */
9870 + FALCON_LOCK_LOCK(nic);
9871 +
9872 + EFHW_TRACE("%s: %d", __func__, nic->buf_commit_outstanding);
9873 +
9874 + while (nic->buf_commit_outstanding > 0) {
9875 + /* we're not expecting to handle any events that require
9876 + * upcalls into the core driver */
9877 + struct efhw_ev_handler handler;
9878 + memset(&handler, 0, sizeof(handler));
9879 + nic->non_interrupting_evq.ev_handlers = &handler;
9880 + rc = efhw_keventq_poll(nic, &nic->non_interrupting_evq);
9881 + nic->non_interrupting_evq.ev_handlers = NULL;
9882 +
9883 + if (rc < 0) {
9884 + EFHW_ERR("%s: poll ERROR (%d:%d) ***** ",
9885 + __func__, rc,
9886 + nic->buf_commit_outstanding);
9887 + goto out;
9888 + }
9889 +
9890 + FALCON_LOCK_UNLOCK(nic);
9891 +
9892 + if (count++)
9893 + udelay(1);
9894 +
9895 + if (count > 1000) {
9896 + EFHW_WARN("%s: poll Timeout ***** (%d)", __func__,
9897 + nic->buf_commit_outstanding);
9898 + nic->buf_commit_outstanding = 0;
9899 + return;
9900 + }
9901 + FALCON_LOCK_LOCK(nic);
9902 + }
9903 +
9904 +out:
9905 + FALCON_LOCK_UNLOCK(nic);
9906 + return;
9907 +}
9908 +
9909 +void falcon_nic_buffer_table_confirm(struct efhw_nic *nic)
9910 +{
9911 + /* confirm buffer table updates - should be used for items where
9912 + loss of data would be unacceptable. E.g for the buffers that back
9913 + an event or DMA queue */
9914 + FALCON_LOCK_DECL;
9915 +
9916 + /* Do nothing if operating in synchronous mode. */
9917 + if (!nic->irq_handler)
9918 + return;
9919 +
9920 + FALCON_LOCK_LOCK(nic);
9921 +
9922 + _falcon_nic_buffer_table_commit(nic);
9923 +
9924 + FALCON_LOCK_UNLOCK(nic);
9925 +
9926 + falcon_nic_buffer_table_update_poll(nic);
9927 +}
9928 +
9929 +/*--------------------------------------------------------------------
9930 + *
9931 + * Buffer table - API
9932 + *
9933 + *--------------------------------------------------------------------*/
9934 +
9935 +static void
9936 +falcon_nic_buffer_table_clear(struct efhw_nic *nic, int buffer_id, int num)
9937 +{
9938 + FALCON_LOCK_DECL;
9939 + FALCON_LOCK_LOCK(nic);
9940 + _falcon_nic_buffer_table_clear(nic, buffer_id, num);
9941 + FALCON_LOCK_UNLOCK(nic);
9942 +}
9943 +
9944 +static void
9945 +falcon_nic_buffer_table_set(struct efhw_nic *nic, dma_addr_t dma_addr,
9946 + uint bufsz, uint region,
9947 + int own_id, int buffer_id)
9948 +{
9949 + FALCON_LOCK_DECL;
9950 +
9951 + EFHW_ASSERT(region < FALCON_REGION_NUM);
9952 +
9953 + EFHW_ASSERT((bufsz == EFHW_4K) ||
9954 + (bufsz == EFHW_8K && FALCON_BUFFER_TABLE_FULL_MODE));
9955 +
9956 + falcon_nic_buffer_table_update_poll(nic);
9957 +
9958 + FALCON_LOCK_LOCK(nic);
9959 +
9960 + _falcon_nic_buffer_table_set(nic, dma_addr, bufsz, region, own_id,
9961 + buffer_id);
9962 +
9963 + falcon_nic_buffer_table_lazy_commit(nic);
9964 +
9965 + FALCON_LOCK_UNLOCK(nic);
9966 +}
9967 +
9968 +void
9969 +falcon_nic_buffer_table_set_n(struct efhw_nic *nic, int buffer_id,
9970 + dma_addr_t dma_addr, uint bufsz, uint region,
9971 + int n_pages, int own_id)
9972 +{
9973 + /* used to set up a contiguous range of buffers */
9974 + FALCON_LOCK_DECL;
9975 +
9976 + EFHW_ASSERT(region < FALCON_REGION_NUM);
9977 +
9978 + EFHW_ASSERT((bufsz == EFHW_4K) ||
9979 + (bufsz == EFHW_8K && FALCON_BUFFER_TABLE_FULL_MODE));
9980 +
9981 + while (n_pages--) {
9982 +
9983 + falcon_nic_buffer_table_update_poll(nic);
9984 +
9985 + FALCON_LOCK_LOCK(nic);
9986 +
9987 + _falcon_nic_buffer_table_set(nic, dma_addr, bufsz, region,
9988 + own_id, buffer_id++);
9989 +
9990 + falcon_nic_buffer_table_lazy_commit(nic);
9991 +
9992 + FALCON_LOCK_UNLOCK(nic);
9993 +
9994 + dma_addr += bufsz;
9995 + }
9996 +}
9997 +
9998 +/*--------------------------------------------------------------------
9999 + *
10000 + * DMA Queues - mid level API
10001 + *
10002 + *--------------------------------------------------------------------*/
10003 +
10004 +#if BUG5302_WORKAROUND
10005 +
10006 +/* Tx queues can get stuck if the software write pointer is set to an index
10007 + * beyond the configured size of the queue, such that they will not flush.
10008 + * This code can be run before attempting a flush; it will detect the bogus
10009 + * value and reset it. This fixes most instances of this problem, although
10010 + * sometimes it does not work, or we may not detect it in the first place,
10011 + * if the out-of-range value was replaced by an in-range value earlier.
10012 + * (In those cases we have to apply a bigger hammer later, if we see that
10013 + * the queue is still not flushing.)
10014 + */
10015 +static void
10016 +falcon_check_for_bogus_tx_dma_wptr(struct efhw_nic *nic, uint dmaq)
10017 +{
10018 + FALCON_LOCK_DECL;
10019 + uint64_t val_low64, val_high64;
10020 + uint64_t size, hwptr, swptr, val;
10021 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
10022 + ulong offset = falcon_dma_tx_q_offset(nic, dmaq);
10023 +
10024 + /* Falcon requires 128 bit atomic access for this register */
10025 + FALCON_LOCK_LOCK(nic);
10026 + falcon_read_qq(efhw_kva + offset, &val_low64, &val_high64);
10027 + FALCON_LOCK_UNLOCK(nic);
10028 +
10029 + size = (val_low64 >> TX_DESCQ_SIZE_LBN)
10030 + & __FALCON_MASK64(TX_DESCQ_SIZE_WIDTH);
10031 + size = (1 << size) * 512;
10032 + hwptr = (val_high64 >> __DW3(TX_DESCQ_HW_RPTR_LBN))
10033 + & __FALCON_MASK64(TX_DESCQ_HW_RPTR_WIDTH);
10034 + swptr = (val_low64 >> TX_DESCQ_SW_WPTR_LBN)
10035 + & __FALCON_MASK64(__LW2(TX_DESCQ_SW_WPTR_LBN));
10036 + val = (val_high64)
10037 + &
10038 + __FALCON_MASK64(__DW3
10039 + (TX_DESCQ_SW_WPTR_LBN + TX_DESCQ_SW_WPTR_WIDTH));
10040 + val = val << __LW2(TX_DESCQ_SW_WPTR_LBN);
10041 + swptr = swptr | val;
10042 +
10043 + if (swptr >= size) {
10044 + EFHW_WARN("Resetting bad write pointer for TXQ[%d]", dmaq);
10045 + writel((uint32_t) ((hwptr + 0) & (size - 1)),
10046 + efhw_kva + falcon_tx_dma_page_addr(dmaq) + 12);
10047 + mmiowb();
10048 + }
10049 +}
10050 +
10051 +/* Here's that "bigger hammer": we reset all the pointers (hardware read,
10052 + * hardware descriptor cache read, software write) to zero.
10053 + */
10054 +void falcon_clobber_tx_dma_ptrs(struct efhw_nic *nic, uint dmaq)
10055 +{
10056 + FALCON_LOCK_DECL;
10057 + uint64_t val_low64, val_high64;
10058 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
10059 + ulong offset = falcon_dma_tx_q_offset(nic, dmaq);
10060 +
10061 + EFHW_WARN("Recovering stuck TXQ[%d]", dmaq);
10062 + FALCON_LOCK_LOCK(nic);
10063 + falcon_read_qq(efhw_kva + offset, &val_low64, &val_high64);
10064 + val_high64 &= ~(__FALCON_MASK64(TX_DESCQ_HW_RPTR_WIDTH)
10065 + << __DW3(TX_DESCQ_HW_RPTR_LBN));
10066 + val_high64 &= ~(__FALCON_MASK64(TX_DC_HW_RPTR_WIDTH)
10067 + << __DW3(TX_DC_HW_RPTR_LBN));
10068 + falcon_write_qq(efhw_kva + offset, val_low64, val_high64);
10069 + mmiowb();
10070 + writel(0, efhw_kva + falcon_tx_dma_page_addr(dmaq) + 12);
10071 + mmiowb();
10072 + FALCON_LOCK_UNLOCK(nic);
10073 +}
10074 +
10075 +#endif
10076 +
10077 +static inline int
10078 +__falcon_really_flush_tx_dma_channel(struct efhw_nic *nic, uint dmaq)
10079 +{
10080 + FALCON_LOCK_DECL;
10081 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
10082 + uint val;
10083 +
10084 + EFHW_BUILD_ASSERT(TX_FLUSH_DESCQ_REG_KER_OFST ==
10085 + TX_FLUSH_DESCQ_REG_OFST);
10086 +
10087 + __DWCHCK(TX_FLUSH_DESCQ_CMD_LBN, TX_FLUSH_DESCQ_CMD_WIDTH);
10088 + __DWCHCK(TX_FLUSH_DESCQ_LBN, TX_FLUSH_DESCQ_WIDTH);
10089 + __RANGECHCK(dmaq, TX_FLUSH_DESCQ_WIDTH);
10090 +
10091 + val = ((1 << TX_FLUSH_DESCQ_CMD_LBN) | (dmaq << TX_FLUSH_DESCQ_LBN));
10092 +
10093 + EFHW_TRACE("TX DMA flush[%d]", dmaq);
10094 +
10095 +#if BUG5302_WORKAROUND
10096 + falcon_check_for_bogus_tx_dma_wptr(nic, dmaq);
10097 +#endif
10098 +
10099 + /* Falcon requires 128 bit atomic access for this register */
10100 + FALCON_LOCK_LOCK(nic);
10101 + falcon_write_qq(efhw_kva + TX_FLUSH_DESCQ_REG_OFST,
10102 + val, FALCON_ATOMIC_TX_FLUSH_DESCQ);
10103 +
10104 + mmiowb();
10105 + FALCON_LOCK_UNLOCK(nic);
10106 + return 0;
10107 +}
10108 +
10109 +static inline int
10110 +__falcon_is_tx_dma_channel_flushed(struct efhw_nic *nic, uint dmaq)
10111 +{
10112 + FALCON_LOCK_DECL;
10113 + uint64_t val_low64, val_high64;
10114 + uint64_t enable, flush_pending;
10115 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
10116 + ulong offset = falcon_dma_tx_q_offset(nic, dmaq);
10117 +
10118 + /* Falcon requires 128 bit atomic access for this register */
10119 + FALCON_LOCK_LOCK(nic);
10120 + falcon_read_qq(efhw_kva + offset, &val_low64, &val_high64);
10121 + FALCON_LOCK_UNLOCK(nic);
10122 +
10123 + /* should see one of three values for these 2 bits
10124 + * 1, queue enabled no flush pending
10125 + * - i.e. first flush request
10126 + * 2, queue enabled, flush pending
10127 + * - i.e. request to reflush before flush finished
10128 + * 3, queue disabled (no flush pending)
10129 + * - flush complete
10130 + */
10131 + __DWCHCK(TX_DESCQ_FLUSH_LBN, TX_DESCQ_FLUSH_WIDTH);
10132 + __DW3CHCK(TX_DESCQ_EN_LBN, TX_DESCQ_EN_WIDTH);
10133 + enable = val_high64 & (1 << __DW3(TX_DESCQ_EN_LBN));
10134 + flush_pending = val_low64 & (1 << TX_DESCQ_FLUSH_LBN);
10135 +
10136 + if (enable && !flush_pending)
10137 + return 0;
10138 +
10139 + EFHW_TRACE("%d, %s: %s, %sflush pending", dmaq, __func__,
10140 + enable ? "enabled" : "disabled",
10141 + flush_pending ? "" : "NO ");
10142 + /* still in progress */
10143 + if (enable && flush_pending)
10144 + return -EALREADY;
10145 +
10146 + return -EAGAIN;
10147 +}
10148 +
10149 +static int falcon_flush_tx_dma_channel(struct efhw_nic *nic, uint dmaq)
10150 +{
10151 + int rc;
10152 + rc = __falcon_is_tx_dma_channel_flushed(nic, dmaq);
10153 + if (rc < 0) {
10154 + EFHW_WARN("%s: failed %d", __func__, rc);
10155 + return rc;
10156 + }
10157 + return __falcon_really_flush_tx_dma_channel(nic, dmaq);
10158 +}
10159 +
10160 +static int
10161 +__falcon_really_flush_rx_dma_channel(struct efhw_nic *nic, uint dmaq)
10162 +{
10163 + FALCON_LOCK_DECL;
10164 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
10165 + uint val;
10166 +
10167 + EFHW_BUILD_ASSERT(RX_FLUSH_DESCQ_REG_KER_OFST ==
10168 + RX_FLUSH_DESCQ_REG_OFST);
10169 +
10170 + __DWCHCK(RX_FLUSH_DESCQ_CMD_LBN, RX_FLUSH_DESCQ_CMD_WIDTH);
10171 + __DWCHCK(RX_FLUSH_DESCQ_LBN, RX_FLUSH_DESCQ_WIDTH);
10172 + __RANGECHCK(dmaq, RX_FLUSH_DESCQ_WIDTH);
10173 +
10174 + val = ((1 << RX_FLUSH_DESCQ_CMD_LBN) | (dmaq << RX_FLUSH_DESCQ_LBN));
10175 +
10176 + EFHW_TRACE("RX DMA flush[%d]", dmaq);
10177 +
10178 + /* Falcon requires 128 bit atomic access for this register */
10179 + FALCON_LOCK_LOCK(nic);
10180 + falcon_write_qq(efhw_kva + RX_FLUSH_DESCQ_REG_OFST, val,
10181 + FALCON_ATOMIC_RX_FLUSH_DESCQ);
10182 + mmiowb();
10183 + FALCON_LOCK_UNLOCK(nic);
10184 + return 0;
10185 +}
10186 +
10187 +static inline int
10188 +__falcon_is_rx_dma_channel_flushed(struct efhw_nic *nic, uint dmaq)
10189 +{
10190 + FALCON_LOCK_DECL;
10191 + uint64_t val;
10192 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
10193 + ulong offset = falcon_dma_rx_q_offset(nic, dmaq);
10194 +
10195 + /* Falcon requires 128 bit atomic access for this register */
10196 + FALCON_LOCK_LOCK(nic);
10197 + falcon_read_q(efhw_kva + offset, &val);
10198 + FALCON_LOCK_UNLOCK(nic);
10199 +
10200 + __DWCHCK(RX_DESCQ_EN_LBN, RX_DESCQ_EN_WIDTH);
10201 +
10202 + /* is it enabled? */
10203 + return (val & (1 << RX_DESCQ_EN_LBN))
10204 + ? 0 : -EAGAIN;
10205 +}
10206 +
10207 +static int falcon_flush_rx_dma_channel(struct efhw_nic *nic, uint dmaq)
10208 +{
10209 + int rc;
10210 + rc = __falcon_is_rx_dma_channel_flushed(nic, dmaq);
10211 + if (rc < 0) {
10212 + EFHW_ERR("%s: failed %d", __func__, rc);
10213 + return rc;
10214 + }
10215 + return __falcon_really_flush_rx_dma_channel(nic, dmaq);
10216 +}
10217 +
10218 +/*--------------------------------------------------------------------
10219 + *
10220 + * Falcon specific event callbacks
10221 + *
10222 + *--------------------------------------------------------------------*/
10223 +
10224 +int
10225 +falcon_handle_char_event(struct efhw_nic *nic, struct efhw_ev_handler *h,
10226 + efhw_event_t *ev)
10227 +{
10228 + EFHW_TRACE("DRIVER EVENT: "FALCON_EVENT_FMT,
10229 + FALCON_EVENT_PRI_ARG(*ev));
10230 +
10231 + switch (FALCON_EVENT_DRIVER_SUBCODE(ev)) {
10232 +
10233 + case TX_DESCQ_FLS_DONE_EV_DECODE:
10234 + EFHW_TRACE("TX[%d] flushed",
10235 + (int)FALCON_EVENT_TX_FLUSH_Q_ID(ev));
10236 + efhw_handle_txdmaq_flushed(nic, h, ev);
10237 + break;
10238 +
10239 + case RX_DESCQ_FLS_DONE_EV_DECODE:
10240 + EFHW_TRACE("RX[%d] flushed",
10241 + (int)FALCON_EVENT_TX_FLUSH_Q_ID(ev));
10242 + efhw_handle_rxdmaq_flushed(nic, h, ev);
10243 + break;
10244 +
10245 + case SRM_UPD_DONE_EV_DECODE:
10246 + nic->buf_commit_outstanding =
10247 + max(0, nic->buf_commit_outstanding - 1);
10248 + EFHW_TRACE("COMMIT DONE %d", nic->buf_commit_outstanding);
10249 + break;
10250 +
10251 + case EVQ_INIT_DONE_EV_DECODE:
10252 + EFHW_TRACE("%sEVQ INIT", "");
10253 + break;
10254 +
10255 + case WAKE_UP_EV_DECODE:
10256 + EFHW_TRACE("%sWAKE UP", "");
10257 + efhw_handle_wakeup_event(nic, h, ev);
10258 + break;
10259 +
10260 + case TIMER_EV_DECODE:
10261 + EFHW_TRACE("%sTIMER", "");
10262 + efhw_handle_timeout_event(nic, h, ev);
10263 + break;
10264 +
10265 + case RX_DESCQ_FLSFF_OVFL_EV_DECODE:
10266 + /* This shouldn't happen. */
10267 + EFHW_ERR("%s: RX flush fifo overflowed", __func__);
10268 + return -EINVAL;
10269 +
10270 + default:
10271 + EFHW_TRACE("UNKOWN DRIVER EVENT: " FALCON_EVENT_FMT,
10272 + FALCON_EVENT_PRI_ARG(*ev));
10273 + break;
10274 + }
10275 + return 0;
10276 +}
10277 +
10278 +
10279 +/*--------------------------------------------------------------------
10280 + *
10281 + * Filter search depth control
10282 + *
10283 + *--------------------------------------------------------------------*/
10284 +
10285 +
10286 +#define Q0_READ(q0, name) \
10287 + ((unsigned)(((q0) >> name##_LBN) & (__FALCON_MASK64(name##_WIDTH))))
10288 +#define Q0_MASK(name) \
10289 + ((__FALCON_MASK64(name##_WIDTH)) << name##_LBN)
10290 +#define Q0_VALUE(name, value) \
10291 + (((uint64_t)(value)) << name##_LBN)
10292 +
10293 +#define Q1_READ(q1, name) \
10294 + ((unsigned)(((q1) >> (name##_LBN - 64)) & \
10295 + (__FALCON_MASK64(name##_WIDTH))))
10296 +#define Q1_MASK(name) \
10297 + ((__FALCON_MASK64(name##_WIDTH)) << (name##_LBN - 64))
10298 +#define Q1_VALUE(name, value) \
10299 + (((uint64_t)(value)) << (name##_LBN - 64))
10300 +
10301 +
10302 +void
10303 +falcon_nic_get_rx_filter_search_limits(struct efhw_nic *nic,
10304 + struct efhw_filter_search_limits *lim,
10305 + int use_raw_values)
10306 +{
10307 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
10308 + FALCON_LOCK_DECL;
10309 + uint64_t q0, q1;
10310 + unsigned ff = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_FULL);
10311 + unsigned wf = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_WILD);
10312 +
10313 + FALCON_LOCK_LOCK(nic);
10314 + falcon_read_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, &q0, &q1);
10315 + FALCON_LOCK_UNLOCK(nic);
10316 +
10317 + lim->tcp_full = Q0_READ(q0, TCP_FULL_SRCH_LIMIT) - ff;
10318 + lim->tcp_wild = Q0_READ(q0, TCP_WILD_SRCH_LIMIT) - wf;
10319 + lim->udp_full = Q0_READ(q0, UDP_FULL_SRCH_LIMIT) - ff;
10320 + lim->udp_wild = Q0_READ(q0, UDP_WILD_SRCH_LIMIT) - wf;
10321 +}
10322 +EXPORT_SYMBOL(falcon_nic_get_rx_filter_search_limits);
10323 +
10324 +
10325 +void
10326 +falcon_nic_set_rx_filter_search_limits(struct efhw_nic *nic,
10327 + struct efhw_filter_search_limits *lim,
10328 + int use_raw_values)
10329 +{
10330 + volatile char __iomem *efhw_kva = EFHW_KVA(nic);
10331 + FALCON_LOCK_DECL;
10332 + uint64_t q0, q1;
10333 + unsigned ff = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_FULL);
10334 + unsigned wf = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_WILD);
10335 +
10336 + FALCON_LOCK_LOCK(nic);
10337 + falcon_read_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, &q0, &q1);
10338 +
10339 + q0 &= ~Q0_MASK(TCP_FULL_SRCH_LIMIT);
10340 + q0 &= ~Q0_MASK(TCP_WILD_SRCH_LIMIT);
10341 + q0 &= ~Q0_MASK(UDP_FULL_SRCH_LIMIT);
10342 + q0 &= ~Q0_MASK(UDP_WILD_SRCH_LIMIT);
10343 + q0 |= Q0_VALUE(TCP_FULL_SRCH_LIMIT, lim->tcp_full + ff);
10344 + q0 |= Q0_VALUE(TCP_WILD_SRCH_LIMIT, lim->tcp_wild + wf);
10345 + q0 |= Q0_VALUE(UDP_FULL_SRCH_LIMIT, lim->udp_full + ff);
10346 + q0 |= Q0_VALUE(UDP_WILD_SRCH_LIMIT, lim->udp_wild + wf);
10347 + nic->tcp_full_srch.max = lim->tcp_full + ff
10348 + - RX_FILTER_CTL_SRCH_FUDGE_FULL;
10349 + nic->tcp_wild_srch.max = lim->tcp_wild + wf
10350 + - RX_FILTER_CTL_SRCH_FUDGE_WILD;
10351 + nic->udp_full_srch.max = lim->udp_full + ff
10352 + - RX_FILTER_CTL_SRCH_FUDGE_FULL;
10353 + nic->udp_wild_srch.max = lim->udp_wild + wf
10354 + - RX_FILTER_CTL_SRCH_FUDGE_WILD;
10355 +
10356 + falcon_write_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, q0, q1);
10357 + mmiowb();
10358 + FALCON_LOCK_UNLOCK(nic);
10359 +}
10360 +EXPORT_SYMBOL(falcon_nic_set_rx_filter_search_limits);
10361 +
10362 +
10363 +#undef READ_Q0
10364 +#undef Q0_MASK
10365 +#undef Q0_VALUE
10366 +#undef READ_Q1
10367 +#undef Q1_MASK
10368 +#undef Q1_VALUE
10369 +
10370 +
10371 +/*--------------------------------------------------------------------
10372 + *
10373 + * New unified filter API
10374 + *
10375 + *--------------------------------------------------------------------*/
10376 +
10377 +
10378 +#if FALCON_FULL_FILTER_CACHE
10379 +static inline struct efhw_filter_spec *
10380 +filter_spec_cache_entry(struct efhw_nic *nic, int filter_idx)
10381 +{
10382 + EFHW_ASSERT(nic->filter_spec_cache);
10383 + return &nic->filter_spec_cache[filter_idx];
10384 +}
10385 +#endif
10386 +
10387 +
10388 +static int filter_is_active(struct efhw_nic *nic, int filter_idx)
10389 +{
10390 + return nic->filter_in_use[filter_idx];
10391 +}
10392 +
10393 +
10394 +static void set_filter_cache_entry(struct efhw_nic *nic,
10395 + struct efhw_filter_spec *spec,
10396 + int filter_idx)
10397 +{
10398 + nic->filter_in_use[filter_idx] = 1;
10399 +#if FALCON_FULL_FILTER_CACHE
10400 + memcpy(filter_spec_cache_entry(nic, filter_idx), spec,
10401 + sizeof(struct efhw_filter_spec));
10402 +#endif
10403 +}
10404 +
10405 +
10406 +static void clear_filter_cache_entry(struct efhw_nic *nic,
10407 + int filter_idx)
10408 +{
10409 + nic->filter_in_use[filter_idx] = 0;
10410 +#if FALCON_FULL_FILTER_CACHE
10411 + memset(filter_spec_cache_entry(nic, filter_idx), 0,
10412 + sizeof(struct efhw_filter_spec));
10413 +#endif
10414 +}
10415 +
10416 +
10417 +#if FALCON_FULL_FILTER_CACHE
10418 +static int filter_is_duplicate(struct efhw_nic *nic,
10419 + struct efhw_filter_spec *spec, int filter_idx)
10420 +{
10421 + struct efhw_filter_spec *cmp;
10422 +
10423 + cmp = filter_spec_cache_entry(nic, filter_idx);
10424 +
10425 + EFHW_ASSERT(filter_is_active(nic, filter_idx));
10426 +
10427 + return (spec->saddr_le32 == cmp->saddr_le32) &&
10428 + (spec->daddr_le32 == cmp->daddr_le32) &&
10429 + (spec->sport_le16 == cmp->sport_le16) &&
10430 + (spec->dport_le16 == cmp->dport_le16) &&
10431 + (spec->tcp == cmp->tcp) &&
10432 + (spec->full == cmp->full);
10433 +}
10434 +#endif
10435 +
10436 +
10437 +static void common_build_ip_filter(struct efhw_nic *nic, int tcp, int full,
10438 + int rss, int scatter, uint dmaq_id,
10439 + unsigned saddr_le32, unsigned sport_le16,
10440 + unsigned daddr_le32, unsigned dport_le16,
10441 + uint64_t *q0, uint64_t *q1)
10442 +{
10443 + uint64_t v1, v2, v3, v4;
10444 + unsigned tmp_port_le16;
10445 +
10446 + if (!full) {
10447 + saddr_le32 = 0;
10448 + sport_le16 = 0;
10449 + if (!tcp) {
10450 + tmp_port_le16 = sport_le16;
10451 + sport_le16 = dport_le16;
10452 + dport_le16 = tmp_port_le16;
10453 + }
10454 + }
10455 +
10456 + v4 = (((!tcp) << __DW4(TCP_UDP_0_LBN)) |
10457 + (dmaq_id << __DW4(RXQ_ID_0_LBN)));
10458 +
10459 + switch (nic->devtype.variant) {
10460 + case 'A':
10461 + EFHW_ASSERT(!rss);
10462 + break;
10463 + case 'B':
10464 + v4 |= scatter << __DW4(SCATTER_EN_0_B0_LBN);
10465 + v4 |= rss << __DW4(RSS_EN_0_B0_LBN);
10466 + break;
10467 + default:
10468 + EFHW_ASSERT(0);
10469 + break;
10470 + }
10471 +
10472 + v3 = daddr_le32;
10473 + v2 = ((dport_le16 << __DW2(DEST_PORT_TCP_0_LBN)) |
10474 + (__HIGH(saddr_le32, SRC_IP_0_LBN, SRC_IP_0_WIDTH)));
10475 + v1 = ((__LOW(saddr_le32, SRC_IP_0_LBN, SRC_IP_0_WIDTH)) |
10476 + (sport_le16 << SRC_TCP_DEST_UDP_0_LBN));
10477 +
10478 + *q0 = (v2 << 32) | v1;
10479 + *q1 = (v4 << 32) | v3;
10480 +}
10481 +
10482 +
10483 +static void build_filter(struct efhw_nic *nic, struct efhw_filter_spec *spec,
10484 + unsigned *key, unsigned *tbl_size,
10485 + struct efhw_filter_depth **depth,
10486 + uint64_t *q0, uint64_t *q1)
10487 +{
10488 + *key = falcon_hash_get_ip_key(spec->saddr_le32,
10489 + spec->sport_le16,
10490 + spec->daddr_le32,
10491 + spec->dport_le16,
10492 + spec->tcp,
10493 + spec->full);
10494 + *tbl_size = nic->ip_filter_tbl_size;
10495 + if (spec->tcp && spec->full)
10496 + *depth = &nic->tcp_full_srch;
10497 + else if (spec->tcp && !spec->full)
10498 + *depth = &nic->tcp_wild_srch;
10499 + else if (!spec->tcp && spec->full)
10500 + *depth = &nic->udp_full_srch;
10501 + else
10502 + *depth = &nic->udp_wild_srch;
10503 + common_build_ip_filter(nic, spec->tcp, spec->full,
10504 + spec->rss, spec->scatter,
10505 + spec->dmaq_id,
10506 + spec->saddr_le32,
10507 + spec->sport_le16,
10508 + spec->daddr_le32,
10509 + spec->dport_le16,
10510 + q0, q1);
10511 +}
10512 +
10513 +
10514 +#if FALCON_VERIFY_FILTERS
10515 +static void verify_filters(struct efhw_nic *nic)
10516 +{
10517 + unsigned table_offset, table_stride;
10518 + unsigned i, dummy_key, dummy_tbl_size;
10519 + struct efhw_filter_depth *dummy_depth;
10520 + unsigned filter_tbl_size;
10521 + struct efhw_filter_spec *spec;
10522 + uint64_t q0_expect, q1_expect, q0_got, q1_got;
10523 +
10524 + filter_tbl_size = nic->ip_filter_tbl_size;
10525 + table_offset = RX_FILTER_TBL0_OFST;
10526 + table_stride = 2 * FALCON_REGISTER128;
10527 +
10528 + for (i = 0; i < filter_tbl_size; i++) {
10529 + if (!filter_is_active(nic, type, i))
10530 + continue;
10531 +
10532 + spec = filter_spec_cache_entry(nic, type, i);
10533 +
10534 + build_filter(nic, spec, &dummy_key, &dummy_tbl_size,
10535 + &dummy_depth, &q0_expect, &q1_expect);
10536 +
10537 + falcon_read_qq(EFHW_KVA(nic) + table_offset + i * table_stride,
10538 + &q0_got, &q1_got);
10539 +
10540 + if ((q0_got != q0_expect) || (q1_got != q1_expect)) {
10541 + falcon_write_qq(EFHW_KVA(nic) + 0x300,
10542 + q0_got, q1_got);
10543 + EFHW_ERR("ERROR: RX-filter[%d][%d] was "
10544 + "%"PRIx64":%" PRIx64" expected "
10545 + "%"PRIx64":%"PRIx64,
10546 + nic->index, i, q0_got, q1_got,
10547 + q0_expect, q1_expect);
10548 + }
10549 + }
10550 +}
10551 +#endif
10552 +
10553 +
10554 +static void write_filter_table_entry(struct efhw_nic *nic,
10555 + unsigned filter_idx,
10556 + uint64_t q0, uint64_t q1)
10557 +{
10558 + unsigned table_offset, table_stride, offset;
10559 +
10560 + EFHW_ASSERT(filter_idx < nic->ip_filter_tbl_size);
10561 + table_offset = RX_FILTER_TBL0_OFST;
10562 + table_stride = 2 * FALCON_REGISTER128;
10563 +
10564 + offset = table_offset + filter_idx * table_stride;
10565 + falcon_write_qq(EFHW_KVA(nic) + offset, q0, q1);
10566 + mmiowb();
10567 +
10568 +#if FALCON_VERIFY_FILTERS
10569 + {
10570 + uint64_t q0read, q1read;
10571 +
10572 + /* Read a different entry first - ensure BIU flushed shadow */
10573 + falcon_read_qq(EFHW_KVA(nic) + offset + 0x10, &q0read, &q1read);
10574 + falcon_read_qq(EFHW_KVA(nic) + offset, &q0read, &q1read);
10575 + EFHW_ASSERT(q0read == q0);
10576 + EFHW_ASSERT(q1read == q1);
10577 +
10578 + verify_filters(nic, type);
10579 + }
10580 +#endif
10581 +}
10582 +
10583 +
10584 +static int falcon_nic_filter_set(struct efhw_nic *nic,
10585 + struct efhw_filter_spec *spec,
10586 + int *filter_idx_out)
10587 +{
10588 + FALCON_LOCK_DECL;
10589 + unsigned key = 0, tbl_size = 0, hash1, hash2, k;
10590 + struct efhw_filter_depth *depth = NULL;
10591 + int filter_idx = -1;
10592 + int rc = 0;
10593 + uint64_t q0, q1;
10594 +
10595 + build_filter(nic, spec, &key, &tbl_size, &depth, &q0, &q1);
10596 +
10597 + if (tbl_size == 0)
10598 + return -EINVAL;
10599 +
10600 + EFHW_TRACE("%s: depth->max=%d", __func__, depth->max);
10601 +
10602 + hash1 = falcon_hash_function1(key, tbl_size);
10603 + hash2 = falcon_hash_function2(key, tbl_size);
10604 +
10605 + FALCON_LOCK_LOCK(nic);
10606 +
10607 + for (k = 0; k < depth->max; k++) {
10608 + filter_idx = falcon_hash_iterator(hash1, hash2, k, tbl_size);
10609 + if (!filter_is_active(nic, filter_idx))
10610 + break;
10611 +#if FALCON_FULL_FILTER_CACHE
10612 + if (filter_is_duplicate(nic, spec, filter_idx)) {
10613 + EFHW_WARN("%s: ERROR: duplicate filter (disabling "
10614 + "interrupts)", __func__);
10615 + falcon_nic_interrupt_hw_disable(nic);
10616 + rc = -EINVAL;
10617 + goto fail1;
10618 + }
10619 +#endif
10620 + }
10621 + if (k == depth->max) {
10622 + rc = -EADDRINUSE;
10623 + filter_idx = -1;
10624 + goto fail1;
10625 + } else if (depth->needed < (k + 1)) {
10626 + depth->needed = k + 1;
10627 + }
10628 +
10629 + EFHW_ASSERT(filter_idx < (int)tbl_size);
10630 +
10631 + set_filter_cache_entry(nic, spec, filter_idx);
10632 + write_filter_table_entry(nic, filter_idx, q0, q1);
10633 +
10634 + ++nic->ip_filter_tbl_used;
10635 +
10636 + *filter_idx_out = filter_idx;
10637 +
10638 + EFHW_TRACE("%s: filter index %d rxq %u set in %u",
10639 + __func__, filter_idx, spec->dmaq_id, k);
10640 +
10641 +fail1:
10642 + FALCON_LOCK_UNLOCK(nic);
10643 + return rc;
10644 +}
10645 +
10646 +
10647 +static void falcon_nic_filter_clear(struct efhw_nic *nic,
10648 + int filter_idx)
10649 +{
10650 + FALCON_LOCK_DECL;
10651 +
10652 + if (filter_idx < 0)
10653 + return;
10654 +
10655 + FALCON_LOCK_LOCK(nic);
10656 + if (filter_is_active(nic, filter_idx)) {
10657 + if (--nic->ip_filter_tbl_used == 0) {
10658 + nic->tcp_full_srch.needed = 0;
10659 + nic->tcp_wild_srch.needed = 0;
10660 + nic->udp_full_srch.needed = 0;
10661 + nic->udp_wild_srch.needed = 0;
10662 + }
10663 + }
10664 + clear_filter_cache_entry(nic, filter_idx);
10665 + write_filter_table_entry(nic, filter_idx, 0, 0);
10666 + FALCON_LOCK_UNLOCK(nic);
10667 +}
10668 +
10669 +
10670 +int
10671 +falcon_nic_filter_ctor(struct efhw_nic *nic)
10672 +{
10673 + nic->ip_filter_tbl_size = 8 * 1024;
10674 + nic->ip_filter_tbl_used = 0;
10675 +
10676 + nic->tcp_full_srch.needed = 0;
10677 + nic->tcp_full_srch.max = RX_FILTER_CTL_SRCH_LIMIT_TCP_FULL
10678 + - RX_FILTER_CTL_SRCH_FUDGE_FULL;
10679 + nic->tcp_wild_srch.needed = 0;
10680 + nic->tcp_wild_srch.max = RX_FILTER_CTL_SRCH_LIMIT_TCP_WILD
10681 + - RX_FILTER_CTL_SRCH_FUDGE_WILD;
10682 + nic->udp_full_srch.needed = 0;
10683 + nic->udp_full_srch.max = RX_FILTER_CTL_SRCH_LIMIT_UDP_FULL
10684 + - RX_FILTER_CTL_SRCH_FUDGE_FULL;
10685 + nic->udp_wild_srch.needed = 0;
10686 + nic->udp_wild_srch.max = RX_FILTER_CTL_SRCH_LIMIT_UDP_WILD
10687 + - RX_FILTER_CTL_SRCH_FUDGE_WILD;
10688 +
10689 + nic->filter_in_use = vmalloc(FALCON_FILTER_TBL_NUM);
10690 + if (nic->filter_in_use == NULL)
10691 + return -ENOMEM;
10692 + memset(nic->filter_in_use, 0, FALCON_FILTER_TBL_NUM);
10693 +#if FALCON_FULL_FILTER_CACHE
10694 + nic->filter_spec_cache = vmalloc(FALCON_FILTER_TBL_NUM
10695 + * sizeof(struct efhw_filter_spec));
10696 + if (nic->filter_spec_cache == NULL)
10697 + return -ENOMEM;
10698 + memset(nic->filter_spec_cache, 0, FALCON_FILTER_TBL_NUM
10699 + * sizeof(struct efhw_filter_spec));
10700 +#endif
10701 +
10702 + return 0;
10703 +}
10704 +
10705 +
10706 +void
10707 +falcon_nic_filter_dtor(struct efhw_nic *nic)
10708 +{
10709 +#if FALCON_FULL_FILTER_CACHE
10710 + if (nic->filter_spec_cache)
10711 + vfree(nic->filter_spec_cache);
10712 +#endif
10713 + if (nic->filter_in_use)
10714 + vfree(nic->filter_in_use);
10715 +}
10716 +
10717 +
10718 +/*--------------------------------------------------------------------
10719 + *
10720 + * Compatibility with old filter API
10721 + *
10722 + *--------------------------------------------------------------------*/
10723 +
10724 +void
10725 +falcon_nic_rx_filter_ctl_get(struct efhw_nic *nic, uint32_t *tcp_full,
10726 + uint32_t *tcp_wild,
10727 + uint32_t *udp_full, uint32_t *udp_wild)
10728 +{
10729 + struct efhw_filter_search_limits lim;
10730 +
10731 + falcon_nic_get_rx_filter_search_limits(nic, &lim, 0);
10732 + *tcp_full = (uint32_t)lim.tcp_full;
10733 + *tcp_wild = (uint32_t)lim.tcp_wild;
10734 + *udp_full = (uint32_t)lim.udp_full;
10735 + *udp_wild = (uint32_t)lim.udp_wild;
10736 +}
10737 +EXPORT_SYMBOL(falcon_nic_rx_filter_ctl_get);
10738 +
10739 +
10740 +void
10741 +falcon_nic_rx_filter_ctl_set(struct efhw_nic *nic, uint32_t tcp_full,
10742 + uint32_t tcp_wild,
10743 + uint32_t udp_full, uint32_t udp_wild)
10744 +{
10745 + struct efhw_filter_search_limits lim;
10746 +
10747 + lim.tcp_full = (unsigned)tcp_full;
10748 + lim.tcp_wild = (unsigned)tcp_wild;
10749 + lim.udp_full = (unsigned)udp_full;
10750 + lim.udp_wild = (unsigned)udp_wild;
10751 + falcon_nic_set_rx_filter_search_limits(nic, &lim, 0);
10752 +}
10753 +EXPORT_SYMBOL(falcon_nic_rx_filter_ctl_set);
10754 +
10755 +
10756 +static int
10757 +falcon_nic_ipfilter_set(struct efhw_nic *nic, int type, int *_filter_idx,
10758 + int dmaq,
10759 + unsigned saddr_be32, unsigned sport_be16,
10760 + unsigned daddr_be32, unsigned dport_be16)
10761 +{
10762 + struct efhw_filter_spec spec;
10763 +
10764 + spec.dmaq_id = dmaq;
10765 + spec.saddr_le32 = ntohl(saddr_be32);
10766 + spec.daddr_le32 = ntohl(daddr_be32);
10767 + spec.sport_le16 = ntohs((unsigned short) sport_be16);
10768 + spec.dport_le16 = ntohs((unsigned short) dport_be16);
10769 + spec.tcp = ((type & EFHW_IP_FILTER_TYPE_TCP_MASK) != 0);
10770 + spec.full = ((type & EFHW_IP_FILTER_TYPE_FULL_MASK) != 0);
10771 + spec.rss = ((type & EFHW_IP_FILTER_TYPE_RSS_B0_MASK) != 0);
10772 + spec.scatter = ((type & EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK) == 0);
10773 + return falcon_nic_filter_set(nic, &spec, _filter_idx);
10774 +}
10775 +
10776 +static void falcon_nic_ipfilter_clear(struct efhw_nic *nic, int filter_idx)
10777 +{
10778 + falcon_nic_filter_clear(nic, filter_idx);
10779 +}
10780 +
10781 +
10782 +/*--------------------------------------------------------------------
10783 + *
10784 + * Abstraction Layer Hooks
10785 + *
10786 + *--------------------------------------------------------------------*/
10787 +
10788 +struct efhw_func_ops falcon_char_functional_units = {
10789 + falcon_nic_close_hardware,
10790 + falcon_nic_init_hardware,
10791 + falcon_nic_interrupt,
10792 + falcon_nic_interrupt_enable,
10793 + falcon_nic_interrupt_disable,
10794 + falcon_nic_set_interrupt_moderation,
10795 + falcon_nic_event_queue_enable,
10796 + falcon_nic_event_queue_disable,
10797 + falcon_nic_wakeup_request,
10798 + falcon_nic_sw_event,
10799 + falcon_nic_ipfilter_set,
10800 + falcon_nic_ipfilter_clear,
10801 + falcon_dmaq_tx_q_init,
10802 + falcon_dmaq_rx_q_init,
10803 + falcon_dmaq_tx_q_disable,
10804 + falcon_dmaq_rx_q_disable,
10805 + falcon_flush_tx_dma_channel,
10806 + falcon_flush_rx_dma_channel,
10807 + falcon_nic_buffer_table_set,
10808 + falcon_nic_buffer_table_set_n,
10809 + falcon_nic_buffer_table_clear,
10810 + falcon_nic_buffer_table_commit,
10811 + falcon_nic_filter_set,
10812 + falcon_nic_filter_clear,
10813 +};
10814 +
10815 +
10816 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/falcon_hash.c
10817 ===================================================================
10818 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
10819 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/falcon_hash.c 2008-07-17 16:18:07.000000000 +0200
10820 @@ -0,0 +1,159 @@
10821 +/****************************************************************************
10822 + * Driver for Solarflare network controllers -
10823 + * resource management for Xen backend, OpenOnload, etc
10824 + * (including support for SFE4001 10GBT NIC)
10825 + *
10826 + * This file contains EtherFabric NIC hash algorithms implementation.
10827 + *
10828 + * Copyright 2005-2007: Solarflare Communications Inc,
10829 + * 9501 Jeronimo Road, Suite 250,
10830 + * Irvine, CA 92618, USA
10831 + *
10832 + * Developed and maintained by Solarflare Communications:
10833 + * <linux-xen-drivers@solarflare.com>
10834 + * <onload-dev@solarflare.com>
10835 + *
10836 + *
10837 + * This program is free software; you can redistribute it and/or modify it
10838 + * under the terms of the GNU General Public License version 2 as published
10839 + * by the Free Software Foundation, incorporated herein by reference.
10840 + *
10841 + * This program is distributed in the hope that it will be useful,
10842 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10843 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10844 + * GNU General Public License for more details.
10845 + *
10846 + * You should have received a copy of the GNU General Public License
10847 + * along with this program; if not, write to the Free Software
10848 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10849 + ****************************************************************************
10850 + */
10851 +
10852 +#include <ci/efhw/debug.h>
10853 +#include <ci/driver/efab/hardware.h>
10854 +
10855 +
10856 +static unsigned int
10857 +common_get_ip_key(unsigned int src_ip, unsigned int src_port,
10858 + unsigned int dest_ip, unsigned int dest_port,
10859 + int tcp, int full, int tx, unsigned int masked_q_id)
10860 +{
10861 +
10862 + unsigned int tmp_port, result;
10863 +
10864 + EFHW_ASSERT(tcp == 0 || tcp == 1);
10865 + EFHW_ASSERT(full == 0 || full == 1);
10866 + EFHW_ASSERT(masked_q_id < (1 << 10));
10867 +
10868 + /* m=masked_q_id(TX)/0(RX) u=UDP S,D=src/dest addr s,d=src/dest port
10869 + *
10870 + * Wildcard filters have src(TX)/dest(RX) addr and port = 0;
10871 + * and UDP wildcard filters have the src and dest port fields swapped.
10872 + *
10873 + * Addr/port fields are little-endian.
10874 + *
10875 + * 3322222222221111111111
10876 + * 10987654321098765432109876543210
10877 + *
10878 + * 000000000000000000000mmmmmmmmmmu ^
10879 + * DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD ^
10880 + * ddddddddddddddddSSSSSSSSSSSSSSSS ^
10881 + * SSSSSSSSSSSSSSSSssssssssssssssss
10882 + */
10883 +
10884 + if (!tx)
10885 + masked_q_id = 0;
10886 +
10887 + if (!full) {
10888 + if (tx) {
10889 + dest_ip = 0;
10890 + dest_port = 0;
10891 + } else {
10892 + src_ip = 0;
10893 + src_port = 0;
10894 + }
10895 + if (!tcp) {
10896 + tmp_port = src_port;
10897 + src_port = dest_port;
10898 + dest_port = tmp_port;
10899 + }
10900 + }
10901 +
10902 + result = ((masked_q_id << 1) | (!tcp)) ^
10903 + (dest_ip) ^
10904 + (((dest_port & 0xffff) << 16) | ((src_ip >> 16) & 0xffff)) ^
10905 + (((src_ip & 0xffff) << 16) | (src_port & 0xffff));
10906 +
10907 + EFHW_TRACE("%s: IP %s %s %x", __func__, tcp ? "TCP" : "UDP",
10908 + full ? "Full" : "Wildcard", result);
10909 +
10910 + return result;
10911 +}
10912 +
10913 +
10914 +unsigned int
10915 +falcon_hash_get_ip_key(unsigned int src_ip, unsigned int src_port,
10916 + unsigned int dest_ip, unsigned int dest_port,
10917 + int tcp, int full)
10918 +{
10919 + return common_get_ip_key(src_ip, src_port, dest_ip, dest_port, tcp,
10920 + full, 0, 0);
10921 +}
10922 +
10923 +
10924 +/* This function generates the First Hash key */
10925 +unsigned int falcon_hash_function1(unsigned int key, unsigned int nfilters)
10926 +{
10927 +
10928 + unsigned short int lfsr_reg;
10929 + unsigned int tmp_key;
10930 + int index;
10931 +
10932 + unsigned short int lfsr_input;
10933 + unsigned short int single_bit_key;
10934 + unsigned short int bit16_lfsr;
10935 + unsigned short int bit3_lfsr;
10936 +
10937 + lfsr_reg = 0xFFFF;
10938 + tmp_key = key;
10939 +
10940 + /* For Polynomial equation X^16+X^3+1 */
10941 + for (index = 0; index < 32; index++) {
10942 + /* Get the bit from key and shift the key */
10943 + single_bit_key = (tmp_key & 0x80000000) >> 31;
10944 + tmp_key = tmp_key << 1;
10945 +
10946 + /* get the Tap bits to XOR operation */
10947 + bit16_lfsr = (lfsr_reg & 0x8000) >> 15;
10948 + bit3_lfsr = (lfsr_reg & 0x0004) >> 2;
10949 +
10950 + /* Get the Input value to the LFSR */
10951 + lfsr_input = ((bit16_lfsr ^ bit3_lfsr) ^ single_bit_key);
10952 +
10953 + /* Shift and store out of the two TAPs */
10954 + lfsr_reg = lfsr_reg << 1;
10955 + lfsr_reg = lfsr_reg | (lfsr_input & 0x0001);
10956 +
10957 + }
10958 +
10959 + lfsr_reg = lfsr_reg & (nfilters - 1);
10960 +
10961 + return lfsr_reg;
10962 +}
10963 +
10964 +/* This function generates the Second Hash */
10965 +unsigned int
10966 +falcon_hash_function2(unsigned int key, unsigned int nfilters)
10967 +{
10968 + return (unsigned int)(((unsigned long long)key * 2 - 1) &
10969 + (nfilters - 1));
10970 +}
10971 +
10972 +/* This function iterates through the hash table */
10973 +unsigned int
10974 +falcon_hash_iterator(unsigned int hash1, unsigned int hash2,
10975 + unsigned int n_search, unsigned int nfilters)
10976 +{
10977 + return (hash1 + (n_search * hash2)) & (nfilters - 1);
10978 +}
10979 +
10980 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/filter_resource.c
10981 ===================================================================
10982 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
10983 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/filter_resource.c 2008-07-17 16:18:07.000000000 +0200
10984 @@ -0,0 +1,250 @@
10985 +/****************************************************************************
10986 + * Driver for Solarflare network controllers -
10987 + * resource management for Xen backend, OpenOnload, etc
10988 + * (including support for SFE4001 10GBT NIC)
10989 + *
10990 + * This file contains filters support.
10991 + *
10992 + * Copyright 2005-2007: Solarflare Communications Inc,
10993 + * 9501 Jeronimo Road, Suite 250,
10994 + * Irvine, CA 92618, USA
10995 + *
10996 + * Developed and maintained by Solarflare Communications:
10997 + * <linux-xen-drivers@solarflare.com>
10998 + * <onload-dev@solarflare.com>
10999 + *
11000 + * Certain parts of the driver were implemented by
11001 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
11002 + * OKTET Labs Ltd, Russia,
11003 + * http://oktetlabs.ru, <info@oktetlabs.ru>
11004 + * by request of Solarflare Communications
11005 + *
11006 + *
11007 + * This program is free software; you can redistribute it and/or modify it
11008 + * under the terms of the GNU General Public License version 2 as published
11009 + * by the Free Software Foundation, incorporated herein by reference.
11010 + *
11011 + * This program is distributed in the hope that it will be useful,
11012 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11013 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11014 + * GNU General Public License for more details.
11015 + *
11016 + * You should have received a copy of the GNU General Public License
11017 + * along with this program; if not, write to the Free Software
11018 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11019 + ****************************************************************************
11020 + */
11021 +
11022 +#include <ci/efrm/nic_table.h>
11023 +#include <ci/driver/efab/hardware.h>
11024 +#include <ci/efhw/falcon.h>
11025 +#include <ci/efrm/vi_resource_manager.h>
11026 +#include <ci/efrm/private.h>
11027 +#include <ci/efrm/filter.h>
11028 +#include <ci/efrm/buffer_table.h>
11029 +#include <ci/efrm/efrm_client.h>
11030 +#include "efrm_internal.h"
11031 +
11032 +
11033 +struct filter_resource_manager {
11034 + struct efrm_resource_manager rm;
11035 + struct kfifo *free_ids;
11036 +};
11037 +
11038 +static struct filter_resource_manager *efrm_filter_manager;
11039 +
11040 +
11041 +void efrm_filter_resource_free(struct filter_resource *frs)
11042 +{
11043 + struct efhw_nic *nic = frs->rs.rs_client->nic;
11044 + int id;
11045 +
11046 + EFRM_RESOURCE_ASSERT_VALID(&frs->rs, 1);
11047 +
11048 + EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __func__,
11049 + EFRM_RESOURCE_PRI_ARG(frs->rs.rs_handle));
11050 +
11051 + efhw_nic_ipfilter_clear(nic, frs->filter_idx);
11052 + frs->filter_idx = -1;
11053 + efrm_vi_resource_release(frs->pt);
11054 +
11055 + /* Free this filter. */
11056 + id = EFRM_RESOURCE_INSTANCE(frs->rs.rs_handle);
11057 + EFRM_VERIFY_EQ(kfifo_put(efrm_filter_manager->free_ids,
11058 + (unsigned char *)&id, sizeof(id)),
11059 + sizeof(id));
11060 +
11061 + efrm_client_put(frs->rs.rs_client);
11062 + EFRM_DO_DEBUG(memset(frs, 0, sizeof(*frs)));
11063 + kfree(frs);
11064 +}
11065 +EXPORT_SYMBOL(efrm_filter_resource_free);
11066 +
11067 +
11068 +void efrm_filter_resource_release(struct filter_resource *frs)
11069 +{
11070 + if (__efrm_resource_release(&frs->rs))
11071 + efrm_filter_resource_free(frs);
11072 +}
11073 +EXPORT_SYMBOL(efrm_filter_resource_release);
11074 +
11075 +
11076 +static void filter_rm_dtor(struct efrm_resource_manager *rm)
11077 +{
11078 + EFRM_TRACE("%s:", __func__);
11079 +
11080 + EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_filter_manager->rm);
11081 + EFRM_ASSERT(&efrm_filter_manager->rm == rm);
11082 +
11083 + kfifo_vfree(efrm_filter_manager->free_ids);
11084 + EFRM_TRACE("%s: done", __func__);
11085 +}
11086 +
11087 +/**********************************************************************/
11088 +/**********************************************************************/
11089 +/**********************************************************************/
11090 +
11091 +int efrm_create_filter_resource_manager(struct efrm_resource_manager **rm_out)
11092 +{
11093 + int rc;
11094 +
11095 + EFRM_ASSERT(rm_out);
11096 +
11097 + efrm_filter_manager =
11098 + kmalloc(sizeof(struct filter_resource_manager), GFP_KERNEL);
11099 + if (efrm_filter_manager == 0)
11100 + return -ENOMEM;
11101 + memset(efrm_filter_manager, 0, sizeof(*efrm_filter_manager));
11102 +
11103 + rc = efrm_resource_manager_ctor(&efrm_filter_manager->rm,
11104 + filter_rm_dtor, "FILTER",
11105 + EFRM_RESOURCE_FILTER);
11106 + if (rc < 0)
11107 + goto fail1;
11108 +
11109 + /* Create a pool of free instances */
11110 + rc = efrm_kfifo_id_ctor(&efrm_filter_manager->free_ids,
11111 + 0, EFHW_IP_FILTER_NUM,
11112 + &efrm_filter_manager->rm.rm_lock);
11113 + if (rc != 0)
11114 + goto fail2;
11115 +
11116 + *rm_out = &efrm_filter_manager->rm;
11117 + EFRM_TRACE("%s: filter resources created - %d IDs",
11118 + __func__, kfifo_len(efrm_filter_manager->free_ids));
11119 + return 0;
11120 +
11121 +fail2:
11122 + efrm_resource_manager_dtor(&efrm_filter_manager->rm);
11123 +fail1:
11124 + memset(efrm_filter_manager, 0, sizeof(*efrm_filter_manager));
11125 + kfree(efrm_filter_manager);
11126 + return rc;
11127 +
11128 +}
11129 +
11130 +
11131 +int efrm_filter_resource_clear(struct filter_resource *frs)
11132 +{
11133 + struct efhw_nic *nic = frs->rs.rs_client->nic;
11134 +
11135 + efhw_nic_ipfilter_clear(nic, frs->filter_idx);
11136 + frs->filter_idx = -1;
11137 + return 0;
11138 +}
11139 +EXPORT_SYMBOL(efrm_filter_resource_clear);
11140 +
11141 +
11142 +int
11143 +__efrm_filter_resource_set(struct filter_resource *frs, int type,
11144 + unsigned saddr, uint16_t sport,
11145 + unsigned daddr, uint16_t dport)
11146 +{
11147 + struct efhw_nic *nic = frs->rs.rs_client->nic;
11148 + int vi_instance;
11149 +
11150 + EFRM_ASSERT(frs);
11151 +
11152 + if (efrm_nic_tablep->a_nic->devtype.variant >= 'B' &&
11153 + (frs->pt->flags & EFHW_VI_JUMBO_EN) == 0)
11154 + type |= EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK;
11155 + vi_instance = EFRM_RESOURCE_INSTANCE(frs->pt->rs.rs_handle);
11156 +
11157 + return efhw_nic_ipfilter_set(nic, type, &frs->filter_idx,
11158 + vi_instance, saddr, sport, daddr, dport);
11159 +}
11160 +EXPORT_SYMBOL(__efrm_filter_resource_set);;
11161 +
11162 +
11163 +int
11164 +efrm_filter_resource_alloc(struct vi_resource *vi_parent,
11165 + struct filter_resource **frs_out)
11166 +{
11167 + struct filter_resource *frs;
11168 + int rc, instance;
11169 +
11170 + EFRM_ASSERT(frs_out);
11171 + EFRM_ASSERT(efrm_filter_manager);
11172 + EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_filter_manager->rm);
11173 + EFRM_ASSERT(vi_parent != NULL);
11174 + EFRM_ASSERT(EFRM_RESOURCE_TYPE(vi_parent->rs.rs_handle) ==
11175 + EFRM_RESOURCE_VI);
11176 +
11177 + /* Allocate resource data structure. */
11178 + frs = kmalloc(sizeof(struct filter_resource), GFP_KERNEL);
11179 + if (!frs)
11180 + return -ENOMEM;
11181 +
11182 + /* Allocate an instance. */
11183 + rc = kfifo_get(efrm_filter_manager->free_ids,
11184 + (unsigned char *)&instance, sizeof(instance));
11185 + if (rc != sizeof(instance)) {
11186 + EFRM_TRACE("%s: out of instances", __func__);
11187 + EFRM_ASSERT(rc == 0);
11188 + rc = -EBUSY;
11189 + goto fail1;
11190 + }
11191 +
11192 + /* Initialise the resource DS. */
11193 + efrm_resource_init(&frs->rs, EFRM_RESOURCE_FILTER, instance);
11194 + frs->pt = vi_parent;
11195 + efrm_resource_ref(&frs->pt->rs);
11196 + frs->filter_idx = -1;
11197 +
11198 + EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " VI %d", __func__,
11199 + EFRM_RESOURCE_PRI_ARG(frs->rs.rs_handle),
11200 + EFRM_RESOURCE_INSTANCE(vi_parent->rs.rs_handle));
11201 +
11202 + efrm_client_add_resource(vi_parent->rs.rs_client, &frs->rs);
11203 + *frs_out = frs;
11204 + return 0;
11205 +
11206 +fail1:
11207 + memset(frs, 0, sizeof(*frs));
11208 + kfree(frs);
11209 + return rc;
11210 +}
11211 +EXPORT_SYMBOL(efrm_filter_resource_alloc);
11212 +
11213 +
11214 +int efrm_filter_resource_instance(struct filter_resource *frs)
11215 +{
11216 + return EFRM_RESOURCE_INSTANCE(frs->rs.rs_handle);
11217 +}
11218 +EXPORT_SYMBOL(efrm_filter_resource_instance);
11219 +
11220 +
11221 +struct efrm_resource *
11222 +efrm_filter_resource_to_resource(struct filter_resource *frs)
11223 +{
11224 + return &frs->rs;
11225 +}
11226 +EXPORT_SYMBOL(efrm_filter_resource_to_resource);
11227 +
11228 +
11229 +struct filter_resource *
11230 +efrm_filter_resource_from_resource(struct efrm_resource *rs)
11231 +{
11232 + return filter_resource(rs);
11233 +}
11234 +EXPORT_SYMBOL(efrm_filter_resource_from_resource);
11235 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/iobufset_resource.c
11236 ===================================================================
11237 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
11238 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/iobufset_resource.c 2008-07-17 16:18:07.000000000 +0200
11239 @@ -0,0 +1,404 @@
11240 +/****************************************************************************
11241 + * Driver for Solarflare network controllers -
11242 + * resource management for Xen backend, OpenOnload, etc
11243 + * (including support for SFE4001 10GBT NIC)
11244 + *
11245 + * This file contains non-contiguous I/O buffers support.
11246 + *
11247 + * Copyright 2005-2007: Solarflare Communications Inc,
11248 + * 9501 Jeronimo Road, Suite 250,
11249 + * Irvine, CA 92618, USA
11250 + *
11251 + * Developed and maintained by Solarflare Communications:
11252 + * <linux-xen-drivers@solarflare.com>
11253 + * <onload-dev@solarflare.com>
11254 + *
11255 + * Certain parts of the driver were implemented by
11256 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
11257 + * OKTET Labs Ltd, Russia,
11258 + * http://oktetlabs.ru, <info@oktetlabs.ru>
11259 + * by request of Solarflare Communications
11260 + *
11261 + *
11262 + * This program is free software; you can redistribute it and/or modify it
11263 + * under the terms of the GNU General Public License version 2 as published
11264 + * by the Free Software Foundation, incorporated herein by reference.
11265 + *
11266 + * This program is distributed in the hope that it will be useful,
11267 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11268 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11269 + * GNU General Public License for more details.
11270 + *
11271 + * You should have received a copy of the GNU General Public License
11272 + * along with this program; if not, write to the Free Software
11273 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11274 + ****************************************************************************
11275 + */
11276 +
11277 +#include <ci/efrm/nic_table.h>
11278 +#include <ci/efhw/iopage.h>
11279 +#include <ci/driver/efab/hardware.h>
11280 +#include <ci/efrm/private.h>
11281 +#include <ci/efrm/iobufset.h>
11282 +#include <ci/efrm/vi_resource_manager.h>
11283 +#include <ci/efrm/buffer_table.h>
11284 +#include <ci/efrm/efrm_client.h>
11285 +#include "efrm_internal.h"
11286 +
11287 +
11288 +#define EFRM_IOBUFSET_MAX_NUM_INSTANCES 0x00010000
11289 +
11290 +struct iobufset_resource_manager {
11291 + struct efrm_resource_manager rm;
11292 + struct kfifo *free_ids;
11293 +};
11294 +
11295 +struct iobufset_resource_manager *efrm_iobufset_manager;
11296 +
11297 +#define iobsrs(rs1) iobufset_resource(rs1)
11298 +
11299 +/* Returns size of iobufset resource data structure. */
11300 +static inline size_t iobsrs_size(int n_pages)
11301 +{
11302 + return offsetof(struct iobufset_resource, bufs) +
11303 + n_pages * sizeof(struct efhw_iopage);
11304 +}
11305 +
11306 +void efrm_iobufset_resource_free(struct iobufset_resource *rs)
11307 +{
11308 + unsigned int i;
11309 + int id;
11310 +
11311 + EFRM_RESOURCE_ASSERT_VALID(&rs->rs, 1);
11312 +
11313 + if (!rs->linked && rs->buf_tbl_alloc.base != (unsigned) -1)
11314 + efrm_buffer_table_free(&rs->buf_tbl_alloc);
11315 +
11316 + /* see comment on call to efhw_iopage_alloc in the alloc routine above
11317 + for discussion on use of efrm_nic_tablep->a_nic here */
11318 + EFRM_ASSERT(efrm_nic_tablep->a_nic);
11319 + if (rs->linked) {
11320 + /* Nothing to do. */
11321 + } else if (rs->chunk_order == 0) {
11322 + for (i = 0; i < rs->n_bufs; ++i)
11323 + efhw_iopage_free(efrm_nic_tablep->a_nic, &rs->bufs[i]);
11324 + } else {
11325 + /* it is important that this is executed in increasing page
11326 + * order because some implementations of
11327 + * efhw_iopages_init_from_iopage() assume this */
11328 + for (i = 0; i < rs->n_bufs;
11329 + i += rs->pages_per_contiguous_chunk) {
11330 + struct efhw_iopages iopages;
11331 + efhw_iopages_init_from_iopage(&iopages, &rs->bufs[i],
11332 + rs->chunk_order);
11333 + efhw_iopages_free(efrm_nic_tablep->a_nic, &iopages);
11334 + }
11335 + }
11336 +
11337 + /* free the instance number */
11338 + id = EFRM_RESOURCE_INSTANCE(rs->rs.rs_handle);
11339 + EFRM_VERIFY_EQ(kfifo_put(efrm_iobufset_manager->free_ids,
11340 + (unsigned char *)&id, sizeof(id)), sizeof(id));
11341 +
11342 + efrm_vi_resource_release(rs->evq);
11343 + if (rs->linked)
11344 + efrm_iobufset_resource_release(rs->linked);
11345 +
11346 + efrm_client_put(rs->rs.rs_client);
11347 + if (iobsrs_size(rs->n_bufs) < PAGE_SIZE) {
11348 + EFRM_DO_DEBUG(memset(rs, 0, sizeof(*rs)));
11349 + kfree(rs);
11350 + } else {
11351 + EFRM_DO_DEBUG(memset(rs, 0, sizeof(*rs)));
11352 + vfree(rs);
11353 + }
11354 +}
11355 +EXPORT_SYMBOL(efrm_iobufset_resource_free);
11356 +
11357 +
11358 +void efrm_iobufset_resource_release(struct iobufset_resource *iobrs)
11359 +{
11360 + if (__efrm_resource_release(&iobrs->rs))
11361 + efrm_iobufset_resource_free(iobrs);
11362 +}
11363 +EXPORT_SYMBOL(efrm_iobufset_resource_release);
11364 +
11365 +
11366 +
11367 +int
11368 +efrm_iobufset_resource_alloc(int32_t n_pages,
11369 + int32_t pages_per_contiguous_chunk,
11370 + struct vi_resource *vi_evq,
11371 + struct iobufset_resource *linked,
11372 + bool phys_addr_mode,
11373 + struct iobufset_resource **iobrs_out)
11374 +{
11375 + struct iobufset_resource *iobrs;
11376 + int rc, instance, object_size;
11377 + unsigned int i;
11378 +
11379 + EFRM_ASSERT(iobrs_out);
11380 + EFRM_ASSERT(efrm_iobufset_manager);
11381 + EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_iobufset_manager->rm);
11382 + EFRM_RESOURCE_ASSERT_VALID(&vi_evq->rs, 0);
11383 + EFRM_ASSERT(EFRM_RESOURCE_TYPE(vi_evq->rs.rs_handle) ==
11384 + EFRM_RESOURCE_VI);
11385 + EFRM_ASSERT(efrm_nic_tablep->a_nic);
11386 +
11387 + if (linked) {
11388 + /* This resource will share properties and memory with
11389 + * another. Only difference is that we'll program it into
11390 + * the buffer table of another nic.
11391 + */
11392 + n_pages = linked->n_bufs;
11393 + pages_per_contiguous_chunk = linked->pages_per_contiguous_chunk;
11394 + phys_addr_mode = linked->buf_tbl_alloc.base == (unsigned) -1;
11395 + }
11396 +
11397 + /* allocate the resource data structure. */
11398 + object_size = iobsrs_size(n_pages);
11399 + if (object_size < PAGE_SIZE) {
11400 + /* this should be OK from a tasklet */
11401 + /* Necessary to do atomic alloc() as this
11402 + can be called from a weird-ass iSCSI context that is
11403 + !in_interrupt but is in_atomic - See BUG3163 */
11404 + iobrs = kmalloc(object_size, GFP_ATOMIC);
11405 + } else { /* can't do this within a tasklet */
11406 +#ifndef NDEBUG
11407 + if (in_interrupt() || in_atomic()) {
11408 + EFRM_ERR("%s(): alloc->u.iobufset.in_n_pages=%d",
11409 + __func__, n_pages);
11410 + EFRM_ASSERT(!in_interrupt());
11411 + EFRM_ASSERT(!in_atomic());
11412 + }
11413 +#endif
11414 + iobrs = (struct iobufset_resource *) vmalloc(object_size);
11415 + }
11416 + if (iobrs == NULL) {
11417 + EFRM_WARN("%s: failed to allocate container", __func__);
11418 + rc = -ENOMEM;
11419 + goto fail1;
11420 + }
11421 +
11422 + /* Allocate an instance number. */
11423 + rc = kfifo_get(efrm_iobufset_manager->free_ids,
11424 + (unsigned char *)&instance, sizeof(instance));
11425 + if (rc != sizeof(instance)) {
11426 + EFRM_WARN("%s: out of instances", __func__);
11427 + EFRM_ASSERT(rc == 0);
11428 + rc = -EBUSY;
11429 + goto fail3;
11430 + }
11431 +
11432 + efrm_resource_init(&iobrs->rs, EFRM_RESOURCE_IOBUFSET, instance);
11433 +
11434 + iobrs->evq = vi_evq;
11435 + iobrs->linked = linked;
11436 + iobrs->n_bufs = n_pages;
11437 + iobrs->pages_per_contiguous_chunk = pages_per_contiguous_chunk;
11438 + iobrs->chunk_order = fls(iobrs->pages_per_contiguous_chunk - 1);
11439 + iobrs->buf_tbl_alloc.base = (unsigned) -1;
11440 +
11441 + EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " %u pages", __func__,
11442 + EFRM_RESOURCE_PRI_ARG(iobrs->rs.rs_handle), iobrs->n_bufs);
11443 +
11444 + /* Allocate the iobuffers. */
11445 + if (linked) {
11446 + memcpy(iobrs->bufs, linked->bufs,
11447 + iobrs->n_bufs * sizeof(iobrs->bufs[0]));
11448 + } else if (iobrs->chunk_order == 0) {
11449 + memset(iobrs->bufs, 0, iobrs->n_bufs * sizeof(iobrs->bufs[0]));
11450 + for (i = 0; i < iobrs->n_bufs; ++i) {
11451 + /* due to bug2426 we have to specifiy a NIC when
11452 + * allocating a DMAable page, which is a bit messy.
11453 + * For now we assume that if the page is suitable
11454 + * (e.g. DMAable) by one nic (efrm_nic_tablep->a_nic),
11455 + * it is suitable for all NICs.
11456 + * XXX I bet that breaks in Solaris.
11457 + */
11458 + rc = efhw_iopage_alloc(efrm_nic_tablep->a_nic,
11459 + &iobrs->bufs[i]);
11460 + if (rc < 0) {
11461 + EFRM_WARN("%s: failed (rc %d) to allocate "
11462 + "page (i=%u)", __func__, rc, i);
11463 + goto fail4;
11464 + }
11465 + }
11466 + } else {
11467 + struct efhw_iopages iopages;
11468 + unsigned j;
11469 +
11470 + memset(iobrs->bufs, 0, iobrs->n_bufs * sizeof(iobrs->bufs[0]));
11471 + for (i = 0; i < iobrs->n_bufs;
11472 + i += iobrs->pages_per_contiguous_chunk) {
11473 + rc = efhw_iopages_alloc(efrm_nic_tablep->a_nic,
11474 + &iopages, iobrs->chunk_order);
11475 + if (rc < 0) {
11476 + EFRM_WARN("%s: failed (rc %d) to allocate "
11477 + "pages (i=%u order %d)",
11478 + __func__, rc, i,
11479 + iobrs->chunk_order);
11480 + goto fail4;
11481 + }
11482 + for (j = 0; j < iobrs->pages_per_contiguous_chunk;
11483 + j++) {
11484 + /* some implementation of
11485 + * efhw_iopage_init_from_iopages() rely on
11486 + * this function being called for
11487 + * _all_ pages in the chunk */
11488 + efhw_iopage_init_from_iopages(
11489 + &iobrs->bufs[i + j],
11490 + &iopages, j);
11491 + }
11492 + }
11493 + }
11494 +
11495 + if (!phys_addr_mode) {
11496 + unsigned owner_id = EFAB_VI_RESOURCE_INSTANCE(iobrs->evq);
11497 +
11498 + if (!linked) {
11499 + /* Allocate space in the NIC's buffer table. */
11500 + rc = efrm_buffer_table_alloc(fls(iobrs->n_bufs - 1),
11501 + &iobrs->buf_tbl_alloc);
11502 + if (rc < 0) {
11503 + EFRM_WARN("%s: failed (%d) to alloc %d buffer "
11504 + "table entries", __func__, rc,
11505 + iobrs->n_bufs);
11506 + goto fail5;
11507 + }
11508 + EFRM_ASSERT(((unsigned)1 << iobrs->buf_tbl_alloc.order)
11509 + >= (unsigned) iobrs->n_bufs);
11510 + } else {
11511 + iobrs->buf_tbl_alloc = linked->buf_tbl_alloc;
11512 + }
11513 +
11514 + /* Initialise the buffer table entries. */
11515 + for (i = 0; i < iobrs->n_bufs; ++i) {
11516 + /*\ ?? \TODO burst them! */
11517 + efrm_buffer_table_set(&iobrs->buf_tbl_alloc,
11518 + vi_evq->rs.rs_client->nic,
11519 + i,
11520 + efhw_iopage_dma_addr(&iobrs->
11521 + bufs[i]),
11522 + owner_id);
11523 + }
11524 + efrm_buffer_table_commit();
11525 + }
11526 +
11527 + EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " %d pages @ "
11528 + EFHW_BUFFER_ADDR_FMT, __func__,
11529 + EFRM_RESOURCE_PRI_ARG(iobrs->rs.rs_handle),
11530 + iobrs->n_bufs, EFHW_BUFFER_ADDR(iobrs->buf_tbl_alloc.base,
11531 + 0));
11532 + efrm_resource_ref(&iobrs->evq->rs);
11533 + if (linked != NULL)
11534 + efrm_resource_ref(&linked->rs);
11535 + efrm_client_add_resource(vi_evq->rs.rs_client, &iobrs->rs);
11536 + *iobrs_out = iobrs;
11537 + return 0;
11538 +
11539 +fail5:
11540 + i = iobrs->n_bufs;
11541 +fail4:
11542 + /* see comment on call to efhw_iopage_alloc above for a discussion
11543 + * on use of efrm_nic_tablep->a_nic here */
11544 + if (linked) {
11545 + /* Nothing to do. */
11546 + } else if (iobrs->chunk_order == 0) {
11547 + while (i--) {
11548 + struct efhw_iopage *page = &iobrs->bufs[i];
11549 + efhw_iopage_free(efrm_nic_tablep->a_nic, page);
11550 + }
11551 + } else {
11552 + unsigned int j;
11553 + for (j = 0; j < i; j += iobrs->pages_per_contiguous_chunk) {
11554 + struct efhw_iopages iopages;
11555 +
11556 + EFRM_ASSERT(j % iobrs->pages_per_contiguous_chunk
11557 + == 0);
11558 + /* it is important that this is executed in increasing
11559 + * page order because some implementations of
11560 + * efhw_iopages_init_from_iopage() assume this */
11561 + efhw_iopages_init_from_iopage(&iopages,
11562 + &iobrs->bufs[j],
11563 + iobrs->chunk_order);
11564 + efhw_iopages_free(efrm_nic_tablep->a_nic, &iopages);
11565 + }
11566 + }
11567 +fail3:
11568 + if (object_size < PAGE_SIZE)
11569 + kfree(iobrs);
11570 + else
11571 + vfree(iobrs);
11572 +fail1:
11573 + return rc;
11574 +}
11575 +EXPORT_SYMBOL(efrm_iobufset_resource_alloc);
11576 +
11577 +static void iobufset_rm_dtor(struct efrm_resource_manager *rm)
11578 +{
11579 + EFRM_ASSERT(&efrm_iobufset_manager->rm == rm);
11580 + kfifo_vfree(efrm_iobufset_manager->free_ids);
11581 +}
11582 +
11583 +int
11584 +efrm_create_iobufset_resource_manager(struct efrm_resource_manager **rm_out)
11585 +{
11586 + int rc, max;
11587 +
11588 + EFRM_ASSERT(rm_out);
11589 +
11590 + efrm_iobufset_manager =
11591 + kmalloc(sizeof(*efrm_iobufset_manager), GFP_KERNEL);
11592 + if (efrm_iobufset_manager == 0)
11593 + return -ENOMEM;
11594 + memset(efrm_iobufset_manager, 0, sizeof(*efrm_iobufset_manager));
11595 +
11596 + /*
11597 + * Bug 1145, 1370: We need to set initial size of both the resource
11598 + * table and instance id table so they never need to grow as we
11599 + * want to be allocate new iobufset at tasklet time. Lets make
11600 + * a pessimistic guess at maximum number of iobufsets possible.
11601 + * Could be less because
11602 + * - jumbo frames have same no of packets per iobufset BUT more
11603 + * pages per buffer
11604 + * - buffer table entries used independently of iobufsets by
11605 + * sendfile
11606 + *
11607 + * Based on TCP/IP stack setting of PKTS_PER_SET_S=5 ...
11608 + * - can't use this define here as it breaks the layering.
11609 + */
11610 +#define MIN_PAGES_PER_IOBUFSET (1 << 4)
11611 +
11612 + max = efrm_buffer_table_size() / MIN_PAGES_PER_IOBUFSET;
11613 + max = min_t(int, max, EFRM_IOBUFSET_MAX_NUM_INSTANCES);
11614 +
11615 + /* HACK: There currently exists an option to allocate buffers that
11616 + * are not programmed into the buffer table, so the max number is
11617 + * not limited by the buffer table size. I'm hoping this usage
11618 + * will go away eventually.
11619 + */
11620 + max = 32768;
11621 +
11622 + rc = efrm_kfifo_id_ctor(&efrm_iobufset_manager->free_ids,
11623 + 0, max, &efrm_iobufset_manager->rm.rm_lock);
11624 + if (rc != 0)
11625 + goto fail1;
11626 +
11627 + rc = efrm_resource_manager_ctor(&efrm_iobufset_manager->rm,
11628 + iobufset_rm_dtor, "IOBUFSET",
11629 + EFRM_RESOURCE_IOBUFSET);
11630 + if (rc < 0)
11631 + goto fail2;
11632 +
11633 + *rm_out = &efrm_iobufset_manager->rm;
11634 + return 0;
11635 +
11636 +fail2:
11637 + kfifo_vfree(efrm_iobufset_manager->free_ids);
11638 +fail1:
11639 + EFRM_DO_DEBUG(memset(efrm_iobufset_manager, 0,
11640 + sizeof(*efrm_iobufset_manager)));
11641 + kfree(efrm_iobufset_manager);
11642 + return rc;
11643 +}
11644 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/iopage.c
11645 ===================================================================
11646 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
11647 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/iopage.c 2008-07-17 16:18:07.000000000 +0200
11648 @@ -0,0 +1,103 @@
11649 +/****************************************************************************
11650 + * Driver for Solarflare network controllers -
11651 + * resource management for Xen backend, OpenOnload, etc
11652 + * (including support for SFE4001 10GBT NIC)
11653 + *
11654 + * This file provides Linux-specific implementation for iopage API used
11655 + * from efhw library.
11656 + *
11657 + * Copyright 2005-2007: Solarflare Communications Inc,
11658 + * 9501 Jeronimo Road, Suite 250,
11659 + * Irvine, CA 92618, USA
11660 + *
11661 + * Developed and maintained by Solarflare Communications:
11662 + * <linux-xen-drivers@solarflare.com>
11663 + * <onload-dev@solarflare.com>
11664 + *
11665 + *
11666 + * This program is free software; you can redistribute it and/or modify it
11667 + * under the terms of the GNU General Public License version 2 as published
11668 + * by the Free Software Foundation, incorporated herein by reference.
11669 + *
11670 + * This program is distributed in the hope that it will be useful,
11671 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11672 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11673 + * GNU General Public License for more details.
11674 + *
11675 + * You should have received a copy of the GNU General Public License
11676 + * along with this program; if not, write to the Free Software
11677 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11678 + ****************************************************************************
11679 + */
11680 +
11681 +#include <ci/driver/resource/linux_efhw_nic.h>
11682 +#include "kernel_compat.h"
11683 +#include <ci/efhw/common_sysdep.h> /* for dma_addr_t */
11684 +
11685 +int efhw_iopage_alloc(struct efhw_nic *nic, struct efhw_iopage *p)
11686 +{
11687 + struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
11688 + dma_addr_t handle;
11689 + void *kva;
11690 +
11691 + kva = efrm_pci_alloc_consistent(lnic->pci_dev, PAGE_SIZE,
11692 + &handle);
11693 + if (kva == 0)
11694 + return -ENOMEM;
11695 +
11696 + EFHW_ASSERT((handle & ~PAGE_MASK) == 0);
11697 +
11698 + memset((void *)kva, 0, PAGE_SIZE);
11699 + efhw_page_init_from_va(&p->p, kva);
11700 +
11701 + p->dma_addr = handle;
11702 +
11703 + return 0;
11704 +}
11705 +
11706 +void efhw_iopage_free(struct efhw_nic *nic, struct efhw_iopage *p)
11707 +{
11708 + struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
11709 + EFHW_ASSERT(efhw_page_is_valid(&p->p));
11710 +
11711 + efrm_pci_free_consistent(lnic->pci_dev, PAGE_SIZE,
11712 + efhw_iopage_ptr(p), p->dma_addr);
11713 +}
11714 +
11715 +int
11716 +efhw_iopages_alloc(struct efhw_nic *nic, struct efhw_iopages *p,
11717 + unsigned order)
11718 +{
11719 + unsigned bytes = 1u << (order + PAGE_SHIFT);
11720 + struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
11721 + dma_addr_t handle;
11722 + caddr_t addr;
11723 + int gfp_flag;
11724 +
11725 + /* Set __GFP_COMP if available to make reference counting work.
11726 + * This is recommended here:
11727 + * http://www.forbiddenweb.org/viewtopic.php?id=83167&page=4#348331
11728 + */
11729 + gfp_flag = ((in_atomic() ? GFP_ATOMIC : GFP_KERNEL) | __GFP_COMP);
11730 + addr = efrm_dma_alloc_coherent(&lnic->pci_dev->dev, bytes, &handle,
11731 + gfp_flag);
11732 + if (addr == NULL)
11733 + return -ENOMEM;
11734 +
11735 + EFHW_ASSERT((handle & ~PAGE_MASK) == 0);
11736 +
11737 + p->order = order;
11738 + p->dma_addr = handle;
11739 + p->kva = addr;
11740 +
11741 + return 0;
11742 +}
11743 +
11744 +void efhw_iopages_free(struct efhw_nic *nic, struct efhw_iopages *p)
11745 +{
11746 + unsigned bytes = 1u << (p->order + PAGE_SHIFT);
11747 + struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
11748 +
11749 + efrm_dma_free_coherent(&lnic->pci_dev->dev, bytes,
11750 + (void *)p->kva, p->dma_addr);
11751 +}
11752 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/kernel_compat.c
11753 ===================================================================
11754 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
11755 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/kernel_compat.c 2008-07-17 16:18:07.000000000 +0200
11756 @@ -0,0 +1,118 @@
11757 +/****************************************************************************
11758 + * Driver for Solarflare network controllers -
11759 + * resource management for Xen backend, OpenOnload, etc
11760 + * (including support for SFE4001 10GBT NIC)
11761 + *
11762 + * This file provides compatibility layer for various Linux kernel versions
11763 + * (starting from 2.6.9 RHEL kernel).
11764 + *
11765 + * Copyright 2005-2007: Solarflare Communications Inc,
11766 + * 9501 Jeronimo Road, Suite 250,
11767 + * Irvine, CA 92618, USA
11768 + *
11769 + * Developed and maintained by Solarflare Communications:
11770 + * <linux-xen-drivers@solarflare.com>
11771 + * <onload-dev@solarflare.com>
11772 + *
11773 + * Certain parts of the driver were implemented by
11774 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
11775 + * OKTET Labs Ltd, Russia,
11776 + * http://oktetlabs.ru, <info@oktetlabs.ru>
11777 + * by request of Solarflare Communications
11778 + *
11779 + *
11780 + * This program is free software; you can redistribute it and/or modify it
11781 + * under the terms of the GNU General Public License version 2 as published
11782 + * by the Free Software Foundation, incorporated herein by reference.
11783 + *
11784 + * This program is distributed in the hope that it will be useful,
11785 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11786 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11787 + * GNU General Public License for more details.
11788 + *
11789 + * You should have received a copy of the GNU General Public License
11790 + * along with this program; if not, write to the Free Software
11791 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11792 + ****************************************************************************
11793 + */
11794 +
11795 +#define IN_KERNEL_COMPAT_C
11796 +#include <linux/types.h>
11797 +#include <ci/efrm/debug.h>
11798 +#include "kernel_compat.h"
11799 +
11800 +/* Set this to 1 to enable very basic counting of iopage(s) allocations, then
11801 + * call dump_iopage_counts() to show the number of current allocations of
11802 + * orders 0-7.
11803 + */
11804 +#define EFRM_IOPAGE_COUNTS_ENABLED 0
11805 +
11806 +
11807 +/****************************************************************************
11808 + *
11809 + * allocate a buffer suitable for DMA to/from the NIC
11810 + *
11811 + ****************************************************************************/
11812 +
11813 +#if EFRM_IOPAGE_COUNTS_ENABLED
11814 +
11815 +static int iopage_counts[8];
11816 +
11817 +void dump_iopage_counts(void)
11818 +{
11819 + EFRM_NOTICE("iopage counts: %d %d %d %d %d %d %d %d", iopage_counts[0],
11820 + iopage_counts[1], iopage_counts[2], iopage_counts[3],
11821 + iopage_counts[4], iopage_counts[5], iopage_counts[6],
11822 + iopage_counts[7]);
11823 +}
11824 +
11825 +#endif
11826 +
11827 +
11828 +
11829 +/*********** pci_alloc_consistent / pci_free_consistent ***********/
11830 +
11831 +void *efrm_dma_alloc_coherent(struct device *dev, size_t size,
11832 + dma_addr_t *dma_addr, int flag)
11833 +{
11834 + void *ptr;
11835 + unsigned order;
11836 +
11837 + order = __ffs(size/PAGE_SIZE);
11838 + EFRM_ASSERT(size == (PAGE_SIZE<<order));
11839 +
11840 + /* Can't take a spinlock here since the allocation can
11841 + * block. */
11842 + ptr = dma_alloc_coherent(dev, size, dma_addr, flag);
11843 + if (ptr == NULL)
11844 + return ptr;
11845 +
11846 +#if EFRM_IOPAGE_COUNTS_ENABLED
11847 + if (order < 8)
11848 + iopage_counts[order]++;
11849 + else
11850 + EFRM_ERR("Huge iopages alloc (order=%d) ??? (not counted)",
11851 + order);
11852 +#endif
11853 +
11854 + return ptr;
11855 +}
11856 +
11857 +void efrm_dma_free_coherent(struct device *dev, size_t size,
11858 + void *ptr, dma_addr_t dma_addr)
11859 +{
11860 + unsigned order;
11861 +
11862 + order = __ffs(size/PAGE_SIZE);
11863 + EFRM_ASSERT(size == (PAGE_SIZE<<order));
11864 +
11865 +#if EFRM_IOPAGE_COUNTS_ENABLED
11866 + if (order < 8)
11867 + --iopage_counts[order];
11868 + else
11869 + EFRM_ERR("Huge iopages free (order=%d) ??? (not counted)",
11870 + order);
11871 +#endif
11872 +
11873 + dma_free_coherent(dev, size, ptr, dma_addr);
11874 +}
11875 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/kernel_compat.h
11876 ===================================================================
11877 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
11878 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/kernel_compat.h 2008-07-17 16:18:07.000000000 +0200
11879 @@ -0,0 +1,70 @@
11880 +/****************************************************************************
11881 + * Driver for Solarflare network controllers -
11882 + * resource management for Xen backend, OpenOnload, etc
11883 + * (including support for SFE4001 10GBT NIC)
11884 + *
11885 + * This file provides compatibility layer for various Linux kernel versions
11886 + * (starting from 2.6.9 RHEL kernel).
11887 + *
11888 + * Copyright 2005-2007: Solarflare Communications Inc,
11889 + * 9501 Jeronimo Road, Suite 250,
11890 + * Irvine, CA 92618, USA
11891 + *
11892 + * Developed and maintained by Solarflare Communications:
11893 + * <linux-xen-drivers@solarflare.com>
11894 + * <onload-dev@solarflare.com>
11895 + *
11896 + * Certain parts of the driver were implemented by
11897 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
11898 + * OKTET Labs Ltd, Russia,
11899 + * http://oktetlabs.ru, <info@oktetlabs.ru>
11900 + * by request of Solarflare Communications
11901 + *
11902 + *
11903 + * This program is free software; you can redistribute it and/or modify it
11904 + * under the terms of the GNU General Public License version 2 as published
11905 + * by the Free Software Foundation, incorporated herein by reference.
11906 + *
11907 + * This program is distributed in the hope that it will be useful,
11908 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11909 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11910 + * GNU General Public License for more details.
11911 + *
11912 + * You should have received a copy of the GNU General Public License
11913 + * along with this program; if not, write to the Free Software
11914 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11915 + ****************************************************************************
11916 + */
11917 +
11918 +#ifndef DRIVER_LINUX_RESOURCE_KERNEL_COMPAT_H
11919 +#define DRIVER_LINUX_RESOURCE_KERNEL_COMPAT_H
11920 +
11921 +#include <linux/moduleparam.h>
11922 +#include <linux/sched.h>
11923 +#include <linux/io.h>
11924 +#include <linux/pci.h>
11925 +
11926 +/********* pci_map_*() ********************/
11927 +
11928 +extern void *efrm_dma_alloc_coherent(struct device *dev, size_t size,
11929 + dma_addr_t *dma_addr, int flag);
11930 +
11931 +extern void efrm_dma_free_coherent(struct device *dev, size_t size,
11932 + void *ptr, dma_addr_t dma_addr);
11933 +
11934 +static inline void *efrm_pci_alloc_consistent(struct pci_dev *hwdev,
11935 + size_t size,
11936 + dma_addr_t *dma_addr)
11937 +{
11938 + return efrm_dma_alloc_coherent(&hwdev->dev, size, dma_addr,
11939 + GFP_ATOMIC);
11940 +}
11941 +
11942 +static inline void efrm_pci_free_consistent(struct pci_dev *hwdev, size_t size,
11943 + void *ptr, dma_addr_t dma_addr)
11944 +{
11945 + efrm_dma_free_coherent(&hwdev->dev, size, ptr, dma_addr);
11946 +}
11947 +
11948 +
11949 +#endif /* DRIVER_LINUX_RESOURCE_KERNEL_COMPAT_H */
11950 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/kernel_proc.c
11951 ===================================================================
11952 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
11953 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/kernel_proc.c 2008-07-17 16:18:07.000000000 +0200
11954 @@ -0,0 +1,109 @@
11955 +/****************************************************************************
11956 + * Driver for Solarflare network controllers -
11957 + * resource management for Xen backend, OpenOnload, etc
11958 + * (including support for SFE4001 10GBT NIC)
11959 + *
11960 + * This file contains /proc/driver/sfc_resource/ implementation.
11961 + *
11962 + * Copyright 2005-2007: Solarflare Communications Inc,
11963 + * 9501 Jeronimo Road, Suite 250,
11964 + * Irvine, CA 92618, USA
11965 + *
11966 + * Developed and maintained by Solarflare Communications:
11967 + * <linux-xen-drivers@solarflare.com>
11968 + * <onload-dev@solarflare.com>
11969 + *
11970 + * Certain parts of the driver were implemented by
11971 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
11972 + * OKTET Labs Ltd, Russia,
11973 + * http://oktetlabs.ru, <info@oktetlabs.ru>
11974 + * by request of Solarflare Communications
11975 + *
11976 + *
11977 + * This program is free software; you can redistribute it and/or modify it
11978 + * under the terms of the GNU General Public License version 2 as published
11979 + * by the Free Software Foundation, incorporated herein by reference.
11980 + *
11981 + * This program is distributed in the hope that it will be useful,
11982 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11983 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11984 + * GNU General Public License for more details.
11985 + *
11986 + * You should have received a copy of the GNU General Public License
11987 + * along with this program; if not, write to the Free Software
11988 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11989 + ****************************************************************************
11990 + */
11991 +
11992 +#include <ci/efrm/debug.h>
11993 +#include <ci/efrm/driver_private.h>
11994 +#include <linux/proc_fs.h>
11995 +
11996 +/** Top level directory for sfc specific stats **/
11997 +static struct proc_dir_entry *efrm_proc_root; /* = NULL */
11998 +
11999 +static int
12000 +efrm_resource_read_proc(char *buf, char **start, off_t offset, int count,
12001 + int *eof, void *data);
12002 +
12003 +int efrm_install_proc_entries(void)
12004 +{
12005 + /* create the top-level directory for etherfabric specific stuff */
12006 + efrm_proc_root = proc_mkdir("driver/sfc_resource", NULL);
12007 + if (!efrm_proc_root)
12008 + return -ENOMEM;
12009 +
12010 + if (create_proc_read_entry("resources", 0, efrm_proc_root,
12011 + efrm_resource_read_proc, 0) == NULL) {
12012 + EFRM_WARN("%s: Unable to create /proc/drivers/sfc_resource/"
12013 + "resources", __func__);
12014 + }
12015 + return 0;
12016 +}
12017 +
12018 +void efrm_uninstall_proc_entries(void)
12019 +{
12020 + EFRM_ASSERT(efrm_proc_root);
12021 + remove_proc_entry("resources", efrm_proc_root);
12022 + remove_proc_entry(efrm_proc_root->name, efrm_proc_root->parent);
12023 + efrm_proc_root = NULL;
12024 +}
12025 +
12026 +/****************************************************************************
12027 + *
12028 + * /proc/drivers/sfc/resources
12029 + *
12030 + ****************************************************************************/
12031 +
12032 +#define EFRM_PROC_PRINTF(buf, len, fmt, ...) \
12033 + do { \
12034 + if (count - len > 0) \
12035 + len += snprintf(buf+len, count-len, (fmt), \
12036 + __VA_ARGS__); \
12037 + } while (0)
12038 +
12039 +static int
12040 +efrm_resource_read_proc(char *buf, char **start, off_t offset, int count,
12041 + int *eof, void *data)
12042 +{
12043 + irq_flags_t lock_flags;
12044 + int len = 0;
12045 + int type;
12046 + struct efrm_resource_manager *rm;
12047 +
12048 + for (type = 0; type < EFRM_RESOURCE_NUM; type++) {
12049 + rm = efrm_rm_table[type];
12050 + if (rm == NULL)
12051 + continue;
12052 +
12053 + EFRM_PROC_PRINTF(buf, len, "*** %s ***\n", rm->rm_name);
12054 +
12055 + spin_lock_irqsave(&rm->rm_lock, lock_flags);
12056 + EFRM_PROC_PRINTF(buf, len, "current = %u\n", rm->rm_resources);
12057 + EFRM_PROC_PRINTF(buf, len, " max = %u\n\n",
12058 + rm->rm_resources_hiwat);
12059 + spin_unlock_irqrestore(&rm->rm_lock, lock_flags);
12060 + }
12061 +
12062 + return count ? strlen(buf) : 0;
12063 +}
12064 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/kfifo.c
12065 ===================================================================
12066 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
12067 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/kfifo.c 2008-07-17 16:18:07.000000000 +0200
12068 @@ -0,0 +1,208 @@
12069 +/*
12070 + * A simple kernel FIFO implementation.
12071 + *
12072 + * Copyright (C) 2004 Stelian Pop <stelian@popies.net>
12073 + *
12074 + * This program is free software; you can redistribute it and/or modify
12075 + * it under the terms of the GNU General Public License as published by
12076 + * the Free Software Foundation; either version 2 of the License, or
12077 + * (at your option) any later version.
12078 + *
12079 + * This program is distributed in the hope that it will be useful,
12080 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12081 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12082 + * GNU General Public License for more details.
12083 + *
12084 + * You should have received a copy of the GNU General Public License
12085 + * along with this program; if not, write to the Free Software
12086 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
12087 + *
12088 + */
12089 +
12090 +/*
12091 + * This file is stolen from the Linux kernel sources
12092 + * (linux-2.6.22/kernel/kfifo.c) into sfc_resource driver.
12093 + * It should be used for old kernels without kfifo implementation.
12094 + * Most part of linux/kfifo.h is incorporated into
12095 + * ci/efrm/sysdep_linux.h.
12096 + */
12097 +#include <ci/efrm/sysdep_linux.h>
12098 +#ifdef HAS_NO_KFIFO
12099 +
12100 +#include <linux/kernel.h>
12101 +#include <linux/module.h>
12102 +#include <linux/slab.h>
12103 +#include <linux/err.h>
12104 +/*#include <linux/kfifo.h>*/
12105 +
12106 +/**
12107 + * kfifo_init - allocates a new FIFO using a preallocated buffer
12108 + * @buffer: the preallocated buffer to be used.
12109 + * @size: the size of the internal buffer, this have to be a power of 2.
12110 + * @gfp_mask: get_free_pages mask, passed to kmalloc()
12111 + * @lock: the lock to be used to protect the fifo buffer
12112 + *
12113 + * Do NOT pass the kfifo to kfifo_free() after use! Simply free the
12114 + * &struct kfifo with kfree().
12115 + */
12116 +struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
12117 + gfp_t gfp_mask, spinlock_t *lock)
12118 +{
12119 + struct kfifo *fifo;
12120 +
12121 + /* size must be a power of 2 */
12122 + BUG_ON(size & (size - 1));
12123 +
12124 + fifo = kmalloc(sizeof(struct kfifo), gfp_mask);
12125 + if (!fifo)
12126 + return ERR_PTR(-ENOMEM);
12127 +
12128 + fifo->buffer = buffer;
12129 + fifo->size = size;
12130 + fifo->in = fifo->out = 0;
12131 + fifo->lock = lock;
12132 +
12133 + return fifo;
12134 +}
12135 +EXPORT_SYMBOL(kfifo_init);
12136 +
12137 +/**
12138 + * kfifo_alloc - allocates a new FIFO and its internal buffer
12139 + * @size: the size of the internal buffer to be allocated.
12140 + * @gfp_mask: get_free_pages mask, passed to kmalloc()
12141 + * @lock: the lock to be used to protect the fifo buffer
12142 + *
12143 + * The size will be rounded-up to a power of 2.
12144 + */
12145 +struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock)
12146 +{
12147 + unsigned char *buffer;
12148 + struct kfifo *ret;
12149 +
12150 + /*
12151 + * round up to the next power of 2, since our 'let the indices
12152 + * wrap' tachnique works only in this case.
12153 + */
12154 + if (size & (size - 1)) {
12155 + BUG_ON(size > 0x80000000);
12156 + size = roundup_pow_of_two(size);
12157 + }
12158 +
12159 + buffer = kmalloc(size, gfp_mask);
12160 + if (!buffer)
12161 + return ERR_PTR(-ENOMEM);
12162 +
12163 + ret = kfifo_init(buffer, size, gfp_mask, lock);
12164 +
12165 + if (IS_ERR(ret))
12166 + kfree(buffer);
12167 +
12168 + return ret;
12169 +}
12170 +EXPORT_SYMBOL(kfifo_alloc);
12171 +
12172 +/**
12173 + * kfifo_free - frees the FIFO
12174 + * @fifo: the fifo to be freed.
12175 + */
12176 +void kfifo_free(struct kfifo *fifo)
12177 +{
12178 + kfree(fifo->buffer);
12179 + kfree(fifo);
12180 +}
12181 +EXPORT_SYMBOL(kfifo_free);
12182 +
12183 +/**
12184 + * __kfifo_put - puts some data into the FIFO, no locking version
12185 + * @fifo: the fifo to be used.
12186 + * @buffer: the data to be added.
12187 + * @len: the length of the data to be added.
12188 + *
12189 + * This function copies at most @len bytes from the @buffer into
12190 + * the FIFO depending on the free space, and returns the number of
12191 + * bytes copied.
12192 + *
12193 + * Note that with only one concurrent reader and one concurrent
12194 + * writer, you don't need extra locking to use these functions.
12195 + */
12196 +unsigned int
12197 +__kfifo_put(struct kfifo *fifo, unsigned char *buffer, unsigned int len)
12198 +{
12199 + unsigned int l;
12200 +
12201 + len = min(len, fifo->size - fifo->in + fifo->out);
12202 +
12203 + /*
12204 + * Ensure that we sample the fifo->out index -before- we
12205 + * start putting bytes into the kfifo.
12206 + */
12207 +
12208 + smp_mb();
12209 +
12210 + /* first put the data starting from fifo->in to buffer end */
12211 + l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
12212 + memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
12213 +
12214 + /* then put the rest (if any) at the beginning of the buffer */
12215 + memcpy(fifo->buffer, buffer + l, len - l);
12216 +
12217 + /*
12218 + * Ensure that we add the bytes to the kfifo -before-
12219 + * we update the fifo->in index.
12220 + */
12221 +
12222 + smp_wmb();
12223 +
12224 + fifo->in += len;
12225 +
12226 + return len;
12227 +}
12228 +EXPORT_SYMBOL(__kfifo_put);
12229 +
12230 +/**
12231 + * __kfifo_get - gets some data from the FIFO, no locking version
12232 + * @fifo: the fifo to be used.
12233 + * @buffer: where the data must be copied.
12234 + * @len: the size of the destination buffer.
12235 + *
12236 + * This function copies at most @len bytes from the FIFO into the
12237 + * @buffer and returns the number of copied bytes.
12238 + *
12239 + * Note that with only one concurrent reader and one concurrent
12240 + * writer, you don't need extra locking to use these functions.
12241 + */
12242 +unsigned int
12243 +__kfifo_get(struct kfifo *fifo, unsigned char *buffer, unsigned int len)
12244 +{
12245 + unsigned int l;
12246 +
12247 + len = min(len, fifo->in - fifo->out);
12248 +
12249 + /*
12250 + * Ensure that we sample the fifo->in index -before- we
12251 + * start removing bytes from the kfifo.
12252 + */
12253 +
12254 + smp_rmb();
12255 +
12256 + /* first get the data from fifo->out until the end of the buffer */
12257 + l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
12258 + memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);
12259 +
12260 + /* then get the rest (if any) from the beginning of the buffer */
12261 + memcpy(buffer + l, fifo->buffer, len - l);
12262 +
12263 + /*
12264 + * Ensure that we remove the bytes from the kfifo -before-
12265 + * we update the fifo->out index.
12266 + */
12267 +
12268 + smp_mb();
12269 +
12270 + fifo->out += len;
12271 +
12272 + return len;
12273 +}
12274 +EXPORT_SYMBOL(__kfifo_get);
12275 +
12276 +#endif
12277 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/linux_resource_internal.h
12278 ===================================================================
12279 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
12280 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/linux_resource_internal.h 2008-07-17 16:18:07.000000000 +0200
12281 @@ -0,0 +1,76 @@
12282 +/****************************************************************************
12283 + * Driver for Solarflare network controllers -
12284 + * resource management for Xen backend, OpenOnload, etc
12285 + * (including support for SFE4001 10GBT NIC)
12286 + *
12287 + * This file contains Linux-specific API internal for the resource driver.
12288 + *
12289 + * Copyright 2005-2007: Solarflare Communications Inc,
12290 + * 9501 Jeronimo Road, Suite 250,
12291 + * Irvine, CA 92618, USA
12292 + *
12293 + * Developed and maintained by Solarflare Communications:
12294 + * <linux-xen-drivers@solarflare.com>
12295 + * <onload-dev@solarflare.com>
12296 + *
12297 + * Certain parts of the driver were implemented by
12298 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
12299 + * OKTET Labs Ltd, Russia,
12300 + * http://oktetlabs.ru, <info@oktetlabs.ru>
12301 + * by request of Solarflare Communications
12302 + *
12303 + *
12304 + * This program is free software; you can redistribute it and/or modify it
12305 + * under the terms of the GNU General Public License version 2 as published
12306 + * by the Free Software Foundation, incorporated herein by reference.
12307 + *
12308 + * This program is distributed in the hope that it will be useful,
12309 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12310 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12311 + * GNU General Public License for more details.
12312 + *
12313 + * You should have received a copy of the GNU General Public License
12314 + * along with this program; if not, write to the Free Software
12315 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12316 + ****************************************************************************
12317 + */
12318 +
12319 +#ifndef __LINUX_RESOURCE_INTERNAL__
12320 +#define __LINUX_RESOURCE_INTERNAL__
12321 +
12322 +#include <ci/driver/resource/linux_efhw_nic.h>
12323 +#include <ci/efrm/debug.h>
12324 +#include <ci/efrm/driver_private.h>
12325 +#include <ci/driver/efab/hardware.h>
12326 +
12327 +
12328 +/*! Linux specific EtherFabric initialisation */
12329 +extern int
12330 +linux_efrm_nic_ctor(struct linux_efhw_nic *, struct pci_dev *,
12331 + spinlock_t *reg_lock,
12332 + unsigned nic_flags, unsigned nic_options);
12333 +
12334 +/*! Linux specific EtherFabric initialisation */
12335 +extern void linux_efrm_nic_dtor(struct linux_efhw_nic *);
12336 +
12337 +/*! Linux specific EtherFabric initialisation -- interrupt registration */
12338 +extern int linux_efrm_irq_ctor(struct linux_efhw_nic *);
12339 +
12340 +/*! Linux specific EtherFabric initialisation -- interrupt deregistration */
12341 +extern void linux_efrm_irq_dtor(struct linux_efhw_nic *);
12342 +
12343 +extern int efrm_driverlink_register(void);
12344 +extern void efrm_driverlink_unregister(void);
12345 +
12346 +extern int
12347 +efrm_nic_add(struct pci_dev *dev, unsigned int opts, const uint8_t *mac_addr,
12348 + struct linux_efhw_nic **lnic_out, spinlock_t *reg_lock,
12349 + int bt_min, int bt_max, int non_irq_evq,
12350 + const struct vi_resource_dimensions *);
12351 +extern void efrm_nic_del(struct linux_efhw_nic *);
12352 +
12353 +
12354 +extern int efrm_install_proc_entries(void);
12355 +extern void efrm_uninstall_proc_entries(void);
12356 +
12357 +#endif /* __LINUX_RESOURCE_INTERNAL__ */
12358 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/nic.c
12359 ===================================================================
12360 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
12361 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/nic.c 2008-07-17 16:18:07.000000000 +0200
12362 @@ -0,0 +1,174 @@
12363 +/****************************************************************************
12364 + * Driver for Solarflare network controllers -
12365 + * resource management for Xen backend, OpenOnload, etc
12366 + * (including support for SFE4001 10GBT NIC)
12367 + *
12368 + * This file contains EtherFabric Generic NIC instance (init, interrupts,
12369 + * etc)
12370 + *
12371 + * Copyright 2005-2007: Solarflare Communications Inc,
12372 + * 9501 Jeronimo Road, Suite 250,
12373 + * Irvine, CA 92618, USA
12374 + *
12375 + * Developed and maintained by Solarflare Communications:
12376 + * <linux-xen-drivers@solarflare.com>
12377 + * <onload-dev@solarflare.com>
12378 + *
12379 + *
12380 + * This program is free software; you can redistribute it and/or modify it
12381 + * under the terms of the GNU General Public License version 2 as published
12382 + * by the Free Software Foundation, incorporated herein by reference.
12383 + *
12384 + * This program is distributed in the hope that it will be useful,
12385 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12386 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12387 + * GNU General Public License for more details.
12388 + *
12389 + * You should have received a copy of the GNU General Public License
12390 + * along with this program; if not, write to the Free Software
12391 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12392 + ****************************************************************************
12393 + */
12394 +
12395 +#include <ci/efhw/debug.h>
12396 +#include <ci/driver/efab/hardware.h>
12397 +#include <ci/efhw/falcon.h>
12398 +#include <ci/efhw/nic.h>
12399 +#include <ci/efhw/eventq.h>
12400 +
12401 +
12402 +int efhw_device_type_init(struct efhw_device_type *dt,
12403 + int vendor_id, int device_id,
12404 + int class_revision)
12405 +{
12406 + if (vendor_id != 0x1924)
12407 + return 0;
12408 +
12409 + switch (device_id) {
12410 + case 0x0703:
12411 + case 0x6703:
12412 + dt->variant = 'A';
12413 + switch (class_revision) {
12414 + case 0:
12415 + dt->revision = 0;
12416 + break;
12417 + case 1:
12418 + dt->revision = 1;
12419 + break;
12420 + default:
12421 + return 0;
12422 + }
12423 + break;
12424 + case 0x0710:
12425 + dt->variant = 'B';
12426 + switch (class_revision) {
12427 + case 2:
12428 + dt->revision = 0;
12429 + break;
12430 + default:
12431 + return 0;
12432 + }
12433 + break;
12434 + default:
12435 + return 0;
12436 + }
12437 +
12438 + return 1;
12439 +}
12440 +
12441 +
12442 +/*--------------------------------------------------------------------
12443 + *
12444 + * NIC Initialisation
12445 + *
12446 + *--------------------------------------------------------------------*/
12447 +
12448 +/* make this separate from initialising data structure
12449 +** to allow this to be called at a later time once we can access PCI
12450 +** config space to find out what hardware we have
12451 +*/
12452 +void efhw_nic_init(struct efhw_nic *nic, unsigned flags, unsigned options,
12453 + struct efhw_device_type dev_type)
12454 +{
12455 + nic->devtype = dev_type;
12456 + nic->flags = flags;
12457 + nic->options = options;
12458 + nic->bar_ioaddr = 0;
12459 + spin_lock_init(&nic->the_reg_lock);
12460 + nic->reg_lock = &nic->the_reg_lock;
12461 + nic->mtu = 1500 + ETH_HLEN;
12462 +
12463 + nic->irq_unit = EFHW_IRQ_UNIT_UNUSED;
12464 +
12465 + nic->evq_sizes = 512 | 1024 | 2048 | 4096 | 8192 |
12466 + 16384 | 32768;
12467 + nic->txq_sizes = 512 | 1024 | 2048 | 4096;
12468 + nic->rxq_sizes = 512 | 1024 | 2048 | 4096;
12469 + nic->efhw_func = &falcon_char_functional_units;
12470 + nic->ctr_ap_bytes = EFHW_64M;
12471 + switch (nic->devtype.variant) {
12472 + case 'A':
12473 + nic->ctr_ap_bar = FALCON_S_CTR_AP_BAR;
12474 + nic->num_evqs = 4096;
12475 + nic->num_dmaqs = 4096;
12476 + nic->num_timers = 4096;
12477 + break;
12478 + case 'B':
12479 + nic->flags |= NIC_FLAG_NO_INTERRUPT;
12480 + nic->ctr_ap_bar = FALCON_P_CTR_AP_BAR;
12481 + nic->num_evqs = 4096;
12482 + nic->num_dmaqs = 4096;
12483 + nic->num_timers = 4096;
12484 + break;
12485 + default:
12486 + EFHW_ASSERT(0);
12487 + break;
12488 + }
12489 +}
12490 +
12491 +
12492 +void efhw_nic_close_interrupts(struct efhw_nic *nic)
12493 +{
12494 + EFHW_ASSERT(nic);
12495 + if (!efhw_nic_have_hw(nic))
12496 + return;
12497 +
12498 + EFHW_ASSERT(efhw_nic_have_hw(nic));
12499 +
12500 + if (nic->irq_unit != EFHW_IRQ_UNIT_UNUSED)
12501 + efhw_nic_interrupt_disable(nic);
12502 +}
12503 +
12504 +void efhw_nic_dtor(struct efhw_nic *nic)
12505 +{
12506 + EFHW_ASSERT(nic);
12507 +
12508 + /* Check that we have functional units because the software only
12509 + * driver doesn't initialise anything hardware related any more */
12510 +
12511 + /* close interrupts is called first because the act of deregistering
12512 + the driver could cause this driver to change from master to slave
12513 + and hence the implicit interrupt mappings would be wrong */
12514 +
12515 + EFHW_TRACE("%s: functional units ... ", __func__);
12516 +
12517 + if (efhw_nic_have_functional_units(nic)) {
12518 + efhw_nic_close_interrupts(nic);
12519 + efhw_nic_close_hardware(nic);
12520 + }
12521 + EFHW_TRACE("%s: functional units ... done", __func__);
12522 +
12523 + /* destroy event queues */
12524 + EFHW_TRACE("%s: event queues ... ", __func__);
12525 +
12526 + if (nic->interrupting_evq.evq_mask)
12527 + efhw_keventq_dtor(nic, &nic->interrupting_evq);
12528 + if (nic->non_interrupting_evq.evq_mask)
12529 + efhw_keventq_dtor(nic, &nic->non_interrupting_evq);
12530 +
12531 + EFHW_TRACE("%s: event queues ... done", __func__);
12532 +
12533 + spin_lock_destroy(&nic->the_reg_lock);
12534 +
12535 + EFHW_TRACE("%s: DONE", __func__);
12536 +}
12537 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/resource_driver.c
12538 ===================================================================
12539 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
12540 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/resource_driver.c 2008-07-17 16:18:07.000000000 +0200
12541 @@ -0,0 +1,600 @@
12542 +/****************************************************************************
12543 + * Driver for Solarflare network controllers -
12544 + * resource management for Xen backend, OpenOnload, etc
12545 + * (including support for SFE4001 10GBT NIC)
12546 + *
12547 + * This file contains main driver entry points.
12548 + *
12549 + * Copyright 2005-2007: Solarflare Communications Inc,
12550 + * 9501 Jeronimo Road, Suite 250,
12551 + * Irvine, CA 92618, USA
12552 + *
12553 + * Developed and maintained by Solarflare Communications:
12554 + * <linux-xen-drivers@solarflare.com>
12555 + * <onload-dev@solarflare.com>
12556 + *
12557 + * Certain parts of the driver were implemented by
12558 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
12559 + * OKTET Labs Ltd, Russia,
12560 + * http://oktetlabs.ru, <info@oktetlabs.ru>
12561 + * by request of Solarflare Communications
12562 + *
12563 + *
12564 + * This program is free software; you can redistribute it and/or modify it
12565 + * under the terms of the GNU General Public License version 2 as published
12566 + * by the Free Software Foundation, incorporated herein by reference.
12567 + *
12568 + * This program is distributed in the hope that it will be useful,
12569 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12570 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12571 + * GNU General Public License for more details.
12572 + *
12573 + * You should have received a copy of the GNU General Public License
12574 + * along with this program; if not, write to the Free Software
12575 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12576 + ****************************************************************************
12577 + */
12578 +
12579 +#include "linux_resource_internal.h"
12580 +#include "kernel_compat.h"
12581 +#include <ci/efrm/nic_table.h>
12582 +#include <ci/driver/resource/efx_vi.h>
12583 +#include <ci/efhw/eventq.h>
12584 +#include <ci/efhw/nic.h>
12585 +#include <ci/efrm/buffer_table.h>
12586 +#include <ci/efrm/vi_resource_private.h>
12587 +#include <ci/efrm/driver_private.h>
12588 +
12589 +MODULE_AUTHOR("Solarflare Communications");
12590 +MODULE_LICENSE("GPL");
12591 +
12592 +static struct efhw_ev_handler ev_handler = {
12593 + .wakeup_fn = efrm_handle_wakeup_event,
12594 + .timeout_fn = efrm_handle_timeout_event,
12595 + .dmaq_flushed_fn = efrm_handle_dmaq_flushed,
12596 +};
12597 +
12598 +const int max_hardware_init_repeats = 10;
12599 +
12600 +/*--------------------------------------------------------------------
12601 + *
12602 + * Module load time variables
12603 + *
12604 + *--------------------------------------------------------------------*/
12605 +/* See docs/notes/pci_alloc_consistent */
12606 +static int do_irq = 1; /* enable interrupts */
12607 +
12608 +#if defined(CONFIG_X86_XEN)
12609 +static int irq_moderation = 60; /* interrupt moderation (60 usec) */
12610 +#else
12611 +static int irq_moderation = 20; /* interrupt moderation (20 usec) */
12612 +#endif
12613 +static int nic_options = NIC_OPT_DEFAULT;
12614 +int efx_vi_eventq_size = EFX_VI_EVENTQ_SIZE_DEFAULT;
12615 +
12616 +module_param(do_irq, int, S_IRUGO);
12617 +MODULE_PARM_DESC(do_irq, "Enable interrupts. "
12618 + "Do not turn it off unless you know what are you doing.");
12619 +module_param(irq_moderation, int, S_IRUGO);
12620 +MODULE_PARM_DESC(irq_moderation, "IRQ moderation in usec");
12621 +module_param(nic_options, int, S_IRUGO);
12622 +MODULE_PARM_DESC(nic_options, "Nic options -- see efhw_types.h");
12623 +module_param(efx_vi_eventq_size, int, S_IRUGO);
12624 +MODULE_PARM_DESC(efx_vi_eventq_size,
12625 + "Size of event queue allocated by efx_vi library");
12626 +
12627 +/*--------------------------------------------------------------------
12628 + *
12629 + * Linux specific NIC initialisation
12630 + *
12631 + *--------------------------------------------------------------------*/
12632 +
12633 +static inline irqreturn_t
12634 +linux_efrm_interrupt(int irr, void *dev_id)
12635 +{
12636 + return efhw_nic_interrupt((struct efhw_nic *)dev_id);
12637 +}
12638 +
12639 +int linux_efrm_irq_ctor(struct linux_efhw_nic *lnic)
12640 +{
12641 + struct efhw_nic *nic = &lnic->efrm_nic.efhw_nic;
12642 +
12643 + nic->flags &= ~NIC_FLAG_MSI;
12644 + if (nic->flags & NIC_FLAG_TRY_MSI) {
12645 + int rc = pci_enable_msi(lnic->pci_dev);
12646 + if (rc < 0) {
12647 + EFRM_WARN("%s: Could not enable MSI (%d)",
12648 + __func__, rc);
12649 + EFRM_WARN("%s: Continuing with legacy interrupt mode",
12650 + __func__);
12651 + } else {
12652 + EFRM_NOTICE("%s: MSI enabled", __func__);
12653 + nic->flags |= NIC_FLAG_MSI;
12654 + }
12655 + }
12656 +
12657 + if (request_irq(lnic->pci_dev->irq, linux_efrm_interrupt,
12658 + IRQF_SHARED, "sfc_resource", nic)) {
12659 + EFRM_ERR("Request for interrupt #%d failed",
12660 + lnic->pci_dev->irq);
12661 + nic->flags &= ~NIC_FLAG_OS_IRQ_EN;
12662 + return -EBUSY;
12663 + }
12664 + nic->flags |= NIC_FLAG_OS_IRQ_EN;
12665 +
12666 + return 0;
12667 +}
12668 +
12669 +void linux_efrm_irq_dtor(struct linux_efhw_nic *lnic)
12670 +{
12671 + EFRM_TRACE("%s: start", __func__);
12672 +
12673 + if (lnic->efrm_nic.efhw_nic.flags & NIC_FLAG_OS_IRQ_EN) {
12674 + free_irq(lnic->pci_dev->irq, &lnic->efrm_nic.efhw_nic);
12675 + lnic->efrm_nic.efhw_nic.flags &= ~NIC_FLAG_OS_IRQ_EN;
12676 + }
12677 +
12678 + if (lnic->efrm_nic.efhw_nic.flags & NIC_FLAG_MSI) {
12679 + pci_disable_msi(lnic->pci_dev);
12680 + lnic->efrm_nic.efhw_nic.flags &= ~NIC_FLAG_MSI;
12681 + }
12682 +
12683 + EFRM_TRACE("%s: done", __func__);
12684 +}
12685 +
12686 +/* Allocate buffer table entries for a particular NIC.
12687 + */
12688 +static int efrm_nic_buffer_table_alloc(struct efhw_nic *nic)
12689 +{
12690 + int capacity;
12691 + int page_order;
12692 + int rc;
12693 +
12694 + /* Choose queue size. */
12695 + for (capacity = 8192; capacity <= nic->evq_sizes; capacity <<= 1) {
12696 + if (capacity > nic->evq_sizes) {
12697 + EFRM_ERR
12698 + ("%s: Unable to choose EVQ size (supported=%x)",
12699 + __func__, nic->evq_sizes);
12700 + return -E2BIG;
12701 + } else if (capacity & nic->evq_sizes)
12702 + break;
12703 + }
12704 +
12705 + nic->interrupting_evq.hw.capacity = capacity;
12706 + nic->interrupting_evq.hw.buf_tbl_alloc.base = (unsigned)-1;
12707 +
12708 + nic->non_interrupting_evq.hw.capacity = capacity;
12709 + nic->non_interrupting_evq.hw.buf_tbl_alloc.base = (unsigned)-1;
12710 +
12711 + /* allocate buffer table entries to map onto the iobuffer */
12712 + page_order = get_order(capacity * sizeof(efhw_event_t));
12713 + if (!(nic->flags & NIC_FLAG_NO_INTERRUPT)) {
12714 + rc = efrm_buffer_table_alloc(page_order,
12715 + &nic->interrupting_evq
12716 + .hw.buf_tbl_alloc);
12717 + if (rc < 0) {
12718 + EFRM_WARN
12719 + ("%s: failed (%d) to alloc %d buffer table entries",
12720 + __func__, rc, page_order);
12721 + return rc;
12722 + }
12723 + }
12724 + rc = efrm_buffer_table_alloc(page_order,
12725 + &nic->non_interrupting_evq.hw.
12726 + buf_tbl_alloc);
12727 + if (rc < 0) {
12728 + EFRM_WARN
12729 + ("%s: failed (%d) to alloc %d buffer table entries",
12730 + __func__, rc, page_order);
12731 + return rc;
12732 + }
12733 +
12734 + return 0;
12735 +}
12736 +
12737 +/* Free buffer table entries allocated for a particular NIC.
12738 + */
12739 +static void efrm_nic_buffer_table_free(struct efhw_nic *nic)
12740 +{
12741 + if (nic->interrupting_evq.hw.buf_tbl_alloc.base != (unsigned)-1)
12742 + efrm_buffer_table_free(&nic->interrupting_evq.hw
12743 + .buf_tbl_alloc);
12744 + if (nic->non_interrupting_evq.hw.buf_tbl_alloc.base != (unsigned)-1)
12745 + efrm_buffer_table_free(&nic->non_interrupting_evq
12746 + .hw.buf_tbl_alloc);
12747 +}
12748 +
12749 +static int iomap_bar(struct linux_efhw_nic *lnic, size_t len)
12750 +{
12751 + volatile char __iomem *ioaddr;
12752 +
12753 + ioaddr = ioremap_nocache(lnic->ctr_ap_pci_addr, len);
12754 + if (ioaddr == 0)
12755 + return -ENOMEM;
12756 +
12757 + lnic->efrm_nic.efhw_nic.bar_ioaddr = ioaddr;
12758 + return 0;
12759 +}
12760 +
12761 +static int linux_efhw_nic_map_ctr_ap(struct linux_efhw_nic *lnic)
12762 +{
12763 + struct efhw_nic *nic = &lnic->efrm_nic.efhw_nic;
12764 + int rc;
12765 +
12766 + rc = iomap_bar(lnic, nic->ctr_ap_bytes);
12767 +
12768 + /* Bug 5195: workaround for now. */
12769 + if (rc != 0 && nic->ctr_ap_bytes > 16 * 1024 * 1024) {
12770 + /* Try half the size for now. */
12771 + nic->ctr_ap_bytes /= 2;
12772 + EFRM_WARN("Bug 5195 WORKAROUND: retrying iomap of %d bytes",
12773 + nic->ctr_ap_bytes);
12774 + rc = iomap_bar(lnic, nic->ctr_ap_bytes);
12775 + }
12776 +
12777 + if (rc < 0) {
12778 + EFRM_ERR("Failed (%d) to map bar (%d bytes)",
12779 + rc, nic->ctr_ap_bytes);
12780 + return rc;
12781 + }
12782 +
12783 + return rc;
12784 +}
12785 +
12786 +int
12787 +linux_efrm_nic_ctor(struct linux_efhw_nic *lnic, struct pci_dev *dev,
12788 + spinlock_t *reg_lock,
12789 + unsigned nic_flags, unsigned nic_options)
12790 +{
12791 + struct efhw_device_type dev_type;
12792 + struct efhw_nic *nic = &lnic->efrm_nic.efhw_nic;
12793 + u8 class_revision;
12794 + int rc;
12795 +
12796 + rc = pci_read_config_byte(dev, PCI_CLASS_REVISION, &class_revision);
12797 + if (rc != 0) {
12798 + EFRM_ERR("%s: pci_read_config_byte failed (%d)",
12799 + __func__, rc);
12800 + return rc;
12801 + }
12802 +
12803 + if (!efhw_device_type_init(&dev_type, dev->vendor, dev->device,
12804 + class_revision)) {
12805 + EFRM_ERR("%s: efhw_device_type_init failed %04x:%04x(%d)",
12806 + __func__, (unsigned) dev->vendor,
12807 + (unsigned) dev->device, (int) class_revision);
12808 + return -ENODEV;
12809 + }
12810 +
12811 + EFRM_NOTICE("attaching device type %04x:%04x %d:%c%d",
12812 + (unsigned) dev->vendor, (unsigned) dev->device,
12813 + dev_type.arch, dev_type.variant, dev_type.revision);
12814 +
12815 + /* Initialise the adapter-structure. */
12816 + efhw_nic_init(nic, nic_flags, nic_options, dev_type);
12817 + lnic->pci_dev = dev;
12818 +
12819 + rc = pci_enable_device(dev);
12820 + if (rc < 0) {
12821 + EFRM_ERR("%s: pci_enable_device failed (%d)",
12822 + __func__, rc);
12823 + return rc;
12824 + }
12825 +
12826 + lnic->ctr_ap_pci_addr = pci_resource_start(dev, nic->ctr_ap_bar);
12827 +
12828 + if (!pci_dma_supported(dev, (dma_addr_t)EFHW_DMA_ADDRMASK)) {
12829 + EFRM_ERR("%s: pci_dma_supported(%lx) failed", __func__,
12830 + (unsigned long)EFHW_DMA_ADDRMASK);
12831 + return -ENODEV;
12832 + }
12833 +
12834 + if (pci_set_dma_mask(dev, (dma_addr_t)EFHW_DMA_ADDRMASK)) {
12835 + EFRM_ERR("%s: pci_set_dma_mask(%lx) failed", __func__,
12836 + (unsigned long)EFHW_DMA_ADDRMASK);
12837 + return -ENODEV;
12838 + }
12839 +
12840 + if (pci_set_consistent_dma_mask(dev, (dma_addr_t)EFHW_DMA_ADDRMASK)) {
12841 + EFRM_ERR("%s: pci_set_consistent_dma_mask(%lx) failed",
12842 + __func__, (unsigned long)EFHW_DMA_ADDRMASK);
12843 + return -ENODEV;
12844 + }
12845 +
12846 + rc = linux_efhw_nic_map_ctr_ap(lnic);
12847 + if (rc < 0)
12848 + return rc;
12849 +
12850 + /* By default struct efhw_nic contains its own lock for protecting
12851 + * access to nic registers. We override it with a pointer to the
12852 + * lock in the net driver. This is needed when resource and net
12853 + * drivers share a single PCI function (falcon B series).
12854 + */
12855 + nic->reg_lock = reg_lock;
12856 + return 0;
12857 +}
12858 +
12859 +void linux_efrm_nic_dtor(struct linux_efhw_nic *lnic)
12860 +{
12861 + struct efhw_nic *nic = &lnic->efrm_nic.efhw_nic;
12862 + volatile char __iomem *bar_ioaddr = nic->bar_ioaddr;
12863 +
12864 + efhw_nic_dtor(nic);
12865 +
12866 + /* Unmap the bar. */
12867 + EFRM_ASSERT(bar_ioaddr);
12868 + iounmap(bar_ioaddr);
12869 + nic->bar_ioaddr = 0;
12870 +}
12871 +
12872 +/****************************************************************************
12873 + *
12874 + * efrm_tasklet - used to poll the eventq which may result in further callbacks
12875 + *
12876 + ****************************************************************************/
12877 +
12878 +static void efrm_tasklet(unsigned long pdev)
12879 +{
12880 + struct efhw_nic *nic = (struct efhw_nic *)pdev;
12881 +
12882 + EFRM_ASSERT(!(nic->flags & NIC_FLAG_NO_INTERRUPT));
12883 +
12884 + efhw_keventq_poll(nic, &nic->interrupting_evq);
12885 + EFRM_TRACE("%s: complete", __func__);
12886 +}
12887 +
12888 +/****************************************************************************
12889 + *
12890 + * char driver specific interrupt callbacks -- run at hard IRQL
12891 + *
12892 + ****************************************************************************/
12893 +static void efrm_handle_eventq_irq(struct efhw_nic *nic, int evq)
12894 +{
12895 + /* NB. The interrupt must have already been acked (for legacy mode). */
12896 +
12897 + EFRM_TRACE("%s: starting tasklet", __func__);
12898 + EFRM_ASSERT(!(nic->flags & NIC_FLAG_NO_INTERRUPT));
12899 +
12900 + tasklet_schedule(&linux_efhw_nic(nic)->tasklet);
12901 +}
12902 +
12903 +/* A count of how many NICs this driver knows about. */
12904 +static int n_nics_probed;
12905 +
12906 +/****************************************************************************
12907 + *
12908 + * efrm_nic_add: add the NIC to the resource driver
12909 + *
12910 + * NOTE: the flow of control through this routine is quite subtle
12911 + * because of the number of operations that can fail. We therefore
12912 + * take the apporaching of keeping the return code (rc) variable
12913 + * accurate, and only do operations while it is non-negative. Tear down
12914 + * is done at the end if rc is negative, depending on what has been set up
12915 + * by that point.
12916 + *
12917 + * So basically just make sure that any code you add checks rc>=0 before
12918 + * doing any work and you'll be fine.
12919 + *
12920 + ****************************************************************************/
12921 +int
12922 +efrm_nic_add(struct pci_dev *dev, unsigned flags, const uint8_t *mac_addr,
12923 + struct linux_efhw_nic **lnic_out, spinlock_t *reg_lock,
12924 + int bt_min, int bt_lim, int non_irq_evq,
12925 + const struct vi_resource_dimensions *res_dim)
12926 +{
12927 + struct linux_efhw_nic *lnic = NULL;
12928 + struct efhw_nic *nic = NULL;
12929 + int count = 0, rc = 0, resources_init = 0;
12930 + int constructed = 0;
12931 + int registered_nic = 0;
12932 + int buffers_allocated = 0;
12933 + static unsigned nic_index; /* = 0; */
12934 +
12935 + EFRM_TRACE("%s: device detected (Slot '%s', IRQ %d)", __func__,
12936 + pci_name(dev) ? pci_name(dev) : "?", dev->irq);
12937 +
12938 + /* Ensure that we have room for the new adapter-structure. */
12939 + if (efrm_nic_tablep->nic_count == EFHW_MAX_NR_DEVS) {
12940 + EFRM_WARN("%s: WARNING: too many devices", __func__);
12941 + rc = -ENOMEM;
12942 + goto failed;
12943 + }
12944 +
12945 + if (n_nics_probed == 0) {
12946 + rc = efrm_resources_init(res_dim, bt_min, bt_lim);
12947 + if (rc != 0)
12948 + goto failed;
12949 + resources_init = 1;
12950 + }
12951 +
12952 + /* Allocate memory for the new adapter-structure. */
12953 + lnic = kmalloc(sizeof(*lnic), GFP_KERNEL);
12954 + if (lnic == NULL) {
12955 + EFRM_ERR("%s: ERROR: failed to allocate memory", __func__);
12956 + rc = -ENOMEM;
12957 + goto failed;
12958 + }
12959 + memset(lnic, 0, sizeof(*lnic));
12960 + nic = &lnic->efrm_nic.efhw_nic;
12961 +
12962 + lnic->ev_handlers = &ev_handler;
12963 +
12964 + /* OS specific hardware mappings */
12965 + rc = linux_efrm_nic_ctor(lnic, dev, reg_lock, flags, nic_options);
12966 + if (rc < 0) {
12967 + EFRM_ERR("%s: ERROR: initialisation failed", __func__);
12968 + goto failed;
12969 + }
12970 +
12971 + constructed = 1;
12972 +
12973 + /* Tell the driver about the NIC - this needs to be done before the
12974 + resources managers get created below. Note we haven't initialised
12975 + the hardware yet, and I don't like doing this before the perhaps
12976 + unreliable hardware initialisation. However, there's quite a lot
12977 + of code to review if we wanted to hardware init before bringing
12978 + up the resource managers. */
12979 + rc = efrm_driver_register_nic(&lnic->efrm_nic, nic_index,
12980 + /* TODO: ifindex */ nic_index);
12981 + if (rc < 0) {
12982 + EFRM_ERR("%s: cannot register nic %d with nic error code %d",
12983 + __func__, efrm_nic_tablep->nic_count, rc);
12984 + goto failed;
12985 + }
12986 + ++nic_index;
12987 + registered_nic = 1;
12988 +
12989 + rc = efrm_nic_buffer_table_alloc(nic);
12990 + if (rc < 0)
12991 + goto failed;
12992 + buffers_allocated = 1;
12993 +
12994 + /****************************************************/
12995 + /* hardware bringup */
12996 + /****************************************************/
12997 + /* Detecting hardware can be a slightly unreliable process;
12998 + we want to make sure that we maximise our chances, so we
12999 + loop a few times until all is good. */
13000 + for (count = 0; count < max_hardware_init_repeats; count++) {
13001 + rc = efhw_nic_init_hardware(nic, &ev_handler, mac_addr,
13002 + non_irq_evq);
13003 + if (rc >= 0)
13004 + break;
13005 +
13006 + /* pain */
13007 + EFRM_ERR
13008 + ("error - hardware initialisation failed code %d, "
13009 + "attempt %d of %d", rc, count + 1,
13010 + max_hardware_init_repeats);
13011 + }
13012 + if (rc < 0)
13013 + goto failed;
13014 +
13015 + tasklet_init(&lnic->tasklet, efrm_tasklet, (ulong)nic);
13016 +
13017 + /* set up interrupt handlers (hard-irq) */
13018 + nic->irq_handler = &efrm_handle_eventq_irq;
13019 +
13020 + /* this device can now take management interrupts */
13021 + if (do_irq && !(nic->flags & NIC_FLAG_NO_INTERRUPT)) {
13022 + rc = linux_efrm_irq_ctor(lnic);
13023 + if (rc < 0) {
13024 + EFRM_ERR("Interrupt initialisation failed (%d)", rc);
13025 + goto failed;
13026 + }
13027 + efhw_nic_set_interrupt_moderation(nic, -1, irq_moderation);
13028 + efhw_nic_interrupt_enable(nic);
13029 + }
13030 + EFRM_TRACE("interrupts are %sregistered", do_irq ? "" : "not ");
13031 +
13032 + *lnic_out = lnic;
13033 + EFRM_ASSERT(rc == 0);
13034 + ++n_nics_probed;
13035 + return 0;
13036 +
13037 +failed:
13038 + if (buffers_allocated)
13039 + efrm_nic_buffer_table_free(nic);
13040 + if (registered_nic)
13041 + efrm_driver_unregister_nic(&lnic->efrm_nic);
13042 + if (constructed)
13043 + linux_efrm_nic_dtor(lnic);
13044 + kfree(lnic); /* safe in any case */
13045 + if (resources_init)
13046 + efrm_resources_fini();
13047 + return rc;
13048 +}
13049 +
13050 +/****************************************************************************
13051 + *
13052 + * efrm_nic_del: Remove the nic from the resource driver structures
13053 + *
13054 + ****************************************************************************/
13055 +void efrm_nic_del(struct linux_efhw_nic *lnic)
13056 +{
13057 + struct efhw_nic *nic = &lnic->efrm_nic.efhw_nic;
13058 +
13059 + EFRM_TRACE("%s:", __func__);
13060 + EFRM_ASSERT(nic);
13061 +
13062 + efrm_nic_buffer_table_free(nic);
13063 +
13064 + efrm_driver_unregister_nic(&lnic->efrm_nic);
13065 +
13066 + /*
13067 + * Synchronise here with any running ISR.
13068 + * Remove the OS handler. There should be no IRQs being generated
13069 + * by our NIC at this point.
13070 + */
13071 + if (efhw_nic_have_functional_units(nic)) {
13072 + efhw_nic_close_interrupts(nic);
13073 + linux_efrm_irq_dtor(lnic);
13074 + tasklet_kill(&lnic->tasklet);
13075 + }
13076 +
13077 + /* Close down hardware and free resources. */
13078 + linux_efrm_nic_dtor(lnic);
13079 + kfree(lnic);
13080 +
13081 + if (--n_nics_probed == 0)
13082 + efrm_resources_fini();
13083 +
13084 + EFRM_TRACE("%s: done", __func__);
13085 +}
13086 +
13087 +/****************************************************************************
13088 + *
13089 + * init_module: register as a PCI driver.
13090 + *
13091 + ****************************************************************************/
13092 +static int init_sfc_resource(void)
13093 +{
13094 + int rc = 0;
13095 +
13096 + EFRM_TRACE("%s: RESOURCE driver starting", __func__);
13097 +
13098 + efrm_driver_ctor();
13099 +
13100 + /* Register the driver so that our 'probe' function is called for
13101 + * each EtherFabric device in the system.
13102 + */
13103 + rc = efrm_driverlink_register();
13104 + if (rc == -ENODEV)
13105 + EFRM_ERR("%s: no devices found", __func__);
13106 + if (rc < 0)
13107 + goto failed_driverlink;
13108 +
13109 + if (efrm_install_proc_entries() != 0) {
13110 + /* Do not fail, but print a warning */
13111 + EFRM_WARN("%s: WARNING: failed to install /proc entries",
13112 + __func__);
13113 + }
13114 +
13115 + return 0;
13116 +
13117 +failed_driverlink:
13118 + efrm_driver_dtor();
13119 + return rc;
13120 +}
13121 +
13122 +/****************************************************************************
13123 + *
13124 + * cleanup_module: module-removal entry-point
13125 + *
13126 + ****************************************************************************/
13127 +static void cleanup_sfc_resource(void)
13128 +{
13129 + efrm_uninstall_proc_entries();
13130 +
13131 + efrm_driverlink_unregister();
13132 +
13133 + /* Clean up char-driver specific initialisation.
13134 + - driver dtor can use both work queue and buffer table entries */
13135 + efrm_driver_dtor();
13136 +
13137 + EFRM_TRACE("%s: unloaded", __func__);
13138 +}
13139 +
13140 +module_init(init_sfc_resource);
13141 +module_exit(cleanup_sfc_resource);
13142 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/resource_manager.c
13143 ===================================================================
13144 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
13145 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/resource_manager.c 2008-07-17 16:18:07.000000000 +0200
13146 @@ -0,0 +1,145 @@
13147 +/****************************************************************************
13148 + * Driver for Solarflare network controllers -
13149 + * resource management for Xen backend, OpenOnload, etc
13150 + * (including support for SFE4001 10GBT NIC)
13151 + *
13152 + * This file contains generic code for resources and resource managers.
13153 + *
13154 + * Copyright 2005-2007: Solarflare Communications Inc,
13155 + * 9501 Jeronimo Road, Suite 250,
13156 + * Irvine, CA 92618, USA
13157 + *
13158 + * Developed and maintained by Solarflare Communications:
13159 + * <linux-xen-drivers@solarflare.com>
13160 + * <onload-dev@solarflare.com>
13161 + *
13162 + * Certain parts of the driver were implemented by
13163 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
13164 + * OKTET Labs Ltd, Russia,
13165 + * http://oktetlabs.ru, <info@oktetlabs.ru>
13166 + * by request of Solarflare Communications
13167 + *
13168 + *
13169 + * This program is free software; you can redistribute it and/or modify it
13170 + * under the terms of the GNU General Public License version 2 as published
13171 + * by the Free Software Foundation, incorporated herein by reference.
13172 + *
13173 + * This program is distributed in the hope that it will be useful,
13174 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13175 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13176 + * GNU General Public License for more details.
13177 + *
13178 + * You should have received a copy of the GNU General Public License
13179 + * along with this program; if not, write to the Free Software
13180 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13181 + ****************************************************************************
13182 + */
13183 +
13184 +#include <ci/efrm/debug.h>
13185 +#include <ci/efrm/nic_table.h>
13186 +#include <ci/efhw/iopage.h>
13187 +#include <ci/efrm/driver_private.h>
13188 +#include <ci/efrm/private.h>
13189 +#include "efrm_internal.h"
13190 +
13191 +/**********************************************************************
13192 + * struct efrm_resource_manager
13193 + */
13194 +
13195 +void efrm_resource_manager_dtor(struct efrm_resource_manager *rm)
13196 +{
13197 + EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm);
13198 +
13199 + /* call destructor */
13200 + EFRM_DO_DEBUG(if (rm->rm_resources)
13201 + EFRM_ERR("%s: %s leaked %d resources",
13202 + __func__, rm->rm_name, rm->rm_resources));
13203 + EFRM_ASSERT(rm->rm_resources == 0);
13204 + EFRM_ASSERT(list_empty(&rm->rm_resources_list));
13205 +
13206 + rm->rm_dtor(rm);
13207 +
13208 + /* clear out things built by efrm_resource_manager_ctor */
13209 + spin_lock_destroy(&rm->rm_lock);
13210 +
13211 + /* and the free the memory */
13212 + EFRM_DO_DEBUG(memset(rm, 0, sizeof(*rm)));
13213 + kfree(rm);
13214 +}
13215 +
13216 +/* Construct a resource manager. Resource managers are singletons. */
13217 +int
13218 +efrm_resource_manager_ctor(struct efrm_resource_manager *rm,
13219 + void (*dtor)(struct efrm_resource_manager *),
13220 + const char *name, unsigned type)
13221 +{
13222 + EFRM_ASSERT(rm);
13223 + EFRM_ASSERT(dtor);
13224 +
13225 + rm->rm_name = name;
13226 + EFRM_DO_DEBUG(rm->rm_type = type);
13227 + rm->rm_dtor = dtor;
13228 + spin_lock_init(&rm->rm_lock);
13229 + rm->rm_resources = 0;
13230 + rm->rm_resources_hiwat = 0;
13231 + INIT_LIST_HEAD(&rm->rm_resources_list);
13232 + EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm);
13233 + return 0;
13234 +}
13235 +
13236 +
13237 +void efrm_client_add_resource(struct efrm_client *client,
13238 + struct efrm_resource *rs)
13239 +{
13240 + struct efrm_resource_manager *rm;
13241 + irq_flags_t lock_flags;
13242 +
13243 + EFRM_ASSERT(client != NULL);
13244 + EFRM_ASSERT(rs != NULL);
13245 +
13246 + spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
13247 + rm = efrm_rm_table[EFRM_RESOURCE_TYPE(rs->rs_handle)];
13248 + ++rm->rm_resources;
13249 + list_add(&rs->rs_manager_link, &rm->rm_resources_list);
13250 + if (rm->rm_resources > rm->rm_resources_hiwat)
13251 + rm->rm_resources_hiwat = rm->rm_resources;
13252 + rs->rs_client = client;
13253 + ++client->ref_count;
13254 + list_add(&rs->rs_client_link, &client->resources);
13255 + spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
13256 +}
13257 +
13258 +
13259 +void efrm_resource_ref(struct efrm_resource *rs)
13260 +{
13261 + irq_flags_t lock_flags;
13262 + spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
13263 + ++rs->rs_ref_count;
13264 + spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
13265 +}
13266 +EXPORT_SYMBOL(efrm_resource_ref);
13267 +
13268 +
13269 +int __efrm_resource_release(struct efrm_resource *rs)
13270 +{
13271 + struct efrm_resource_manager *rm;
13272 + irq_flags_t lock_flags;
13273 + int free_rs;
13274 +
13275 + spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
13276 + free_rs = --rs->rs_ref_count == 0;
13277 + if (free_rs) {
13278 + rm = efrm_rm_table[EFRM_RESOURCE_TYPE(rs->rs_handle)];
13279 + EFRM_ASSERT(rm->rm_resources > 0);
13280 + --rm->rm_resources;
13281 + list_del(&rs->rs_manager_link);
13282 + list_del(&rs->rs_client_link);
13283 + }
13284 + spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
13285 + return free_rs;
13286 +}
13287 +EXPORT_SYMBOL(__efrm_resource_release);
13288 +
13289 +/*
13290 + * vi: sw=8:ai:aw
13291 + */
13292 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/resources.c
13293 ===================================================================
13294 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
13295 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/resources.c 2008-07-17 16:18:07.000000000 +0200
13296 @@ -0,0 +1,94 @@
13297 +/****************************************************************************
13298 + * Driver for Solarflare network controllers -
13299 + * resource management for Xen backend, OpenOnload, etc
13300 + * (including support for SFE4001 10GBT NIC)
13301 + *
13302 + * This file contains resource managers initialisation functions.
13303 + *
13304 + * Copyright 2005-2007: Solarflare Communications Inc,
13305 + * 9501 Jeronimo Road, Suite 250,
13306 + * Irvine, CA 92618, USA
13307 + *
13308 + * Developed and maintained by Solarflare Communications:
13309 + * <linux-xen-drivers@solarflare.com>
13310 + * <onload-dev@solarflare.com>
13311 + *
13312 + * Certain parts of the driver were implemented by
13313 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
13314 + * OKTET Labs Ltd, Russia,
13315 + * http://oktetlabs.ru, <info@oktetlabs.ru>
13316 + * by request of Solarflare Communications
13317 + *
13318 + *
13319 + * This program is free software; you can redistribute it and/or modify it
13320 + * under the terms of the GNU General Public License version 2 as published
13321 + * by the Free Software Foundation, incorporated herein by reference.
13322 + *
13323 + * This program is distributed in the hope that it will be useful,
13324 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13325 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13326 + * GNU General Public License for more details.
13327 + *
13328 + * You should have received a copy of the GNU General Public License
13329 + * along with this program; if not, write to the Free Software
13330 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13331 + ****************************************************************************
13332 + */
13333 +
13334 +#include <ci/efrm/private.h>
13335 +#include <ci/efrm/buffer_table.h>
13336 +
13337 +int
13338 +efrm_resources_init(const struct vi_resource_dimensions *vi_res_dim,
13339 + int buffer_table_min, int buffer_table_lim)
13340 +{
13341 + int i, rc;
13342 +
13343 + rc = efrm_buffer_table_ctor(buffer_table_min, buffer_table_lim);
13344 + if (rc != 0)
13345 + return rc;
13346 +
13347 + /* Create resources in the correct order */
13348 + for (i = 0; i < EFRM_RESOURCE_NUM; ++i) {
13349 + struct efrm_resource_manager **rmp = &efrm_rm_table[i];
13350 +
13351 + EFRM_ASSERT(*rmp == NULL);
13352 + switch (i) {
13353 + case EFRM_RESOURCE_VI:
13354 + rc = efrm_create_vi_resource_manager(rmp,
13355 + vi_res_dim);
13356 + break;
13357 + case EFRM_RESOURCE_FILTER:
13358 + rc = efrm_create_filter_resource_manager(rmp);
13359 + break;
13360 + case EFRM_RESOURCE_IOBUFSET:
13361 + rc = efrm_create_iobufset_resource_manager(rmp);
13362 + break;
13363 + default:
13364 + rc = 0;
13365 + break;
13366 + }
13367 +
13368 + if (rc < 0) {
13369 + EFRM_ERR("%s: failed type=%d (%d)",
13370 + __func__, i, rc);
13371 + efrm_buffer_table_dtor();
13372 + return rc;
13373 + }
13374 + }
13375 +
13376 + return 0;
13377 +}
13378 +
13379 +void efrm_resources_fini(void)
13380 +{
13381 + int i;
13382 +
13383 + for (i = EFRM_RESOURCE_NUM - 1; i >= 0; --i)
13384 + if (efrm_rm_table[i]) {
13385 + efrm_resource_manager_dtor(efrm_rm_table[i]);
13386 + efrm_rm_table[i] = NULL;
13387 + }
13388 +
13389 + efrm_buffer_table_dtor();
13390 +}
13391 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/vi_resource_alloc.c
13392 ===================================================================
13393 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
13394 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/vi_resource_alloc.c 2008-07-17 16:18:07.000000000 +0200
13395 @@ -0,0 +1,820 @@
13396 +/****************************************************************************
13397 + * Driver for Solarflare network controllers -
13398 + * resource management for Xen backend, OpenOnload, etc
13399 + * (including support for SFE4001 10GBT NIC)
13400 + *
13401 + * This file contains allocation of VI resources.
13402 + *
13403 + * Copyright 2005-2007: Solarflare Communications Inc,
13404 + * 9501 Jeronimo Road, Suite 250,
13405 + * Irvine, CA 92618, USA
13406 + *
13407 + * Developed and maintained by Solarflare Communications:
13408 + * <linux-xen-drivers@solarflare.com>
13409 + * <onload-dev@solarflare.com>
13410 + *
13411 + * Certain parts of the driver were implemented by
13412 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
13413 + * OKTET Labs Ltd, Russia,
13414 + * http://oktetlabs.ru, <info@oktetlabs.ru>
13415 + * by request of Solarflare Communications
13416 + *
13417 + *
13418 + * This program is free software; you can redistribute it and/or modify it
13419 + * under the terms of the GNU General Public License version 2 as published
13420 + * by the Free Software Foundation, incorporated herein by reference.
13421 + *
13422 + * This program is distributed in the hope that it will be useful,
13423 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13424 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13425 + * GNU General Public License for more details.
13426 + *
13427 + * You should have received a copy of the GNU General Public License
13428 + * along with this program; if not, write to the Free Software
13429 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13430 + ****************************************************************************
13431 + */
13432 +
13433 +#include <ci/efrm/nic_table.h>
13434 +#include <ci/efhw/iopage.h>
13435 +#include <ci/driver/efab/hardware.h>
13436 +#include <ci/efhw/public.h>
13437 +#include <ci/efhw/falcon.h>
13438 +#include <ci/efrm/private.h>
13439 +#include <ci/efrm/buffer_table.h>
13440 +#include <ci/efrm/vi_resource_private.h>
13441 +#include <ci/efrm/efrm_client.h>
13442 +#include "efrm_internal.h"
13443 +
13444 +
13445 +/*** Data definitions ****************************************************/
13446 +
13447 +static const char *dmaq_names[] = { "TX", "RX" };
13448 +
13449 +struct vi_resource_manager *efrm_vi_manager;
13450 +
13451 +/*** Forward references **************************************************/
13452 +
13453 +static int
13454 +efrm_vi_resource_alloc_or_free(struct efrm_client *client,
13455 + int alloc, struct vi_resource *evq_virs,
13456 + uint16_t vi_flags, int32_t evq_capacity,
13457 + int32_t txq_capacity, int32_t rxq_capacity,
13458 + uint8_t tx_q_tag, uint8_t rx_q_tag,
13459 + struct vi_resource **virs_in_out);
13460 +
13461 +/*** Reference count handling ********************************************/
13462 +
13463 +static inline void efrm_vi_rm_get_ref(struct vi_resource *virs)
13464 +{
13465 + atomic_inc(&virs->evq_refs);
13466 +}
13467 +
13468 +static inline void efrm_vi_rm_drop_ref(struct vi_resource *virs)
13469 +{
13470 + EFRM_ASSERT(atomic_read(&virs->evq_refs) != 0);
13471 + if (atomic_dec_and_test(&virs->evq_refs))
13472 + efrm_vi_resource_alloc_or_free(virs->rs.rs_client, false, NULL,
13473 + 0, 0, 0, 0, 0, 0, &virs);
13474 +}
13475 +
13476 +/*** Instance numbers ****************************************************/
13477 +
13478 +static inline int efrm_vi_rm_alloc_id(uint16_t vi_flags, int32_t evq_capacity)
13479 +{
13480 + irq_flags_t lock_flags;
13481 + int instance;
13482 + int rc;
13483 +
13484 + if (efrm_nic_tablep->a_nic == NULL) /* ?? FIXME: surely not right */
13485 + return -ENODEV;
13486 +
13487 + spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
13488 +
13489 + /* Falcon A1 RX phys addr wierdness. */
13490 + if (efrm_nic_tablep->a_nic->devtype.variant == 'A' &&
13491 + (vi_flags & EFHW_VI_RX_PHYS_ADDR_EN)) {
13492 + if (vi_flags & EFHW_VI_JUMBO_EN) {
13493 + /* Falcon-A cannot do phys + scatter. */
13494 + EFRM_WARN
13495 + ("%s: falcon-A does not support phys+scatter mode",
13496 + __func__);
13497 + instance = -1;
13498 + } else if (efrm_vi_manager->iscsi_dmaq_instance_is_free
13499 + && evq_capacity == 0) {
13500 + /* Falcon-A has a single RXQ that gives the correct
13501 + * semantics for physical addressing. However, it
13502 + * happens to have the same instance number as the
13503 + * 'char' event queue, so we cannot also hand out
13504 + * the event queue. */
13505 + efrm_vi_manager->iscsi_dmaq_instance_is_free = false;
13506 + instance = FALCON_A1_ISCSI_DMAQ;
13507 + } else {
13508 + EFRM_WARN("%s: iSCSI receive queue not free",
13509 + __func__);
13510 + instance = -1;
13511 + }
13512 + goto unlock_out;
13513 + }
13514 +
13515 + if (vi_flags & EFHW_VI_RM_WITH_INTERRUPT) {
13516 + rc = __kfifo_get(efrm_vi_manager->instances_with_interrupt,
13517 + (unsigned char *)&instance, sizeof(instance));
13518 + if (rc != sizeof(instance)) {
13519 + EFRM_ASSERT(rc == 0);
13520 + instance = -1;
13521 + }
13522 + goto unlock_out;
13523 + }
13524 +
13525 + /* Otherwise a normal run-of-the-mill VI. */
13526 + rc = __kfifo_get(efrm_vi_manager->instances_with_timer,
13527 + (unsigned char *)&instance, sizeof(instance));
13528 + if (rc != sizeof(instance)) {
13529 + EFRM_ASSERT(rc == 0);
13530 + instance = -1;
13531 + }
13532 +
13533 +unlock_out:
13534 + spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
13535 + return instance;
13536 +}
13537 +
13538 +static void efrm_vi_rm_free_id(int instance)
13539 +{
13540 + irq_flags_t lock_flags;
13541 + struct kfifo *instances;
13542 +
13543 + if (efrm_nic_tablep->a_nic == NULL) /* ?? FIXME: surely not right */
13544 + return;
13545 +
13546 + if (efrm_nic_tablep->a_nic->devtype.variant == 'A' &&
13547 + instance == FALCON_A1_ISCSI_DMAQ) {
13548 + EFRM_ASSERT(efrm_vi_manager->iscsi_dmaq_instance_is_free ==
13549 + false);
13550 + spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
13551 + efrm_vi_manager->iscsi_dmaq_instance_is_free = true;
13552 + spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock,
13553 + lock_flags);
13554 + } else {
13555 + if (instance >= efrm_vi_manager->with_timer_base &&
13556 + instance < efrm_vi_manager->with_timer_limit) {
13557 + instances = efrm_vi_manager->instances_with_timer;
13558 + } else {
13559 + EFRM_ASSERT(instance >=
13560 + efrm_vi_manager->with_interrupt_base);
13561 + EFRM_ASSERT(instance <
13562 + efrm_vi_manager->with_interrupt_limit);
13563 + instances = efrm_vi_manager->instances_with_interrupt;
13564 + }
13565 +
13566 + EFRM_VERIFY_EQ(kfifo_put(instances, (unsigned char *)&instance,
13567 + sizeof(instance)), sizeof(instance));
13568 + }
13569 +}
13570 +
13571 +/*** Queue sizes *********************************************************/
13572 +
13573 +/* NB. This should really take a nic as an argument, but that makes
13574 + * the buffer table allocation difficult. */
13575 +uint32_t efrm_vi_rm_evq_bytes(struct vi_resource *virs
13576 + /*,struct efhw_nic *nic */)
13577 +{
13578 + return virs->evq_capacity * sizeof(efhw_event_t);
13579 +}
13580 +EXPORT_SYMBOL(efrm_vi_rm_evq_bytes);
13581 +
13582 +/* NB. This should really take a nic as an argument, but that makes
13583 + * the buffer table allocation difficult. */
13584 +uint32_t efrm_vi_rm_txq_bytes(struct vi_resource *virs
13585 + /*,struct efhw_nic *nic */)
13586 +{
13587 + return virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] *
13588 + FALCON_DMA_TX_DESC_BYTES;
13589 +}
13590 +EXPORT_SYMBOL(efrm_vi_rm_txq_bytes);
13591 +
13592 +/* NB. This should really take a nic as an argument, but that makes
13593 + * the buffer table allocation difficult. */
13594 +uint32_t efrm_vi_rm_rxq_bytes(struct vi_resource *virs
13595 + /*,struct efhw_nic *nic */)
13596 +{
13597 + uint32_t bytes_per_desc = ((virs->flags & EFHW_VI_RX_PHYS_ADDR_EN)
13598 + ? FALCON_DMA_RX_PHYS_DESC_BYTES
13599 + : FALCON_DMA_RX_BUF_DESC_BYTES);
13600 + return virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX] * bytes_per_desc;
13601 +}
13602 +EXPORT_SYMBOL(efrm_vi_rm_rxq_bytes);
13603 +
13604 +static int choose_size(int size_rq, unsigned sizes)
13605 +{
13606 + int size;
13607 +
13608 + /* size_rq < 0 means default, but we interpret this as 'minimum'. */
13609 +
13610 + for (size = 256;; size <<= 1)
13611 + if ((size & sizes) && size >= size_rq)
13612 + return size;
13613 + else if ((sizes & ~((size - 1) | size)) == 0)
13614 + return -1;
13615 +}
13616 +
13617 +static int
13618 +efrm_vi_rm_adjust_alloc_request(struct vi_resource *virs, struct efhw_nic *nic)
13619 +{
13620 + int capacity;
13621 +
13622 + EFRM_ASSERT(nic->efhw_func);
13623 +
13624 + if (virs->evq_capacity) {
13625 + capacity = choose_size(virs->evq_capacity, nic->evq_sizes);
13626 + if (capacity < 0) {
13627 + EFRM_ERR("vi_resource: bad evq size %d (supported=%x)",
13628 + virs->evq_capacity, nic->evq_sizes);
13629 + return -E2BIG;
13630 + }
13631 + virs->evq_capacity = capacity;
13632 + }
13633 + if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX]) {
13634 + capacity =
13635 + choose_size(virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX],
13636 + nic->txq_sizes);
13637 + if (capacity < 0) {
13638 + EFRM_ERR("vi_resource: bad txq size %d (supported=%x)",
13639 + virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX],
13640 + nic->txq_sizes);
13641 + return -E2BIG;
13642 + }
13643 + virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] = capacity;
13644 + }
13645 + if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]) {
13646 + capacity =
13647 + choose_size(virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX],
13648 + nic->rxq_sizes);
13649 + if (capacity < 0) {
13650 + EFRM_ERR("vi_resource: bad rxq size %d (supported=%x)",
13651 + virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX],
13652 + nic->rxq_sizes);
13653 + return -E2BIG;
13654 + }
13655 + virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX] = capacity;
13656 + }
13657 +
13658 + return 0;
13659 +}
13660 +
13661 +/* remove the reference to the event queue in this VI resource and decrement
13662 + the event queue's use count */
13663 +static inline void efrm_vi_rm_detach_evq(struct vi_resource *virs)
13664 +{
13665 + struct vi_resource *evq_virs;
13666 +
13667 + EFRM_ASSERT(virs != NULL);
13668 +
13669 + evq_virs = virs->evq_virs;
13670 +
13671 + if (evq_virs != NULL) {
13672 + virs->evq_virs = NULL;
13673 + if (evq_virs == virs) {
13674 + EFRM_TRACE("%s: " EFRM_RESOURCE_FMT
13675 + " had internal event queue ", __func__,
13676 + EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
13677 + } else {
13678 + efrm_vi_rm_drop_ref(evq_virs);
13679 + EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " had event queue "
13680 + EFRM_RESOURCE_FMT, __func__,
13681 + EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
13682 + EFRM_RESOURCE_PRI_ARG(evq_virs->rs.
13683 + rs_handle));
13684 + }
13685 + } else {
13686 + EFRM_TRACE("%s: " EFRM_RESOURCE_FMT
13687 + " had no event queue (nothing to do)",
13688 + __func__,
13689 + EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
13690 + }
13691 +}
13692 +
13693 +/*** Buffer Table allocations ********************************************/
13694 +
13695 +static int
13696 +efrm_vi_rm_alloc_or_free_buffer_table(struct vi_resource *virs, bool is_alloc)
13697 +{
13698 + uint32_t bytes;
13699 + int page_order;
13700 + int rc;
13701 +
13702 + if (!is_alloc)
13703 + goto destroy;
13704 +
13705 + if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX]) {
13706 + bytes = efrm_vi_rm_txq_bytes(virs);
13707 + page_order = get_order(bytes);
13708 + rc = efrm_buffer_table_alloc(page_order,
13709 + (virs->dmaq_buf_tbl_alloc +
13710 + EFRM_VI_RM_DMA_QUEUE_TX));
13711 + if (rc != 0) {
13712 + EFRM_TRACE
13713 + ("%s: Error %d allocating TX buffer table entry",
13714 + __func__, rc);
13715 + goto fail_txq_alloc;
13716 + }
13717 + }
13718 +
13719 + if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]) {
13720 + bytes = efrm_vi_rm_rxq_bytes(virs);
13721 + page_order = get_order(bytes);
13722 + rc = efrm_buffer_table_alloc(page_order,
13723 + (virs->dmaq_buf_tbl_alloc +
13724 + EFRM_VI_RM_DMA_QUEUE_RX));
13725 + if (rc != 0) {
13726 + EFRM_TRACE
13727 + ("%s: Error %d allocating RX buffer table entry",
13728 + __func__, rc);
13729 + goto fail_rxq_alloc;
13730 + }
13731 + }
13732 + return 0;
13733 +
13734 +destroy:
13735 + rc = 0;
13736 +
13737 + if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]) {
13738 + efrm_buffer_table_free(&virs->
13739 + dmaq_buf_tbl_alloc
13740 + [EFRM_VI_RM_DMA_QUEUE_RX]);
13741 + }
13742 +fail_rxq_alloc:
13743 +
13744 + if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX]) {
13745 + efrm_buffer_table_free(&virs->
13746 + dmaq_buf_tbl_alloc
13747 + [EFRM_VI_RM_DMA_QUEUE_TX]);
13748 + }
13749 +fail_txq_alloc:
13750 +
13751 + return rc;
13752 +}
13753 +
13754 +/*** Per-NIC allocations *************************************************/
13755 +
13756 +static inline int
13757 +efrm_vi_rm_init_evq(struct vi_resource *virs, struct efhw_nic *nic)
13758 +{
13759 + int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
13760 + struct eventq_resource_hardware *evq_hw =
13761 + &virs->nic_info.evq_pages;
13762 + uint32_t buf_bytes = efrm_vi_rm_evq_bytes(virs);
13763 + int rc;
13764 +
13765 + if (virs->evq_capacity == 0)
13766 + return 0;
13767 + evq_hw->capacity = virs->evq_capacity;
13768 +
13769 + /* Allocate buffer table entries to map onto the iobuffer. This
13770 + * currently allocates its own buffer table entries on Falcon which is
13771 + * a bit wasteful on a multi-NIC system. */
13772 + evq_hw->buf_tbl_alloc.base = (unsigned)-1;
13773 + rc = efrm_buffer_table_alloc(get_order(buf_bytes),
13774 + &evq_hw->buf_tbl_alloc);
13775 + if (rc < 0) {
13776 + EFHW_WARN("%s: failed (%d) to alloc %d buffer table entries",
13777 + __func__, rc, get_order(buf_bytes));
13778 + return rc;
13779 + }
13780 +
13781 + /* Allocate the event queue memory. */
13782 + rc = efhw_nic_event_queue_alloc_iobuffer(nic, evq_hw, instance,
13783 + buf_bytes);
13784 + if (rc != 0) {
13785 + EFRM_ERR("%s: Error allocating iobuffer: %d", __func__, rc);
13786 + efrm_buffer_table_free(&evq_hw->buf_tbl_alloc);
13787 + return rc;
13788 + }
13789 +
13790 + /* Initialise the event queue hardware */
13791 + efhw_nic_event_queue_enable(nic, instance, virs->evq_capacity,
13792 + efhw_iopages_dma_addr(&evq_hw->iobuff) +
13793 + evq_hw->iobuff_off,
13794 + evq_hw->buf_tbl_alloc.base,
13795 + instance < 64);
13796 +
13797 + EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " capacity=%u", __func__,
13798 + EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
13799 + virs->evq_capacity);
13800 +
13801 +#if defined(__ia64__)
13802 + /* Page size may be large, so for now just increase the
13803 + * size of the requested evq up to a round number of
13804 + * pages
13805 + */
13806 + buf_bytes = CI_ROUNDUP(buf_bytes, PAGE_SIZE);
13807 +#endif
13808 + EFRM_ASSERT(buf_bytes % PAGE_SIZE == 0);
13809 +
13810 + virs->mem_mmap_bytes += buf_bytes;
13811 +
13812 + return 0;
13813 +}
13814 +
13815 +static inline void
13816 +efrm_vi_rm_fini_evq(struct vi_resource *virs, struct efhw_nic *nic)
13817 +{
13818 + int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
13819 + struct vi_resource_nic_info *nic_info = &virs->nic_info;
13820 +
13821 + if (virs->evq_capacity == 0)
13822 + return;
13823 +
13824 + /* Zero the timer-value for this queue.
13825 + And Tell NIC to stop using this event queue. */
13826 + efhw_nic_event_queue_disable(nic, instance, 0);
13827 +
13828 + if (nic_info->evq_pages.buf_tbl_alloc.base != (unsigned)-1)
13829 + efrm_buffer_table_free(&nic_info->evq_pages.buf_tbl_alloc);
13830 +
13831 + efhw_iopages_free(nic, &nic_info->evq_pages.iobuff);
13832 +}
13833 +
13834 +/*! FIXME: we should make sure this number is never zero (=> unprotected) */
13835 +/*! FIXME: put this definition in a relevant header (e.g. as (evqid)+1) */
13836 +#define EFAB_EVQ_OWNER_ID(evqid) ((evqid))
13837 +
13838 +void
13839 +efrm_vi_rm_init_dmaq(struct vi_resource *virs, int queue_type,
13840 + struct efhw_nic *nic)
13841 +{
13842 + int instance;
13843 + int evq_instance;
13844 + efhw_buffer_addr_t buf_addr;
13845 +
13846 + instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
13847 + evq_instance = EFRM_RESOURCE_INSTANCE(virs->evq_virs->rs.rs_handle);
13848 +
13849 + buf_addr = virs->dmaq_buf_tbl_alloc[queue_type].base;
13850 +
13851 + if (queue_type == EFRM_VI_RM_DMA_QUEUE_TX) {
13852 + efhw_nic_dmaq_tx_q_init(nic,
13853 + instance, /* dmaq */
13854 + evq_instance, /* evq */
13855 + EFAB_EVQ_OWNER_ID(evq_instance), /* owner */
13856 + virs->dmaq_tag[queue_type], /* tag */
13857 + virs->dmaq_capacity[queue_type], /* size of queue */
13858 + buf_addr, /* buffer index */
13859 + virs->flags); /* user specified Q attrs */
13860 + } else {
13861 + efhw_nic_dmaq_rx_q_init(nic,
13862 + instance, /* dmaq */
13863 + evq_instance, /* evq */
13864 + EFAB_EVQ_OWNER_ID(evq_instance), /* owner */
13865 + virs->dmaq_tag[queue_type], /* tag */
13866 + virs->dmaq_capacity[queue_type], /* size of queue */
13867 + buf_addr, /* buffer index */
13868 + virs->flags); /* user specified Q attrs */
13869 + }
13870 +}
13871 +
13872 +static int
13873 +efrm_vi_rm_init_or_fini_dmaq(struct vi_resource *virs,
13874 + int queue_type, int init,
13875 + struct efhw_nic *nic)
13876 +{
13877 + int rc;
13878 + int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
13879 + uint32_t buf_bytes;
13880 + struct vi_resource_nic_info *nic_info = &virs->nic_info;
13881 + int page_order;
13882 + uint32_t num_pages;
13883 + struct efhw_iopages *iobuff;
13884 +
13885 + if (!init)
13886 + goto destroy;
13887 +
13888 + /* Ignore disabled queues. */
13889 + if (virs->dmaq_capacity[queue_type] == 0) {
13890 + if (queue_type == EFRM_VI_RM_DMA_QUEUE_TX)
13891 + efhw_nic_dmaq_tx_q_disable(nic, instance);
13892 + else
13893 + efhw_nic_dmaq_rx_q_disable(nic, instance);
13894 + return 0;
13895 + }
13896 +
13897 + buf_bytes = (queue_type == EFRM_VI_RM_DMA_QUEUE_TX
13898 + ? efrm_vi_rm_txq_bytes(virs)
13899 + : efrm_vi_rm_rxq_bytes(virs));
13900 +
13901 + page_order = get_order(buf_bytes);
13902 +
13903 + rc = efhw_iopages_alloc(nic, &nic_info->dmaq_pages[queue_type],
13904 + page_order);
13905 + if (rc != 0) {
13906 + EFRM_ERR("%s: Failed to allocate %s DMA buffer.", __func__,
13907 + dmaq_names[queue_type]);
13908 + goto fail_iopages;
13909 + }
13910 +
13911 + num_pages = 1 << page_order;
13912 + iobuff = &nic_info->dmaq_pages[queue_type];
13913 + efhw_nic_buffer_table_set_n(nic,
13914 + virs->dmaq_buf_tbl_alloc[queue_type].base,
13915 + efhw_iopages_dma_addr(iobuff),
13916 + EFHW_NIC_PAGE_SIZE, 0, num_pages, 0);
13917 +
13918 + falcon_nic_buffer_table_confirm(nic);
13919 +
13920 + virs->mem_mmap_bytes += roundup(buf_bytes, PAGE_SIZE);
13921 +
13922 + /* Make sure there is an event queue. */
13923 + if (virs->evq_virs->evq_capacity <= 0) {
13924 + EFRM_ERR("%s: Cannot use empty event queue for %s DMA",
13925 + __func__, dmaq_names[queue_type]);
13926 + rc = -EINVAL;
13927 + goto fail_evq;
13928 + }
13929 +
13930 + efrm_vi_rm_init_dmaq(virs, queue_type, nic);
13931 +
13932 + return 0;
13933 +
13934 +destroy:
13935 + rc = 0;
13936 +
13937 + /* Ignore disabled queues. */
13938 + if (virs->dmaq_capacity[queue_type] == 0)
13939 + return 0;
13940 +
13941 + /* Ensure TX pacing turned off -- queue flush doesn't reset this. */
13942 + if (queue_type == EFRM_VI_RM_DMA_QUEUE_TX)
13943 + falcon_nic_pace(nic, instance, 0);
13944 +
13945 + /* No need to disable the queue here. Nobody is using it anyway. */
13946 +
13947 +fail_evq:
13948 + efhw_iopages_free(nic, &nic_info->dmaq_pages[queue_type]);
13949 +fail_iopages:
13950 +
13951 + return rc;
13952 +}
13953 +
13954 +static int
13955 +efrm_vi_rm_init_or_fini_nic(struct vi_resource *virs, int init,
13956 + struct efhw_nic *nic)
13957 +{
13958 + int rc;
13959 +#ifndef NDEBUG
13960 + int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
13961 +#endif
13962 +
13963 + if (!init)
13964 + goto destroy;
13965 +
13966 + rc = efrm_vi_rm_init_evq(virs, nic);
13967 + if (rc != 0)
13968 + goto fail_evq;
13969 +
13970 + rc = efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_TX,
13971 + init, nic);
13972 + if (rc != 0)
13973 + goto fail_txq;
13974 +
13975 + rc = efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_RX,
13976 + init, nic);
13977 + if (rc != 0)
13978 + goto fail_rxq;
13979 +
13980 + /* Allocate space for the control page. */
13981 + EFRM_ASSERT(falcon_tx_dma_page_offset(instance) < PAGE_SIZE);
13982 + EFRM_ASSERT(falcon_rx_dma_page_offset(instance) < PAGE_SIZE);
13983 + EFRM_ASSERT(falcon_timer_page_offset(instance) < PAGE_SIZE);
13984 + virs->bar_mmap_bytes += PAGE_SIZE;
13985 +
13986 + return 0;
13987 +
13988 +destroy:
13989 + rc = 0;
13990 +
13991 + efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_RX,
13992 + false, nic);
13993 +fail_rxq:
13994 +
13995 + efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_TX,
13996 + false, nic);
13997 +fail_txq:
13998 +
13999 + efrm_vi_rm_fini_evq(virs, nic);
14000 +fail_evq:
14001 +
14002 + EFRM_ASSERT(rc != 0 || !init);
14003 + return rc;
14004 +}
14005 +
14006 +static int
14007 +efrm_vi_resource_alloc_or_free(struct efrm_client *client,
14008 + int alloc, struct vi_resource *evq_virs,
14009 + uint16_t vi_flags, int32_t evq_capacity,
14010 + int32_t txq_capacity, int32_t rxq_capacity,
14011 + uint8_t tx_q_tag, uint8_t rx_q_tag,
14012 + struct vi_resource **virs_in_out)
14013 +{
14014 + struct efhw_nic *nic = client->nic;
14015 + struct vi_resource *virs;
14016 + int rc;
14017 + int instance;
14018 +
14019 + EFRM_ASSERT(virs_in_out);
14020 + EFRM_ASSERT(efrm_vi_manager);
14021 + EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_vi_manager->rm);
14022 +
14023 + if (!alloc)
14024 + goto destroy;
14025 +
14026 + rx_q_tag &= (1 << TX_DESCQ_LABEL_WIDTH) - 1;
14027 + tx_q_tag &= (1 << RX_DESCQ_LABEL_WIDTH) - 1;
14028 +
14029 + virs = kmalloc(sizeof(*virs), GFP_KERNEL);
14030 + if (virs == NULL) {
14031 + EFRM_ERR("%s: Error allocating VI resource object",
14032 + __func__);
14033 + rc = -ENOMEM;
14034 + goto fail_alloc;
14035 + }
14036 + memset(virs, 0, sizeof(*virs));
14037 +
14038 + /* Some macros make the assumption that the struct efrm_resource is
14039 + * the first member of a struct vi_resource. */
14040 + EFRM_ASSERT(&virs->rs == (struct efrm_resource *) (virs));
14041 +
14042 + instance = efrm_vi_rm_alloc_id(vi_flags, evq_capacity);
14043 + if (instance < 0) {
14044 + /* Clear out the close list... */
14045 + efrm_vi_rm_salvage_flushed_vis();
14046 + instance = efrm_vi_rm_alloc_id(vi_flags, evq_capacity);
14047 + if (instance >= 0)
14048 + EFRM_TRACE("%s: Salvaged a closed VI.", __func__);
14049 + }
14050 +
14051 + if (instance < 0) {
14052 + /* Could flush resources and try again here. */
14053 + EFRM_ERR("%s: Out of appropriate VI resources", __func__);
14054 + rc = -EBUSY;
14055 + goto fail_alloc_id;
14056 + }
14057 +
14058 + EFRM_TRACE("%s: new VI ID %d", __func__, instance);
14059 + efrm_resource_init(&virs->rs, EFRM_RESOURCE_VI, instance);
14060 +
14061 + /* Start with one reference. Any external VIs using the EVQ of this
14062 + * resource will increment this reference rather than the resource
14063 + * reference to avoid DMAQ flushes from waiting for other DMAQ
14064 + * flushes to complete. When the resource reference goes to zero,
14065 + * the DMAQ flush happens. When the flush completes, this reference
14066 + * is decremented. When this reference reaches zero, the instance
14067 + * is freed. */
14068 + atomic_set(&virs->evq_refs, 1);
14069 +
14070 + virs->bar_mmap_bytes = 0;
14071 + virs->mem_mmap_bytes = 0;
14072 + virs->evq_capacity = evq_capacity;
14073 + virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] = txq_capacity;
14074 + virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX] = rxq_capacity;
14075 + virs->dmaq_tag[EFRM_VI_RM_DMA_QUEUE_TX] = tx_q_tag;
14076 + virs->dmaq_tag[EFRM_VI_RM_DMA_QUEUE_RX] = rx_q_tag;
14077 + virs->flags = vi_flags;
14078 + INIT_LIST_HEAD(&virs->tx_flush_link);
14079 + INIT_LIST_HEAD(&virs->rx_flush_link);
14080 + virs->tx_flushing = 0;
14081 + virs->rx_flushing = 0;
14082 +
14083 + /* Adjust the queue sizes. */
14084 + rc = efrm_vi_rm_adjust_alloc_request(virs, nic);
14085 + if (rc != 0)
14086 + goto fail_adjust_request;
14087 +
14088 + /* Attach the EVQ early so that we can ensure that the NIC sets
14089 + * match. */
14090 + if (evq_virs == NULL) {
14091 + evq_virs = virs;
14092 + EFRM_TRACE("%s: " EFRM_RESOURCE_FMT
14093 + " has no external event queue", __func__,
14094 + EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
14095 + } else {
14096 + /* Make sure the resource managers are the same. */
14097 + if (EFRM_RESOURCE_TYPE(evq_virs->rs.rs_handle) !=
14098 + EFRM_RESOURCE_VI) {
14099 + EFRM_ERR("%s: Mismatched owner for event queue VI "
14100 + EFRM_RESOURCE_FMT, __func__,
14101 + EFRM_RESOURCE_PRI_ARG(evq_virs->rs.rs_handle));
14102 + return -EINVAL;
14103 + }
14104 + EFRM_ASSERT(atomic_read(&evq_virs->evq_refs) != 0);
14105 + efrm_vi_rm_get_ref(evq_virs);
14106 + EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " uses event queue "
14107 + EFRM_RESOURCE_FMT,
14108 + __func__,
14109 + EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
14110 + EFRM_RESOURCE_PRI_ARG(evq_virs->rs.rs_handle));
14111 + }
14112 + virs->evq_virs = evq_virs;
14113 +
14114 + rc = efrm_vi_rm_alloc_or_free_buffer_table(virs, true);
14115 + if (rc != 0)
14116 + goto fail_buffer_table;
14117 +
14118 + rc = efrm_vi_rm_init_or_fini_nic(virs, true, nic);
14119 + if (rc != 0)
14120 + goto fail_init_nic;
14121 +
14122 + efrm_client_add_resource(client, &virs->rs);
14123 + *virs_in_out = virs;
14124 + EFRM_TRACE("%s: Allocated " EFRM_RESOURCE_FMT, __func__,
14125 + EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
14126 + return 0;
14127 +
14128 +destroy:
14129 + virs = *virs_in_out;
14130 + EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 1);
14131 + instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
14132 +
14133 + EFRM_TRACE("%s: Freeing %d", __func__,
14134 + EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle));
14135 +
14136 + /* Destroying the VI. The reference count must be zero. */
14137 + EFRM_ASSERT(atomic_read(&virs->evq_refs) == 0);
14138 +
14139 + /* The EVQ should have gone (and DMA disabled) so that this
14140 + * function can't be re-entered to destroy the EVQ VI. */
14141 + EFRM_ASSERT(virs->evq_virs == NULL);
14142 + rc = 0;
14143 +
14144 +fail_init_nic:
14145 + efrm_vi_rm_init_or_fini_nic(virs, false, nic);
14146 +
14147 + efrm_vi_rm_alloc_or_free_buffer_table(virs, false);
14148 +fail_buffer_table:
14149 +
14150 + efrm_vi_rm_detach_evq(virs);
14151 +
14152 +fail_adjust_request:
14153 +
14154 + EFRM_ASSERT(virs->evq_callback_fn == NULL);
14155 + EFRM_TRACE("%s: delete VI ID %d", __func__, instance);
14156 + efrm_vi_rm_free_id(instance);
14157 +fail_alloc_id:
14158 + if (!alloc)
14159 + efrm_client_put(virs->rs.rs_client);
14160 + EFRM_DO_DEBUG(memset(virs, 0, sizeof(*virs)));
14161 + kfree(virs);
14162 +fail_alloc:
14163 + *virs_in_out = NULL;
14164 +
14165 + return rc;
14166 +}
14167 +
14168 +/*** Resource object ****************************************************/
14169 +
14170 +int
14171 +efrm_vi_resource_alloc(struct efrm_client *client,
14172 + struct vi_resource *evq_virs,
14173 + uint16_t vi_flags, int32_t evq_capacity,
14174 + int32_t txq_capacity, int32_t rxq_capacity,
14175 + uint8_t tx_q_tag, uint8_t rx_q_tag,
14176 + struct vi_resource **virs_out,
14177 + uint32_t *out_io_mmap_bytes,
14178 + uint32_t *out_mem_mmap_bytes,
14179 + uint32_t *out_txq_capacity, uint32_t *out_rxq_capacity)
14180 +{
14181 + int rc;
14182 + EFRM_ASSERT(client != NULL);
14183 + rc = efrm_vi_resource_alloc_or_free(client, true, evq_virs, vi_flags,
14184 + evq_capacity, txq_capacity,
14185 + rxq_capacity, tx_q_tag, rx_q_tag,
14186 + virs_out);
14187 + if (rc == 0) {
14188 + if (out_io_mmap_bytes != NULL)
14189 + *out_io_mmap_bytes = (*virs_out)->bar_mmap_bytes;
14190 + if (out_mem_mmap_bytes != NULL)
14191 + *out_mem_mmap_bytes = (*virs_out)->mem_mmap_bytes;
14192 + if (out_txq_capacity != NULL)
14193 + *out_txq_capacity =
14194 + (*virs_out)->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX];
14195 + if (out_rxq_capacity != NULL)
14196 + *out_rxq_capacity =
14197 + (*virs_out)->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX];
14198 + }
14199 +
14200 + return rc;
14201 +}
14202 +EXPORT_SYMBOL(efrm_vi_resource_alloc);
14203 +
14204 +void efrm_vi_rm_free_flushed_resource(struct vi_resource *virs)
14205 +{
14206 + EFRM_ASSERT(virs != NULL);
14207 + EFRM_ASSERT(virs->rs.rs_ref_count == 0);
14208 +
14209 + EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __func__,
14210 + EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
14211 + /* release the associated event queue then drop our own reference
14212 + * count */
14213 + efrm_vi_rm_detach_evq(virs);
14214 + efrm_vi_rm_drop_ref(virs);
14215 +}
14216 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/vi_resource_event.c
14217 ===================================================================
14218 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
14219 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/vi_resource_event.c 2008-07-17 16:18:07.000000000 +0200
14220 @@ -0,0 +1,250 @@
14221 +/****************************************************************************
14222 + * Driver for Solarflare network controllers -
14223 + * resource management for Xen backend, OpenOnload, etc
14224 + * (including support for SFE4001 10GBT NIC)
14225 + *
14226 + * This file contains event handling for VI resource.
14227 + *
14228 + * Copyright 2005-2007: Solarflare Communications Inc,
14229 + * 9501 Jeronimo Road, Suite 250,
14230 + * Irvine, CA 92618, USA
14231 + *
14232 + * Developed and maintained by Solarflare Communications:
14233 + * <linux-xen-drivers@solarflare.com>
14234 + * <onload-dev@solarflare.com>
14235 + *
14236 + * Certain parts of the driver were implemented by
14237 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
14238 + * OKTET Labs Ltd, Russia,
14239 + * http://oktetlabs.ru, <info@oktetlabs.ru>
14240 + * by request of Solarflare Communications
14241 + *
14242 + *
14243 + * This program is free software; you can redistribute it and/or modify it
14244 + * under the terms of the GNU General Public License version 2 as published
14245 + * by the Free Software Foundation, incorporated herein by reference.
14246 + *
14247 + * This program is distributed in the hope that it will be useful,
14248 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14249 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14250 + * GNU General Public License for more details.
14251 + *
14252 + * You should have received a copy of the GNU General Public License
14253 + * along with this program; if not, write to the Free Software
14254 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14255 + ****************************************************************************
14256 + */
14257 +
14258 +#include <ci/efrm/nic_table.h>
14259 +#include <ci/driver/efab/hardware.h>
14260 +#include <ci/efhw/eventq.h>
14261 +#include <ci/efrm/private.h>
14262 +#include <ci/efrm/vi_resource_private.h>
14263 +#include <ci/efrm/efrm_nic.h>
14264 +#include "efrm_internal.h"
14265 +
14266 +
14267 +static inline int
14268 +efrm_eventq_bytes(struct vi_resource *virs)
14269 +{
14270 + return efrm_vi_rm_evq_bytes(virs);
14271 +}
14272 +
14273 +
14274 +static inline efhw_event_t *
14275 +efrm_eventq_base(struct vi_resource *virs)
14276 +{
14277 + struct eventq_resource_hardware *hw;
14278 + hw = &(virs->nic_info.evq_pages);
14279 + return (efhw_event_t *) (efhw_iopages_ptr(&(hw->iobuff)) +
14280 + hw->iobuff_off);
14281 +}
14282 +
14283 +
14284 +void
14285 +efrm_eventq_request_wakeup(struct vi_resource *virs, unsigned current_ptr)
14286 +{
14287 + struct efhw_nic *nic = virs->rs.rs_client->nic;
14288 + int next_i;
14289 + next_i = ((current_ptr / sizeof(efhw_event_t)) &
14290 + (virs->evq_capacity - 1));
14291 +
14292 + efhw_nic_wakeup_request(nic, efrm_eventq_dma_addr(virs), next_i,
14293 + EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle));
14294 +}
14295 +EXPORT_SYMBOL(efrm_eventq_request_wakeup);
14296 +
14297 +void efrm_eventq_reset(struct vi_resource *virs)
14298 +{
14299 + struct efhw_nic *nic = virs->rs.rs_client->nic;
14300 + int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
14301 +
14302 + EFRM_ASSERT(virs->evq_capacity != 0);
14303 +
14304 + /* FIXME: Protect against concurrent resets. */
14305 +
14306 + efhw_nic_event_queue_disable(nic, instance, 0);
14307 +
14308 + memset(efrm_eventq_base(virs), EFHW_CLEAR_EVENT_VALUE,
14309 + efrm_eventq_bytes(virs));
14310 + efhw_nic_event_queue_enable(nic, instance, virs->evq_capacity,
14311 + efrm_eventq_dma_addr(virs),
14312 + virs->nic_info.evq_pages.
14313 + buf_tbl_alloc.base,
14314 + instance < 64);
14315 + EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __func__,
14316 + EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
14317 +}
14318 +EXPORT_SYMBOL(efrm_eventq_reset);
14319 +
14320 +int
14321 +efrm_eventq_register_callback(struct vi_resource *virs,
14322 + void (*handler) (void *, int,
14323 + struct efhw_nic *nic),
14324 + void *arg)
14325 +{
14326 + struct efrm_nic_per_vi *cb_info;
14327 + int instance;
14328 + int bit;
14329 +
14330 + EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0);
14331 + EFRM_ASSERT(virs->evq_capacity != 0);
14332 + EFRM_ASSERT(handler != NULL);
14333 +
14334 + /* ?? TODO: Get rid of this test when client is compulsory. */
14335 + if (virs->rs.rs_client == NULL) {
14336 + EFRM_ERR("%s: no client", __func__);
14337 + return -EINVAL;
14338 + }
14339 +
14340 + virs->evq_callback_arg = arg;
14341 + virs->evq_callback_fn = handler;
14342 + instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
14343 + cb_info = &efrm_nic(virs->rs.rs_client->nic)->vis[instance];
14344 +
14345 + /* The handler can be set only once. */
14346 + bit = test_and_set_bit(VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED,
14347 + &cb_info->state);
14348 + if (bit)
14349 + return -EBUSY;
14350 + cb_info->vi = virs;
14351 +
14352 + return 0;
14353 +}
14354 +EXPORT_SYMBOL(efrm_eventq_register_callback);
14355 +
14356 +void efrm_eventq_kill_callback(struct vi_resource *virs)
14357 +{
14358 + struct efrm_nic_per_vi *cb_info;
14359 + int32_t evq_state;
14360 + int instance;
14361 + int bit;
14362 +
14363 + EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0);
14364 + EFRM_ASSERT(virs->evq_capacity != 0);
14365 + EFRM_ASSERT(virs->rs.rs_client != NULL);
14366 +
14367 + instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
14368 + cb_info = &efrm_nic(virs->rs.rs_client->nic)->vis[instance];
14369 + cb_info->vi = NULL;
14370 +
14371 + /* Disable the timer. */
14372 + efhw_nic_event_queue_disable(virs->rs.rs_client->nic,
14373 + instance, /*timer_only */ 1);
14374 +
14375 + /* Disable the callback. */
14376 + bit = test_and_clear_bit(VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED,
14377 + &cb_info->state);
14378 + EFRM_ASSERT(bit); /* do not call me twice! */
14379 +
14380 + /* Spin until the callback is complete. */
14381 + do {
14382 + rmb();
14383 +
14384 + udelay(1);
14385 + evq_state = cb_info->state;
14386 + } while ((evq_state & VI_RESOURCE_EVQ_STATE(BUSY)));
14387 +
14388 + virs->evq_callback_fn = NULL;
14389 +}
14390 +EXPORT_SYMBOL(efrm_eventq_kill_callback);
14391 +
14392 +static void
14393 +efrm_eventq_do_callback(struct efhw_nic *nic, unsigned instance,
14394 + bool is_timeout)
14395 +{
14396 + struct efrm_nic *rnic = efrm_nic(nic);
14397 + void (*handler) (void *, int is_timeout, struct efhw_nic *nic);
14398 + void *arg;
14399 + struct efrm_nic_per_vi *cb_info;
14400 + int32_t evq_state;
14401 + int32_t new_evq_state;
14402 + struct vi_resource *virs;
14403 + int bit;
14404 +
14405 + EFRM_ASSERT(efrm_vi_manager);
14406 +
14407 + cb_info = &rnic->vis[instance];
14408 +
14409 + /* Set the BUSY bit and clear WAKEUP_PENDING. Do this
14410 + * before waking up the sleeper to avoid races. */
14411 + while (1) {
14412 + evq_state = cb_info->state;
14413 + new_evq_state = evq_state;
14414 +
14415 + if ((evq_state & VI_RESOURCE_EVQ_STATE(BUSY)) != 0) {
14416 + EFRM_ERR("%s:%d: evq_state[%d] corrupted!",
14417 + __func__, __LINE__, instance);
14418 + return;
14419 + }
14420 +
14421 + if (!is_timeout)
14422 + new_evq_state &= ~VI_RESOURCE_EVQ_STATE(WAKEUP_PENDING);
14423 +
14424 + if (evq_state & VI_RESOURCE_EVQ_STATE(CALLBACK_REGISTERED)) {
14425 + new_evq_state |= VI_RESOURCE_EVQ_STATE(BUSY);
14426 + virs = cb_info->vi;
14427 + if (cmpxchg(&cb_info->state, evq_state,
14428 + new_evq_state) == evq_state)
14429 + break;
14430 + } else {
14431 + /* Just update the state if necessary. */
14432 + if (new_evq_state == evq_state ||
14433 + cmpxchg(&cb_info->state, evq_state,
14434 + new_evq_state) == evq_state)
14435 + return;
14436 + }
14437 + }
14438 +
14439 + if (virs) {
14440 + handler = virs->evq_callback_fn;
14441 + arg = virs->evq_callback_arg;
14442 + EFRM_ASSERT(handler != NULL);
14443 + handler(arg, is_timeout, nic);
14444 + }
14445 +
14446 + /* Clear the BUSY bit. */
14447 + bit =
14448 + test_and_clear_bit(VI_RESOURCE_EVQ_STATE_BUSY,
14449 + &cb_info->state);
14450 + if (!bit) {
14451 + EFRM_ERR("%s:%d: evq_state corrupted!",
14452 + __func__, __LINE__);
14453 + }
14454 +}
14455 +
14456 +void efrm_handle_wakeup_event(struct efhw_nic *nic, unsigned instance)
14457 +{
14458 + efrm_eventq_do_callback(nic, instance, false);
14459 +}
14460 +
14461 +void efrm_handle_timeout_event(struct efhw_nic *nic, unsigned instance)
14462 +{
14463 + efrm_eventq_do_callback(nic, instance, true);
14464 +}
14465 +
14466 +void efrm_handle_sram_event(struct efhw_nic *nic)
14467 +{
14468 + if (nic->buf_commit_outstanding > 0)
14469 + nic->buf_commit_outstanding--;
14470 +}
14471 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/vi_resource_flush.c
14472 ===================================================================
14473 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
14474 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/vi_resource_flush.c 2008-07-17 16:18:07.000000000 +0200
14475 @@ -0,0 +1,483 @@
14476 +/****************************************************************************
14477 + * Driver for Solarflare network controllers -
14478 + * resource management for Xen backend, OpenOnload, etc
14479 + * (including support for SFE4001 10GBT NIC)
14480 + *
14481 + * This file contains DMA queue flushing of VI resources.
14482 + *
14483 + * Copyright 2005-2007: Solarflare Communications Inc,
14484 + * 9501 Jeronimo Road, Suite 250,
14485 + * Irvine, CA 92618, USA
14486 + *
14487 + * Developed and maintained by Solarflare Communications:
14488 + * <linux-xen-drivers@solarflare.com>
14489 + * <onload-dev@solarflare.com>
14490 + *
14491 + * Certain parts of the driver were implemented by
14492 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
14493 + * OKTET Labs Ltd, Russia,
14494 + * http://oktetlabs.ru, <info@oktetlabs.ru>
14495 + * by request of Solarflare Communications
14496 + *
14497 + *
14498 + * This program is free software; you can redistribute it and/or modify it
14499 + * under the terms of the GNU General Public License version 2 as published
14500 + * by the Free Software Foundation, incorporated herein by reference.
14501 + *
14502 + * This program is distributed in the hope that it will be useful,
14503 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14504 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14505 + * GNU General Public License for more details.
14506 + *
14507 + * You should have received a copy of the GNU General Public License
14508 + * along with this program; if not, write to the Free Software
14509 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14510 + ****************************************************************************
14511 + */
14512 +
14513 +#include <ci/efrm/nic_table.h>
14514 +#include <ci/driver/efab/hardware.h>
14515 +#include <ci/efhw/falcon.h>
14516 +#include <ci/efrm/private.h>
14517 +#include <ci/efrm/sysdep.h>
14518 +#include <ci/efrm/buffer_table.h>
14519 +#include <ci/efrm/vi_resource_private.h>
14520 +#include "efrm_internal.h"
14521 +
14522 +
14523 +/* can fail as workitem can already be scheuled -- ignore failure */
14524 +#define EFRM_VI_RM_DELAYED_FREE(manager) \
14525 + queue_work(manager->workqueue, &manager->work_item)
14526 +
14527 +static const int flush_fifo_hwm = 8 /* TODO should be a HW specific const */ ;
14528 +
14529 +static void
14530 +efrm_vi_resource_rx_flush_done(struct vi_resource *virs, bool *completed)
14531 +{
14532 + /* We should only get a flush event if there is a flush
14533 + * outstanding. */
14534 + EFRM_ASSERT(virs->rx_flush_outstanding);
14535 +
14536 + virs->rx_flush_outstanding = 0;
14537 + virs->rx_flushing = 0;
14538 +
14539 + list_del(&virs->rx_flush_link);
14540 + efrm_vi_manager->rx_flush_outstanding_count--;
14541 +
14542 + if (virs->tx_flushing == 0) {
14543 + list_add_tail(&virs->rx_flush_link,
14544 + &efrm_vi_manager->close_pending);
14545 + *completed = 1;
14546 + }
14547 +}
14548 +
14549 +static void
14550 +efrm_vi_resource_tx_flush_done(struct vi_resource *virs, bool *completed)
14551 +{
14552 + /* We should only get a flush event if there is a flush
14553 + * outstanding. */
14554 + EFRM_ASSERT(virs->tx_flushing);
14555 +
14556 + virs->tx_flushing = 0;
14557 +
14558 + list_del(&virs->tx_flush_link);
14559 +
14560 + if (virs->rx_flushing == 0) {
14561 + list_add_tail(&virs->rx_flush_link,
14562 + &efrm_vi_manager->close_pending);
14563 + *completed = 1;
14564 + }
14565 +}
14566 +
14567 +static void
14568 +efrm_vi_resource_issue_rx_flush(struct vi_resource *virs, bool *completed)
14569 +{
14570 + struct efhw_nic *nic = virs->rs.rs_client->nic;
14571 + int instance;
14572 + int rc;
14573 +
14574 + instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
14575 +
14576 + list_add_tail(&virs->rx_flush_link,
14577 + &efrm_vi_manager->rx_flush_outstanding_list);
14578 + virs->rx_flush_outstanding = virs->rx_flushing;
14579 + efrm_vi_manager->rx_flush_outstanding_count++;
14580 +
14581 + EFRM_TRACE("%s: rx queue %d flush requested for nic %d",
14582 + __func__, instance, nic->index);
14583 + rc = efhw_nic_flush_rx_dma_channel(nic, instance);
14584 + if (rc == -EAGAIN)
14585 + efrm_vi_resource_rx_flush_done(virs, completed);
14586 +}
14587 +
14588 +static void
14589 +efrm_vi_resource_issue_tx_flush(struct vi_resource *virs, bool *completed)
14590 +{
14591 + struct efhw_nic *nic = virs->rs.rs_client->nic;
14592 + int instance;
14593 + int rc;
14594 +
14595 + instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
14596 +
14597 + list_add_tail(&virs->tx_flush_link,
14598 + &efrm_vi_manager->tx_flush_outstanding_list);
14599 +
14600 + EFRM_TRACE("%s: tx queue %d flush requested for nic %d",
14601 + __func__, instance, nic->index);
14602 + rc = efhw_nic_flush_tx_dma_channel(nic, instance);
14603 + if (rc == -EAGAIN)
14604 + efrm_vi_resource_tx_flush_done(virs, completed);
14605 +}
14606 +
14607 +static void efrm_vi_resource_process_waiting_flushes(bool *completed)
14608 +{
14609 + struct vi_resource *virs;
14610 +
14611 + while (efrm_vi_manager->rx_flush_outstanding_count < flush_fifo_hwm &&
14612 + !list_empty(&efrm_vi_manager->rx_flush_waiting_list)) {
14613 + virs =
14614 + list_entry(list_pop
14615 + (&efrm_vi_manager->rx_flush_waiting_list),
14616 + struct vi_resource, rx_flush_link);
14617 + efrm_vi_resource_issue_rx_flush(virs, completed);
14618 + }
14619 +}
14620 +
14621 +#if BUG7916_WORKAROUND || BUG5302_WORKAROUND
14622 +static void
14623 +efrm_vi_resource_flush_retry_vi(struct vi_resource *virs,
14624 + int64_t time_now, bool *completed)
14625 +{
14626 + struct efhw_nic *nic;
14627 + int instance;
14628 +
14629 + instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
14630 +
14631 + virs->flush_count++;
14632 + virs->flush_time = time_now;
14633 + nic = virs->rs.rs_client->nic;
14634 +
14635 +#if BUG7916_WORKAROUND
14636 + if (virs->rx_flush_outstanding) {
14637 + EFRM_TRACE("%s: Retrying RX flush on instance %d",
14638 + __func__, instance);
14639 +
14640 + list_del(&virs->rx_flush_link);
14641 + efrm_vi_manager->rx_flush_outstanding_count--;
14642 + efrm_vi_resource_issue_rx_flush(virs, completed);
14643 + efrm_vi_resource_process_waiting_flushes(completed);
14644 + }
14645 +#endif
14646 +
14647 +#if BUG5302_WORKAROUND
14648 + if (virs->tx_flushing) {
14649 + if (virs->flush_count > 5) {
14650 + EFRM_TRACE("%s: VI resource stuck flush pending "
14651 + "(instance=%d, count=%d)",
14652 + __func__, instance, virs->flush_count);
14653 + falcon_clobber_tx_dma_ptrs(nic, instance);
14654 + } else {
14655 + EFRM_TRACE("%s: Retrying TX flush on instance %d",
14656 + __func__, instance);
14657 + }
14658 +
14659 + list_del(&virs->tx_flush_link);
14660 + efrm_vi_resource_issue_tx_flush(virs, completed);
14661 + }
14662 +#endif
14663 +}
14664 +#endif
14665 +
14666 +int efrm_vi_resource_flush_retry(struct vi_resource *virs)
14667 +{
14668 +#if BUG7916_WORKAROUND || BUG5302_WORKAROUND
14669 + irq_flags_t lock_flags;
14670 + bool completed = false;
14671 +
14672 + if (virs->rx_flushing == 0 && virs->tx_flushing == 0)
14673 + return -EALREADY;
14674 +
14675 + spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
14676 + efrm_vi_resource_flush_retry_vi(virs, get_jiffies_64(), &completed);
14677 + spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
14678 +
14679 + if (completed)
14680 + EFRM_VI_RM_DELAYED_FREE(efrm_vi_manager);
14681 +#endif
14682 +
14683 + return 0;
14684 +}
14685 +EXPORT_SYMBOL(efrm_vi_resource_flush_retry);
14686 +
14687 +#if BUG7916_WORKAROUND || BUG5302_WORKAROUND
14688 +/* resource manager lock should be taken before this call */
14689 +static void efrm_vi_handle_flush_loss(bool *completed)
14690 +{
14691 + struct list_head *pos, *temp;
14692 + struct vi_resource *virs;
14693 + int64_t time_now, time_pending;
14694 +
14695 + /* It's possible we miss flushes - the list is sorted in order we
14696 + * generate flushes, see if any are very old. It's also possible
14697 + * that we decide an endpoint is flushed even though we've not
14698 + * received all the flush events. We *should * mark as
14699 + * completed, reclaim and loop again. ??
14700 + * THIS NEEDS BACKPORTING FROM THE FALCON branch
14701 + */
14702 + time_now = get_jiffies_64();
14703 +
14704 +#if BUG7916_WORKAROUND
14705 + list_for_each_safe(pos, temp,
14706 + &efrm_vi_manager->rx_flush_outstanding_list) {
14707 + virs = container_of(pos, struct vi_resource, rx_flush_link);
14708 +
14709 + time_pending = time_now - virs->flush_time;
14710 +
14711 + /* List entries are held in reverse chronological order. Only
14712 + * process the old ones. */
14713 + if (time_pending <= 0x100000000LL)
14714 + break;
14715 +
14716 + efrm_vi_resource_flush_retry_vi(virs, time_now, completed);
14717 + }
14718 +#endif
14719 +
14720 +#if BUG5302_WORKAROUND
14721 + list_for_each_safe(pos, temp,
14722 + &efrm_vi_manager->tx_flush_outstanding_list) {
14723 + virs = container_of(pos, struct vi_resource, tx_flush_link);
14724 +
14725 + time_pending = time_now - virs->flush_time;
14726 +
14727 + /* List entries are held in reverse chronological order.
14728 + * Only process the old ones. */
14729 + if (time_pending <= 0x100000000LL)
14730 + break;
14731 +
14732 + efrm_vi_resource_flush_retry_vi(virs, time_now, completed);
14733 + }
14734 +#endif
14735 +}
14736 +#endif
14737 +
14738 +void
14739 +efrm_vi_register_flush_callback(struct vi_resource *virs,
14740 + void (*handler)(void *), void *arg)
14741 +{
14742 + if (handler == NULL) {
14743 + virs->flush_callback_fn = handler;
14744 + wmb();
14745 + virs->flush_callback_arg = arg;
14746 + } else {
14747 + virs->flush_callback_arg = arg;
14748 + wmb();
14749 + virs->flush_callback_fn = handler;
14750 + }
14751 +}
14752 +EXPORT_SYMBOL(efrm_vi_register_flush_callback);
14753 +
14754 +int efrm_pt_flush(struct vi_resource *virs)
14755 +{
14756 + int instance;
14757 + irq_flags_t lock_flags;
14758 + bool completed = false;
14759 +
14760 + instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
14761 +
14762 + EFRM_ASSERT(virs->rx_flushing == 0);
14763 + EFRM_ASSERT(virs->rx_flush_outstanding == 0);
14764 + EFRM_ASSERT(virs->tx_flushing == 0);
14765 +
14766 + EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " EVQ=%d TXQ=%d RXQ=%d",
14767 + __func__, EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
14768 + virs->evq_capacity,
14769 + virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX],
14770 + virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]);
14771 +
14772 + spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
14773 +
14774 + if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX] != 0)
14775 + virs->rx_flushing = 1;
14776 +
14777 + if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] != 0)
14778 + virs->tx_flushing = 1;
14779 +
14780 + /* Clean up immediately if there are no flushes. */
14781 + if (virs->rx_flushing == 0 && virs->tx_flushing == 0) {
14782 + list_add_tail(&virs->rx_flush_link,
14783 + &efrm_vi_manager->close_pending);
14784 + completed = true;
14785 + }
14786 +
14787 + /* Issue the RX flush if possible or queue it for later. */
14788 + if (virs->rx_flushing) {
14789 +#if BUG7916_WORKAROUND || BUG5302_WORKAROUND
14790 + if (efrm_vi_manager->rx_flush_outstanding_count >=
14791 + flush_fifo_hwm)
14792 + efrm_vi_handle_flush_loss(&completed);
14793 +#endif
14794 + if (efrm_vi_manager->rx_flush_outstanding_count >=
14795 + flush_fifo_hwm) {
14796 + list_add_tail(&virs->rx_flush_link,
14797 + &efrm_vi_manager->rx_flush_waiting_list);
14798 + } else {
14799 + efrm_vi_resource_issue_rx_flush(virs, &completed);
14800 + }
14801 + }
14802 +
14803 + /* Issue the TX flush. There's no limit to the number of
14804 + * outstanding TX flushes. */
14805 + if (virs->tx_flushing)
14806 + efrm_vi_resource_issue_tx_flush(virs, &completed);
14807 +
14808 + virs->flush_time = get_jiffies_64();
14809 +
14810 + spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
14811 +
14812 + if (completed)
14813 + EFRM_VI_RM_DELAYED_FREE(efrm_vi_manager);
14814 +
14815 + return 0;
14816 +}
14817 +EXPORT_SYMBOL(efrm_pt_flush);
14818 +
14819 +static void
14820 +efrm_handle_rx_dmaq_flushed(struct efhw_nic *flush_nic, int instance,
14821 + bool *completed)
14822 +{
14823 + struct list_head *pos, *temp;
14824 + struct vi_resource *virs;
14825 +
14826 + list_for_each_safe(pos, temp,
14827 + &efrm_vi_manager->rx_flush_outstanding_list) {
14828 + virs = container_of(pos, struct vi_resource, rx_flush_link);
14829 +
14830 + if (instance == EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle)) {
14831 + efrm_vi_resource_rx_flush_done(virs, completed);
14832 + efrm_vi_resource_process_waiting_flushes(completed);
14833 + return;
14834 + }
14835 + }
14836 + EFRM_TRACE("%s: Unhandled rx flush event, nic %d, instance %d",
14837 + __func__, flush_nic->index, instance);
14838 +}
14839 +
14840 +static void
14841 +efrm_handle_tx_dmaq_flushed(struct efhw_nic *flush_nic, int instance,
14842 + bool *completed)
14843 +{
14844 + struct list_head *pos, *temp;
14845 + struct vi_resource *virs;
14846 +
14847 + list_for_each_safe(pos, temp,
14848 + &efrm_vi_manager->tx_flush_outstanding_list) {
14849 + virs = container_of(pos, struct vi_resource, tx_flush_link);
14850 +
14851 + if (instance == EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle)) {
14852 + efrm_vi_resource_tx_flush_done(virs, completed);
14853 + return;
14854 + }
14855 + }
14856 + EFRM_TRACE("%s: Unhandled tx flush event, nic %d, instance %d",
14857 + __func__, flush_nic->index, instance);
14858 +}
14859 +
14860 +void
14861 +efrm_handle_dmaq_flushed(struct efhw_nic *flush_nic, unsigned instance,
14862 + int rx_flush)
14863 +{
14864 + irq_flags_t lock_flags;
14865 + bool completed = false;
14866 +
14867 + EFRM_TRACE("%s: nic_i=%d instance=%d rx_flush=%d", __func__,
14868 + flush_nic->index, instance, rx_flush);
14869 +
14870 + spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
14871 +
14872 + if (rx_flush)
14873 + efrm_handle_rx_dmaq_flushed(flush_nic, instance, &completed);
14874 + else
14875 + efrm_handle_tx_dmaq_flushed(flush_nic, instance, &completed);
14876 +
14877 +#if BUG7916_WORKAROUND || BUG5302_WORKAROUND
14878 + efrm_vi_handle_flush_loss(&completed);
14879 +#endif
14880 +
14881 + spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
14882 +
14883 + if (completed)
14884 + EFRM_VI_RM_DELAYED_FREE(efrm_vi_manager);
14885 +}
14886 +
14887 +static void
14888 +efrm_vi_rm_reinit_dmaqs(struct vi_resource *virs)
14889 +{
14890 + struct efhw_nic *nic = virs->rs.rs_client->nic;
14891 +
14892 + if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] != 0)
14893 + efrm_vi_rm_init_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_TX, nic);
14894 + if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX])
14895 + efrm_vi_rm_init_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_RX, nic);
14896 +}
14897 +
14898 +/* free any PT endpoints whose flush has now complete */
14899 +void efrm_vi_rm_delayed_free(struct work_struct *data)
14900 +{
14901 + irq_flags_t lock_flags;
14902 + struct list_head close_pending;
14903 + struct vi_resource *virs;
14904 +
14905 + EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_vi_manager->rm);
14906 +
14907 + spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
14908 + list_replace_init(&efrm_vi_manager->close_pending, &close_pending);
14909 + spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
14910 +
14911 + EFRM_TRACE("%s: %p", __func__, efrm_vi_manager);
14912 + while (!list_empty(&close_pending)) {
14913 + virs =
14914 + list_entry(list_pop(&close_pending), struct vi_resource,
14915 + rx_flush_link);
14916 + EFRM_TRACE("%s: flushed VI instance=%d", __func__,
14917 + EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle));
14918 +
14919 + if (virs->flush_callback_fn != NULL) {
14920 + efrm_vi_rm_reinit_dmaqs(virs);
14921 + virs->flush_callback_fn(virs->flush_callback_arg);
14922 + } else
14923 + efrm_vi_rm_free_flushed_resource(virs);
14924 + }
14925 +}
14926 +
14927 +void efrm_vi_rm_salvage_flushed_vis(void)
14928 +{
14929 +#if BUG7916_WORKAROUND || BUG5302_WORKAROUND
14930 + irq_flags_t lock_flags;
14931 + bool completed;
14932 +
14933 + spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
14934 + efrm_vi_handle_flush_loss(&completed);
14935 + spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
14936 +#endif
14937 +
14938 + efrm_vi_rm_delayed_free(&efrm_vi_manager->work_item);
14939 +}
14940 +
14941 +void efrm_vi_resource_free(struct vi_resource *virs)
14942 +{
14943 + efrm_vi_register_flush_callback(virs, NULL, NULL);
14944 + efrm_pt_flush(virs);
14945 +}
14946 +EXPORT_SYMBOL(efrm_vi_resource_free);
14947 +
14948 +
14949 +void efrm_vi_resource_release(struct vi_resource *virs)
14950 +{
14951 + if (__efrm_resource_release(&virs->rs))
14952 + efrm_vi_resource_free(virs);
14953 +}
14954 +EXPORT_SYMBOL(efrm_vi_resource_release);
14955 +
14956 +/*
14957 + * vi: sw=8:ai:aw
14958 + */
14959 Index: head-2008-07-15/drivers/net/sfc/sfc_resource/vi_resource_manager.c
14960 ===================================================================
14961 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
14962 +++ head-2008-07-15/drivers/net/sfc/sfc_resource/vi_resource_manager.c 2008-07-17 16:18:07.000000000 +0200
14963 @@ -0,0 +1,231 @@
14964 +/****************************************************************************
14965 + * Driver for Solarflare network controllers -
14966 + * resource management for Xen backend, OpenOnload, etc
14967 + * (including support for SFE4001 10GBT NIC)
14968 + *
14969 + * This file contains the VI resource manager.
14970 + *
14971 + * Copyright 2005-2007: Solarflare Communications Inc,
14972 + * 9501 Jeronimo Road, Suite 250,
14973 + * Irvine, CA 92618, USA
14974 + *
14975 + * Developed and maintained by Solarflare Communications:
14976 + * <linux-xen-drivers@solarflare.com>
14977 + * <onload-dev@solarflare.com>
14978 + *
14979 + * Certain parts of the driver were implemented by
14980 + * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
14981 + * OKTET Labs Ltd, Russia,
14982 + * http://oktetlabs.ru, <info@oktetlabs.ru>
14983 + * by request of Solarflare Communications
14984 + *
14985 + *
14986 + * This program is free software; you can redistribute it and/or modify it
14987 + * under the terms of the GNU General Public License version 2 as published
14988 + * by the Free Software Foundation, incorporated herein by reference.
14989 + *
14990 + * This program is distributed in the hope that it will be useful,
14991 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14992 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14993 + * GNU General Public License for more details.
14994 + *
14995 + * You should have received a copy of the GNU General Public License
14996 + * along with this program; if not, write to the Free Software
14997 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14998 + ****************************************************************************
14999 + */
15000 +
15001 +#include <ci/efrm/nic_table.h>
15002 +#include <ci/driver/efab/hardware.h>
15003 +#include <ci/efhw/falcon.h>
15004 +#include <ci/efrm/private.h>
15005 +#include <ci/efrm/vi_resource_private.h>
15006 +#include "efrm_internal.h"
15007 +
15008 +
15009 +int efrm_pt_pace(struct vi_resource *virs, unsigned int val)
15010 +{
15011 + struct efhw_nic *nic = virs->rs.rs_client->nic;
15012 + int instance;
15013 +
15014 + EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0);
15015 + instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
15016 + falcon_nic_pace(nic, instance, val);
15017 + EFRM_TRACE("%s[%d]=%d DONE", __func__, instance, val);
15018 + return 0;
15019 +}
15020 +EXPORT_SYMBOL(efrm_pt_pace);
15021 +
15022 +/*** Resource manager creation/destruction *******************************/
15023 +
15024 +static void efrm_vi_rm_dtor(struct efrm_resource_manager *rm);
15025 +
15026 +static int
15027 +efrm_create_or_destroy_vi_resource_manager(
15028 + struct efrm_resource_manager **rm_in_out,
15029 + const struct vi_resource_dimensions *dims,
15030 + bool destroy)
15031 +{
15032 + struct vi_resource *virs;
15033 + struct list_head *pos, *temp;
15034 + struct list_head flush_pending;
15035 + irq_flags_t lock_flags;
15036 + int rc;
15037 + unsigned dmaq_min, dmaq_lim;
15038 +
15039 + EFRM_ASSERT(rm_in_out);
15040 +
15041 + if (destroy)
15042 + goto destroy;
15043 +
15044 + EFRM_ASSERT(dims);
15045 + EFRM_NOTICE("vi_resource_manager: evq_int=%u-%u evq_timer=%u-%u",
15046 + dims->evq_int_min, dims->evq_int_lim,
15047 + dims->evq_timer_min, dims->evq_timer_lim);
15048 + EFRM_NOTICE("vi_resource_manager: rxq=%u-%u txq=%u-%u",
15049 + dims->rxq_min, dims->rxq_lim,
15050 + dims->txq_min, dims->txq_lim);
15051 +
15052 + efrm_vi_manager = kmalloc(sizeof(*efrm_vi_manager), GFP_KERNEL);
15053 + if (efrm_vi_manager == NULL) {
15054 + rc = -ENOMEM;
15055 + goto fail_alloc;
15056 + }
15057 +
15058 + memset(efrm_vi_manager, 0, sizeof(*efrm_vi_manager));
15059 +
15060 + efrm_vi_manager->iscsi_dmaq_instance_is_free = true;
15061 +
15062 + dmaq_min = max(dims->rxq_min, dims->txq_min);
15063 + dmaq_lim = min(dims->rxq_lim, dims->txq_lim);
15064 +
15065 + efrm_vi_manager->with_timer_base =
15066 + max(dmaq_min, dims->evq_timer_min);
15067 + efrm_vi_manager->with_timer_limit =
15068 + min(dmaq_lim, dims->evq_timer_lim);
15069 + rc = efrm_kfifo_id_ctor(&efrm_vi_manager->instances_with_timer,
15070 + efrm_vi_manager->with_timer_base,
15071 + efrm_vi_manager->with_timer_limit,
15072 + &efrm_vi_manager->rm.rm_lock);
15073 + if (rc < 0)
15074 + goto fail_with_timer_id_pool;
15075 +
15076 + efrm_vi_manager->with_interrupt_base =
15077 + max(dmaq_min, dims->evq_int_min);
15078 + efrm_vi_manager->with_interrupt_limit =
15079 + min(dmaq_lim, dims->evq_int_lim);
15080 + efrm_vi_manager->with_interrupt_limit =
15081 + max(efrm_vi_manager->with_interrupt_limit,
15082 + efrm_vi_manager->with_interrupt_base);
15083 + rc = efrm_kfifo_id_ctor(&efrm_vi_manager->instances_with_interrupt,
15084 + efrm_vi_manager->with_interrupt_base,
15085 + efrm_vi_manager->with_interrupt_limit,
15086 + &efrm_vi_manager->rm.rm_lock);
15087 + if (rc < 0)
15088 + goto fail_with_int_id_pool;
15089 +
15090 + INIT_LIST_HEAD(&efrm_vi_manager->rx_flush_waiting_list);
15091 + INIT_LIST_HEAD(&efrm_vi_manager->rx_flush_outstanding_list);
15092 + INIT_LIST_HEAD(&efrm_vi_manager->tx_flush_outstanding_list);
15093 + efrm_vi_manager->rx_flush_outstanding_count = 0;
15094 +
15095 + INIT_LIST_HEAD(&efrm_vi_manager->close_pending);
15096 + efrm_vi_manager->workqueue = create_workqueue("sfc_vi");
15097 + if (efrm_vi_manager->workqueue == NULL)
15098 + goto fail_create_workqueue;
15099 + INIT_WORK(&efrm_vi_manager->work_item, efrm_vi_rm_delayed_free);
15100 +
15101 + /* NB. This must be the last step to avoid things getting tangled.
15102 + * efrm_resource_manager_dtor calls the vi_rm_dtor which ends up in
15103 + * this function. */
15104 + rc = efrm_resource_manager_ctor(&efrm_vi_manager->rm, efrm_vi_rm_dtor,
15105 + "VI", EFRM_RESOURCE_VI);
15106 + if (rc < 0)
15107 + goto fail_rm_ctor;
15108 +
15109 + *rm_in_out = &efrm_vi_manager->rm;
15110 + return 0;
15111 +
15112 +destroy:
15113 + rc = 0;
15114 + EFRM_RESOURCE_MANAGER_ASSERT_VALID(*rm_in_out);
15115 +
15116 + /* Abort outstanding flushes. Note, a VI resource can be on more
15117 + * than one of these lists. We handle this by starting with the TX
15118 + * list and then append VIs to this list if they aren't on the TX
15119 + * list already. A VI is on the TX flush list if tx_flushing
15120 + * is not empty. */
15121 + spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags);
15122 +
15123 + list_replace_init(&efrm_vi_manager->tx_flush_outstanding_list,
15124 + &flush_pending);
15125 +
15126 + list_for_each_safe(pos, temp,
15127 + &efrm_vi_manager->rx_flush_waiting_list) {
15128 + virs = container_of(pos, struct vi_resource, rx_flush_link);
15129 +
15130 + list_del(&virs->rx_flush_link);
15131 + if (virs->tx_flushing == 0)
15132 + list_add_tail(&virs->tx_flush_link, &flush_pending);
15133 + }
15134 +
15135 + list_for_each_safe(pos, temp,
15136 + &efrm_vi_manager->rx_flush_outstanding_list) {
15137 + virs = container_of(pos, struct vi_resource, rx_flush_link);
15138 +
15139 + list_del(&virs->rx_flush_link);
15140 + if (virs->tx_flushing == 0)
15141 + list_add_tail(&virs->tx_flush_link, &flush_pending);
15142 + }
15143 +
15144 + spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags);
15145 +
15146 + while (!list_empty(&flush_pending)) {
15147 + virs =
15148 + list_entry(list_pop(&flush_pending), struct vi_resource,
15149 + tx_flush_link);
15150 + EFRM_TRACE("%s: found PT endpoint " EFRM_RESOURCE_FMT
15151 + " with flush pending [Tx=0x%x, Rx=0x%x, RxO=0x%x]",
15152 + __func__,
15153 + EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
15154 + virs->tx_flushing,
15155 + virs->rx_flushing,
15156 + virs->rx_flush_outstanding);
15157 + efrm_vi_rm_free_flushed_resource(virs);
15158 + }
15159 +
15160 +fail_rm_ctor:
15161 +
15162 + /* Complete outstanding closes. */
15163 + destroy_workqueue(efrm_vi_manager->workqueue);
15164 +fail_create_workqueue:
15165 + EFRM_ASSERT(list_empty(&efrm_vi_manager->close_pending));
15166 + kfifo_vfree(efrm_vi_manager->instances_with_interrupt);
15167 +fail_with_int_id_pool:
15168 +
15169 + kfifo_vfree(efrm_vi_manager->instances_with_timer);
15170 +fail_with_timer_id_pool:
15171 +
15172 + if (destroy)
15173 + return 0;
15174 +
15175 + EFRM_DO_DEBUG(memset(efrm_vi_manager, 0, sizeof(*efrm_vi_manager)));
15176 + kfree(efrm_vi_manager);
15177 +fail_alloc:
15178 +
15179 + *rm_in_out = NULL;
15180 + EFRM_ERR("%s: failed rc=%d", __func__, rc);
15181 + return rc;
15182 +}
15183 +
15184 +int
15185 +efrm_create_vi_resource_manager(struct efrm_resource_manager **rm_out,
15186 + const struct vi_resource_dimensions *dims)
15187 +{
15188 + return efrm_create_or_destroy_vi_resource_manager(rm_out, dims, false);
15189 +}
15190 +
15191 +static void efrm_vi_rm_dtor(struct efrm_resource_manager *rm)
15192 +{
15193 + efrm_create_or_destroy_vi_resource_manager(&rm, NULL, true);
15194 +}