]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - 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
CommitLineData
cc90b958
BS
1From: 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
8Subject: Solarflare: Resource driver.
9References: FATE#303479
10Acked-by: jbeulich@novell.com
11
12Index: 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.
26Index: 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/
36Index: 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
55Index: 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
152Index: 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+}
377Index: 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+}
591Index: 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__ */
784Index: 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__ */
857Index: 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 */
1284Index: 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
2436Index: 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
2516Index: 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
2676Index: 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
2725Index: 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__ */
2797Index: 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__ */
3075Index: 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__ */
3149Index: 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__ */
3272Index: 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__ */
3370Index: 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__ */
3436Index: 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__ */
3525Index: 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__ */
3573Index: 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__ */
3960Index: 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__ */
4037Index: 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__ */
4119Index: 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__ */
4218Index: 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__ */
4281Index: 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__ */
4355Index: 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__ */
4418Index: 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__ */
4613Index: 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__ */
4680Index: 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__ */
4789Index: 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__ */
4849Index: 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__ */
4922Index: 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__ */
5008Index: 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__ */
5091Index: 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__ */
5185Index: 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__ */
5222Index: 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__ */
5253Index: 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 */
5380Index: 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__ */
5495Index: 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__ */
5604Index: 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__ */
5707Index: 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__ */
5830Index: 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__ */
5954Index: 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__ */
6063Index: 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__ */
6114Index: 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__ */
6212Index: 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__ */
6374Index: 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__ */
6534Index: 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__ */
6604Index: 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);
6937Index: 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+}
7202Index: 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__ */
7248Index: 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;
00e5a55c 7753+ struct filter_resource *uninitialized_var(frs);
cc90b958
BS
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);
7960Index: 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+}
8286Index: 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);
00e5a55c 10383+ return &nic->filter_spec_cache[filter_idx];
cc90b958
BS
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+
10816Index: 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+
10980Index: 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);
11235Index: 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+}
11644Index: 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+}
11752Index: 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+}
11875Index: 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 */
11950Index: 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+}
12064Index: 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
12277Index: 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__ */
12358Index: 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+}
12537Index: 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);
13142Index: 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+ */
13292Index: 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+}
13391Index: 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+}
14216Index: 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+}
14471Index: 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+ */
14959Index: 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+}