1 From: David Riddoch <driddoch@solarflare.com>
2 commit d96c061bfd1839e34e136de0555564520acc97af
3 Author: Steve Hodgson <shodgson@solarflare.com>
4 Date: Mon Jul 14 15:38:47 2008 +0100
6 Subject: sfc: Driverlink API for exporting hardware features to client drivers
8 References: FATE#303479
9 Acked-by: jbeulich@novell.com
11 Index: 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
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
20 + mdio_10g.o tenxpress.o boards.o sfe4001.o \
22 obj-$(CONFIG_SFC) += sfc.o
23 Index: 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
28 +/****************************************************************************
29 + * Driver for Solarflare Solarstorm network controllers and boards
30 + * Copyright 2005 Fen Systems Ltd.
31 + * Copyright 2005-2008 Solarflare Communications Inc.
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.
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"
44 +#include "driverlink_api.h"
45 +#include "driverlink.h"
47 +/* Protects @efx_driverlink_lock and @efx_driver_list */
48 +static DEFINE_MUTEX(efx_driverlink_lock);
50 +/* List of all registered drivers */
51 +static LIST_HEAD(efx_driver_list);
53 +/* List of all registered Efx ports */
54 +static LIST_HEAD(efx_port_list);
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
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;
70 +static struct efx_dl_handle *efx_dl_handle(struct efx_dl_device *efx_dev)
72 + return container_of(efx_dev, struct efx_dl_handle, efx_dev);
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)
79 + struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
81 + EFX_INFO(efx_handle->efx, "%s driverlink client unregistering\n",
82 + efx_dev->driver->name);
84 + if (efx_dev->driver->remove)
85 + efx_dev->driver->remove(efx_dev);
87 + list_del(&efx_handle->driver_node);
88 + list_del(&efx_handle->port_node);
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)
99 + struct efx_dl_handle *efx_handle;
100 + struct efx_dl_device *efx_dev;
103 + efx_handle = kzalloc(sizeof(*efx_handle), GFP_KERNEL);
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);
113 + rc = driver->probe(efx_dev, efx->net_dev,
114 + efx->dl_info, efx->silicon_rev);
118 + list_add_tail(&efx_handle->driver_node, &driver->device_list);
119 + list_add_tail(&efx_handle->port_node, &efx->dl_device_list);
121 + EFX_INFO(efx, "%s driverlink client registered\n", driver->name);
125 + EFX_INFO(efx, "%s driverlink client skipped\n", driver->name);
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)
134 + struct efx_dl_handle *efx_handle, *efx_handle_n;
136 + printk(KERN_INFO "Efx driverlink unregistering %s driver\n",
139 + mutex_lock(&efx_driverlink_lock);
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);
145 + list_del(&driver->node);
147 + mutex_unlock(&efx_driverlink_lock);
149 +EXPORT_SYMBOL(efx_dl_unregister_driver);
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)
155 + struct efx_nic *efx;
158 + printk(KERN_INFO "Efx driverlink registering %s driver\n",
161 + INIT_LIST_HEAD(&driver->node);
162 + INIT_LIST_HEAD(&driver->device_list);
164 + rc = mutex_lock_interruptible(&efx_driverlink_lock);
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);
172 + mutex_unlock(&efx_driverlink_lock);
176 +EXPORT_SYMBOL(efx_dl_register_driver);
178 +void efx_dl_unregister_nic(struct efx_nic *efx)
180 + struct efx_dl_handle *efx_handle, *efx_handle_n;
182 + mutex_lock(&efx_driverlink_lock);
184 + list_for_each_entry_safe_reverse(efx_handle, efx_handle_n,
185 + &efx->dl_device_list,
187 + efx_dl_del_device(&efx_handle->efx_dev);
189 + list_del(&efx->dl_node);
191 + mutex_unlock(&efx_driverlink_lock);
194 +int efx_dl_register_nic(struct efx_nic *efx)
196 + struct efx_dl_driver *driver;
199 + rc = mutex_lock_interruptible(&efx_driverlink_lock);
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);
207 + mutex_unlock(&efx_driverlink_lock);
212 +/* Dummy callback implementations.
213 + * To avoid a branch point on the fast-path, the callbacks are always
214 + * implemented - they are never NULL.
216 +static enum efx_veto efx_dummy_tx_packet_callback(struct efx_dl_device *efx_dev,
217 + struct sk_buff *skb)
219 + return EFX_ALLOW_PACKET;
222 +static enum efx_veto efx_dummy_rx_packet_callback(struct efx_dl_device *efx_dev,
223 + const char *pkt_buf, int len)
225 + return EFX_ALLOW_PACKET;
228 +static int efx_dummy_request_mtu_callback(struct efx_dl_device *efx_dev,
234 +static void efx_dummy_mtu_changed_callback(struct efx_dl_device *efx_dev,
240 +static void efx_dummy_event_callback(struct efx_dl_device *efx_dev, void *event)
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,
253 +void efx_dl_unregister_callbacks(struct efx_dl_device *efx_dev,
254 + struct efx_dl_callbacks *callbacks)
256 + struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
257 + struct efx_nic *efx = efx_handle->efx;
261 + EFX_INFO(efx, "removing callback hooks into %s driver\n",
262 + efx_dev->driver->name);
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;
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;
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;
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;
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;
292 +EXPORT_SYMBOL(efx_dl_unregister_callbacks);
294 +int efx_dl_register_callbacks(struct efx_dl_device *efx_dev,
295 + struct efx_dl_callbacks *callbacks)
297 + struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
298 + struct efx_nic *efx = efx_handle->efx;
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)) {
313 + EFX_INFO(efx, "adding callback hooks to %s driver\n",
314 + efx_dev->driver->name);
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;
322 + if (callbacks->rx_packet) {
323 + efx->dl_cb.rx_packet = callbacks->rx_packet;
324 + efx->dl_cb_dev.rx_packet = efx_dev;
326 + if (callbacks->request_mtu) {
327 + efx->dl_cb.request_mtu = callbacks->request_mtu;
328 + efx->dl_cb_dev.request_mtu = efx_dev;
330 + if (callbacks->mtu_changed) {
331 + efx->dl_cb.mtu_changed = callbacks->mtu_changed;
332 + efx->dl_cb_dev.mtu_changed = efx_dev;
334 + if (callbacks->event) {
335 + efx->dl_cb.event = callbacks->event;
336 + efx->dl_cb_dev.event = efx_dev;
344 +EXPORT_SYMBOL(efx_dl_register_callbacks);
346 +void efx_dl_schedule_reset(struct efx_dl_device *efx_dev)
348 + struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
349 + struct efx_nic *efx = efx_handle->efx;
351 + efx_schedule_reset(efx, RESET_TYPE_ALL);
353 +EXPORT_SYMBOL(efx_dl_schedule_reset);
355 +void efx_dl_reset_unlock(void)
357 + mutex_unlock(&efx_driverlink_lock);
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)
364 + struct efx_dl_handle *efx_handle;
365 + struct efx_dl_device *efx_dev;
367 + mutex_lock(&efx_driverlink_lock);
369 + list_for_each_entry_reverse(efx_handle,
370 + &efx->dl_device_list,
372 + efx_dev = &efx_handle->efx_dev;
373 + if (efx_dev->driver->reset_suspend)
374 + efx_dev->driver->reset_suspend(efx_dev);
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)
383 + struct efx_dl_handle *efx_handle;
384 + struct efx_dl_device *efx_dev;
386 + list_for_each_entry(efx_handle, &efx->dl_device_list,
388 + efx_dev = &efx_handle->efx_dev;
389 + if (efx_dev->driver->reset_resume)
390 + efx_dev->driver->reset_resume(efx_dev, ok);
393 + mutex_unlock(&efx_driverlink_lock);
395 Index: 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
400 +/****************************************************************************
401 + * Driver for Solarflare Solarstorm network controllers and boards
402 + * Copyright 2005 Fen Systems Ltd.
403 + * Copyright 2006-2008 Solarflare Communications Inc.
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.
410 +#ifndef EFX_DRIVERLINK_H
411 +#define EFX_DRIVERLINK_H
413 +/* Forward declarations */
414 +struct efx_dl_device;
417 +/* Efx callback devices
419 + * A list of the devices that own each callback. The partner to
420 + * struct efx_dl_callbacks.
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;
430 +extern struct efx_dl_callbacks efx_default_callbacks;
432 +#define EFX_DL_CALLBACK(_port, _name, ...) \
433 + (_port)->dl_cb._name((_port)->dl_cb_dev._name, __VA_ARGS__)
435 +extern int efx_dl_register_nic(struct efx_nic *efx);
436 +extern void efx_dl_unregister_nic(struct efx_nic *efx);
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);
442 +#endif /* EFX_DRIVERLINK_H */
443 Index: 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
448 +/****************************************************************************
449 + * Driver for Solarflare Solarstorm network controllers and boards
450 + * Copyright 2005-2006 Fen Systems Ltd.
451 + * Copyright 2005-2008 Solarflare Communications Inc.
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.
458 +#ifndef EFX_DRIVERLINK_API_H
459 +#define EFX_DRIVERLINK_API_H
461 +#include <linux/list.h>
463 +/* Forward declarations */
467 +struct efx_dl_device;
468 +struct efx_dl_device_info;
470 +/* An extra safeguard in addition to symbol versioning */
471 +#define EFX_DRIVERLINK_API_VERSION 2
474 + * struct efx_dl_driver - An Efx driverlink device driver
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().
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
500 +struct efx_dl_driver {
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);
512 + struct list_head node;
513 + struct list_head device_list;
517 + * enum efx_dl_device_info_type - Device information identifier.
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.
522 + * @EFX_DL_FALCON_RESOURCES: Information type is &struct efx_dl_falcon_resources
524 +enum efx_dl_device_info_type {
525 + /** Falcon resources available for export */
526 + EFX_DL_FALCON_RESOURCES = 0,
530 + * struct efx_dl_device_info - device information structure
532 + * @next: Link to next structure, if any
533 + * @type: Type code for this structure
535 +struct efx_dl_device_info {
536 + struct efx_dl_device_info *next;
537 + enum efx_dl_device_info_type type;
541 + * enum efx_dl_falcon_resource_flags - Falcon resource information flags.
543 + * Flags that describe hardware variations for the current Falcon device.
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
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
554 +enum efx_dl_falcon_resource_flags {
555 + EFX_DL_FALCON_DUAL_FUNC = 0x1,
556 + EFX_DL_FALCON_USE_MSI = 0x2,
560 + * struct efx_dl_falcon_resources - Falcon resource information.
562 + * This structure describes Falcon hardware resources available for
563 + * use by a driverlink driver.
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
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;
596 + enum efx_dl_falcon_resource_flags flags;
600 + * struct efx_dl_device - An Efx driverlink device.
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
610 +struct efx_dl_device {
611 + struct pci_dev *pci_dev;
613 + struct efx_dl_driver *driver;
617 + * enum efx_veto - Packet veto request flag.
619 + * This is the return type for the rx_packet() and tx_packet() methods
620 + * in &struct efx_dl_callbacks.
622 + * @EFX_ALLOW_PACKET: Packet may be transmitted/received
623 + * @EFX_VETO_PACKET: Packet must not be transmitted/received
626 + EFX_ALLOW_PACKET = 0,
627 + EFX_VETO_PACKET = 1,
631 + * struct efx_dl_callbacks - Efx callbacks
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.
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.
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.
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.
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);
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)
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.
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.
690 +extern int efx_dl_register_driver(struct efx_dl_driver *driver);
692 +extern void efx_dl_unregister_driver(struct efx_dl_driver *driver);
694 +extern int efx_dl_register_callbacks(struct efx_dl_device *efx_dev,
695 + struct efx_dl_callbacks *callbacks);
697 +extern void efx_dl_unregister_callbacks(struct efx_dl_device *efx_dev,
698 + struct efx_dl_callbacks *callbacks);
700 +/* Schedule a reset without grabbing any locks */
701 +extern void efx_dl_schedule_reset(struct efx_dl_device *efx_dev);
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
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,
716 + * if (res->flags & EFX_DL_FALCON_DUAL_FUNC)
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); \
724 + (_p) = container_of((_p)->_field.next, _info_type, _field))\
725 + if ((_p)->_field.type != _type) \
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
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);
744 +#define efx_dl_search_device_info(_dev_info, _type, _info_type, \
746 + efx_dl_for_each_device_info_matching((_dev_info), (_type), \
747 + _info_type, _field, (_p)) \
750 +#endif /* EFX_DRIVERLINK_API_H */
751 Index: 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
759 + /* Ask driverlink client if we can change MTU */
760 + rc = EFX_DL_CALLBACK(efx, request_mtu, new_mtu);
764 EFX_LOG(efx, "changing MTU to %d\n", new_mtu);
766 efx_fini_channels(efx);
767 @@ -1435,6 +1440,10 @@ static int efx_change_mtu(struct net_dev
771 + /* Notify driverlink client of new MTU */
772 + EFX_DL_CALLBACK(efx, mtu_changed, new_mtu);
778 @@ -1587,6 +1596,23 @@ static void efx_unregister_netdev(struct
779 * Device reset and suspend
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)
786 + EFX_LOG(efx, "suspending operations\n");
792 +void efx_resume(struct efx_nic *efx)
794 + EFX_LOG(efx, "resuming operations\n");
796 + efx_start_all(efx);
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;
806 - /* Serialise with kernel interfaces */
808 + efx_dl_reset_suspend(efx);
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
816 + efx_dl_reset_resume(efx, 1);
820 @@ -1729,6 +1756,7 @@ static int efx_reset(struct efx_nic *efx
821 efx->state = STATE_DISABLED;
823 mutex_unlock(&efx->mac_lock);
824 + efx_dl_reset_resume(efx, 0);
826 efx_unregister_netdev(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);
838 @@ -1990,6 +2021,7 @@ static void efx_pci_remove(struct pci_de
839 efx = pci_get_drvdata(pci_dev);
842 + efx_dl_unregister_nic(efx);
844 /* Mark the NIC as fini, then stop the interface */
846 @@ -2157,8 +2189,15 @@ static int __devinit efx_pci_probe(struc
848 EFX_LOG(efx, "initialisation successful\n");
850 + /* Register with driverlink layer */
851 + rc = efx_dl_register_nic(efx);
858 + efx_unregister_netdev(efx);
860 efx_pci_remove_main(efx);
862 Index: 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
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
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;
881 @@ -322,8 +322,8 @@ static int falcon_alloc_special_buffer(s
882 memset(buffer->addr, 0xff, len);
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;
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);
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);
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",
909 + EFX_DL_CALLBACK(efx, event, event);
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);
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);
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,
927 + EFX_DL_CALLBACK(efx, event, event);
931 @@ -2371,6 +2377,59 @@ static int falcon_probe_nvconfig(struct
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
938 +static int falcon_dimension_resources(struct efx_nic *efx)
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;
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;
949 + /* NB. The minimum values get increased as this driver initialises
950 + * its resources, so this should prevent any overlap.
952 + switch (falcon_rev(efx)) {
953 + case FALCON_REV_A1:
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;
962 + case FALCON_REV_B0:
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;
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;
979 + if (FALCON_IS_DUAL_FUNC(efx))
980 + res->flags |= EFX_DL_FALCON_DUAL_FUNC;
982 + if (EFX_INT_MODE_USE_MSI(efx))
983 + res->flags |= EFX_DL_FALCON_USE_MSI;
988 /* Probe the NIC variant (revision, ASIC vs FPGA, function count, port
989 * count, port speed). Set workaround and feature flags accordingly.
991 @@ -2403,10 +2462,12 @@ static int falcon_probe_nic_variant(stru
992 EFX_ERR(efx, "1G mode not supported\n");
995 + efx->silicon_rev = "falcon/a1";
1000 + efx->silicon_rev = "falcon/b0";
1004 @@ -2472,6 +2533,10 @@ int falcon_probe_nic(struct efx_nic *efx
1008 + rc = falcon_dimension_resources(efx);
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);
1025 + efx->dl_info = NULL;
1027 falcon_free_buffer(efx, &efx->irq_status);
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;
1036 void falcon_update_nic_stats(struct efx_nic *efx)
1037 Index: 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
1044 #include "bitfield.h"
1045 +#include "driverlink_api.h"
1046 +#include "driverlink.h"
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
1061 * The @priv field of the corresponding &struct net_device points to
1063 @@ -752,6 +760,13 @@ struct efx_nic {
1064 unsigned int loopback_modes;
1066 void *loopback_selftest;
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;
1076 static inline int efx_dev_registered(struct efx_nic *efx)
1077 Index: 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)
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;
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);
1102 /* Pass the skb/page into the LRO engine */
1104 @@ -686,6 +700,7 @@ void __efx_rx_packet(struct efx_channel
1105 struct efx_rx_buffer *rx_buf, int checksummed)
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;
1112 @@ -723,6 +738,16 @@ void __efx_rx_packet(struct efx_channel
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);
1126 /* Form an skb if required */
1128 int hdr_len = min(rx_buf->len, EFX_SKB_HEADERS);
1129 Index: 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)
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;
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;
1152 + return efx_xmit(efx, tx_queue, skb);
1155 void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)