15295Srandyf /* 25295Srandyf * CDDL HEADER START 35295Srandyf * 45295Srandyf * The contents of this file are subject to the terms of the 55295Srandyf * Common Development and Distribution License (the "License"). 65295Srandyf * You may not use this file except in compliance with the License. 75295Srandyf * 85295Srandyf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95295Srandyf * or http://www.opensolaris.org/os/licensing. 105295Srandyf * See the License for the specific language governing permissions 115295Srandyf * and limitations under the License. 125295Srandyf * 135295Srandyf * When distributing Covered Code, include this CDDL HEADER in each 145295Srandyf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155295Srandyf * If applicable, add the following below this CDDL HEADER, with the 165295Srandyf * fields enclosed by brackets "[]" replaced with your own identifying 175295Srandyf * information: Portions Copyright [yyyy] [name of copyright owner] 185295Srandyf * 195295Srandyf * CDDL HEADER END 205295Srandyf */ 215295Srandyf 225295Srandyf /* 2310311SRandy.Fishel@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 245295Srandyf * Use is subject to license terms. 255295Srandyf */ 265295Srandyf 275295Srandyf 285295Srandyf /* 295295Srandyf * srn Provide apm-like interfaces to Xorg 305295Srandyf */ 315295Srandyf 325295Srandyf #include <sys/types.h> 335295Srandyf #include <sys/errno.h> 345295Srandyf #include <sys/modctl.h> 355295Srandyf #include <sys/conf.h> /* driver flags and functions */ 365295Srandyf #include <sys/open.h> /* OTYP_CHR definition */ 375295Srandyf #include <sys/stat.h> /* S_IFCHR definition */ 385295Srandyf #include <sys/pathname.h> /* name -> dev_info xlation */ 395295Srandyf #include <sys/kmem.h> /* memory alloc stuff */ 405295Srandyf #include <sys/debug.h> 415295Srandyf #include <sys/pm.h> 425295Srandyf #include <sys/ddi.h> 435295Srandyf #include <sys/sunddi.h> 445295Srandyf #include <sys/epm.h> 455295Srandyf #include <sys/vfs.h> 465295Srandyf #include <sys/mode.h> 475295Srandyf #include <sys/mkdev.h> 485295Srandyf #include <sys/promif.h> 495295Srandyf #include <sys/consdev.h> 505295Srandyf #include <sys/ddi_impldefs.h> 515295Srandyf #include <sys/poll.h> 525295Srandyf #include <sys/note.h> 535295Srandyf #include <sys/taskq.h> 545295Srandyf #include <sys/policy.h> 555295Srandyf #include <sys/srn.h> 565295Srandyf 575295Srandyf /* 585295Srandyf * Minor number is instance<<8 + clone minor from range 1-255; 595295Srandyf * But only one will be allocated 605295Srandyf */ 615295Srandyf #define SRN_MINOR_TO_CLONE(minor) ((minor) & (SRN_MAX_CLONE - 1)) 625295Srandyf #define SU 0x002 635295Srandyf #define SG 0x004 645295Srandyf 655295Srandyf extern kmutex_t srn_clone_lock; /* protects srn_clones array */ 665295Srandyf extern kcondvar_t srn_clones_cv[SRN_MAX_CLONE]; 675295Srandyf extern uint_t srn_poll_cnt[SRN_MAX_CLONE]; 685295Srandyf 695295Srandyf /* 705295Srandyf * The soft state of the srn driver. Since there will only be 715295Srandyf * one of these, just reference it through a static struct. 725295Srandyf */ 735295Srandyf static struct srnstate { 745295Srandyf dev_info_t *srn_dip; /* ptr to our dev_info node */ 755295Srandyf int srn_instance; /* for ddi_get_instance() */ 765295Srandyf uchar_t srn_clones[SRN_MAX_CLONE]; /* unique opens */ 775295Srandyf struct cred *srn_cred[SRN_MAX_CLONE]; /* cred for each open */ 785295Srandyf int srn_type[SRN_MAX_CLONE]; /* type of handshake */ 795295Srandyf int srn_delivered[SRN_MAX_CLONE]; 805295Srandyf srn_event_info_t srn_pending[SRN_MAX_CLONE]; 8110311SRandy.Fishel@Sun.COM int srn_fault[SRN_MAX_CLONE]; 825295Srandyf } srn = { NULL, -1}; 835295Srandyf typedef struct srnstate *srn_state_t; 845295Srandyf 855295Srandyf kcondvar_t srn_clones_cv[SRN_MAX_CLONE]; 865295Srandyf uint_t srn_poll_cnt[SRN_MAX_CLONE]; /* count of events for poll */ 875295Srandyf int srn_apm_count; 885295Srandyf int srn_autosx_count; 8910311SRandy.Fishel@Sun.COM /* Number of seconds to wait for clients to ack a poll */ 9010311SRandy.Fishel@Sun.COM int srn_timeout = 10; 9110311SRandy.Fishel@Sun.COM 925295Srandyf struct pollhead srn_pollhead[SRN_MAX_CLONE]; 935295Srandyf 945295Srandyf static int srn_open(dev_t *, int, int, cred_t *); 955295Srandyf static int srn_close(dev_t, int, int, cred_t *); 965295Srandyf static int srn_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 975295Srandyf static int srn_chpoll(dev_t, short, int, short *, struct pollhead **); 985295Srandyf 995295Srandyf static struct cb_ops srn_cb_ops = { 1005295Srandyf srn_open, /* open */ 1015295Srandyf srn_close, /* close */ 1025295Srandyf nodev, /* strategy */ 1035295Srandyf nodev, /* print */ 1045295Srandyf nodev, /* dump */ 1055295Srandyf nodev, /* read */ 1065295Srandyf nodev, /* write */ 1075295Srandyf srn_ioctl, /* ioctl */ 1085295Srandyf nodev, /* devmap */ 1095295Srandyf nodev, /* mmap */ 1105295Srandyf nodev, /* segmap */ 1115295Srandyf srn_chpoll, /* poll */ 1125295Srandyf ddi_prop_op, /* prop_op */ 1135295Srandyf NULL, /* streamtab */ 1145295Srandyf D_NEW | D_MP /* driver compatibility flag */ 1155295Srandyf }; 1165295Srandyf 1175295Srandyf static int srn_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 1185295Srandyf void **result); 1195295Srandyf static int srn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 1205295Srandyf static int srn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 1215295Srandyf static void srn_notify(int type, int event); 1225295Srandyf 1235295Srandyf static struct dev_ops srn_ops = { 1245295Srandyf DEVO_REV, /* devo_rev */ 1255295Srandyf 0, /* refcnt */ 1265295Srandyf srn_getinfo, /* info */ 1275295Srandyf nulldev, /* identify */ 1285295Srandyf nulldev, /* probe */ 1295295Srandyf srn_attach, /* attach */ 1305295Srandyf srn_detach, /* detach */ 1315295Srandyf nodev, /* reset */ 1325295Srandyf &srn_cb_ops, /* driver operations */ 1335295Srandyf NULL, /* bus operations */ 1347656SSherry.Moore@Sun.COM NULL, /* power */ 1357656SSherry.Moore@Sun.COM ddi_quiesce_not_needed, /* quiesce */ 1365295Srandyf }; 1375295Srandyf 1385295Srandyf static struct modldrv modldrv = { 1395295Srandyf &mod_driverops, 1407656SSherry.Moore@Sun.COM "srn driver", 1415295Srandyf &srn_ops 1425295Srandyf }; 1435295Srandyf 1445295Srandyf static struct modlinkage modlinkage = { 1455295Srandyf MODREV_1, &modldrv, 0 1465295Srandyf }; 1475295Srandyf 1485295Srandyf /* Local functions */ 1495295Srandyf 1505295Srandyf int 1515295Srandyf _init(void) 1525295Srandyf { 1535295Srandyf return (mod_install(&modlinkage)); 1545295Srandyf } 1555295Srandyf 1565295Srandyf int 1575295Srandyf _fini(void) 1585295Srandyf { 1595295Srandyf return (mod_remove(&modlinkage)); 1605295Srandyf } 1615295Srandyf 1625295Srandyf int 1635295Srandyf _info(struct modinfo *modinfop) 1645295Srandyf { 1655295Srandyf return (mod_info(&modlinkage, modinfop)); 1665295Srandyf } 1675295Srandyf 1685295Srandyf static int 1695295Srandyf srn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 1705295Srandyf { 1715295Srandyf int i; 1725295Srandyf extern void (*srn_signal)(int, int); 1735295Srandyf 1745295Srandyf switch (cmd) { 1755295Srandyf 1765295Srandyf case DDI_ATTACH: 1775295Srandyf if (srn.srn_instance != -1) /* Only allow one instance */ 1785295Srandyf return (DDI_FAILURE); 1795295Srandyf srn.srn_instance = ddi_get_instance(dip); 1805295Srandyf if (ddi_create_minor_node(dip, "srn", S_IFCHR, 1815295Srandyf (srn.srn_instance << 8) + 0, DDI_PSEUDO, 0) 1825295Srandyf != DDI_SUCCESS) { 1835295Srandyf return (DDI_FAILURE); 1845295Srandyf } 1855295Srandyf srn.srn_dip = dip; /* srn_init and getinfo depend on it */ 1865295Srandyf 1875295Srandyf for (i = 0; i < SRN_MAX_CLONE; i++) 1885295Srandyf cv_init(&srn_clones_cv[i], NULL, CV_DEFAULT, NULL); 1895295Srandyf 1905295Srandyf srn.srn_instance = ddi_get_instance(dip); 1915295Srandyf mutex_enter(&srn_clone_lock); 1925295Srandyf srn_signal = srn_notify; 1935295Srandyf mutex_exit(&srn_clone_lock); 1945295Srandyf ddi_report_dev(dip); 1955295Srandyf return (DDI_SUCCESS); 1965295Srandyf 1975295Srandyf default: 1985295Srandyf return (DDI_FAILURE); 1995295Srandyf } 2005295Srandyf } 2015295Srandyf 2025295Srandyf /* ARGSUSED */ 2035295Srandyf static int 2045295Srandyf srn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2055295Srandyf { 2065295Srandyf int i; 2075295Srandyf extern int srn_inuse; 2085295Srandyf extern void (*srn_signal)(int, int); 2095295Srandyf 2105295Srandyf switch (cmd) { 2115295Srandyf case DDI_DETACH: 2125295Srandyf 2135295Srandyf mutex_enter(&srn_clone_lock); 2145295Srandyf while (srn_inuse) { 2155295Srandyf mutex_exit(&srn_clone_lock); 2165295Srandyf delay(1); 2175295Srandyf mutex_enter(&srn_clone_lock); 2185295Srandyf } 2195295Srandyf srn_signal = NULL; 2205295Srandyf mutex_exit(&srn_clone_lock); 2215295Srandyf 2225295Srandyf for (i = 0; i < SRN_MAX_CLONE; i++) 2235295Srandyf cv_destroy(&srn_clones_cv[i]); 2245295Srandyf 2255295Srandyf ddi_remove_minor_node(dip, NULL); 2265295Srandyf srn.srn_instance = -1; 2275295Srandyf return (DDI_SUCCESS); 2285295Srandyf 2295295Srandyf default: 2305295Srandyf return (DDI_FAILURE); 2315295Srandyf } 2325295Srandyf } 2335295Srandyf 2345295Srandyf 2355295Srandyf #ifdef DEBUG 2365295Srandyf char *srn_cmd_string; 2375295Srandyf int srn_cmd; 2385295Srandyf #endif 2395295Srandyf 2405295Srandyf /* 2415295Srandyf * Returns true if permission granted by credentials 2425295Srandyf * XXX 2435295Srandyf */ 2445295Srandyf static int 2455295Srandyf srn_perms(int perm, cred_t *cr) 2465295Srandyf { 2475295Srandyf if ((perm & SU) && secpolicy_power_mgmt(cr) == 0) /* privileged? */ 2485295Srandyf return (1); 2495295Srandyf if ((perm & SG) && (crgetgid(cr) == 0)) /* group 0 is ok */ 2505295Srandyf return (1); 2515295Srandyf return (0); 2525295Srandyf } 2535295Srandyf 2545295Srandyf static int 2555295Srandyf srn_chpoll(dev_t dev, short events, int anyyet, short *reventsp, 2565295Srandyf struct pollhead **phpp) 2575295Srandyf { 25810311SRandy.Fishel@Sun.COM extern struct pollhead srn_pollhead[]; 2595295Srandyf int clone; 2605295Srandyf 2615295Srandyf clone = SRN_MINOR_TO_CLONE(getminor(dev)); 2625295Srandyf if ((events & (POLLIN | POLLRDNORM)) && srn_poll_cnt[clone]) { 2635295Srandyf *reventsp |= (POLLIN | POLLRDNORM); 2645295Srandyf } else { 2655295Srandyf *reventsp = 0; 2665295Srandyf if (!anyyet) { 2675295Srandyf *phpp = &srn_pollhead[clone]; 2685295Srandyf } 2695295Srandyf } 2705295Srandyf return (0); 2715295Srandyf } 2725295Srandyf 2735295Srandyf /*ARGSUSED*/ 2745295Srandyf static int 2755295Srandyf srn_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2765295Srandyf { 2775295Srandyf dev_t dev; 2785295Srandyf int instance; 2795295Srandyf 2805295Srandyf switch (infocmd) { 2815295Srandyf case DDI_INFO_DEVT2DEVINFO: 2825295Srandyf if (srn.srn_instance == -1) 2835295Srandyf return (DDI_FAILURE); 2845295Srandyf *result = srn.srn_dip; 2855295Srandyf return (DDI_SUCCESS); 2865295Srandyf 2875295Srandyf case DDI_INFO_DEVT2INSTANCE: 2885295Srandyf dev = (dev_t)arg; 2895295Srandyf instance = getminor(dev) >> 8; 2905295Srandyf *result = (void *)(uintptr_t)instance; 2915295Srandyf return (DDI_SUCCESS); 2925295Srandyf 2935295Srandyf default: 2945295Srandyf return (DDI_FAILURE); 2955295Srandyf } 2965295Srandyf } 2975295Srandyf 2985295Srandyf 2995295Srandyf /*ARGSUSED1*/ 3005295Srandyf static int 3015295Srandyf srn_open(dev_t *devp, int flag, int otyp, cred_t *cr) 3025295Srandyf { 3035295Srandyf int clone; 3045295Srandyf 3055295Srandyf if (otyp != OTYP_CHR) 3065295Srandyf return (EINVAL); 3075295Srandyf 3085295Srandyf mutex_enter(&srn_clone_lock); 3095295Srandyf for (clone = 1; clone < SRN_MAX_CLONE - 1; clone++) 3105295Srandyf if (!srn.srn_clones[clone]) 3115295Srandyf break; 3125295Srandyf 3135295Srandyf if (clone == SRN_MAX_CLONE) { 3145295Srandyf mutex_exit(&srn_clone_lock); 3155295Srandyf return (ENXIO); 3165295Srandyf } 3175295Srandyf srn.srn_cred[clone] = cr; 3185295Srandyf ASSERT(srn_apm_count >= 0); 3195295Srandyf srn_apm_count++; 3205295Srandyf srn.srn_type[clone] = SRN_TYPE_APM; 3215295Srandyf crhold(cr); 3225295Srandyf 3235295Srandyf *devp = makedevice(getmajor(*devp), (srn.srn_instance << 8) + 3245295Srandyf clone); 3255295Srandyf srn.srn_clones[clone] = 1; 3265295Srandyf srn.srn_cred[clone] = cr; 3275295Srandyf crhold(cr); 3285295Srandyf mutex_exit(&srn_clone_lock); 3295295Srandyf PMD(PMD_SX, ("srn open OK\n")) 3305295Srandyf return (0); 3315295Srandyf } 3325295Srandyf 3335295Srandyf /*ARGSUSED1*/ 3345295Srandyf static int 3355295Srandyf srn_close(dev_t dev, int flag, int otyp, cred_t *cr) 3365295Srandyf { 3375295Srandyf int clone; 3385295Srandyf 3395295Srandyf if (otyp != OTYP_CHR) 3405295Srandyf return (EINVAL); 3415295Srandyf 3425295Srandyf clone = SRN_MINOR_TO_CLONE(getminor(dev)); 3435295Srandyf PMD(PMD_SX, ("srn_close: minor %x, clone %x\n", getminor(dev), 3445295Srandyf clone)) 3455295Srandyf mutex_enter(&srn_clone_lock); 3465295Srandyf crfree(srn.srn_cred[clone]); 3475295Srandyf srn.srn_cred[clone] = 0; 3485295Srandyf srn_poll_cnt[clone] = 0; 34910311SRandy.Fishel@Sun.COM srn.srn_fault[clone] = 0; 3505295Srandyf if (srn.srn_pending[clone].ae_type || srn.srn_delivered[clone]) { 3515295Srandyf srn.srn_pending[clone].ae_type = 0; 3525295Srandyf srn.srn_delivered[clone] = 0; 3535295Srandyf cv_signal(&srn_clones_cv[clone]); 3545295Srandyf } 3555295Srandyf switch (srn.srn_type[clone]) { 3565295Srandyf case SRN_TYPE_AUTOSX: 3575295Srandyf ASSERT(srn_autosx_count); 3585295Srandyf srn_autosx_count--; 3595295Srandyf break; 3605295Srandyf case SRN_TYPE_APM: 3615295Srandyf ASSERT(srn_apm_count); 3625295Srandyf srn_apm_count--; 3635295Srandyf break; 3645295Srandyf default: 3655295Srandyf ASSERT(0); 3665295Srandyf return (EINVAL); 3675295Srandyf } 3685295Srandyf srn.srn_clones[clone] = 0; 3695295Srandyf mutex_exit(&srn_clone_lock); 3705295Srandyf return (0); 3715295Srandyf } 3725295Srandyf 3735295Srandyf /*ARGSUSED*/ 3745295Srandyf static int 3755295Srandyf srn_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p) 3765295Srandyf { 3775295Srandyf int clone = SRN_MINOR_TO_CLONE(getminor(dev)); 3785295Srandyf 3795295Srandyf PMD(PMD_SX, ("ioctl: %x: begin\n", cmd)) 3805295Srandyf 3815295Srandyf switch (cmd) { 3825295Srandyf case SRN_IOC_NEXTEVENT: 3835295Srandyf case SRN_IOC_SUSPEND: 3845295Srandyf case SRN_IOC_RESUME: 3855295Srandyf case SRN_IOC_AUTOSX: 3865295Srandyf break; 3875295Srandyf default: 3885295Srandyf return (ENOTTY); 3895295Srandyf } 3905295Srandyf 3915295Srandyf if (!srn_perms(SU | SG, srn.srn_cred[clone])) { 3925295Srandyf return (EPERM); 3935295Srandyf } 3945295Srandyf switch (cmd) { 3955295Srandyf case SRN_IOC_AUTOSX: 3965295Srandyf PMD(PMD_SX, ("SRN_IOC_AUTOSX entered\n")) 3975295Srandyf mutex_enter(&srn_clone_lock); 3985295Srandyf if (!srn.srn_clones[clone]) { 3995295Srandyf PMD(PMD_SX, (" ioctl !srn_clones--EINVAL\n")) 4005295Srandyf mutex_exit(&srn_clone_lock); 4015295Srandyf return (EINVAL); 4025295Srandyf } 4035295Srandyf if (srn.srn_pending[clone].ae_type) { 4045295Srandyf PMD(PMD_SX, ("AUTOSX while pending--EBUSY\n")) 4055295Srandyf mutex_exit(&srn_clone_lock); 4065295Srandyf return (EBUSY); 4075295Srandyf } 4085295Srandyf if (srn.srn_type[clone] == SRN_TYPE_AUTOSX) { 4095295Srandyf PMD(PMD_SX, ("AUTOSX already--EBUSY\n")) 4105295Srandyf mutex_exit(&srn_clone_lock); 4115295Srandyf return (EBUSY); 4125295Srandyf } 4135295Srandyf ASSERT(srn.srn_type[clone] == SRN_TYPE_APM); 4145295Srandyf srn.srn_type[clone] = SRN_TYPE_AUTOSX; 41510311SRandy.Fishel@Sun.COM srn.srn_fault[clone] = 0; 4165295Srandyf srn_apm_count--; 4175295Srandyf ASSERT(srn_apm_count >= 0); 4185295Srandyf ASSERT(srn_autosx_count >= 0); 4195295Srandyf srn_autosx_count++; 4205295Srandyf mutex_exit(&srn_clone_lock); 4215295Srandyf PMD(PMD_SX, ("SRN_IOC_AUTOSX returns success\n")) 4225295Srandyf return (0); 4235295Srandyf 4245295Srandyf case SRN_IOC_NEXTEVENT: 4255295Srandyf /* 4265295Srandyf * return the next suspend or resume event; there should 4275295Srandyf * be one, cause we only get called if we've signalled a 4285295Srandyf * poll data completion 4295295Srandyf * then wake up the kernel thread sleeping for the delivery 4305295Srandyf */ 4315295Srandyf PMD(PMD_SX, ("SRN_IOC_NEXTEVENT entered\n")) 43210311SRandy.Fishel@Sun.COM if (srn.srn_fault[clone]) { 43310311SRandy.Fishel@Sun.COM PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d fault " 43410311SRandy.Fishel@Sun.COM "cleared\n", clone)) 43510311SRandy.Fishel@Sun.COM srn.srn_fault[clone] = 0; 43610311SRandy.Fishel@Sun.COM } 4375295Srandyf mutex_enter(&srn_clone_lock); 4385295Srandyf if (srn_poll_cnt[clone] == 0) { 4395295Srandyf mutex_exit(&srn_clone_lock); 4405295Srandyf PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d " 4415295Srandyf "EWOULDBLOCK\n", clone)) 4425295Srandyf return (EWOULDBLOCK); 4435295Srandyf } 4445295Srandyf ASSERT(srn.srn_pending[clone].ae_type); 4455295Srandyf if (ddi_copyout(&srn.srn_pending[clone], (void *)arg, 4465295Srandyf sizeof (srn_event_info_t), mode) != 0) { 4475295Srandyf mutex_exit(&srn_clone_lock); 4485295Srandyf PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d EFAULT\n", 4495295Srandyf clone)) 4505295Srandyf return (EFAULT); 4515295Srandyf } 4525295Srandyf if (srn.srn_type[clone] == SRN_TYPE_APM) 4535295Srandyf srn.srn_delivered[clone] = 4545295Srandyf srn.srn_pending[clone].ae_type; 4555295Srandyf PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d delivered %x\n", 4565295Srandyf clone, srn.srn_pending[clone].ae_type)) 4575295Srandyf srn_poll_cnt[clone] = 0; 4585295Srandyf mutex_exit(&srn_clone_lock); 4595295Srandyf return (0); 4605295Srandyf 4615295Srandyf case SRN_IOC_SUSPEND: 4625295Srandyf /* ack suspend */ 4635295Srandyf PMD(PMD_SX, ("SRN_IOC_SUSPEND entered clone %d\n", clone)) 46410311SRandy.Fishel@Sun.COM if (srn.srn_fault[clone]) { 46510311SRandy.Fishel@Sun.COM PMD(PMD_SX, ("SRN_IOC_SUSPEND clone %d fault " 46610311SRandy.Fishel@Sun.COM "cleared\n", clone)) 46710311SRandy.Fishel@Sun.COM srn.srn_fault[clone] = 0; 46810311SRandy.Fishel@Sun.COM } 4695295Srandyf mutex_enter(&srn_clone_lock); 4705295Srandyf if (srn.srn_delivered[clone] != SRN_SUSPEND_REQ) { 4715295Srandyf mutex_exit(&srn_clone_lock); 4725295Srandyf PMD(PMD_SX, ("SRN_IOC_SUSPEND EINVAL\n")) 4735295Srandyf return (EINVAL); 4745295Srandyf } 4755295Srandyf srn.srn_delivered[clone] = 0; 4765295Srandyf srn.srn_pending[clone].ae_type = 0; 4775295Srandyf /* notify the kernel suspend thread to continue */ 4785295Srandyf PMD(PMD_SX, ("SRN_IOC_SUSPEND clone %d ok\n", clone)) 4795295Srandyf cv_signal(&srn_clones_cv[clone]); 4805295Srandyf mutex_exit(&srn_clone_lock); 4815295Srandyf return (0); 4825295Srandyf 4835295Srandyf case SRN_IOC_RESUME: 4845295Srandyf /* ack resume */ 4855295Srandyf PMD(PMD_SX, ("SRN_IOC_RESUME entered clone %d\n", clone)) 48610311SRandy.Fishel@Sun.COM if (srn.srn_fault[clone]) { 48710311SRandy.Fishel@Sun.COM PMD(PMD_SX, ("SRN_IOC_RESUME clone %d fault " 48810311SRandy.Fishel@Sun.COM "cleared\n", clone)) 48910311SRandy.Fishel@Sun.COM srn.srn_fault[clone] = 0; 49010311SRandy.Fishel@Sun.COM } 4915295Srandyf mutex_enter(&srn_clone_lock); 4925295Srandyf if (srn.srn_delivered[clone] != SRN_NORMAL_RESUME) { 4935295Srandyf mutex_exit(&srn_clone_lock); 4945295Srandyf PMD(PMD_SX, ("SRN_IOC_RESUME EINVAL\n")) 4955295Srandyf return (EINVAL); 4965295Srandyf } 4975295Srandyf srn.srn_delivered[clone] = 0; 4985295Srandyf srn.srn_pending[clone].ae_type = 0; 4995295Srandyf /* notify the kernel resume thread to continue */ 5005295Srandyf PMD(PMD_SX, ("SRN_IOC_RESUME ok for clone %d\n", clone)) 5015295Srandyf cv_signal(&srn_clones_cv[clone]); 5025295Srandyf mutex_exit(&srn_clone_lock); 5035295Srandyf return (0); 5045295Srandyf 5055295Srandyf default: 5065295Srandyf PMD(PMD_SX, ("srn_ioctl unknown cmd EINVAL\n")) 5075295Srandyf return (EINVAL); 5085295Srandyf } 5095295Srandyf } 5105295Srandyf /* 5115295Srandyf * A very simple handshake with the srn driver, 5125295Srandyf * only one outstanding event at a time. 5135295Srandyf * The OS delivers the event and depending on type, 5145295Srandyf * either blocks waiting for the ack, or drives on 5155295Srandyf */ 5165295Srandyf void 5175295Srandyf srn_notify(int type, int event) 5185295Srandyf { 5195295Srandyf int clone, count; 5205295Srandyf PMD(PMD_SX, ("srn_notify entered with type %d, event 0x%x\n", 5215295Srandyf type, event)); 5225295Srandyf ASSERT(mutex_owned(&srn_clone_lock)); 5235295Srandyf switch (type) { 5245295Srandyf case SRN_TYPE_APM: 5255295Srandyf if (srn_apm_count == 0) { 5265295Srandyf PMD(PMD_SX, ("no apm types\n")) 5275295Srandyf return; 5285295Srandyf } 5295295Srandyf count = srn_apm_count; 5305295Srandyf break; 5315295Srandyf case SRN_TYPE_AUTOSX: 5325295Srandyf if (srn_autosx_count == 0) { 5335295Srandyf PMD(PMD_SX, ("no autosx types\n")) 5345295Srandyf return; 5355295Srandyf } 5365295Srandyf count = srn_autosx_count; 5375295Srandyf break; 5385295Srandyf default: 5395295Srandyf ASSERT(0); 5405295Srandyf break; 5415295Srandyf } 5425295Srandyf ASSERT(count > 0); 5435295Srandyf PMD(PMD_SX, ("count %d\n", count)) 5445295Srandyf for (clone = 0; clone < SRN_MAX_CLONE; clone++) { 5455295Srandyf if (srn.srn_type[clone] == type) { 54610311SRandy.Fishel@Sun.COM #ifdef DEBUG 547*10642SRandy.Fishel@Sun.COM if (type == SRN_TYPE_APM && !srn.srn_fault[clone]) { 5485295Srandyf ASSERT(srn.srn_pending[clone].ae_type == 0); 5495295Srandyf ASSERT(srn_poll_cnt[clone] == 0); 5505295Srandyf ASSERT(srn.srn_delivered[clone] == 0); 5515295Srandyf } 55210311SRandy.Fishel@Sun.COM #endif 5535295Srandyf srn.srn_pending[clone].ae_type = event; 5545295Srandyf srn_poll_cnt[clone] = 1; 5555295Srandyf PMD(PMD_SX, ("pollwake %d\n", clone)) 5565295Srandyf pollwakeup(&srn_pollhead[clone], (POLLRDNORM | POLLIN)); 5575295Srandyf count--; 5585295Srandyf if (count == 0) 5595295Srandyf break; 5605295Srandyf } 5615295Srandyf } 5625295Srandyf if (type == SRN_TYPE_AUTOSX) { /* we don't wait */ 5635295Srandyf PMD(PMD_SX, ("Not waiting for AUTOSX ack\n")) 5645295Srandyf return; 5655295Srandyf } 5665295Srandyf ASSERT(type == SRN_TYPE_APM); 5675295Srandyf /* otherwise wait for acks */ 5685295Srandyf restart: 5695295Srandyf /* 57010311SRandy.Fishel@Sun.COM * We wait until all of the pending events are cleared. 5715295Srandyf * We have to start over every time we do a cv_wait because 5725295Srandyf * we give up the mutex and can be re-entered 5735295Srandyf */ 5745295Srandyf for (clone = 1; clone < SRN_MAX_CLONE; clone++) { 5755295Srandyf if (srn.srn_clones[clone] == 0 || 5765295Srandyf srn.srn_type[clone] != SRN_TYPE_APM) 5775295Srandyf continue; 57810311SRandy.Fishel@Sun.COM if (srn.srn_pending[clone].ae_type && !srn.srn_fault[clone]) { 5795295Srandyf PMD(PMD_SX, ("srn_notify waiting for ack for clone %d, " 5805295Srandyf "event %x\n", clone, event)) 58110311SRandy.Fishel@Sun.COM if (cv_timedwait(&srn_clones_cv[clone], 58210311SRandy.Fishel@Sun.COM &srn_clone_lock, ddi_get_lbolt() + 58310311SRandy.Fishel@Sun.COM drv_usectohz(srn_timeout * 1000000)) == -1) { 58410311SRandy.Fishel@Sun.COM /* 58510311SRandy.Fishel@Sun.COM * Client didn't respond, mark it as faulted 58610311SRandy.Fishel@Sun.COM * and continue as if a regular signal. 58710311SRandy.Fishel@Sun.COM */ 58810311SRandy.Fishel@Sun.COM PMD(PMD_SX, ("srn_notify: clone %d did not " 58910311SRandy.Fishel@Sun.COM "ack event %x\n", clone, event)) 59010311SRandy.Fishel@Sun.COM cmn_err(CE_WARN, "srn_notify: clone %d did " 59110311SRandy.Fishel@Sun.COM "not ack event %x\n", clone, event); 59210311SRandy.Fishel@Sun.COM srn.srn_fault[clone] = 1; 59310311SRandy.Fishel@Sun.COM } 5945295Srandyf goto restart; 5955295Srandyf } 5965295Srandyf } 5975295Srandyf PMD(PMD_SX, ("srn_notify done with %x\n", event)) 5985295Srandyf } 599