e10k: enabling requesting default queue
[barrelfish] / lib / net_interfaces / interface_raw.c
1 /*
2  * Copyright (c) 2007-2012, ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
8  */
9
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include <barrelfish/barrelfish.h>
16 #include <barrelfish/waitset.h>
17 #include <barrelfish/nameservice_client.h>
18 #include <net_interfaces/net_interfaces.h>
19
20 #include <barrelfish/net_constants.h>
21 #include <devif/queue_interface.h>
22 #include <devif/backends/descq.h>
23 #if defined(__x86_64__)
24     #include <devif/backends/net/sfn5122f_devif.h>
25     #include <devif/backends/net/e10k_devif.h>
26 #endif
27
28 #define MAX_SERVICE_NAME_LEN  256   // Max len that a name of service can have
29 #define BUFFER_SIZE 2048
30 #define BUFFER_COUNT ((128*1024*1024) / BUFFER_SIZE)
31
32 static uint64_t queue_id = 0;
33 static uint64_t card_mac = -1ULL;
34
35 static struct devq *devq = NULL;
36 static regionid_t regid;
37 static uint64_t bufid;
38
39
40 static struct capref buffer_frame;
41 void *buffer_base = NULL;
42 size_t buffer_size = 2048;
43 size_t buffer_count = BUFFER_COUNT;
44
45
46 /******************************************************************************/
47 /* Buffer management */
48
49 errval_t buffer_tx_add(size_t idx, size_t offset, size_t length,
50                        size_t more_chunks, uint64_t flags)
51 {
52     errval_t err;
53     uint64_t flags_new = flags | NETIF_TXFLAG | NETIF_TXFLAG_LAST;
54
55     
56     offset += idx * BUFFER_SIZE;
57     err = devq_enqueue((struct devq *)devq, regid, offset, 
58                        length, 0, length, flags_new);
59     return err;
60 }
61
62 errval_t buffer_rx_add(size_t idx)
63 {
64     errval_t err;
65     size_t offset;
66     uint64_t flags = NETIF_RXFLAG;
67
68     offset = idx * BUFFER_SIZE;
69     err = devq_enqueue((struct devq *)devq, regid, offset, BUFFER_SIZE, 
70                            0, BUFFER_SIZE, flags);
71     return err;
72 }
73
74
75 static void alloc_mem(struct capref *frame, void** virt, size_t size)
76 {
77     errval_t r;
78     vregion_flags_t flags;
79
80     r = frame_alloc(frame, size, NULL);
81     if (!err_is_ok(r)) {
82         USER_PANIC("Allocating memory region frame failed!");
83     }
84
85     flags = VREGION_FLAGS_READ_WRITE;
86     r = vspace_map_one_frame_attr(virt, size, *frame, flags, NULL, NULL);
87     if (!err_is_ok(r)) {
88         USER_PANIC("Mapping memory region frame failed!");
89     }
90     memset(*virt, 0, size);
91 }
92
93 static void buffers_init(size_t count)
94 {
95     errval_t err;
96     alloc_mem(&buffer_frame, &buffer_base, BUFFER_SIZE * count);
97
98     err = devq_register((struct devq *)devq, buffer_frame, &regid);
99     assert(err_is_ok(err));
100 }
101
102
103 /******************************************************************************/
104 /* Flounder interface */
105
106 // Returns the bufferid for specified type (RX, TX)
107 uint64_t get_rx_bufferid(void)
108 {
109     return bufid;
110 }
111
112 uint64_t get_tx_bufferid(void)
113 {
114     return bufid;
115 }
116
117 static errval_t notify_handler(struct descq *queue)  
118 {
119     regionid_t rid;
120     genoffset_t offset;
121     genoffset_t length;
122     genoffset_t valid_data;
123     genoffset_t valid_length;
124     uint64_t flags;
125     int count = 0;
126
127     for(;;){
128         errval_t err;
129         err = devq_dequeue((struct devq*) queue, &rid, &offset, &length,
130                            &valid_data, &valid_length, &flags);
131         if (err_is_fail(err))
132             break;
133
134         count++;
135         size_t idx = offset / BUFFER_SIZE;
136         if (flags & NETIF_TXFLAG) {
137             benchmark_tx_done(idx);
138         } else if (flags & NETIF_RXFLAG) {
139             assert(valid_length > 0);
140             benchmark_rx_done(idx, valid_length, 0/*more*/, flags);
141         }
142     }
143     return SYS_ERR_OK;
144 }
145
146
147 static void connect_to_driver(const char *cname, uint64_t qid, struct waitset *ws)
148 {
149     errval_t err;
150     char qm_name[MAX_SERVICE_NAME_LEN] = { 0 };
151
152     snprintf(qm_name, sizeof(qm_name), "%s_%"PRIu64"", cname, qid);
153     debug_printf("%s: nqm bind [%s]\n", __func__, qm_name);
154
155     struct descq* q;
156     struct descq_func_pointer f;
157     f.notify = notify_handler;
158     
159     err = descq_create(&q, DESCQ_DEFAULT_SIZE, qm_name,
160                        false, true, 0, &bufid, &f);
161     assert(err_is_ok(err));
162     devq = (struct devq*) q;
163 }
164
165
166 #if defined(__x86_64__)
167 static void int_handler(void* args)
168 {
169     regionid_t rid;
170     genoffset_t offset;
171     genoffset_t length;
172     genoffset_t valid_data;
173     genoffset_t valid_length;
174     uint64_t flags;
175     int count = 0;
176
177     for(;;){
178         errval_t err;
179         err = devq_dequeue(devq, &rid, &offset, &length,
180                            &valid_data, &valid_length, &flags);
181         if (err_is_fail(err))
182             break;
183
184         count++;
185         size_t idx = offset / BUFFER_SIZE;
186         if (flags & NETIF_TXFLAG) {
187             benchmark_tx_done(idx);
188         } else if (flags & NETIF_RXFLAG) {
189             if (valid_length == 0) {
190                 printf("rid %d \n", rid);
191                 printf("offset %lx \n", offset);
192                 printf("length %lu \n", length);
193                 printf("valid_data %lu \n", valid_data);
194                 printf("valid_length %lu \n", valid_length);
195             }
196             assert(valid_length > 0);
197             benchmark_rx_done(idx, valid_length, 0/*more*/, flags);
198         }
199     }
200
201 }
202 #endif
203
204 void net_if_init(const char* cardname, uint64_t qid)
205 {
206     errval_t err;
207     static bool initialized = false;
208     struct waitset *ws = get_default_waitset();
209
210     // Only initialize once
211     if (initialized) {
212         return;
213     }
214
215     queue_id = qid;
216
217     // Connect RX path
218
219 #if defined(__x86_64__)
220     if ((strcmp(cardname, "e1000") == 0) || (qid == 0)) {
221         connect_to_driver(cardname, queue_id, ws);
222     } else if ((strcmp(cardname, "e10k") == 0) && (qid != 0)) {
223         USER_PANIC("e10k queue NIY \n"); 
224         struct e10k_queue* e10k;
225         err = e10k_queue_create(&e10k, int_handler, false, true, false);
226         assert(err_is_ok(err));
227
228         devq = (struct devq*) e10k; 
229         card_mac = 0x1; // TODO 
230     } else if ((strcmp(cardname, "sfn5122f") == 0) && qid != 0) {
231         struct sfn5122f_queue* sfn5122f;
232         err = sfn5122f_queue_create(&sfn5122f, int_handler, 
233                                     false /*userlevel network feature*/, 
234                                     true /* user interrupts*/,
235                                     false);
236         assert(err_is_ok(err));
237
238         devq = (struct devq*) sfn5122f; 
239     } else {
240         USER_PANIC("Unknown card name \n");
241     }
242
243 #else 
244     connect_to_driver(cardname, queue_id, ws);
245 #endif
246     buffers_init(BUFFER_COUNT);
247
248     // Get MAC address
249     err = devq_control((struct devq *)devq, 0, 0, &card_mac);
250     assert(err_is_ok(err));
251
252     initialized = true;
253 }
254
255 void net_if_terminate(void)
256 {
257     vspace_unmap(buffer_base);
258     cap_delete(buffer_frame);
259 }
260
261 void benchmark_get_mac_address(uint8_t *mac)
262 {
263     memcpy(mac, &card_mac, 6);
264 }