]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/60005_sfc-driverlink.patch1
Fix core28 updater kernel version
[people/pmueller/ipfire-2.x.git] / src / patches / 60005_sfc-driverlink.patch1
CommitLineData
cc90b958
BS
1From: David Riddoch <driddoch@solarflare.com>
2commit d96c061bfd1839e34e136de0555564520acc97af
3Author: Steve Hodgson <shodgson@solarflare.com>
4Date: Mon Jul 14 15:38:47 2008 +0100
5
6Subject: sfc: Driverlink API for exporting hardware features to client drivers
7
8References: FATE#303479
9Acked-by: jbeulich@novell.com
10
11Index: head-2008-08-18/drivers/net/sfc/Makefile
12===================================================================
13--- head-2008-08-18.orig/drivers/net/sfc/Makefile 2008-08-18 10:16:43.000000000 +0200
14+++ head-2008-08-18/drivers/net/sfc/Makefile 2008-08-18 10:16:46.000000000 +0200
15@@ -1,5 +1,5 @@
16 sfc-y += efx.o falcon.o tx.o rx.o falcon_xmac.o \
17 selftest.o ethtool.o xfp_phy.o \
18- mdio_10g.o tenxpress.o boards.o sfe4001.o
19-
20+ mdio_10g.o tenxpress.o boards.o sfe4001.o \
21+ driverlink.o
22 obj-$(CONFIG_SFC) += sfc.o
23Index: head-2008-08-18/drivers/net/sfc/driverlink.c
24===================================================================
25--- /dev/null 1970-01-01 00:00:00.000000000 +0000
26+++ head-2008-08-18/drivers/net/sfc/driverlink.c 2008-08-18 10:16:46.000000000 +0200
27@@ -0,0 +1,367 @@
28+/****************************************************************************
29+ * Driver for Solarflare Solarstorm network controllers and boards
30+ * Copyright 2005 Fen Systems Ltd.
31+ * Copyright 2005-2008 Solarflare Communications Inc.
32+ *
33+ * This program is free software; you can redistribute it and/or modify it
34+ * under the terms of the GNU General Public License version 2 as published
35+ * by the Free Software Foundation, incorporated herein by reference.
36+ */
37+
38+#include <linux/module.h>
39+#include <linux/list.h>
40+#include <linux/skbuff.h>
41+#include <linux/rtnetlink.h>
42+#include "net_driver.h"
43+#include "efx.h"
44+#include "driverlink_api.h"
45+#include "driverlink.h"
46+
47+/* Protects @efx_driverlink_lock and @efx_driver_list */
48+static DEFINE_MUTEX(efx_driverlink_lock);
49+
50+/* List of all registered drivers */
51+static LIST_HEAD(efx_driver_list);
52+
53+/* List of all registered Efx ports */
54+static LIST_HEAD(efx_port_list);
55+
56+/**
57+ * Driver link handle used internally to track devices
58+ * @efx_dev: driverlink device handle exported to consumers
59+ * @efx: efx_nic backing the driverlink device
60+ * @port_node: per-device list head
61+ * @driver_node: per-driver list head
62+ */
63+struct efx_dl_handle {
64+ struct efx_dl_device efx_dev;
65+ struct efx_nic *efx;
66+ struct list_head port_node;
67+ struct list_head driver_node;
68+};
69+
70+static struct efx_dl_handle *efx_dl_handle(struct efx_dl_device *efx_dev)
71+{
72+ return container_of(efx_dev, struct efx_dl_handle, efx_dev);
73+}
74+
75+/* Remove an Efx device, and call the driver's remove() callback if
76+ * present. The caller must hold @efx_driverlink_lock. */
77+static void efx_dl_del_device(struct efx_dl_device *efx_dev)
78+{
79+ struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
80+
81+ EFX_INFO(efx_handle->efx, "%s driverlink client unregistering\n",
82+ efx_dev->driver->name);
83+
84+ if (efx_dev->driver->remove)
85+ efx_dev->driver->remove(efx_dev);
86+
87+ list_del(&efx_handle->driver_node);
88+ list_del(&efx_handle->port_node);
89+
90+ kfree(efx_handle);
91+}
92+
93+/* Attempt to probe the given device with the driver, creating a
94+ * new &struct efx_dl_device. If the probe routine returns an error,
95+ * then the &struct efx_dl_device is destroyed */
96+static void efx_dl_try_add_device(struct efx_nic *efx,
97+ struct efx_dl_driver *driver)
98+{
99+ struct efx_dl_handle *efx_handle;
100+ struct efx_dl_device *efx_dev;
101+ int rc;
102+
103+ efx_handle = kzalloc(sizeof(*efx_handle), GFP_KERNEL);
104+ if (!efx_handle)
105+ goto fail;
106+ efx_dev = &efx_handle->efx_dev;
107+ efx_handle->efx = efx;
108+ efx_dev->driver = driver;
109+ efx_dev->pci_dev = efx->pci_dev;
110+ INIT_LIST_HEAD(&efx_handle->port_node);
111+ INIT_LIST_HEAD(&efx_handle->driver_node);
112+
113+ rc = driver->probe(efx_dev, efx->net_dev,
114+ efx->dl_info, efx->silicon_rev);
115+ if (rc)
116+ goto fail;
117+
118+ list_add_tail(&efx_handle->driver_node, &driver->device_list);
119+ list_add_tail(&efx_handle->port_node, &efx->dl_device_list);
120+
121+ EFX_INFO(efx, "%s driverlink client registered\n", driver->name);
122+ return;
123+
124+ fail:
125+ EFX_INFO(efx, "%s driverlink client skipped\n", driver->name);
126+
127+ kfree(efx_handle);
128+}
129+
130+/* Unregister a driver from the driverlink layer, calling the
131+ * driver's remove() callback for every attached device */
132+void efx_dl_unregister_driver(struct efx_dl_driver *driver)
133+{
134+ struct efx_dl_handle *efx_handle, *efx_handle_n;
135+
136+ printk(KERN_INFO "Efx driverlink unregistering %s driver\n",
137+ driver->name);
138+
139+ mutex_lock(&efx_driverlink_lock);
140+
141+ list_for_each_entry_safe(efx_handle, efx_handle_n,
142+ &driver->device_list, driver_node)
143+ efx_dl_del_device(&efx_handle->efx_dev);
144+
145+ list_del(&driver->node);
146+
147+ mutex_unlock(&efx_driverlink_lock);
148+}
149+EXPORT_SYMBOL(efx_dl_unregister_driver);
150+
151+/* Register a new driver with the driverlink layer. The driver's
152+ * probe routine will be called for every attached nic. */
153+int efx_dl_register_driver(struct efx_dl_driver *driver)
154+{
155+ struct efx_nic *efx;
156+ int rc;
157+
158+ printk(KERN_INFO "Efx driverlink registering %s driver\n",
159+ driver->name);
160+
161+ INIT_LIST_HEAD(&driver->node);
162+ INIT_LIST_HEAD(&driver->device_list);
163+
164+ rc = mutex_lock_interruptible(&efx_driverlink_lock);
165+ if (rc)
166+ return rc;
167+
168+ list_add_tail(&driver->node, &efx_driver_list);
169+ list_for_each_entry(efx, &efx_port_list, dl_node)
170+ efx_dl_try_add_device(efx, driver);
171+
172+ mutex_unlock(&efx_driverlink_lock);
173+
174+ return 0;
175+}
176+EXPORT_SYMBOL(efx_dl_register_driver);
177+
178+void efx_dl_unregister_nic(struct efx_nic *efx)
179+{
180+ struct efx_dl_handle *efx_handle, *efx_handle_n;
181+
182+ mutex_lock(&efx_driverlink_lock);
183+
184+ list_for_each_entry_safe_reverse(efx_handle, efx_handle_n,
185+ &efx->dl_device_list,
186+ port_node)
187+ efx_dl_del_device(&efx_handle->efx_dev);
188+
189+ list_del(&efx->dl_node);
190+
191+ mutex_unlock(&efx_driverlink_lock);
192+}
193+
194+int efx_dl_register_nic(struct efx_nic *efx)
195+{
196+ struct efx_dl_driver *driver;
197+ int rc;
198+
199+ rc = mutex_lock_interruptible(&efx_driverlink_lock);
200+ if (rc)
201+ return rc;
202+
203+ list_add_tail(&efx->dl_node, &efx_port_list);
204+ list_for_each_entry(driver, &efx_driver_list, node)
205+ efx_dl_try_add_device(efx, driver);
206+
207+ mutex_unlock(&efx_driverlink_lock);
208+
209+ return 0;
210+}
211+
212+/* Dummy callback implementations.
213+ * To avoid a branch point on the fast-path, the callbacks are always
214+ * implemented - they are never NULL.
215+ */
216+static enum efx_veto efx_dummy_tx_packet_callback(struct efx_dl_device *efx_dev,
217+ struct sk_buff *skb)
218+{
219+ return EFX_ALLOW_PACKET;
220+}
221+
222+static enum efx_veto efx_dummy_rx_packet_callback(struct efx_dl_device *efx_dev,
223+ const char *pkt_buf, int len)
224+{
225+ return EFX_ALLOW_PACKET;
226+}
227+
228+static int efx_dummy_request_mtu_callback(struct efx_dl_device *efx_dev,
229+ int new_mtu)
230+{
231+ return 0;
232+}
233+
234+static void efx_dummy_mtu_changed_callback(struct efx_dl_device *efx_dev,
235+ int mtu)
236+{
237+ return;
238+}
239+
240+static void efx_dummy_event_callback(struct efx_dl_device *efx_dev, void *event)
241+{
242+ return;
243+}
244+
245+struct efx_dl_callbacks efx_default_callbacks = {
246+ .tx_packet = efx_dummy_tx_packet_callback,
247+ .rx_packet = efx_dummy_rx_packet_callback,
248+ .request_mtu = efx_dummy_request_mtu_callback,
249+ .mtu_changed = efx_dummy_mtu_changed_callback,
250+ .event = efx_dummy_event_callback,
251+};
252+
253+void efx_dl_unregister_callbacks(struct efx_dl_device *efx_dev,
254+ struct efx_dl_callbacks *callbacks)
255+{
256+ struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
257+ struct efx_nic *efx = efx_handle->efx;
258+
259+ efx_suspend(efx);
260+
261+ EFX_INFO(efx, "removing callback hooks into %s driver\n",
262+ efx_dev->driver->name);
263+
264+ if (callbacks->tx_packet) {
265+ BUG_ON(efx->dl_cb_dev.tx_packet != efx_dev);
266+ efx->dl_cb.tx_packet = efx_default_callbacks.tx_packet;
267+ efx->dl_cb_dev.tx_packet = NULL;
268+ }
269+ if (callbacks->rx_packet) {
270+ BUG_ON(efx->dl_cb_dev.rx_packet != efx_dev);
271+ efx->dl_cb.rx_packet = efx_default_callbacks.rx_packet;
272+ efx->dl_cb_dev.rx_packet = NULL;
273+ }
274+ if (callbacks->request_mtu) {
275+ BUG_ON(efx->dl_cb_dev.request_mtu != efx_dev);
276+ efx->dl_cb.request_mtu = efx_default_callbacks.request_mtu;
277+ efx->dl_cb_dev.request_mtu = NULL;
278+ }
279+ if (callbacks->mtu_changed) {
280+ BUG_ON(efx->dl_cb_dev.mtu_changed != efx_dev);
281+ efx->dl_cb.mtu_changed = efx_default_callbacks.mtu_changed;
282+ efx->dl_cb_dev.mtu_changed = NULL;
283+ }
284+ if (callbacks->event) {
285+ BUG_ON(efx->dl_cb_dev.event != efx_dev);
286+ efx->dl_cb.event = efx_default_callbacks.event;
287+ efx->dl_cb_dev.event = NULL;
288+ }
289+
290+ efx_resume(efx);
291+}
292+EXPORT_SYMBOL(efx_dl_unregister_callbacks);
293+
294+int efx_dl_register_callbacks(struct efx_dl_device *efx_dev,
295+ struct efx_dl_callbacks *callbacks)
296+{
297+ struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
298+ struct efx_nic *efx = efx_handle->efx;
299+ int rc = 0;
300+
301+ efx_suspend(efx);
302+
303+ /* Check that the requested callbacks are not already hooked. */
304+ if ((callbacks->tx_packet && efx->dl_cb_dev.tx_packet) ||
305+ (callbacks->rx_packet && efx->dl_cb_dev.rx_packet) ||
306+ (callbacks->request_mtu && efx->dl_cb_dev.request_mtu) ||
307+ (callbacks->mtu_changed && efx->dl_cb_dev.mtu_changed) ||
308+ (callbacks->event && efx->dl_cb_dev.event)) {
309+ rc = -EBUSY;
310+ goto out;
311+ }
312+
313+ EFX_INFO(efx, "adding callback hooks to %s driver\n",
314+ efx_dev->driver->name);
315+
316+ /* Hook in the requested callbacks, leaving any NULL members
317+ * referencing the members of @efx_default_callbacks */
318+ if (callbacks->tx_packet) {
319+ efx->dl_cb.tx_packet = callbacks->tx_packet;
320+ efx->dl_cb_dev.tx_packet = efx_dev;
321+ }
322+ if (callbacks->rx_packet) {
323+ efx->dl_cb.rx_packet = callbacks->rx_packet;
324+ efx->dl_cb_dev.rx_packet = efx_dev;
325+ }
326+ if (callbacks->request_mtu) {
327+ efx->dl_cb.request_mtu = callbacks->request_mtu;
328+ efx->dl_cb_dev.request_mtu = efx_dev;
329+ }
330+ if (callbacks->mtu_changed) {
331+ efx->dl_cb.mtu_changed = callbacks->mtu_changed;
332+ efx->dl_cb_dev.mtu_changed = efx_dev;
333+ }
334+ if (callbacks->event) {
335+ efx->dl_cb.event = callbacks->event;
336+ efx->dl_cb_dev.event = efx_dev;
337+ }
338+
339+ out:
340+ efx_resume(efx);
341+
342+ return rc;
343+}
344+EXPORT_SYMBOL(efx_dl_register_callbacks);
345+
346+void efx_dl_schedule_reset(struct efx_dl_device *efx_dev)
347+{
348+ struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
349+ struct efx_nic *efx = efx_handle->efx;
350+
351+ efx_schedule_reset(efx, RESET_TYPE_ALL);
352+}
353+EXPORT_SYMBOL(efx_dl_schedule_reset);
354+
355+void efx_dl_reset_unlock(void)
356+{
357+ mutex_unlock(&efx_driverlink_lock);
358+}
359+
360+/* Suspend ready for reset, serialising against all the driverlink interfacse
361+ * and calling the suspend() callback of every registered driver */
362+void efx_dl_reset_suspend(struct efx_nic *efx)
363+{
364+ struct efx_dl_handle *efx_handle;
365+ struct efx_dl_device *efx_dev;
366+
367+ mutex_lock(&efx_driverlink_lock);
368+
369+ list_for_each_entry_reverse(efx_handle,
370+ &efx->dl_device_list,
371+ port_node) {
372+ efx_dev = &efx_handle->efx_dev;
373+ if (efx_dev->driver->reset_suspend)
374+ efx_dev->driver->reset_suspend(efx_dev);
375+ }
376+}
377+
378+/* Resume after a reset, calling the resume() callback of every registered
379+ * driver, and releasing @Efx_driverlink_lock acquired in
380+ * efx_dl_reset_resume() */
381+void efx_dl_reset_resume(struct efx_nic *efx, int ok)
382+{
383+ struct efx_dl_handle *efx_handle;
384+ struct efx_dl_device *efx_dev;
385+
386+ list_for_each_entry(efx_handle, &efx->dl_device_list,
387+ port_node) {
388+ efx_dev = &efx_handle->efx_dev;
389+ if (efx_dev->driver->reset_resume)
390+ efx_dev->driver->reset_resume(efx_dev, ok);
391+ }
392+
393+ mutex_unlock(&efx_driverlink_lock);
394+}
395Index: head-2008-08-18/drivers/net/sfc/driverlink.h
396===================================================================
397--- /dev/null 1970-01-01 00:00:00.000000000 +0000
398+++ head-2008-08-18/drivers/net/sfc/driverlink.h 2008-08-18 10:16:46.000000000 +0200
399@@ -0,0 +1,43 @@
400+/****************************************************************************
401+ * Driver for Solarflare Solarstorm network controllers and boards
402+ * Copyright 2005 Fen Systems Ltd.
403+ * Copyright 2006-2008 Solarflare Communications Inc.
404+ *
405+ * This program is free software; you can redistribute it and/or modify it
406+ * under the terms of the GNU General Public License version 2 as published
407+ * by the Free Software Foundation, incorporated herein by reference.
408+ */
409+
410+#ifndef EFX_DRIVERLINK_H
411+#define EFX_DRIVERLINK_H
412+
413+/* Forward declarations */
414+struct efx_dl_device;
415+struct efx_nic;
416+
417+/* Efx callback devices
418+ *
419+ * A list of the devices that own each callback. The partner to
420+ * struct efx_dl_callbacks.
421+ */
422+struct efx_dl_cb_devices {
423+ struct efx_dl_device *tx_packet;
424+ struct efx_dl_device *rx_packet;
425+ struct efx_dl_device *request_mtu;
426+ struct efx_dl_device *mtu_changed;
427+ struct efx_dl_device *event;
428+};
429+
430+extern struct efx_dl_callbacks efx_default_callbacks;
431+
432+#define EFX_DL_CALLBACK(_port, _name, ...) \
433+ (_port)->dl_cb._name((_port)->dl_cb_dev._name, __VA_ARGS__)
434+
435+extern int efx_dl_register_nic(struct efx_nic *efx);
436+extern void efx_dl_unregister_nic(struct efx_nic *efx);
437+
438+/* Suspend and resume client drivers over a hardware reset */
439+extern void efx_dl_reset_suspend(struct efx_nic *efx);
440+extern void efx_dl_reset_resume(struct efx_nic *efx, int ok);
441+
442+#endif /* EFX_DRIVERLINK_H */
443Index: head-2008-08-18/drivers/net/sfc/driverlink_api.h
444===================================================================
445--- /dev/null 1970-01-01 00:00:00.000000000 +0000
446+++ head-2008-08-18/drivers/net/sfc/driverlink_api.h 2008-08-18 10:16:46.000000000 +0200
447@@ -0,0 +1,303 @@
448+/****************************************************************************
449+ * Driver for Solarflare Solarstorm network controllers and boards
450+ * Copyright 2005-2006 Fen Systems Ltd.
451+ * Copyright 2005-2008 Solarflare Communications Inc.
452+ *
453+ * This program is free software; you can redistribute it and/or modify it
454+ * under the terms of the GNU General Public License version 2 as published
455+ * by the Free Software Foundation, incorporated herein by reference.
456+ */
457+
458+#ifndef EFX_DRIVERLINK_API_H
459+#define EFX_DRIVERLINK_API_H
460+
461+#include <linux/list.h>
462+
463+/* Forward declarations */
464+struct pci_dev;
465+struct net_device;
466+struct sk_buff;
467+struct efx_dl_device;
468+struct efx_dl_device_info;
469+
470+/* An extra safeguard in addition to symbol versioning */
471+#define EFX_DRIVERLINK_API_VERSION 2
472+
473+/**
474+ * struct efx_dl_driver - An Efx driverlink device driver
475+ *
476+ * A driverlink client defines and initializes as many instances of
477+ * efx_dl_driver as required, registering each one with
478+ * efx_dl_register_driver().
479+ *
480+ * @name: Name of the driver
481+ * @probe: Called when device added
482+ * The client should use the @def_info linked list and @silicon_rev
483+ * to determine if they wish to attach to this device.
484+ * Context: process, driverlink semaphore held
485+ * @remove: Called when device removed
486+ * The client must ensure the finish all operations with this
487+ * device before returning from this method.
488+ * Context: process, driverlink semaphore held
489+ * @reset_suspend: Called before device is reset
490+ * Called immediately before a hardware reset. The client must stop all
491+ * hardware processing before returning from this method. Callbacks will
492+ * be inactive when this method is called.
493+ * Context: process, driverlink semaphore held. rtnl_lock may be held
494+ * @reset_resume: Called after device is reset
495+ * Called after a hardware reset. If @ok is true, the client should
496+ * state and resume normal operations. If @ok is false, the client should
497+ * abandon use of the hardware resources. remove() will still be called.
498+ * Context: process, driverlink semaphore held. rtnl_lock may be held
499+ */
500+struct efx_dl_driver {
501+ const char *name;
502+
503+ int (*probe) (struct efx_dl_device *efx_dl_dev,
504+ const struct net_device *net_dev,
505+ const struct efx_dl_device_info *dev_info,
506+ const char *silicon_rev);
507+ void (*remove) (struct efx_dl_device *efx_dev);
508+ void (*reset_suspend) (struct efx_dl_device *efx_dev);
509+ void (*reset_resume) (struct efx_dl_device *efx_dev, int ok);
510+
511+/* private: */
512+ struct list_head node;
513+ struct list_head device_list;
514+};
515+
516+/**
517+ * enum efx_dl_device_info_type - Device information identifier.
518+ *
519+ * Used to identify each item in the &struct efx_dl_device_info linked list
520+ * provided to each driverlink client in the probe() @dev_info member.
521+ *
522+ * @EFX_DL_FALCON_RESOURCES: Information type is &struct efx_dl_falcon_resources
523+ */
524+enum efx_dl_device_info_type {
525+ /** Falcon resources available for export */
526+ EFX_DL_FALCON_RESOURCES = 0,
527+};
528+
529+/**
530+ * struct efx_dl_device_info - device information structure
531+ *
532+ * @next: Link to next structure, if any
533+ * @type: Type code for this structure
534+ */
535+struct efx_dl_device_info {
536+ struct efx_dl_device_info *next;
537+ enum efx_dl_device_info_type type;
538+};
539+
540+/**
541+ * enum efx_dl_falcon_resource_flags - Falcon resource information flags.
542+ *
543+ * Flags that describe hardware variations for the current Falcon device.
544+ *
545+ * @EFX_DL_FALCON_DUAL_FUNC: Port is dual-function.
546+ * Certain silicon revisions have two pci functions, and require
547+ * certain hardware resources to be accessed via the secondary
548+ * function
549+ * @EFX_DL_FALCON_USE_MSI: Port is initialised to use MSI/MSI-X interrupts.
550+ * Falcon supports traditional legacy interrupts and MSI/MSI-X
551+ * interrupts. The choice is made at run time by the sfc driver, and
552+ * notified to the clients by this enumeration
553+ */
554+enum efx_dl_falcon_resource_flags {
555+ EFX_DL_FALCON_DUAL_FUNC = 0x1,
556+ EFX_DL_FALCON_USE_MSI = 0x2,
557+};
558+
559+/**
560+ * struct efx_dl_falcon_resources - Falcon resource information.
561+ *
562+ * This structure describes Falcon hardware resources available for
563+ * use by a driverlink driver.
564+ *
565+ * @hdr: Resource linked list header
566+ * @biu_lock: Register access lock.
567+ * Some Falcon revisions require register access for configuration
568+ * registers to be serialised between ports and PCI functions.
569+ * The sfc driver will provide the appropriate lock semantics for
570+ * the underlying hardware.
571+ * @buffer_table_min: First available buffer table entry
572+ * @buffer_table_lim: Last available buffer table entry + 1
573+ * @evq_timer_min: First available event queue with timer
574+ * @evq_timer_lim: Last available event queue with timer + 1
575+ * @evq_int_min: First available event queue with interrupt
576+ * @evq_int_lim: Last available event queue with interrupt + 1
577+ * @rxq_min: First available RX queue
578+ * @rxq_lim: Last available RX queue + 1
579+ * @txq_min: First available TX queue
580+ * @txq_lim: Last available TX queue + 1
581+ * @flags: Hardware variation flags
582+ */
583+struct efx_dl_falcon_resources {
584+ struct efx_dl_device_info hdr;
585+ spinlock_t *biu_lock;
586+ unsigned buffer_table_min;
587+ unsigned buffer_table_lim;
588+ unsigned evq_timer_min;
589+ unsigned evq_timer_lim;
590+ unsigned evq_int_min;
591+ unsigned evq_int_lim;
592+ unsigned rxq_min;
593+ unsigned rxq_lim;
594+ unsigned txq_min;
595+ unsigned txq_lim;
596+ enum efx_dl_falcon_resource_flags flags;
597+};
598+
599+/**
600+ * struct efx_dl_device - An Efx driverlink device.
601+ *
602+ * @pci_dev: PCI device used by the sfc driver.
603+ * @priv: Driver private data
604+ * Driverlink clients can use this to store a pointer to their
605+ * internal per-device data structure. Each (driver, device)
606+ * tuple has a separate &struct efx_dl_device, so clients can use
607+ * this @priv field independently.
608+ * @driver: Efx driverlink driver for this device
609+ */
610+struct efx_dl_device {
611+ struct pci_dev *pci_dev;
612+ void *priv;
613+ struct efx_dl_driver *driver;
614+};
615+
616+/**
617+ * enum efx_veto - Packet veto request flag.
618+ *
619+ * This is the return type for the rx_packet() and tx_packet() methods
620+ * in &struct efx_dl_callbacks.
621+ *
622+ * @EFX_ALLOW_PACKET: Packet may be transmitted/received
623+ * @EFX_VETO_PACKET: Packet must not be transmitted/received
624+ */
625+enum efx_veto {
626+ EFX_ALLOW_PACKET = 0,
627+ EFX_VETO_PACKET = 1,
628+};
629+
630+/**
631+ * struct efx_dl_callbacks - Efx callbacks
632+ *
633+ * This is a tighly controlled set of simple callbacks, that are attached
634+ * to the sfc driver via efx_dl_register_callbacks(). They export just enough
635+ * state to allow clients to make use of the available hardware resources.
636+ *
637+ * For efficiency, only one client can hook each callback. Since these
638+ * callbacks are called on packet transmit and reception paths, and the
639+ * sfc driver may have multiple tx and rx queues per port, clients should
640+ * avoid acquiring locks or allocating memory.
641+ *
642+ * @tx_packet: Called when packet is about to be transmitted
643+ * Called for every packet about to be transmitted, providing means
644+ * for the client to snoop traffic, and veto transmission by returning
645+ * %EFX_VETO_PACKET (the sfc driver will subsequently free the skb).
646+ * Context: tasklet, netif_tx_lock held
647+ * @rx_packet: Called when packet is received
648+ * Called for every received packet (after LRO), allowing the client
649+ * to snoop every received packet (on every rx queue), and veto
650+ * reception by returning %EFX_VETO_PACKET.
651+ * Context: tasklet
652+ * @request_mtu: Called to request MTU change.
653+ * Called whenever the user requests the net_dev mtu to be changed.
654+ * If the client returns an error, the mtu change is aborted. The sfc
655+ * driver guarantees that no other callbacks are running.
656+ * Context: process, rtnl_lock held.
657+ * @mtu_changed: Called when MTU has been changed.
658+ * Called after the mtu has been successfully changed, always after
659+ * a previous call to request_mtu(). The sfc driver guarantees that no
660+ * other callbacks are running.
661+ * Context: process, rtnl_lock held.
662+ * @event: Called when a hardware NIC event is not understood by the sfc driver.
663+ * Context: tasklet.
664+ */
665+struct efx_dl_callbacks {
666+ enum efx_veto (*tx_packet) (struct efx_dl_device *efx_dev,
667+ struct sk_buff *skb);
668+ enum efx_veto (*rx_packet) (struct efx_dl_device *efx_dev,
669+ const char *pkt_hdr, int pkt_len);
670+ int (*request_mtu) (struct efx_dl_device *efx_dev, int new_mtu);
671+ void (*mtu_changed) (struct efx_dl_device *efx_dev, int mtu);
672+ void (*event) (struct efx_dl_device *efx_dev, void *p_event);
673+};
674+
675+/* Include API version number in symbol used for efx_dl_register_driver */
676+#define efx_dl_stringify_1(x, y) x ## y
677+#define efx_dl_stringify_2(x, y) efx_dl_stringify_1(x, y)
678+#define efx_dl_register_driver \
679+ efx_dl_stringify_2(efx_dl_register_driver_api_ver_, \
680+ EFX_DRIVERLINK_API_VERSION)
681+
682+/* Exported driverlink api used to register and unregister the client driver
683+ * and any callbacks [only one per port allowed], and to allow a client driver
684+ * to request reset to recover from an error condition.
685+ *
686+ * All of these functions acquire the driverlink semaphore, so must not be
687+ * called from an efx_dl_driver or efx_dl_callbacks member, and must be called
688+ * from process context.
689+ */
690+extern int efx_dl_register_driver(struct efx_dl_driver *driver);
691+
692+extern void efx_dl_unregister_driver(struct efx_dl_driver *driver);
693+
694+extern int efx_dl_register_callbacks(struct efx_dl_device *efx_dev,
695+ struct efx_dl_callbacks *callbacks);
696+
697+extern void efx_dl_unregister_callbacks(struct efx_dl_device *efx_dev,
698+ struct efx_dl_callbacks *callbacks);
699+
700+/* Schedule a reset without grabbing any locks */
701+extern void efx_dl_schedule_reset(struct efx_dl_device *efx_dev);
702+
703+/**
704+ * efx_dl_for_each_device_info_matching - iterate an efx_dl_device_info list
705+ * @_dev_info: Pointer to first &struct efx_dl_device_info
706+ * @_type: Type code to look for
707+ * @_info_type: Structure type corresponding to type code
708+ * @_field: Name of &struct efx_dl_device_info field in the type
709+ * @_p: Iterator variable
710+ *
711+ * Example:
712+ * struct efx_dl_falcon_resources *res;
713+ * efx_dl_for_each_device_info_matching(dev_info, EFX_DL_FALCON_RESOURCES,
714+ * struct efx_dl_falcon_resources,
715+ * hdr, res) {
716+ * if (res->flags & EFX_DL_FALCON_DUAL_FUNC)
717+ * ....
718+ * }
719+ */
720+#define efx_dl_for_each_device_info_matching(_dev_info, _type, \
721+ _info_type, _field, _p) \
722+ for ((_p) = container_of((_dev_info), _info_type, _field); \
723+ (_p) != NULL; \
724+ (_p) = container_of((_p)->_field.next, _info_type, _field))\
725+ if ((_p)->_field.type != _type) \
726+ continue; \
727+ else
728+
729+/**
730+ * efx_dl_search_device_info - search an efx_dl_device_info list
731+ * @_dev_info: Pointer to first &struct efx_dl_device_info
732+ * @_type: Type code to look for
733+ * @_info_type: Structure type corresponding to type code
734+ * @_field: Name of &struct efx_dl_device_info member in this type
735+ * @_p: Result variable
736+ *
737+ * Example:
738+ * struct efx_dl_falcon_resources *res;
739+ * efx_dl_search_device_info(dev_info, EFX_DL_FALCON_RESOURCES,
740+ * struct efx_dl_falcon_resources, hdr, res);
741+ * if (res)
742+ * ....
743+ */
744+#define efx_dl_search_device_info(_dev_info, _type, _info_type, \
745+ _field, _p) \
746+ efx_dl_for_each_device_info_matching((_dev_info), (_type), \
747+ _info_type, _field, (_p)) \
748+ break;
749+
750+#endif /* EFX_DRIVERLINK_API_H */
751Index: head-2008-08-18/drivers/net/sfc/efx.c
752===================================================================
753--- head-2008-08-18.orig/drivers/net/sfc/efx.c 2008-08-18 10:16:43.000000000 +0200
754+++ head-2008-08-18/drivers/net/sfc/efx.c 2008-08-18 10:16:46.000000000 +0200
755@@ -1427,6 +1427,11 @@ static int efx_change_mtu(struct net_dev
756
757 efx_stop_all(efx);
758
759+ /* Ask driverlink client if we can change MTU */
760+ rc = EFX_DL_CALLBACK(efx, request_mtu, new_mtu);
761+ if (rc)
762+ goto out;
763+
764 EFX_LOG(efx, "changing MTU to %d\n", new_mtu);
765
766 efx_fini_channels(efx);
767@@ -1435,6 +1440,10 @@ static int efx_change_mtu(struct net_dev
768 if (rc)
769 goto fail;
770
771+ /* Notify driverlink client of new MTU */
772+ EFX_DL_CALLBACK(efx, mtu_changed, new_mtu);
773+
774+ out:
775 efx_start_all(efx);
776 return rc;
777
778@@ -1587,6 +1596,23 @@ static void efx_unregister_netdev(struct
779 * Device reset and suspend
780 *
781 **************************************************************************/
782+/* Serialise access to the driverlink callbacks, by quiescing event processing
783+ * (without flushing the descriptor queues), and acquiring the rtnl_lock */
784+void efx_suspend(struct efx_nic *efx)
785+{
786+ EFX_LOG(efx, "suspending operations\n");
787+
788+ rtnl_lock();
789+ efx_stop_all(efx);
790+}
791+
792+void efx_resume(struct efx_nic *efx)
793+{
794+ EFX_LOG(efx, "resuming operations\n");
795+
796+ efx_start_all(efx);
797+ rtnl_unlock();
798+}
799
800 /* The final hardware and software finalisation before reset. */
801 static int efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
802@@ -1649,8 +1675,8 @@ static int efx_reset(struct efx_nic *efx
803 enum reset_type method = efx->reset_pending;
804 int rc;
805
806- /* Serialise with kernel interfaces */
807 rtnl_lock();
808+ efx_dl_reset_suspend(efx);
809
810 /* If we're not RUNNING then don't reset. Leave the reset_pending
811 * flag set so that efx_pci_probe_main will be retried */
812@@ -1717,6 +1743,7 @@ static int efx_reset(struct efx_nic *efx
813 efx_start_all(efx);
814
815 unlock_rtnl:
816+ efx_dl_reset_resume(efx, 1);
817 rtnl_unlock();
818 return 0;
819
820@@ -1729,6 +1756,7 @@ static int efx_reset(struct efx_nic *efx
821 efx->state = STATE_DISABLED;
822
823 mutex_unlock(&efx->mac_lock);
824+ efx_dl_reset_resume(efx, 0);
825 rtnl_unlock();
826 efx_unregister_netdev(efx);
827 efx_fini_port(efx);
828@@ -1871,6 +1899,9 @@ static int efx_init_struct(struct efx_ni
829 mutex_init(&efx->mac_lock);
830 efx->phy_op = &efx_dummy_phy_operations;
831 efx->mii.dev = net_dev;
832+ INIT_LIST_HEAD(&efx->dl_node);
833+ INIT_LIST_HEAD(&efx->dl_device_list);
834+ efx->dl_cb = efx_default_callbacks;
835 INIT_WORK(&efx->reconfigure_work, efx_reconfigure_work);
836 atomic_set(&efx->netif_stop_count, 1);
837
838@@ -1990,6 +2021,7 @@ static void efx_pci_remove(struct pci_de
839 efx = pci_get_drvdata(pci_dev);
840 if (!efx)
841 return;
842+ efx_dl_unregister_nic(efx);
843
844 /* Mark the NIC as fini, then stop the interface */
845 rtnl_lock();
846@@ -2157,8 +2189,15 @@ static int __devinit efx_pci_probe(struc
847
848 EFX_LOG(efx, "initialisation successful\n");
849
850+ /* Register with driverlink layer */
851+ rc = efx_dl_register_nic(efx);
852+ if (rc)
853+ goto fail6;
854+
855 return 0;
856
857+ fail6:
858+ efx_unregister_netdev(efx);
859 fail5:
860 efx_pci_remove_main(efx);
861 fail4:
862Index: head-2008-08-18/drivers/net/sfc/falcon.c
863===================================================================
864--- head-2008-08-18.orig/drivers/net/sfc/falcon.c 2008-08-18 10:16:43.000000000 +0200
865+++ head-2008-08-18/drivers/net/sfc/falcon.c 2008-08-18 10:16:46.000000000 +0200
866@@ -36,12 +36,12 @@
867
868 /**
869 * struct falcon_nic_data - Falcon NIC state
870- * @next_buffer_table: First available buffer table id
871+ * @resources: Resource information for driverlink client
872 * @pci_dev2: The secondary PCI device if present
873 * @i2c_data: Operations and state for I2C bit-bashing algorithm
874 */
875 struct falcon_nic_data {
876- unsigned next_buffer_table;
877+ struct efx_dl_falcon_resources resources;
878 struct pci_dev *pci_dev2;
879 struct i2c_algo_bit_data i2c_data;
880 };
881@@ -322,8 +322,8 @@ static int falcon_alloc_special_buffer(s
882 memset(buffer->addr, 0xff, len);
883
884 /* Select new buffer ID */
885- buffer->index = nic_data->next_buffer_table;
886- nic_data->next_buffer_table += buffer->entries;
887+ buffer->index = nic_data->resources.buffer_table_min;
888+ nic_data->resources.buffer_table_min += buffer->entries;
889
890 EFX_LOG(efx, "allocating special buffers %d-%d at %llx+%x "
891 "(virt %p phys %lx)\n", buffer->index,
892@@ -1115,10 +1115,12 @@ static void falcon_handle_driver_event(s
893 case TX_DESCQ_FLS_DONE_EV_DECODE:
894 EFX_TRACE(efx, "channel %d TXQ %d flushed\n",
895 channel->channel, ev_sub_data);
896+ EFX_DL_CALLBACK(efx, event, event);
897 break;
898 case RX_DESCQ_FLS_DONE_EV_DECODE:
899 EFX_TRACE(efx, "channel %d RXQ %d flushed\n",
900 channel->channel, ev_sub_data);
901+ EFX_DL_CALLBACK(efx, event, event);
902 break;
903 case EVQ_INIT_DONE_EV_DECODE:
904 EFX_LOG(efx, "channel %d EVQ %d initialised\n",
905@@ -1127,14 +1129,17 @@ static void falcon_handle_driver_event(s
906 case SRM_UPD_DONE_EV_DECODE:
907 EFX_TRACE(efx, "channel %d SRAM update done\n",
908 channel->channel);
909+ EFX_DL_CALLBACK(efx, event, event);
910 break;
911 case WAKE_UP_EV_DECODE:
912 EFX_TRACE(efx, "channel %d RXQ %d wakeup event\n",
913 channel->channel, ev_sub_data);
914+ EFX_DL_CALLBACK(efx, event, event);
915 break;
916 case TIMER_EV_DECODE:
917 EFX_TRACE(efx, "channel %d RX queue %d timer expired\n",
918 channel->channel, ev_sub_data);
919+ EFX_DL_CALLBACK(efx, event, event);
920 break;
921 case RX_RECOVERY_EV_DECODE:
922 EFX_ERR(efx, "channel %d seen DRIVER RX_RESET event. "
923@@ -1159,6 +1164,7 @@ static void falcon_handle_driver_event(s
924 EFX_TRACE(efx, "channel %d unknown driver event code %d "
925 "data %04x\n", channel->channel, ev_sub_code,
926 ev_sub_data);
927+ EFX_DL_CALLBACK(efx, event, event);
928 break;
929 }
930 }
931@@ -2371,6 +2377,59 @@ static int falcon_probe_nvconfig(struct
932 return rc;
933 }
934
935+/* Looks at available SRAM resources and silicon revision, and works out
936+ * how many queues we can support, and where things like descriptor caches
937+ * should live. */
938+static int falcon_dimension_resources(struct efx_nic *efx)
939+{
940+ unsigned internal_dcs_entries;
941+ struct falcon_nic_data *nic_data = efx->nic_data;
942+ struct efx_dl_falcon_resources *res = &nic_data->resources;
943+
944+ /* Fill out the driverlink resource list */
945+ res->hdr.type = EFX_DL_FALCON_RESOURCES;
946+ res->biu_lock = &efx->biu_lock;
947+ efx->dl_info = &res->hdr;
948+
949+ /* NB. The minimum values get increased as this driver initialises
950+ * its resources, so this should prevent any overlap.
951+ */
952+ switch (falcon_rev(efx)) {
953+ case FALCON_REV_A1:
954+ res->rxq_min = 16;
955+ res->txq_min = 16;
956+ res->evq_int_min = 4;
957+ res->evq_int_lim = 5;
958+ res->evq_timer_min = 5;
959+ res->evq_timer_lim = 4096;
960+ internal_dcs_entries = 8192;
961+ break;
962+ case FALCON_REV_B0:
963+ default:
964+ res->rxq_min = 0;
965+ res->txq_min = 0;
966+ res->evq_int_min = 0;
967+ res->evq_int_lim = 64;
968+ res->evq_timer_min = 64;
969+ res->evq_timer_lim = 4096;
970+ internal_dcs_entries = 4096;
971+ break;
972+ }
973+
974+ /* Internal SRAM only for now */
975+ res->rxq_lim = internal_dcs_entries / RX_DC_ENTRIES;
976+ res->txq_lim = internal_dcs_entries / TX_DC_ENTRIES;
977+ res->buffer_table_lim = 8192;
978+
979+ if (FALCON_IS_DUAL_FUNC(efx))
980+ res->flags |= EFX_DL_FALCON_DUAL_FUNC;
981+
982+ if (EFX_INT_MODE_USE_MSI(efx))
983+ res->flags |= EFX_DL_FALCON_USE_MSI;
984+
985+ return 0;
986+}
987+
988 /* Probe the NIC variant (revision, ASIC vs FPGA, function count, port
989 * count, port speed). Set workaround and feature flags accordingly.
990 */
991@@ -2403,10 +2462,12 @@ static int falcon_probe_nic_variant(stru
992 EFX_ERR(efx, "1G mode not supported\n");
993 return -ENODEV;
994 }
995+ efx->silicon_rev = "falcon/a1";
996 break;
997 }
998
999 case FALCON_REV_B0:
1000+ efx->silicon_rev = "falcon/b0";
1001 break;
1002
1003 default:
1004@@ -2472,6 +2533,10 @@ int falcon_probe_nic(struct efx_nic *efx
1005 if (rc)
1006 goto fail5;
1007
1008+ rc = falcon_dimension_resources(efx);
1009+ if (rc)
1010+ goto fail6;
1011+
1012 /* Initialise I2C adapter */
1013 efx->i2c_adap.owner = THIS_MODULE;
1014 nic_data->i2c_data = falcon_i2c_bit_operations;
1015@@ -2481,10 +2546,12 @@ int falcon_probe_nic(struct efx_nic *efx
1016 strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name));
1017 rc = i2c_bit_add_bus(&efx->i2c_adap);
1018 if (rc)
1019- goto fail5;
1020+ goto fail6;
1021
1022 return 0;
1023
1024+ fail6:
1025+ efx->dl_info = NULL;
1026 fail5:
1027 falcon_free_buffer(efx, &efx->irq_status);
1028 fail4:
1029@@ -2675,6 +2742,7 @@ void falcon_remove_nic(struct efx_nic *e
1030 /* Tear down the private nic state */
1031 kfree(efx->nic_data);
1032 efx->nic_data = NULL;
1033+ efx->dl_info = NULL;
1034 }
1035
1036 void falcon_update_nic_stats(struct efx_nic *efx)
1037Index: head-2008-08-18/drivers/net/sfc/net_driver.h
1038===================================================================
1039--- head-2008-08-18.orig/drivers/net/sfc/net_driver.h 2008-08-18 10:16:43.000000000 +0200
1040+++ head-2008-08-18/drivers/net/sfc/net_driver.h 2008-08-18 10:16:46.000000000 +0200
1041@@ -30,6 +30,8 @@
1042
1043 #include "enum.h"
1044 #include "bitfield.h"
1045+#include "driverlink_api.h"
1046+#include "driverlink.h"
1047
1048 #define EFX_MAX_LRO_DESCRIPTORS 8
1049 #define EFX_MAX_LRO_AGGR MAX_SKB_FRAGS
1050@@ -676,6 +678,12 @@ union efx_multicast_hash {
1051 * @loopback_mode: Loopback status
1052 * @loopback_modes: Supported loopback mode bitmask
1053 * @loopback_selftest: Offline self-test private state
1054+ * @silicon_rev: Silicon revision description for driverlink
1055+ * @dl_info: Linked list of hardware parameters exposed through driverlink
1056+ * @dl_node: Driverlink port list
1057+ * @dl_device_list: Driverlink device list
1058+ * @dl_cb: Driverlink callbacks table
1059+ * @dl_cb_dev: Driverlink callback owner devices
1060 *
1061 * The @priv field of the corresponding &struct net_device points to
1062 * this.
1063@@ -752,6 +760,13 @@ struct efx_nic {
1064 unsigned int loopback_modes;
1065
1066 void *loopback_selftest;
1067+
1068+ const char *silicon_rev;
1069+ struct efx_dl_device_info *dl_info;
1070+ struct list_head dl_node;
1071+ struct list_head dl_device_list;
1072+ struct efx_dl_callbacks dl_cb;
1073+ struct efx_dl_cb_devices dl_cb_dev;
1074 };
1075
1076 static inline int efx_dev_registered(struct efx_nic *efx)
1077Index: head-2008-08-18/drivers/net/sfc/rx.c
1078===================================================================
1079--- head-2008-08-18.orig/drivers/net/sfc/rx.c 2008-08-18 10:16:43.000000000 +0200
1080+++ head-2008-08-18/drivers/net/sfc/rx.c 2008-08-18 10:16:46.000000000 +0200
1081@@ -549,8 +549,22 @@ static inline void efx_rx_packet__check_
1082 static inline void efx_rx_packet_lro(struct efx_channel *channel,
1083 struct efx_rx_buffer *rx_buf)
1084 {
1085+ struct efx_nic *efx = channel->efx;
1086 struct net_lro_mgr *lro_mgr = &channel->lro_mgr;
1087 void *priv = channel;
1088+ enum efx_veto veto;
1089+
1090+ /* It would be faster if we had access to packets at the
1091+ * other side of generic LRO. Unfortunately, there isn't
1092+ * an obvious interface to this, so veto packets before LRO */
1093+ veto = EFX_DL_CALLBACK(efx, rx_packet, rx_buf->data, rx_buf->len);
1094+ if (unlikely(veto)) {
1095+ EFX_TRACE(efx, "LRO RX vetoed by driverlink %s driver\n",
1096+ efx->dl_cb_dev.rx_packet->driver->name);
1097+ /* Free the buffer now */
1098+ efx_free_rx_buffer(efx, rx_buf);
1099+ return;
1100+ }
1101
1102 /* Pass the skb/page into the LRO engine */
1103 if (rx_buf->page) {
1104@@ -686,6 +700,7 @@ void __efx_rx_packet(struct efx_channel
1105 struct efx_rx_buffer *rx_buf, int checksummed)
1106 {
1107 struct efx_nic *efx = channel->efx;
1108+ enum efx_veto veto;
1109 struct sk_buff *skb;
1110 int lro = efx->net_dev->features & NETIF_F_LRO;
1111
1112@@ -723,6 +738,16 @@ void __efx_rx_packet(struct efx_channel
1113 goto done;
1114 }
1115
1116+ /* Allow callback to veto the packet */
1117+ veto = EFX_DL_CALLBACK(efx, rx_packet, rx_buf->data, rx_buf->len);
1118+ if (unlikely(veto)) {
1119+ EFX_LOG(efx, "RX vetoed by driverlink %s driver\n",
1120+ efx->dl_cb_dev.rx_packet->driver->name);
1121+ /* Free the buffer now */
1122+ efx_free_rx_buffer(efx, rx_buf);
1123+ goto done;
1124+ }
1125+
1126 /* Form an skb if required */
1127 if (rx_buf->page) {
1128 int hdr_len = min(rx_buf->len, EFX_SKB_HEADERS);
1129Index: head-2008-08-18/drivers/net/sfc/tx.c
1130===================================================================
1131--- head-2008-08-18.orig/drivers/net/sfc/tx.c 2008-08-18 10:16:43.000000000 +0200
1132+++ head-2008-08-18/drivers/net/sfc/tx.c 2008-08-18 10:16:46.000000000 +0200
1133@@ -368,7 +368,21 @@ inline int efx_xmit(struct efx_nic *efx,
1134 int efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
1135 {
1136 struct efx_nic *efx = net_dev->priv;
1137- return efx_xmit(efx, &efx->tx_queue[0], skb);
1138+ struct efx_tx_queue *tx_queue = &efx->tx_queue[0];
1139+ enum efx_veto veto;
1140+
1141+ /* See if driverlink wants to veto the packet. */
1142+ veto = EFX_DL_CALLBACK(efx, tx_packet, skb);
1143+ if (unlikely(veto)) {
1144+ EFX_TRACE(efx, "TX queue %d packet vetoed by "
1145+ "driverlink %s driver\n", tx_queue->queue,
1146+ efx->dl_cb_dev.tx_packet->driver->name);
1147+ /* Free the skb; nothing else will do it */
1148+ dev_kfree_skb_any(skb);
1149+ return NETDEV_TX_OK;
1150+ }
1151+
1152+ return efx_xmit(efx, tx_queue, skb);
1153 }
1154
1155 void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)