/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2010, Intel Corporation.
* All rights reserved.
*/
#include <sys/dditypes.h>
#include <sys/ddi_impldefs.h>
#include <sys/ndi_impldefs.h>
#include <sys/mem_config.h>
#include <sys/mem_cage.h>
#include <sys/sysmacros.h>
#include <sys/archsystm.h>
#include <sys/machsystm.h>
#include <sys/x86_archext.h>
#include <sys/fastboot_impl.h>
#include <sys/sysevent.h>
#include <sys/acpidev_rsc.h>
#include <sys/acpidev_dr.h>
#include "drmach_acpi.h"
/* utility */
static int drmach_init(void);
static void drmach_fini(void);
static int drmach_name2type_idx(char *);
static void drmach_io_dispose(drmachid_t);
static void drmach_cpu_dispose(drmachid_t);
static void drmach_mem_dispose(drmachid_t);
#ifdef DEBUG
#endif /* DEBUG */
/* rwlock to protect drmach_boards. */
/* rwlock to block out CPR thread. */
/* CPR callb id. */
static struct {
const char *name;
const char *type;
} drmach_name2type[] = {
};
/*
* drmach autoconfiguration data structures and interfaces
*/
"ACPI based DR v1.0"
};
(void *)&modlmisc,
};
int
_init(void)
{
int err;
if ((err = drmach_init()) != 0) {
return (err);
}
drmach_fini();
}
return (err);
}
int
_fini(void)
{
int err;
drmach_fini();
}
return (err);
}
int
{
}
/*
* Internal support functions.
*/
static DRMACH_HANDLE
{
}
static dev_info_t *
{
return (NULL);
}
return (dip);
}
static int
{
int rv = 0;
DRMACH_PR("!drmach_node_acpi_get_prop: NULL handle");
rv = -1;
} else {
if (rv >= 0) {
rv = 0;
}
}
return (rv);
}
static int
{
int rv = 0;
DRMACH_PR("!drmach_node_acpi_get_proplen: NULL handle");
rv = -1;
} else {
if (rv >= 0) {
return (0);
}
}
return (-1);
}
static ACPI_STATUS
{
int rv;
/* Skip subtree if the device is not powered. */
if (!acpidev_dr_device_is_powered(hdl)) {
return (AE_CTRL_DEPTH);
}
/*
* Keep scanning subtree if it fails to lookup device node.
* There may be some ACPI objects without device nodes created.
*/
return (AE_OK);
}
if (rv) {
return (AE_CTRL_TERMINATE);
}
/*
*/
return (AE_CTRL_DEPTH);
}
return (AE_OK);
}
static int
{
int rv = 0;
/* initialize the args structure for callback */
/* save the handle, it will be modified when walking the tree. */
DRMACH_PR("!drmach_node_acpi_walk: failed to get device node.");
return (EX86_INAPPROP);
}
/*
* If acpidev_dr_device_walk_device() itself fails, rv won't
* be set to suitable error code. Set it here.
*/
if (rv == 0) {
"walk ACPI namespace.");
rv = EX86_ACPIWALK;
}
}
/* restore the handle to original value after walking the tree. */
return ((int)rv);
}
static drmach_node_t *
drmach_node_new(void)
{
return (np);
}
static drmachid_t
{
dup = drmach_node_new();
return (dup);
}
static void
{
}
static int
{
}
static DRMACH_HANDLE
{
}
/*
* drmach_array provides convenient array construction, access,
* bounds checking and array destruction logic.
*/
static drmach_array_t *
{
return (arr);
} else {
return (0);
}
}
static int
{
return (-1);
return (0);
}
/*
* Get the item with index idx.
* Return 0 with the value stored in val if succeeds, otherwise return -1.
*/
static int
{
return (-1);
return (0);
}
static int
{
int rv;
*idx += 1;
return (rv);
}
static int
{
int rv;
*idx += 1;
*idx += 1;
return (rv);
}
static void
{
int rv;
while (rv == 0) {
}
}
static drmach_board_t *
{
return ((drmach_board_t *)id);
else
return (NULL);
}
{
int i;
int rv;
if (rv) {
/* every node is expected to have a name */
return (err);
}
/*
* The node currently being examined is not listed in the name2type[]
* array. In this case, the node is no interest to drmach. Both
* dp and err are initialized here to yield nothing (no device or
* error structure) for this case.
*/
i = drmach_name2type_idx(name);
if (i < 0) {
*idp = (drmachid_t)0;
return (NULL);
}
/* device specific new function will set unum */
}
static void
{
}
static sbd_error_t *
{
if (!DRMACH_IS_ID(id))
}
{
return (NULL);
}
sbd_err_clear(&err);
return (NULL);
}
} else {
bp->boot_board = 0;
}
} else {
}
return (bp);
}
static void
{
}
static sbd_error_t *
{
if (!DRMACH_IS_BOARD_ID(id))
return (NULL);
}
static int
{
return (acpidev_dr_device_is_powered(hdl));
}
struct drmach_board_list_dep_arg {
int count;
char *buf;
};
static ACPI_STATUS
void **retval)
{
/* Skip non-board devices. */
if (!acpidev_dr_device_is_board(hdl)) {
return (AE_OK);
}
DRMACH_PR("!drmach_board_generate_name: failed to "
"generate board name for handle %p.", hdl);
/* Keep on walking. */
return (AE_OK);
}
return (AE_CTRL_TERMINATE);
}
return (AE_OK);
}
static ssize_t
{
return (-1);
}
*buf = '\0';
return (-1);
}
/* Generate the device dependency list. */
if (edl) {
} else {
}
if (ACPI_FAILURE(rc)) {
*buf = '\0';
/* No device has dependency on this board. */
*buf = '\0';
}
return (off);
}
static sbd_error_t *
{
if (!DRMACH_IS_BOARD_ID(id))
} else {
}
/* Generate the eject device list. */
DRMACH_PR("!drmach_board_status: failed to generate "
}
DRMACH_PR("!drmach_board_status: failed to generate "
}
}
case ACPIDEV_CPU_BOARD:
break;
case ACPIDEV_MEMORY_BOARD:
break;
case ACPIDEV_IO_BOARD:
break;
case ACPIDEV_SYSTEM_BOARD:
/*FALLTHROUGH*/
default:
break;
}
int rv;
while (rv == 0) {
if (err)
break;
}
}
return (err);
}
/*
* When DR is initialized, we walk the device tree and acquire a hold on
* all the nodes that are interesting to DR. This is so that the corresponding
* branches cannot be deleted.
*/
static int
{
/* Skip nodes and subtrees which are not created by acpidev. */
return (DDI_WALK_PRUNECHILD);
}
return (DDI_WALK_PRUNECHILD);
}
if (acpidev_data_dr_ready(dhdl)) {
if (*holdp) {
} else {
}
}
return (DDI_WALK_CONTINUE);
}
static void
drmach_hold_devtree(void)
{
int circ;
dip = ddi_root_node();
}
static void
drmach_release_devtree(void)
{
int circ;
int hold = 0;
dip = ddi_root_node();
}
static boolean_t
{
if (code == CB_CODE_CPR_CHKPT) {
/*
* Temporarily block CPR operations if there are DR operations
* ongoing.
*/
} else {
}
return (B_TRUE);
}
static int
drmach_init(void)
{
if (MAX_BOARDS > SHRT_MAX) {
"hotplug capable boards.", MAX_BOARDS);
return (ENXIO);
} else if (MAX_CMP_UNITS_PER_BOARD > 1) {
"(%d) physical processors on one board.",
return (ENXIO);
} else if (!ISP2(MAX_CORES_PER_CMP)) {
"physical processor is not power of 2.",
return (ENXIO);
} else if (MAX_CPU_UNITS_PER_BOARD > DEVSET_CPU_NUMBER ||
"units than the DR driver can handle.");
return (ENXIO);
}
CB_CL_CPR_PM, "drmach");
"handle for board %d.", bnum);
continue;
}
DRMACH_PR("!drmach_init: failed to get handle "
"for board %d.", bnum);
ASSERT(0);
goto error;
}
}
/*
* Walk descendants of the devinfo root node and hold
* all devinfo branches of interest.
*/
return (0);
return (ENXIO);
}
static void
drmach_fini(void)
{
if (drmach_boards != NULL) {
}
/*
* Walk descendants of the root devinfo node
* release holds acquired on branches in drmach_init()
*/
(void) callb_delete(drmach_cpr_cid);
}
{
int portid;
return (NULL);
}
static void
{
}
static sbd_error_t *
{
if (!DRMACH_IS_IO_ID(id))
return (NULL);
}
static sbd_error_t *
{
int configured;
if (err)
return (err);
return (NULL);
}
{
int portid;
/* the portid is APIC ID of the node */
/*
* Assume all CPUs are homogeneous and have the same number of
*/
} else {
}
/* Mark CPU0 as busy, many other components have dependency on it. */
}
return (NULL);
}
static void
{
}
static sbd_error_t *
{
if (!DRMACH_IS_CPU_ID(id))
return (NULL);
}
static sbd_error_t *
{
return (NULL);
}
static int
{
return (-1);
return (-1);
} else {
}
addr_max = 0;
total_size = 0;
skipped_size = 0;
/*
* There's a memory hole just below 4G on x86, which needs special
* handling. All other addresses assigned to a specific memory device
* should be contiguous.
*/
&count))) {
return (-1);
}
for (i = 0, j = 0; i < count; i++) {
if (size == 0)
continue;
else
j++;
total_size += size;
j <= acpidev_dr_max_segments_per_mem_device()) {
} else {
skipped_size += size;
}
}
if (skipped_size != 0) {
"of memory skipped.",
}
/*
* we intersect phys_install to get base_pa.
* This only works at boot-up time.
*/
}
}
/*
* Create a memlist for the memory board.
* The created memlist only contains configured memory if there's
* configured memory on the board, otherwise it contains all memory
* on the board.
*/
if (ml2) {
struct memlist *p;
}
if (nbytes == 0) {
} else {
/* Node has configured memory at boot time. */
if (ml)
}
}
/* Not configured at boot time. */
}
return (0);
}
{
int portid;
}
/* make sure we do not create memoryless nodes */
} else
return (NULL);
}
static void
{
}
}
static sbd_error_t *
{
if (!DRMACH_IS_MEM_ID(id))
return (NULL);
}
static sbd_error_t *
{
/* get starting physical address of target memory */
/* round down to slice boundary */
/* stop at first span that is in slice */
break;
return (NULL);
}
/*
* Public interfaces exported to support platform independent dr driver.
*/
drmach_max_boards(void)
{
return (acpidev_dr_max_boards());
}
{
return (acpidev_dr_max_io_units_per_board());
}
{
return (acpidev_dr_max_cmp_units_per_board());
}
{
return (acpidev_dr_max_mem_units_per_board());
}
drmach_max_core_per_cmp(void)
{
return (acpidev_dr_max_cpu_units_per_cmp());
}
{
/* allow status and ncm operations to always succeed */
return (NULL);
}
switch (cmd) {
case SBD_CMD_POWERON:
case SBD_CMD_POWEROFF:
/*
* Note: this is a temporary solution and will be revised when
*
* ACPI BIOS generates some static ACPI tables, such as MADT,
* SRAT and SLIT, to describe system hardware configuration on
* static tables won't be updated and will become stale.
*
* If we reset system by fast reboot, BIOS will have no chance
* to regenerate those staled static tables. Fast reboot can't
* tolerate such inconsistency between staled ACPI tables and
* real hardware configuration yet.
*
* A temporary solution is introduced to disable fast reboot if
* DR operations.
*/
/*FALLTHROUGH*/
default:
/* Block out the CPR thread. */
break;
}
/* check all other commands for the required option string */
}
} else {
}
switch (cmd) {
case SBD_CMD_TEST:
break;
case SBD_CMD_CONNECT:
else if (!drmach_domain.allow_dr)
break;
case SBD_CMD_DISCONNECT:
else if (!drmach_domain.allow_dr)
break;
default:
if (!drmach_domain.allow_dr)
break;
}
}
/*
* With early versions, some operations should be blocked here.
* operations are supported on x86 systems.
*
* We only need to filter unsupported device types for
* SBD_CMD_CONFIGURE/SBD_CMD_UNCONFIGURE commands, all other
* commands are supported by all device types.
*/
int i;
switch (cmd) {
case SBD_CMD_CONFIGURE:
if (!plat_dr_support_cpu()) {
} else {
for (i = MAX_CPU_UNITS_PER_BOARD;
i < DEVSET_CPU_NUMBER; i++) {
}
}
if (!plat_dr_support_memory()) {
} else {
for (i = MAX_MEM_UNITS_PER_BOARD;
i < DEVSET_MEM_NUMBER; i++) {
}
}
/* No support of configuring IOH devices yet. */
break;
case SBD_CMD_UNCONFIGURE:
if (!plat_dr_support_cpu()) {
} else {
for (i = MAX_CPU_UNITS_PER_BOARD;
i < DEVSET_CPU_NUMBER; i++) {
}
}
break;
}
if (DEVSET_IS_NULL(devset)) {
}
}
return (err);
}
{
switch (cmd) {
case SBD_CMD_STATUS:
case SBD_CMD_GETNCM:
break;
default:
break;
}
return (NULL);
}
{
if (!DRMACH_IS_DEVICE_ID(id))
/* allocate cpu id for the CPU device. */
if (DRMACH_IS_CPU_ID(id)) {
}
return (err);
}
if (DRMACH_IS_MEM_ID(id)) {
if (err)
return (err);
}
/* If non-NULL, fdip is returned held and must be released */
}
return (err);
}
{
if (!DRMACH_IS_DEVICE_ID(id))
if (DRMACH_IS_CPU_ID(id)) {
}
return (err);
}
/*
* Note: FORCE flag is no longer necessary under devfs
*/
/*
* If non-NULL, fdip is returned held and must be released.
*/
} else {
}
}
return (err);
}
{
if (!DRMACH_IS_DEVICE_ID(id))
return (NULL);
}
{
if (!DRMACH_IS_DEVICE_ID(id))
}
{
if (!DRMACH_IS_ID(id)) {
}
return (err);
}
static sbd_error_t *
{
char *copts;
/* Get the status code. */
strlen(ACPIDEV_CMD_OST_INPROGRESS)) == 0) {
inprogress = B_TRUE;
strlen(ACPIDEV_CMD_OST_SUCCESS)) == 0) {
strlen(ACPIDEV_CMD_OST_FAILURE)) == 0) {
strlen(ACPIDEV_CMD_OST_NOOP)) == 0) {
return (NULL);
} else {
}
/* Get the event type. */
}
if (copts[0] != '=') {
}
strlen(ACPIDEV_EVENT_TYPE_BUS_CHECK)) == 0) {
strlen(ACPIDEV_EVENT_TYPE_DEVICE_CHECK)) == 0) {
strlen(ACPIDEV_EVENT_TYPE_DEVICE_CHECK_LIGHT)) == 0) {
strlen(ACPIDEV_EVENT_TYPE_EJECT_REQUEST)) == 0) {
if (inprogress) {
}
} else {
}
return (NULL);
}
static struct {
const char *name;
} drmach_pt_arr[] = {
/* the following line must always be last */
};
{
int i;
i = 0;
break;
i += 1;
}
else
return (err);
}
/*
* Board specific interfaces to support dr driver
*/
static int
{
/*
* acpidev returns portid as uint32_t, validates it.
*/
return (-1);
} else {
return (portid);
}
}
return (-1);
}
/*
* This is a helper function to determine if a given
* node should be considered for a dr operation according
* to predefined dr type nodes and the node's name.
* Formal Parameter : The name of a device node.
* Return Value: -1, name does not map to a valid dr type.
* A value greater or equal to 0, name is a valid dr type.
*/
static int
{
return (-1);
/*
* Determine how many possible types are currently supported
* for dr.
*/
/* Determine if the node's name correspond to a predefined type. */
/* The node is an allowed type for dr. */
return (index);
}
/*
* If the name of the node does not map to any of the
* types in the array drmach_name2type then the node is not of
* interest to dr.
*/
return (-1);
}
static int
{
if (rv)
return (0);
if (rv) {
return (0);
}
return (0);
}
return (0);
if (drmach_name2type_idx(name) < 0) {
return (0);
}
/*
* Create a device data structure from this node data.
* The call may yield nothing if the node is not of interest
* to drmach.
*/
return (-1);
else if (!id) {
/*
* drmach_device_new examined the node we passed in
* and determined that it was one not of interest to
* drmach. So, it is skipped.
*/
return (0);
}
if (rv) {
return (-1);
}
}
{
int max_devices;
int rv;
if (!DRMACH_IS_BOARD_ID(id))
data.a = a;
if (rv == 0) {
} else {
else
err = DRMACH_INTERNAL_ERROR();
}
return (err);
}
int
{
int rv = 0;
if (bnum < 0) {
*id = 0;
return (-1);
}
*id = 0;
rv = -1;
}
return (rv);
}
{
if (bnum < 0) {
}
DRMACH_PR("!drmach_board_name: failed to lookup ACPI handle "
"for board %d.", bnum);
DRMACH_PR("!drmach_board_name: failed to generate board name "
"for board %d.", bnum);
": buffer is too small for board name.");
}
return (err);
}
int
{
if (!DRMACH_IS_BOARD_ID(id))
return (0);
}
static ACPI_STATUS
void **retval)
{
/* Skip non-board devices. */
if (!acpidev_dr_device_is_board(hdl)) {
return (AE_OK);
DRMACH_PR("!drmach_board_check_dependent_cb: failed to get "
"board number for object %p.\n", hdl);
return (AE_ERROR);
} else if (bdnum > MAX_BOARDS) {
DRMACH_PR("!drmach_board_check_dependent_cb: board number %u "
return (AE_ERROR);
}
switch (cmd) {
case SBD_CMD_CONNECT:
/*
* Its parent board should be present, assigned, powered and
* connected when connecting the child board.
*/
} else {
}
}
break;
case SBD_CMD_POWERON:
/*
* Its parent board should be present, assigned and powered when
* powering on the child board.
*/
} else {
}
}
break;
case SBD_CMD_ASSIGN:
/*
* Its parent board should be present and assigned when
* assigning the child board.
*/
}
break;
case SBD_CMD_DISCONNECT:
/*
* The child board should be disconnected if present when
* disconnecting its parent board.
*/
}
break;
case SBD_CMD_POWEROFF:
/*
* The child board should be disconnected and powered off if
* present when powering off its parent board.
*/
}
}
break;
case SBD_CMD_UNASSIGN:
/*
* The child board should be disconnected, powered off and
* unassigned if present when unassigning its parent board.
*/
}
}
break;
default:
/* Return success for all other commands. */
break;
}
return (rc);
}
{
int reverse;
char *name;
switch (cmd) {
case SBD_CMD_ASSIGN:
case SBD_CMD_POWERON:
case SBD_CMD_CONNECT:
return (NULL);
}
reverse = 0;
break;
case SBD_CMD_UNASSIGN:
case SBD_CMD_POWEROFF:
case SBD_CMD_DISCONNECT:
return (NULL);
}
reverse = 1;
break;
default:
}
}
} else if (reverse == 0) {
} else {
}
return (err);
}
{
if (bnum < 0) {
}
} else {
/*
* Board has already been created, downgrade to reader.
*/
if (*id)
if (!(*id))
DRMACH_PR("!drmach_board_assign: failed to create "
"object for board %d.", bnum);
} else {
}
}
return (err);
}
{
if (DRMACH_NULL_ID(id))
return (NULL);
if (!DRMACH_IS_BOARD_ID(id)) {
}
if (err) {
return (err);
}
} else {
err = DRMACH_INTERNAL_ERROR();
else
}
}
return (err);
}
{
if (!DRMACH_IS_BOARD_ID(id))
return (NULL);
}
/* Check whether the board is powered on. */
}
return (err);
}
{
if (DRMACH_NULL_ID(id))
return (NULL);
if (!DRMACH_IS_BOARD_ID(id))
/* Check whether the board is busy, configured or connected. */
return (err);
}
return (NULL);
}
}
return (err);
}
{
if (DRMACH_NULL_ID(id))
return (NULL);
if (!DRMACH_IS_BOARD_ID(id))
return (NULL);
}
{
if (!DRMACH_IS_BOARD_ID(id))
(void) acpidev_dr_device_remove(hdl);
} else {
}
}
return (err);
}
{
if (DRMACH_NULL_ID(id))
return (NULL);
if (!DRMACH_IS_BOARD_ID(id))
/* Check whether the board is busy or configured. */
return (err);
} else {
}
}
return (err);
}
{
if (!DRMACH_IS_BOARD_ID(id))
}
bp->boot_board = 0;
return (NULL);
}
/*
* CPU specific interfaces to support dr driver
*/
{
if (!DRMACH_IS_CPU_ID(id))
return (NULL);
}
{
if (!DRMACH_IS_CPU_ID(id))
} else {
*cpuid = -1;
}
} else {
}
return (NULL);
}
{
if (!DRMACH_IS_CPU_ID(id))
/* Assume all CPUs in system are homogeneous. */
/* NHM-EX CPU */
}
}
return (NULL);
}
/*
* Memory specific interfaces to support dr driver
*/
/*
* When drmach_mem_new() is called, the mp->base_pa field is set to the base
* address of configured memory if there's configured memory on the board,
* otherwise set to UINT64_MAX. For hot-added memory board, there's no
* configured memory when drmach_mem_new() is called, so mp->base_pa is set
* to UINT64_MAX and we need to set a correct value for it after memory
* hot-add operations.
* A hot-added memory board may contain multiple memory segments,
* drmach_mem_add_span() will be called once for each segment, so we can't
* rely on the basepa argument. And it's possible that only part of a memory
* segment is added into OS, so need to intersect with phys_installed list
* to get the real base address of configured memory on the board.
*/
{
struct memlist *p;
if (!DRMACH_IS_MEM_ID(id))
/* Compute basepa and size of installed memory. */
}
if (ml2) {
}
}
return (NULL);
}
static sbd_error_t *
{
void *hdlp;
if (!DRMACH_IS_MEM_ID(id))
/* No need to update lgrp if memory is already installed. */
return (NULL);
/* No need to update lgrp if lgrp is disabled. */
if (max_mem_nodes == 1)
return (NULL);
/* Add memory to lgroup */
if (ACPI_FAILURE(rc)) {
"can't update lgrp information.");
}
if (ACPI_FAILURE(rc)) {
"can't update lgrp information.");
}
return (NULL);
}
{
if (!DRMACH_IS_MEM_ID(id))
else
return (NULL);
}
{
if (!DRMACH_IS_MEM_ID(id))
/*
* for copying.
*/
return (NULL);
}
{
if (!DRMACH_IS_MEM_ID(id))
if (bp)
if (ep)
if (sp)
return (NULL);
}
{
#ifdef DEBUG
int rv;
#endif
if (!DRMACH_IS_MEM_ID(id))
#ifdef DEBUG
/*
* Make sure the incoming memlist doesn't already
* intersect with what's present in the system (phys_install).
*/
if (rv) {
DRMACH_PR("Derived memlist intersects with phys_install\n");
DRMACH_PR("phys_install memlist:\n");
return (DRMACH_INTERNAL_ERROR());
}
DRMACH_PR("Derived memlist:");
#endif
return (NULL);
}
{
return (CPU_CURRENT);
}
int
{
return (0);
}
/*
* IO specific interfaces to support dr driver
*/
{
if (!DRMACH_IS_IO_ID(id))
return (NULL);
}
{
if (!DRMACH_IS_IO_ID(id))
return (NULL);
}
{
return (NULL);
}
{
if (!DRMACH_IS_IO_ID(id))
return (NULL);
}
{
int state;
if (!DRMACH_IS_IO_ID(id))
*yes = 0;
return (NULL);
}
(state == DDI_DEVSTATE_UP));
return (NULL);
}
/*
* Miscellaneous interfaces to support dr driver
*/
int
{
return (0);
}
void
drmach_suspend_last(void)
{
}
void
drmach_resume_first(void)
{
}
/*
* Log a DR sysevent.
* Return value: 0 success, non-zero failure.
*/
int
{
attach_pnt[0] = '\0';
sbd_err_clear(&err);
rv = -1;
goto logexit;
}
if (verbose) {
DRMACH_PR("drmach_log_sysevent: %s %s, flag: %d, verbose: %d\n",
}
rv = -2;
goto logexit;
}
km_flag)) != 0)
goto logexit;
km_flag)) != 0) {
goto logexit;
}
/*
* Log the event but do not sleep waiting for its
* delivery. This provides insulation from syseventd.
*/
if (ev)
return (rv);
}