freebsd-nq/sys/dev/nxge/xgehal/xgehal-driver.c
Robert Watson 3be4cb0b4a Merge Neterion if_nxge driver version 2.0.9.11230 with the following
changes:

  01 -  Enhanced LRO:
  LRO feature is extended to support multi-buffer mode. Previously,
  Ethernet frames received in contiguous buffers were offloaded.
  Now, frames received in multiple non-contiguous buffers can be
  offloaded, as well. The driver now supports LRO for jumbo frames.

  02 - Locks Optimization:
  The driver code was re-organized to limit the use of locks.
  Moreover, lock contention was reduced by replacing wait locks
  with try locks.

  03 - Code Optimization:
  The driver code was re-factored  to eliminate some memcpy
  operations.  Fast path loops were optimized.

  04 - Tag Creations:
  Physical Buffer Tags are now optimized based upon frame size.
  For better performance, Physical Memory Maps are now re-used.

  05 - Configuration:
  Features such as TSO, LRO, and Interrupt Mode can be configured
  either at load or at run time. Rx buffer mode (mode 1 or mode 2)
  can be configured at load time through kenv.

  06 - Driver Statistics:
  Run time statistics are enhanced to provide better visibility
  into the driver performance.

  07 - Bug Fixes:
  The driver contains fixes for the problems discovered and
  reported since last submission.

  08 - MSI support:
  Added Message Signaled Interrupt feature which currently uses 1
  message.

  09  Removed feature:
  Rx 3 buffer mode feature has been removed. Driver now supports 1,
  2 and 5 buffer modes of which 2 and 5 buffer modes can be used
  for header separation.

  10  Compiler warning:
  Fixed compiler warning when compiled for 32 bit system.

  11 Copyright notice:
  Source files are updated with the proper copyright notice.

MFC after:	3 days
Submitted by:	Alicia Pena <Alicia dot Pena at neterion dot com>,
		Muhammad Shafiq <Muhammad dot Shafiq at neterion dot com>
2007-10-29 14:19:32 +00:00

293 lines
8.8 KiB
C

/*-
* Copyright (c) 2002-2007 Neterion, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <dev/nxge/include/xgehal-driver.h>
#include <dev/nxge/include/xgehal-device.h>
static xge_hal_driver_t g_driver;
xge_hal_driver_t *g_xge_hal_driver = NULL;
char *g_xge_hal_log = NULL;
#ifdef XGE_OS_MEMORY_CHECK
xge_os_malloc_t g_malloc_arr[XGE_OS_MALLOC_CNT_MAX];
int g_malloc_cnt = 0;
#endif
/*
* Runtime tracing support
*/
static unsigned long g_module_mask_default = 0;
unsigned long *g_module_mask = &g_module_mask_default;
static int g_level_default = 0;
int *g_level = &g_level_default;
#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
static xge_os_tracebuf_t g_tracebuf;
char *dmesg, *dmesg_start;
/**
* xge_hal_driver_tracebuf_dump - Dump the trace buffer.
*
* Dump the trace buffer contents.
*/
void
xge_hal_driver_tracebuf_dump(void)
{
int i;
int off = 0;
if (g_xge_os_tracebuf == NULL) {
return;
}
xge_os_printf("################ Trace dump Begin ###############");
if (g_xge_os_tracebuf->wrapped_once) {
for (i = 0; i < g_xge_os_tracebuf->size -
g_xge_os_tracebuf->offset; i += off) {
if (*(dmesg_start + i))
xge_os_printf(dmesg_start + i);
off = xge_os_strlen(dmesg_start + i) + 1;
}
}
for (i = 0; i < g_xge_os_tracebuf->offset; i += off) {
if (*(dmesg + i))
xge_os_printf(dmesg + i);
off = xge_os_strlen(dmesg + i) + 1;
}
xge_os_printf("################ Trace dump End ###############");
}
xge_hal_status_e
xge_hal_driver_tracebuf_read(int bufsize, char *retbuf, int *retsize)
{
int i;
int off = 0, retbuf_off = 0;
*retsize = 0;
*retbuf = 0;
if (g_xge_os_tracebuf == NULL) {
return XGE_HAL_FAIL;
}
if (g_xge_os_tracebuf->wrapped_once) {
for (i = 0; i < g_xge_os_tracebuf->size -
g_xge_os_tracebuf->offset; i += off) {
if (*(dmesg_start + i)) {
xge_os_sprintf(retbuf + retbuf_off, "%s\n", dmesg_start + i);
retbuf_off += xge_os_strlen(dmesg_start + i) + 1;
if (retbuf_off > bufsize)
return XGE_HAL_ERR_OUT_OF_MEMORY;
}
off = xge_os_strlen(dmesg_start + i) + 1;
}
}
for (i = 0; i < g_xge_os_tracebuf->offset; i += off) {
if (*(dmesg + i)) {
xge_os_sprintf(retbuf + retbuf_off, "%s\n", dmesg + i);
retbuf_off += xge_os_strlen(dmesg + i) + 1;
if (retbuf_off > bufsize)
return XGE_HAL_ERR_OUT_OF_MEMORY;
}
off = xge_os_strlen(dmesg + i) + 1;
}
*retsize = retbuf_off;
*(retbuf + retbuf_off + 1) = 0;
return XGE_HAL_OK;
}
#endif
xge_os_tracebuf_t *g_xge_os_tracebuf = NULL;
#ifdef XGE_HAL_DEBUG_BAR0_OFFSET
void
xge_hal_driver_bar0_offset_check(void)
{
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, adapter_status) ==
0x108);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, tx_traffic_int) ==
0x08E0);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, dtx_control) ==
0x09E8);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, tx_fifo_partition_0) ==
0x1108);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, pcc_enable) ==
0x1170);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, prc_rxd0_n[0]) ==
0x1930);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rti_command_mem) ==
0x19B8);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_cfg) ==
0x2100);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rmac_addr_cmd_mem) ==
0x2128);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_link_util) ==
0x2170);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mc_pause_thresh_q0q3) ==
0x2918);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, pcc_err_reg) ==
0x1040);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rxdma_int_status) ==
0x1800);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_tmac_err_reg) ==
0x2010);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mc_err_reg) ==
0x2810);
xge_assert(xge_offsetof(xge_hal_pci_bar0_t, xgxs_int_status) ==
0x3000);
}
#endif
/**
* xge_hal_driver_initialize - Initialize HAL.
* @config: HAL configuration, see xge_hal_driver_config_t{}.
* @uld_callbacks: Upper-layer driver callbacks, e.g. link-up.
*
* HAL initialization entry point. Not to confuse with device initialization
* (note that HAL "contains" zero or more Xframe devices).
*
* Returns: XGE_HAL_OK - success;
* XGE_HAL_ERR_BAD_DRIVER_CONFIG - Driver configuration params invalid.
*
* See also: xge_hal_device_initialize(), xge_hal_status_e{},
* xge_hal_uld_cbs_t{}.
*/
xge_hal_status_e
xge_hal_driver_initialize(xge_hal_driver_config_t *config,
xge_hal_uld_cbs_t *uld_callbacks)
{
xge_hal_status_e status;
g_xge_hal_driver = &g_driver;
xge_hal_driver_debug_module_mask_set(XGE_DEBUG_MODULE_MASK_DEF);
xge_hal_driver_debug_level_set(XGE_DEBUG_LEVEL_DEF);
#ifdef XGE_HAL_DEBUG_BAR0_OFFSET
xge_hal_driver_bar0_offset_check();
#endif
#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
if (config->tracebuf_size == 0)
/*
* Trace buffer implementation is not lock protected.
* The only harm to expect is memcpy() to go beyond of
* allowed boundaries. To make it safe (driver-wise),
* we pre-allocate needed number of extra bytes.
*/
config->tracebuf_size = XGE_HAL_DEF_CIRCULAR_ARR +
XGE_OS_TRACE_MSGBUF_MAX;
#endif
status = __hal_driver_config_check(config);
if (status != XGE_HAL_OK)
return status;
xge_os_memzero(g_xge_hal_driver, sizeof(xge_hal_driver_t));
/* apply config */
xge_os_memcpy(&g_xge_hal_driver->config, config,
sizeof(xge_hal_driver_config_t));
/* apply ULD callbacks */
xge_os_memcpy(&g_xge_hal_driver->uld_callbacks, uld_callbacks,
sizeof(xge_hal_uld_cbs_t));
g_xge_hal_driver->is_initialized = 1;
#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
g_tracebuf.size = config->tracebuf_size;
g_tracebuf.data = (char *)xge_os_malloc(NULL, g_tracebuf.size);
if (g_tracebuf.data == NULL) {
xge_os_printf("cannot allocate trace buffer!");
return XGE_HAL_ERR_OUT_OF_MEMORY;
}
/* timestamps disabled by default */
g_tracebuf.timestamp = config->tracebuf_timestamp_en;
if (g_tracebuf.timestamp) {
xge_os_timestamp(g_tracebuf.msg);
g_tracebuf.msgbuf_max = XGE_OS_TRACE_MSGBUF_MAX -
xge_os_strlen(g_tracebuf.msg);
} else
g_tracebuf.msgbuf_max = XGE_OS_TRACE_MSGBUF_MAX;
g_tracebuf.offset = 0;
*g_tracebuf.msg = 0;
xge_os_memzero(g_tracebuf.data, g_tracebuf.size);
g_xge_os_tracebuf = &g_tracebuf;
dmesg = g_tracebuf.data;
*dmesg = 0;
#endif
return XGE_HAL_OK;
}
/**
* xge_hal_driver_terminate - Terminate HAL.
*
* HAL termination entry point.
*
* See also: xge_hal_device_terminate().
*/
void
xge_hal_driver_terminate(void)
{
g_xge_hal_driver->is_initialized = 0;
#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
if (g_tracebuf.size) {
xge_os_free(NULL, g_tracebuf.data, g_tracebuf.size);
}
#endif
g_xge_hal_driver = NULL;
#ifdef XGE_OS_MEMORY_CHECK
{
int i, leaks=0;
xge_os_printf("OSPAL: max g_malloc_cnt %d", g_malloc_cnt);
for (i=0; i<g_malloc_cnt; i++) {
if (g_malloc_arr[i].ptr != NULL) {
xge_os_printf("OSPAL: memory leak detected at "
"%s:%d:"XGE_OS_LLXFMT":%d",
g_malloc_arr[i].file,
g_malloc_arr[i].line,
(unsigned long long)(ulong_t)
g_malloc_arr[i].ptr,
g_malloc_arr[i].size);
leaks++;
}
}
if (leaks) {
xge_os_printf("OSPAL: %d memory leaks detected", leaks);
} else {
xge_os_printf("OSPAL: no memory leaks detected");
}
}
#endif
}