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