hxge_ndd.c revision 1667122dc3c9d4356089cb2f8f9b2e9f2d7fa604
/*
* 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
* 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.
*/
#include <hxge_impl.h>
extern uint64_t hpi_debug_level;
#define HXGE_PARAM_MAC_RW \
HXGE_PARAM_RW | HXGE_PARAM_MAC | \
#define HXGE_PARAM_L2CLASS_CFG \
#define HXGE_PARAM_CLASS_RWS \
#define HXGE_PARAM_ARRAY_INIT_SIZE 0x20ULL
#define BASE_ANY 0
#define BASE_BINARY 2
#define BASE_HEX 16
#define BASE_DECIMAL 10
#define ALL_FF_64 0xFFFFFFFFFFFFFFFFULL
#define ALL_FF_32 0xFFFFFFFFUL
#define HXGE_NDD_INFODUMP_BUFF_8K 8192
#define HXGE_NDD_INFODUMP_BUFF_16K 0x2000
#define HXGE_NDD_INFODUMP_BUFF_64K 0x8000
}
char *, caddr_t);
/*
* Global array of Hydra changable parameters.
* This array is initialized to correspond to the default
* Hydra configuration. This array would be copied
* into the parameter structure and modifed per
* fcode and hxge.conf configuration. Later, the parameters are
* exported to ndd to display and run-time configuration (at least
* some of them).
*/
static hxge_param_t hxge_param_arr[] = {
/* min max value old hw-name conf-name */
0, 999, 1000, 0, "instance", "instance"},
/* MTU cannot be propagated to the stack from here, so don't show it */
0, 1, 0, 0, "accept-jumbo", "accept_jumbo"},
"rx-rbr-size", "rx_rbr_size"},
"rx-rcr-size", "rx_rcr_size"},
"rxdma-intr-pkts", "rxdma_intr_pkts"},
/* Hardware VLAN is not used currently, so don't show it */
/* Hardware VLAN is not used currently, so don't show it */
"implicit-vlan-id", "implicit_vlan_id"},
0, 0x1, 0x0, 0, "tcam-enable", "tcam_enable"},
"hash-init-value", "hash_init_value"},
0, ALL_FF_32, 0x0, 0,
"class-cfg-ether-usr1", "class_cfg_ether_usr1"},
0, ALL_FF_32, 0x0, 0,
"class-cfg-ether-usr2", "class_cfg_ether_usr2"},
0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
"class-opt-ipv4-tcp", "class_opt_ipv4_tcp"},
0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
"class-opt-ipv4-udp", "class_opt_ipv4_udp"},
0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
"class-opt-ipv4-ah", "class_opt_ipv4_ah"},
0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
"class-opt-ipv4-sctp", "class_opt_ipv4_sctp"},
0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
"class-opt-ipv6-tcp", "class_opt_ipv6_tcp"},
0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
"class-opt-ipv6-udp", "class_opt_ipv6_udp"},
0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
"class-opt-ipv6-ah", "class_opt_ipv6_ah"},
0, ALL_FF_32, HXGE_CLASS_TCAM_LOOKUP, 0,
"class-opt-ipv6-sctp", "class_opt_ipv6_sctp"},
"hxge-debug-flag", "hxge_debug_flag"},
"hpi-debug-flag", "hpi_debug_flag"},
0, 0x0fffffff, 0x0fffffff, 0, "dump-ptrs", "dump_ptrs"},
0, 0x0fffffff, 0x0fffffff, 0, "end", "end"},
};
extern void *hxge_list;
/*
* Update the NDD array from the soft properties.
*/
void
{
int i, j;
for (i = 0; i < param_count; i++) {
continue;
continue;
#if defined(__i386)
#else
#endif
for (j = 0; j < prop_len; j++) {
cfg_value[j] = int_prop_val[j];
}
}
continue;
}
&prop_len) == DDI_PROP_SUCCESS) {
}
}
}
}
static int
{
int channel;
char *prop_name;
char *end;
return (B_TRUE);
return (B_TRUE);
else
return (B_FALSE);
}
prop_name += name_chars;
/* now check if this rdc is in config */
" hxge_private_param_register: %d", channel));
}
return (B_FALSE);
}
return (status);
}
void
{
int i;
/*
* Make sure the param_instance is set to a valid device instance.
*/
for (i = 0; i < hxgep->param_count; i++) {
B_FALSE)) {
}
}
}
break;
}
}
}
/*
* Called from the attached function, it allocates memory for
* the parameter array and some members.
*/
void
{
int i, alloc_size;
/*
* Make sure the param_instance is set to a valid device instance.
*/
sizeof (hxge_param_arr), KM_SLEEP);
}
for (i = 0; i < sizeof (hxge_param_arr) / sizeof (hxge_param_t); i++) {
param_arr[i] = hxge_param_arr[i];
#if defined(__i386)
KM_SLEEP);
KM_SLEEP);
#else
#endif
}
}
hxgep->param_count));
}
/*
* Called from the attached functions, it frees memory for the parameter array
*/
void
{
int i;
/*
* Make sure the param_instance is set to a valid device instance.
*/
break;
}
}
if (hxgep->param_list)
for (i = 0; i < hxgep->param_count; i++) {
#if defined(__i386)
#else
#endif
}
}
}
/*
* Extracts the value from the 'hxge' parameter array and prints the
* parameter value. cp points to the required parameter.
*/
/* ARGSUSED */
int
{
else
return (0);
}
/* ARGSUSED */
static int
{
return (0);
}
/* ARGSUSED */
int
{
int rdc;
/* The following may work even if we cannot get a large buf. */
return (0);
}
"RDC\t HW RDC\t Timeout\t Packets RBR ptr \t"
"chunks\t RCR ptr\n");
" %d\t %d\t $%p\t 0x%x\t $%p\n",
}
return (0);
}
int
{
if (!tmp)
return (ENOMEM);
}
return (0);
}
/*
* Sets the ge parameter to the value in the hxge_param_register using
* hxge_nd_load().
*/
/* ARGSUSED */
int
{
char *end;
return (EINVAL);
}
return (0);
}
/* ARGSUSED */
int
{
char *end;
int status = 0;
return (EINVAL);
}
}
(void) hxge_rx_vmac_disable(hxgep);
(void) hxge_tx_vmac_disable(hxgep);
/*
* Apply the new jumbo parameter here.
* The order of the following two calls is important.
*/
(void) hxge_tx_vmac_enable(hxgep);
(void) hxge_rx_vmac_enable(hxgep);
}
return (status);
}
/* ARGSUSED */
int
{
char *end;
value += 2;
if ((cfg_value > HXGE_RDC_RCR_THRESHOLD_MAX) ||
return (EINVAL);
}
}
return (0);
}
/* ARGSUSED */
int
{
char *end;
value += 2;
if ((cfg_value > HXGE_RDC_RCR_TIMEOUT_MAX) ||
return (EINVAL);
}
}
return (0);
}
/* ARGSUSED */
static int
{
char *end;
int i, inc = 0, cfg_position;
value += 2;
/* now do decoding */
if (cfgd_vlans >= HXGE_PARAM_ARRAY_INIT_SIZE) {
/*
* for now, we process only upto HXGE_PARAM_ARRAY_INIT_SIZE
* parameters In the future, we may want to expand
* the storage array and continue
*/
return (EINVAL);
}
return (EINVAL);
}
#if defined(__i386)
#else
#endif
/* Search to see if this vlan id is already configured */
for (i = 0; i < cfgd_vlans; i++) {
cfg_position = i;
break;
}
}
if (cfgd_vlans == 0) {
cfg_position = 0;
inc++;
}
if (i == cfgd_vlans) {
cfg_position = i;
inc++;
}
" set_vlan_ids mapping i %d cfgd_vlans %llx position %d ",
i, cfgd_vlans, cfg_position));
if (inc) {
cfgd_vlans++;
}
" after: param_set_vlan_ids cfg_vlans %llx position %d \n",
}
if (status != HPI_SUCCESS)
return (EINVAL);
}
return (0);
}
/* ARGSUSED */
static int
{
int i;
uint64_t cfgd_vlans = 0;
return (0);
}
i = (int)cfgd_vlans;
"Configured VLANs %d\n VLAN ID\n", i);
#if defined(__i386)
#else
#endif
for (i = 0; i < cfgd_vlans; i++) {
}
}
return (0);
}
/* ARGSUSED */
static int
{
char *end;
}
else
return (EINVAL);
}
return (0);
}
/* ARGSUSED */
static int
{
char *end;
value += 2;
return (EINVAL);
}
}
return (status);
}
static int
{
int i;
for (i = TCAM_CLASS_TCP_IPV4; i <= TCAM_CLASS_SCTP_IPV6; i++) {
return (i);
}
return (-1);
}
/* ARGSUSED */
int
{
char *end;
value += 2;
return (EINVAL);
}
}
/* do the actual hw setup */
if (class == -1)
return (EINVAL);
return (EINVAL);
}
return (0);
}
/* ARGSUSED */
int
{
/* do the actual hw setup */
if (class == -1)
return (EINVAL);
cfg_value = 0;
return (EINVAL);
"hxge_param_get_ip_opt_get %x ", cfg_value));
return (0);
}
/* ARGSUSED */
static int
{
char *end;
value += 2;
return (EINVAL);
}
" hxge_param_pfc_hash_init value %x", cfg_value));
}
return (EINVAL);
}
return (0);
}
/* ARGSUSED */
static int
{
char *end;
value += 2;
" hxge_param_set_hxge_debug_flag"
" outof range %llx", cfg_value));
return (EINVAL);
}
}
return (status);
}
/* ARGSUSED */
static int
{
int status = 0;
else
return (status);
}
/* ARGSUSED */
static int
{
char *end;
value += 2;
" outof range %llx", cfg_value));
return (EINVAL);
}
}
}
return (status);
}
typedef struct block_info {
char *name;
} block_info_t;
block_info_t reg_block[] = {
{"PIO", PIO_BASE_ADDR},
{"PIO_LDSV", PIO_LDSV_BASE_ADDR},
{"PIO_LDMASK", PIO_LDMASK_BASE_ADDR},
{"PFC", PFC_BASE_ADDR},
{"RDC", RDC_BASE_ADDR},
{"TDC", TDC_BASE_ADDR},
{"VMAC", VMAC_BASE_ADDR},
{"END", ALL_FF_32},
};
/* ARGSUSED */
static int
{
/* The following may work even if we cannot get a large buf. */
return (0);
}
"hxgep (hxge_t) $%p\n dev_regs (dev_regs_t) $%p\n",
/* do register pointers */
"reg base (hpi_reg_ptr_t) $%p\t pci reg (hpi_reg_ptr_t) $%p\n",
"\nBlock \t Offset \n");
block = 0;
#if defined(__i386)
#else
#endif
block++;
}
"\nRDC\t rcrp (rx_rcr_ring_t)\t rbrp (rx_rbr_ring_t)\n");
" %d\t $%p\t\t $%p\n",
}
"\nTDC\t tdcp (tx_ring_t)\n");
}
return (0);
}
/*
* Load 'name' into the named dispatch table pointed to by 'ndp'.
* 'ndp' should be the address of a char pointer cell. If the table
* does not exist (*ndp == 0), a new table is allocated and 'ndp'
* is stuffed. If there is not enough space in the table for a new
* entry, more space is allocated.
*/
{
if (!pparam)
return (B_FALSE);
return (B_FALSE);
}
goto fill_it;
}
}
return (B_FALSE);
} else {
nd->nd_free_count--;
}
}
noop;
nd->nd_free_count--;
return (B_TRUE);
}
/*
* Free the table pointed to by 'pparam'
*/
void
{
}
}
int
{
int err;
char *valp;
if (!param) {
return (B_FALSE);
}
return (B_FALSE);
}
/*
* NOTE - logic throughout nd_xxx assumes single data block for ioctl.
* However, existing code sends in some big buffers.
*/
}
if (*valp == '-')
*valp = '_';
}
return (B_FALSE);
break;
}
while (*valp++)
noop;
case ND_GET:
return (B_FALSE);
/*
* (temporary) hack: "*valp" is size of user buffer for
* copyout. If result of action routine is too big, free excess
* and return ioc_rval as buffer size needed. Return as many
* mblocks as will fit, free the rest. For backward
* compatibility, assume size of original ioctl buffer if
* "*valp" bad or not given.
*/
if (valp)
/*
*/
while (mp2) {
}
if (!err) {
/* Tack on the null */
if (!err) {
if (excess > 0) {
if (!err)
else
size_out = 0;
}
} else
size_out = 0;
}
break;
case ND_SET:
if (valp) {
if (nde->nde_set_pfi) {
}
}
break;
default:
break;
}
return (B_TRUE);
}
/* ARGSUSED */
int
{
char *rwtag;
int status = 0;
if (!nd)
return (ENOENT);
if (get_ok) {
if (set_ok)
rwtag = "read and write";
else
rwtag = "read only";
} else if (set_ok)
rwtag = "write only";
else {
continue;
}
param_len += 4;
}
return (status);
}
/* ARGSUSED */
int
{
return (EACCES);
}
/* ARGSUSED */
int
{
return (EACCES);
}
void
{
int cmd;
switch (cmd) {
default:
"hxge_param_ioctl: bad cmd 0x%0x", cmd));
break;
case ND_GET:
case ND_SET:
"hxge_param_ioctl: cmd 0x%0x", cmd));
"false ret from hxge_nd_getset"));
break;
}
break;
}
if (status) {
} else {
}
}