Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/xen/io/xnbu.c
+++ new/usr/src/uts/common/xen/io/xnbu.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * Xen inter-domain backend - GLDv3 driver edition.
29 29 *
30 30 * A traditional GLDv3 driver used to communicate with a guest
31 31 * domain. This driver is typically plumbed underneath the IP stack
32 32 * or a software ethernet bridge.
33 33 */
34 34
35 35 #include "xnb.h"
36 36
37 37 #include <sys/sunddi.h>
38 38 #include <sys/conf.h>
39 39 #include <sys/modctl.h>
40 40 #include <sys/strsubr.h>
41 41 #include <sys/dlpi.h>
42 42 #include <sys/pattr.h>
43 43 #include <sys/mac_provider.h>
44 44 #include <sys/mac_ether.h>
45 45 #include <xen/sys/xendev.h>
46 46 #include <sys/note.h>
47 47
48 48 /* Required driver entry points for GLDv3 */
49 49 static int xnbu_m_start(void *);
50 50 static void xnbu_m_stop(void *);
51 51 static int xnbu_m_set_mac_addr(void *, const uint8_t *);
52 52 static int xnbu_m_set_multicast(void *, boolean_t, const uint8_t *);
53 53 static int xnbu_m_set_promiscuous(void *, boolean_t);
54 54 static int xnbu_m_stat(void *, uint_t, uint64_t *);
55 55 static boolean_t xnbu_m_getcapab(void *, mac_capab_t, void *);
56 56 static mblk_t *xnbu_m_send(void *, mblk_t *);
57 57
58 58 typedef struct xnbu {
59 59 mac_handle_t u_mh;
60 60 boolean_t u_need_sched;
61 61 } xnbu_t;
62 62
63 63 static mac_callbacks_t xnbu_callbacks = {
64 64 MC_GETCAPAB,
65 65 xnbu_m_stat,
66 66 xnbu_m_start,
67 67 xnbu_m_stop,
68 68 xnbu_m_set_promiscuous,
69 69 xnbu_m_set_multicast,
70 70 xnbu_m_set_mac_addr,
71 71 xnbu_m_send,
72 72 NULL,
73 73 NULL,
74 74 xnbu_m_getcapab
75 75 };
76 76
77 77 static void
78 78 xnbu_to_host(xnb_t *xnbp, mblk_t *mp)
79 79 {
80 80 xnbu_t *xnbup = xnbp->xnb_flavour_data;
81 81 boolean_t sched = B_FALSE;
82 82
83 83 ASSERT(mp != NULL);
84 84
85 85 mac_rx(xnbup->u_mh, NULL, mp);
86 86
87 87 mutex_enter(&xnbp->xnb_rx_lock);
88 88
89 89 /*
90 90 * If a transmit attempt failed because we ran out of ring
91 91 * space and there is now some space, re-enable the transmit
92 92 * path.
93 93 */
94 94 if (xnbup->u_need_sched &&
95 95 RING_HAS_UNCONSUMED_REQUESTS(&xnbp->xnb_rx_ring)) {
96 96 sched = B_TRUE;
97 97 xnbup->u_need_sched = B_FALSE;
98 98 }
99 99
100 100 mutex_exit(&xnbp->xnb_rx_lock);
101 101
102 102 if (sched)
103 103 mac_tx_update(xnbup->u_mh);
104 104 }
105 105
106 106 static mblk_t *
107 107 xnbu_cksum_from_peer(xnb_t *xnbp, mblk_t *mp, uint16_t flags)
108 108 {
109 109 /*
110 110 * Take a conservative approach - if the checksum is blank
111 111 * then we fill it in.
112 112 *
113 113 * If the consumer of the packet is IP then we might actually
114 114 * only need fill it in if the data is not validated, but how
115 115 * do we know who might end up with the packet?
116 116 */
117 117
118 118 if ((flags & NETTXF_csum_blank) != 0) {
119 119 /*
120 120 * The checksum is blank. We must fill it in here.
121 121 */
122 122 mp = xnb_process_cksum_flags(xnbp, mp, 0);
123 123
124 124 /*
125 125 * Because we calculated the checksum ourselves we
126 126 * know that it must be good, so we assert this.
127 127 */
128 128 flags |= NETTXF_data_validated;
129 129 }
130 130
131 131 if ((flags & NETTXF_data_validated) != 0) {
132 132 /*
133 133 * The checksum is asserted valid.
134 134 */
135 135 mac_hcksum_set(mp, 0, 0, 0, 0, HCK_FULLCKSUM_OK);
136 136 }
137 137
138 138 return (mp);
139 139 }
140 140
141 141 static uint16_t
142 142 xnbu_cksum_to_peer(xnb_t *xnbp, mblk_t *mp)
143 143 {
144 144 _NOTE(ARGUNUSED(xnbp));
145 145 uint16_t r = 0;
146 146 uint32_t pflags;
147 147
148 148 mac_hcksum_get(mp, NULL, NULL, NULL, NULL, &pflags);
149 149
150 150 /*
151 151 * If the protocol stack has requested checksum
152 152 * offload, inform the peer that we have not
153 153 * calculated the checksum.
154 154 */
155 155 if ((pflags & HCK_FULLCKSUM) != 0)
156 156 r |= NETRXF_csum_blank;
157 157
158 158 return (r);
159 159 }
160 160
161 161 static boolean_t
162 162 xnbu_start_connect(xnb_t *xnbp)
163 163 {
164 164 xnbu_t *xnbup = xnbp->xnb_flavour_data;
165 165
166 166 mac_link_update(xnbup->u_mh, LINK_STATE_UP);
167 167 /*
168 168 * We are able to send packets now - bring them on.
169 169 */
170 170 mac_tx_update(xnbup->u_mh);
171 171
172 172 return (B_TRUE);
173 173 }
174 174
175 175 static boolean_t
176 176 xnbu_peer_connected(xnb_t *xnbp)
177 177 {
178 178 _NOTE(ARGUNUSED(xnbp));
179 179
180 180 return (B_TRUE);
181 181 }
182 182
183 183 static void
184 184 xnbu_peer_disconnected(xnb_t *xnbp)
185 185 {
186 186 xnbu_t *xnbup = xnbp->xnb_flavour_data;
187 187
188 188 mac_link_update(xnbup->u_mh, LINK_STATE_DOWN);
189 189 }
190 190
191 191 /*ARGSUSED*/
192 192 static boolean_t
193 193 xnbu_hotplug_connected(xnb_t *xnbp)
194 194 {
195 195 return (B_TRUE);
196 196 }
197 197
198 198 static mblk_t *
199 199 xnbu_m_send(void *arg, mblk_t *mp)
200 200 {
201 201 xnb_t *xnbp = arg;
202 202 xnbu_t *xnbup = xnbp->xnb_flavour_data;
203 203 boolean_t sched = B_FALSE;
204 204
205 205 mp = xnb_copy_to_peer(arg, mp);
206 206
207 207 mutex_enter(&xnbp->xnb_rx_lock);
208 208 /*
209 209 * If we consumed all of the mblk_t's offered, perhaps we need
210 210 * to indicate that we can accept more. Otherwise we are full
211 211 * and need to wait for space.
212 212 */
213 213 if (mp == NULL) {
214 214 sched = xnbup->u_need_sched;
215 215 xnbup->u_need_sched = B_FALSE;
216 216 } else {
217 217 xnbup->u_need_sched = B_TRUE;
218 218 }
219 219 mutex_exit(&xnbp->xnb_rx_lock);
220 220
221 221 /*
222 222 * If a previous transmit attempt failed because the ring
223 223 * was full, try again now.
224 224 */
225 225 if (sched)
226 226 mac_tx_update(xnbup->u_mh);
227 227
228 228 return (mp);
229 229 }
230 230
231 231 /*
232 232 * xnbu_m_set_mac_addr() -- set the physical network address on the board
233 233 */
234 234 /* ARGSUSED */
235 235 static int
236 236 xnbu_m_set_mac_addr(void *arg, const uint8_t *macaddr)
237 237 {
238 238 xnb_t *xnbp = arg;
239 239 xnbu_t *xnbup = xnbp->xnb_flavour_data;
240 240
241 241 bcopy(macaddr, xnbp->xnb_mac_addr, ETHERADDRL);
242 242 mac_unicst_update(xnbup->u_mh, xnbp->xnb_mac_addr);
243 243
244 244 return (0);
245 245 }
246 246
247 247 /*
248 248 * xnbu_m_set_multicast() -- set (enable) or disable a multicast address
249 249 */
250 250 /*ARGSUSED*/
251 251 static int
252 252 xnbu_m_set_multicast(void *arg, boolean_t add, const uint8_t *mca)
253 253 {
254 254 /*
255 255 * We always accept all packets from the peer, so nothing to
256 256 * do for enable or disable.
257 257 */
258 258 return (0);
259 259 }
260 260
261 261
262 262 /*
263 263 * xnbu_m_set_promiscuous() -- set or reset promiscuous mode on the board
264 264 */
265 265 /* ARGSUSED */
266 266 static int
267 267 xnbu_m_set_promiscuous(void *arg, boolean_t on)
268 268 {
269 269 /*
270 270 * We always accept all packets from the peer, so nothing to
271 271 * do for enable or disable.
272 272 */
273 273 return (0);
274 274 }
275 275
276 276 /*
277 277 * xnbu_m_start() -- start the board receiving and enable interrupts.
278 278 */
279 279 /*ARGSUSED*/
280 280 static int
281 281 xnbu_m_start(void *arg)
282 282 {
283 283 return (0);
284 284 }
285 285
286 286 /*
287 287 * xnbu_m_stop() - disable hardware
288 288 */
289 289 /*ARGSUSED*/
290 290 static void
291 291 xnbu_m_stop(void *arg)
292 292 {
293 293 }
294 294
295 295 static int
296 296 xnbu_m_stat(void *arg, uint_t stat, uint64_t *val)
297 297 {
298 298 xnb_t *xnbp = arg;
299 299
300 300 mutex_enter(&xnbp->xnb_tx_lock);
301 301 mutex_enter(&xnbp->xnb_rx_lock);
302 302
303 303 #define map_stat(q, r) \
304 304 case (MAC_STAT_##q): \
305 305 *val = xnbp->xnb_stat_##r; \
306 306 break
307 307
308 308 switch (stat) {
309 309
310 310 map_stat(IPACKETS, opackets);
311 311 map_stat(OPACKETS, ipackets);
312 312 map_stat(RBYTES, obytes);
313 313 map_stat(OBYTES, rbytes);
314 314
315 315 default:
316 316 mutex_exit(&xnbp->xnb_rx_lock);
317 317 mutex_exit(&xnbp->xnb_tx_lock);
318 318
319 319 return (ENOTSUP);
320 320 }
321 321
322 322 #undef map_stat
323 323
324 324 mutex_exit(&xnbp->xnb_rx_lock);
325 325 mutex_exit(&xnbp->xnb_tx_lock);
326 326
327 327 return (0);
328 328 }
329 329
330 330 static boolean_t
331 331 xnbu_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
332 332 {
333 333 _NOTE(ARGUNUSED(arg));
334 334
335 335 switch (cap) {
336 336 case MAC_CAPAB_HCKSUM: {
337 337 uint32_t *capab = cap_data;
338 338
339 339 *capab = HCKSUM_INET_PARTIAL;
340 340 break;
341 341 }
342 342 default:
343 343 return (B_FALSE);
344 344 }
345 345
346 346 return (B_TRUE);
347 347 }
348 348
349 349 /*
350 350 * All packets are passed to the peer, so adding and removing
351 351 * multicast addresses is meaningless.
352 352 */
353 353 static boolean_t
354 354 xnbu_mcast_add(xnb_t *xnbp, ether_addr_t *addr)
355 355 {
356 356 _NOTE(ARGUNUSED(xnbp, addr));
357 357
358 358 return (B_TRUE);
359 359 }
360 360
361 361 static boolean_t
362 362 xnbu_mcast_del(xnb_t *xnbp, ether_addr_t *addr)
363 363 {
364 364 _NOTE(ARGUNUSED(xnbp, addr));
365 365
366 366 return (B_TRUE);
367 367 }
368 368
369 369 static int
370 370 xnbu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
371 371 {
372 372 static xnb_flavour_t flavour = {
373 373 xnbu_to_host, xnbu_peer_connected, xnbu_peer_disconnected,
374 374 xnbu_hotplug_connected, xnbu_start_connect,
375 375 xnbu_cksum_from_peer, xnbu_cksum_to_peer,
376 376 xnbu_mcast_add, xnbu_mcast_del,
377 377 };
378 378 xnbu_t *xnbup;
379 379 xnb_t *xnbp;
380 380 mac_register_t *mr;
381 381 int err;
382 382
383 383 switch (cmd) {
384 384 case DDI_ATTACH:
385 385 break;
386 386 case DDI_RESUME:
387 387 return (DDI_SUCCESS);
388 388 default:
389 389 return (DDI_FAILURE);
390 390 }
391 391
392 392 xnbup = kmem_zalloc(sizeof (*xnbup), KM_SLEEP);
393 393
394 394 if ((mr = mac_alloc(MAC_VERSION)) == NULL) {
395 395 kmem_free(xnbup, sizeof (*xnbup));
396 396 return (DDI_FAILURE);
397 397 }
398 398
399 399 if (xnb_attach(dip, &flavour, xnbup) != DDI_SUCCESS) {
400 400 mac_free(mr);
401 401 kmem_free(xnbup, sizeof (*xnbup));
402 402 return (DDI_FAILURE);
403 403 }
404 404
405 405 xnbp = ddi_get_driver_private(dip);
406 406 ASSERT(xnbp != NULL);
407 407
408 408 mr->m_dip = dip;
409 409 mr->m_driver = xnbp;
410 410
411 411 /*
412 412 * Initialize pointers to device specific functions which will be
413 413 * used by the generic layer.
414 414 */
415 415 mr->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
416 416 mr->m_src_addr = xnbp->xnb_mac_addr;
417 417 mr->m_callbacks = &xnbu_callbacks;
418 418 mr->m_min_sdu = 0;
419 419 mr->m_max_sdu = XNBMAXPKT;
420 420 /*
421 421 * xnbu is a virtual device, and it is not associated with any
422 422 * physical device. Its margin size is determined by the maximum
423 423 * packet size it can handle, which is PAGESIZE.
424 424 */
425 425 mr->m_margin = PAGESIZE - XNBMAXPKT - sizeof (struct ether_header);
426 426
427 427 (void) memset(xnbp->xnb_mac_addr, 0xff, ETHERADDRL);
428 428 xnbp->xnb_mac_addr[0] &= 0xfe;
429 429 xnbup->u_need_sched = B_FALSE;
430 430
431 431 /*
432 432 * Register ourselves with the GLDv3 interface.
433 433 */
434 434 err = mac_register(mr, &xnbup->u_mh);
435 435 mac_free(mr);
436 436 if (err != 0) {
437 437 xnb_detach(dip);
438 438 kmem_free(xnbup, sizeof (*xnbup));
439 439 return (DDI_FAILURE);
440 440 }
441 441
442 442 mac_link_update(xnbup->u_mh, LINK_STATE_DOWN);
443 443
444 444 return (DDI_SUCCESS);
445 445 }
446 446
447 447 /*ARGSUSED*/
448 448 int
449 449 xnbu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
450 450 {
451 451 xnb_t *xnbp = ddi_get_driver_private(dip);
452 452 xnbu_t *xnbup = xnbp->xnb_flavour_data;
453 453
454 454 switch (cmd) {
455 455 case DDI_DETACH:
456 456 break;
457 457 case DDI_SUSPEND:
458 458 return (DDI_SUCCESS);
459 459 default:
460 460 return (DDI_FAILURE);
461 461 }
462 462
463 463 ASSERT(xnbp != NULL);
464 464 ASSERT(xnbup != NULL);
465 465
466 466 mutex_enter(&xnbp->xnb_tx_lock);
467 467 mutex_enter(&xnbp->xnb_rx_lock);
468 468
469 469 if (!xnbp->xnb_detachable || xnbp->xnb_connected ||
470 470 (xnbp->xnb_tx_buf_count > 0)) {
471 471 mutex_exit(&xnbp->xnb_rx_lock);
472 472 mutex_exit(&xnbp->xnb_tx_lock);
473 473
474 474 return (DDI_FAILURE);
475 475 }
476 476
477 477 mutex_exit(&xnbp->xnb_rx_lock);
478 478 mutex_exit(&xnbp->xnb_tx_lock);
479 479
480 480 /*
481 481 * Attempt to unregister the mac.
482 482 */
483 483 if ((xnbup->u_mh != NULL) && (mac_unregister(xnbup->u_mh) != 0))
484 484 return (DDI_FAILURE);
485 485 kmem_free(xnbup, sizeof (*xnbup));
486 486
487 487 xnb_detach(dip);
488 488
489 489 return (DDI_SUCCESS);
↓ open down ↓ |
489 lines elided |
↑ open up ↑ |
490 490 }
491 491
492 492 DDI_DEFINE_STREAM_OPS(ops, nulldev, nulldev, xnbu_attach, xnbu_detach,
493 493 nodev, NULL, D_MP, NULL, ddi_quiesce_not_supported);
494 494
495 495 static struct modldrv modldrv = {
496 496 &mod_driverops, "xnbu driver", &ops
497 497 };
498 498
499 499 static struct modlinkage modlinkage = {
500 - MODREV_1, &modldrv, NULL
500 + MODREV_1, { &modldrv, NULL }
501 501 };
502 502
503 503 int
504 504 _init(void)
505 505 {
506 506 int i;
507 507
508 508 mac_init_ops(&ops, "xnbu");
509 509
510 510 i = mod_install(&modlinkage);
511 511 if (i != DDI_SUCCESS)
512 512 mac_fini_ops(&ops);
513 513
514 514 return (i);
515 515 }
516 516
517 517 int
518 518 _fini(void)
519 519 {
520 520 int i;
521 521
522 522 i = mod_remove(&modlinkage);
523 523 if (i == DDI_SUCCESS)
524 524 mac_fini_ops(&ops);
525 525
526 526 return (i);
527 527 }
528 528
529 529 int
530 530 _info(struct modinfo *modinfop)
531 531 {
532 532 return (mod_info(&modlinkage, modinfop));
533 533 }
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX