936b7af69172dce89b577831f79c0e18d15e854bjw/*
936b7af69172dce89b577831f79c0e18d15e854bjw * CDDL HEADER START
936b7af69172dce89b577831f79c0e18d15e854bjw *
936b7af69172dce89b577831f79c0e18d15e854bjw * The contents of this file are subject to the terms of the
936b7af69172dce89b577831f79c0e18d15e854bjw * Common Development and Distribution License (the "License").
936b7af69172dce89b577831f79c0e18d15e854bjw * You may not use this file except in compliance with the License.
936b7af69172dce89b577831f79c0e18d15e854bjw *
936b7af69172dce89b577831f79c0e18d15e854bjw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
936b7af69172dce89b577831f79c0e18d15e854bjw * or http://www.opensolaris.org/os/licensing.
936b7af69172dce89b577831f79c0e18d15e854bjw * See the License for the specific language governing permissions
936b7af69172dce89b577831f79c0e18d15e854bjw * and limitations under the License.
936b7af69172dce89b577831f79c0e18d15e854bjw *
936b7af69172dce89b577831f79c0e18d15e854bjw * When distributing Covered Code, include this CDDL HEADER in each
936b7af69172dce89b577831f79c0e18d15e854bjw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
936b7af69172dce89b577831f79c0e18d15e854bjw * If applicable, add the following below this CDDL HEADER, with the
936b7af69172dce89b577831f79c0e18d15e854bjw * fields enclosed by brackets "[]" replaced with your own identifying
936b7af69172dce89b577831f79c0e18d15e854bjw * information: Portions Copyright [yyyy] [name of copyright owner]
936b7af69172dce89b577831f79c0e18d15e854bjw *
936b7af69172dce89b577831f79c0e18d15e854bjw * CDDL HEADER END
936b7af69172dce89b577831f79c0e18d15e854bjw */
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
936b7af69172dce89b577831f79c0e18d15e854bjw * Use is subject to license terms.
936b7af69172dce89b577831f79c0e18d15e854bjw */
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*
936b7af69172dce89b577831f79c0e18d15e854bjw * SMP - Serial Management Protocol Device Driver
936b7af69172dce89b577831f79c0e18d15e854bjw *
936b7af69172dce89b577831f79c0e18d15e854bjw * The SMP driver provides user programs access to SAS Serial Management
936b7af69172dce89b577831f79c0e18d15e854bjw * Protocol devices by providing ioctl interface.
936b7af69172dce89b577831f79c0e18d15e854bjw */
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw#include <sys/modctl.h>
936b7af69172dce89b577831f79c0e18d15e854bjw#include <sys/file.h>
936b7af69172dce89b577831f79c0e18d15e854bjw#include <sys/scsi/scsi.h>
936b7af69172dce89b577831f79c0e18d15e854bjw#include <sys/scsi/targets/smp.h>
936b7af69172dce89b577831f79c0e18d15e854bjw#include <sys/sdt.h>
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*
936b7af69172dce89b577831f79c0e18d15e854bjw * Standard entrypoints
936b7af69172dce89b577831f79c0e18d15e854bjw */
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int smp_attach(dev_info_t *, ddi_attach_cmd_t);
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int smp_detach(dev_info_t *, ddi_detach_cmd_t);
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int smp_open(dev_t *, int, int, cred_t *);
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int smp_close(dev_t, int, int, cred_t *);
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int smp_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*
936b7af69172dce89b577831f79c0e18d15e854bjw * Configuration routines
936b7af69172dce89b577831f79c0e18d15e854bjw */
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int smp_do_attach(dev_info_t *);
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int smp_do_detach(dev_info_t *);
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*
936b7af69172dce89b577831f79c0e18d15e854bjw * Command handle routing
936b7af69172dce89b577831f79c0e18d15e854bjw */
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int smp_handle_func(dev_t, intptr_t, int, cred_t *, int *);
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*
936b7af69172dce89b577831f79c0e18d15e854bjw * Logging/debugging routines
936b7af69172dce89b577831f79c0e18d15e854bjw */
936b7af69172dce89b577831f79c0e18d15e854bjwstatic void smp_log(smp_state_t *, int, const char *, ...);
936b7af69172dce89b577831f79c0e18d15e854bjw
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint smp_retry_times = SMP_DEFAULT_RETRY_TIMES;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint smp_retry_delay = 10000; /* 10msec */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint smp_delay_cmd = 1; /* 1usec */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint smp_single_command = 1; /* one command at a time */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int smp_retry_recovered = 0; /* retry recovery counter */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int smp_retry_failed = 0; /* retry failed counter */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int smp_failed = 0;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjwstatic struct cb_ops smp_cb_ops = {
936b7af69172dce89b577831f79c0e18d15e854bjw smp_open, /* open */
936b7af69172dce89b577831f79c0e18d15e854bjw smp_close, /* close */
936b7af69172dce89b577831f79c0e18d15e854bjw nodev, /* strategy */
936b7af69172dce89b577831f79c0e18d15e854bjw nodev, /* print */
936b7af69172dce89b577831f79c0e18d15e854bjw nodev, /* dump */
936b7af69172dce89b577831f79c0e18d15e854bjw nodev, /* read */
936b7af69172dce89b577831f79c0e18d15e854bjw nodev, /* write */
936b7af69172dce89b577831f79c0e18d15e854bjw smp_ioctl, /* ioctl */
936b7af69172dce89b577831f79c0e18d15e854bjw nodev, /* devmap */
936b7af69172dce89b577831f79c0e18d15e854bjw nodev, /* mmap */
936b7af69172dce89b577831f79c0e18d15e854bjw nodev, /* segmap */
936b7af69172dce89b577831f79c0e18d15e854bjw nochpoll, /* poll */
936b7af69172dce89b577831f79c0e18d15e854bjw ddi_prop_op, /* cb_prop_op */
936b7af69172dce89b577831f79c0e18d15e854bjw 0, /* streamtab */
936b7af69172dce89b577831f79c0e18d15e854bjw D_MP | D_NEW | D_HOTPLUG /* Driver compatibility flag */
936b7af69172dce89b577831f79c0e18d15e854bjw};
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjwstatic struct dev_ops smp_dev_ops = {
936b7af69172dce89b577831f79c0e18d15e854bjw DEVO_REV, /* devo_rev, */
936b7af69172dce89b577831f79c0e18d15e854bjw 0, /* refcnt */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne ddi_getinfo_1to1, /* info */
936b7af69172dce89b577831f79c0e18d15e854bjw nulldev, /* identify */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne NULL, /* probe */
936b7af69172dce89b577831f79c0e18d15e854bjw smp_attach, /* attach */
936b7af69172dce89b577831f79c0e18d15e854bjw smp_detach, /* detach */
936b7af69172dce89b577831f79c0e18d15e854bjw nodev, /* reset */
936b7af69172dce89b577831f79c0e18d15e854bjw &smp_cb_ops, /* driver operations */
936b7af69172dce89b577831f79c0e18d15e854bjw (struct bus_ops *)0, /* bus operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore NULL, /* power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_needed, /* quiesce */
936b7af69172dce89b577831f79c0e18d15e854bjw};
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjwstatic void *smp_soft_state = NULL;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjwstatic struct modldrv modldrv = {
193974072f41a843678abf5f61979c748687e66bSherry Moore &mod_driverops, "smp device driver", &smp_dev_ops
936b7af69172dce89b577831f79c0e18d15e854bjw};
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjwstatic struct modlinkage modlinkage = {
936b7af69172dce89b577831f79c0e18d15e854bjw MODREV_1, &modldrv, NULL
936b7af69172dce89b577831f79c0e18d15e854bjw};
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjwint
936b7af69172dce89b577831f79c0e18d15e854bjw_init(void)
936b7af69172dce89b577831f79c0e18d15e854bjw{
936b7af69172dce89b577831f79c0e18d15e854bjw int err;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw if ((err = ddi_soft_state_init(&smp_soft_state,
936b7af69172dce89b577831f79c0e18d15e854bjw sizeof (smp_state_t), SMP_ESTIMATED_NUM_DEVS)) != 0) {
936b7af69172dce89b577831f79c0e18d15e854bjw return (err);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw if ((err = mod_install(&modlinkage)) != 0) {
936b7af69172dce89b577831f79c0e18d15e854bjw ddi_soft_state_fini(&smp_soft_state);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw return (err);
936b7af69172dce89b577831f79c0e18d15e854bjw}
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjwint
936b7af69172dce89b577831f79c0e18d15e854bjw_fini(void)
936b7af69172dce89b577831f79c0e18d15e854bjw{
936b7af69172dce89b577831f79c0e18d15e854bjw int err;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw if ((err = mod_remove(&modlinkage)) == 0) {
936b7af69172dce89b577831f79c0e18d15e854bjw ddi_soft_state_fini(&smp_soft_state);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw return (err);
936b7af69172dce89b577831f79c0e18d15e854bjw}
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjwint
936b7af69172dce89b577831f79c0e18d15e854bjw_info(struct modinfo *modinfop)
936b7af69172dce89b577831f79c0e18d15e854bjw{
936b7af69172dce89b577831f79c0e18d15e854bjw return (mod_info(&modlinkage, modinfop));
936b7af69172dce89b577831f79c0e18d15e854bjw}
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*
936b7af69172dce89b577831f79c0e18d15e854bjw * smp_attach()
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * attach(9e) entrypoint.
936b7af69172dce89b577831f79c0e18d15e854bjw */
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int
936b7af69172dce89b577831f79c0e18d15e854bjwsmp_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
936b7af69172dce89b577831f79c0e18d15e854bjw{
936b7af69172dce89b577831f79c0e18d15e854bjw int err;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw switch (cmd) {
936b7af69172dce89b577831f79c0e18d15e854bjw case DDI_ATTACH:
936b7af69172dce89b577831f79c0e18d15e854bjw err = smp_do_attach(dip);
936b7af69172dce89b577831f79c0e18d15e854bjw break;
936b7af69172dce89b577831f79c0e18d15e854bjw case DDI_RESUME:
936b7af69172dce89b577831f79c0e18d15e854bjw err = DDI_SUCCESS;
936b7af69172dce89b577831f79c0e18d15e854bjw break;
936b7af69172dce89b577831f79c0e18d15e854bjw default:
936b7af69172dce89b577831f79c0e18d15e854bjw err = DDI_FAILURE;
936b7af69172dce89b577831f79c0e18d15e854bjw break;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw if (err != DDI_SUCCESS) {
936b7af69172dce89b577831f79c0e18d15e854bjw smp_log(NULL, CE_NOTE, "!smp_attach(), "
936b7af69172dce89b577831f79c0e18d15e854bjw "device unit-address @%s failed",
936b7af69172dce89b577831f79c0e18d15e854bjw ddi_get_name_addr(dip));
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw return (err);
936b7af69172dce89b577831f79c0e18d15e854bjw}
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*
936b7af69172dce89b577831f79c0e18d15e854bjw * smp_do_attach()
936b7af69172dce89b577831f79c0e18d15e854bjw * handle the nitty details of attach.
936b7af69172dce89b577831f79c0e18d15e854bjw */
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int
936b7af69172dce89b577831f79c0e18d15e854bjwsmp_do_attach(dev_info_t *dip)
936b7af69172dce89b577831f79c0e18d15e854bjw{
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne int instance;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne struct smp_device *smp_sd;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne uchar_t *srmir = NULL;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne uint_t srmirlen = 0;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne ddi_devid_t devid = NULL;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_state_t *smp_state;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw instance = ddi_get_instance(dip);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_sd = ddi_get_driver_private(dip);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne ASSERT(smp_sd != NULL);
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw DTRACE_PROBE2(smp__attach__detach, int, instance, char *,
936b7af69172dce89b577831f79c0e18d15e854bjw ddi_get_name_addr(dip));
936b7af69172dce89b577831f79c0e18d15e854bjw
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne /* make sure device is there, and establish srmir identity property */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne if (smp_probe(smp_sd) != DDI_PROBE_SUCCESS) {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_log(NULL, CE_NOTE,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne "!smp_do_attach: failed smp_probe, "
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne "device unit-address @%s", ddi_get_name_addr(dip));
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne return (DDI_FAILURE);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne }
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne /* if we have not already registered a devid, then do so now */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne if (ddi_devid_get(dip, &devid) != DDI_SUCCESS) {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne /* get the srmir identity information for use in devid */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne (void) ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne SMP_PROP_REPORT_MANUFACTURER, &srmir, &srmirlen);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne /* Convert smp unit-address and srmir into devid */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne if (ddi_devid_smp_encode(DEVID_SMP_ENCODE_VERSION_LATEST,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne (char *)ddi_driver_name(dip), ddi_get_name_addr(dip),
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne srmir, srmirlen, &devid) == DDI_SUCCESS) {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne /* register the devid */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne (void) ddi_devid_register(dip, devid);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne }
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne ddi_prop_free(srmir);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne }
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne /* We don't need the devid for our own operation, so free now. */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne if (devid)
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne ddi_devid_free(devid);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne /* we are now done with srmir identity property defined by smp_probe */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne (void) ndi_prop_remove(DDI_DEV_T_NONE,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne dip, SMP_PROP_REPORT_MANUFACTURER);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne
936b7af69172dce89b577831f79c0e18d15e854bjw if (ddi_soft_state_zalloc(smp_soft_state, instance) != DDI_SUCCESS) {
936b7af69172dce89b577831f79c0e18d15e854bjw smp_log(NULL, CE_NOTE,
936b7af69172dce89b577831f79c0e18d15e854bjw "!smp_do_attach: failed to allocate softstate, "
936b7af69172dce89b577831f79c0e18d15e854bjw "device unit-address @%s", ddi_get_name_addr(dip));
936b7af69172dce89b577831f79c0e18d15e854bjw return (DDI_FAILURE);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state = ddi_get_soft_state(smp_soft_state, instance);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_state->smp_sd = smp_sd;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw /*
936b7af69172dce89b577831f79c0e18d15e854bjw * For simplicity, the minor number == the instance number
936b7af69172dce89b577831f79c0e18d15e854bjw */
936b7af69172dce89b577831f79c0e18d15e854bjw if (ddi_create_minor_node(dip, "smp", S_IFCHR,
936b7af69172dce89b577831f79c0e18d15e854bjw instance, DDI_NT_SMP, NULL) == DDI_FAILURE) {
936b7af69172dce89b577831f79c0e18d15e854bjw smp_log(smp_state, CE_NOTE,
936b7af69172dce89b577831f79c0e18d15e854bjw "!smp_do_attach: minor node creation failed, "
936b7af69172dce89b577831f79c0e18d15e854bjw "device unit-address @%s", ddi_get_name_addr(dip));
936b7af69172dce89b577831f79c0e18d15e854bjw ddi_soft_state_free(smp_soft_state, instance);
936b7af69172dce89b577831f79c0e18d15e854bjw return (DDI_FAILURE);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw mutex_init(&smp_state->smp_mutex, NULL, MUTEX_DRIVER, NULL);
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state->smp_open_flag = SMP_CLOSED;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw ddi_report_dev(dip);
936b7af69172dce89b577831f79c0e18d15e854bjw return (DDI_SUCCESS);
936b7af69172dce89b577831f79c0e18d15e854bjw}
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*
936b7af69172dce89b577831f79c0e18d15e854bjw * smp_detach()
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * detach(9E) entrypoint
936b7af69172dce89b577831f79c0e18d15e854bjw */
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int
936b7af69172dce89b577831f79c0e18d15e854bjwsmp_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
936b7af69172dce89b577831f79c0e18d15e854bjw{
936b7af69172dce89b577831f79c0e18d15e854bjw int instance;
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state_t *smp_state;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw instance = ddi_get_instance(dip);
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state = ddi_get_soft_state(smp_soft_state, instance);
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw if (smp_state == NULL) {
936b7af69172dce89b577831f79c0e18d15e854bjw smp_log(NULL, CE_NOTE,
936b7af69172dce89b577831f79c0e18d15e854bjw "!smp_detach: failed, no softstate found (%d), "
936b7af69172dce89b577831f79c0e18d15e854bjw "device unit-address @%s",
936b7af69172dce89b577831f79c0e18d15e854bjw instance, ddi_get_name_addr(dip));
936b7af69172dce89b577831f79c0e18d15e854bjw return (DDI_FAILURE);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw switch (cmd) {
936b7af69172dce89b577831f79c0e18d15e854bjw case DDI_DETACH:
936b7af69172dce89b577831f79c0e18d15e854bjw return (smp_do_detach(dip));
936b7af69172dce89b577831f79c0e18d15e854bjw case DDI_SUSPEND:
936b7af69172dce89b577831f79c0e18d15e854bjw return (DDI_SUCCESS);
936b7af69172dce89b577831f79c0e18d15e854bjw default:
936b7af69172dce89b577831f79c0e18d15e854bjw return (DDI_FAILURE);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw}
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*
936b7af69172dce89b577831f79c0e18d15e854bjw * smp_do_detach()
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * detach the driver, tearing down resources.
936b7af69172dce89b577831f79c0e18d15e854bjw */
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int
936b7af69172dce89b577831f79c0e18d15e854bjwsmp_do_detach(dev_info_t *dip)
936b7af69172dce89b577831f79c0e18d15e854bjw{
936b7af69172dce89b577831f79c0e18d15e854bjw int instance;
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state_t *smp_state;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw instance = ddi_get_instance(dip);
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state = ddi_get_soft_state(smp_soft_state, instance);
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw DTRACE_PROBE2(smp__attach__detach, int, instance, char *,
936b7af69172dce89b577831f79c0e18d15e854bjw ddi_get_name_addr(dip));
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw mutex_destroy(&smp_state->smp_mutex);
936b7af69172dce89b577831f79c0e18d15e854bjw ddi_soft_state_free(smp_soft_state, instance);
936b7af69172dce89b577831f79c0e18d15e854bjw ddi_remove_minor_node(dip, NULL);
936b7af69172dce89b577831f79c0e18d15e854bjw return (DDI_SUCCESS);
936b7af69172dce89b577831f79c0e18d15e854bjw}
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*ARGSUSED*/
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int
936b7af69172dce89b577831f79c0e18d15e854bjwsmp_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
936b7af69172dce89b577831f79c0e18d15e854bjw{
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state_t *smp_state;
936b7af69172dce89b577831f79c0e18d15e854bjw int instance;
936b7af69172dce89b577831f79c0e18d15e854bjw int rv = 0;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw instance = getminor(*dev_p);
936b7af69172dce89b577831f79c0e18d15e854bjw if ((smp_state = ddi_get_soft_state(smp_soft_state, instance))
936b7af69172dce89b577831f79c0e18d15e854bjw == NULL) {
936b7af69172dce89b577831f79c0e18d15e854bjw return (ENXIO);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw mutex_enter(&smp_state->smp_mutex);
936b7af69172dce89b577831f79c0e18d15e854bjw if (flag & FEXCL) {
936b7af69172dce89b577831f79c0e18d15e854bjw if (smp_state->smp_open_flag != SMP_CLOSED) {
936b7af69172dce89b577831f79c0e18d15e854bjw rv = EBUSY;
936b7af69172dce89b577831f79c0e18d15e854bjw } else {
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state->smp_open_flag = SMP_EXOPENED;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw } else {
936b7af69172dce89b577831f79c0e18d15e854bjw if (smp_state->smp_open_flag == SMP_EXOPENED) {
936b7af69172dce89b577831f79c0e18d15e854bjw rv = EBUSY;
936b7af69172dce89b577831f79c0e18d15e854bjw } else {
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state->smp_open_flag = SMP_SOPENED;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw mutex_exit(&smp_state->smp_mutex);
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw return (rv);
936b7af69172dce89b577831f79c0e18d15e854bjw}
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*ARGSUSED*/
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int
936b7af69172dce89b577831f79c0e18d15e854bjwsmp_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
936b7af69172dce89b577831f79c0e18d15e854bjw{
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state_t *smp_state;
936b7af69172dce89b577831f79c0e18d15e854bjw int instance;
936b7af69172dce89b577831f79c0e18d15e854bjw int rv = 0;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw instance = getminor(dev);
936b7af69172dce89b577831f79c0e18d15e854bjw if ((smp_state = ddi_get_soft_state(smp_soft_state, instance))
936b7af69172dce89b577831f79c0e18d15e854bjw == NULL) {
936b7af69172dce89b577831f79c0e18d15e854bjw return (ENXIO);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw mutex_enter(&smp_state->smp_mutex);
8eadeb3489ef8b23c9940c162fade966feeaa2d0ml if (smp_state->smp_open_flag == SMP_CLOSED) {
8eadeb3489ef8b23c9940c162fade966feeaa2d0ml smp_log(smp_state, CE_NOTE, "!smp device is already in close");
8eadeb3489ef8b23c9940c162fade966feeaa2d0ml } else {
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state->smp_open_flag = SMP_CLOSED;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw mutex_exit(&smp_state->smp_mutex);
936b7af69172dce89b577831f79c0e18d15e854bjw return (rv);
936b7af69172dce89b577831f79c0e18d15e854bjw}
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*ARGSUSED*/
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int
936b7af69172dce89b577831f79c0e18d15e854bjwsmp_handle_func(dev_t dev,
936b7af69172dce89b577831f79c0e18d15e854bjw intptr_t arg, int flag, cred_t *cred_p, int *rval_p)
936b7af69172dce89b577831f79c0e18d15e854bjw{
936b7af69172dce89b577831f79c0e18d15e854bjw usmp_cmd_t usmp_cmd_data, *usmp_cmd = &usmp_cmd_data;
936b7af69172dce89b577831f79c0e18d15e854bjw smp_pkt_t smp_pkt_data, *smp_pkt = &smp_pkt_data;
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state_t *smp_state;
936b7af69172dce89b577831f79c0e18d15e854bjw int instance, retrycount;
936b7af69172dce89b577831f79c0e18d15e854bjw cred_t *cr;
936b7af69172dce89b577831f79c0e18d15e854bjw uint64_t cmd_flags = 0;
936b7af69172dce89b577831f79c0e18d15e854bjw int rval = 0;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw#ifdef _MULTI_DATAMODEL
936b7af69172dce89b577831f79c0e18d15e854bjw usmp_cmd32_t usmp_cmd32_data, *usmp_cmd32 = &usmp_cmd32_data;
936b7af69172dce89b577831f79c0e18d15e854bjw#endif
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw /* require PRIV_SYS_DEVICES privilege */
936b7af69172dce89b577831f79c0e18d15e854bjw cr = ddi_get_cred();
936b7af69172dce89b577831f79c0e18d15e854bjw if ((drv_priv(cred_p) != 0) && (drv_priv(cr) != 0)) {
936b7af69172dce89b577831f79c0e18d15e854bjw return (EPERM);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw bzero(smp_pkt, sizeof (smp_pkt_t));
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw instance = getminor(dev);
936b7af69172dce89b577831f79c0e18d15e854bjw if ((smp_state = ddi_get_soft_state(smp_soft_state, instance))
936b7af69172dce89b577831f79c0e18d15e854bjw == NULL) {
936b7af69172dce89b577831f79c0e18d15e854bjw return (ENXIO);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw#ifdef _MULTI_DATAMODEL
936b7af69172dce89b577831f79c0e18d15e854bjw switch (ddi_model_convert_from(flag & FMODELS)) {
936b7af69172dce89b577831f79c0e18d15e854bjw case DDI_MODEL_ILP32:
936b7af69172dce89b577831f79c0e18d15e854bjw if (ddi_copyin((void *)arg, usmp_cmd32, sizeof (usmp_cmd32_t),
936b7af69172dce89b577831f79c0e18d15e854bjw flag)) {
936b7af69172dce89b577831f79c0e18d15e854bjw return (EFAULT);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw usmp_cmd32tousmp_cmd(usmp_cmd32, usmp_cmd);
936b7af69172dce89b577831f79c0e18d15e854bjw break;
936b7af69172dce89b577831f79c0e18d15e854bjw case DDI_MODEL_NONE:
936b7af69172dce89b577831f79c0e18d15e854bjw if (ddi_copyin((void *)arg, usmp_cmd, sizeof (usmp_cmd_t),
936b7af69172dce89b577831f79c0e18d15e854bjw flag)) {
936b7af69172dce89b577831f79c0e18d15e854bjw return (EFAULT);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw break;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw#else /* ! _MULTI_DATAMODEL */
936b7af69172dce89b577831f79c0e18d15e854bjw if (ddi_copyin((void *)arg, usmp_cmd, sizeof (usmp_cmd_t), flag)) {
936b7af69172dce89b577831f79c0e18d15e854bjw return (EFAULT);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw#endif /* _MULTI_DATAMODEL */
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw if ((usmp_cmd->usmp_reqsize < SMP_MIN_REQUEST_SIZE) ||
936b7af69172dce89b577831f79c0e18d15e854bjw (usmp_cmd->usmp_reqsize > SMP_MAX_REQUEST_SIZE) ||
936b7af69172dce89b577831f79c0e18d15e854bjw (usmp_cmd->usmp_rspsize < SMP_MIN_RESPONSE_SIZE) ||
936b7af69172dce89b577831f79c0e18d15e854bjw (usmp_cmd->usmp_rspsize > SMP_MAX_RESPONSE_SIZE)) {
936b7af69172dce89b577831f79c0e18d15e854bjw rval = EINVAL;
936b7af69172dce89b577831f79c0e18d15e854bjw goto done;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reqsize = usmp_cmd->usmp_reqsize;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_rspsize = usmp_cmd->usmp_rspsize;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw /* allocate memory space for smp request and response frame in kernel */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_req = kmem_zalloc((size_t)usmp_cmd->usmp_reqsize,
936b7af69172dce89b577831f79c0e18d15e854bjw KM_SLEEP);
936b7af69172dce89b577831f79c0e18d15e854bjw cmd_flags |= SMP_FLAG_REQBUF;
936b7af69172dce89b577831f79c0e18d15e854bjw
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_rsp = kmem_zalloc((size_t)usmp_cmd->usmp_rspsize,
936b7af69172dce89b577831f79c0e18d15e854bjw KM_SLEEP);
936b7af69172dce89b577831f79c0e18d15e854bjw cmd_flags |= SMP_FLAG_RSPBUF;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw /* copy smp request frame to kernel space */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne if (ddi_copyin(usmp_cmd->usmp_req, smp_pkt->smp_pkt_req,
936b7af69172dce89b577831f79c0e18d15e854bjw (size_t)usmp_cmd->usmp_reqsize, flag) != 0) {
936b7af69172dce89b577831f79c0e18d15e854bjw rval = EFAULT;
936b7af69172dce89b577831f79c0e18d15e854bjw goto done;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne DTRACE_PROBE1(smp__transport__start, caddr_t, smp_pkt->smp_pkt_req);
936b7af69172dce89b577831f79c0e18d15e854bjw
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_address = &smp_state->smp_sd->smp_sd_address;
936b7af69172dce89b577831f79c0e18d15e854bjw if (usmp_cmd->usmp_timeout <= 0) {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_timeout = SMP_DEFAULT_TIMEOUT;
936b7af69172dce89b577831f79c0e18d15e854bjw } else {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_timeout = usmp_cmd->usmp_timeout;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne /* call smp_transport entry and send smp_pkt to HBA driver */
936b7af69172dce89b577831f79c0e18d15e854bjw cmd_flags |= SMP_FLAG_XFER;
936b7af69172dce89b577831f79c0e18d15e854bjw for (retrycount = 0; retrycount <= smp_retry_times; retrycount++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * To improve transport reliability, only allow one command
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne * outstanding at a time in smp_transport().
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * NOTE: Some expanders have issues with heavy smp load.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (smp_single_command) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&smp_state->smp_mutex);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (smp_state->smp_busy)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_wait(&smp_state->smp_cv,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &smp_state->smp_mutex);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh smp_state->smp_busy = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&smp_state->smp_mutex);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Let the transport know if more retries are possible. */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_will_retry =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (retrycount < smp_retry_times) ? 1 : 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason = 0;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne rval = smp_transport(smp_pkt); /* put on the wire */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (smp_delay_cmd)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh delay(drv_usectohz(smp_delay_cmd));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (smp_single_command) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&smp_state->smp_mutex);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh smp_state->smp_busy = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_signal(&smp_state->smp_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&smp_state->smp_mutex);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval == DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (retrycount)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh smp_retry_recovered++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = 0;
936b7af69172dce89b577831f79c0e18d15e854bjw break;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne switch (smp_pkt->smp_pkt_reason) {
936b7af69172dce89b577831f79c0e18d15e854bjw case EAGAIN:
936b7af69172dce89b577831f79c0e18d15e854bjw if (retrycount < smp_retry_times) {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne bzero(smp_pkt->smp_pkt_rsp,
936b7af69172dce89b577831f79c0e18d15e854bjw (size_t)usmp_cmd->usmp_rspsize);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (smp_retry_delay)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh delay(drv_usectohz(smp_retry_delay));
936b7af69172dce89b577831f79c0e18d15e854bjw continue;
936b7af69172dce89b577831f79c0e18d15e854bjw } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh smp_retry_failed++;
936b7af69172dce89b577831f79c0e18d15e854bjw smp_log(smp_state, CE_NOTE,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne "!smp_transport failed, smp_pkt_reason %d",
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne rval = smp_pkt->smp_pkt_reason;
936b7af69172dce89b577831f79c0e18d15e854bjw goto copyout;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw default:
936b7af69172dce89b577831f79c0e18d15e854bjw smp_log(smp_state, CE_NOTE,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne "!smp_transport failed, smp_pkt_reason %d",
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne rval = smp_pkt->smp_pkt_reason;
936b7af69172dce89b577831f79c0e18d15e854bjw goto copyout;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjwcopyout:
936b7af69172dce89b577831f79c0e18d15e854bjw /* copy out smp response to user process */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne if (ddi_copyout(smp_pkt->smp_pkt_rsp, usmp_cmd->usmp_rsp,
936b7af69172dce89b577831f79c0e18d15e854bjw (size_t)usmp_cmd->usmp_rspsize, flag) != 0) {
936b7af69172dce89b577831f79c0e18d15e854bjw rval = EFAULT;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjwdone:
936b7af69172dce89b577831f79c0e18d15e854bjw if ((cmd_flags & SMP_FLAG_XFER) != 0) {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne DTRACE_PROBE2(smp__transport__done, caddr_t,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_rsp, uchar_t, smp_pkt->smp_pkt_reason);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw if ((cmd_flags & SMP_FLAG_REQBUF) != 0) {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne kmem_free(smp_pkt->smp_pkt_req, smp_pkt->smp_pkt_reqsize);
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw if ((cmd_flags & SMP_FLAG_RSPBUF) != 0) {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne kmem_free(smp_pkt->smp_pkt_rsp, smp_pkt->smp_pkt_rspsize);
936b7af69172dce89b577831f79c0e18d15e854bjw }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh smp_failed++;
936b7af69172dce89b577831f79c0e18d15e854bjw return (rval);
936b7af69172dce89b577831f79c0e18d15e854bjw}
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw/*ARGSUSED*/
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int
936b7af69172dce89b577831f79c0e18d15e854bjwsmp_ioctl(dev_t dev,
936b7af69172dce89b577831f79c0e18d15e854bjw int cmd, intptr_t arg, int flag, cred_t *cred_p, int *rval_p)
936b7af69172dce89b577831f79c0e18d15e854bjw{
936b7af69172dce89b577831f79c0e18d15e854bjw int rval = 0;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw switch (cmd) {
936b7af69172dce89b577831f79c0e18d15e854bjw case USMPFUNC:
936b7af69172dce89b577831f79c0e18d15e854bjw /*
936b7af69172dce89b577831f79c0e18d15e854bjw * The response payload is valid only if return value is 0
936b7af69172dce89b577831f79c0e18d15e854bjw * or EOVERFLOW.
936b7af69172dce89b577831f79c0e18d15e854bjw */
936b7af69172dce89b577831f79c0e18d15e854bjw rval = smp_handle_func(dev, arg, flag, cred_p, rval_p);
936b7af69172dce89b577831f79c0e18d15e854bjw break;
936b7af69172dce89b577831f79c0e18d15e854bjw default:
936b7af69172dce89b577831f79c0e18d15e854bjw rval = EINVAL;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw return (rval);
936b7af69172dce89b577831f79c0e18d15e854bjw}
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjwstatic void
936b7af69172dce89b577831f79c0e18d15e854bjwsmp_log(smp_state_t *smp_state, int level, const char *fmt, ...)
936b7af69172dce89b577831f79c0e18d15e854bjw{
936b7af69172dce89b577831f79c0e18d15e854bjw va_list ap;
936b7af69172dce89b577831f79c0e18d15e854bjw char buf[256];
936b7af69172dce89b577831f79c0e18d15e854bjw dev_info_t *dip;
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw if (smp_state == (smp_state_t *)NULL) {
936b7af69172dce89b577831f79c0e18d15e854bjw dip = NULL;
936b7af69172dce89b577831f79c0e18d15e854bjw } else {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne dip = smp_state->smp_sd->smp_sd_dev;
936b7af69172dce89b577831f79c0e18d15e854bjw }
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw va_start(ap, fmt);
936b7af69172dce89b577831f79c0e18d15e854bjw (void) vsnprintf(buf, sizeof (buf), fmt, ap);
936b7af69172dce89b577831f79c0e18d15e854bjw va_end(ap);
936b7af69172dce89b577831f79c0e18d15e854bjw
936b7af69172dce89b577831f79c0e18d15e854bjw scsi_log(dip, "smp", level, "%s", buf);
936b7af69172dce89b577831f79c0e18d15e854bjw}