wrsm_getput.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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This file implements the RSMPI rsm_get* and rsm_put* functions
* in the Wildcat RSM driver.
*/
#include <vm/seg_kmem.h>
#include <sys/ddimapreq.h>
#include <sys/wrsm_common.h>
#include <sys/wrsm_memseg.h>
#include <sys/wrsm_memseg_impl.h>
#include <sys/wrsm_barrier.h>
#include <sys/wci_common.h>
#include <sys/wrsm_intr.h>
#include <sys/wrsm_plugin.h>
#ifdef DEBUG
extern char platform[];
#define DBG_WARN 0x001
#define DBG_SMPUT 0x008
#define DBG_SMPUT_EXTRA 0x080
#else /* DEBUG */
#define DPRINTF(a, b) { }
#endif /* DEBUG */
static void
{
if (node) {
}
}
/*
* Send one or more interrupt requests to cause <len> bytes from buffer
* <buf> be written at offset <offset> into the segment.
*/
static int
{
int writesize;
int put_offset;
int err;
#ifdef DEBUG
#endif
/* LINTED */
#ifdef DEBUG
(CE_CONT, "small put buffer is 8 bytes\n"));
smallput_body_size = 8;
} else {
smallput_body_size = 48;
}
#endif
while (len) {
/*
* Place the data in putdata buffer so that it is long
* aligned with respect to the segment offset. (Note that
* the start of the putdata buffer is long aligned.)
*/
#ifdef DEBUG
if (len < smallput_body_size)
else
#else
if (len < WRSM_SMALLPUT_BODY_SIZE)
else
#endif
(CE_CONT, "len 0x%x offset 0x%lx writesize %d "
"put_offset %d msg 0x%p msg-buf-start 0x%p "
"put-paddr 0x%lx\n",
if (err) {
return (RSMERR_BARRIER_FAILURE);
}
}
return (RSM_SUCCESS);
}
int
{
int err = RSM_SUCCESS;
RSM_SUCCESS) {
return (err);
}
if (importseg->unpublished) {
return (RSMERR_CONN_ABORTED);
}
return (RSMERR_PERM_DENIED);
}
return (RSMERR_BAD_LENGTH);
}
if (length == 0) {
return (RSM_SUCCESS);
}
if (!importseg->kernel_user) {
if (!iseginfo->kernel_users) {
if (err) {
return (err);
}
}
iseginfo->kernel_users++;
}
RSM_SUCCESS) {
return (err);
}
}
/*
* handle partial line write at start of buffer
*/
if (offset & WRSM_CACHELINE_MASK) {
if (partial_cacheline > length)
if (err) {
if (importseg->barrier_mode ==
(void) wrsm_close_barrier(&barrier);
}
/*
* guarantee that any outstanding small puts have
* finished
*/
msg, 0, WRSM_INTR_WAIT_DEFAULT, 0);
return (err);
}
dp += partial_cacheline;
if (length == 0) {
int intr_err;
/*
* this put call is finished
*/
/*
* guarantee that any outstanding small
* puts have finished
*/
if (importseg->barrier_mode ==
}
msg, 0, WRSM_INTR_WAIT_DEFAULT, 0);
/*
* Return the barrier error, or if that succeeded,
* the send error if there was one.
*/
return (err);
}
}
/*
* handle cacheline sized writes
*/
if (num_cachelines) {
}
/*
* handle partial line write at end of buffer
*/
if (length) {
if (err) {
/*
* guarantee that any outstanding small puts have
* finished
*/
msg, 0, WRSM_INTR_WAIT_DEFAULT, 0);
if (importseg->barrier_mode ==
(void) wrsm_close_barrier(&barrier);
}
return (err);
}
}
if (did_small_puts) {
/*
* guarantee that any outstanding small puts have finished
*/
msg, 0, WRSM_INTR_WAIT_DEFAULT, 0);
}
}
return (err);
}
/* ARGSUSED */
int
{
/* Since Wildcat is SPARC-only, don't need to worry about byte_swap */
}
/* ARGSUSED */
int
{
/* Check alignment */
return (RSMERR_BAD_MEM_ALIGNMENT);
}
/* Since Wildcat is SPARC-only, don't need to worry about byte_swap */
}
/* ARGSUSED */
int
{
/* Check alignment */
return (RSMERR_BAD_MEM_ALIGNMENT);
}
/* Since Wildcat is SPARC-only, don't need to worry about byte_swap */
}
/* ARGSUSED */
int
{
/* Check alignment */
return (RSMERR_BAD_MEM_ALIGNMENT);
}
/* Since Wildcat is SPARC-only, don't need to worry about byte_swap */
}
static int
{
return (RSM_SUCCESS);
}
int
{
int err;
"wrsmrsm_get - importseg 0x%p offset 0x%lx len %ld\n",
RSM_SUCCESS) {
return (err);
}
if (importseg->unpublished) {
return (RSMERR_CONN_ABORTED);
}
if (!importseg->kernel_user) {
if (!iseginfo->kernel_users) {
if (err) {
return (err);
}
}
iseginfo->kernel_users++;
}
return (RSMERR_PERM_DENIED);
}
/* barrier doesn't record this type of error */
return (RSMERR_BAD_LENGTH);
}
if (length == 0) {
return (RSM_SUCCESS);
}
RSM_SUCCESS) {
return (err);
}
}
/*
* handle partial line read at start of buffer
*/
if (offset & WRSM_CACHELINE_MASK) {
if (partial_cacheline > length)
!= 0) {
if (importseg->barrier_mode ==
(void) wrsm_close_barrier(&barrier);
}
return (err);
}
dp += partial_cacheline;
if (length == 0) {
if (importseg->barrier_mode ==
return (wrsm_close_barrier(&barrier));
} else {
return (RSM_SUCCESS);
}
}
}
/*
* handle cacheline sized reads
*/
if (num_cachelines) {
"full cacheline read offset 0x%lx num_cachelines %d\n",
offset, num_cachelines));
seg,
dp,
}
/*
* handle partial line read at end of buffer
*/
if (length) {
if (importseg->barrier_mode ==
(void) wrsm_close_barrier(&barrier);
}
return (err);
}
}
}
return (err);
}
/* ARGSUSED */
int
{
/* Since Wildcat is SPARC-only, don't need to worry about byte_swap */
}
/* ARGSUSED */
int
{
/* Check alignment */
return (RSMERR_BAD_MEM_ALIGNMENT);
}
/* Since Wildcat is SPARC-only, don't need to worry about byte_swap */
}
/* ARGSUSED */
int
{
/* Check alignment */
return (RSMERR_BAD_MEM_ALIGNMENT);
}
/* Since Wildcat is SPARC-only, don't need to worry about byte_swap */
}
/* ARGSUSED */
int
{
/* Check alignment */
return (RSMERR_BAD_MEM_ALIGNMENT);
}
/* Since Wildcat is SPARC-only, don't need to worry about byte_swap */
}
/*
* Called from wrsm_ioctl() when invoked on a driver instance which
* has a type of wrsm_rsm_controller and cmd = WRSM_CTLR_PLUGIN_SMALLPUT
*/
/* ARGSUSED */
int
{
int err;
int datamodel;
switch (datamodel) {
case DDI_MODEL_ILP32:
sizeof (msg_pluginput_args32_t), mode) != 0) {
"ioctl ddi_copyin failed 32 bit "));
return (EFAULT);
}
"app. segid %d length %ld cnode %ld",
!= 0) {
"ioctl ddicopyin msg buffer failed "));
return (EFAULT);
}
break;
default:
sizeof (msg_pluginput_args_t), mode) != 0) {
"ioctl ddi_copyin failed 64 bit "));
return (EFAULT);
}
" bit app. segid %d length %ld cnode %ld",
!= 0) {
"ioctl ddicopyin msg buffer failed "));
return (EFAULT);
}
break;
}
/*
* Get iseginfo for this controller, cnodeid, and segment_id.
* iseginfo is returned locked.
*/
&iseginfo);
if (err != RSM_SUCCESS) {
return (err);
}
/*
* RSM Kernel Agent prevents iseginfo being removed (it holds
* an importseg on behalf of the caller), so it is not necessary
* to hold iseginfo->lock during the call to small_put().
*/
if (err != RSM_SUCCESS) {
return (EIO);
}
/* send 0 length, 0 buf to assure put finished */
msg, 0, WRSM_INTR_WAIT_DEFAULT, 0);
return (0);
}