wrsm_cf.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Configuration layer of the WildCat RSM driver
*
* This file handles user interaction for the wrsm driver, including
* - receiving and parsing a configuration,
* - initiating controller configuration and reconfiguration,
* - keeping track of which wci devices and ncslices are owned by which
* controllers,
* - private test interfaces
*/
/* Driver specific headers */
#include <sys/wrsm_common.h>
#include <sys/wrsm_cf_impl.h>
#include <sys/wrsm_plat.h>
#include <sys/wrsm_transport.h>
#include <sys/wrsm_session.h>
#include <sys/wrsm_memseg.h>
#include <sys/wrsm_memseg_impl.h>
#include <sys/wrsm_barrier.h>
#ifdef DEBUG
#define CF_DEBUG 0x0001
#define CF_WARN 0x0002
#define DPRINT_BITMASK(m, b) dprint_bitmask(m, b)
#else
#define DPRINTF(a, b) { }
#define DPRINT_BITMASK(m, b)
#endif
#ifdef DEBUG
static void
{
int i;
for (i = 0; i < WRSM_MAX_NCSLICES; ++i) {
if (WRSM_IN_SET(bits, i)) {
}
}
}
#endif /* DEBUG */
/*
* Represents the state of the "admin" instance of the wrsm
* driver. There should be only one such instance.
*/
typedef struct {
int controller_devs;
} cf_state_t;
/*
* Called from the driver _init() routine to initialize
* data private to the config layer.
*/
void
wrsm_cf_init(void)
{
int i;
for (i = 0; i < WRSM_MAX_NCSLICES; ++i) {
}
}
/*
* Called from the driver _fini() routine to clean up
* cf specific things.
*/
void
wrsm_cf_fini(void)
{
}
/*
* Called from wrsm_ioctl() when called on a driver instance which
* has a type of wrsm_admin. All of the calls from the RSM proxy
* to install, update and query the configuration data come through
* here.
*/
/*ARGSUSED*/
int
{
return (retval);
switch (cmd) {
case WRSM_CONTROLLERS:
return (0);
case WRSM_REPLACECFG:
break;
case WRSM_CHECKCFG:
break;
case WRSM_INSTALLCFG:
break;
case WRSM_ENABLECFG:
break;
case WRSM_INITIALCFG:
break;
case WRSM_REMOVECFG:
break;
case WRSM_STARTCFG:
break;
case WRSM_STOPCFG:
break;
case WRSM_GETCFG:
break;
default:
return (EINVAL);
}
return (retval);
}
/* For a give wci port, finds the controller it should belong to */
static uint32_t
{
if (cont->controller) {
int i;
return (WRSM_BAD_RSM_ID);
}
return (cont->controller_id);
}
}
}
}
return (WRSM_BAD_RSM_ID);
}
/*
* Called from _attach() when a new physical WCI is added.
* The LC handle and port id are saved so that when configuration
* data comes in which specifies WCIs by port id, it can be
* translated to the LC handle before being handed to the NC
*/
int
{
/*
* If we already have an wci_dev_t for this wci, that means
* that it had previously been attached, assigned to a controller
* removed by DR, and now is being added again.
*/
/* This is a new WCI, so create an entry for it. */
KM_SLEEP);
}
if (newwci) {
/* If new wci, add to wci list */
}
/* See if this WCI belongs to an existing controller */
if (cont) {
/* Don't call wrsm_nc_newwci if controller isn't enabled */
} else {
/*
* Tried to DR in a WCI which belongs to a
* controller which is in the middle of being
* reconfigured.
*/
return (EBUSY);
}
}
return (WRSM_SUCCESS);
}
/*
* Remove an entry from the list of attached WCIs
*/
int
{
}
(void *)lcwci));
return (WRSM_SUCCESS);
}
/*
* If this WCI belongs to a controller, then check with
* nr to see if it's safe to let it be removed. If it is
* removed, we leave it on the wci_list so that when it
* comes back, cf_newwci() can plug it back into the same
* controller.
*/
if (!ier)
return (ier);
}
else
return (EBUSY);
}
/*
* If the WCI does not belong to a controller, then
* delete it from the list.
*/
} else {
return (EINVAL);
}
}
return (WRSM_SUCCESS);
}
/*
* Given the Safari port id of an attached wci, return
* the corresponding lcwci_handle_t.
*/
{
if (wci)
else
return (NULL);
}
/*
* This function is registered as a callback from the wrsm mailbox
* module and is called when it is notfied that the SC has come back
* up. This implies that the SC had previously crashed so any
* outstanding mailbox requests need to be re-sent.
*/
void
{
while (cfwci) {
}
}
/*
* Reserve a wci for use by the specified controller
*/
int
{
if (wci) {
return (WRSM_SUCCESS);
} else {
"wci %d is unavailable", wci_id));
return (EACCES);
}
}
return (WRSM_SUCCESS);
}
void
{
if (wci)
}
{
if (wci)
return (wci->controller_id);
else
return (WRSM_BAD_RSM_ID);
}
/*
* Return true if the local cnode is configured to be used as a
* starcat central switch.
*/
{
int i;
return (B_FALSE);
if (policy->forwarding_allowed) {
"forwarding is allowed"));
return (B_TRUE);
}
}
return (B_FALSE);
}
/*
* This function is called from _attach() when a new instance of the
* driver is created represeting an RSM controller. The def_info
* pointer is stashed away allong with the controller id (instance
* number) so that we can later translate from controller ids coming
* in via ioctl to the appropriate dev_info to pass to the NC
*/
int
{
sizeof (wrsm_controller_dev_t), KM_SLEEP);
return (WRSM_SUCCESS);
}
/*
* Delete an entry from the list of valid controllers. This is called
* from the driver _detach() when the instance type is
* wrsm_rsm_controller. In this context a "controller" is just a
* driver instance and it's associated wrsm_controller_dev_t struct.
* If the controller has configuration data associated with it (ie it
* has been the subject of an INITIALCFG ioctl) then this will cause
* the detach to fail.
*/
int
{
return (EINVAL);
/*
* Do not allow the driver to be unloaded if there are
* any active controllers.
*/
"%d is still active", cont_id));
return (EBUSY);
}
} else {
return (EINVAL);
}
}
return (WRSM_SUCCESS);
}
/*ARGSUSED*/
static int
{
int retval = 0;
int i;
void *controller_data = NULL;
int num_attached;
int num_claimed_wcis = 0;
ncslice_bitmask_t new_ncslices = {0};
ncslice_bitmask_t added_ncslices = {0};
sizeof (wrsm_admin_arg_config_t), flag) != 0) {
goto finish;
}
return (EINVAL);
}
goto finish;
}
goto finish;
}
goto finish;
}
KM_SLEEP);
goto finish;
}
goto finish;
}
/*
* Scan through the wci list in the wrsm_routing_data
* structure and pull out the port numbers, then pass the list
* of port numbers to create_wci_ids which builds the list of
* wci_ids_t that the NC expects. This also has the side
* effect of marking the wcis as belonging to this controller.
*/
KM_SLEEP);
/* Check wci ownership/availability */
if (wrsm_cf_wci_owner(port_list[i]) !=
port_list[i]) != 0) {
goto finish;
}
}
}
/* LINTED: E_NOP_IF_STMT */
if (!attached_wcis) {
}
goto finish;
}
goto finish;
}
/*
* Find all the slices in the new config not in the old one
* and attempt to allocate them.
*/
for (i = 0; i < WRSM_MAX_NCSLICES; ++i) {
if (WRSM_IN_SET(new_ncslices, i) &&
}
DPRINT_BITMASK("cf_replacecfg: new config added slices",
!= 0) {
"ncslices");
goto finish;
}
#ifdef DEBUG
{
int j;
num_attached));
for (j = 0; j < num_attached; ++j)
"lcwci = %p port = %d", j,
(void *)attached_wcis[i].lcwci,
attached_wcis[i].port));
}
#endif
if (retval == 0) {
} else {
if (port_list) {
for (i = 0; i < num_claimed_wcis; ++i) {
if (new_wci[i]) {
}
}
}
if (slices_allocated) {
}
/* If unpack failed, free controller_data */
if (controller_data) {
}
}
if (port_list) {
}
if (attached_wcis) {
}
return (retval);
}
/* ARGSUSED */
static void
{
}
static void
{
int i, retval;
DPRINT_BITMASK("cf_release_slices: ncslices before removal",
for (i = 0; i < WRSM_MAX_NCSLICES; ++i) {
if (WRSM_IN_SET(rel_slices, i)) {
}
}
/*
* Notify wrsmplat of the new list of allocated ncslices
*/
&granted))) {
/*
* a failure should never happen, as we're releasing
* slices we already owned; ignore failure.
*/
"failed %d", retval);
}
DPRINT_BITMASK("cf_release_slices: ncslices after removal",
}
static void
{
int i, retval;
DPRINT_BITMASK("cf_release_all_slices: ncslices before removal",
for (i = 0; i < WRSM_MAX_NCSLICES; ++i) {
}
}
/*
* Notify wrsmplat of the new list of allocated ncslices
*/
&granted))) {
/*
* a failure should never happen, as we're releasing
* slices we already owned; ignore failure.
*/
"failed %d", retval);
}
DPRINT_BITMASK("cf_release_all_slices: ncslices after removal",
}
static void
{
#ifdef DEBUG
} else {
}
#endif /* DEBUG */
}
static int
{
int retval = 0;
int i;
DPRINT_BITMASK("cf_claim_slices: ncslices allocated",
/*
* Find out if any of the requsted slices are already taken
* by another controller. This will be the case if any of
* the slices in req_slices is allocated and the owner is
* someone else.
*/
for (i = 0; i < WRSM_MAX_NCSLICES; ++i) {
if (WRSM_IN_SET(req_slices, i) &&
"contid %d ncslice %d already taken by cont %d",
return (EACCES);
}
}
/* Get the union of the old and new ncslices */
/* Determine what new slices are needed */
/* If there are new slices that are needed, allocate from SC */
if (!WRSMSET_ISNULL(new_slices)) {
DPRINT_BITMASK("cf_claim_slices: new slices",
/* wrsmplat needs to see list of ALL slices desired */
"failed %d", retval);
return (retval);
}
/*
* If we didn't get everything we requested, back out new
* ncslices, then fail.
*/
if ((retval = wrsmplat_alloc_slices(
/* ignore failure; this shouldn't happen */
"cf_claim_slices: wrsmplat_alloc "
"failed %d", retval);
}
return (EACCES);
}
/*
* All requested slices were allocated, so update the
* ownership list.
*/
for (i = 0; i < WRSM_MAX_NCSLICES; ++i) {
if (WRSM_IN_SET(req_slices, i)) {
}
}
}
return (WRSM_SUCCESS);
}
/*ARGSUSED*/
static int
{
int retval = 0;
return (EINVAL);
"not present %d", (int)arg));
return (EINVAL);
}
if (!up)
return (retval);
}
/*ARGSUSED*/
static int
{
int retval = 0;
int num_attached;
ncslice_bitmask_t old_slices = {0};
int i;
sizeof (wrsm_admin_arg_wci_t), flag) != 0)
return (EFAULT);
return (EINVAL);
}
return (EINVAL);
return (EINVAL);
}
return (EBUSY);
}
return (EINVAL);
}
KM_SLEEP);
goto finish;
}
/* LINTED: E_NOP_IF_STMT */
if (!attached_wcis) {
}
if (retval != 0)
goto finish;
/*
* At this point, the NC guarantees that no accesses will be made
* to the old ncslices, so it's safe to release them.
*/
#ifdef DEBUG
{
int j;
num_attached));
for (j = 0; j < num_attached; ++j)
"lcwci = %p port = %d", j,
(void *)attached_wcis[j].lcwci,
attached_wcis[j].port));
}
#endif
if (retval != 0)
goto finish;
for (i = 0; i < WRSM_MAX_NCSLICES; ++i) {
WRSMSET_ADD(old_slices, i);
}
}
if (retval == 0) {
int i, j, old_port;
/*
* Release WCIs from the old config not in the new.
* This relies on both the old and new lists of wcis
* to be sorted in ascending order by port number.
*/
j = 0;
++j;
}
}
}
if (attached_wcis) {
}
return (retval);
}
static int
{
int retval = 0;
int num_attached;
sizeof (wrsm_admin_arg_wci_t), flag) != 0)
return (EFAULT);
return (EINVAL);
}
return (EINVAL);
return (EINVAL);
}
return (EBUSY);
}
goto err_return;
}
KM_SLEEP);
goto err_return;
}
/* LINTED: E_NOP_IF_STMT */
if (!attached_wcis) {
}
if (attached_wcis) {
}
if (retval == 0)
return (retval);
if (wcis)
if (attached_wcis) {
}
return (retval);
}
/*
* Called as a result of an WRSM_INITIALCFG ioctl() call to the wrsm
* admin psuedo driver. The arg is a pointer to a wrsm_admin_arg_config_t
* structure which contains the address and size of a wrsm_controller_t.
* If successfull, this function brings the controller data in from user
* space and passes it to wsrm_nc_initialcfg().
*/
static int
{
int retval = 0;
int i;
void *controller_data = NULL;
int num_attached;
sizeof (wrsm_admin_arg_config_t), flag) != 0) {
"failed"));
goto err_return;
}
return (EINVAL);
}
"failed"));
goto err_return;
}
/*
* If there is already a cached wrsm_conroller_t pointer then
* we already have a config for this controller so it can't
* be "initial".
*/
"controller already configured");
goto err_return;
}
return (EBUSY);
}
/* Bring the controller data in from user space */
"failed"));
goto err_return;
}
goto err_return;
}
/*
* Scan through the wci list in the wrsm_routing_data
* structure and pull out the port numbers, then pass the list
* of port numbers to create_wci_ids which builds the list of
* wci_ids_t that the NC expects. This also has the side
* effect of marking the wcis as belonging to this controller.
*/
port_list[i]) != 0) {
"failed"));
goto err_return;
}
}
if (!attached_wcis) {
goto err_return;
}
"failed"));
goto err_return;
}
if (retval != 0) {
goto err_return;
}
#ifdef DEBUG
{
int j;
num_attached));
for (j = 0; j < num_attached; ++j)
"lcwci = %p port = %d", j,
(void *)attached_wcis[j].lcwci,
attached_wcis[j].port));
}
#endif
"failed"));
goto err_return;
}
if (attached_wcis)
if (port_list)
return (WRSM_SUCCESS);
if (slices_allocated) {
}
if (port_list)
/*
* Only release WCIs that we have succesfully claimed
*/
if (wrsm_cf_wci_owner(port_list[i]) ==
}
if (attached_wcis) {
}
if (port_list) {
}
}
if (controller_data)
if (cont) {
}
return (retval);
}
/*
* Calledback from the NC to the CF in response to
* wrsm_nc_initialconfig(). This should be called as soon as
* the NC has enabled the config.
*/
void
{
return;
}
}
/*ARGSUSED*/
static int
{
int retval;
int i;
return (EINVAL);
if (!cont->controller)
return (ENOENT);
return (EBUSY);
}
return (retval);
}
/* remove ncslice request from inuse */
return (WRSM_SUCCESS);
}
/*ARGSUSED*/
static int
{
int retval;
return (EINVAL);
if (!cont->controller)
return (ENOENT);
return (EBUSY);
}
return (retval);
}
/*ARGSUSED*/
static int
{
int retval;
return (EINVAL);
if (!cont->controller)
return (ENOENT);
return (EBUSY);
}
return (retval);
}
static int
{
sizeof (wrsm_admin_arg_config_t), flag) != 0)
return (EFAULT);
return (EINVAL);
}
/*
* Search for a controller with a matching id in the cache
*/
return (EINVAL);
if (!cont->controller)
return (ENOENT);
/*
* If the size of the user mode data block provided is not big
* enough to hold the controller data, fill in the required
* size, and return. Typically this function should be called
* once with size of 0 and then a second time with an
* appropriate size buffer.
*/
get_arg.controller = 0;
sizeof (wrsm_admin_arg_config_t), 0) != 0)
return (EFAULT);
else
return (WRSM_SUCCESS);
}
return (EFAULT);
}
return (WRSM_SUCCESS);
}
/*
* Search for the specified controller id in the list created
* by wrsm_cf_new_controller().
*/
static wrsm_controller_dev_t *
{
if (controller_id == WRSM_BAD_RSM_ID)
return (NULL);
while (cont) {
break;
}
return (cont);
}
/*
* Search for the specified wci port id in the list created
* by wrsm_cf_newwci().
*/
static wrsm_wci_dev_t *
{
while (wci) {
break;
}
return (wci);
}
/*
* A wrsm_controller_t contains a list of pointers to wrsm_wci_data_t.
* Before calling any of the nc_ functions, this list should be
* translated to an array of wci_ids_t. This is done by looking
* up the safari id of the WCIs in the list created by wrsm_cf_newwci()
*/
static wci_ids_t *
int *nfoundp)
{
int i;
int nfound = 0;
for (i = 0; i < nwcis; ++i) {
"number %d", port));
continue;
}
continue;
}
continue;
++nfound;
}
if (nfoundp)
return (ret);
if (nfoundp)
*nfoundp = 0;
return (NULL);
}
static int
{
int i, j;
int err;
return (EINVAL);
}
/*
* Verify that the local wnode is mentioned in the reachable
* list and that it points to the local cnode
*/
return (EINVAL);
}
}
if (err) {
return (err);
}
/* Check that all ncslices exported to this node are unique */
if (!WRSMSET_ISNULL(intersect)) {
/*
* If the intersection is not empty, then some
* of the slices are not unique, so scan
* through the list to find which ones for a
* better error message and return an error.
*/
for (j = 0; j < WRSM_MAX_NCSLICES; ++j)
if (WRSM_IN_SET(intersect, j))
return (EINVAL);
}
/*
* Check that comm_ncslice is one of the slices
* exported by the remote node.
*/
"verify: comm_slice 0x%x not in exported set",
return (EINVAL);
}
/* Check that the remote cnodeid is valid */
return (EINVAL);
}
/* Check that in and out driver comm offsets are unique */
continue;
"local_offsets, cnode %d and cnode %d\n",
return (EINVAL);
}
}
}
/*
* Collect the ncslices being imported by remote nodes (exported by
* this node). Note that each node's imported ncslices do _not_
* need to be different from those of other nodes; however there
* must be an agreement on which are large and small ncslices.
*/
if (err) {
return (err);
}
}
/*
* Check that no small slices are also used as large slices.
*/
if (!WRSMSET_ISNULL(intersect)) {
/*
* If the intersection is not empty, then some
* of the slices are being used both for large and
* small pages.
*/
"imported ncslices used for both large and small pages");
for (j = 0; j < WRSM_MAX_NCSLICES; ++j)
if (WRSM_IN_SET(intersect, j))
"conflict %d", j);
return (EINVAL);
}
/*
* Collect the ncslices used to allow this node to forward traffic
* from other nodes.
*/
if (policy->forwarding_allowed) {
if (!wrsm_forwarding_supported) {
return (ENOTSUP);
}
if (!WRSMSET_ISNULL(intersect)) {
/*
* If the intersection is not empty, then
* some of the ncslices used for forwarding
* are also exported by this node. This
* isn't supported.
*/
"forwarding ncslices clash with import"
"ncslices");
for (j = 0; j < WRSM_MAX_NCSLICES; ++j)
if (WRSM_IN_SET(intersect, j))
"conflict %d", j);
return (EINVAL);
}
}
}
DPRINT_BITMASK("cf_verify_config: new config slices",
return (WRSM_SUCCESS);
}
static int
{
return (EINVAL);
}
/*
* The cnode of the local node never changes while it is
* participating in an RSM network.
*/
return (EINVAL);
}
/*
* Three related constraints:
*
* 1) A new configuration must not assign an ncslice to a new
* cnode if it was used by a different cnode in the old
* configuration. This is overridden by the stronger constraint #3.
*
* 2) The ncslice and offset used for driver communication must
* not change on a cnode that is containd in both the old and
* new configuration. This is checked in wrsm_nc.c
*
* 3) No ncslices already exported by a node in the old
* configuration can be removed in the new configuration.
* This is checked in wrsm_nc.c
*/
return (WRSM_SUCCESS);
}
/*
* Called from wrsm_ioctl() when invoked on a driver instance which
* has a type of wrsm_rsm_controller.
*/
/* ARGSUSED */
int
{
int retval;
switch (cmd) {
case WRSM_CTLR_PING:
break;
case WRSM_CTLR_MBOX:
break;
case WRSM_CTLR_SESS:
break;
case WRSM_CTLR_MEM_LOOPBACK:
break;
default:
cmd));
}
return (retval);
}
static int
{
int i, rc;
sizeof (wrsm_ping_arg_t), flag) != 0)
return (EFAULT);
return (EINVAL);
}
"id %d", cont_id));
return (EINVAL);
}
"for controller %d", cont_id));
return (EINVAL);
}
for (i = 0; i < WRSM_MESSAGE_BODY_SIZE; i++) {
}
gethrestime(&time1);
if (rc != 0) {
" failed rc=%x i=%d", rc, i));
return (rc);
}
}
gethrestime(&time2);
0) != 0) {
return (EFAULT);
}
return (WRSM_SUCCESS);
}
static int
{
int i;
sizeof (wrsm_link_arg_t), flag) != 0)
return (EFAULT);
return (EINVAL);
}
"id %d", cont_id));
return (EINVAL);
}
"configured", cont_id));
return (EINVAL);
}
break;
}
return (EINVAL);
}
case WRSM_CTLR_UPLINK:
break;
case WRSM_CTLR_DOWNLINK:
break;
case WRSM_CTLR_SET_LED:
break;
case WRSM_CTLR_ALLOC_SLICES:
break;
case WRSM_CTLR_SET_SEPROM:
break;
default:
break;
}
return (WRSM_SUCCESS);
}
/*
* loopback memory
*/
#ifdef DEBUG
#define DPRINT_DATA(a) dprint_pattern_data(a)
void
dprint_pattern_data(unsigned char *d)
{
"%2x%2x%2x%2x%2x%2x%2x%2x %2x%2x%2x%2x%2x%2x%2x%2x "
"%2x%2x%2x%2x%2x%2x%2x%2x %2x%2x%2x%2x%2x%2x%2x%2x "
"%2x%2x%2x%2x%2x%2x%2x%2x %2x%2x%2x%2x%2x%2x%2x%2x "
"%2x%2x%2x%2x%2x%2x%2x%2x %2x%2x%2x%2x%2x%2x%2x%2x",
d[0x0], d[0x1], d[0x2], d[0x3],
d[0x4], d[0x5], d[0x6], d[0x7],
d[0x8], d[0x9], d[0xa], d[0xb],
d[0xc], d[0xd], d[0xe], d[0xf],
d[0x10], d[0x11], d[0x12], d[0x13],
d[0x14], d[0x15], d[0x16], d[0x17],
d[0x18], d[0x19], d[0x1a], d[0x1b],
d[0x1c], d[0x1d], d[0x1e], d[0x1f],
d[0x20], d[0x21], d[0x22], d[0x23],
d[0x24], d[0x25], d[0x26], d[0x27],
d[0x28], d[0x29], d[0x2a], d[0x2b],
d[0x2c], d[0x2d], d[0x2e], d[0x2f],
d[0x30], d[0x31], d[0x32], d[0x33],
d[0x34], d[0x35], d[0x36], d[0x37],
d[0x38], d[0x39], d[0x3a], d[0x3b],
d[0x3c], d[0x3d], d[0x3e], d[0x3f]));
}
#else
#define DPRINT_DATA(a)
#endif
unsigned char *expected_data, unsigned char *actual_data);
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
0xffffffffffffffff, 0xffffffffffffffff,
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
0xffffffffffffffff, 0xffffffffffffffff,
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0,
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
0xffffffffffffffff, 0x0, 0x0, 0x0, 0x0,
};
/*
* Write the entire memory region pointed to by memptr. Apply each of the
* 4 64 byte patterns in sso_pat to 4 consecutive cachelines. Keep doing
* this until the entire region is written.
*/
int
unsigned char *expected_data, unsigned char *actual_data)
{
char *send_data;
char *receive_data = (char *)&raw_msg;
uint_t i, j;
for (i = 0; i < (len / 64); i++) {
DPRINT_DATA((unsigned char *)send_data);
for (j = 0; j < 64; j++) {
if (send_data[j] != receive_data[j]) {
*error_offset = (i * 64) + j;
return (EIO);
}
}
memptr += 64;
}
return (WRSM_SUCCESS);
}
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
/*
* Write the entire memory region pointed to by memptr, alternately writing
* 2 cachelines of all 0s followed by 2 cachelines of all 1s. March one
* bit along which has the opposite setting from the rest of the bits in
* each set of 4 cachelines. (Thus, in the first 4 cachelines, bit 0 is
* flipped. In the next 4 cachelines, bit 1 is flipped, and so on.)
*/
int
unsigned char *expected_data, unsigned char *actual_data)
{
char *receive_data = (char *)&raw_rsp;
uint_t i, j;
unsigned char marcher = 1;
int march_index = 63;
for (i = 0; i < (len / 64); i++) {
if (marcher_is_one) {
} else {
/* set marcher bit to 0 */
}
DPRINT_DATA((unsigned char *)send_data);
for (j = 0; j < 64; j++) {
if (send_data[j] != receive_data[j]) {
*error_offset = (i * 64) + j;
return (EIO);
}
}
memptr += 64;
/*
* march a bit across the 64 byte cacheline.
*/
if (first_cacheline) {
/*
* each 64 byte pattern is repeated
*/
} else {
if (marcher_is_one) {
/*
* second half of round: bits are all 1
* except marcher, which is 0.
*/
pat = 64;
} else {
/*
* start new round: bits are all 0 except
* marcher, which is 1.
*/
pat = 0;
if (marcher & 0x80) {
/*
* wrap marcher back to start of
* 64 byte cacheline.
*/
marcher = 1;
march_index--;
if (march_index == -1) {
march_index = 63;
}
} else {
}
}
}
}
return (WRSM_SUCCESS);
}
/*
* Write the entire memory region pointed to by memptr, alternately writing
* a cacheline of all 0s and all 1s. March one bit along at each 128 bit
* offset in the cacheline which has the opposite setting from the rest of
* the bits in each pair of cachelines. (Thus, in the first 2 cachelines,
* bits 0, 128, 256 and 384 are flipped. In the next 2 cachelines, bits 1,
* 129, 257, 385 are flipped, and so on.)
*/
int
unsigned char *expected_data, unsigned char *actual_data)
{
char *receive_data = (char *)&raw_rsp;
uint_t i, j;
unsigned char marcher = 1;
for (i = 0; i < (len / 64); i++) {
for (j = 0; j < 4; j++) {
if (turn_bit_off) {
} else {
}
}
DPRINT_DATA((unsigned char *)send_data);
for (j = 0; j < 64; j++) {
if (send_data[j] != receive_data[j]) {
*error_offset = (i * 64) + j;
return (EIO);
}
}
memptr += 64;
/*
* march alternating bit along
*/
if (turn_bit_off) {
/* finished both passes; increment marcher bit */
if (marcher & 0x80) {
marcher = 1;
march_index--;
if (march_index == 47) {
march_index = 63;
}
} else {
}
pat = 0;
} else {
pat = 64;
}
}
return (WRSM_SUCCESS);
}
0x5555555555555555, 0x5555555555555555, 0x5555555555555555,
0x5555555555555555, 0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa,
0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa,
};
/*
* Write the entire memory region pointed to by memptr. Apply the 64 byte
* pattern in xtalk_pat to each cacheline. Keep doing this until the
* entire region is written.
*/
int
unsigned char *expected_data, unsigned char *actual_data)
{
char *receive_data = (char *)&raw_buf;
uint_t i, j;
for (i = 0; i < (len / 64); i++) {
DPRINT_DATA((unsigned char *)send_data);
for (j = 0; j < 64; j++) {
if (send_data[j] != receive_data[j]) {
*error_offset = (i * 64) + j;
return (EIO);
}
}
memptr += 64;
}
return (WRSM_SUCCESS);
}
};
/*
* Loopback memory test.
*
* Create a memory segment, import it (loopback connection), then
* write and read a pattern to requested various offsets in the
* segment. Clean up (remove segment), and return whether the
*
* This test is intended for use by SunVTS.
*/
static int
{
void *buf;
int err = 0;
int i;
sizeof (wrsm_memloopback_arg_t), flag) != 0) {
return (EFAULT);
}
loop_arg.error_pattern = 0;
"controller id %d", cont_id));
return (EINVAL);
}
"struct for controller %d", cont_id));
return (ENXIO);
}
/*
* We now use our own allocation routines rather than
* kmem_{z}alloc() because we require the underlying memory
* pages to be static in memory (i.e. non-relocatable).
*/
return (ENOMEM);
}
/*
* create segment
*/
"failed %d", err));
if (err == RSMERR_NOT_MEM)
err = EHOSTUNREACH;
else
return (err);
}
/*
* publish segment
*/
while (segid <= RSM_USER_APP_ID_END) {
!= RSM_SUCCESS) {
if (err == RSMERR_SEGID_IN_USE) {
/* segment id is already in use */
segid++;
} else {
goto export_cleanup;
}
} else {
/* successful publish */
break;
}
}
if (segid > RSM_USER_APP_ID_END) {
"available"));
goto export_cleanup;
}
"published a segment with size of 0x%x and segid 0x%x\n",
MEMLOOP_BSIZE, segid));
/*
* connect to segment
*/
&importseg)) != RSM_SUCCESS) {
/*
*/
"wrsmrsm_connect failed err=%d cnodeid %d segid %d",
if (err == RSMERR_RSM_ADDR_UNREACHABLE)
err = EHOSTUNREACH;
else if (err == RSMERR_CONN_ABORTED)
else
goto export_cleanup;
}
/*
* map in segment
*/
if (err) {
(void) wrsmrsm_disconnect(importseg);
goto export_cleanup;
}
"dip 0x%p, rnumber %d offset 0x%lx len 0x%lx\n",
if (err != DDI_SUCCESS) {
(void) wrsmrsm_unmap(importseg);
(void) wrsmrsm_disconnect(importseg);
/*
*/
"failed err = %d rnumber %d offset 0x%lx len 0x%lx",
err = EHOSTUNREACH;
goto export_cleanup;
}
"map_kaddr 0x%p", (void *)map_kaddr));
/*
*/
for (i = 0; i < WRSM_MAX_PATTERN; i++) {
/*
* make sure there are no accidentally correct
* patterns in the buffer
*/
&barrier)) != RSM_SUCCESS) {
goto import_cleanup;
}
loop_arg.actual_data)) != 0) {
va_to_pa((void *)(aligned_buf +
error_offset));
goto import_cleanup;
}
!= RSM_SUCCESS) {
/*
* pattern subtest
*/
if (err == RSMERR_BARRIER_FAILURE)
else
goto import_cleanup;
}
}
}
/*
* finished successfully
*/
map_len);
(void) wrsmrsm_unmap(importseg);
(void) wrsmrsm_disconnect(importseg);
(void) wrsmrsm_unpublish(exportseg);
(void) wrsmrsm_seg_destroy(exportseg);
0) != 0) {
return (EFAULT);
}
return (err);
}
static int
{
int retval = 0;
sizeof (wrsm_sess_arg_t), flag) != 0) {
return (EFAULT);
}
return (EINVAL);
}
"id %d", cont_id));
return (EINVAL);
}
"for controller %d", cont_id));
return (EINVAL);
}
case WRSM_CTLR_SESS_START:
}
break;
case WRSM_CTLR_SESS_END:
break;
case WRSM_CTLR_SESS_ENABLE:
break;
case WRSM_CTLR_SESS_DISABLE:
break;
case WRSM_CTLR_SESS_GET:
break;
default:
}
0) != 0) {
return (EFAULT);
}
return (retval);
}
/*
* verify that the ncslice array has valid values, then convert into
* a bitmask. Return 0 if valid.
*/
static int
{
int i;
return (EINVAL);
}
/*
* Verify the large page ncslices are valid. The ncslice for entry
* 1 must end with b'001', the ncslice for entry 2 must end with
* b'010', entry 3 with b'011' and so on. An ncslice value of 0
* indicates that the entry is invalid.
*/
for (i = 1; i < WRSM_NODE_NCSLICES; i++) {
if (slice_array.id[i] == 0) {
continue;
}
return (EINVAL);
}
if (!wrsm_large_pages_supported) {
"verify: large page ncslices not supported");
return (ENOTSUP);
}
return (EINVAL);
}
"verify: large page ncslice not unique");
return (EINVAL);
}
}
DPRINT_BITMASK("wrsm_cf_ncslicelist_to_bitmask large slices",
return (0);
}