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 int pcktrput(queue_t *, mblk_t *); 101 static int pcktrsrv(queue_t *); 102 static int 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 pcktrput, 146 pcktrsrv, 147 pcktopen, 148 pcktclose, 149 NULL, 150 &pcktiinfo, 151 NULL 152 }; 153 154 static struct qinit pcktwinit = { 155 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 int 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 return (0); 410 } 411 412 /* 413 * pcktrsrv - module read service procedure 414 * This function deals with messages left in the queue due to 415 * (a) not enough memory to allocate the header M_PROTO message 416 * (b) flow control reasons 417 * The function will attempt to get the messages off the queue and 418 * process them. 419 */ 420 static int 421 pcktrsrv(queue_t *q) 422 { 423 mblk_t *mp; 424 425 while ((mp = getq(q)) != NULL) { 426 if (!canputnext(q)) { 427 /* 428 * For high priority messages, make sure there is no 429 * infinite loop. Disable the queue for this case. 430 * High priority messages get here only for buffer 431 * allocation failures. Thus the bufcall callout 432 * will reenable the q. 433 * XXX bug alert - nooenable will *not* prevent 434 * putbq of a hipri messages frm enabling the queue. 435 */ 436 if (!datamsg(mp->b_datap->db_type)) 437 noenable(q); 438 (void) putbq(q, mp); 439 return (0); 440 } 441 442 /* 443 * M_FLUSH msgs may also be here if there was a memory 444 * failure. 445 */ 446 switch (mp->b_datap->db_type) { 447 case M_FLUSH: 448 case M_PROTO: 449 case M_PCPROTO: 450 case M_STOP: 451 case M_START: 452 case M_IOCTL: 453 case M_DATA: 454 case M_READ: 455 case M_STARTI: 456 case M_STOPI: 457 /* 458 * Prefix an M_PROTO header to msg and pass upstream. 459 */ 460 if ((mp = add_ctl_info(q, mp)) == NULL) { 461 /* 462 * Running into memory or flow ctl problems. 463 */ 464 return (0); 465 } 466 /* FALL THROUGH */ 467 468 default: 469 putnext(q, mp); 470 break; 471 } 472 } 473 return (0); 474 } 475 476 /* 477 * pcktwput - Module write queue put procedure. 478 * All messages are send downstream unchanged 479 */ 480 481 static int 482 pcktwput( 483 queue_t *q, /* Pointer to the read queue */ 484 mblk_t *mp) /* Pointer to current message block */ 485 { 486 putnext(q, mp); 487 return (0); 488 } 489 490 #ifdef _MULTI_DATAMODEL 491 /* 492 * reallocb - copy the data block from the given message block into a new block. 493 * This function is used in case data block had another message block 494 * pointing to it (and hence we just copy this one data block). 495 * 496 * Returns new message block if successful. On failure it returns NULL. 497 * It also tries to do a qbufcall and if that also fails, 498 * it frees the message block. 499 */ 500 static mblk_t * 501 pckt_reallocb( 502 queue_t *q, /* Pointer to the read queue */ 503 mblk_t *mp) /* Pointer to the message block to be changed */ 504 { 505 mblk_t *nmp; 506 507 ASSERT(mp->b_datap->db_ref >= 1); 508 509 /* 510 * No reallocation is needed if there is only one reference 511 * to this data block. 512 */ 513 if (mp->b_datap->db_ref == 1) 514 return (mp); 515 516 if ((nmp = copyb(mp)) == NULL) { 517 struct pckt_info *pip = (struct pckt_info *)q->q_ptr; 518 519 noenable(q); 520 if (pip->pi_bufcall_id = qbufcall(q, mp->b_wptr - mp->b_rptr, 521 BPRI_MED, add_ctl_wkup, q)) { 522 /* 523 * Put the message back onto the q. 524 */ 525 (void) putq(q, mp); 526 } else { 527 /* 528 * Things are pretty bad and serious if bufcall fails! 529 * Drop the message in this case. 530 */ 531 freemsg(mp); 532 } 533 return ((mblk_t *)0); 534 } 535 536 nmp->b_cont = mp->b_cont; 537 freeb(mp); 538 return (nmp); 539 } 540 #endif /* _MULTI_DATAMODEL */ 541 542 /* 543 * add_ctl_info: add message control information to in coming 544 * message. 545 */ 546 static mblk_t * 547 add_ctl_info( 548 queue_t *q, /* pointer to the read queue */ 549 mblk_t *mp) /* pointer to the raw data input message */ 550 { 551 struct pckt_info *pip = (struct pckt_info *)q->q_ptr; 552 mblk_t *bp; /* pointer to the unmodified message block */ 553 554 /* 555 * Waiting on space for previous message? 556 */ 557 if (pip->pi_bufcall_id) { 558 /* 559 * Chain this message on to q for later processing. 560 */ 561 (void) putq(q, mp); 562 return (NULL); 563 } 564 565 /* 566 * Need to add the message block header as 567 * an M_PROTO type message. 568 */ 569 if ((bp = allocb(sizeof (char), BPRI_MED)) == (mblk_t *)NULL) { 570 571 /* 572 * There are two reasons to disable the q: 573 * (1) Flow control reasons should not wake up the q. 574 * (2) High priority messages will wakeup the q 575 * immediately. Disallow this. 576 */ 577 noenable(q); 578 if (pip->pi_bufcall_id = qbufcall(q, sizeof (char), BPRI_MED, 579 add_ctl_wkup, q)) { 580 /* 581 * Add the message to the q. 582 */ 583 (void) putq(q, mp); 584 } else { 585 /* 586 * Things are pretty bad and serious if bufcall fails! 587 * Drop the message in this case. 588 */ 589 freemsg(mp); 590 } 591 592 return (NULL); 593 } 594 595 /* 596 * Copy the message type information to this message. 597 */ 598 bp->b_datap->db_type = M_PROTO; 599 *(unsigned char *)bp->b_rptr = mp->b_datap->db_type; 600 bp->b_wptr++; 601 602 #ifdef _MULTI_DATAMODEL 603 /* 604 * Check the datamodel and if the calling program is 605 * an ILP32 application then we covert the M_IOCTLs and M_READs 606 * into the native ILP32 format before passing them upstream 607 * to user mode. 608 */ 609 switch (pip->model) { 610 case DDI_MODEL_ILP32: 611 switch (mp->b_datap->db_type) { 612 /* 613 * This structure must have the same shape as 614 * the * ILP32 compilation of `struct iocblk' 615 * from <sys/stream.h>. 616 */ 617 struct iocblk32 { 618 int32_t ioc_cmd; 619 caddr32_t ioc_cr; 620 uint32_t ioc_id; 621 int32_t ioc_count; 622 int32_t ioc_error; 623 int32_t ioc_rval; 624 int32_t ioc_fill1; 625 uint32_t ioc_flag; 626 int32_t ioc_filler[2]; 627 } niocblk_32; 628 struct iocblk *iocblk_64; 629 630 case M_IOCTL: 631 if ((mp = pckt_reallocb(q, mp)) == (mblk_t *)0) 632 return ((mblk_t *)0); 633 634 bzero(&niocblk_32, sizeof (niocblk_32)); 635 iocblk_64 = (struct iocblk *)mp->b_rptr; 636 637 /* Leave the pointer to cred_t structure as it is. */ 638 niocblk_32.ioc_cmd = iocblk_64->ioc_cmd; 639 niocblk_32.ioc_cr = (caddr32_t)(uintptr_t) 640 iocblk_64->ioc_cr; 641 niocblk_32.ioc_id = iocblk_64->ioc_id; 642 niocblk_32.ioc_count = iocblk_64->ioc_count; 643 niocblk_32.ioc_error = iocblk_64->ioc_error; 644 niocblk_32.ioc_rval = iocblk_64->ioc_rval; 645 niocblk_32.ioc_flag = iocblk_64->ioc_flag; 646 647 /* Copy the iocblk structure for ILP32 back */ 648 *(struct iocblk32 *)mp->b_rptr = niocblk_32; 649 mp->b_wptr = mp->b_rptr + sizeof (struct iocblk32); 650 break; 651 652 case M_READ: 653 if ((mp = pckt_reallocb(q, mp)) == (mblk_t *)0) 654 return ((mblk_t *)0); 655 656 /* change the size_t to size32_t for ILP32 */ 657 *(size32_t *)mp->b_rptr = *(size_t *)mp->b_rptr; 658 mp->b_wptr = mp->b_rptr + sizeof (size32_t); 659 break; 660 } 661 break; 662 663 case DATAMODEL_NONE: 664 break; 665 } 666 #endif /* _MULTI_DATAMODEL */ 667 668 /* 669 * Now change the orginal message type to M_DATA and tie them up. 670 */ 671 mp->b_datap->db_type = M_DATA; 672 bp->b_cont = mp; 673 674 return (bp); 675 } 676 677 static void 678 add_ctl_wkup(void *arg) 679 { 680 queue_t *q = arg; /* ptr to the read queue */ 681 struct pckt_info *pip = (struct pckt_info *)q->q_ptr; 682 683 pip->pi_bufcall_id = 0; 684 /* 685 * Allow enabling of the q to allow the service 686 * function to do its job. 687 * 688 * Also, qenable() to schedule the q immediately. 689 * This is to ensure timely processing of high priority 690 * messages if they are on the q. 691 */ 692 enableok(q); 693 qenable(q); 694 } 695