- supported.conf: Added sparse_keymap (eeepc_laptop depends on it)
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / sfc_netutil / accel_msg_iface.h
1 /****************************************************************************
2  * Solarflare driver for Xen network acceleration
3  *
4  * Copyright 2006-2008: Solarflare Communications Inc,
5  *                      9501 Jeronimo Road, Suite 250,
6  *                      Irvine, CA 92618, USA
7  *
8  * Maintained by Solarflare Communications <linux-xen-drivers@solarflare.com>
9  *
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.
13  *
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.
18  *
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  ****************************************************************************
23  */
24
25 #ifndef NET_ACCEL_MSG_IFACE_H
26 #define NET_ACCEL_MSG_IFACE_H
27
28 #include <linux/ip.h>
29 #include <linux/tcp.h>
30 #include <linux/udp.h>
31 #include <linux/in.h>
32 #include <linux/netdevice.h>
33 #include <linux/etherdevice.h>
34
35 #include "accel_shared_fifo.h"
36
37 #define NET_ACCEL_MSG_MAGIC (0x85465479)
38
39 /*! We talk version 0.010 of the interdomain protocol */
40 #define NET_ACCEL_MSG_VERSION (0x00001000)
41
42 /*! Shared memory portion of inter-domain FIFO */
43 struct net_accel_msg_queue {
44         u32 read;
45         u32 write;
46 };
47
48
49 /*
50  * The aflags in the following structure is used as follows:
51  *
52  *  - each bit is set when one of the corresponding variables is
53  *  changed by either end.
54  *
55  *  - the end that has made the change then forwards an IRQ to the
56  *  other
57  *
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.
60  *
61  *  - once it has seen a change, it clears the relevant bit.
62  *
63  * aflags is accessed atomically using clear_bit, test_bit,
64  * test_and_set_bit etc
65  */
66
67 /*
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
71  * clarity
72  */
73
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
89
90 /*
91  * Masks used to test if there are any messages for domU and dom0
92  * respectively
93  */
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)
101
102 /*! The shared data structure used for inter-VM communication. */
103 struct net_accel_shared_page {
104         /*! Sanity check */
105         u32 magic;          
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 */
111         u32 aflags;     
112         /*! State of net_dev used for acceleration */     
113         u32 net_dev_up; 
114 };
115
116
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,
124 };
125
126 /*! The maximum number of pages used by an event queue. */
127 #define EF_HW_FALCON_EVQ_PAGES 8
128
129 struct net_accel_hw_falcon_b {
130         /* VI */
131         /*! Grant for Tx DMA Q */
132         u32 txdmaq_gnt;   
133         /*! Grant for Rx DMA Q */
134         u32 rxdmaq_gnt;   
135         /*! Machine frame number for Tx/Rx doorbell page */
136         u32 doorbell_mfn; 
137         /*! Grant for Tx/Rx doorbell page */
138         u32 doorbell_gnt;
139
140         /* Event Q */
141         /*! Grants for the pages of the EVQ */
142         u32 evq_mem_gnts[EF_HW_FALCON_EVQ_PAGES]; 
143         u32 evq_offs;
144         /*! log2(pages in event Q) */
145         u32 evq_order;    
146         /*! Capacity in events */
147         u32 evq_capacity; 
148         /*! Eventq pointer register physical address */
149         u32 evq_rptr; 
150         /*! Interface instance */
151         u32 instance; 
152         /*! Capacity of RX queue */
153         u32 rx_capacity;
154         /*! Capacity of TX queue */
155         u32 tx_capacity;
156
157         /* NIC */
158         s32 nic_arch;
159         s32 nic_revision;
160         u8 nic_variant;
161 };
162
163 struct net_accel_hw_falcon_a {
164         struct net_accel_hw_falcon_b common;
165         u32 evq_rptr_gnt;
166 };
167
168
169 /*! Description of the hardware that the DomU is being given. */
170 struct net_accel_msg_hw {
171         u32 type;               /*!< Hardware type */
172         union {
173                 struct net_accel_hw_falcon_a falcon_a;
174                 struct net_accel_hw_falcon_b falcon_b;
175         } resources;
176 };
177
178 /*! Start-of-day handshake message. Dom0 fills in its version and
179  * sends, DomU checks, inserts its version and replies
180  */
181 struct net_accel_msg_hello {
182         /*! Sender's version (set by each side in turn) */
183         u32 version;    
184         /*! max pages allocated/allowed for buffers */
185         u32 max_pages;      
186 };
187
188 /*! Maximum number of page requests that can fit in a message. */
189 #define NET_ACCEL_MSG_MAX_PAGE_REQ (8)
190
191 /*! Request for NIC buffers. DomU fils out pages and grants (and
192  *  optionally) reqid, dom0 fills out buf and sends reply 
193  */
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 */
199 };
200
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 */
206 };
207
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) */
214 };
215
216 /*! Values for struct ef_msg_localmac/fastpath.flags */
217 #define NET_ACCEL_MSG_ADD    0x1
218 #define NET_ACCEL_MSG_REMOVE 0x2
219
220 /*! Overall message structure */
221 struct net_accel_msg {
222         /*! ID specifying type of messge */
223         u32 id;              
224         union {
225                 /*! handshake */
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)]; 
237         }  u;
238 };
239
240
241 #define NET_ACCEL_MSG_HW_TO_MSG(_u) container_of(_u, struct net_accel_msg, u.hw)
242
243 /*! Inter-domain message FIFO */
244 typedef struct {
245         struct net_accel_msg *fifo;
246         u32 fifo_mask;
247         u32 *fifo_rd_i;
248         u32 *fifo_wr_i;
249         spinlock_t lock;
250         u32 is_locked; /* Debug flag */
251 } sh_msg_fifo2;
252
253
254 #define NET_ACCEL_MSG_OFFSET_MASK PAGE_MASK
255
256 /* Modifiers */
257 #define NET_ACCEL_MSG_REPLY    (0x80000000)
258 #define NET_ACCEL_MSG_ERROR    (0x40000000)
259
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)
264 /*
265  * Dom0 -> DomU. Notification of a local mac to add/remove from slow
266  * path filter
267  */
268 #define NET_ACCEL_MSG_LOCALMAC (0x00000003)
269 /* 
270  * DomU -> Dom0 and reply. Request for buffer table entries for
271  * preallocated pages.
272  */
273 #define NET_ACCEL_MSG_MAPBUF   (0x00000004)
274 /* 
275  * Dom0 -> DomU. Notification of a local mac to add/remove from fast
276  * path filter
277  */
278 #define NET_ACCEL_MSG_FASTPATH (0x00000005)
279
280 /*! Initialise a message and set the type
281  * \param message : the message
282  * \param code : the message type 
283  */
284 static inline void net_accel_msg_init(struct net_accel_msg *msg, int code) {
285         msg->id = (u32)code;
286 }
287
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
293  */
294 extern int net_accel_msg_init_page(void *shared_page, int len, int up);
295
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
301  */
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);
305
306 /* Notify after a batch of messages have been sent */
307 extern void net_accel_msg_notify(int irq);
308
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
315  */ 
316 extern int net_accel_msg_send(struct net_accel_shared_page *sp,
317                               sh_msg_fifo2 *q, 
318                               struct net_accel_msg *msg);
319 extern int net_accel_msg_reply(struct net_accel_shared_page *sp,
320                               sh_msg_fifo2 *q, 
321                               struct net_accel_msg *msg);
322
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);
331
332 /*! Receive a message on the specified FIFO. Returns 0 on success,
333  *  -errno on failure.
334  */
335 extern int net_accel_msg_recv(struct net_accel_shared_page *sp,
336                               sh_msg_fifo2 *q,
337                               struct net_accel_msg *msg);
338
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()
343  */
344 extern int net_accel_msg_peek(struct net_accel_shared_page *sp,
345                               sh_msg_fifo2 *queue, 
346                               struct net_accel_msg *msg, int *cookie);
347 /*! Move the queue onto the next element, used after finished with a
348  *  peeked msg 
349  */
350 extern int net_accel_msg_recv_next(struct net_accel_shared_page *sp,
351                                    sh_msg_fifo2 *queue, int cookie);
352
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.
356  */
357 extern 
358 struct net_accel_msg *net_accel_msg_start_send(struct net_accel_shared_page *sp,
359                                                sh_msg_fifo2 *queue,
360                                                unsigned long *flags);
361
362
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 
366  */
367 extern void net_accel_msg_complete_send(struct net_accel_shared_page *sp,
368                                         sh_msg_fifo2 *queue,
369                                         unsigned long *flags);
370
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, 
373                                                sh_msg_fifo2 *queue,
374                                                unsigned long *flags, int irq);
375
376 /*! Lock the queue so that multiple "_locked" functions can be called
377  *  without the queue being modified by others 
378  */
379 static inline
380 void net_accel_msg_lock_queue(sh_msg_fifo2 *queue, unsigned long *flags)
381 {
382         spin_lock_irqsave(&queue->lock, (*flags));
383         rmb();
384         BUG_ON(queue->is_locked);
385         queue->is_locked = 1;
386 }
387
388 /*! Unlock the queue */
389 static inline
390 void net_accel_msg_unlock_queue(sh_msg_fifo2 *queue, unsigned long *flags)
391 {
392         BUG_ON(!queue->is_locked);
393         queue->is_locked = 0;
394         wmb();
395         spin_unlock_irqrestore(&queue->lock, (*flags));
396 }
397
398 /*! Give up without sending a message that was started with
399  *  net_accel_msg_start_send() 
400  */
401 static inline 
402 void net_accel_msg_abort_send(struct net_accel_shared_page *sp,
403                               sh_msg_fifo2 *queue, unsigned long *flags)
404 {
405         net_accel_msg_unlock_queue(queue, flags);
406 }
407
408 /*! Test the queue to ensure there is sufficient space */
409 static inline
410 int net_accel_msg_check_space(sh_msg_fifo2 *queue, unsigned space)
411 {
412         return sh_fifo2_space(queue) >= space;
413 }
414
415 #endif /* NET_ACCEL_MSG_IFACE_H */