ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim/*
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * CDDL HEADER START
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim *
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * The contents of this file are subject to the terms of the
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * Common Development and Distribution License (the "License").
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * You may not use this file except in compliance with the License.
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim *
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * or http://www.opensolaris.org/os/licensing.
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * See the License for the specific language governing permissions
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * and limitations under the License.
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim *
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * When distributing Covered Code, include this CDDL HEADER in each
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * If applicable, add the following below this CDDL HEADER, with the
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * fields enclosed by brackets "[]" replaced with your own identifying
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * information: Portions Copyright [yyyy] [name of copyright owner]
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim *
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * CDDL HEADER END
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim */
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim/*
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim */
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <sys/types.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <sys/stat.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <sys/scsi/scsi_address.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <sys/scsi/impl/usmp.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <sys/libdevid.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <unistd.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <fcntl.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <errno.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <string.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <strings.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <stdio.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <limits.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <scsi/libsmp.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <scsi/libsmp_plugin.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim#include <libdevinfo.h>
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimstruct usmp_dev {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim int ud_fd;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim char *ud_dev;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim uint64_t ud_addr;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim};
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimstruct di_walk_arg {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim dev_t dev;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim uint64_t addr;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim};
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimstatic int
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimdi_walk(di_node_t node, di_minor_t minor, void *arg)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim{
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim struct di_walk_arg *wp = arg;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim char *wwn;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (di_minor_spectype(minor) != S_IFCHR)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (DI_WALK_CONTINUE);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (di_minor_devt(minor) == wp->dev) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim SCSI_ADDR_PROP_TARGET_PORT, &wwn) != 1 &&
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim di_prop_lookup_strings(DDI_DEV_T_ANY, node,
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim "smp-wwn", &wwn) != 1)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (DI_WALK_CONTINUE);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (scsi_wwnstr_to_wwn(wwn, &wp->addr) != DDI_SUCCESS)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (DI_WALK_CONTINUE);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (DI_WALK_TERMINATE);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim }
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (DI_WALK_CONTINUE);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim}
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimstatic void *
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimusmp_open(const void *target)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim{
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim struct usmp_dev *dp;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim const char *target_name = (const char *)target;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim struct stat64 st;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim di_node_t root, smp;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim struct di_walk_arg walk;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if ((dp = smp_zalloc(sizeof (struct usmp_dev))) == NULL)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (NULL);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if ((dp->ud_dev = smp_strdup(target_name)) == NULL) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim smp_free(dp);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (NULL);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim }
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if ((dp->ud_fd = open(target_name, O_RDONLY)) < 0) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim (void) smp_error(ESMP_BADTARGET,
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim "failed to open %s for reading: %s",
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim target_name, strerror(errno));
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim smp_free(dp->ud_dev);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim smp_free(dp);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (NULL);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim }
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (fstat64(dp->ud_fd, &st) != 0) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim (void) smp_error(ESMP_BADTARGET,
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim "failed to stat %s: %s", target_name, strerror(errno));
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim (void) close(dp->ud_fd);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim smp_free(dp->ud_dev);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim smp_free(dp);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (NULL);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim }
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if ((root = di_init("/", DINFOCACHE)) != DI_NODE_NIL) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim for (smp = di_drv_first_node("smp", root); smp != DI_NODE_NIL;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim smp = di_drv_next_node(smp)) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim bzero(&walk, sizeof (walk));
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim walk.dev = st.st_rdev;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim (void) di_walk_minor(smp, NULL, 0, &walk, di_walk);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (walk.addr != 0) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim dp->ud_addr = walk.addr;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim break;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim }
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim }
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim di_fini(root);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim }
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (dp);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim}
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimstatic void
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimusmp_close(void *private)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim{
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim struct usmp_dev *dp = (struct usmp_dev *)private;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (dp == NULL)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (dp->ud_fd > 0)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim (void) close(dp->ud_fd);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim smp_free(dp->ud_dev);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim smp_free(dp);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim}
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimstatic int
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimusmp_exec(void *private, smp_action_t *ap)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim{
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim struct usmp_dev *dp = (struct usmp_dev *)private;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim struct usmp_cmd cmd;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim void *req, *resp;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim size_t reqlen, resplen;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim bzero(&cmd, sizeof (cmd));
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim smp_action_get_request_frame(ap, &req, &reqlen);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim smp_action_get_response_frame(ap, &resp, &resplen);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim ASSERT(req != NULL);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim ASSERT(resp != NULL);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim ASSERT(reqlen != 0);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim ASSERT(resplen != 0);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim cmd.usmp_req = req;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim cmd.usmp_reqsize = reqlen;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim cmd.usmp_rsp = resp;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim cmd.usmp_rspsize = resplen;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim cmd.usmp_timeout = (int)smp_action_get_timeout(ap);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (ioctl(dp->ud_fd, USMPFUNC, &cmd) < 0) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim ASSERT(errno != EFAULT);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim switch (errno) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim case EINVAL:
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (smp_error(ESMP_BADFUNC, "internal usmp error"));
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim case EPERM:
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (smp_error(ESMP_PERM,
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim "insufficient privileges"));
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim case EIO:
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (smp_error(ESMP_IO, "I/O error"));
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim default:
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (smp_error(ESMP_SYS, "usmp ioctl failed: %s",
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim strerror(errno)));
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim }
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim }
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim /*
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * There is no way to determine the amount of data actually transferred
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * so we will just place the upper bound at the allocated size.
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim */
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim smp_action_set_response_len(ap, resplen);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (0);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim}
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimstatic void
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimusmp_target_name(void *private, char *buf, size_t len)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim{
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim struct usmp_dev *dp = (struct usmp_dev *)private;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim (void) strlcpy(buf, dp->ud_dev, len);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim}
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimstatic uint64_t
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimusmp_target_addr(void *private)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim{
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim struct usmp_dev *dp = (struct usmp_dev *)private;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (dp->ud_addr);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim}
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimstatic const smp_engine_ops_t usmp_ops = {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim .seo_open = usmp_open,
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim .seo_close = usmp_close,
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim .seo_exec = usmp_exec,
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim .seo_target_name = usmp_target_name,
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim .seo_target_addr = usmp_target_addr
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim};
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kimint
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim_smp_init(smp_engine_t *ep)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim{
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim smp_engine_config_t config = {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim .sec_name = "usmp",
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim .sec_ops = &usmp_ops
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim };
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (smp_engine_register(ep, LIBSMP_ENGINE_VERSION, &config));
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim}