936b7af69172dce89b577831f79c0e18d15e854bjw * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
936b7af69172dce89b577831f79c0e18d15e854bjw * See the License for the specific language governing permissions
936b7af69172dce89b577831f79c0e18d15e854bjw * and limitations under the License.
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 * CDDL HEADER END
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
936b7af69172dce89b577831f79c0e18d15e854bjw * Use is subject to license terms.
936b7af69172dce89b577831f79c0e18d15e854bjw * SMP - Serial Management Protocol Device Driver
936b7af69172dce89b577831f79c0e18d15e854bjw * The SMP driver provides user programs access to SAS Serial Management
936b7af69172dce89b577831f79c0e18d15e854bjw * Protocol devices by providing ioctl interface.
936b7af69172dce89b577831f79c0e18d15e854bjw * Standard entrypoints
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int smp_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
936b7af69172dce89b577831f79c0e18d15e854bjw * Configuration routines
936b7af69172dce89b577831f79c0e18d15e854bjw * Command handle routing
936b7af69172dce89b577831f79c0e18d15e854bjwstatic int smp_handle_func(dev_t, intptr_t, int, cred_t *, int *);
936b7af69172dce89b577831f79c0e18d15e854bjwstatic void smp_log(smp_state_t *, int, const char *, ...);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int smp_retry_recovered = 0; /* retry recovery counter */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int smp_retry_failed = 0; /* retry failed counter */
936b7af69172dce89b577831f79c0e18d15e854bjw 0, /* streamtab */
936b7af69172dce89b577831f79c0e18d15e854bjw 0, /* refcnt */
193974072f41a843678abf5f61979c748687e66bSherry Moore &mod_driverops, "smp device driver", &smp_dev_ops
936b7af69172dce89b577831f79c0e18d15e854bjw * smp_attach()
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * attach(9e) entrypoint.
936b7af69172dce89b577831f79c0e18d15e854bjw switch (cmd) {
936b7af69172dce89b577831f79c0e18d15e854bjw "device unit-address @%s failed",
936b7af69172dce89b577831f79c0e18d15e854bjw * smp_do_attach()
936b7af69172dce89b577831f79c0e18d15e854bjw * handle the nitty details of attach.
936b7af69172dce89b577831f79c0e18d15e854bjw DTRACE_PROBE2(smp__attach__detach, int, instance, char *,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne /* make sure device is there, and establish srmir identity property */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne "!smp_do_attach: failed smp_probe, "
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne "device unit-address @%s", ddi_get_name_addr(dip));
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 SMP_PROP_REPORT_MANUFACTURER, &srmir, &srmirlen);
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 /* register the devid */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne /* We don't need the devid for our own operation, so free now. */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne /* we are now done with srmir identity property defined by smp_probe */
936b7af69172dce89b577831f79c0e18d15e854bjw if (ddi_soft_state_zalloc(smp_soft_state, instance) != DDI_SUCCESS) {
936b7af69172dce89b577831f79c0e18d15e854bjw "!smp_do_attach: failed to allocate softstate, "
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state = ddi_get_soft_state(smp_soft_state, instance);
936b7af69172dce89b577831f79c0e18d15e854bjw * For simplicity, the minor number == the instance number
936b7af69172dce89b577831f79c0e18d15e854bjw "!smp_do_attach: minor node creation failed, "
936b7af69172dce89b577831f79c0e18d15e854bjw mutex_init(&smp_state->smp_mutex, NULL, MUTEX_DRIVER, NULL);
936b7af69172dce89b577831f79c0e18d15e854bjw * smp_detach()
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * detach(9E) entrypoint
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state = ddi_get_soft_state(smp_soft_state, instance);
936b7af69172dce89b577831f79c0e18d15e854bjw "!smp_detach: failed, no softstate found (%d), "
936b7af69172dce89b577831f79c0e18d15e854bjw "device unit-address @%s",
936b7af69172dce89b577831f79c0e18d15e854bjw switch (cmd) {
936b7af69172dce89b577831f79c0e18d15e854bjw * smp_do_detach()
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * detach the driver, tearing down resources.
936b7af69172dce89b577831f79c0e18d15e854bjw smp_state = ddi_get_soft_state(smp_soft_state, instance);
936b7af69172dce89b577831f79c0e18d15e854bjw DTRACE_PROBE2(smp__attach__detach, int, instance, char *,
936b7af69172dce89b577831f79c0e18d15e854bjw/*ARGSUSED*/
936b7af69172dce89b577831f79c0e18d15e854bjwsmp_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
936b7af69172dce89b577831f79c0e18d15e854bjw if ((smp_state = ddi_get_soft_state(smp_soft_state, instance))
936b7af69172dce89b577831f79c0e18d15e854bjw return (rv);
936b7af69172dce89b577831f79c0e18d15e854bjw/*ARGSUSED*/
936b7af69172dce89b577831f79c0e18d15e854bjw if ((smp_state = ddi_get_soft_state(smp_soft_state, instance))
8eadeb3489ef8b23c9940c162fade966feeaa2d0ml smp_log(smp_state, CE_NOTE, "!smp device is already in close");
936b7af69172dce89b577831f79c0e18d15e854bjw return (rv);
936b7af69172dce89b577831f79c0e18d15e854bjw/*ARGSUSED*/
936b7af69172dce89b577831f79c0e18d15e854bjw usmp_cmd32_t usmp_cmd32_data, *usmp_cmd32 = &usmp_cmd32_data;
936b7af69172dce89b577831f79c0e18d15e854bjw /* require PRIV_SYS_DEVICES privilege */
936b7af69172dce89b577831f79c0e18d15e854bjw if ((smp_state = ddi_get_soft_state(smp_soft_state, instance))
936b7af69172dce89b577831f79c0e18d15e854bjw if (ddi_copyin((void *)arg, usmp_cmd32, sizeof (usmp_cmd32_t),
936b7af69172dce89b577831f79c0e18d15e854bjw if (ddi_copyin((void *)arg, usmp_cmd, sizeof (usmp_cmd_t),
936b7af69172dce89b577831f79c0e18d15e854bjw#else /* ! _MULTI_DATAMODEL */
936b7af69172dce89b577831f79c0e18d15e854bjw if (ddi_copyin((void *)arg, usmp_cmd, sizeof (usmp_cmd_t), flag)) {
936b7af69172dce89b577831f79c0e18d15e854bjw#endif /* _MULTI_DATAMODEL */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reqsize = usmp_cmd->usmp_reqsize;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_rspsize = usmp_cmd->usmp_rspsize;
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,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_rsp = kmem_zalloc((size_t)usmp_cmd->usmp_rspsize,
936b7af69172dce89b577831f79c0e18d15e854bjw /* copy smp request frame to kernel space */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne if (ddi_copyin(usmp_cmd->usmp_req, smp_pkt->smp_pkt_req,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne DTRACE_PROBE1(smp__transport__start, caddr_t, smp_pkt->smp_pkt_req);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_address = &smp_state->smp_sd->smp_sd_address;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_timeout = usmp_cmd->usmp_timeout;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne /* call smp_transport entry and send smp_pkt to HBA driver */
936b7af69172dce89b577831f79c0e18d15e854bjw for (retrycount = 0; retrycount <= smp_retry_times; retrycount++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * To improve transport reliability, only allow one command
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne * outstanding at a time in smp_transport().
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * NOTE: Some expanders have issues with heavy smp load.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Let the transport know if more retries are possible. */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne rval = smp_transport(smp_pkt); /* put on the wire */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne "!smp_transport failed, smp_pkt_reason %d",
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne "!smp_transport failed, smp_pkt_reason %d",
936b7af69172dce89b577831f79c0e18d15e854bjw /* copy out smp response to user process */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne if (ddi_copyout(smp_pkt->smp_pkt_rsp, usmp_cmd->usmp_rsp,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_rsp, uchar_t, smp_pkt->smp_pkt_reason);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne kmem_free(smp_pkt->smp_pkt_req, smp_pkt->smp_pkt_reqsize);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne kmem_free(smp_pkt->smp_pkt_rsp, smp_pkt->smp_pkt_rspsize);
936b7af69172dce89b577831f79c0e18d15e854bjw/*ARGSUSED*/
936b7af69172dce89b577831f79c0e18d15e854bjw int cmd, intptr_t arg, int flag, cred_t *cred_p, int *rval_p)
936b7af69172dce89b577831f79c0e18d15e854bjw switch (cmd) {
936b7af69172dce89b577831f79c0e18d15e854bjw * The response payload is valid only if return value is 0
936b7af69172dce89b577831f79c0e18d15e854bjw * or EOVERFLOW.
936b7af69172dce89b577831f79c0e18d15e854bjwstatic void
936b7af69172dce89b577831f79c0e18d15e854bjwsmp_log(smp_state_t *smp_state, int level, const char *fmt, ...)