1 /* 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2001 Atsushi Onoe 8 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * Alternatively, this software may be distributed under the terms of the 23 * GNU General Public License ("GPL") version 2 as published by the Free 24 * Software Foundation. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #pragma ident "%Z%%M% %I% %E% SMI" 39 40 /* 41 * IEEE 802.11 generic handler 42 */ 43 44 #include <sys/param.h> 45 #include <sys/types.h> 46 #include <sys/cmn_err.h> 47 #include <sys/modctl.h> 48 #include "net80211_impl.h" 49 50 uint32_t ieee80211_debug = 0x0; /* debug msg flags */ 51 52 const char *ieee80211_phymode_name[] = { 53 "auto", /* IEEE80211_MODE_AUTO */ 54 "11a", /* IEEE80211_MODE_11A */ 55 "11b", /* IEEE80211_MODE_11B */ 56 "11g", /* IEEE80211_MODE_11G */ 57 "FH", /* IEEE80211_MODE_FH */ 58 "turboA", /* IEEE80211_MODE_TURBO_A */ 59 "turboG", /* IEEE80211_MODE_TURBO_G */ 60 }; 61 62 #define IEEE80211_DPRINT(_level, _fmt) do { \ 63 _NOTE(CONSTCOND) \ 64 va_list ap; \ 65 va_start(ap, (_fmt)); \ 66 vcmn_err((_level), (_fmt), ap); \ 67 va_end(ap); \ 68 _NOTE(CONSTCOND) \ 69 } while (0) 70 71 /* 72 * Print error messages 73 */ 74 void 75 ieee80211_err(const int8_t *fmt, ...) 76 { 77 IEEE80211_DPRINT(CE_WARN, fmt); 78 } 79 80 /* 81 * Print debug messages 82 */ 83 void 84 ieee80211_dbg(uint32_t flag, const int8_t *fmt, ...) 85 { 86 if (flag & ieee80211_debug) 87 IEEE80211_DPRINT(CE_CONT, fmt); 88 } 89 90 /* 91 * Default reset method for use with the ioctl support. This 92 * method is invoked after any state change in the 802.11 93 * layer that should be propagated to the hardware but not 94 * require re-initialization of the 802.11 state machine (e.g 95 * rescanning for an ap). We always return ENETRESET which 96 * should cause the driver to re-initialize the device. Drivers 97 * can override this method to implement more optimized support. 98 */ 99 /* ARGSUSED */ 100 static int 101 ieee80211_default_reset(ieee80211com_t *ic) 102 { 103 return (ENETRESET); 104 } 105 106 /* 107 * Convert channel to IEEE channel number. 108 */ 109 uint32_t 110 ieee80211_chan2ieee(ieee80211com_t *ic, struct ieee80211_channel *ch) 111 { 112 if ((ic->ic_sup_channels <= ch) && 113 (ch <= &ic->ic_sup_channels[IEEE80211_CHAN_MAX])) { 114 return (ch - ic->ic_sup_channels); 115 } else if (ch == IEEE80211_CHAN_ANYC) { 116 return (IEEE80211_CHAN_ANY); 117 } else if (ch != NULL) { 118 ieee80211_err("invalid channel freq %u flags %x\n", 119 ch->ich_freq, ch->ich_flags); 120 return (0); 121 } 122 ieee80211_err("invalid channel (NULL)\n"); /* ch == NULL */ 123 return (0); 124 } 125 126 /* 127 * Convert IEEE channel number to MHz frequency. 128 * chan IEEE channel number 129 * flags specify whether the frequency is in the 2GHz ISM 130 * band or the 5GHz band 131 * 132 * 802.11b 2GHz: 14 channels, each 5 MHz wide. Channel 1 is placed 133 * at 2.412 GHz, channel 2 at 2.417 GHz, and so on up to channel 13 134 * at 2.472 GHz. Channel 14 was defined especially for operation in 135 * Japan, and has a center frequency 2.484 GHz. 136 * 802.11g 2GHz: adopts the frequency plan of 802.11b. Japan only 137 * allows 802.11g operation in channels 1-13 138 * 802.11a 5GHz: starting every 5 MHz 139 * 802.11b/g channels 15-24 (2512-2692) are used by some implementation 140 * (Atheros etc.) 141 */ 142 uint32_t 143 ieee80211_ieee2mhz(uint32_t chan, uint32_t flags) 144 { 145 if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */ 146 if (chan == 14) 147 return (2484); 148 if (chan < 14) 149 return (2412 + (chan - 1) * 5); 150 else 151 return (2512 + ((chan - 15) * 20)); 152 } else if (flags & IEEE80211_CHAN_5GHZ) { /* 5Ghz band */ 153 return (5000 + (chan * 5)); /* OFDM */ 154 } else { /* either, guess */ 155 if (chan == 14) 156 return (2484); 157 if (chan < 14) /* 0-13 */ 158 return (2412 + (chan - 1) * 5); 159 if (chan < 27) /* 15-26 */ 160 return (2512 + ((chan - 15) * 20)); 161 return (5000 + (chan * 5)); 162 } 163 } 164 165 /* 166 * Do late attach work. It must be called by the driver after 167 * calling ieee80211_attach() and before calling most ieee80211 168 * functions. 169 */ 170 void 171 ieee80211_media_init(ieee80211com_t *ic) 172 { 173 /* 174 * Do late attach work that must wait for any subclass 175 * (i.e. driver) work such as overriding methods. 176 */ 177 ieee80211_node_lateattach(ic); 178 } 179 180 /* 181 * Start Watchdog timer. After count down timer(s), ic_watchdog 182 * will be called 183 */ 184 void 185 ieee80211_start_watchdog(ieee80211com_t *ic, uint32_t timer) 186 { 187 if (ic->ic_watchdog_timer == 0 && ic->ic_watchdog != NULL) { 188 ic->ic_watchdog_timer = timeout(ic->ic_watchdog, ic, 189 drv_usectohz(1000000 * timer)); 190 } 191 } 192 193 /* 194 * Stop watchdog timer. 195 */ 196 void 197 ieee80211_stop_watchdog(ieee80211com_t *ic) 198 { 199 if (ic->ic_watchdog_timer != 0) { 200 if (ic->ic_watchdog != NULL) 201 (void) untimeout(ic->ic_watchdog_timer); 202 ic->ic_watchdog_timer = 0; 203 } 204 } 205 206 /* 207 * Called from a driver's xxx_watchdog routine. It is used to 208 * perform periodic cleanup of state for net80211, as well as 209 * timeout scans. 210 */ 211 void 212 ieee80211_watchdog(void *arg) 213 { 214 ieee80211com_t *ic = arg; 215 struct ieee80211_impl *im = ic->ic_private; 216 ieee80211_node_table_t *nt; 217 int inact_timer = 0; 218 219 if (ic->ic_state == IEEE80211_S_INIT) 220 return; 221 222 IEEE80211_LOCK(ic); 223 if ((im->im_mgt_timer != 0) && (--im->im_mgt_timer == 0)) { 224 IEEE80211_UNLOCK(ic); 225 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 226 IEEE80211_LOCK(ic); 227 } 228 229 nt = &ic->ic_scan; 230 if (nt->nt_inact_timer != 0) { 231 if (--nt->nt_inact_timer == 0) 232 nt->nt_timeout(nt); 233 inact_timer += nt->nt_inact_timer; 234 } 235 nt = &ic->ic_sta; 236 if (nt->nt_inact_timer != 0) { 237 if (--nt->nt_inact_timer == 0) 238 nt->nt_timeout(nt); 239 inact_timer += nt->nt_inact_timer; 240 } 241 242 IEEE80211_UNLOCK(ic); 243 244 if (im->im_mgt_timer != 0 || inact_timer > 0) 245 ieee80211_start_watchdog(ic, 1); 246 } 247 248 /* 249 * Set the current phy mode and recalculate the active channel 250 * set and supported rates based on the available channels for 251 * this mode. Also select a new BSS channel if the current one 252 * is inappropriate for this mode. 253 * This function is called by net80211, and not intended to be 254 * called directly. 255 */ 256 static int 257 ieee80211_setmode(ieee80211com_t *ic, enum ieee80211_phymode mode) 258 { 259 static const uint32_t chanflags[] = { 260 0, /* IEEE80211_MODE_AUTO */ 261 IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ 262 IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ 263 IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */ 264 IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ 265 IEEE80211_CHAN_T, /* IEEE80211_MODE_TURBO_A */ 266 IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */ 267 }; 268 struct ieee80211_channel *ch; 269 uint32_t modeflags; 270 int i; 271 int achannels = 0; 272 273 /* validate new mode */ 274 if ((ic->ic_modecaps & (1 << mode)) == 0) { 275 ieee80211_err("ieee80211_setmode(): mode %u not supported" 276 " (caps 0x%x)\n", mode, ic->ic_modecaps); 277 return (EINVAL); 278 } 279 280 /* 281 * Verify at least one channel is present in the available 282 * channel list before committing to the new mode. 283 * Calculate the active channel set. 284 */ 285 ASSERT(mode < IEEE80211_N(chanflags)); 286 modeflags = chanflags[mode]; 287 bzero(ic->ic_chan_active, sizeof (ic->ic_chan_active)); 288 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { 289 ch = &ic->ic_sup_channels[i]; 290 if (ch->ich_flags == 0) 291 continue; 292 if (mode == IEEE80211_MODE_AUTO) { 293 /* take anything but pure turbo channels */ 294 if ((ch->ich_flags & ~IEEE80211_CHAN_TURBO) != 0) { 295 ieee80211_setbit(ic->ic_chan_active, i); 296 achannels++; 297 } 298 } else { 299 if ((ch->ich_flags & modeflags) == modeflags) { 300 ieee80211_setbit(ic->ic_chan_active, i); 301 achannels++; 302 } 303 } 304 } 305 if (achannels == 0) { 306 ieee80211_err("ieee80211_setmode(): " 307 "no channel found for mode %u\n", mode); 308 return (EINVAL); 309 } 310 311 /* 312 * If no current/default channel is setup or the current 313 * channel is wrong for the mode then pick the first 314 * available channel from the active list. This is likely 315 * not the right one. 316 */ 317 if (ic->ic_ibss_chan == NULL || 318 ieee80211_isclr(ic->ic_chan_active, 319 ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) { 320 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { 321 if (ieee80211_isset(ic->ic_chan_active, i)) { 322 ic->ic_ibss_chan = &ic->ic_sup_channels[i]; 323 break; 324 } 325 } 326 } 327 /* 328 * If the desired channel is set but no longer valid then reset it. 329 */ 330 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 331 ieee80211_isclr(ic->ic_chan_active, 332 ieee80211_chan2ieee(ic, ic->ic_des_chan))) { 333 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 334 } 335 336 /* 337 * Do mode-specific rate setup. 338 */ 339 if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11B) 340 ieee80211_setbasicrates(&ic->ic_sup_rates[mode], mode); 341 342 /* 343 * Setup an initial rate set according to the 344 * current/default channel. This will be changed 345 * when scanning but must exist now so drivers have 346 * consistent state of ic_bsschan. 347 */ 348 if (ic->ic_bss != NULL) 349 ic->ic_bss->in_rates = ic->ic_sup_rates[mode]; 350 ic->ic_curmode = mode; 351 ieee80211_reset_erp(ic); /* reset ERP state */ 352 353 return (0); 354 } 355 356 /* 357 * Return the phy mode for with the specified channel so the 358 * caller can select a rate set. This is problematic for channels 359 * where multiple operating modes are possible (e.g. 11g+11b). 360 * In those cases we defer to the current operating mode when set. 361 */ 362 enum ieee80211_phymode 363 ieee80211_chan2mode(ieee80211com_t *ic, struct ieee80211_channel *chan) 364 { 365 if (IEEE80211_IS_CHAN_T(chan)) { 366 return (IEEE80211_MODE_TURBO_A); 367 } else if (IEEE80211_IS_CHAN_5GHZ(chan)) { 368 return (IEEE80211_MODE_11A); 369 } else if (IEEE80211_IS_CHAN_FHSS(chan)) { 370 return (IEEE80211_MODE_FH); 371 } else if (chan->ich_flags & (IEEE80211_CHAN_OFDM|IEEE80211_CHAN_DYN)) { 372 /* 373 * This assumes all 11g channels are also usable 374 * for 11b, which is currently true. 375 */ 376 if (ic->ic_curmode == IEEE80211_MODE_TURBO_G) 377 return (IEEE80211_MODE_TURBO_G); 378 if (ic->ic_curmode == IEEE80211_MODE_11B) 379 return (IEEE80211_MODE_11B); 380 return (IEEE80211_MODE_11G); 381 } else { 382 return (IEEE80211_MODE_11B); 383 } 384 } 385 386 /* 387 * Return the size of the 802.11 header for a management or data frame. 388 */ 389 int 390 ieee80211_hdrspace(const void *data) 391 { 392 const struct ieee80211_frame *wh = data; 393 int size = sizeof (struct ieee80211_frame); 394 395 /* NB: we don't handle control frames */ 396 ASSERT((wh->i_fc[0]&IEEE80211_FC0_TYPE_MASK) != 397 IEEE80211_FC0_TYPE_CTL); 398 if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) 399 size += IEEE80211_ADDR_LEN; 400 401 return (size); 402 } 403 404 /* 405 * Allocate and setup a management frame of the specified 406 * size. We return the mblk and a pointer to the start 407 * of the contiguous data area that's been reserved based 408 * on the packet length. 409 */ 410 mblk_t * 411 ieee80211_getmgtframe(uint8_t **frm, int pktlen) 412 { 413 mblk_t *mp; 414 int len; 415 416 len = sizeof (struct ieee80211_frame) + pktlen; 417 mp = allocb(len, BPRI_MED); 418 if (mp != NULL) { 419 *frm = mp->b_rptr + sizeof (struct ieee80211_frame); 420 mp->b_wptr = mp->b_rptr + len; 421 } else { 422 ieee80211_err("ieee80211_getmgtframe: " 423 "alloc frame failed, %d\n", len); 424 } 425 return (mp); 426 } 427 428 /* 429 * Send system messages to notify the device has joined a WLAN. 430 * This is an OS specific function. Solaris marks link status 431 * as up. 432 */ 433 void 434 ieee80211_notify_node_join(ieee80211com_t *ic, ieee80211_node_t *in) 435 { 436 if (in == ic->ic_bss) 437 mac_link_update(ic->ic_mach, LINK_STATE_UP); 438 } 439 440 /* 441 * Send system messages to notify the device has left a WLAN. 442 * This is an OS specific function. Solaris marks link status 443 * as down. 444 */ 445 void 446 ieee80211_notify_node_leave(ieee80211com_t *ic, ieee80211_node_t *in) 447 { 448 if (in == ic->ic_bss) 449 mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 450 } 451 452 /* 453 * Get 802.11 kstats defined in ieee802.11(5) 454 * 455 * Return 0 on success 456 */ 457 int 458 ieee80211_stat(ieee80211com_t *ic, uint_t stat, uint64_t *val) 459 { 460 ASSERT(val != NULL); 461 IEEE80211_LOCK(ic); 462 switch (stat) { 463 case WIFI_STAT_TX_FRAGS: 464 *val = ic->ic_stats.is_tx_frags; 465 break; 466 case WIFI_STAT_MCAST_TX: 467 *val = ic->ic_stats.is_tx_mcast; 468 break; 469 case WIFI_STAT_TX_FAILED: 470 *val = ic->ic_stats.is_tx_failed; 471 break; 472 case WIFI_STAT_TX_RETRANS: 473 *val = ic->ic_stats.is_tx_retries; 474 break; 475 case WIFI_STAT_RTS_SUCCESS: 476 *val = ic->ic_stats.is_rts_success; 477 break; 478 case WIFI_STAT_RTS_FAILURE: 479 *val = ic->ic_stats.is_rts_failure; 480 break; 481 case WIFI_STAT_ACK_FAILURE: 482 *val = ic->ic_stats.is_ack_failure; 483 break; 484 case WIFI_STAT_RX_FRAGS: 485 *val = ic->ic_stats.is_rx_frags; 486 break; 487 case WIFI_STAT_MCAST_RX: 488 *val = ic->ic_stats.is_rx_mcast; 489 break; 490 case WIFI_STAT_RX_DUPS: 491 *val = ic->ic_stats.is_rx_dups; 492 break; 493 case WIFI_STAT_FCS_ERRORS: 494 *val = ic->ic_stats.is_fcs_errors; 495 break; 496 case WIFI_STAT_WEP_ERRORS: 497 *val = ic->ic_stats.is_wep_errors; 498 break; 499 } 500 IEEE80211_UNLOCK(ic); 501 return (0); 502 } 503 504 /* 505 * Attach network interface to the 802.11 support module. This 506 * function must be called before using any of the ieee80211 507 * functionss. The parameter "ic" MUST be initialized to tell 508 * net80211 about interface's capabilities. 509 */ 510 void 511 ieee80211_attach(ieee80211com_t *ic) 512 { 513 struct ieee80211_impl *im; 514 struct ieee80211_channel *ch; 515 int i; 516 517 /* Check mandatory callback functions not NULL */ 518 ASSERT(ic->ic_xmit != NULL); 519 520 mutex_init(&ic->ic_genlock, NULL, MUTEX_DRIVER, NULL); 521 522 im = kmem_alloc(sizeof (ieee80211_impl_t), KM_SLEEP); 523 ic->ic_private = im; 524 cv_init(&im->im_scan_cv, NULL, CV_DRIVER, NULL); 525 526 /* 527 * Fill in 802.11 available channel set, mark 528 * all available channels as active, and pick 529 * a default channel if not already specified. 530 */ 531 bzero(im->im_chan_avail, sizeof (im->im_chan_avail)); 532 ic->ic_modecaps |= 1 << IEEE80211_MODE_AUTO; 533 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { 534 ch = &ic->ic_sup_channels[i]; 535 if (ch->ich_flags) { 536 /* Verify driver passed us valid data */ 537 if (i != ieee80211_chan2ieee(ic, ch)) { 538 ieee80211_err("bad channel ignored: " 539 "freq %u flags%x number %u\n", 540 ch->ich_freq, ch->ich_flags, i); 541 ch->ich_flags = 0; 542 continue; 543 } 544 ieee80211_setbit(im->im_chan_avail, i); 545 /* Identify mode capabilities */ 546 if (IEEE80211_IS_CHAN_A(ch)) 547 ic->ic_modecaps |= 1 << IEEE80211_MODE_11A; 548 if (IEEE80211_IS_CHAN_B(ch)) 549 ic->ic_modecaps |= 1 << IEEE80211_MODE_11B; 550 if (IEEE80211_IS_CHAN_PUREG(ch)) 551 ic->ic_modecaps |= 1 << IEEE80211_MODE_11G; 552 if (IEEE80211_IS_CHAN_FHSS(ch)) 553 ic->ic_modecaps |= 1 << IEEE80211_MODE_FH; 554 if (IEEE80211_IS_CHAN_T(ch)) 555 ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_A; 556 if (IEEE80211_IS_CHAN_108G(ch)) 557 ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_G; 558 if (ic->ic_curchan == NULL) { 559 /* arbitrarily pick the first channel */ 560 ic->ic_curchan = &ic->ic_sup_channels[i]; 561 } 562 } 563 } 564 /* validate ic->ic_curmode */ 565 if ((ic->ic_modecaps & (1 << ic->ic_curmode)) == 0) 566 ic->ic_curmode = IEEE80211_MODE_AUTO; 567 ic->ic_des_chan = IEEE80211_CHAN_ANYC; /* any channel is ok */ 568 (void) ieee80211_setmode(ic, ic->ic_curmode); 569 570 if (ic->ic_caps & IEEE80211_C_BURST) 571 ic->ic_flags |= IEEE80211_F_BURST; 572 ic->ic_bintval = IEEE80211_BINTVAL_DEFAULT; 573 ic->ic_lintval = ic->ic_bintval; 574 ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX; 575 ic->ic_bmissthreshold = IEEE80211_HWBMISS_DEFAULT; 576 577 ic->ic_reset = ieee80211_default_reset; 578 579 ieee80211_node_attach(ic); 580 ieee80211_proto_attach(ic); 581 ieee80211_crypto_attach(ic); 582 583 ic->ic_watchdog_timer = 0; 584 } 585 586 /* 587 * Free any ieee80211 structures associated with the driver. 588 */ 589 void 590 ieee80211_detach(ieee80211com_t *ic) 591 { 592 struct ieee80211_impl *im = ic->ic_private; 593 594 ieee80211_stop_watchdog(ic); 595 cv_destroy(&im->im_scan_cv); 596 kmem_free(im, sizeof (ieee80211_impl_t)); 597 598 ieee80211_node_detach(ic); 599 ieee80211_crypto_detach(ic); 600 601 mutex_destroy(&ic->ic_genlock); 602 } 603 604 static struct modlmisc i_wifi_modlmisc = { 605 &mod_miscops, 606 "IEEE80211 Kernel Misc Module" 607 }; 608 609 static struct modlinkage i_wifi_modlinkage = { 610 MODREV_1, 611 &i_wifi_modlmisc, 612 NULL 613 }; 614 615 /* 616 * modlinkage functions 617 */ 618 int 619 _init(void) 620 { 621 return (mod_install(&i_wifi_modlinkage)); 622 } 623 624 int 625 _fini(void) 626 { 627 return (mod_remove(&i_wifi_modlinkage)); 628 } 629 630 int 631 _info(struct modinfo *modinfop) 632 { 633 return (mod_info(&i_wifi_modlinkage, modinfop)); 634 } 635