Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/pckt.c
+++ new/usr/src/uts/common/io/pckt.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, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 28 /* All Rights Reserved */
29 29
30 30
31 31 /*
32 32 * Description: The pckt module packetizes messages on
33 33 * its read queue by pre-fixing an M_PROTO
34 34 * message type to certain incoming messages.
35 35 */
36 36
37 37 #include <sys/types.h>
38 38 #include <sys/param.h>
39 39 #include <sys/stream.h>
40 40 #include <sys/stropts.h>
41 41 #include <sys/kmem.h>
42 42 #include <sys/errno.h>
43 43 #include <sys/ddi.h>
44 44 #include <sys/sunddi.h>
45 45 #include <sys/debug.h>
46 46
47 47 /*
48 48 * This is the loadable module wrapper.
49 49 */
50 50 #include <sys/conf.h>
51 51 #include <sys/modctl.h>
52 52
53 53 static struct streamtab pcktinfo;
54 54
55 55 /*
56 56 * Per queue instances are single-threaded since the q_ptr
57 57 * field of queues need to be shared among threads.
58 58 */
59 59 static struct fmodsw fsw = {
60 60 "pckt",
61 61 &pcktinfo,
62 62 D_NEW | D_MTPERQ | D_MP
63 63 };
64 64
65 65 /*
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
66 66 * Module linkage information for the kernel.
67 67 */
68 68
69 69 static struct modlstrmod modlstrmod = {
70 70 &mod_strmodops,
71 71 "pckt module",
72 72 &fsw
73 73 };
74 74
75 75 static struct modlinkage modlinkage = {
76 - MODREV_1, &modlstrmod, NULL
76 + MODREV_1, { &modlstrmod, NULL }
77 77 };
78 78
79 79
80 80 int
81 81 _init(void)
82 82 {
83 83 return (mod_install(&modlinkage));
84 84 }
85 85
86 86 int
87 87 _fini(void)
88 88 {
89 89 return (mod_remove(&modlinkage));
90 90 }
91 91
92 92 int
93 93 _info(struct modinfo *modinfop)
94 94 {
95 95 return (mod_info(&modlinkage, modinfop));
96 96 }
97 97
98 98 static int pcktopen(queue_t *, dev_t *, int, int, cred_t *);
99 99 static int pcktclose(queue_t *, int, cred_t *);
100 100 static void pcktrput(queue_t *, mblk_t *);
101 101 static void pcktrsrv(queue_t *);
102 102 static void pcktwput(queue_t *, mblk_t *);
103 103 static mblk_t *add_ctl_info(queue_t *, mblk_t *);
104 104 static void add_ctl_wkup(void *);
105 105
106 106
107 107 /*
108 108 * Stream module data structure definitions.
109 109 * Sits over the ptm module generally.
110 110 *
111 111 * Read side flow control strategy: Since we may be putting messages on
112 112 * the read q due to allocb failures, these failures must get
113 113 * reflected fairly quickly to the module below us.
114 114 * No sense in piling on messages in times of memory shortage.
115 115 * Further, for the case of upper level flow control, there is no
116 116 * compelling reason to have more buffering in this module.
117 117 * Thus use a hi-water mark of one.
118 118 * This module imposes no max packet size, there is no inherent reason
119 119 * in the code to do so.
120 120 */
121 121 static struct module_info pcktiinfo = {
122 122 0x9898, /* module id number */
123 123 "pckt", /* module name */
124 124 0, /* minimum packet size */
125 125 INFPSZ, /* maximum packet size */
126 126 1, /* hi-water mark */
127 127 0 /* lo-water mark */
128 128 };
129 129
130 130 /*
131 131 * Write side flow control strategy: There is no write service procedure.
132 132 * The write put function is pass thru, thus there is no reason to have any
133 133 * limits on the maximum packet size.
134 134 */
135 135 static struct module_info pcktoinfo = {
136 136 0x9898, /* module id number */
137 137 "pckt", /* module name */
138 138 0, /* minimum packet size */
139 139 INFPSZ, /* maximum packet size */
140 140 0, /* hi-water mark */
141 141 0 /* lo-water mark */
142 142 };
143 143
144 144 static struct qinit pcktrinit = {
145 145 (int (*)())pcktrput,
146 146 (int (*)())pcktrsrv,
147 147 pcktopen,
148 148 pcktclose,
149 149 NULL,
150 150 &pcktiinfo,
151 151 NULL
152 152 };
153 153
154 154 static struct qinit pcktwinit = {
155 155 (int (*)())pcktwput,
156 156 NULL,
157 157 NULL,
158 158 NULL,
159 159 NULL,
160 160 &pcktoinfo,
161 161 NULL
162 162 };
163 163
164 164 static struct streamtab pcktinfo = {
165 165 &pcktrinit,
166 166 &pcktwinit,
167 167 NULL,
168 168 NULL
169 169 };
170 170
171 171
172 172 /*
173 173 * Per-instance state struct for the pckt module.
174 174 */
175 175 struct pckt_info {
176 176 queue_t *pi_qptr; /* back pointer to q */
177 177 bufcall_id_t pi_bufcall_id;
178 178 #ifdef _MULTI_DATAMODEL
179 179 model_t model;
180 180 #endif /* _MULTI_DATAMODEL */
181 181 };
182 182
183 183 /*
184 184 * Dummy qbufcall callback routine used by open and close.
185 185 * The framework will wake up qwait_sig when we return from
186 186 * this routine (as part of leaving the perimeters.)
187 187 * (The framework enters the perimeters before calling the qbufcall() callback
188 188 * and leaves the perimeters after the callback routine has executed. The
189 189 * framework performs an implicit wakeup of any thread in qwait/qwait_sig
190 190 * when it leaves the perimeter. See qwait(9E).)
191 191 */
192 192 /* ARGSUSED */
193 193 static void
194 194 dummy_callback(void *arg)
195 195 {}
196 196
197 197 /*
198 198 * pcktopen - open routine gets called when the
199 199 * module gets pushed onto the stream.
200 200 */
201 201 /*ARGSUSED*/
202 202 static int
203 203 pcktopen(
204 204 queue_t *q, /* pointer to the read side queue */
205 205 dev_t *devp, /* pointer to stream tail's dev */
206 206 int oflag, /* the user open(2) supplied flags */
207 207 int sflag, /* open state flag */
208 208 cred_t *credp) /* credentials */
209 209 {
210 210 struct pckt_info *pip;
211 211 mblk_t *mop; /* ptr to a setopts msg block */
212 212 struct stroptions *sop;
213 213
214 214 if (sflag != MODOPEN)
215 215 return (EINVAL);
216 216
217 217 if (q->q_ptr != NULL) {
218 218 /* It's already attached. */
219 219 return (0);
220 220 }
221 221
222 222 /*
223 223 * Allocate state structure.
224 224 */
225 225 pip = kmem_zalloc(sizeof (*pip), KM_SLEEP);
226 226
227 227 #ifdef _MULTI_DATAMODEL
228 228 pip->model = ddi_model_convert_from(get_udatamodel());
229 229 #endif /* _MULTI_DATAMODEL */
230 230
231 231 /*
232 232 * Cross-link.
233 233 */
234 234 pip->pi_qptr = q;
235 235 q->q_ptr = pip;
236 236 WR(q)->q_ptr = pip;
237 237
238 238 qprocson(q);
239 239
240 240 /*
241 241 * Initialize an M_SETOPTS message to set up hi/lo water marks on
242 242 * stream head read queue.
243 243 */
244 244
245 245 while ((mop = allocb(sizeof (struct stroptions), BPRI_MED)) == NULL) {
246 246 bufcall_id_t id = qbufcall(q, sizeof (struct stroptions),
247 247 BPRI_MED, dummy_callback, NULL);
248 248 if (!qwait_sig(q)) {
249 249 qunbufcall(q, id);
250 250 kmem_free(pip, sizeof (*pip));
251 251 qprocsoff(q);
252 252 return (EINTR);
253 253 }
254 254 qunbufcall(q, id);
255 255 }
256 256
257 257
258 258 /*
259 259 * XXX: Should this module really control the hi/low water marks?
260 260 * Is there any reason in this code to do so?
261 261 */
262 262 mop->b_datap->db_type = M_SETOPTS;
263 263 mop->b_wptr += sizeof (struct stroptions);
264 264 sop = (struct stroptions *)mop->b_rptr;
265 265 sop->so_flags = SO_HIWAT | SO_LOWAT;
266 266 sop->so_hiwat = 512;
267 267 sop->so_lowat = 256;
268 268
269 269 /*
270 270 * Commit to the open and send the M_SETOPTS off to the stream head.
271 271 */
272 272 putnext(q, mop);
273 273
274 274 return (0);
275 275 }
276 276
277 277
278 278 /*
279 279 * pcktclose - This routine gets called when the module
280 280 * gets popped off of the stream.
281 281 */
282 282
283 283 /*ARGSUSED*/
284 284 static int
285 285 pcktclose(
286 286 queue_t *q, /* Pointer to the read queue */
287 287 int flag,
288 288 cred_t *credp)
289 289 {
290 290 struct pckt_info *pip = (struct pckt_info *)q->q_ptr;
291 291
292 292 qprocsoff(q);
293 293 /*
294 294 * Cancel outstanding qbufcall
295 295 */
296 296 if (pip->pi_bufcall_id) {
297 297 qunbufcall(q, pip->pi_bufcall_id);
298 298 pip->pi_bufcall_id = 0;
299 299 }
300 300 /*
301 301 * Do not worry about msgs queued on the q, the framework
302 302 * will free them up.
303 303 */
304 304 kmem_free(q->q_ptr, sizeof (struct pckt_info));
305 305 q->q_ptr = WR(q)->q_ptr = NULL;
306 306 return (0);
307 307 }
308 308
309 309 /*
310 310 * pcktrput - Module read queue put procedure.
311 311 * This is called from the module or
312 312 * driver downstream.
313 313 */
314 314 static void
315 315 pcktrput(
316 316 queue_t *q, /* Pointer to the read queue */
317 317 mblk_t *mp) /* Pointer to the current message block */
318 318 {
319 319 mblk_t *pckt_msgp;
320 320
321 321
322 322 switch (mp->b_datap->db_type) {
323 323 case M_FLUSH:
324 324 /*
325 325 * The PTS driver swaps the FLUSHR and FLUSHW flags
326 326 * we need to swap them back to reflect the actual
327 327 * slave side FLUSH mode.
328 328 */
329 329 if ((*mp->b_rptr & FLUSHRW) != FLUSHRW)
330 330 if ((*mp->b_rptr & FLUSHRW) == FLUSHR)
331 331 *mp->b_rptr = FLUSHW;
332 332 else if ((*mp->b_rptr & FLUSHRW) == FLUSHW)
333 333 *mp->b_rptr = FLUSHR;
334 334
335 335 pckt_msgp = copymsg(mp);
336 336 if (*mp->b_rptr & FLUSHW) {
337 337 /*
338 338 * In the packet model we are not allowing
339 339 * flushes of the master's stream head read
340 340 * side queue. This is because all packet
341 341 * state information is stored there and
342 342 * a flush could destroy this data before
343 343 * it is read.
344 344 */
345 345 *mp->b_rptr = FLUSHW;
346 346 putnext(q, mp);
347 347 } else {
348 348 /*
349 349 * Free messages that only flush the
350 350 * master's read queue.
351 351 */
352 352 freemsg(mp);
353 353 }
354 354
355 355 if (pckt_msgp == NULL)
356 356 break;
357 357
358 358 mp = pckt_msgp;
359 359 /*
360 360 * Prefix M_PROTO and putnext.
361 361 */
362 362 goto prefix_head;
363 363
364 364 case M_DATA:
365 365 case M_IOCTL:
366 366 case M_PROTO:
367 367 /*
368 368 * For non-priority messages, follow flow-control rules.
369 369 * Also, if there are messages on the q already, keep
370 370 * queueing them since they need to be processed in order.
371 371 */
372 372 if (!canputnext(q) || (qsize(q) > 0)) {
373 373 (void) putq(q, mp);
374 374 break;
375 375 }
376 376 /* FALLTHROUGH */
377 377
378 378 /*
379 379 * For high priority messages, skip flow control checks.
380 380 */
381 381 case M_PCPROTO:
382 382 case M_READ:
383 383 case M_STOP:
384 384 case M_START:
385 385 case M_STARTI:
386 386 case M_STOPI:
387 387 prefix_head:
388 388 /*
389 389 * Prefix an M_PROTO header to message and pass upstream.
390 390 */
391 391 if ((mp = add_ctl_info(q, mp)) != NULL)
392 392 putnext(q, mp);
393 393 break;
394 394
395 395 default:
396 396 /*
397 397 * For data messages, queue them back on the queue if
398 398 * there are messages on the queue already. This is
399 399 * done to preserve the order of messages.
400 400 * For high priority messages or for no messages on the
401 401 * q, simply putnext() and pass it on.
402 402 */
403 403 if ((datamsg(mp->b_datap->db_type)) && (qsize(q) > 0))
404 404 (void) putq(q, mp);
405 405 else
406 406 putnext(q, mp);
407 407 break;
408 408 }
409 409 }
410 410
411 411 /*
412 412 * pcktrsrv - module read service procedure
413 413 * This function deals with messages left in the queue due to
414 414 * (a) not enough memory to allocate the header M_PROTO message
415 415 * (b) flow control reasons
416 416 * The function will attempt to get the messages off the queue and
417 417 * process them.
418 418 */
419 419 static void
420 420 pcktrsrv(queue_t *q)
421 421 {
422 422 mblk_t *mp;
423 423
424 424 while ((mp = getq(q)) != NULL) {
425 425 if (!canputnext(q)) {
426 426 /*
427 427 * For high priority messages, make sure there is no
428 428 * infinite loop. Disable the queue for this case.
429 429 * High priority messages get here only for buffer
430 430 * allocation failures. Thus the bufcall callout
431 431 * will reenable the q.
432 432 * XXX bug alert - nooenable will *not* prevent
433 433 * putbq of a hipri messages frm enabling the queue.
434 434 */
435 435 if (!datamsg(mp->b_datap->db_type))
436 436 noenable(q);
437 437 (void) putbq(q, mp);
438 438 return;
439 439 }
440 440
441 441 /*
442 442 * M_FLUSH msgs may also be here if there was a memory
443 443 * failure.
444 444 */
445 445 switch (mp->b_datap->db_type) {
446 446 case M_FLUSH:
447 447 case M_PROTO:
448 448 case M_PCPROTO:
449 449 case M_STOP:
450 450 case M_START:
451 451 case M_IOCTL:
452 452 case M_DATA:
453 453 case M_READ:
454 454 case M_STARTI:
455 455 case M_STOPI:
456 456 /*
457 457 * Prefix an M_PROTO header to msg and pass upstream.
458 458 */
459 459 if ((mp = add_ctl_info(q, mp)) == NULL) {
460 460 /*
461 461 * Running into memory or flow ctl problems.
462 462 */
463 463 return;
464 464 }
465 465 /* FALL THROUGH */
466 466
467 467 default:
468 468 putnext(q, mp);
469 469 break;
470 470 }
471 471 }
472 472 }
473 473
474 474 /*
475 475 * pcktwput - Module write queue put procedure.
476 476 * All messages are send downstream unchanged
477 477 */
478 478
479 479 static void
480 480 pcktwput(
481 481 queue_t *q, /* Pointer to the read queue */
482 482 mblk_t *mp) /* Pointer to current message block */
483 483 {
484 484 putnext(q, mp);
485 485 }
486 486
487 487 #ifdef _MULTI_DATAMODEL
488 488 /*
489 489 * reallocb - copy the data block from the given message block into a new block.
490 490 * This function is used in case data block had another message block
491 491 * pointing to it (and hence we just copy this one data block).
492 492 *
493 493 * Returns new message block if successful. On failure it returns NULL.
494 494 * It also tries to do a qbufcall and if that also fails,
495 495 * it frees the message block.
496 496 */
497 497 static mblk_t *
498 498 pckt_reallocb(
499 499 queue_t *q, /* Pointer to the read queue */
500 500 mblk_t *mp /* Pointer to the message block to be changed */
501 501 )
502 502 {
503 503 mblk_t *nmp;
504 504
505 505 ASSERT(mp->b_datap->db_ref >= 1);
506 506
507 507 /*
508 508 * No reallocation is needed if there is only one reference
509 509 * to this data block.
510 510 */
511 511 if (mp->b_datap->db_ref == 1)
512 512 return (mp);
513 513
514 514 if ((nmp = copyb(mp)) == NULL) {
515 515 struct pckt_info *pip = (struct pckt_info *)q->q_ptr;
516 516
517 517 noenable(q);
518 518 if (pip->pi_bufcall_id = qbufcall(q, mp->b_wptr - mp->b_rptr,
519 519 BPRI_MED, add_ctl_wkup, q)) {
520 520 /*
521 521 * Put the message back onto the q.
522 522 */
523 523 (void) putq(q, mp);
524 524 } else {
525 525 /*
526 526 * Things are pretty bad and serious if bufcall fails!
527 527 * Drop the message in this case.
528 528 */
529 529 freemsg(mp);
530 530 }
531 531 return ((mblk_t *)0);
532 532 }
533 533
534 534 nmp->b_cont = mp->b_cont;
535 535 freeb(mp);
536 536 return (nmp);
537 537 }
538 538 #endif /* _MULTI_DATAMODEL */
539 539
540 540 /*
541 541 * add_ctl_info: add message control information to in coming
542 542 * message.
543 543 */
544 544 static mblk_t *
545 545 add_ctl_info(
546 546 queue_t *q, /* pointer to the read queue */
547 547 mblk_t *mp) /* pointer to the raw data input message */
548 548 {
549 549 struct pckt_info *pip = (struct pckt_info *)q->q_ptr;
550 550 mblk_t *bp; /* pointer to the unmodified message block */
551 551
552 552 /*
553 553 * Waiting on space for previous message?
554 554 */
555 555 if (pip->pi_bufcall_id) {
556 556 /*
557 557 * Chain this message on to q for later processing.
558 558 */
559 559 (void) putq(q, mp);
560 560 return (NULL);
561 561 }
562 562
563 563 /*
564 564 * Need to add the message block header as
565 565 * an M_PROTO type message.
566 566 */
567 567 if ((bp = allocb(sizeof (char), BPRI_MED)) == (mblk_t *)NULL) {
568 568
569 569 /*
570 570 * There are two reasons to disable the q:
571 571 * (1) Flow control reasons should not wake up the q.
572 572 * (2) High priority messages will wakeup the q
573 573 * immediately. Disallow this.
574 574 */
575 575 noenable(q);
576 576 if (pip->pi_bufcall_id = qbufcall(q, sizeof (char), BPRI_MED,
577 577 add_ctl_wkup, q)) {
578 578 /*
579 579 * Add the message to the q.
580 580 */
581 581 (void) putq(q, mp);
582 582 } else {
583 583 /*
584 584 * Things are pretty bad and serious if bufcall fails!
585 585 * Drop the message in this case.
586 586 */
587 587 freemsg(mp);
588 588 }
589 589
590 590 return (NULL);
591 591 }
592 592
593 593 /*
594 594 * Copy the message type information to this message.
595 595 */
596 596 bp->b_datap->db_type = M_PROTO;
597 597 *(unsigned char *)bp->b_rptr = mp->b_datap->db_type;
598 598 bp->b_wptr++;
599 599
600 600 #ifdef _MULTI_DATAMODEL
601 601 /*
602 602 * Check the datamodel and if the calling program is
603 603 * an ILP32 application then we covert the M_IOCTLs and M_READs
604 604 * into the native ILP32 format before passing them upstream
605 605 * to user mode.
606 606 */
607 607 switch (pip->model) {
608 608 case DDI_MODEL_ILP32:
609 609 switch (mp->b_datap->db_type) {
610 610 /*
611 611 * This structure must have the same shape as
612 612 * the * ILP32 compilation of `struct iocblk'
613 613 * from <sys/stream.h>.
614 614 */
615 615 struct iocblk32 {
616 616 int32_t ioc_cmd;
617 617 caddr32_t ioc_cr;
618 618 uint32_t ioc_id;
619 619 int32_t ioc_count;
620 620 int32_t ioc_error;
621 621 int32_t ioc_rval;
622 622 int32_t ioc_fill1;
623 623 uint32_t ioc_flag;
624 624 int32_t ioc_filler[2];
625 625 } niocblk_32;
626 626 struct iocblk *iocblk_64;
627 627
628 628 case M_IOCTL:
629 629 if ((mp = pckt_reallocb(q, mp)) == (mblk_t *)0)
630 630 return ((mblk_t *)0);
631 631
632 632 bzero(&niocblk_32, sizeof (niocblk_32));
633 633 iocblk_64 = (struct iocblk *)mp->b_rptr;
634 634
635 635 /* Leave the pointer to cred_t structure as it is. */
636 636 niocblk_32.ioc_cmd = iocblk_64->ioc_cmd;
637 637 niocblk_32.ioc_cr = (caddr32_t)(uintptr_t)
638 638 iocblk_64->ioc_cr;
639 639 niocblk_32.ioc_id = iocblk_64->ioc_id;
640 640 niocblk_32.ioc_count = iocblk_64->ioc_count;
641 641 niocblk_32.ioc_error = iocblk_64->ioc_error;
642 642 niocblk_32.ioc_rval = iocblk_64->ioc_rval;
643 643 niocblk_32.ioc_flag = iocblk_64->ioc_flag;
644 644
645 645 /* Copy the iocblk structure for ILP32 back */
646 646 *(struct iocblk32 *)mp->b_rptr = niocblk_32;
647 647 mp->b_wptr = mp->b_rptr + sizeof (struct iocblk32);
648 648 break;
649 649
650 650 case M_READ:
651 651 if ((mp = pckt_reallocb(q, mp)) == (mblk_t *)0)
652 652 return ((mblk_t *)0);
653 653
654 654 /* change the size_t to size32_t for ILP32 */
655 655 *(size32_t *)mp->b_rptr = *(size_t *)mp->b_rptr;
656 656 mp->b_wptr = mp->b_rptr + sizeof (size32_t);
657 657 break;
658 658 }
659 659 break;
660 660
661 661 case DATAMODEL_NONE:
662 662 break;
663 663 }
664 664 #endif /* _MULTI_DATAMODEL */
665 665
666 666 /*
667 667 * Now change the orginal message type to M_DATA and tie them up.
668 668 */
669 669 mp->b_datap->db_type = M_DATA;
670 670 bp->b_cont = mp;
671 671
672 672 return (bp);
673 673 }
674 674
675 675 static void
676 676 add_ctl_wkup(void *arg)
677 677 {
678 678 queue_t *q = arg; /* ptr to the read queue */
679 679 struct pckt_info *pip = (struct pckt_info *)q->q_ptr;
680 680
681 681 pip->pi_bufcall_id = 0;
682 682 /*
683 683 * Allow enabling of the q to allow the service
684 684 * function to do its job.
685 685 *
686 686 * Also, qenable() to schedule the q immediately.
687 687 * This is to ensure timely processing of high priority
688 688 * messages if they are on the q.
689 689 */
690 690 enableok(q);
691 691 qenable(q);
692 692 }
↓ open down ↓ |
606 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX