diff options
Diffstat (limited to 'usr/src/uts/common/io/dcopy.c')
-rw-r--r-- | usr/src/uts/common/io/dcopy.c | 932 |
1 files changed, 0 insertions, 932 deletions
diff --git a/usr/src/uts/common/io/dcopy.c b/usr/src/uts/common/io/dcopy.c deleted file mode 100644 index 2dc5a311bc..0000000000 --- a/usr/src/uts/common/io/dcopy.c +++ /dev/null @@ -1,932 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (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 - * or http://www.opensolaris.org/os/licensing. - * 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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * dcopy.c - * dcopy misc module - */ - -#include <sys/conf.h> -#include <sys/kmem.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/modctl.h> -#include <sys/sysmacros.h> -#include <sys/atomic.h> - - -#include <sys/dcopy.h> -#include <sys/dcopy_device.h> - - -/* Number of entries per channel to allocate */ -uint_t dcopy_channel_size = 1024; - - -typedef struct dcopy_list_s { - list_t dl_list; - kmutex_t dl_mutex; - uint_t dl_cnt; /* num entries on list */ -} dcopy_list_t; - -/* device state for register/unregister */ -struct dcopy_device_s { - /* DMA device drivers private pointer */ - void *dc_device_private; - - /* to track list of channels from this DMA device */ - dcopy_list_t dc_devchan_list; - list_node_t dc_device_list_node; - - /* - * dc_removing_cnt track how many channels still have to be freed up - * before it's safe to allow the DMA device driver to detach. - */ - uint_t dc_removing_cnt; - dcopy_device_cb_t *dc_cb; - - dcopy_device_info_t dc_info; - -}; - -typedef struct dcopy_stats_s { - kstat_named_t cs_bytes_xfer; - kstat_named_t cs_cmd_alloc; - kstat_named_t cs_cmd_post; - kstat_named_t cs_cmd_poll; - kstat_named_t cs_notify_poll; - kstat_named_t cs_notify_pending; - kstat_named_t cs_id; - kstat_named_t cs_capabilities; -} dcopy_stats_t; - -/* DMA channel state */ -struct dcopy_channel_s { - /* DMA driver channel private pointer */ - void *ch_channel_private; - - /* shortcut to device callbacks */ - dcopy_device_cb_t *ch_cb; - - /* - * number of outstanding allocs for this channel. used to track when - * it's safe to free up this channel so the DMA device driver can - * detach. - */ - uint64_t ch_ref_cnt; - - /* state for if channel needs to be removed when ch_ref_cnt gets to 0 */ - boolean_t ch_removing; - - list_node_t ch_devchan_list_node; - list_node_t ch_globalchan_list_node; - - /* - * per channel list of commands actively blocking waiting for - * completion. - */ - dcopy_list_t ch_poll_list; - - /* pointer back to our device */ - struct dcopy_device_s *ch_device; - - dcopy_query_channel_t ch_info; - - kstat_t *ch_kstat; - dcopy_stats_t ch_stat; -}; - -/* - * If grabbing both device_list mutex & globalchan_list mutex, - * Always grab globalchan_list mutex before device_list mutex - */ -typedef struct dcopy_state_s { - dcopy_list_t d_device_list; - dcopy_list_t d_globalchan_list; -} dcopy_state_t; -dcopy_state_t *dcopy_statep; - - -/* Module Driver Info */ -static struct modlmisc dcopy_modlmisc = { - &mod_miscops, - "dcopy kernel module" -}; - -/* Module Linkage */ -static struct modlinkage dcopy_modlinkage = { - MODREV_1, - &dcopy_modlmisc, - NULL -}; - -static int dcopy_init(); -static void dcopy_fini(); - -static int dcopy_list_init(dcopy_list_t *list, size_t node_size, - offset_t link_offset); -static void dcopy_list_fini(dcopy_list_t *list); -static void dcopy_list_push(dcopy_list_t *list, void *list_node); -static void *dcopy_list_pop(dcopy_list_t *list); - -static void dcopy_device_cleanup(dcopy_device_handle_t device, - boolean_t do_callback); - -static int dcopy_stats_init(dcopy_handle_t channel); -static void dcopy_stats_fini(dcopy_handle_t channel); - - -/* - * _init() - */ -int -_init() -{ - int e; - - e = dcopy_init(); - if (e != 0) { - return (e); - } - - return (mod_install(&dcopy_modlinkage)); -} - - -/* - * _info() - */ -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&dcopy_modlinkage, modinfop)); -} - - -/* - * _fini() - */ -int -_fini() -{ - int e; - - e = mod_remove(&dcopy_modlinkage); - if (e != 0) { - return (e); - } - - dcopy_fini(); - - return (e); -} - -/* - * dcopy_init() - */ -static int -dcopy_init() -{ - int e; - - - dcopy_statep = kmem_zalloc(sizeof (*dcopy_statep), KM_SLEEP); - - /* Initialize the list we use to track device register/unregister */ - e = dcopy_list_init(&dcopy_statep->d_device_list, - sizeof (struct dcopy_device_s), - offsetof(struct dcopy_device_s, dc_device_list_node)); - if (e != DCOPY_SUCCESS) { - goto dcopyinitfail_device; - } - - /* Initialize the list we use to track all DMA channels */ - e = dcopy_list_init(&dcopy_statep->d_globalchan_list, - sizeof (struct dcopy_channel_s), - offsetof(struct dcopy_channel_s, ch_globalchan_list_node)); - if (e != DCOPY_SUCCESS) { - goto dcopyinitfail_global; - } - - return (0); - -dcopyinitfail_cback: - dcopy_list_fini(&dcopy_statep->d_globalchan_list); -dcopyinitfail_global: - dcopy_list_fini(&dcopy_statep->d_device_list); -dcopyinitfail_device: - kmem_free(dcopy_statep, sizeof (*dcopy_statep)); - - return (-1); -} - - -/* - * dcopy_fini() - */ -static void -dcopy_fini() -{ - /* - * if mod_remove was successfull, we shouldn't have any - * devices/channels to worry about. - */ - ASSERT(list_head(&dcopy_statep->d_globalchan_list.dl_list) == NULL); - ASSERT(list_head(&dcopy_statep->d_device_list.dl_list) == NULL); - - dcopy_list_fini(&dcopy_statep->d_globalchan_list); - dcopy_list_fini(&dcopy_statep->d_device_list); - kmem_free(dcopy_statep, sizeof (*dcopy_statep)); -} - - -/* *** EXTERNAL INTERFACE *** */ -/* - * dcopy_query() - */ -void -dcopy_query(dcopy_query_t *query) -{ - query->dq_version = DCOPY_QUERY_V0; - query->dq_num_channels = dcopy_statep->d_globalchan_list.dl_cnt; -} - - -/* - * dcopy_alloc() - */ -/*ARGSUSED*/ -int -dcopy_alloc(int flags, dcopy_handle_t *handle) -{ - dcopy_handle_t channel; - dcopy_list_t *list; - - - /* - * we don't use the dcopy_list_* code here because we need to due - * some non-standard stuff. - */ - - list = &dcopy_statep->d_globalchan_list; - - /* - * if nothing is on the channel list, return DCOPY_NORESOURCES. This - * can happen if there aren't any DMA device registered. - */ - mutex_enter(&list->dl_mutex); - channel = list_head(&list->dl_list); - if (channel == NULL) { - mutex_exit(&list->dl_mutex); - return (DCOPY_NORESOURCES); - } - - /* - * increment the reference count, and pop the channel off the head and - * push it on the tail. This ensures we rotate through the channels. - * DMA channels are shared. - */ - channel->ch_ref_cnt++; - list_remove(&list->dl_list, channel); - list_insert_tail(&list->dl_list, channel); - mutex_exit(&list->dl_mutex); - - *handle = (dcopy_handle_t)channel; - return (DCOPY_SUCCESS); -} - - -/* - * dcopy_free() - */ -void -dcopy_free(dcopy_handle_t *channel) -{ - dcopy_device_handle_t device; - dcopy_list_t *list; - boolean_t cleanup; - - - ASSERT(*channel != NULL); - - /* - * we don't need to add the channel back to the list since we never - * removed it. decrement the reference count. - */ - list = &dcopy_statep->d_globalchan_list; - mutex_enter(&list->dl_mutex); - (*channel)->ch_ref_cnt--; - - /* - * if we need to remove this channel, and the reference count is down - * to 0, decrement the number of channels which still need to be - * removed on the device. - */ - if ((*channel)->ch_removing && ((*channel)->ch_ref_cnt == 0)) { - cleanup = B_FALSE; - device = (*channel)->ch_device; - mutex_enter(&device->dc_devchan_list.dl_mutex); - device->dc_removing_cnt--; - if (device->dc_removing_cnt == 0) { - cleanup = B_TRUE; - } - mutex_exit(&device->dc_devchan_list.dl_mutex); - } - mutex_exit(&list->dl_mutex); - - /* - * if there are no channels which still need to be removed, cleanup the - * device state and call back into the DMA device driver to tell them - * the device is free. - */ - if (cleanup) { - dcopy_device_cleanup(device, B_TRUE); - } - - *channel = NULL; -} - - -/* - * dcopy_query_channel() - */ -void -dcopy_query_channel(dcopy_handle_t channel, dcopy_query_channel_t *query) -{ - *query = channel->ch_info; -} - - -/* - * dcopy_cmd_alloc() - */ -int -dcopy_cmd_alloc(dcopy_handle_t handle, int flags, dcopy_cmd_t *cmd) -{ - dcopy_handle_t channel; - dcopy_cmd_priv_t priv; - int e; - - - channel = handle; - - atomic_inc_64(&channel->ch_stat.cs_cmd_alloc.value.ui64); - e = channel->ch_cb->cb_cmd_alloc(channel->ch_channel_private, flags, - cmd); - if (e == DCOPY_SUCCESS) { - priv = (*cmd)->dp_private; - priv->pr_channel = channel; - /* - * we won't initialize the blocking state until we actually - * need to block. - */ - priv->pr_block_init = B_FALSE; - } - - return (e); -} - - -/* - * dcopy_cmd_free() - */ -void -dcopy_cmd_free(dcopy_cmd_t *cmd) -{ - dcopy_handle_t channel; - dcopy_cmd_priv_t priv; - - - ASSERT(*cmd != NULL); - - priv = (*cmd)->dp_private; - channel = priv->pr_channel; - - /* if we initialized the blocking state, clean it up too */ - if (priv->pr_block_init) { - cv_destroy(&priv->pr_cv); - mutex_destroy(&priv->pr_mutex); - } - - channel->ch_cb->cb_cmd_free(channel->ch_channel_private, cmd); -} - - -/* - * dcopy_cmd_post() - */ -int -dcopy_cmd_post(dcopy_cmd_t cmd) -{ - dcopy_handle_t channel; - int e; - - - channel = cmd->dp_private->pr_channel; - - atomic_inc_64(&channel->ch_stat.cs_cmd_post.value.ui64); - if (cmd->dp_cmd == DCOPY_CMD_COPY) { - atomic_add_64(&channel->ch_stat.cs_bytes_xfer.value.ui64, - cmd->dp.copy.cc_size); - } - e = channel->ch_cb->cb_cmd_post(channel->ch_channel_private, cmd); - if (e != DCOPY_SUCCESS) { - return (e); - } - - return (DCOPY_SUCCESS); -} - - -/* - * dcopy_cmd_poll() - */ -int -dcopy_cmd_poll(dcopy_cmd_t cmd, int flags) -{ - dcopy_handle_t channel; - dcopy_cmd_priv_t priv; - int e; - - - priv = cmd->dp_private; - channel = priv->pr_channel; - - /* - * if the caller is trying to block, they needed to post the - * command with DCOPY_CMD_INTR set. - */ - if ((flags & DCOPY_POLL_BLOCK) && !(cmd->dp_flags & DCOPY_CMD_INTR)) { - return (DCOPY_FAILURE); - } - - atomic_inc_64(&channel->ch_stat.cs_cmd_poll.value.ui64); - -repoll: - e = channel->ch_cb->cb_cmd_poll(channel->ch_channel_private, cmd); - if (e == DCOPY_PENDING) { - /* - * if the command is still active, and the blocking flag - * is set. - */ - if (flags & DCOPY_POLL_BLOCK) { - - /* - * if we haven't initialized the state, do it now. A - * command can be re-used, so it's possible it's - * already been initialized. - */ - if (!priv->pr_block_init) { - priv->pr_block_init = B_TRUE; - mutex_init(&priv->pr_mutex, NULL, MUTEX_DRIVER, - NULL); - cv_init(&priv->pr_cv, NULL, CV_DRIVER, NULL); - priv->pr_cmd = cmd; - } - - /* push it on the list for blocking commands */ - priv->pr_wait = B_TRUE; - dcopy_list_push(&channel->ch_poll_list, priv); - - mutex_enter(&priv->pr_mutex); - /* - * it's possible we already cleared pr_wait before we - * grabbed the mutex. - */ - if (priv->pr_wait) { - cv_wait(&priv->pr_cv, &priv->pr_mutex); - } - mutex_exit(&priv->pr_mutex); - - /* - * the command has completed, go back and poll so we - * get the status. - */ - goto repoll; - } - } - - return (e); -} - -/* *** END OF EXTERNAL INTERFACE *** */ - -/* - * dcopy_list_init() - */ -static int -dcopy_list_init(dcopy_list_t *list, size_t node_size, offset_t link_offset) -{ - mutex_init(&list->dl_mutex, NULL, MUTEX_DRIVER, NULL); - list_create(&list->dl_list, node_size, link_offset); - list->dl_cnt = 0; - - return (DCOPY_SUCCESS); -} - - -/* - * dcopy_list_fini() - */ -static void -dcopy_list_fini(dcopy_list_t *list) -{ - list_destroy(&list->dl_list); - mutex_destroy(&list->dl_mutex); -} - - -/* - * dcopy_list_push() - */ -static void -dcopy_list_push(dcopy_list_t *list, void *list_node) -{ - mutex_enter(&list->dl_mutex); - list_insert_tail(&list->dl_list, list_node); - list->dl_cnt++; - mutex_exit(&list->dl_mutex); -} - - -/* - * dcopy_list_pop() - */ -static void * -dcopy_list_pop(dcopy_list_t *list) -{ - list_node_t *list_node; - - mutex_enter(&list->dl_mutex); - list_node = list_head(&list->dl_list); - if (list_node == NULL) { - mutex_exit(&list->dl_mutex); - return (list_node); - } - list->dl_cnt--; - list_remove(&list->dl_list, list_node); - mutex_exit(&list->dl_mutex); - - return (list_node); -} - - -/* *** DEVICE INTERFACE *** */ -/* - * dcopy_device_register() - */ -int -dcopy_device_register(void *device_private, dcopy_device_info_t *info, - dcopy_device_handle_t *handle) -{ - struct dcopy_channel_s *channel; - struct dcopy_device_s *device; - int e; - int i; - - - /* initialize the per device state */ - device = kmem_zalloc(sizeof (*device), KM_SLEEP); - device->dc_device_private = device_private; - device->dc_info = *info; - device->dc_removing_cnt = 0; - device->dc_cb = info->di_cb; - - /* - * we have a per device channel list so we can remove a device in the - * future. - */ - e = dcopy_list_init(&device->dc_devchan_list, - sizeof (struct dcopy_channel_s), - offsetof(struct dcopy_channel_s, ch_devchan_list_node)); - if (e != DCOPY_SUCCESS) { - goto registerfail_devchan; - } - - /* - * allocate state for each channel, allocate the channel, and then add - * the devices dma channels to the devices channel list. - */ - for (i = 0; i < info->di_num_dma; i++) { - channel = kmem_zalloc(sizeof (*channel), KM_SLEEP); - channel->ch_device = device; - channel->ch_removing = B_FALSE; - channel->ch_ref_cnt = 0; - channel->ch_cb = info->di_cb; - - e = info->di_cb->cb_channel_alloc(device_private, channel, - DCOPY_SLEEP, dcopy_channel_size, &channel->ch_info, - &channel->ch_channel_private); - if (e != DCOPY_SUCCESS) { - kmem_free(channel, sizeof (*channel)); - goto registerfail_alloc; - } - - e = dcopy_stats_init(channel); - if (e != DCOPY_SUCCESS) { - info->di_cb->cb_channel_free( - &channel->ch_channel_private); - kmem_free(channel, sizeof (*channel)); - goto registerfail_alloc; - } - - e = dcopy_list_init(&channel->ch_poll_list, - sizeof (struct dcopy_cmd_priv_s), - offsetof(struct dcopy_cmd_priv_s, pr_poll_list_node)); - if (e != DCOPY_SUCCESS) { - dcopy_stats_fini(channel); - info->di_cb->cb_channel_free( - &channel->ch_channel_private); - kmem_free(channel, sizeof (*channel)); - goto registerfail_alloc; - } - - dcopy_list_push(&device->dc_devchan_list, channel); - } - - /* add the device to device list */ - dcopy_list_push(&dcopy_statep->d_device_list, device); - - /* - * add the device's dma channels to the global channel list (where - * dcopy_alloc's come from) - */ - mutex_enter(&dcopy_statep->d_globalchan_list.dl_mutex); - mutex_enter(&dcopy_statep->d_device_list.dl_mutex); - channel = list_head(&device->dc_devchan_list.dl_list); - while (channel != NULL) { - list_insert_tail(&dcopy_statep->d_globalchan_list.dl_list, - channel); - dcopy_statep->d_globalchan_list.dl_cnt++; - channel = list_next(&device->dc_devchan_list.dl_list, channel); - } - mutex_exit(&dcopy_statep->d_device_list.dl_mutex); - mutex_exit(&dcopy_statep->d_globalchan_list.dl_mutex); - - *handle = device; - return (DCOPY_SUCCESS); - -registerfail_alloc: - channel = list_head(&device->dc_devchan_list.dl_list); - while (channel != NULL) { - /* remove from the list */ - channel = dcopy_list_pop(&device->dc_devchan_list); - ASSERT(channel != NULL); - - dcopy_list_fini(&channel->ch_poll_list); - dcopy_stats_fini(channel); - info->di_cb->cb_channel_free(&channel->ch_channel_private); - kmem_free(channel, sizeof (*channel)); - } - - dcopy_list_fini(&device->dc_devchan_list); -registerfail_devchan: - kmem_free(device, sizeof (*device)); - - return (DCOPY_FAILURE); -} - - -/* - * dcopy_device_unregister() - */ -/*ARGSUSED*/ -int -dcopy_device_unregister(dcopy_device_handle_t *handle) -{ - struct dcopy_channel_s *channel; - dcopy_device_handle_t device; - boolean_t device_busy; - - - device = *handle; - device_busy = B_FALSE; - - /* - * remove the devices dma channels from the global channel list (where - * dcopy_alloc's come from) - */ - mutex_enter(&dcopy_statep->d_globalchan_list.dl_mutex); - mutex_enter(&device->dc_devchan_list.dl_mutex); - channel = list_head(&device->dc_devchan_list.dl_list); - while (channel != NULL) { - /* - * if the channel has outstanding allocs, mark it as having - * to be removed and increment the number of channels which - * need to be removed in the device state too. - */ - if (channel->ch_ref_cnt != 0) { - channel->ch_removing = B_TRUE; - device_busy = B_TRUE; - device->dc_removing_cnt++; - } - dcopy_statep->d_globalchan_list.dl_cnt--; - list_remove(&dcopy_statep->d_globalchan_list.dl_list, channel); - channel = list_next(&device->dc_devchan_list.dl_list, channel); - } - mutex_exit(&device->dc_devchan_list.dl_mutex); - mutex_exit(&dcopy_statep->d_globalchan_list.dl_mutex); - - /* - * if there are channels which still need to be removed, we will clean - * up the device state after they are freed up. - */ - if (device_busy) { - return (DCOPY_PENDING); - } - - dcopy_device_cleanup(device, B_FALSE); - - *handle = NULL; - return (DCOPY_SUCCESS); -} - - -/* - * dcopy_device_cleanup() - */ -static void -dcopy_device_cleanup(dcopy_device_handle_t device, boolean_t do_callback) -{ - struct dcopy_channel_s *channel; - - /* - * remove all the channels in the device list, free them, and clean up - * the state. - */ - mutex_enter(&dcopy_statep->d_device_list.dl_mutex); - channel = list_head(&device->dc_devchan_list.dl_list); - while (channel != NULL) { - device->dc_devchan_list.dl_cnt--; - list_remove(&device->dc_devchan_list.dl_list, channel); - dcopy_list_fini(&channel->ch_poll_list); - dcopy_stats_fini(channel); - channel->ch_cb->cb_channel_free(&channel->ch_channel_private); - kmem_free(channel, sizeof (*channel)); - channel = list_head(&device->dc_devchan_list.dl_list); - } - - /* remove it from the list of devices */ - list_remove(&dcopy_statep->d_device_list.dl_list, device); - - mutex_exit(&dcopy_statep->d_device_list.dl_mutex); - - /* - * notify the DMA device driver that the device is free to be - * detached. - */ - if (do_callback) { - device->dc_cb->cb_unregister_complete( - device->dc_device_private, DCOPY_SUCCESS); - } - - dcopy_list_fini(&device->dc_devchan_list); - kmem_free(device, sizeof (*device)); -} - - -/* - * dcopy_device_channel_notify() - */ -/*ARGSUSED*/ -void -dcopy_device_channel_notify(dcopy_handle_t handle, int status) -{ - struct dcopy_channel_s *channel; - dcopy_list_t *poll_list; - dcopy_cmd_priv_t priv; - int e; - - - ASSERT(status == DCOPY_COMPLETION); - channel = handle; - - poll_list = &channel->ch_poll_list; - - /* - * when we get a completion notification from the device, go through - * all of the commands blocking on this channel and see if they have - * completed. Remove the command and wake up the block thread if they - * have. Once we hit a command which is still pending, we are done - * polling since commands in a channel complete in order. - */ - mutex_enter(&poll_list->dl_mutex); - if (poll_list->dl_cnt != 0) { - priv = list_head(&poll_list->dl_list); - while (priv != NULL) { - atomic_inc_64(&channel-> - ch_stat.cs_notify_poll.value.ui64); - e = channel->ch_cb->cb_cmd_poll( - channel->ch_channel_private, - priv->pr_cmd); - if (e == DCOPY_PENDING) { - atomic_inc_64(&channel-> - ch_stat.cs_notify_pending.value.ui64); - break; - } - - poll_list->dl_cnt--; - list_remove(&poll_list->dl_list, priv); - - mutex_enter(&priv->pr_mutex); - priv->pr_wait = B_FALSE; - cv_signal(&priv->pr_cv); - mutex_exit(&priv->pr_mutex); - - priv = list_head(&poll_list->dl_list); - } - } - - mutex_exit(&poll_list->dl_mutex); -} - - -/* - * dcopy_stats_init() - */ -static int -dcopy_stats_init(dcopy_handle_t channel) -{ -#define CHANSTRSIZE 20 - char chanstr[CHANSTRSIZE]; - dcopy_stats_t *stats; - int instance; - char *name; - - - stats = &channel->ch_stat; - name = (char *)ddi_driver_name(channel->ch_device->dc_info.di_dip); - instance = ddi_get_instance(channel->ch_device->dc_info.di_dip); - - (void) snprintf(chanstr, CHANSTRSIZE, "channel%d", - (uint32_t)channel->ch_info.qc_chan_num); - - channel->ch_kstat = kstat_create(name, instance, chanstr, "misc", - KSTAT_TYPE_NAMED, sizeof (dcopy_stats_t) / sizeof (kstat_named_t), - KSTAT_FLAG_VIRTUAL); - if (channel->ch_kstat == NULL) { - return (DCOPY_FAILURE); - } - channel->ch_kstat->ks_data = stats; - - kstat_named_init(&stats->cs_bytes_xfer, "bytes_xfer", - KSTAT_DATA_UINT64); - kstat_named_init(&stats->cs_cmd_alloc, "cmd_alloc", - KSTAT_DATA_UINT64); - kstat_named_init(&stats->cs_cmd_post, "cmd_post", - KSTAT_DATA_UINT64); - kstat_named_init(&stats->cs_cmd_poll, "cmd_poll", - KSTAT_DATA_UINT64); - kstat_named_init(&stats->cs_notify_poll, "notify_poll", - KSTAT_DATA_UINT64); - kstat_named_init(&stats->cs_notify_pending, "notify_pending", - KSTAT_DATA_UINT64); - kstat_named_init(&stats->cs_id, "id", - KSTAT_DATA_UINT64); - kstat_named_init(&stats->cs_capabilities, "capabilities", - KSTAT_DATA_UINT64); - - kstat_install(channel->ch_kstat); - - channel->ch_stat.cs_id.value.ui64 = channel->ch_info.qc_id; - channel->ch_stat.cs_capabilities.value.ui64 = - channel->ch_info.qc_capabilities; - - return (DCOPY_SUCCESS); -} - - -/* - * dcopy_stats_fini() - */ -static void -dcopy_stats_fini(dcopy_handle_t channel) -{ - kstat_delete(channel->ch_kstat); -} -/* *** END OF DEVICE INTERFACE *** */ |