102ac6454SAndrew Thompson /* $FreeBSD$ */ 202ac6454SAndrew Thompson /*- 302ac6454SAndrew Thompson * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 402ac6454SAndrew Thompson * 502ac6454SAndrew Thompson * Redistribution and use in source and binary forms, with or without 602ac6454SAndrew Thompson * modification, are permitted provided that the following conditions 702ac6454SAndrew Thompson * are met: 802ac6454SAndrew Thompson * 1. Redistributions of source code must retain the above copyright 902ac6454SAndrew Thompson * notice, this list of conditions and the following disclaimer. 1002ac6454SAndrew Thompson * 2. Redistributions in binary form must reproduce the above copyright 1102ac6454SAndrew Thompson * notice, this list of conditions and the following disclaimer in the 1202ac6454SAndrew Thompson * documentation and/or other materials provided with the distribution. 1302ac6454SAndrew Thompson * 1402ac6454SAndrew Thompson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1502ac6454SAndrew Thompson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1602ac6454SAndrew Thompson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1702ac6454SAndrew Thompson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1802ac6454SAndrew Thompson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1902ac6454SAndrew Thompson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2002ac6454SAndrew Thompson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2102ac6454SAndrew Thompson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2202ac6454SAndrew Thompson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2302ac6454SAndrew Thompson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2402ac6454SAndrew Thompson * SUCH DAMAGE. 2502ac6454SAndrew Thompson */ 2602ac6454SAndrew Thompson 27ed6d949aSAndrew Thompson #include <sys/stdint.h> 28ed6d949aSAndrew Thompson #include <sys/stddef.h> 29ed6d949aSAndrew Thompson #include <sys/param.h> 30ed6d949aSAndrew Thompson #include <sys/queue.h> 31ed6d949aSAndrew Thompson #include <sys/types.h> 32ed6d949aSAndrew Thompson #include <sys/systm.h> 33ed6d949aSAndrew Thompson #include <sys/kernel.h> 34ed6d949aSAndrew Thompson #include <sys/bus.h> 35ed6d949aSAndrew Thompson #include <sys/module.h> 36ed6d949aSAndrew Thompson #include <sys/lock.h> 37ed6d949aSAndrew Thompson #include <sys/mutex.h> 38ed6d949aSAndrew Thompson #include <sys/condvar.h> 39ed6d949aSAndrew Thompson #include <sys/sysctl.h> 40ed6d949aSAndrew Thompson #include <sys/sx.h> 41ed6d949aSAndrew Thompson #include <sys/unistd.h> 42ed6d949aSAndrew Thompson #include <sys/callout.h> 43ed6d949aSAndrew Thompson #include <sys/malloc.h> 44ed6d949aSAndrew Thompson #include <sys/priv.h> 45ed6d949aSAndrew Thompson 4602ac6454SAndrew Thompson #include <dev/usb/usb.h> 47ed6d949aSAndrew Thompson #include <dev/usb/usbdi.h> 4802ac6454SAndrew Thompson 4902ac6454SAndrew Thompson #include <dev/usb/usb_core.h> 5002ac6454SAndrew Thompson #include <dev/usb/usb_debug.h> 5102ac6454SAndrew Thompson #include <dev/usb/usb_process.h> 5202ac6454SAndrew Thompson #include <dev/usb/usb_device.h> 5302ac6454SAndrew Thompson #include <dev/usb/usb_busdma.h> 5402ac6454SAndrew Thompson #include <dev/usb/usb_transfer.h> 5502ac6454SAndrew Thompson 56ed6d949aSAndrew Thompson #include <ddb/ddb.h> 57ed6d949aSAndrew Thompson #include <ddb/db_sym.h> 58ed6d949aSAndrew Thompson 5902ac6454SAndrew Thompson /* 6002ac6454SAndrew Thompson * Define this unconditionally in case a kernel module is loaded that 6102ac6454SAndrew Thompson * has been compiled with debugging options. 6202ac6454SAndrew Thompson */ 63a593f6b8SAndrew Thompson int usb_debug = 0; 6402ac6454SAndrew Thompson 659360ae40SAndrew Thompson SYSCTL_NODE(_hw, OID_AUTO, usb, CTLFLAG_RW, 0, "USB debugging"); 669360ae40SAndrew Thompson SYSCTL_INT(_hw_usb, OID_AUTO, debug, CTLFLAG_RW, 67a593f6b8SAndrew Thompson &usb_debug, 0, "Debug level"); 6802ac6454SAndrew Thompson 69c13fd8d4SAndrew Thompson TUNABLE_INT("hw.usb.debug", &usb_debug); 70c13fd8d4SAndrew Thompson 71*37506412SHans Petter Selasky #ifdef USB_DEBUG 72*37506412SHans Petter Selasky /* 73*37506412SHans Petter Selasky * Sysctls to modify timings/delays 74*37506412SHans Petter Selasky */ 75*37506412SHans Petter Selasky static SYSCTL_NODE(_hw_usb, OID_AUTO, timings, CTLFLAG_RW, 0, "Timings"); 76*37506412SHans Petter Selasky static int usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS); 77*37506412SHans Petter Selasky 78*37506412SHans Petter Selasky TUNABLE_INT("hw.usb.timings.port_reset_delay", (int *)&usb_port_reset_delay); 79*37506412SHans Petter Selasky SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_reset_delay, CTLTYPE_UINT | CTLFLAG_RW, 80*37506412SHans Petter Selasky &usb_port_reset_delay, sizeof(usb_port_reset_delay), 81*37506412SHans Petter Selasky usb_timings_sysctl_handler, "IU", "Port Reset Delay"); 82*37506412SHans Petter Selasky TUNABLE_INT("hw.usb.timings.port_root_reset_delay", (int *)&usb_port_root_reset_delay); 83*37506412SHans Petter Selasky SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_root_reset_delay, CTLTYPE_UINT | CTLFLAG_RW, 84*37506412SHans Petter Selasky &usb_port_root_reset_delay, sizeof(usb_port_root_reset_delay), 85*37506412SHans Petter Selasky usb_timings_sysctl_handler, "IU", "Root Port Reset Delay"); 86*37506412SHans Petter Selasky TUNABLE_INT("hw.usb.timings.port_reset_recovery", (int *)&usb_port_reset_recovery); 87*37506412SHans Petter Selasky SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_reset_recovery, CTLTYPE_UINT | CTLFLAG_RW, 88*37506412SHans Petter Selasky &usb_port_reset_recovery, sizeof(usb_port_reset_recovery), 89*37506412SHans Petter Selasky usb_timings_sysctl_handler, "IU", "Port Reset Recovery"); 90*37506412SHans Petter Selasky TUNABLE_INT("hw.usb.timings.port_powerup_delay", (int *)&usb_port_powerup_delay); 91*37506412SHans Petter Selasky SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_powerup_delay, CTLTYPE_UINT | CTLFLAG_RW, 92*37506412SHans Petter Selasky &usb_port_powerup_delay, sizeof(usb_port_powerup_delay), 93*37506412SHans Petter Selasky usb_timings_sysctl_handler, "IU", "Port PowerUp Delay"); 94*37506412SHans Petter Selasky TUNABLE_INT("hw.usb.timings.port_resume_delay", (int *)&usb_port_resume_delay); 95*37506412SHans Petter Selasky SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_resume_delay, CTLTYPE_UINT | CTLFLAG_RW, 96*37506412SHans Petter Selasky &usb_port_resume_delay, sizeof(usb_port_resume_delay), 97*37506412SHans Petter Selasky usb_timings_sysctl_handler, "IU", "Port Resume Delay"); 98*37506412SHans Petter Selasky TUNABLE_INT("hw.usb.timings.set_address_settle", (int *)&usb_set_address_settle); 99*37506412SHans Petter Selasky SYSCTL_PROC(_hw_usb_timings, OID_AUTO, set_address_settle, CTLTYPE_UINT | CTLFLAG_RW, 100*37506412SHans Petter Selasky &usb_set_address_settle, sizeof(usb_set_address_settle), 101*37506412SHans Petter Selasky usb_timings_sysctl_handler, "IU", "Set Address Settle"); 102*37506412SHans Petter Selasky TUNABLE_INT("hw.usb.timings.resume_delay", (int *)&usb_resume_delay); 103*37506412SHans Petter Selasky SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_delay, CTLTYPE_UINT | CTLFLAG_RW, 104*37506412SHans Petter Selasky &usb_resume_delay, sizeof(usb_resume_delay), 105*37506412SHans Petter Selasky usb_timings_sysctl_handler, "IU", "Resume Delay"); 106*37506412SHans Petter Selasky TUNABLE_INT("hw.usb.timings.resume_wait", (int *)&usb_resume_wait); 107*37506412SHans Petter Selasky SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_wait, CTLTYPE_UINT | CTLFLAG_RW, 108*37506412SHans Petter Selasky &usb_resume_wait, sizeof(usb_resume_wait), 109*37506412SHans Petter Selasky usb_timings_sysctl_handler, "IU", "Resume Wait"); 110*37506412SHans Petter Selasky TUNABLE_INT("hw.usb.timings.resume_recovery", (int *)&usb_resume_recovery); 111*37506412SHans Petter Selasky SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_recovery, CTLTYPE_UINT | CTLFLAG_RW, 112*37506412SHans Petter Selasky &usb_resume_recovery, sizeof(usb_resume_recovery), 113*37506412SHans Petter Selasky usb_timings_sysctl_handler, "IU", "Resume Recovery"); 114*37506412SHans Petter Selasky TUNABLE_INT("hw.usb.timings.extra_power_up_time", (int *)&usb_extra_power_up_time); 115*37506412SHans Petter Selasky SYSCTL_PROC(_hw_usb_timings, OID_AUTO, extra_power_up_time, CTLTYPE_UINT | CTLFLAG_RW, 116*37506412SHans Petter Selasky &usb_extra_power_up_time, sizeof(usb_extra_power_up_time), 117*37506412SHans Petter Selasky usb_timings_sysctl_handler, "IU", "Extra PowerUp Time"); 118*37506412SHans Petter Selasky #endif 119*37506412SHans Petter Selasky 12002ac6454SAndrew Thompson /*------------------------------------------------------------------------* 121a593f6b8SAndrew Thompson * usb_dump_iface 12202ac6454SAndrew Thompson * 12302ac6454SAndrew Thompson * This function dumps information about an USB interface. 12402ac6454SAndrew Thompson *------------------------------------------------------------------------*/ 12502ac6454SAndrew Thompson void 126a593f6b8SAndrew Thompson usb_dump_iface(struct usb_interface *iface) 12702ac6454SAndrew Thompson { 128a593f6b8SAndrew Thompson printf("usb_dump_iface: iface=%p\n", iface); 12902ac6454SAndrew Thompson if (iface == NULL) { 13002ac6454SAndrew Thompson return; 13102ac6454SAndrew Thompson } 13202ac6454SAndrew Thompson printf(" iface=%p idesc=%p altindex=%d\n", 13302ac6454SAndrew Thompson iface, iface->idesc, iface->alt_index); 13402ac6454SAndrew Thompson } 13502ac6454SAndrew Thompson 13602ac6454SAndrew Thompson /*------------------------------------------------------------------------* 137a593f6b8SAndrew Thompson * usb_dump_device 13802ac6454SAndrew Thompson * 13902ac6454SAndrew Thompson * This function dumps information about an USB device. 14002ac6454SAndrew Thompson *------------------------------------------------------------------------*/ 14102ac6454SAndrew Thompson void 142a593f6b8SAndrew Thompson usb_dump_device(struct usb_device *udev) 14302ac6454SAndrew Thompson { 144a593f6b8SAndrew Thompson printf("usb_dump_device: dev=%p\n", udev); 14502ac6454SAndrew Thompson if (udev == NULL) { 14602ac6454SAndrew Thompson return; 14702ac6454SAndrew Thompson } 14802ac6454SAndrew Thompson printf(" bus=%p \n" 14902ac6454SAndrew Thompson " address=%d config=%d depth=%d speed=%d self_powered=%d\n" 15002ac6454SAndrew Thompson " power=%d langid=%d\n", 15102ac6454SAndrew Thompson udev->bus, 15202ac6454SAndrew Thompson udev->address, udev->curr_config_no, udev->depth, udev->speed, 15302ac6454SAndrew Thompson udev->flags.self_powered, udev->power, udev->langid); 15402ac6454SAndrew Thompson } 15502ac6454SAndrew Thompson 15602ac6454SAndrew Thompson /*------------------------------------------------------------------------* 157a593f6b8SAndrew Thompson * usb_dump_queue 15802ac6454SAndrew Thompson * 159ae60fdfbSAndrew Thompson * This function dumps the USB transfer that are queued up on an USB endpoint. 16002ac6454SAndrew Thompson *------------------------------------------------------------------------*/ 16102ac6454SAndrew Thompson void 162a593f6b8SAndrew Thompson usb_dump_queue(struct usb_endpoint *ep) 16302ac6454SAndrew Thompson { 164760bc48eSAndrew Thompson struct usb_xfer *xfer; 165a5cf1aaaSHans Petter Selasky usb_stream_t x; 16602ac6454SAndrew Thompson 167a593f6b8SAndrew Thompson printf("usb_dump_queue: endpoint=%p xfer: ", ep); 168a5cf1aaaSHans Petter Selasky for (x = 0; x != USB_MAX_EP_STREAMS; x++) { 169a5cf1aaaSHans Petter Selasky TAILQ_FOREACH(xfer, &ep->endpoint_q[x].head, wait_entry) 17002ac6454SAndrew Thompson printf(" %p", xfer); 17102ac6454SAndrew Thompson } 17202ac6454SAndrew Thompson printf("\n"); 17302ac6454SAndrew Thompson } 17402ac6454SAndrew Thompson 17502ac6454SAndrew Thompson /*------------------------------------------------------------------------* 176a593f6b8SAndrew Thompson * usb_dump_endpoint 17702ac6454SAndrew Thompson * 178ae60fdfbSAndrew Thompson * This function dumps information about an USB endpoint. 17902ac6454SAndrew Thompson *------------------------------------------------------------------------*/ 18002ac6454SAndrew Thompson void 181a593f6b8SAndrew Thompson usb_dump_endpoint(struct usb_endpoint *ep) 18202ac6454SAndrew Thompson { 183ae60fdfbSAndrew Thompson if (ep) { 184a593f6b8SAndrew Thompson printf("usb_dump_endpoint: endpoint=%p", ep); 18502ac6454SAndrew Thompson 18602ac6454SAndrew Thompson printf(" edesc=%p isoc_next=%d toggle_next=%d", 187ae60fdfbSAndrew Thompson ep->edesc, ep->isoc_next, ep->toggle_next); 18802ac6454SAndrew Thompson 189ae60fdfbSAndrew Thompson if (ep->edesc) { 19002ac6454SAndrew Thompson printf(" bEndpointAddress=0x%02x", 191ae60fdfbSAndrew Thompson ep->edesc->bEndpointAddress); 19202ac6454SAndrew Thompson } 19302ac6454SAndrew Thompson printf("\n"); 194a593f6b8SAndrew Thompson usb_dump_queue(ep); 19502ac6454SAndrew Thompson } else { 196a593f6b8SAndrew Thompson printf("usb_dump_endpoint: endpoint=NULL\n"); 19702ac6454SAndrew Thompson } 19802ac6454SAndrew Thompson } 19902ac6454SAndrew Thompson 20002ac6454SAndrew Thompson /*------------------------------------------------------------------------* 201a593f6b8SAndrew Thompson * usb_dump_xfer 20202ac6454SAndrew Thompson * 20302ac6454SAndrew Thompson * This function dumps information about an USB transfer. 20402ac6454SAndrew Thompson *------------------------------------------------------------------------*/ 20502ac6454SAndrew Thompson void 206a593f6b8SAndrew Thompson usb_dump_xfer(struct usb_xfer *xfer) 20702ac6454SAndrew Thompson { 208760bc48eSAndrew Thompson struct usb_device *udev; 209a593f6b8SAndrew Thompson printf("usb_dump_xfer: xfer=%p\n", xfer); 21002ac6454SAndrew Thompson if (xfer == NULL) { 21102ac6454SAndrew Thompson return; 21202ac6454SAndrew Thompson } 213ae60fdfbSAndrew Thompson if (xfer->endpoint == NULL) { 214ae60fdfbSAndrew Thompson printf("xfer %p: endpoint=NULL\n", 21502ac6454SAndrew Thompson xfer); 21602ac6454SAndrew Thompson return; 21702ac6454SAndrew Thompson } 21802ac6454SAndrew Thompson udev = xfer->xroot->udev; 21902ac6454SAndrew Thompson printf("xfer %p: udev=%p vid=0x%04x pid=0x%04x addr=%d " 220ae60fdfbSAndrew Thompson "endpoint=%p ep=0x%02x attr=0x%02x\n", 22102ac6454SAndrew Thompson xfer, udev, 22202ac6454SAndrew Thompson UGETW(udev->ddesc.idVendor), 22302ac6454SAndrew Thompson UGETW(udev->ddesc.idProduct), 224ae60fdfbSAndrew Thompson udev->address, xfer->endpoint, 225ae60fdfbSAndrew Thompson xfer->endpoint->edesc->bEndpointAddress, 226ae60fdfbSAndrew Thompson xfer->endpoint->edesc->bmAttributes); 22702ac6454SAndrew Thompson } 228*37506412SHans Petter Selasky 229*37506412SHans Petter Selasky #ifdef USB_DEBUG 230*37506412SHans Petter Selasky unsigned int usb_port_reset_delay = USB_PORT_RESET_DELAY; 231*37506412SHans Petter Selasky unsigned int usb_port_root_reset_delay = USB_PORT_ROOT_RESET_DELAY; 232*37506412SHans Petter Selasky unsigned int usb_port_reset_recovery = USB_PORT_RESET_RECOVERY; 233*37506412SHans Petter Selasky unsigned int usb_port_powerup_delay = USB_PORT_POWERUP_DELAY; 234*37506412SHans Petter Selasky unsigned int usb_port_resume_delay = USB_PORT_RESUME_DELAY; 235*37506412SHans Petter Selasky unsigned int usb_set_address_settle = USB_SET_ADDRESS_SETTLE; 236*37506412SHans Petter Selasky unsigned int usb_resume_delay = USB_RESUME_DELAY; 237*37506412SHans Petter Selasky unsigned int usb_resume_wait = USB_RESUME_WAIT; 238*37506412SHans Petter Selasky unsigned int usb_resume_recovery = USB_RESUME_RECOVERY; 239*37506412SHans Petter Selasky unsigned int usb_extra_power_up_time = USB_EXTRA_POWER_UP_TIME; 240*37506412SHans Petter Selasky 241*37506412SHans Petter Selasky /*------------------------------------------------------------------------* 242*37506412SHans Petter Selasky * usb_timings_sysctl_handler 243*37506412SHans Petter Selasky * 244*37506412SHans Petter Selasky * This function updates timings variables, adjusting them where necessary. 245*37506412SHans Petter Selasky *------------------------------------------------------------------------*/ 246*37506412SHans Petter Selasky static int usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS) 247*37506412SHans Petter Selasky { 248*37506412SHans Petter Selasky int error = 0; 249*37506412SHans Petter Selasky unsigned int val; 250*37506412SHans Petter Selasky 251*37506412SHans Petter Selasky /* 252*37506412SHans Petter Selasky * Attempt to get a coherent snapshot by making a copy of the data. 253*37506412SHans Petter Selasky */ 254*37506412SHans Petter Selasky if (arg1) 255*37506412SHans Petter Selasky val = *(unsigned int *)arg1; 256*37506412SHans Petter Selasky else 257*37506412SHans Petter Selasky val = arg2; 258*37506412SHans Petter Selasky error = SYSCTL_OUT(req, &val, sizeof(int)); 259*37506412SHans Petter Selasky if (error || !req->newptr) 260*37506412SHans Petter Selasky return (error); 261*37506412SHans Petter Selasky 262*37506412SHans Petter Selasky if (!arg1) 263*37506412SHans Petter Selasky return EPERM; 264*37506412SHans Petter Selasky 265*37506412SHans Petter Selasky error = SYSCTL_IN(req, &val, sizeof(unsigned int)); 266*37506412SHans Petter Selasky if (error) 267*37506412SHans Petter Selasky return (error); 268*37506412SHans Petter Selasky 269*37506412SHans Petter Selasky /* 270*37506412SHans Petter Selasky * Now make sure the values are decent, and certainly no lower than 271*37506412SHans Petter Selasky * what the USB spec prescribes. 272*37506412SHans Petter Selasky */ 273*37506412SHans Petter Selasky unsigned int *p = (unsigned int *)arg1; 274*37506412SHans Petter Selasky if (p == &usb_port_reset_delay) { 275*37506412SHans Petter Selasky if (val < USB_PORT_RESET_DELAY_SPEC) 276*37506412SHans Petter Selasky return (EINVAL); 277*37506412SHans Petter Selasky } else if (p == &usb_port_root_reset_delay) { 278*37506412SHans Petter Selasky if (val < USB_PORT_ROOT_RESET_DELAY_SPEC) 279*37506412SHans Petter Selasky return (EINVAL); 280*37506412SHans Petter Selasky } else if (p == &usb_port_reset_recovery) { 281*37506412SHans Petter Selasky if (val < USB_PORT_RESET_RECOVERY_SPEC) 282*37506412SHans Petter Selasky return (EINVAL); 283*37506412SHans Petter Selasky } else if (p == &usb_port_powerup_delay) { 284*37506412SHans Petter Selasky if (val < USB_PORT_POWERUP_DELAY_SPEC) 285*37506412SHans Petter Selasky return (EINVAL); 286*37506412SHans Petter Selasky } else if (p == &usb_port_resume_delay) { 287*37506412SHans Petter Selasky if (val < USB_PORT_RESUME_DELAY_SPEC) 288*37506412SHans Petter Selasky return (EINVAL); 289*37506412SHans Petter Selasky } else if (p == &usb_set_address_settle) { 290*37506412SHans Petter Selasky if (val < USB_SET_ADDRESS_SETTLE_SPEC) 291*37506412SHans Petter Selasky return (EINVAL); 292*37506412SHans Petter Selasky } else if (p == &usb_resume_delay) { 293*37506412SHans Petter Selasky if (val < USB_RESUME_DELAY_SPEC) 294*37506412SHans Petter Selasky return (EINVAL); 295*37506412SHans Petter Selasky } else if (p == &usb_resume_wait) { 296*37506412SHans Petter Selasky if (val < USB_RESUME_WAIT_SPEC) 297*37506412SHans Petter Selasky return (EINVAL); 298*37506412SHans Petter Selasky } else if (p == &usb_resume_recovery) { 299*37506412SHans Petter Selasky if (val < USB_RESUME_RECOVERY_SPEC) 300*37506412SHans Petter Selasky return (EINVAL); 301*37506412SHans Petter Selasky } else if (p == &usb_extra_power_up_time) { 302*37506412SHans Petter Selasky if (val < USB_EXTRA_POWER_UP_TIME_SPEC) 303*37506412SHans Petter Selasky return (EINVAL); 304*37506412SHans Petter Selasky } else { 305*37506412SHans Petter Selasky /* noop */ 306*37506412SHans Petter Selasky } 307*37506412SHans Petter Selasky 308*37506412SHans Petter Selasky *p = val; 309*37506412SHans Petter Selasky return 0; 310*37506412SHans Petter Selasky } 311*37506412SHans Petter Selasky #endif 312