1 /****************************************************************************
2 * Solarflare driver for Xen network acceleration
4 * Copyright 2006-2008: Solarflare Communications Inc,
5 * 9501 Jeronimo Road, Suite 250,
6 * Irvine, CA 92618, USA
8 * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published
12 * by the Free Software Foundation, incorporated herein by reference.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 ****************************************************************************
25 #ifndef NET_ACCEL_MSG_IFACE_H
26 #define NET_ACCEL_MSG_IFACE_H
29 #include <linux/tcp.h>
30 #include <linux/udp.h>
32 #include <linux/netdevice.h>
33 #include <linux/etherdevice.h>
35 #include "accel_shared_fifo.h"
37 #define NET_ACCEL_MSG_MAGIC (0x85465479)
39 /*! We talk version 0.010 of the interdomain protocol */
40 #define NET_ACCEL_MSG_VERSION (0x00001000)
42 /*! Shared memory portion of inter-domain FIFO */
43 struct net_accel_msg_queue {
50 * The aflags in the following structure is used as follows:
52 * - each bit is set when one of the corresponding variables is
53 * changed by either end.
55 * - the end that has made the change then forwards an IRQ to the
58 * - the IRQ handler deals with these bits either on the fast path, or
59 * for less common changes, by jumping onto the slow path.
61 * - once it has seen a change, it clears the relevant bit.
63 * aflags is accessed atomically using clear_bit, test_bit,
64 * test_and_set_bit etc
68 * The following used to signify to the other domain when the queue
69 * they want to use is full, and when it is no longer full. Could be
70 * compressed to use fewer bits but done this way for simplicity and
74 /* "dom0->domU queue" is full */
75 #define NET_ACCEL_MSG_AFLAGS_QUEUE0FULL 0x1
76 #define NET_ACCEL_MSG_AFLAGS_QUEUE0FULL_B 0
77 /* "dom0->domU queue" is not full */
78 #define NET_ACCEL_MSG_AFLAGS_QUEUE0NOTFULL 0x2
79 #define NET_ACCEL_MSG_AFLAGS_QUEUE0NOTFULL_B 1
80 /* "domU->dom0 queue" is full */
81 #define NET_ACCEL_MSG_AFLAGS_QUEUEUFULL 0x4
82 #define NET_ACCEL_MSG_AFLAGS_QUEUEUFULL_B 2
83 /* "domU->dom0 queue" is not full */
84 #define NET_ACCEL_MSG_AFLAGS_QUEUEUNOTFULL 0x8
85 #define NET_ACCEL_MSG_AFLAGS_QUEUEUNOTFULL_B 3
86 /* dom0 -> domU net_dev up/down events */
87 #define NET_ACCEL_MSG_AFLAGS_NETUPDOWN 0x10
88 #define NET_ACCEL_MSG_AFLAGS_NETUPDOWN_B 4
91 * Masks used to test if there are any messages for domU and dom0
94 #define NET_ACCEL_MSG_AFLAGS_TO_DOMU_MASK \
95 (NET_ACCEL_MSG_AFLAGS_QUEUE0FULL | \
96 NET_ACCEL_MSG_AFLAGS_QUEUEUNOTFULL | \
97 NET_ACCEL_MSG_AFLAGS_NETUPDOWN)
98 #define NET_ACCEL_MSG_AFLAGS_TO_DOM0_MASK \
99 (NET_ACCEL_MSG_AFLAGS_QUEUE0NOTFULL | \
100 NET_ACCEL_MSG_AFLAGS_QUEUEUFULL)
102 /*! The shared data structure used for inter-VM communication. */
103 struct net_accel_shared_page {
106 /*! Used by host/Dom0 */
107 struct net_accel_msg_queue queue0;
108 /*! Used by guest/DomU */
109 struct net_accel_msg_queue queue1;
110 /*! Atomic flags, used to communicate simple state changes */
112 /*! State of net_dev used for acceleration */
117 enum net_accel_hw_type {
118 /*! Not a virtualisable NIC: use slow path. */
119 NET_ACCEL_MSG_HWTYPE_NONE = 0,
120 /*! NIC is Falcon-based */
121 NET_ACCEL_MSG_HWTYPE_FALCON_A = 1,
122 NET_ACCEL_MSG_HWTYPE_FALCON_B = 2,
123 NET_ACCEL_MSG_HWTYPE_SIENA_A = 3,
126 /*! The maximum number of pages used by an event queue. */
127 #define EF_HW_FALCON_EVQ_PAGES 8
129 struct net_accel_hw_falcon_b {
131 /*! Grant for Tx DMA Q */
133 /*! Grant for Rx DMA Q */
135 /*! Machine frame number for Tx/Rx doorbell page */
137 /*! Grant for Tx/Rx doorbell page */
141 /*! Grants for the pages of the EVQ */
142 u32 evq_mem_gnts[EF_HW_FALCON_EVQ_PAGES];
144 /*! log2(pages in event Q) */
146 /*! Capacity in events */
148 /*! Eventq pointer register physical address */
150 /*! Interface instance */
152 /*! Capacity of RX queue */
154 /*! Capacity of TX queue */
163 struct net_accel_hw_falcon_a {
164 struct net_accel_hw_falcon_b common;
169 /*! Description of the hardware that the DomU is being given. */
170 struct net_accel_msg_hw {
171 u32 type; /*!< Hardware type */
173 struct net_accel_hw_falcon_a falcon_a;
174 struct net_accel_hw_falcon_b falcon_b;
178 /*! Start-of-day handshake message. Dom0 fills in its version and
179 * sends, DomU checks, inserts its version and replies
181 struct net_accel_msg_hello {
182 /*! Sender's version (set by each side in turn) */
184 /*! max pages allocated/allowed for buffers */
188 /*! Maximum number of page requests that can fit in a message. */
189 #define NET_ACCEL_MSG_MAX_PAGE_REQ (8)
191 /*! Request for NIC buffers. DomU fils out pages and grants (and
192 * optionally) reqid, dom0 fills out buf and sends reply
194 struct net_accel_msg_map_buffers {
195 u32 reqid; /*!< Optional request ID */
196 u32 pages; /*!< Number of pages to map */
197 u32 grants[NET_ACCEL_MSG_MAX_PAGE_REQ]; /*!< Grant ids to map */
198 u32 buf; /*!< NIC buffer address of pages obtained */
201 /*! Notification of a change to local mac address, used to filter
202 locally destined packets off the fast path */
203 struct net_accel_msg_localmac {
204 u32 flags; /*!< Should this be added or removed? */
205 u8 mac[ETH_ALEN]; /*!< The mac address to filter onto slow path */
208 struct net_accel_msg_fastpath {
209 u32 flags; /*!< Should this be added or removed? */
210 u8 mac[ETH_ALEN];/*!< The mac address to filter onto fast path */
211 u16 port; /*!< The port of the connection */
212 u32 ip; /*!< The IP address of the connection */
213 u8 proto; /*!< The protocol of connection (TCP/UDP) */
216 /*! Values for struct ef_msg_localmac/fastpath.flags */
217 #define NET_ACCEL_MSG_ADD 0x1
218 #define NET_ACCEL_MSG_REMOVE 0x2
220 /*! Overall message structure */
221 struct net_accel_msg {
222 /*! ID specifying type of messge */
226 struct net_accel_msg_hello hello;
227 /*! hardware description */
228 struct net_accel_msg_hw hw;
229 /*! buffer map request */
230 struct net_accel_msg_map_buffers mapbufs;
231 /*! mac address of a local interface */
232 struct net_accel_msg_localmac localmac;
233 /*! address of a new fastpath connection */
234 struct net_accel_msg_fastpath fastpath;
235 /*! make the message a fixed size */
236 u8 pad[128 - sizeof(u32)];
241 #define NET_ACCEL_MSG_HW_TO_MSG(_u) container_of(_u, struct net_accel_msg, u.hw)
243 /*! Inter-domain message FIFO */
245 struct net_accel_msg *fifo;
250 u32 is_locked; /* Debug flag */
254 #define NET_ACCEL_MSG_OFFSET_MASK PAGE_MASK
257 #define NET_ACCEL_MSG_REPLY (0x80000000)
258 #define NET_ACCEL_MSG_ERROR (0x40000000)
260 /* Dom0 -> DomU and reply. Handshake/version check. */
261 #define NET_ACCEL_MSG_HELLO (0x00000001)
262 /* Dom0 -> DomU : hardware setup (VI info.) */
263 #define NET_ACCEL_MSG_SETHW (0x00000002)
265 * Dom0 -> DomU. Notification of a local mac to add/remove from slow
268 #define NET_ACCEL_MSG_LOCALMAC (0x00000003)
270 * DomU -> Dom0 and reply. Request for buffer table entries for
271 * preallocated pages.
273 #define NET_ACCEL_MSG_MAPBUF (0x00000004)
275 * Dom0 -> DomU. Notification of a local mac to add/remove from fast
278 #define NET_ACCEL_MSG_FASTPATH (0x00000005)
280 /*! Initialise a message and set the type
281 * \param message : the message
282 * \param code : the message type
284 static inline void net_accel_msg_init(struct net_accel_msg *msg, int code) {
288 /*! initialise a shared page structure
289 * \param shared_page : mapped memory in which the structure resides
290 * \param len : size of the message FIFO area that follows
291 * \param up : initial up/down state of netdev
292 * \return 0 or an error code
294 extern int net_accel_msg_init_page(void *shared_page, int len, int up);
296 /*! initialise a message queue
297 * \param queue : the message FIFO to initialise
298 * \param indices : the read and write indices in shared memory
299 * \param base : the start of the memory area for the FIFO
300 * \param size : the size of the FIFO in bytes
302 extern void net_accel_msg_init_queue(sh_msg_fifo2 *queue,
303 struct net_accel_msg_queue *indices,
304 struct net_accel_msg *base, int size);
306 /* Notify after a batch of messages have been sent */
307 extern void net_accel_msg_notify(int irq);
309 /*! Send a message on the specified FIFO. The message is copied to the
310 * current slot of the FIFO.
311 * \param sp : pointer to shared page
312 * \param q : pointer to message FIFO to use
313 * \param msg : pointer to message
314 * \return 0 on success, -errno on
316 extern int net_accel_msg_send(struct net_accel_shared_page *sp,
318 struct net_accel_msg *msg);
319 extern int net_accel_msg_reply(struct net_accel_shared_page *sp,
321 struct net_accel_msg *msg);
323 /*! As net_accel_msg_send but also posts a notification to the far end. */
324 extern int net_accel_msg_send_notify(struct net_accel_shared_page *sp,
325 int irq, sh_msg_fifo2 *q,
326 struct net_accel_msg *msg);
327 /*! As net_accel_msg_send but also posts a notification to the far end. */
328 extern int net_accel_msg_reply_notify(struct net_accel_shared_page *sp,
329 int irq, sh_msg_fifo2 *q,
330 struct net_accel_msg *msg);
332 /*! Receive a message on the specified FIFO. Returns 0 on success,
335 extern int net_accel_msg_recv(struct net_accel_shared_page *sp,
337 struct net_accel_msg *msg);
339 /*! Look at a received message, if any, so a decision can be made
340 * about whether to read it now or not. Cookie is a bit of debug
341 * which is set here and checked when passed to
342 * net_accel_msg_recv_next()
344 extern int net_accel_msg_peek(struct net_accel_shared_page *sp,
346 struct net_accel_msg *msg, int *cookie);
347 /*! Move the queue onto the next element, used after finished with a
350 extern int net_accel_msg_recv_next(struct net_accel_shared_page *sp,
351 sh_msg_fifo2 *queue, int cookie);
353 /*! Start sending a message without copying. returns a pointer to a
354 * message that will be filled out in place. The queue is locked
355 * until the message is sent.
358 struct net_accel_msg *net_accel_msg_start_send(struct net_accel_shared_page *sp,
360 unsigned long *flags);
363 /*! Complete the sending of a message started with
364 * net_accel_msg_start_send. The message is implicit since the queue
365 * was locked by _start
367 extern void net_accel_msg_complete_send(struct net_accel_shared_page *sp,
369 unsigned long *flags);
371 /*! As net_accel_msg_complete_send but does the notify. */
372 extern void net_accel_msg_complete_send_notify(struct net_accel_shared_page *sp,
374 unsigned long *flags, int irq);
376 /*! Lock the queue so that multiple "_locked" functions can be called
377 * without the queue being modified by others
380 void net_accel_msg_lock_queue(sh_msg_fifo2 *queue, unsigned long *flags)
382 spin_lock_irqsave(&queue->lock, (*flags));
384 BUG_ON(queue->is_locked);
385 queue->is_locked = 1;
388 /*! Unlock the queue */
390 void net_accel_msg_unlock_queue(sh_msg_fifo2 *queue, unsigned long *flags)
392 BUG_ON(!queue->is_locked);
393 queue->is_locked = 0;
395 spin_unlock_irqrestore(&queue->lock, (*flags));
398 /*! Give up without sending a message that was started with
399 * net_accel_msg_start_send()
402 void net_accel_msg_abort_send(struct net_accel_shared_page *sp,
403 sh_msg_fifo2 *queue, unsigned long *flags)
405 net_accel_msg_unlock_queue(queue, flags);
408 /*! Test the queue to ensure there is sufficient space */
410 int net_accel_msg_check_space(sh_msg_fifo2 *queue, unsigned space)
412 return sh_fifo2_space(queue) >= space;
415 #endif /* NET_ACCEL_MSG_IFACE_H */