diff options
Diffstat (limited to 'sys/dev/nxge')
41 files changed, 33856 insertions, 0 deletions
diff --git a/sys/dev/nxge/if_nxge.c b/sys/dev/nxge/if_nxge.c new file mode 100644 index 0000000..6687b4b --- /dev/null +++ b/sys/dev/nxge/if_nxge.c @@ -0,0 +1,3415 @@ +/*- + * 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$ + */ + +/* + * if_nxge.c + * + * FreeBSD specific initialization & routines + */ + +#include <dev/nxge/if_nxge.h> +#include <dev/nxge/xge-osdep.h> +#include <net/if_arp.h> +#include <sys/types.h> +#include <net/if.h> +#include <net/if_vlan_var.h> + +int copyright_print = 0; +int hal_driver_init_count = 0; +size_t size = sizeof(int); + +/****************************************** + * xge_probe + * Parameters: Device structure + * Return: BUS_PROBE_DEFAULT/ENXIO/ENOMEM + * Description: Probes for Xframe device + ******************************************/ +int +xge_probe(device_t dev) +{ + int devid = pci_get_device(dev); + int vendorid = pci_get_vendor(dev); + int retValue = ENXIO; + + ENTER_FUNCTION + + if(vendorid == XGE_PCI_VENDOR_ID) { + if((devid == XGE_PCI_DEVICE_ID_XENA_2) || + (devid == XGE_PCI_DEVICE_ID_HERC_2)) { + if(!copyright_print) { + PRINT_COPYRIGHT; + copyright_print = 1; + } + device_set_desc_copy(dev, + "Neterion Xframe 10 Gigabit Ethernet Adapter"); + retValue = BUS_PROBE_DEFAULT; + } + } + + LEAVE_FUNCTION + return retValue; +} + +/****************************************** + * xge_init_params + * Parameters: HAL device configuration + * structure, device pointer + * Return: None + * Description: Sets parameter values in + * xge_hal_device_config_t structure + ******************************************/ +void +xge_init_params(xge_hal_device_config_t *dconfig, device_t dev) +{ + int index, revision; + device_t checkdev; + + ENTER_FUNCTION + +#define SAVE_PARAM(to, what, value) to.what = value; + +#define GET_PARAM(str_kenv, to, param, hardcode) { \ + static int param##__LINE__; \ + if(testenv(str_kenv) == 1) { \ + getenv_int(str_kenv, ¶m##__LINE__); \ + } \ + else { \ + param##__LINE__ = hardcode; \ + } \ + SAVE_PARAM(to, param, param##__LINE__); \ +} + +#define GET_PARAM_MAC(str_kenv, param, hardcode) \ + GET_PARAM(str_kenv, ((*dconfig).mac), param, hardcode); + +#define GET_PARAM_FIFO(str_kenv, param, hardcode) \ + GET_PARAM(str_kenv, ((*dconfig).fifo), param, hardcode); + +#define GET_PARAM_FIFO_QUEUE(str_kenv, param, qindex, hardcode) \ + GET_PARAM(str_kenv, ((*dconfig).fifo.queue[qindex]), param, hardcode); + +#define GET_PARAM_FIFO_QUEUE_TTI(str_kenv, param, qindex, tindex, hardcode) \ + GET_PARAM(str_kenv, ((*dconfig).fifo.queue[qindex].tti[tindex]), \ + param, hardcode); + +#define GET_PARAM_RING(str_kenv, param, hardcode) \ + GET_PARAM(str_kenv, ((*dconfig).ring), param, hardcode); + +#define GET_PARAM_RING_QUEUE(str_kenv, param, qindex, hardcode) \ + GET_PARAM(str_kenv, ((*dconfig).ring.queue[qindex]), param, hardcode); + +#define GET_PARAM_RING_QUEUE_RTI(str_kenv, param, qindex, hardcode) \ + GET_PARAM(str_kenv, ((*dconfig).ring.queue[qindex].rti), param, \ + hardcode); + + dconfig->mtu = XGE_DEFAULT_INITIAL_MTU; + dconfig->pci_freq_mherz = XGE_DEFAULT_USER_HARDCODED; + dconfig->device_poll_millis = XGE_HAL_DEFAULT_DEVICE_POLL_MILLIS; + dconfig->link_stability_period = XGE_HAL_DEFAULT_LINK_STABILITY_PERIOD; + dconfig->mac.rmac_bcast_en = XGE_DEFAULT_MAC_RMAC_BCAST_EN; + dconfig->fifo.alignment_size = XGE_DEFAULT_FIFO_ALIGNMENT_SIZE; + + GET_PARAM("hw.xge.latency_timer", (*dconfig), latency_timer, + XGE_DEFAULT_LATENCY_TIMER); + GET_PARAM("hw.xge.max_splits_trans", (*dconfig), max_splits_trans, + XGE_DEFAULT_MAX_SPLITS_TRANS); + GET_PARAM("hw.xge.mmrb_count", (*dconfig), mmrb_count, + XGE_DEFAULT_MMRB_COUNT); + GET_PARAM("hw.xge.shared_splits", (*dconfig), shared_splits, + XGE_DEFAULT_SHARED_SPLITS); + GET_PARAM("hw.xge.isr_polling_cnt", (*dconfig), isr_polling_cnt, + XGE_DEFAULT_ISR_POLLING_CNT); + GET_PARAM("hw.xge.stats_refresh_time_sec", (*dconfig), + stats_refresh_time_sec, XGE_DEFAULT_STATS_REFRESH_TIME_SEC); + + GET_PARAM_MAC("hw.xge.mac_tmac_util_period", tmac_util_period, + XGE_DEFAULT_MAC_TMAC_UTIL_PERIOD); + GET_PARAM_MAC("hw.xge.mac_rmac_util_period", rmac_util_period, + XGE_DEFAULT_MAC_RMAC_UTIL_PERIOD); + GET_PARAM_MAC("hw.xge.mac_rmac_pause_gen_en", rmac_pause_gen_en, + XGE_DEFAULT_MAC_RMAC_PAUSE_GEN_EN); + GET_PARAM_MAC("hw.xge.mac_rmac_pause_rcv_en", rmac_pause_rcv_en, + XGE_DEFAULT_MAC_RMAC_PAUSE_RCV_EN); + GET_PARAM_MAC("hw.xge.mac_rmac_pause_time", rmac_pause_time, + XGE_DEFAULT_MAC_RMAC_PAUSE_TIME); + GET_PARAM_MAC("hw.xge.mac_mc_pause_threshold_q0q3", + mc_pause_threshold_q0q3, XGE_DEFAULT_MAC_MC_PAUSE_THRESHOLD_Q0Q3); + GET_PARAM_MAC("hw.xge.mac_mc_pause_threshold_q4q7", + mc_pause_threshold_q4q7, XGE_DEFAULT_MAC_MC_PAUSE_THRESHOLD_Q4Q7); + + GET_PARAM_FIFO("hw.xge.fifo_memblock_size", memblock_size, + XGE_DEFAULT_FIFO_MEMBLOCK_SIZE); + GET_PARAM_FIFO("hw.xge.fifo_reserve_threshold", reserve_threshold, + XGE_DEFAULT_FIFO_RESERVE_THRESHOLD); + GET_PARAM_FIFO("hw.xge.fifo_max_frags", max_frags, + XGE_DEFAULT_FIFO_MAX_FRAGS); + + GET_PARAM_FIFO_QUEUE("hw.xge.fifo_queue_intr", intr, 0, + XGE_DEFAULT_FIFO_QUEUE_INTR); + GET_PARAM_FIFO_QUEUE("hw.xge.fifo_queue_max", max, 0, + XGE_DEFAULT_FIFO_QUEUE_MAX); + GET_PARAM_FIFO_QUEUE("hw.xge.fifo_queue_initial", initial, 0, + XGE_DEFAULT_FIFO_QUEUE_INITIAL); + + for (index = 0; index < XGE_HAL_MAX_FIFO_TTI_NUM; index++) { + dconfig->fifo.queue[0].tti[index].enabled = 1; + dconfig->fifo.queue[0].configured = 1; + + GET_PARAM_FIFO_QUEUE_TTI("hw.xge.fifo_queue_tti_urange_a", + urange_a, 0, index, XGE_DEFAULT_FIFO_QUEUE_TTI_URANGE_A); + GET_PARAM_FIFO_QUEUE_TTI("hw.xge.fifo_queue_tti_urange_b", + urange_b, 0, index, XGE_DEFAULT_FIFO_QUEUE_TTI_URANGE_B); + GET_PARAM_FIFO_QUEUE_TTI("hw.xge.fifo_queue_tti_urange_c", + urange_c, 0, index, XGE_DEFAULT_FIFO_QUEUE_TTI_URANGE_C); + GET_PARAM_FIFO_QUEUE_TTI("hw.xge.fifo_queue_tti_ufc_a", + ufc_a, 0, index, XGE_DEFAULT_FIFO_QUEUE_TTI_UFC_A); + GET_PARAM_FIFO_QUEUE_TTI("hw.xge.fifo_queue_tti_ufc_b", + ufc_b, 0, index, XGE_DEFAULT_FIFO_QUEUE_TTI_UFC_B); + GET_PARAM_FIFO_QUEUE_TTI("hw.xge.fifo_queue_tti_ufc_c", + ufc_c, 0, index, XGE_DEFAULT_FIFO_QUEUE_TTI_UFC_C); + GET_PARAM_FIFO_QUEUE_TTI("hw.xge.fifo_queue_tti_ufc_d", + ufc_d, 0, index, XGE_DEFAULT_FIFO_QUEUE_TTI_UFC_D); + GET_PARAM_FIFO_QUEUE_TTI("hw.xge.fifo_queue_tti_timer_ci_en", + timer_ci_en, 0, index, XGE_DEFAULT_FIFO_QUEUE_TTI_TIMER_CI_EN); + GET_PARAM_FIFO_QUEUE_TTI("hw.xge.fifo_queue_tti_timer_ac_en", + timer_ac_en, 0, index, XGE_DEFAULT_FIFO_QUEUE_TTI_TIMER_AC_EN); + GET_PARAM_FIFO_QUEUE_TTI("hw.xge.fifo_queue_tti_timer_val_us", + timer_val_us, 0, index, + XGE_DEFAULT_FIFO_QUEUE_TTI_TIMER_VAL_US); + } + + GET_PARAM_RING("hw.xge.ring_memblock_size", memblock_size, + XGE_DEFAULT_RING_MEMBLOCK_SIZE); + + GET_PARAM_RING("hw.xge.ring_strip_vlan_tag", strip_vlan_tag, + XGE_DEFAULT_RING_STRIP_VLAN_TAG); + + for (index = 0; index < XGE_HAL_MIN_RING_NUM; index++) { + dconfig->ring.queue[index].max_frm_len = XGE_HAL_RING_USE_MTU; + dconfig->ring.queue[index].priority = 0; + dconfig->ring.queue[index].configured = 1; + dconfig->ring.queue[index].buffer_mode = + XGE_HAL_RING_QUEUE_BUFFER_MODE_1; + + GET_PARAM_RING_QUEUE("hw.xge.ring_queue_max", max, index, + XGE_DEFAULT_RING_QUEUE_MAX); + GET_PARAM_RING_QUEUE("hw.xge.ring_queue_initial", initial, index, + XGE_DEFAULT_RING_QUEUE_INITIAL); + GET_PARAM_RING_QUEUE("hw.xge.ring_queue_dram_size_mb", dram_size_mb, + index, XGE_DEFAULT_RING_QUEUE_DRAM_SIZE_MB); + GET_PARAM_RING_QUEUE("hw.xge.ring_queue_indicate_max_pkts", + indicate_max_pkts, index, + XGE_DEFAULT_RING_QUEUE_INDICATE_MAX_PKTS); + GET_PARAM_RING_QUEUE("hw.xge.ring_queue_backoff_interval_us", + backoff_interval_us, index, + XGE_DEFAULT_RING_QUEUE_BACKOFF_INTERVAL_US); + + GET_PARAM_RING_QUEUE_RTI("hw.xge.ring_queue_rti_ufc_a", ufc_a, + index, XGE_DEFAULT_RING_QUEUE_RTI_UFC_A); + GET_PARAM_RING_QUEUE_RTI("hw.xge.ring_queue_rti_ufc_b", ufc_b, + index, XGE_DEFAULT_RING_QUEUE_RTI_UFC_B); + GET_PARAM_RING_QUEUE_RTI("hw.xge.ring_queue_rti_ufc_c", ufc_c, + index, XGE_DEFAULT_RING_QUEUE_RTI_UFC_C); + GET_PARAM_RING_QUEUE_RTI("hw.xge.ring_queue_rti_ufc_d", ufc_d, + index, XGE_DEFAULT_RING_QUEUE_RTI_UFC_D); + GET_PARAM_RING_QUEUE_RTI("hw.xge.ring_queue_rti_timer_ac_en", + timer_ac_en, index, XGE_DEFAULT_RING_QUEUE_RTI_TIMER_AC_EN); + GET_PARAM_RING_QUEUE_RTI("hw.xge.ring_queue_rti_timer_val_us", + timer_val_us, index, XGE_DEFAULT_RING_QUEUE_RTI_TIMER_VAL_US); + GET_PARAM_RING_QUEUE_RTI("hw.xge.ring_queue_rti_urange_a", urange_a, + index, XGE_DEFAULT_RING_QUEUE_RTI_URANGE_A); + GET_PARAM_RING_QUEUE_RTI("hw.xge.ring_queue_rti_urange_b", urange_b, + index, XGE_DEFAULT_RING_QUEUE_RTI_URANGE_B); + GET_PARAM_RING_QUEUE_RTI("hw.xge.ring_queue_rti_urange_c", urange_c, + index, XGE_DEFAULT_RING_QUEUE_RTI_URANGE_C); + } + + if(dconfig->fifo.max_frags > (PAGE_SIZE/32)) { + xge_os_printf("fifo_max_frags = %d", dconfig->fifo.max_frags); + xge_os_printf("fifo_max_frags should be <= (PAGE_SIZE / 32) = %d", + (PAGE_SIZE / 32)); + xge_os_printf("Using fifo_max_frags = %d", (PAGE_SIZE / 32)); + dconfig->fifo.max_frags = (PAGE_SIZE / 32); + } + + checkdev = pci_find_device(VENDOR_ID_AMD, DEVICE_ID_8131_PCI_BRIDGE); + if(checkdev != NULL) { + /* Check Revision for 0x12 */ + revision = pci_read_config(checkdev, + xge_offsetof(xge_hal_pci_config_t, revision), 1); + if(revision <= 0x12) { + /* Set mmrb_count to 1k and max splits = 2 */ + dconfig->mmrb_count = 1; + dconfig->max_splits_trans = XGE_HAL_THREE_SPLIT_TRANSACTION; + } + } + +#ifdef XGE_FEATURE_LRO + /* updating the LRO frame's sg size and frame len size. */ + dconfig->lro_sg_size = 20; + dconfig->lro_frm_len = 65536; +#endif + + LEAVE_FUNCTION +} + +/****************************************** + * xge_driver_initialize + * Parameters: None + * Return: 0/1 + * Description: Defines HAL-ULD callbacks + * and initializes the HAL driver + ******************************************/ +int +xge_driver_initialize(void) +{ + xge_hal_uld_cbs_t uld_callbacks; + xge_hal_driver_config_t driver_config; + xge_hal_status_e status = XGE_HAL_OK; + + ENTER_FUNCTION + + /* Initialize HAL driver */ + if(!hal_driver_init_count) { + xge_os_memzero(&uld_callbacks, sizeof(xge_hal_uld_cbs_t)); + + /* + * Initial and maximum size of the queue used to store the events + * like Link up/down (xge_hal_event_e) + */ + driver_config.queue_size_initial = 1; + driver_config.queue_size_max = 4; + + uld_callbacks.link_up = xgell_callback_link_up; + uld_callbacks.link_down = xgell_callback_link_down; + uld_callbacks.crit_err = xgell_callback_crit_err; + uld_callbacks.event = xgell_callback_event; + + status = xge_hal_driver_initialize(&driver_config, &uld_callbacks); + if(status != XGE_HAL_OK) { + xge_os_printf("xgeX: Initialization failed (Status: %d)", + status); + goto xdi_out; + } + } + hal_driver_init_count = hal_driver_init_count + 1; + + xge_hal_driver_debug_module_mask_set(0xffffffff); + xge_hal_driver_debug_level_set(XGE_TRACE); + +xdi_out: + LEAVE_FUNCTION + return status; +} + +/****************************************** + * Function: xge_media_init + * Parameters: Device pointer + * Return: None + * Description: Initializes, adds and sets + * media + ******************************************/ +void +xge_media_init(device_t devc) +{ + xgelldev_t *lldev = (xgelldev_t *)device_get_softc(devc); + + ENTER_FUNCTION + + /* Initialize Media */ + ifmedia_init(&lldev->xge_media, IFM_IMASK, xge_ifmedia_change, + xge_ifmedia_status); + + /* Add supported media */ + ifmedia_add(&lldev->xge_media, IFM_ETHER | IFM_1000_SX | IFM_FDX, + 0, NULL); + ifmedia_add(&lldev->xge_media, IFM_ETHER | IFM_1000_SX, 0, NULL); + ifmedia_add(&lldev->xge_media, IFM_ETHER | IFM_AUTO, 0, NULL); + ifmedia_add(&lldev->xge_media, IFM_ETHER | IFM_10G_SR, 0, NULL); + ifmedia_add(&lldev->xge_media, IFM_ETHER | IFM_10G_LR, 0, NULL); + + /* Set media */ + ifmedia_set(&lldev->xge_media, IFM_ETHER | IFM_AUTO); + + LEAVE_FUNCTION +} + +/* + * xge_pci_space_save + * Save PCI configuration space + * @dev Device structure + */ +void +xge_pci_space_save(device_t dev) +{ + ENTER_FUNCTION + + struct pci_devinfo *dinfo = NULL; + + dinfo = device_get_ivars(dev); + xge_trace(XGE_TRACE, "Saving PCI configuration space"); + pci_cfg_save(dev, dinfo, 0); + + LEAVE_FUNCTION +} + +/* + * xge_pci_space_restore + * Restore saved PCI configuration space + * @dev Device structure + */ +void +xge_pci_space_restore(device_t dev) +{ + ENTER_FUNCTION + + struct pci_devinfo *dinfo = NULL; + + dinfo = device_get_ivars(dev); + xge_trace(XGE_TRACE, "Restoring PCI configuration space"); + pci_cfg_restore(dev, dinfo); + + LEAVE_FUNCTION +} + +/****************************************** + * xge_attach + * Parameters: Per adapter xgelldev_t + * structure pointer + * Return: None + * Description: Connects the driver to the + * system if the probe routine returned success + ******************************************/ +int +xge_attach(device_t dev) +{ + xge_hal_device_config_t *device_config; + xge_hal_ring_config_t *pRingConfig; + xge_hal_device_attr_t attr; + xgelldev_t *lldev; + xge_hal_device_t *hldev; + pci_info_t *pci_info; + struct ifnet *ifnetp; + char *mesg; + char *desc; + int rid; + int rid0; + int rid1; + int error; + u64 val64 = 0; + int retValue = 0; + int mode = 0; + int buffer_index, buffer_length, index; + + ENTER_FUNCTION + + device_config = xge_malloc(sizeof(xge_hal_device_config_t)); + if(!device_config) { + xge_ctrace(XGE_ERR, "Malloc of device config failed"); + retValue = ENOMEM; + goto attach_out_config; + } + + lldev = (xgelldev_t *) device_get_softc(dev); + if(!lldev) { + xge_ctrace(XGE_ERR, "Adapter softc structure allocation failed"); + retValue = ENOMEM; + goto attach_out; + } + lldev->device = dev; + + /* Initialize mutex */ + if(mtx_initialized(&lldev->xge_lock) == 0) { + mtx_init((&lldev->xge_lock), "xge", MTX_NETWORK_LOCK, MTX_DEF); + } + + error = xge_driver_initialize(); + if(error != XGE_HAL_OK) { + xge_ctrace(XGE_ERR, "Initializing driver failed"); + freeResources(dev, 1); + retValue = ENXIO; + goto attach_out; + } + + /* HAL device */ + hldev = (xge_hal_device_t *)xge_malloc(sizeof(xge_hal_device_t)); + if(!hldev) { + xge_trace(XGE_ERR, "Allocating memory for xge_hal_device_t failed"); + freeResources(dev, 2); + retValue = ENOMEM; + goto attach_out; + } + lldev->devh = hldev; + + /* Our private structure */ + pci_info = (pci_info_t*) xge_malloc(sizeof(pci_info_t)); + if(!pci_info) { + xge_trace(XGE_ERR, "Allocating memory for pci_info_t failed"); + freeResources(dev, 3); + retValue = ENOMEM; + goto attach_out; + } + lldev->pdev = pci_info; + pci_info->device = dev; + + /* Set bus master */ + pci_enable_busmaster(dev); + + /* Get virtual address for BAR0 */ + rid0 = PCIR_BAR(0); + pci_info->regmap0 = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, + RF_ACTIVE); + if(pci_info->regmap0 == NULL) { + xge_trace(XGE_ERR, "NULL handler for BAR0"); + freeResources(dev, 4); + retValue = ENOMEM; + goto attach_out; + } + attr.bar0 = (char *)pci_info->regmap0; + + pci_info->bar0resource = + (busresource_t*) xge_malloc(sizeof(busresource_t)); + if(pci_info->bar0resource == NULL) { + xge_trace(XGE_ERR, "Allocating memory for bar0resources failed"); + freeResources(dev, 5); + retValue = ENOMEM; + goto attach_out; + } + ((struct busresources *)(pci_info->bar0resource))->bus_tag = + rman_get_bustag(pci_info->regmap0); + ((struct busresources *)(pci_info->bar0resource))->bus_handle = + rman_get_bushandle(pci_info->regmap0); + ((struct busresources *)(pci_info->bar0resource))->bar_start_addr = + pci_info->regmap0; + + /* Get virtual address for BAR1 */ + rid1 = PCIR_BAR(2); + pci_info->regmap1 = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid1, + RF_ACTIVE); + if(pci_info->regmap1 == NULL) { + xge_trace(XGE_ERR, "NULL handler for BAR1"); + freeResources(dev, 6); + retValue = ENOMEM; + goto attach_out; + } + attr.bar1 = (char *)pci_info->regmap1; + + pci_info->bar1resource = + (busresource_t*) xge_malloc(sizeof(busresource_t)); + if(pci_info->bar1resource == NULL) { + xge_trace(XGE_ERR, "Allocating memory for bar0resources failed"); + freeResources(dev, 7); + retValue = ENOMEM; + goto attach_out; + } + ((struct busresources *)(pci_info->bar1resource))->bus_tag = + rman_get_bustag(pci_info->regmap1); + ((struct busresources *)(pci_info->bar1resource))->bus_handle = + rman_get_bushandle(pci_info->regmap1); + ((struct busresources *)(pci_info->bar1resource))->bar_start_addr = + pci_info->regmap1; + + /* Save PCI config space */ + xge_pci_space_save(dev); + + attr.regh0 = (busresource_t *) pci_info->bar0resource; + attr.regh1 = (busresource_t *) pci_info->bar1resource; + attr.irqh = lldev->irqhandle; + attr.cfgh = pci_info; + attr.pdev = pci_info; + + /* Initialize device configuration parameters */ + xge_init_params(device_config, dev); + + /* Initialize HAL device */ + error = xge_hal_device_initialize(hldev, &attr, device_config); + if(error != XGE_HAL_OK) { + switch(error) { + case XGE_HAL_ERR_DRIVER_NOT_INITIALIZED: + xge_trace(XGE_ERR, "XGE_HAL_ERR_DRIVER_NOT_INITIALIZED"); + break; + + case XGE_HAL_ERR_OUT_OF_MEMORY: + xge_trace(XGE_ERR, "XGE_HAL_ERR_OUT_OF_MEMORY"); + break; + + case XGE_HAL_ERR_BAD_SUBSYSTEM_ID: + xge_trace(XGE_ERR, "XGE_HAL_ERR_BAD_SUBSYSTEM_ID"); + break; + + case XGE_HAL_ERR_INVALID_MAC_ADDRESS: + xge_trace(XGE_ERR, "XGE_HAL_ERR_INVALID_MAC_ADDRESS"); + break; + + case XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING: + xge_trace(XGE_ERR, "XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING"); + break; + + case XGE_HAL_ERR_SWAPPER_CTRL: + xge_trace(XGE_ERR, "XGE_HAL_ERR_SWAPPER_CTRL"); + break; + + case XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT: + xge_trace(XGE_ERR, "XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT"); + break; + } + xge_trace(XGE_ERR, "Initializing HAL device failed (error: %d)\n", + error); + freeResources(dev, 8); + retValue = ENXIO; + goto attach_out; + } + + desc = (char *) malloc(100, M_DEVBUF, M_NOWAIT); + if(desc == NULL) { + retValue = ENOMEM; + } + else { + sprintf(desc, "%s (Rev %d) Driver v%s \n%s: Serial Number: %s ", + hldev->vpd_data.product_name, hldev->revision, DRIVER_VERSION, + device_get_nameunit(dev), hldev->vpd_data.serial_num); + printf("%s: Xframe%s %s\n", device_get_nameunit(dev), + ((hldev->device_id == XGE_PCI_DEVICE_ID_XENA_2) ? "I": "II"), + desc); + free(desc, M_DEVBUF); + + } + + if(pci_get_device(dev) == XGE_PCI_DEVICE_ID_HERC_2) { + error = xge_hal_mgmt_reg_read(hldev, 0, + xge_offsetof(xge_hal_pci_bar0_t, pci_info), &val64); + if(error != XGE_HAL_OK) { + xge_trace(XGE_ERR, "Error for getting bus speed"); + } + mesg = (char *) xge_malloc(20); + if(mesg == NULL) { + freeResources(dev, 8); + retValue = ENOMEM; + goto attach_out; + } + + sprintf(mesg, "%s: Device is on %s bit", device_get_nameunit(dev), + (val64 & BIT(8)) ? "32":"64"); + + mode = (u8)((val64 & vBIT(0xF, 0, 4)) >> 60); + switch(mode) { + case 0x00: xge_os_printf("%s PCI 33MHz bus", mesg); break; + case 0x01: xge_os_printf("%s PCI 66MHz bus", mesg); break; + case 0x02: xge_os_printf("%s PCIX(M1) 66MHz bus", mesg); break; + case 0x03: xge_os_printf("%s PCIX(M1) 100MHz bus", mesg); break; + case 0x04: xge_os_printf("%s PCIX(M1) 133MHz bus", mesg); break; + case 0x05: xge_os_printf("%s PCIX(M2) 133MHz bus", mesg); break; + case 0x06: xge_os_printf("%s PCIX(M2) 200MHz bus", mesg); break; + case 0x07: xge_os_printf("%s PCIX(M2) 266MHz bus", mesg); break; + } + free(mesg, M_DEVBUF); + } + + xge_hal_device_private_set(hldev, lldev); + + error = xge_interface_setup(dev); + if(error != 0) { + retValue = error; + goto attach_out; + } + + ifnetp = lldev->ifnetp; + ifnetp->if_mtu = device_config->mtu; + + xge_media_init(dev); + + /* Interrupt */ + rid = 0; + lldev->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_SHAREABLE | RF_ACTIVE); + if(lldev->irq == NULL) { + xge_trace(XGE_ERR, "NULL handler for IRQ"); + freeResources(dev, 10); + retValue = ENOMEM; + goto attach_out; + } + + /* Associate interrupt handler with the device */ + error = bus_setup_intr(dev, lldev->irq, INTR_TYPE_NET | INTR_MPSAFE, +#if __FreeBSD_version > 700030 + xge_intr_filter, +#endif + (void *)xge_intr, lldev, &lldev->irqhandle); + if(error != 0) { + xge_trace(XGE_ERR, + "Associating interrupt handler with device failed"); + freeResources(dev, 11); + retValue = ENXIO; + goto attach_out; + } + + /* Create DMA tags */ + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* Parent */ + PAGE_SIZE, /* Alignment */ + 0, /* Bounds */ + BUS_SPACE_MAXADDR, /* Low Address */ + BUS_SPACE_MAXADDR, /* High Address */ + NULL, /* Filter Function */ + NULL, /* Filter Function Arguments */ + MCLBYTES * MAX_SEGS, /* Maximum Size */ + MAX_SEGS, /* Number of Segments */ + MCLBYTES, /* Maximum Segment Size */ + BUS_DMA_ALLOCNOW, /* Flags */ + NULL, /* Lock Function */ + NULL, /* Lock Function Arguments */ + (&lldev->dma_tag_tx)); /* DMA Tag */ + if(error != 0) { + xge_trace(XGE_ERR, "Tx DMA tag creation failed"); + freeResources(dev, 12); + retValue = ENOMEM; + goto attach_out; + } + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* Parent */ + PAGE_SIZE, /* Alignment */ + 0, /* Bounds */ + BUS_SPACE_MAXADDR, /* Low Address */ + BUS_SPACE_MAXADDR, /* High Address */ + NULL, /* Filter Function */ + NULL, /* Filter Function Arguments */ + MJUMPAGESIZE, /* Maximum Size */ + 1, /* Number of Segments */ + MJUMPAGESIZE, /* Maximum Segment Size */ + BUS_DMA_ALLOCNOW, /* Flags */ + NULL, /* Lock Function */ + NULL, /* Lock Function Arguments */ + (&lldev->dma_tag_rx)); /* DMA Tag */ + + if(error != 0) { + xge_trace(XGE_ERR, "Rx DMA tag creation failed"); + freeResources(dev, 13); + retValue = ENOMEM; + goto attach_out; + } + + /*Updating lldev->buffer_mode parameter*/ + pRingConfig = &(hldev->config.ring); + + if((device_config->mtu + XGE_HAL_MAC_HEADER_MAX_SIZE) <= PAGE_SIZE) { +#if defined(XGE_FEATURE_BUFFER_MODE_3) + xge_os_printf("%s: 3 Buffer Mode Enabled", + device_get_nameunit(dev)); + for(index = 0; index < XGE_RING_COUNT; index++) { + pRingConfig->queue[index].buffer_mode = + XGE_HAL_RING_QUEUE_BUFFER_MODE_3; + } + pRingConfig->scatter_mode = XGE_HAL_RING_QUEUE_SCATTER_MODE_A; + lldev->buffer_mode = XGE_HAL_RING_QUEUE_BUFFER_MODE_3; + lldev->rxd_mbuf_len[0] = XGE_HAL_MAC_HEADER_MAX_SIZE; + lldev->rxd_mbuf_len[1] = XGE_HAL_TCPIP_HEADER_MAX_SIZE; + lldev->rxd_mbuf_len[2] = device_config->mtu; + lldev->rxd_mbuf_cnt = 3; +#else +#if defined(XGE_FEATURE_BUFFER_MODE_2) + xge_os_printf("%s: 2 Buffer Mode Enabled", + device_get_nameunit(dev)); + for(index = 0; index < XGE_RING_COUNT; index++) { + pRingConfig->queue[index].buffer_mode = + XGE_HAL_RING_QUEUE_BUFFER_MODE_3; + } + pRingConfig->scatter_mode = XGE_HAL_RING_QUEUE_SCATTER_MODE_B; + lldev->buffer_mode = XGE_HAL_RING_QUEUE_BUFFER_MODE_2; + lldev->rxd_mbuf_len[0] = XGE_HAL_MAC_HEADER_MAX_SIZE; + lldev->rxd_mbuf_len[1] = device_config->mtu; + lldev->rxd_mbuf_cnt = 2; +#else + lldev->buffer_mode = XGE_HAL_RING_QUEUE_BUFFER_MODE_1; + lldev->rxd_mbuf_len[0] = device_config->mtu; + lldev->rxd_mbuf_cnt = 1; +#endif +#endif + } + else { + xge_os_printf("%s: 5 Buffer Mode Enabled", + device_get_nameunit(dev)); + xge_os_memzero(lldev->rxd_mbuf_len, sizeof(lldev->rxd_mbuf_len)); + for(index = 0; index < XGE_RING_COUNT; index++) { + pRingConfig->queue[index].buffer_mode = + XGE_HAL_RING_QUEUE_BUFFER_MODE_5; + } + lldev->buffer_mode = XGE_HAL_RING_QUEUE_BUFFER_MODE_5; + buffer_length = device_config->mtu; + buffer_index = 2; + lldev->rxd_mbuf_len[0] = XGE_HAL_MAC_HEADER_MAX_SIZE; + lldev->rxd_mbuf_len[1] = XGE_HAL_TCPIP_HEADER_MAX_SIZE; + + while(buffer_length > PAGE_SIZE) { + buffer_length -= PAGE_SIZE; + lldev->rxd_mbuf_len[buffer_index] = PAGE_SIZE; + buffer_index++; + } + + BUFALIGN(buffer_length); + + lldev->rxd_mbuf_len[buffer_index] = buffer_length; + lldev->rxd_mbuf_cnt = buffer_index; + } + +#ifdef XGE_FEATURE_LRO + xge_os_printf("%s: LRO (Large Receive Offload) Enabled", + device_get_nameunit(dev)); +#endif + +#ifdef XGE_FEATURE_TSO + xge_os_printf("%s: TSO (TCP Segmentation Offload) enabled", + device_get_nameunit(dev)); +#endif + +attach_out: + free(device_config, M_DEVBUF); +attach_out_config: + LEAVE_FUNCTION + return retValue; +} + +/****************************************** + * freeResources + * Parameters: Device structure, error (used + * to branch freeing) + * Return: None + * Description: Frees allocated resources + ******************************************/ +void +freeResources(device_t dev, int error) +{ + xgelldev_t *lldev; + pci_info_t *pci_info; + xge_hal_device_t *hldev; + int rid, status; + + ENTER_FUNCTION + + /* LL Device */ + lldev = (xgelldev_t *) device_get_softc(dev); + pci_info = lldev->pdev; + + /* HAL Device */ + hldev = lldev->devh; + + switch(error) { + case 0: + status = bus_dma_tag_destroy(lldev->dma_tag_rx); + if(status) { + xge_trace(XGE_ERR, "Rx DMA tag destroy failed"); + } + + case 13: + status = bus_dma_tag_destroy(lldev->dma_tag_tx); + if(status) { + xge_trace(XGE_ERR, "Tx DMA tag destroy failed"); + } + + case 12: + /* Teardown interrupt handler - device association */ + bus_teardown_intr(dev, lldev->irq, lldev->irqhandle); + + case 11: + /* Release IRQ */ + bus_release_resource(dev, SYS_RES_IRQ, 0, lldev->irq); + + case 10: + /* Media */ + ifmedia_removeall(&lldev->xge_media); + + /* Detach Ether */ + ether_ifdetach(lldev->ifnetp); + if_free(lldev->ifnetp); + + xge_hal_device_private_set(hldev, NULL); + xge_hal_device_disable(hldev); + + case 9: + /* HAL Device */ + xge_hal_device_terminate(hldev); + + case 8: + /* Restore PCI configuration space */ + xge_pci_space_restore(dev); + + /* Free bar1resource */ + free(pci_info->bar1resource, M_DEVBUF); + + case 7: + /* Release BAR1 */ + rid = PCIR_BAR(2); + bus_release_resource(dev, SYS_RES_MEMORY, rid, + pci_info->regmap1); + + case 6: + /* Free bar0resource */ + free(pci_info->bar0resource, M_DEVBUF); + + case 5: + /* Release BAR0 */ + rid = PCIR_BAR(0); + bus_release_resource(dev, SYS_RES_MEMORY, rid, + pci_info->regmap0); + + case 4: + /* Disable Bus Master */ + pci_disable_busmaster(dev); + + /* Free pci_info_t */ + lldev->pdev = NULL; + free(pci_info, M_DEVBUF); + + case 3: + /* Free device configuration struct and HAL device */ + free(hldev, M_DEVBUF); + + case 2: + /* Terminate HAL driver */ + hal_driver_init_count = hal_driver_init_count - 1; + if(!hal_driver_init_count) { + xge_hal_driver_terminate(); + } + + case 1: + if(mtx_initialized(&lldev->xge_lock) != 0) { + mtx_destroy(&lldev->xge_lock); + } + } + + LEAVE_FUNCTION +} + +/****************************************** + * xge_detach + * Parameters: Device structure + * Return: 0 + * Description: Detaches the driver from the + * kernel subsystem. + ******************************************/ +int +xge_detach(device_t dev) +{ + xgelldev_t *lldev = (xgelldev_t *)device_get_softc(dev); + + ENTER_FUNCTION + + mtx_lock(&lldev->xge_lock); + lldev->in_detach = 1; + xge_stop(lldev); + mtx_unlock(&lldev->xge_lock); + + freeResources(dev, 0); + + LEAVE_FUNCTION + + return 0; +} + +/****************************************** + * xge_shutdown + * Parameters: Per adapter xgelldev_t + * structure pointer + * Return: None + * Description: Gets called when the system + * is about to be shutdown. + ******************************************/ +int +xge_shutdown(device_t dev) +{ + xgelldev_t *lldev = (xgelldev_t *) device_get_softc(dev); + + ENTER_FUNCTION + mtx_lock(&lldev->xge_lock); + xge_stop(lldev); + mtx_unlock(&lldev->xge_lock); + LEAVE_FUNCTION + return 0; +} + +/****************************************** + * Function: xge_interface_setup + * Parameters: Device pointer + * Return: 0/ENXIO/ENOMEM + * Description: Sets up the interface + * through ifnet pointer + ******************************************/ +int +xge_interface_setup(device_t dev) +{ + u8 mcaddr[ETHER_ADDR_LEN]; + xge_hal_status_e status_code; + xgelldev_t *lldev = (xgelldev_t *)device_get_softc(dev); + struct ifnet *ifnetp; + xge_hal_device_t *hldev = lldev->devh; + int retValue = 0; + + ENTER_FUNCTION + + /* Get the MAC address of the device */ + status_code = xge_hal_device_macaddr_get(hldev, 0, &mcaddr); + if(status_code != XGE_HAL_OK) { + switch(status_code) { + case XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING: + xge_trace(XGE_ERR, + "Failed to retrieve MAC address (timeout)"); + break; + + case XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES: + xge_trace(XGE_ERR, "Invalid MAC address index"); + break; + + default: + xge_trace(XGE_TRACE, "Default Case"); + break; + } + freeResources(dev, 9); + retValue = ENXIO; + goto ifsetup_out; + } + + /* Get interface ifnet structure for this Ether device */ + ifnetp = lldev->ifnetp = if_alloc(IFT_ETHER); + if(ifnetp == NULL) { + xge_trace(XGE_ERR, "Allocating/getting ifnet structure failed"); + freeResources(dev, 9); + retValue = ENOMEM; + goto ifsetup_out; + } + + /* Initialize interface ifnet structure */ + if_initname(ifnetp, device_get_name(dev), device_get_unit(dev)); + ifnetp->if_mtu = XGE_HAL_DEFAULT_MTU; + + /* + * TODO: Can't set more than 2Gbps. -- Higher value results in overflow. + * But there is no effect in performance even if you set this to 10 Mbps + */ + ifnetp->if_baudrate = IF_Gbps(2); + ifnetp->if_init = xge_init; + ifnetp->if_softc = lldev; + ifnetp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifnetp->if_ioctl = xge_ioctl; + ifnetp->if_start = xge_send; + + /* TODO: Check and assign optimal value */ + ifnetp->if_snd.ifq_maxlen = IFQ_MAXLEN; + + ifnetp->if_capabilities = IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | + IFCAP_HWCSUM; + + ifnetp->if_capenable = ifnetp->if_capabilities; + +#ifdef XGE_FEATURE_TSO + ifnetp->if_capabilities |= IFCAP_TSO4; + ifnetp->if_capenable |= IFCAP_TSO4; +#endif + + /* Attach the interface */ + ether_ifattach(ifnetp, mcaddr); + +ifsetup_out: + LEAVE_FUNCTION + + return retValue; +} + +/****************************************** + * xgell_callback_link_up + * Parameters: Per adapter xgelldev_t + * structure pointer as void * + * Return: None + * Description: Called by HAL to notify + * hardware link up state change + ******************************************/ +void +xgell_callback_link_up(void *userdata) +{ + xgelldev_t *lldev = (xgelldev_t *)userdata; + struct ifnet *ifnetp = lldev->ifnetp; + + ENTER_FUNCTION + + ifnetp->if_flags &= ~IFF_DRV_OACTIVE; + if_link_state_change(ifnetp, LINK_STATE_UP); + + LEAVE_FUNCTION +} + +/****************************************** + * xgell_callback_link_down + * Parameters: Per adapter xgelldev_t + * structure pointer as void * + * Return: None + * Description: Called by HAL to notify + * hardware link up state change + ******************************************/ +void +xgell_callback_link_down(void *userdata) +{ + xgelldev_t *lldev = (xgelldev_t *)userdata; + struct ifnet *ifnetp = lldev->ifnetp; + + ENTER_FUNCTION + + ifnetp->if_flags |= IFF_DRV_OACTIVE; + if_link_state_change(ifnetp, LINK_STATE_DOWN); + + LEAVE_FUNCTION +} + +/****************************************** + * xgell_callback_crit_err + * Parameters: Per adapter xgelldev_t + * structure pointer as void *, event, + * serr_data -> + * Return: None + * Description: Called by HAL on serious + * error event + ******************************************/ +void +xgell_callback_crit_err(void *userdata, xge_hal_event_e type, u64 serr_data) +{ + ENTER_FUNCTION + + xge_trace(XGE_ERR, "Critical Error"); + xgell_reset(userdata); + + LEAVE_FUNCTION +} + +/****************************************** + * xgell_callback_event + * Parameters: Queue item + * Return: None + * Description: Called by HAL in case of + * some unknown to HAL events. + ******************************************/ +void +xgell_callback_event(xge_queue_item_t *item) +{ + xgelldev_t *lldev = NULL; + xge_hal_device_t *hldev = NULL; + struct ifnet *ifnetp = NULL; + + ENTER_FUNCTION + + hldev = item->context; + lldev = xge_hal_device_private(hldev); + ifnetp = lldev->ifnetp; + + if(item->event_type == XGE_LL_EVENT_TRY_XMIT_AGAIN) { + if(lldev->initialized) { + if(xge_hal_channel_dtr_count(lldev->fifo_channel_0) > 0) { + ifnetp->if_flags &= ~IFF_DRV_OACTIVE; + } + else { + /* try next time */ + xge_queue_produce_context( + xge_hal_device_queue(lldev->devh), + XGE_LL_EVENT_TRY_XMIT_AGAIN, lldev->devh); + } + } + } + else if(item->event_type == XGE_LL_EVENT_DEVICE_RESETTING) { + xgell_reset(item->context); + } + + LEAVE_FUNCTION +} + +/****************************************** + * Function: xge_ifmedia_change + * Parameters: Pointer to ifnet structure + * Return: 0 for success, EINVAL if media + * type is not IFM_ETHER. + * Description: Media change driver callback + ******************************************/ +int +xge_ifmedia_change(struct ifnet *ifnetp) +{ + xgelldev_t *lldev = ifnetp->if_softc; + struct ifmedia *ifmediap = &lldev->xge_media; + + ENTER_FUNCTION + LEAVE_FUNCTION + + return (IFM_TYPE(ifmediap->ifm_media) != IFM_ETHER) ? EINVAL:0; +} + +/****************************************** + * Function: xge_ifmedia_status + * Parameters: Pointer to ifnet structure + * ifmediareq structure pointer + * through which status of media + * will be returned. + * Return: None + * Description: Media status driver callback + ******************************************/ +void +xge_ifmedia_status(struct ifnet *ifnetp, struct ifmediareq *ifmr) +{ + xge_hal_status_e status; + u64 regvalue; + xgelldev_t *lldev = ifnetp->if_softc; + xge_hal_device_t *hldev = lldev->devh; + + ENTER_FUNCTION + + ifmr->ifm_status = IFM_AVALID; + ifmr->ifm_active = IFM_ETHER; + + status = xge_hal_mgmt_reg_read(hldev, 0, + xge_offsetof(xge_hal_pci_bar0_t, adapter_status), ®value); + if(status != XGE_HAL_OK) { + xge_trace(XGE_ERR, "Getting adapter status failed"); + return; + } + + if((regvalue & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | + XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)) == 0) { + ifmr->ifm_status |= IFM_ACTIVE; + ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; + if_link_state_change(ifnetp, LINK_STATE_UP); + } + else { + if_link_state_change(ifnetp, LINK_STATE_DOWN); + } + + LEAVE_FUNCTION +} + +/****************************************** + * Function: xge_ioctl + * Parameters: Pointer to ifnet structure, + * command -> indicates requests, + * data -> passed values (if any) + * Return: + * Description: IOCTL entry point. Called + * when the user wants to + * configure the interface + ******************************************/ +int +xge_ioctl(struct ifnet *ifnetp, unsigned long command, caddr_t data) +{ + struct ifmedia *ifmediap; + xge_hal_stats_hw_info_t *hw_stats; + xge_hal_pci_config_t *pci_conf; + xge_hal_device_config_t *device_conf; + xge_hal_stats_sw_err_t *tcode; + xge_hal_stats_device_info_t *intr; + bar0reg_t *reg; + xge_hal_status_e status_code; + xge_hal_device_t *hldev; + void *regInfo; + u64 value; + u64 offset; + char *pAccess; + char *version; + int retValue = 0, index = 0, buffer_mode = 0; + struct ifreq *ifreqp = (struct ifreq *) data; + xgelldev_t *lldev = ifnetp->if_softc; + + ifmediap = &lldev->xge_media; + hldev = lldev->devh; + + if(lldev->in_detach) { + return retValue; + } + + switch(command) { + /* Set/Get ifnet address */ + case SIOCSIFADDR: + case SIOCGIFADDR: + ether_ioctl(ifnetp, command, data); + break; + + /* Set ifnet MTU */ + case SIOCSIFMTU: + retValue = changeMtu(lldev, ifreqp->ifr_mtu); + break; + + /* Set ifnet flags */ + case SIOCSIFFLAGS: + mtx_lock(&lldev->xge_lock); + if(ifnetp->if_flags & IFF_UP) { + /* Link status is UP */ + if(!(ifnetp->if_drv_flags & IFF_DRV_RUNNING)) { + xge_init_locked(lldev); + } + xge_disable_promisc(lldev); + xge_enable_promisc(lldev); + } + else { + /* Link status is DOWN */ + /* If device is in running, make it down */ + if(ifnetp->if_drv_flags & IFF_DRV_RUNNING) { + xge_stop(lldev); + } + } + mtx_unlock(&lldev->xge_lock); + break; + + /* Add/delete multicast address */ + case SIOCADDMULTI: + case SIOCDELMULTI: + if(ifnetp->if_drv_flags & IFF_DRV_RUNNING) { + xge_setmulti(lldev); + } + break; + + /* Set/Get net media */ + case SIOCSIFMEDIA: + case SIOCGIFMEDIA: + retValue = ifmedia_ioctl(ifnetp, ifreqp, ifmediap, command); + break; + + /* Set capabilities */ + case SIOCSIFCAP: + mtx_lock(&lldev->xge_lock); + int mask = 0; + mask = ifreqp->ifr_reqcap ^ ifnetp->if_capenable; +#if defined(__FreeBSD_version) && (__FreeBSD_version >= 700026) + if(mask & IFCAP_TSO4) { + if(ifnetp->if_capenable & IFCAP_TSO4) { + ifnetp->if_capenable &= ~IFCAP_TSO4; + ifnetp->if_hwassist &= ~CSUM_TSO; + } + + /*enable tso only if txcsum is enabled*/ + if(ifnetp->if_capenable & IFCAP_TXCSUM) { + ifnetp->if_capenable |= IFCAP_TSO4; + ifnetp->if_hwassist |= CSUM_TSO; + } + } +#endif + mtx_unlock(&lldev->xge_lock); + break; + + /* Custom IOCTL 0 : + * Used to get Statistics & PCI configuration through application */ + case SIOCGPRIVATE_0: + pAccess = (char*) ifreqp->ifr_data; + if(*pAccess == XGE_QUERY_STATS) { + mtx_lock(&lldev->xge_lock); + status_code = xge_hal_stats_hw(hldev, &hw_stats); + if(status_code != XGE_HAL_OK) { + xge_trace(XGE_ERR, + "Getting statistics failed (Status: %d)", + status_code); + mtx_unlock(&lldev->xge_lock); + retValue = EINVAL; + } + copyout(hw_stats, ifreqp->ifr_data, + sizeof(xge_hal_stats_hw_info_t)); + mtx_unlock(&lldev->xge_lock); + } + else if(*pAccess == XGE_QUERY_PCICONF) { + pci_conf = xge_malloc(sizeof(xge_hal_pci_config_t)); + if(pci_conf == NULL) { + return(ENOMEM); + } + mtx_lock(&lldev->xge_lock); + status_code = xge_hal_mgmt_pci_config(hldev, pci_conf, + sizeof(xge_hal_pci_config_t)); + if(status_code != XGE_HAL_OK) { + xge_trace(XGE_ERR, + "Getting PCIconfiguration failed (Status: %d)", + status_code); + mtx_unlock(&lldev->xge_lock); + retValue = EINVAL; + } + copyout(pci_conf, ifreqp->ifr_data, + sizeof(xge_hal_pci_config_t)); + mtx_unlock(&lldev->xge_lock); + free(pci_conf, M_DEVBUF); + } + else if(*pAccess ==XGE_QUERY_INTRSTATS) { + intr = xge_malloc(sizeof(xge_hal_stats_device_info_t)); + if(intr == NULL) { + return(ENOMEM); + } + mtx_lock(&lldev->xge_lock); + status_code =xge_hal_mgmt_device_stats(hldev, intr, + sizeof(xge_hal_stats_device_info_t)); + if(status_code != XGE_HAL_OK) { + xge_trace(XGE_ERR, + "Getting intr statistics failed (Status: %d)", + status_code); + mtx_unlock(&lldev->xge_lock); + retValue = EINVAL; + } + copyout(intr, ifreqp->ifr_data, + sizeof(xge_hal_stats_device_info_t)); + mtx_unlock(&lldev->xge_lock); + free(intr, M_DEVBUF); + } + else if(*pAccess == XGE_QUERY_TCODE) { + tcode = xge_malloc(sizeof(xge_hal_stats_sw_err_t)); + if(tcode == NULL) { + return(ENOMEM); + } + mtx_lock(&lldev->xge_lock); + status_code =xge_hal_mgmt_sw_stats(hldev, tcode, + sizeof(xge_hal_stats_sw_err_t)); + if(status_code != XGE_HAL_OK) { + xge_trace(XGE_ERR, + "Getting tcode statistics failed (Status: %d)", + status_code); + mtx_unlock(&lldev->xge_lock); + retValue = EINVAL; + } + copyout(tcode, ifreqp->ifr_data, + sizeof(xge_hal_stats_sw_err_t)); + mtx_unlock(&lldev->xge_lock); + free(tcode, M_DEVBUF); + } + else if(*pAccess ==XGE_READ_VERSION) { + version = xge_malloc(BUFFER_SIZE); + if(version == NULL) { + return(ENOMEM); + } + mtx_lock(&lldev->xge_lock); + strcpy(version,DRIVER_VERSION); + copyout(version, ifreqp->ifr_data, BUFFER_SIZE); + mtx_unlock(&lldev->xge_lock); + free(version, M_DEVBUF); + } + else if(*pAccess == XGE_QUERY_DEVCONF) { + device_conf = xge_malloc(sizeof(xge_hal_device_config_t)); + if(device_conf == NULL) { + return(ENOMEM); + } + mtx_lock(&lldev->xge_lock); + status_code = xge_hal_mgmt_device_config(hldev, device_conf, + sizeof(xge_hal_device_config_t)); + if(status_code != XGE_HAL_OK) { + xge_trace(XGE_ERR, + "Getting devconfig failed (Status: %d)", + status_code); + mtx_unlock(&lldev->xge_lock); + retValue = EINVAL; + } + if(copyout(device_conf, ifreqp->ifr_data, + sizeof(xge_hal_device_config_t)) != 0) { + xge_trace(XGE_ERR, "Device configuration copyout erro"); + } + mtx_unlock(&lldev->xge_lock); + free(device_conf, M_DEVBUF); + } + else if(*pAccess == XGE_QUERY_BUFFER_MODE) { + buffer_mode = lldev->buffer_mode; + if(copyout(&buffer_mode, ifreqp->ifr_data, + sizeof(int)) != 0) { + xge_trace(XGE_ERR, "Error with copyout of buffermode"); + retValue = EINVAL; + } + } + else if((*pAccess == XGE_SET_BUFFER_MODE_1) || + (*pAccess == XGE_SET_BUFFER_MODE_2) || + (*pAccess == XGE_SET_BUFFER_MODE_3) || + (*pAccess == XGE_SET_BUFFER_MODE_5)) { + switch(*pAccess) { + case XGE_SET_BUFFER_MODE_1: *pAccess = 'Y'; break; + case XGE_SET_BUFFER_MODE_2: + case XGE_SET_BUFFER_MODE_3: + case XGE_SET_BUFFER_MODE_5: *pAccess = 'N'; break; + } + if(copyout(pAccess, ifreqp->ifr_data, + sizeof(pAccess)) != 0) { + xge_trace(XGE_ERR, + "Copyout of chgbufmode result failed"); + } + } + else { + xge_trace(XGE_TRACE, "Nothing is matching"); + } + break; + + /* + * Custom IOCTL 1 : + * Used to get BAR0 register values through application program + */ + case SIOCGPRIVATE_1: + reg = (bar0reg_t *) ifreqp->ifr_data; + if(strcmp(reg->option,"-r") == 0) { + offset = reg->offset; + value = 0x0000; + mtx_lock(&lldev->xge_lock); + status_code = xge_hal_mgmt_reg_read(hldev, 0, offset, + &value ); + if(status_code == XGE_HAL_OK) { + reg->value = value; + } + else { + xge_trace(XGE_ERR, "Getting register value failed"); + mtx_unlock(&lldev->xge_lock); + retValue = EINVAL; + break; + } + copyout(reg, ifreqp->ifr_data, sizeof(bar0reg_t)); + mtx_unlock(&lldev->xge_lock); + } + else if(strcmp(reg->option,"-w") == 0) { + offset = reg->offset; + value = reg->value; + mtx_lock(&lldev->xge_lock); + status_code = xge_hal_mgmt_reg_write(hldev, 0, offset, + value ); + if(status_code != XGE_HAL_OK) { + xge_trace(XGE_ERR, "Getting register value failed"); + mtx_unlock(&lldev->xge_lock); + retValue = EINVAL; + break; + } + value = 0x0000; + status_code = xge_hal_mgmt_reg_read(hldev, 0, offset, + &value); + if(status_code != XGE_HAL_OK) { + xge_trace(XGE_ERR, "Getting register value failed"); + mtx_unlock(&lldev->xge_lock); + retValue = EINVAL; + break; + } + if(reg->value != value) { + mtx_unlock(&lldev->xge_lock); + retValue = EINVAL; + break; + } + mtx_unlock(&lldev->xge_lock); + } + else + { + offset = 0x0000; + value = 0x0000; + regInfo = (void *)ifreqp->ifr_data; + + mtx_lock(&lldev->xge_lock); + for(index = 0, offset = 0; offset <= XGE_OFFSET_OF_LAST_REG; + index++, offset += 0x0008) { + status_code = xge_hal_mgmt_reg_read(hldev, 0, offset, + &value); + if(status_code == XGE_HAL_OK) { + *( ( u64 *)( ( u64 * )regInfo + index ) ) = value; + } + else { + xge_trace(XGE_ERR, "Getting register value failed"); + mtx_unlock(&lldev->xge_lock); + retValue = EINVAL; + break; + } + } + + copyout(regInfo, ifreqp->ifr_data, + sizeof(xge_hal_pci_bar0_t)); + mtx_unlock(&lldev->xge_lock); + } + break; + + default: + retValue = EINVAL; + break; + } + return retValue; +} + +/****************************************** + * Function: xge_init + * Parameters: Pointer to per-device + * xgelldev_t structure as void*. + * Return: None + * Description: Init entry point. + ******************************************/ +void +xge_init(void *plldev) +{ + ENTER_FUNCTION + + xgelldev_t *lldev = (xgelldev_t *)plldev; + + mtx_lock(&lldev->xge_lock); + xge_init_locked(lldev); + mtx_unlock(&lldev->xge_lock); + + LEAVE_FUNCTION +} + +void +xge_init_locked(void *pdevin) +{ + ENTER_FUNCTION + + xgelldev_t *lldev = (xgelldev_t *)pdevin; + struct ifnet *ifnetp = lldev->ifnetp; + device_t dev = lldev->device; + + mtx_assert((&lldev->xge_lock), MA_OWNED); + + /* If device is in running state, initializing is not required */ + if(ifnetp->if_drv_flags & IFF_DRV_RUNNING) { + return; + } + + /* Initializing timer */ + callout_init(&lldev->timer, CALLOUT_MPSAFE); + + xge_initialize(dev, XGE_HAL_CHANNEL_OC_NORMAL); + + LEAVE_FUNCTION +} + +/****************************************** + * Function: xge_timer + * Parameters: Pointer to per-device + * xgelldev_t structure as void*. + * Return: None + * Description: Polls the changes. + ******************************************/ +void +xge_timer(void *devp) +{ + xgelldev_t *lldev = (xgelldev_t *)devp; + xge_hal_device_t *hldev = lldev->devh; + + /* Poll for changes */ + xge_hal_device_poll(hldev); + + /* Reset timer */ + callout_reset(&lldev->timer, hz, xge_timer, lldev); + + return; +} + +/****************************************** + * Function: xge_stop + * Parameters: Per adapter xgelldev_t + * structure pointer + * Return: None + * Description: Deactivates the interface + * (Called on "ifconfig down" + ******************************************/ +void +xge_stop(xgelldev_t *lldev) +{ + struct ifnet *ifnetp = lldev->ifnetp; + device_t dev = lldev->device; + + ENTER_FUNCTION + + mtx_assert((&lldev->xge_lock), MA_OWNED); + + /* If device is not in "Running" state, return */ + if (!(ifnetp->if_drv_flags & IFF_DRV_RUNNING)) { + goto xfstop_out; + } + + xge_terminate(dev, XGE_HAL_CHANNEL_OC_NORMAL); + +xfstop_out: + LEAVE_FUNCTION + return; +} + +/* + * xge_intr_filter + * + * ISR filter function + * @handle softc/lldev per device structure + */ +int +xge_intr_filter(void *handle) +{ + xgelldev_t *lldev = NULL; + xge_hal_device_t *hldev = NULL; + xge_hal_pci_bar0_t *bar0 = NULL; + device_t dev = NULL; + u16 retValue = FILTER_STRAY; + u64 val64 = 0; + + lldev = (xgelldev_t *)handle; + hldev = lldev->devh; + dev = lldev->device; + bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + + val64 = xge_os_pio_mem_read64(lldev->pdev, hldev->regh0, + &bar0->general_int_status); + retValue = (!val64) ? FILTER_STRAY : FILTER_SCHEDULE_THREAD; + + return retValue; +} + +/****************************************** + * xge_intr + * Parameters: Per adapter xgelldev_t + * structure pointer + * Return: None + * Description: Interrupt service routine + ******************************************/ +void +xge_intr(void *plldev) +{ + xge_hal_status_e status; + xgelldev_t *lldev = (xgelldev_t *)plldev; + xge_hal_device_t *hldev = (xge_hal_device_t *)lldev->devh; + struct ifnet *ifnetp = lldev->ifnetp; + + mtx_lock(&lldev->xge_lock); + if(ifnetp->if_drv_flags & IFF_DRV_RUNNING) { + status = xge_hal_device_handle_irq(hldev); + + if(!(IFQ_DRV_IS_EMPTY(&ifnetp->if_snd))) { + xge_send_locked(ifnetp); + } + } + mtx_unlock(&lldev->xge_lock); + return; +} + +/******************************************** + * Function : xgell_rx_open + * Parameters: Queue index, channel + * open/close/reopen flag + * Return: 0 or ENODEV + * Description: Initialize and open all Rx + * channels. + ******************************************/ +int +xgell_rx_open(int qid, xgelldev_t *lldev, xge_hal_channel_reopen_e rflag) +{ + u64 adapter_status = 0x0; + int retValue = 0; + xge_hal_status_e status_code; + + ENTER_FUNCTION + + xge_hal_channel_attr_t attr = { + .post_qid = qid, + .compl_qid = 0, + .callback = xgell_rx_compl, + .per_dtr_space = sizeof(xgell_rx_priv_t), + .flags = 0, + .type = XGE_HAL_CHANNEL_TYPE_RING, + .userdata = lldev, + .dtr_init = xgell_rx_initial_replenish, + .dtr_term = xgell_rx_term + }; + + /* If device is not ready, return */ + if(xge_hal_device_status(lldev->devh, &adapter_status)) { + xge_trace(XGE_ERR, "Device is not ready. Adapter status: 0x%llx", + (unsigned long long) adapter_status); + retValue = -ENODEV; + goto rxopen_out; + } + + /* Open ring channel */ + status_code = xge_hal_channel_open(lldev->devh, &attr, + &lldev->ring_channel[qid], rflag); + if(status_code != XGE_HAL_OK) { + xge_trace(XGE_ERR, "Can not open Rx RING channel, Status: %d\n", + status_code); + retValue = -ENODEV; + goto rxopen_out; + } + +rxopen_out: + LEAVE_FUNCTION + + return retValue; +} + +/****************************************** + * Function: xgell_tx_open + * Parameters: Channel + * open/close/reopen flag + * Return: 0 or ENODEV + * Description: Initialize and open all Tx + * channels. + ******************************************/ +int +xgell_tx_open(xgelldev_t *lldev, xge_hal_channel_reopen_e tflag) +{ + xge_hal_status_e status_code; + u64 adapter_status = 0x0; + int retValue = 0; + + ENTER_FUNCTION + + xge_hal_channel_attr_t attr = { + .post_qid = 0, + .compl_qid = 0, + .callback = xgell_tx_compl, + .per_dtr_space = sizeof(xgell_tx_priv_t), + .flags = 0, + .type = XGE_HAL_CHANNEL_TYPE_FIFO, + .userdata = lldev, + .dtr_init = xgell_tx_initial_replenish, + .dtr_term = xgell_tx_term + }; + + /* If device is not ready, return */ + if(xge_hal_device_status(lldev->devh, &adapter_status)) { + xge_trace(XGE_ERR, "Device is not ready. Adapter status: 0x%llx\n", + (unsigned long long) adapter_status); + retValue = -ENODEV; + goto txopen_out; + } + + /* Open FIFO channel */ + status_code = xge_hal_channel_open(lldev->devh, &attr, + &lldev->fifo_channel_0, tflag); + if(status_code != XGE_HAL_OK) { + xge_trace(XGE_ERR, "Can not open Tx FIFO channel, Status: %d\n", + status_code); + retValue = -ENODEV; + goto txopen_out; + } + +txopen_out: + LEAVE_FUNCTION + + return retValue; +} + +/****************************************** + * Function: xgell_channel_open + * Parameters: Per adapter xgelldev_t + * structure pointer + * Return: None + * Description: Opens both Rx and Tx channels. + ******************************************/ +int +xgell_channel_open(xgelldev_t *lldev, xge_hal_channel_reopen_e option) +{ + int status = XGE_HAL_OK; + int index = 0; + int index2 = 0; + + ENTER_FUNCTION + + /* Open ring (Rx) channel */ + for(index = 0; index < XGE_RING_COUNT; index++) { + if((status = xgell_rx_open(index, lldev, option))) { + xge_trace(XGE_ERR, "Opening Rx channel failed (Status: %d)\n", + status); + for(index2 = 0; index2 < index; index2++) { + xge_hal_channel_close(lldev->ring_channel[index2], option); + } + return status; + } + } +#ifdef XGE_FEATURE_LRO + status = xge_hal_lro_init(1, lldev->devh); + if (status != XGE_HAL_OK) { + xge_trace(XGE_ERR, "cannot init Rx LRO got status code %d", status); + return -ENODEV; + } +#endif + + /* Open FIFO (Tx) channel */ + if((status = xgell_tx_open(lldev, option))) { + xge_trace(XGE_ERR, "Opening Tx channel failed (Status: %d)\n", + status); + for(index = 0; index < XGE_RING_COUNT; index++) { + xge_hal_channel_close(lldev->ring_channel[index], option); + } + } + + LEAVE_FUNCTION + return status; +} + +/****************************************** + * Function: xgell_channel_close + * Parameters: Per adapter xgelldev_t + * structure pointer + * Return: 0 for success, non-zero for + * failure + * Description: Closes both Tx and Rx channels + ******************************************/ +int +xgell_channel_close(xgelldev_t *lldev, xge_hal_channel_reopen_e option) +{ + int index; + + ENTER_FUNCTION + + DELAY(1000 * 1000); + + /* Close FIFO (Tx) channel */ + xge_hal_channel_close(lldev->fifo_channel_0, option); + + /* Close Ring (Rx) channel */ + for(index = 0; index < XGE_RING_COUNT; index++) { + xge_hal_channel_close(lldev->ring_channel[index], option); + } + + LEAVE_FUNCTION + + return 0; +} + + +/****************************************** + * Function: dmamap_cb + * Parameters: Parameter passed from dmamap + * function, Segment, Number of + * segments, error (if any) + * Return: None + * Description: Callback function used for + * DMA mapping + ******************************************/ +void +dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ + if(!error) { + *(bus_addr_t *) arg = segs->ds_addr; + } +} + +/****************************************** + * Function: xgell_reset + * Parameters: Per adapter xgelldev_t + * structure pointer + * Return: HAL status code/EPERM + * Description: Resets the device + ******************************************/ +void +xgell_reset(xgelldev_t *lldev) +{ + device_t dev = lldev->device; + + ENTER_FUNCTION + + xge_trace(XGE_TRACE, "Reseting the chip"); + + mtx_lock(&lldev->xge_lock); + + /* If the device is not initialized, return */ + if(!lldev->initialized) { + goto xreset_out; + } + + xge_terminate(dev, XGE_HAL_CHANNEL_OC_NORMAL); + + xge_initialize(dev, XGE_HAL_CHANNEL_OC_NORMAL); + +xreset_out: + LEAVE_FUNCTION + mtx_unlock(&lldev->xge_lock); + + return; +} + +/****************************************** + * Function: xge_setmulti + * Parameters: Per adapter xgelldev_t + * structure pointer + * Return: None + * Description: Set an address as a multicast + * address + ******************************************/ +void +xge_setmulti(xgelldev_t *lldev) +{ + ENTER_FUNCTION + struct ifmultiaddr *ifma; + u8 *lladdr; + xge_hal_device_t *hldev = (xge_hal_device_t *)lldev->devh; + struct ifnet *ifnetp = lldev->ifnetp; + int index = 0; + int offset = 1; + int table_size = 47; + xge_hal_status_e status = XGE_HAL_OK; + u8 initial_addr[]= {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + if((ifnetp->if_flags & IFF_MULTICAST) && (!lldev->all_multicast)) { + status = xge_hal_device_mcast_enable(hldev); + lldev->all_multicast = 1; + } + else if((ifnetp->if_flags & IFF_MULTICAST) && (lldev->all_multicast)) { + status = xge_hal_device_mcast_disable(hldev); + lldev->all_multicast = 0; + } + + if(status != XGE_HAL_OK) { + printf("Failed to %s multicast (status: %d)\n", + (ifnetp->if_flags & IFF_ALLMULTI ? "enable" : "disable"), + status); + } + + /* Updating address list */ + IF_ADDR_LOCK(ifnetp); + index = 0; + TAILQ_FOREACH(ifma, &ifnetp->if_multiaddrs, ifma_link) { + if(ifma->ifma_addr->sa_family != AF_LINK) { + continue; + } + lladdr = LLADDR((struct sockaddr_dl *)ifma->ifma_addr); + index += 1; + } + IF_ADDR_UNLOCK(ifnetp); + + if((!lldev->all_multicast) && (index)) { + lldev->macaddr_count = (index + 1); + if(lldev->macaddr_count > table_size) { + return; + } + + /* Clear old addresses */ + for(index = 0; index < 48; index++) { + xge_hal_device_macaddr_set(hldev, (offset + index), + initial_addr); + } + } + + /* Add new addresses */ + IF_ADDR_LOCK(ifnetp); + index = 0; + TAILQ_FOREACH(ifma, &ifnetp->if_multiaddrs, ifma_link) { + if(ifma->ifma_addr->sa_family != AF_LINK) { + continue; + } + lladdr = LLADDR((struct sockaddr_dl *)ifma->ifma_addr); + xge_hal_device_macaddr_set(hldev, (offset + index), lladdr); + index += 1; + } + IF_ADDR_UNLOCK(ifnetp); + + LEAVE_FUNCTION +} + +/****************************************** + * Function: xge_enable_promisc + * Parameters: Adapter structure + * Return: None + * Description: Enables promiscuous mode + ******************************************/ +void +xge_enable_promisc(xgelldev_t *lldev) +{ + struct ifnet *ifnetp = lldev->ifnetp; + xge_hal_device_t *hldev = lldev->devh; + xge_hal_pci_bar0_t *bar0 = NULL; + u64 val64 = 0; + + ENTER_FUNCTION + + bar0 = (xge_hal_pci_bar0_t *) hldev->bar0; + + if(ifnetp->if_flags & IFF_PROMISC) { + xge_hal_device_promisc_enable(lldev->devh); + + /* + * When operating in promiscuous mode, don't strip the VLAN tag + */ + val64 = xge_os_pio_mem_read64(lldev->pdev, hldev->regh0, + &bar0->rx_pa_cfg); + val64 &= ~XGE_HAL_RX_PA_CFG_STRIP_VLAN_TAG_MODE(1); + val64 |= XGE_HAL_RX_PA_CFG_STRIP_VLAN_TAG_MODE(0); + xge_os_pio_mem_write64(lldev->pdev, hldev->regh0, val64, + &bar0->rx_pa_cfg); + + xge_trace(XGE_TRACE, "Promiscuous mode ON"); + } + + LEAVE_FUNCTION +} + +/****************************************** + * Function: xge_disable_promisc + * Parameters: Adapter structure + * Return: None + * Description: Disables promiscuous mode + ******************************************/ +void +xge_disable_promisc(xgelldev_t *lldev) +{ + xge_hal_device_t *hldev = lldev->devh; + xge_hal_pci_bar0_t *bar0 = NULL; + u64 val64 = 0; + + ENTER_FUNCTION + + bar0 = (xge_hal_pci_bar0_t *) hldev->bar0; + + xge_hal_device_promisc_disable(lldev->devh); + + /* + * Strip VLAN tag when operating in non-promiscuous mode + */ + val64 = xge_os_pio_mem_read64(lldev->pdev, hldev->regh0, + &bar0->rx_pa_cfg); + val64 &= ~XGE_HAL_RX_PA_CFG_STRIP_VLAN_TAG_MODE(1); + val64 |= XGE_HAL_RX_PA_CFG_STRIP_VLAN_TAG_MODE(1); + xge_os_pio_mem_write64(lldev->pdev, hldev->regh0, val64, + &bar0->rx_pa_cfg); + + xge_trace(XGE_TRACE, "Promiscuous mode OFF"); + + LEAVE_FUNCTION +} + +/****************************************** + * Function: changeMtu + * Parameters: Pointer to per-device + * xgelldev_t structure, New + * MTU size. + * Return: None + * Description: Changes MTU size to requested + ******************************************/ +int +changeMtu(xgelldev_t *lldev, int NewMtu) +{ + struct ifnet *ifnetp = lldev->ifnetp; + xge_hal_device_t *hldev = lldev->devh; + int retValue = 0; + + ENTER_FUNCTION + + do { + /* Check requested MTU size for boundary */ + if(xge_hal_device_mtu_check(hldev, NewMtu) != XGE_HAL_OK) { + xge_trace(XGE_ERR, "Invalid MTU"); + retValue = EINVAL; + break; + } + + if(lldev->initialized != 0) { + mtx_lock(&lldev->xge_lock); + if_down(ifnetp); + xge_stop(lldev); + ifnetp->if_mtu = NewMtu; + changeBufmode(lldev, NewMtu); + xge_init_locked((void *)lldev); + if_up(ifnetp); + mtx_unlock(&lldev->xge_lock); + } + else { + ifnetp->if_mtu = NewMtu; + changeBufmode(lldev, NewMtu); + } + } while(FALSE); + + LEAVE_FUNCTION + return retValue; +} + +/****************************************** + * Function: changeBufmode + * Parameters: Pointer to per-device + * xgelldev_t structure, New + * MTU size. + * Return: None + * Description: Updates RingConfiguration structure + * depending the NewMtu size. + ******************************************/ +int +changeBufmode (xgelldev_t *lldev, int NewMtu) +{ + xge_hal_ring_config_t * pRingConfig; + xge_hal_device_t *hldev = lldev->devh; + device_t dev = lldev->device; + int buffer_length = 0, buffer_index = 0, index; + + pRingConfig = &(hldev->config.ring); + xge_os_memzero(lldev->rxd_mbuf_len, sizeof(lldev->rxd_mbuf_len)); + + if((NewMtu + XGE_HAL_MAC_HEADER_MAX_SIZE) <= MJUMPAGESIZE) { +#if defined(XGE_FEATURE_BUFFER_MODE_3) + xge_os_printf("%s: 3 Buffer Mode Enabled", + device_get_nameunit(dev)); + for(index = 0; index < XGE_RING_COUNT; index++) { + pRingConfig->queue[index].buffer_mode = + XGE_HAL_RING_QUEUE_BUFFER_MODE_3; + } + pRingConfig->scatter_mode = XGE_HAL_RING_QUEUE_SCATTER_MODE_A; + lldev->buffer_mode = XGE_HAL_RING_QUEUE_BUFFER_MODE_3; + lldev->rxd_mbuf_len[0] = XGE_HAL_MAC_HEADER_MAX_SIZE; + lldev->rxd_mbuf_len[1] = XGE_HAL_TCPIP_HEADER_MAX_SIZE; + lldev->rxd_mbuf_len[2] = NewMtu; + lldev->rxd_mbuf_cnt = 3; +#else +#if defined(XGE_FEATURE_BUFFER_MODE_2) + xge_os_printf("%s: 2 Buffer Mode Enabled", + device_get_nameunit(dev)); + for(index = 0; index < XGE_RING_COUNT; index++) { + pRingConfig->queue[index].buffer_mode = + XGE_HAL_RING_QUEUE_BUFFER_MODE_3; + } + pRingConfig->scatter_mode = XGE_HAL_RING_QUEUE_SCATTER_MODE_B; + lldev->buffer_mode = XGE_HAL_RING_QUEUE_BUFFER_MODE_2; + lldev->rxd_mbuf_len[0] = XGE_HAL_MAC_HEADER_MAX_SIZE; + lldev->rxd_mbuf_len[1] = NewMtu; + lldev->rxd_mbuf_cnt = 2; +#else + for(index = 0; index < XGE_RING_COUNT; index++) { + pRingConfig->queue[index].buffer_mode = + XGE_HAL_RING_QUEUE_BUFFER_MODE_1; + } + pRingConfig->scatter_mode = XGE_HAL_RING_QUEUE_SCATTER_MODE_A; + lldev->buffer_mode = XGE_HAL_RING_QUEUE_BUFFER_MODE_1; + lldev->rxd_mbuf_len[0] = NewMtu; + lldev->rxd_mbuf_cnt = 1; +#endif +#endif + } + else { +#if defined(XGE_FEATURE_BUFFER_MODE_3) || defined (XGE_FEATURE_BUFFER_MODE_2) + xge_os_printf("2 or 3 Buffer mode is not supported for given MTU"); + xge_os_printf("So changing buffer mode to 5 buffer mode\n"); +#endif + xge_os_printf("%s: 5 Buffer Mode Enabled", + device_get_nameunit(dev)); + for(index = 0; index < XGE_RING_COUNT; index++) { + pRingConfig->queue[index].buffer_mode = + XGE_HAL_RING_QUEUE_BUFFER_MODE_5; + } + lldev->buffer_mode = XGE_HAL_RING_QUEUE_BUFFER_MODE_5; + buffer_length = NewMtu; + buffer_index = 2; + lldev->rxd_mbuf_len[0] = XGE_HAL_MAC_HEADER_MAX_SIZE; + lldev->rxd_mbuf_len[1] = XGE_HAL_TCPIP_HEADER_MAX_SIZE; + + while(buffer_length > MJUMPAGESIZE) { + buffer_length -= MJUMPAGESIZE; + lldev->rxd_mbuf_len[buffer_index] = MJUMPAGESIZE; + buffer_index++; + } + + BUFALIGN(buffer_length); + + lldev->rxd_mbuf_len[buffer_index] = buffer_length; + lldev->rxd_mbuf_cnt = buffer_index+1; + } + + return XGE_HAL_OK; +} + +/************************************************************* + * xge_initialize + * + * @dev: Device structure + * @option: Normal/Reset option for channels + * + * Called by both init and reset functions to enable device, interrupts, and to + * open channels. + * + **************************************************************/ +void xge_initialize(device_t dev, xge_hal_channel_reopen_e option) +{ + ENTER_FUNCTION + + struct ifaddr *ifaddrp; + struct sockaddr_dl *sockaddrp; + unsigned char *macaddr; + xgelldev_t *lldev = (xgelldev_t *) device_get_softc(dev); + xge_hal_device_t *hldev = lldev->devh; + struct ifnet *ifnetp = lldev->ifnetp; + int status = XGE_HAL_OK; + + xge_trace(XGE_TRACE, "Set MTU size"); + status = xge_hal_device_mtu_set(hldev, ifnetp->if_mtu); + if(status != XGE_HAL_OK) { + xge_trace(XGE_ERR, "Setting HAL device MTU failed (Status: %d)", + status); + goto init_sub_out; + } + + + /* Enable HAL device */ + xge_hal_device_enable(hldev); + + /* Get MAC address and update in HAL */ + ifaddrp = ifaddr_byindex(ifnetp->if_index); + sockaddrp = (struct sockaddr_dl *)ifaddrp->ifa_addr; + sockaddrp->sdl_type = IFT_ETHER; + sockaddrp->sdl_alen = ifnetp->if_addrlen; + macaddr = LLADDR(sockaddrp); + xge_trace(XGE_TRACE, + "Setting MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", + *macaddr, *(macaddr + 1), *(macaddr + 2), *(macaddr + 3), + *(macaddr + 4), *(macaddr + 5)); + status = xge_hal_device_macaddr_set(hldev, 0, macaddr); + if(status != XGE_HAL_OK) { + xge_trace(XGE_ERR, + "Setting MAC address failed (Status: %d)\n", status); + } + + /* Opening channels */ + mtx_unlock(&lldev->xge_lock); + status = xgell_channel_open(lldev, option); + mtx_lock(&lldev->xge_lock); + if(status != 0) { + goto init_sub_out; + } + + /* Set appropriate flags */ + ifnetp->if_drv_flags |= IFF_DRV_RUNNING; + ifnetp->if_flags &= ~IFF_DRV_OACTIVE; + + /* Checksum capability */ + ifnetp->if_hwassist = (ifnetp->if_capenable & IFCAP_TXCSUM) ? + (CSUM_TCP | CSUM_UDP) : 0; + +#ifdef XGE_FEATURE_TSO + if(ifnetp->if_capenable & IFCAP_TSO4) + ifnetp->if_hwassist |= CSUM_TSO; +#endif + + /* Enable interrupts */ + xge_hal_device_intr_enable(hldev); + + callout_reset(&lldev->timer, 10*hz, xge_timer, lldev); + + /* Disable promiscuous mode */ + xge_trace(XGE_TRACE, "If opted, enable promiscuous mode"); + xge_enable_promisc(lldev); + + /* Device is initialized */ + lldev->initialized = 1; + xge_os_mdelay(1000); + +init_sub_out: + LEAVE_FUNCTION + return; +} + +/******************************************************* + * xge_terminate + * + * @dev: Device structure + * @option: Normal/Reset option for channels + * + * Called by both stop and reset functions to disable device, interrupts, and to + * close channels. + ******************************************************/ +void xge_terminate(device_t dev, xge_hal_channel_reopen_e option) +{ + ENTER_FUNCTION + + xgelldev_t *lldev = (xgelldev_t *)device_get_softc(dev); + xge_hal_device_t *hldev = lldev->devh; + struct ifnet *ifnetp = lldev->ifnetp; + + /* Set appropriate flags */ + ifnetp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + + /* Stop timer */ + callout_stop(&lldev->timer); + + /* Disable interrupts */ + xge_hal_device_intr_disable(hldev); + + mtx_unlock(&lldev->xge_lock); + xge_queue_flush(xge_hal_device_queue(lldev->devh)); + mtx_lock(&lldev->xge_lock); + + /* Disable HAL device */ + if(xge_hal_device_disable(hldev) != XGE_HAL_OK) { + xge_trace(XGE_ERR, "Disabling HAL device failed"); + } + + /* Close Tx and Rx channels */ + xgell_channel_close(lldev, option); + + /* Reset HAL device */ + xge_hal_device_reset(hldev); + + xge_os_mdelay(1000); + lldev->initialized = 0; + + if_link_state_change(ifnetp, LINK_STATE_DOWN); + + LEAVE_FUNCTION +} + +/****************************************** + * Function: xgell_set_mbuf_cflags + * Parameters: mbuf structure pointer + * Return: None + * Description: This fuction will set the csum_flag of the mbuf + ******************************************/ +void xgell_set_mbuf_cflags(mbuf_t pkt) +{ + pkt->m_pkthdr.csum_flags = CSUM_IP_CHECKED; + pkt->m_pkthdr.csum_flags |= CSUM_IP_VALID; + pkt->m_pkthdr.csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); + pkt->m_pkthdr.csum_data = htons(0xffff); +} + +#ifdef XGE_FEATURE_LRO +/****************************************** + * Function: xgell_lro_flush_sessions + * Parameters: Per adapter xgelldev_t + * Return: None + * Description: This function will flush the LRO session and send the + * accumulated LRO packet to Upper layer. + ******************************************/ +void xgell_lro_flush_sessions(xgelldev_t *lldev) +{ + lro_t *lro; + struct ifnet *ifnetp = lldev->ifnetp; + xge_hal_device_t *hldev = (xge_hal_device_t *)lldev->devh; + + while (NULL != (lro = xge_hal_lro_get_next_session(hldev))) { + xgell_set_mbuf_cflags(lro->os_buf); + + /* Send it up */ + mtx_unlock(&lldev->xge_lock); + (*ifnetp->if_input)(ifnetp, lro->os_buf); + mtx_lock(&lldev->xge_lock); + + xge_hal_lro_close_session(lro); + } +} + +/****************************************** + * Function: xgell_accumulate_large_rx + * Parameters: Descriptor info structure, current mbuf structure, + * packet length, Per adapter structure, Rx Desc private structure + * Return: None + * Description: This function will accumulate packets to form the LRO + * packets based on various condition. + ******************************************/ +void xgell_accumulate_large_rx(xge_hal_dtr_info_t *ext_info,mbuf_t pkt, + int pkt_length, xgelldev_t *lldev, xgell_rx_priv_t *rxd_priv) +{ + tcplro_t *tcp; + lro_t *lro, *lro_end3; + xge_hal_status_e status; + unsigned char * temp; + struct ifnet *ifnetp = lldev->ifnetp; + + status = xge_hal_accumulate_large_rx(pkt->m_data, &tcp, &pkt_length, + &lro, ext_info, lldev->devh, &lro_end3); + pkt->m_next = NULL; + temp = (unsigned char *)tcp; + + if(status == XGE_HAL_INF_LRO_BEGIN) { + pkt->m_flags |= M_PKTHDR; + pkt->m_pkthdr.rcvif = ifnetp; + lro->os_buf = lro->os_buf_end = pkt; + } + else if(status == XGE_HAL_INF_LRO_CONT) { + /* + * Current mbuf will be combine to form LRO frame, + * So mask the pkthdr of the flag variable for current mbuf + */ + pkt->m_flags = pkt->m_flags & 0xFFFD; //Mask pkthdr + pkt->m_data = (u8 *)tcp; + pkt->m_len = pkt_length; + + /* + * Combine the current mbuf to the LRO frame and update + * the LRO's pkthdr len accordingly + */ + lro->os_buf_end->m_next = pkt; + lro->os_buf_end = pkt; + lro->os_buf->m_pkthdr.len += pkt_length; + } + else if(status == XGE_HAL_INF_LRO_END_2) { + lro->os_buf->m_flags |= M_EOR; + + /* Update the Checksum flags of the LRO frames */ + xgell_set_mbuf_cflags(lro->os_buf); + + /* Post-Read sync */ + bus_dmamap_sync(lldev->dma_tag_rx, rxd_priv->dmainfo[0].dma_map, + BUS_DMASYNC_POSTREAD); + + /* + * Current packet can not be combined with LRO frame. + * Flush the previous LRO frames and send the current packet + * seperately + */ + mtx_unlock(&lldev->xge_lock); + (*ifnetp->if_input)(ifnetp, lro->os_buf); + (*ifnetp->if_input)(ifnetp, pkt); + mtx_lock(&lldev->xge_lock); + xge_hal_lro_close_session(lro); + } + else if(status == XGE_HAL_INF_LRO_END_1) { + pkt->m_flags = pkt->m_flags & 0xFFFD; + pkt->m_data = (u8 *)tcp; + pkt->m_len = pkt_length; + lro->os_buf_end->m_next = pkt; + lro->os_buf->m_pkthdr.len += pkt_length; + xgell_set_mbuf_cflags(lro->os_buf); + lro->os_buf->m_flags |= M_EOR; + + /* Post-Read sync */ + bus_dmamap_sync(lldev->dma_tag_rx, rxd_priv->dmainfo[0].dma_map, + BUS_DMASYNC_POSTREAD); + + /* Send it up */ + mtx_unlock(&lldev->xge_lock); + (*ifnetp->if_input)(ifnetp, lro->os_buf); + mtx_lock(&lldev->xge_lock); + + xge_hal_lro_close_session(lro); + } + else if(status == XGE_HAL_INF_LRO_END_3) { + pkt->m_flags |= M_PKTHDR; + pkt->m_len = pkt_length; + pkt->m_pkthdr.len = pkt_length; + lro_end3->os_buf = lro_end3->os_buf_end = pkt; + lro->os_buf->m_flags |= M_EOR; + xgell_set_mbuf_cflags(lro->os_buf); + + /* Post-Read sync */ + bus_dmamap_sync(lldev->dma_tag_rx, rxd_priv->dmainfo[0].dma_map, + BUS_DMASYNC_POSTREAD); + + /* Send it up */ + mtx_unlock(&lldev->xge_lock); + (*ifnetp->if_input)(ifnetp, lro->os_buf); + mtx_lock(&lldev->xge_lock); + xge_hal_lro_close_session(lro); + } + else if((status == XGE_HAL_INF_LRO_UNCAPABLE) || + (status == XGE_HAL_INF_LRO_SESSIONS_XCDED)) { + pkt->m_flags |= M_PKTHDR; + pkt->m_len = pkt_length; + pkt->m_pkthdr.len = pkt_length; + + /* Post-Read sync */ + bus_dmamap_sync(lldev->dma_tag_rx, rxd_priv->dmainfo[0].dma_map, + BUS_DMASYNC_POSTREAD); + + /* Send it up */ + mtx_unlock(&lldev->xge_lock); + (*ifnetp->if_input)(ifnetp, pkt); + mtx_lock(&lldev->xge_lock); + } +} +#endif + +/****************************************** + * Function: xgell_rx_compl + * Parameters: Channel handle, descriptor, + * transfer code, userdata + * (not used) + * Return: HAL status code + * Description: If the interrupt is because + * of a received frame or if + * the receive ring contains + * fresh as yet un-processed + * frames, this function is + * called. + ******************************************/ +xge_hal_status_e +xgell_rx_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code, + void *userdata) +{ + xge_hal_dtr_info_t ext_info; + xge_hal_status_e status_code; + struct ifnet *ifnetp; + device_t dev; + int index; + mbuf_t mbuf_up = NULL; + xgell_rx_priv_t *rxd_priv = NULL, old_rxd_priv; + u16 vlan_tag; + +// ENTER_FUNCTION + + + /*get the user data portion*/ + xgelldev_t *lldev = xge_hal_channel_userdata(channelh); + if(!lldev) { + xge_ctrace(XGE_TRACE, "xgeX: %s: Failed to get user data", + __FUNCTION__); + return XGE_HAL_FAIL; + } + dev = lldev->device; + + mtx_assert((&lldev->xge_lock), MA_OWNED); + + /* get the interface pointer */ + ifnetp = lldev->ifnetp; + + do { + if(!(ifnetp->if_drv_flags & IFF_DRV_RUNNING)) { + return XGE_HAL_FAIL; + } + + if(t_code) { + xge_trace(XGE_TRACE, "Packet dropped because of %d", t_code); + xge_hal_device_handle_tcode(channelh, dtr, t_code); + xge_hal_ring_dtr_post(channelh,dtr); + continue; + } + + /* Get the private data for this descriptor*/ + rxd_priv = (xgell_rx_priv_t *) xge_hal_ring_dtr_private(channelh, + dtr); + if(!rxd_priv) { + xge_trace(XGE_ERR, "Failed to get descriptor private data"); + return XGE_HAL_FAIL; + } + + /* Taking backup of rxd_priv structure details of current packet */ + xge_os_memcpy(&old_rxd_priv, rxd_priv, sizeof(xgell_rx_priv_t)); + + /* Prepare one buffer to send it to upper layer -- since the upper + * layer frees the buffer do not use rxd_priv->buffer + * Meanwhile prepare a new buffer, do mapping, use it in the + * current descriptor and post descriptor back to ring channel */ + mbuf_up = rxd_priv->bufferArray[0]; + + /* Gets details of mbuf i.e., packet length */ + xge_ring_dtr_get(mbuf_up, channelh, dtr, lldev, rxd_priv); + + status_code = + (lldev->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_1) ? + xgell_get_buf(dtr, rxd_priv, lldev, 0) : + xgell_get_buf_3b_5b(dtr, rxd_priv, lldev); + + if(status_code != XGE_HAL_OK) { + xge_trace(XGE_ERR, "No memory"); + + /* + * Do not deliver the received buffer to the stack. Instead, + * Re-post the descriptor with the same buffer + */ + + /* Get back previous rxd_priv structure before posting */ + xge_os_memcpy(rxd_priv, &old_rxd_priv, sizeof(xgell_rx_priv_t)); + + xge_hal_ring_dtr_post(channelh, dtr); + continue; + } + + /* Get the extended information */ + xge_hal_ring_dtr_info_get(channelh, dtr, &ext_info); + + if(lldev->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_1) { + /* + * As we have allocated a new mbuf for this descriptor, post + * this descriptor with new mbuf back to ring channel + */ + vlan_tag = ext_info.vlan; + xge_hal_ring_dtr_post(channelh, dtr); + if ((!(ext_info.proto & XGE_HAL_FRAME_PROTO_IP_FRAGMENTED) && + (ext_info.proto & XGE_HAL_FRAME_PROTO_TCP_OR_UDP) && + (ext_info.l3_cksum == XGE_HAL_L3_CKSUM_OK) && + (ext_info.l4_cksum == XGE_HAL_L4_CKSUM_OK))) { + /* set Checksum Flag */ + xgell_set_mbuf_cflags(mbuf_up); +#ifdef XGE_FEATURE_LRO + if(lldev->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_1) { + xgell_accumulate_large_rx(&ext_info, mbuf_up, + mbuf_up->m_len, lldev, rxd_priv); + } +#else + /* Post-Read sync for buffers*/ + bus_dmamap_sync(lldev->dma_tag_rx, + rxd_priv->dmainfo[0].dma_map, BUS_DMASYNC_POSTREAD); + + /* Send it up */ + mtx_unlock(&lldev->xge_lock); + (*ifnetp->if_input)(ifnetp, mbuf_up); + mtx_lock(&lldev->xge_lock); +#endif + } + else { + /* + * Packet with erroneous checksum , let the upper layer + * deal with it + */ + + /* Post-Read sync for buffers*/ + bus_dmamap_sync(lldev->dma_tag_rx, + rxd_priv->dmainfo[0].dma_map, BUS_DMASYNC_POSTREAD); + +#ifdef XGE_FEATURE_LRO + xgell_lro_flush_sessions(lldev); +#endif + + if (vlan_tag) { + mbuf_up->m_pkthdr.ether_vtag = vlan_tag; + mbuf_up->m_flags |= M_VLANTAG; + } + /* Send it up */ + mtx_unlock(&lldev->xge_lock); + (*ifnetp->if_input)(ifnetp, mbuf_up); + mtx_lock(&lldev->xge_lock); + } + } + else { + /* + * As we have allocated a new mbuf for this descriptor, post + * this descriptor with new mbuf back to ring channel + */ + xge_hal_ring_dtr_post(channelh, dtr); + if ((!(ext_info.proto & XGE_HAL_FRAME_PROTO_IP_FRAGMENTED) && + (ext_info.proto & XGE_HAL_FRAME_PROTO_TCP_OR_UDP) && + (ext_info.l3_cksum == XGE_HAL_L3_CKSUM_OK) && + (ext_info.l4_cksum == XGE_HAL_L4_CKSUM_OK))) { + /* set Checksum Flag */ + xgell_set_mbuf_cflags(mbuf_up); +#ifdef XGE_FEATURE_LRO + if(lldev->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_1) { + xgell_accumulate_large_rx(&ext_info, mbuf_up, + mbuf_up->m_len, lldev, rxd_priv); + } +#else + /* Post-Read sync for buffers*/ + for(index = 0; index < lldev->rxd_mbuf_cnt; index++) { + /* Post-Read sync */ + bus_dmamap_sync(lldev->dma_tag_rx, + rxd_priv->dmainfo[index].dma_map, + BUS_DMASYNC_POSTREAD); + } + + /* Send it up */ + mtx_unlock(&lldev->xge_lock); + (*ifnetp->if_input)(ifnetp, mbuf_up); + mtx_lock(&lldev->xge_lock); +#endif + } + else { + /* + * Packet with erroneous checksum , let the upper layer + * deal with it + */ + for(index = 0; index < lldev->rxd_mbuf_cnt; index++) { + /* Post-Read sync */ + bus_dmamap_sync(lldev->dma_tag_rx, + rxd_priv->dmainfo[index].dma_map, + BUS_DMASYNC_POSTREAD); + } + +#ifdef XGE_FEATURE_LRO + xgell_lro_flush_sessions(lldev); +#endif + /* Send it up */ + mtx_unlock(&lldev->xge_lock); + (*ifnetp->if_input)(ifnetp, mbuf_up); + mtx_lock(&lldev->xge_lock); + } + } + } while(xge_hal_ring_dtr_next_completed(channelh, &dtr, &t_code) + == XGE_HAL_OK); +#ifdef XGE_FEATURE_LRO + xgell_lro_flush_sessions(lldev); +#endif + +// LEAVE_FUNCTION + + return XGE_HAL_OK; +} + +/****************************************** + * Function: xge_ring_dtr_get + * Parameters: mbuf pointer, channel handler + * descriptot, Per adapter xgelldev_t + * structure pointer, + * Rx private structure + * Return: HAL status code + * Description: Updates the mbuf lengths + * depending on packet lengths. + ******************************************/ +int +xge_ring_dtr_get(mbuf_t mbuf_up, xge_hal_channel_h channelh, xge_hal_dtr_h dtr, + xgelldev_t *lldev, xgell_rx_priv_t *rxd_priv) +{ + mbuf_t m; + int pkt_length[5]={0,0}, pkt_len=0; + dma_addr_t dma_data[5]; + int index; + + m = mbuf_up; + pkt_len = 0; + + if(lldev->buffer_mode != XGE_HAL_RING_QUEUE_BUFFER_MODE_1) { + xge_os_memzero(pkt_length, sizeof(pkt_length)); + + /* + * Retrieve data of interest from the completed descriptor -- This + * returns the packet length + */ + if(lldev->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_5) { + xge_hal_ring_dtr_5b_get(channelh, dtr, dma_data, pkt_length); + } + else { + xge_hal_ring_dtr_3b_get(channelh, dtr, dma_data, pkt_length); + } + + for(index = 0; index < lldev->rxd_mbuf_cnt; index++) { + m->m_len = pkt_length[index]; + + if(index < (lldev->rxd_mbuf_cnt-1)) { + m->m_next = rxd_priv->bufferArray[index + 1]; + m = m->m_next; + } + else { + m->m_next = NULL; + } + pkt_len+=pkt_length[index]; + } + + /* + * Since 2 buffer mode is an exceptional case where data is in 3rd + * buffer but not in 2nd buffer + */ + if(lldev->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_2) { + m->m_len = pkt_length[2]; + pkt_len+=pkt_length[2]; + } + + /* + * Update length of newly created buffer to be sent up with packet + * length + */ + mbuf_up->m_pkthdr.len = pkt_len; + } + else { + /* + * Retrieve data of interest from the completed descriptor -- This + * returns the packet length + */ + xge_hal_ring_dtr_1b_get(channelh, dtr,&dma_data[0], &pkt_length[0]); + + /* + * Update length of newly created buffer to be sent up with packet + * length + */ + mbuf_up->m_len = mbuf_up->m_pkthdr.len = pkt_length[0]; + } + +return XGE_HAL_OK; +} + + +/****************************************** + * Function: xge_send + * Parameters: Pointer to ifnet structure + * Return: None + * Description: Transmit entry point + ******************************************/ +void +xge_send(struct ifnet *ifnetp) +{ + xgelldev_t *lldev = ifnetp->if_softc; + + mtx_lock(&lldev->xge_lock); + xge_send_locked(ifnetp); + mtx_unlock(&lldev->xge_lock); +} + +void +xge_send_locked(struct ifnet *ifnetp) +{ + xge_hal_dtr_h dtr; + static bus_dma_segment_t segs[MAX_SEGS]; + xge_hal_status_e status_code; + unsigned int max_fragments; + xgelldev_t *lldev = ifnetp->if_softc; + xge_hal_channel_h channelh = lldev->fifo_channel_0; + mbuf_t m_head = NULL; + mbuf_t m_buf = NULL; + xgell_tx_priv_t *ll_tx_priv = NULL; + register unsigned int count = 0; + unsigned int nsegs = 0; + u16 vlan_tag; + + max_fragments = ((xge_hal_fifo_t *)channelh)->config->max_frags; + + mtx_assert((&lldev->xge_lock), MA_OWNED); + + /* If device is not initialized, return */ + if((!lldev->initialized) || + (!(ifnetp->if_drv_flags & IFF_DRV_RUNNING))) { + xge_trace(XGE_ERR, "Device is not initialized"); + return; + } + + /* + * Get the number of free descriptors in the FIFO channel and return if + * the count is less than the XGELL_TX_LEVEL_LOW -- the low threshold + */ + count = xge_hal_channel_dtr_count(channelh); + if(count <= XGELL_TX_LEVEL_LOW) { + ifnetp->if_drv_flags |= IFF_DRV_OACTIVE; + xge_trace(XGE_TRACE, "Free descriptor count %d/%d at low threshold", + count, XGELL_TX_LEVEL_LOW); + + /* Serialized -- through queue */ + xge_queue_produce_context(xge_hal_device_queue(lldev->devh), + XGE_LL_EVENT_TRY_XMIT_AGAIN, lldev); + return; + } + + /* This loop will be executed for each packet in the kernel maintained + * queue -- each packet can be with fragments as an mbuf chain */ + while((ifnetp->if_snd.ifq_head) && + (xge_hal_channel_dtr_count(channelh) > XGELL_TX_LEVEL_LOW)) { + IF_DEQUEUE(&ifnetp->if_snd, m_head); + + for(count = 0, m_buf = m_head; m_buf != NULL; + m_buf = m_buf->m_next) { + if(m_buf->m_len) { + count += 1; + } + } + + if(count >= max_fragments) { + m_buf = m_defrag(m_head, M_DONTWAIT); + if(m_buf != NULL) { + m_head = m_buf; + } + } + + /* Reserve descriptors */ + status_code = xge_hal_fifo_dtr_reserve(channelh, &dtr); + if(status_code) { + switch(status_code) { + case XGE_HAL_INF_CHANNEL_IS_NOT_READY: + xge_trace(XGE_ERR, "Channel is not ready"); + break; + + case XGE_HAL_INF_OUT_OF_DESCRIPTORS: + xge_trace(XGE_ERR, "Out of descriptors"); + break; + + default: + xge_trace(XGE_ERR, + "Reserving (Tx) descriptors failed. Status %d", + status_code); + } + goto out2; + break; + } + + vlan_tag = (m_head->m_flags & M_VLANTAG) ? m_head->m_pkthdr.ether_vtag : 0; + xge_hal_fifo_dtr_vlan_set(dtr, vlan_tag); + + /* Update Tx private structure for this descriptor */ + ll_tx_priv = xge_hal_fifo_dtr_private(dtr); + ll_tx_priv->buffer = m_head; + + /* + * Do mapping -- Required DMA tag has been created in xge_init + * function and DMA maps have already been created in the + * xgell_tx_replenish function. + * Returns number of segments through nsegs + */ + if(bus_dmamap_load_mbuf_sg(lldev->dma_tag_tx, + ll_tx_priv->dma_map, m_head, segs, &nsegs, BUS_DMA_NOWAIT)) { + xge_trace(XGE_ERR, "DMA map load with segments failed"); + goto out2; + } + + /* Set descriptor buffer for header and each fragment/segment */ + count = 0; + do { + xge_hal_fifo_dtr_buffer_set(channelh, dtr, count, + (dma_addr_t)htole64(segs[count].ds_addr), + segs[count].ds_len); + count = count + 1; + } while(count < nsegs); + + /* Pre-write Sync of mapping */ + bus_dmamap_sync(lldev->dma_tag_tx, ll_tx_priv->dma_map, + BUS_DMASYNC_PREWRITE); + +#ifdef XGE_FEATURE_TSO + if((m_head->m_pkthdr.csum_flags & CSUM_TSO) != 0) { + xge_hal_fifo_dtr_mss_set(dtr, m_head->m_pkthdr.tso_segsz); + } +#endif + /* Checksum */ + if(ifnetp->if_hwassist > 0) { + xge_hal_fifo_dtr_cksum_set_bits(dtr, XGE_HAL_TXD_TX_CKO_IPV4_EN + | XGE_HAL_TXD_TX_CKO_TCP_EN | XGE_HAL_TXD_TX_CKO_UDP_EN); + } + + /* Post descriptor to FIFO channel */ + xge_hal_fifo_dtr_post(channelh, dtr); + + /* Send the same copy of mbuf packet to BPF (Berkely Packet Filter) + * listener so that we can use tools like tcpdump */ + ETHER_BPF_MTAP(ifnetp, m_head); + } + goto out1; +out2: + /* Prepend the packet back to queue */ + IF_PREPEND(&ifnetp->if_snd, m_head); +out1: + ifnetp->if_timer = 15; +} + +/****************************************** + * Function: xgell_get_buf + * Parameters: Per adapter xgelldev_t + * structure pointer, descriptor, + * Rx private structure, rxd_priv buffer + * buffer index for mapping + * Return: HAL status code + * Description: Gets buffer from system mbuf + * buffer pool. + ******************************************/ +int +xgell_get_buf(xge_hal_dtr_h dtrh, xgell_rx_priv_t *rxd_priv, + xgelldev_t *lldev, int index) +{ + register mbuf_t mp = NULL; + struct ifnet *ifnetp = lldev->ifnetp; + int retValue = XGE_HAL_OK; + bus_addr_t paddr; + int BUFLEN = 0, CLUSTLEN = 0; + + if(lldev->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_1) { + CLUSTLEN = MJUMPAGESIZE; + BUFLEN = MJUMPAGESIZE; + } + else { + BUFLEN = lldev->rxd_mbuf_len[index]; + if(BUFLEN < MCLBYTES) { + CLUSTLEN = MCLBYTES; + } + else { + CLUSTLEN = MJUMPAGESIZE; + } + } + + /* Get mbuf with attached cluster */ + mp = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, CLUSTLEN); + if(!mp) { + xge_trace(XGE_ERR, "Out of memory to allocate mbuf"); + retValue = XGE_HAL_FAIL; + goto getbuf_out; + } + + /* Update mbuf's length, packet length and receive interface */ + mp->m_len = mp->m_pkthdr.len = BUFLEN; + mp->m_pkthdr.rcvif = ifnetp; + + /* Unload DMA map of mbuf in current descriptor */ + bus_dmamap_unload(lldev->dma_tag_rx, rxd_priv->dmainfo[index].dma_map); + + /* Load DMA map */ + if(bus_dmamap_load(lldev->dma_tag_rx , rxd_priv->dmainfo[index].dma_map, + mtod(mp, void*), mp->m_len, dmamap_cb , &paddr , 0)) { + xge_trace(XGE_ERR, "Loading DMA map failed"); + m_freem(mp); + retValue = XGE_HAL_FAIL; + goto getbuf_out; + } + + /* Update descriptor private data */ + rxd_priv->bufferArray[index] = mp; + rxd_priv->dmainfo[index].dma_phyaddr = htole64(paddr); + + /* Pre-Read/Write sync */ + bus_dmamap_sync(lldev->dma_tag_rx, rxd_priv->dmainfo[index].dma_map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + + /* Set descriptor buffer */ + if(lldev->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_1) { + xge_hal_ring_dtr_1b_set(dtrh, rxd_priv->dmainfo[0].dma_phyaddr, + MJUMPAGESIZE); + } + +getbuf_out: + return retValue; +} + +/****************************************** + * Function: xgell_get_buf_3b_5b + * Parameters: Per adapter xgelldev_t + * structure pointer, descriptor, + * Rx private structure + * Return: HAL status code + * Description: Gets buffers from system mbuf + * buffer pool. + ******************************************/ +int +xgell_get_buf_3b_5b(xge_hal_dtr_h dtrh, xgell_rx_priv_t *rxd_priv, + xgelldev_t *lldev) +{ + bus_addr_t dma_pointers[5]; + int dma_sizes[5]; + int retValue = XGE_HAL_OK, index; + int newindex = 0; + + for(index = 0; index < lldev->rxd_mbuf_cnt; index++) { + retValue = xgell_get_buf(dtrh, rxd_priv, lldev, index); + if(retValue != XGE_HAL_OK) { + for(newindex = 0; newindex < index; newindex++) { + m_freem(rxd_priv->bufferArray[newindex]); + } + return retValue; + } + } + + for(index = 0; index < lldev->buffer_mode; index++) { + if(lldev->rxd_mbuf_len[index] != 0) { + dma_pointers[index] = rxd_priv->dmainfo[index].dma_phyaddr; + dma_sizes[index] = lldev->rxd_mbuf_len[index]; + } + else { + dma_pointers[index] = rxd_priv->dmainfo[index-1].dma_phyaddr; + dma_sizes[index] = 1; + } + } + + /* Assigning second buffer to third pointer in 2 buffer mode */ + if(lldev->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_2) { + dma_pointers[2] = dma_pointers[1]; + dma_sizes[2] = dma_sizes[1]; + dma_sizes[1] = 1; + } + + if(lldev->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_5) { + xge_hal_ring_dtr_5b_set(dtrh, dma_pointers, dma_sizes); + } + else { + xge_hal_ring_dtr_3b_set(dtrh, dma_pointers, dma_sizes); + } + + return retValue; +} + +/****************************************** + * Function: xgell_tx_compl + * Parameters: Channel handle, descriptor, + * transfer code, + * userdata -> per adapter + * xgelldev_t structure as void * + * Return: HAL status code + * Description: If an interrupt was raised + * to indicate DMA complete of + * the Tx packet, this function + * is called. It identifies the + * last TxD whose buffer was + * freed and frees all skbs + * whose data have already DMA'ed + * into the NICs internal memory. + ******************************************/ +xge_hal_status_e +xgell_tx_compl(xge_hal_channel_h channelh, + xge_hal_dtr_h dtr, u8 t_code, void *userdata) +{ + xgell_tx_priv_t *ll_tx_priv; + mbuf_t m_buffer; + xgelldev_t *lldev = (xgelldev_t *)userdata; + struct ifnet *ifnetp = lldev->ifnetp; + + ifnetp->if_timer = 0; + + /* For each completed descriptor: Get private structure, free buffer, + * do unmapping, and free descriptor */ + do { + if(t_code) { + xge_trace(XGE_TRACE, "t_code %d", t_code); + xge_hal_device_handle_tcode(channelh, dtr, t_code); + } + + ll_tx_priv = xge_hal_fifo_dtr_private(dtr); + m_buffer = ll_tx_priv->buffer; + bus_dmamap_unload(lldev->dma_tag_tx, ll_tx_priv->dma_map); + m_freem(m_buffer); + ll_tx_priv->buffer = NULL; + xge_hal_fifo_dtr_free(channelh, dtr); + } while(xge_hal_fifo_dtr_next_completed(channelh, &dtr, &t_code) + == XGE_HAL_OK); + ifnetp->if_drv_flags &= ~IFF_DRV_OACTIVE; + + return XGE_HAL_OK; +} + +/****************************************** + * Function: xgell_tx_initial_replenish + * Parameters: Channel handle, descriptor, + * index (not used), userdata + * (not used), channel + * open/close/reopen option. + * Return: HAL status code + * Description: Creates DMA maps to be used + * for Tx + ******************************************/ +xge_hal_status_e +xgell_tx_initial_replenish(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + int index, void *userdata, xge_hal_channel_reopen_e reopen) +{ + xgell_tx_priv_t *txd_priv = NULL; + int retValue = XGE_HAL_OK; + device_t dev = NULL; + + /* Get the user data portion from channel handle */ + xgelldev_t *lldev = xge_hal_channel_userdata(channelh); + if(lldev == NULL) { + xge_trace(XGE_ERR, "Failed to get user data"); + retValue = XGE_HAL_FAIL; + goto txinit_out; + } + dev = lldev->device; + + /* Get the private data */ + txd_priv = (xgell_tx_priv_t *) xge_hal_fifo_dtr_private(dtrh); + if(txd_priv == NULL) { + xge_trace(XGE_ERR, "Failed to get descriptor private data"); + retValue = XGE_HAL_FAIL; + goto txinit_out; + } + + /* Create DMA map for this descriptor */ + if(bus_dmamap_create(lldev->dma_tag_tx, BUS_DMA_NOWAIT, + &txd_priv->dma_map)) { + xge_trace(XGE_ERR, "DMA map creation for Tx descriptor failed"); + retValue = XGE_HAL_FAIL; + goto txinit_out; + } + +txinit_out: + return retValue; +} + +/****************************************** + * Function: xgell_rx_initial_replenish + * Parameters: Channel handle, descriptor, + * ring index, userdata + * (not used), channel + * open/close/reopen option. + * Return: HAL status code + * Description: Replenish descriptor with + * rx_buffer in Rx buffer pool. + ******************************************/ +xge_hal_status_e +xgell_rx_initial_replenish(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + int index, void *userdata, xge_hal_channel_reopen_e reopen) +{ + xgell_rx_priv_t *rxd_priv = NULL; + int retValue = XGE_HAL_OK; + struct ifnet *ifnetp; + device_t dev; + int index1, index2; + + /* Get the user data portion from channel handle */ + xgelldev_t *lldev = xge_hal_channel_userdata(channelh); + if(lldev == NULL) { + xge_ctrace(XGE_ERR, "xgeX: %s: Failed to get user data", + __FUNCTION__); + retValue = XGE_HAL_FAIL; + goto rxinit_out; + } + dev = lldev->device; + + /* Get the private data */ + rxd_priv = (xgell_rx_priv_t *) xge_hal_ring_dtr_private(channelh, dtrh); + if(rxd_priv == NULL) { + xge_trace(XGE_ERR, "Failed to get descriptor private data"); + retValue = XGE_HAL_FAIL; + goto rxinit_out; + } + + rxd_priv->bufferArray = + malloc(((sizeof(rxd_priv->bufferArray)) * (lldev->rxd_mbuf_cnt)), + M_DEVBUF, M_NOWAIT); + + if(rxd_priv->bufferArray == NULL) { + xge_trace(XGE_ERR, + "Failed to allocate buffers for Rxd private structure"); + retValue = XGE_HAL_FAIL; + goto rxinit_out; + } + + ifnetp = lldev->ifnetp; + + if(lldev->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_1) { + /* Create DMA map for these descriptors*/ + if(bus_dmamap_create(lldev->dma_tag_rx , BUS_DMA_NOWAIT, + &rxd_priv->dmainfo[0].dma_map)) { + xge_trace(XGE_ERR, + "DMA map creation for Rx descriptor failed"); + retValue = XGE_HAL_FAIL; + goto rxinit_err_out; + } + /* Get a buffer, attach it to this descriptor */ + retValue = xgell_get_buf(dtrh, rxd_priv, lldev, 0); + } + else { + for(index1 = 0; index1 < lldev->rxd_mbuf_cnt; index1++) { + /* Create DMA map for this descriptor */ + if(bus_dmamap_create(lldev->dma_tag_rx , BUS_DMA_NOWAIT , + &rxd_priv->dmainfo[index1].dma_map)) { + xge_trace(XGE_ERR, + "Jumbo DMA map creation for Rx descriptor failed"); + for(index2 = index1 - 1; index2 >= 0; index2--) { + bus_dmamap_destroy(lldev->dma_tag_rx, + rxd_priv->dmainfo[index2].dma_map); + } + retValue = XGE_HAL_FAIL; + goto rxinit_err_out; + } + } + retValue = xgell_get_buf_3b_5b(dtrh, rxd_priv, lldev); + } + + if(retValue != XGE_HAL_OK) { + for(index1 = 0; index1 < lldev->rxd_mbuf_cnt; index1++) { + bus_dmamap_destroy(lldev->dma_tag_rx, + rxd_priv->dmainfo[index1].dma_map); + } + goto rxinit_err_out; + } + else { + goto rxinit_out; + } + +rxinit_err_out: + free(rxd_priv->bufferArray,M_DEVBUF); +rxinit_out: + return retValue; +} + +/****************************************** + * Function: xgell_rx_term + * Parameters: Channel handle, descriptor, + * descriptor state, userdata + * (not used), channel + * open/close/reopen option. + * Return: None + * Description: Called by HAL to terminate + * all DTRs for ring channels. + ******************************************/ +void +xgell_rx_term(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + xge_hal_dtr_state_e state, void *userdata, + xge_hal_channel_reopen_e reopen) +{ + xgell_rx_priv_t *rxd_priv; + xgelldev_t *lldev; + struct ifnet *ifnetp; + device_t dev; + int index; + +// ENTER_FUNCTION + + /* Descriptor state is not "Posted" */ + if(state != XGE_HAL_DTR_STATE_POSTED) { + xge_ctrace(XGE_ERR, "xgeX: %s: Descriptor not posted\n", + __FUNCTION__); + goto rxterm_out; + } + + /* Get the user data portion */ + lldev = xge_hal_channel_userdata(channelh); + + dev = lldev->device; + ifnetp = lldev->ifnetp; + + /* Get the private data */ + rxd_priv = (xgell_rx_priv_t *) xge_hal_ring_dtr_private(channelh, dtrh); + + if(lldev->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_1) { + /* Post-Read sync */ + bus_dmamap_sync(lldev->dma_tag_rx, rxd_priv->dmainfo[0].dma_map, + BUS_DMASYNC_POSTREAD); + + /* Do unmapping and destory DMA map */ + bus_dmamap_unload(lldev->dma_tag_rx, rxd_priv->dmainfo[0].dma_map); + m_freem(rxd_priv->bufferArray[0]); + bus_dmamap_destroy(lldev->dma_tag_rx, rxd_priv->dmainfo[0].dma_map); + } + else { + for(index = 0; index < lldev->rxd_mbuf_cnt; index++) { + /* Post-Read sync */ + bus_dmamap_sync(lldev->dma_tag_rx, + rxd_priv->dmainfo[index].dma_map, BUS_DMASYNC_POSTREAD); + + /* Do unmapping and destory DMA map */ + bus_dmamap_unload(lldev->dma_tag_rx, + rxd_priv->dmainfo[index].dma_map); + + bus_dmamap_destroy(lldev->dma_tag_rx, + rxd_priv->dmainfo[index].dma_map); + + /* Free the buffer */ + m_free(rxd_priv->bufferArray[index]); + } + } + free(rxd_priv->bufferArray,M_DEVBUF); + + /* Free the descriptor */ + xge_hal_ring_dtr_free(channelh, dtrh); + +rxterm_out: +// LEAVE_FUNCTION + return; +} + + +/****************************************** + * Function: xgell_tx_term + * Parameters: Channel handle, descriptor, + * descriptor state, userdata + * (not used), channel + * open/close/reopen option. + * Return: None + * Description: Called by HAL to terminate + * all DTRs for fifo channels. + ******************************************/ +void +xgell_tx_term(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, + xge_hal_dtr_state_e state, void *userdata, + xge_hal_channel_reopen_e reopen) +{ + xgell_tx_priv_t *ll_tx_priv = xge_hal_fifo_dtr_private(dtr); + xgelldev_t *lldev = (xgelldev_t *)userdata; + +// ENTER_FUNCTION + + /* Destroy DMA map */ + bus_dmamap_destroy(lldev->dma_tag_tx, ll_tx_priv->dma_map); + +// LEAVE_FUNCTION +} + +/****************************************** + * xge_methods + * + * FreeBSD device interface entry points + ******************************************/ +static device_method_t xge_methods[] = { + DEVMETHOD(device_probe, xge_probe), + DEVMETHOD(device_attach, xge_attach), + DEVMETHOD(device_detach, xge_detach), + DEVMETHOD(device_shutdown, xge_shutdown), + {0, 0} +}; + +static driver_t xge_driver = { + "nxge", + xge_methods, + sizeof(xgelldev_t), +}; +static devclass_t xge_devclass; +DRIVER_MODULE(nxge, pci, xge_driver, xge_devclass, 0, 0); diff --git a/sys/dev/nxge/if_nxge.h b/sys/dev/nxge/if_nxge.h new file mode 100644 index 0000000..1e99a62 --- /dev/null +++ b/sys/dev/nxge/if_nxge.h @@ -0,0 +1,287 @@ +/*- + * 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$ + */ + +/* + * if_xge.h + */ + +#ifndef _IF_XGE_H +#define _IF_XGE_H + +#include <dev/nxge/include/xgehal.h> +#include <dev/nxge/xge-osdep.h> + +#if defined(XGE_FEATURE_TSO) && (__FreeBSD_version < 700026) +#undef XGE_FEATURE_TSO +#endif + +#if defined(XGE_FEATURE_LRO) +#if __FreeBSD_version < 700047 +#undef XGE_FEATURE_LRO +#undef XGE_HAL_CONFIG_LRO +#else +#define XGE_HAL_CONFIG_LRO +#endif +#endif + +#ifdef FUNC_PRINT +#define ENTER_FUNCTION xge_os_printf("Enter\t==>[%s]\n", __FUNCTION__); +#define LEAVE_FUNCTION xge_os_printf("Leave\t<==[%s]\n", __FUNCTION__); +#else +#define ENTER_FUNCTION +#define LEAVE_FUNCTION +#endif + +/* Printing description, Copyright */ +#define DRIVER_VERSION XGELL_VERSION_MAJOR"." \ + XGELL_VERSION_MINOR"." \ + XGELL_VERSION_FIX"." \ + XGELL_VERSION_BUILD +#define COPYRIGHT_STRING "Copyright(c) 2002-2007 Neterion Inc." +#define PRINT_COPYRIGHT xge_os_printf("%s", COPYRIGHT_STRING) + +/* Printing */ +#define xge_trace(trace, fmt, args...) xge_debug_ll(trace, fmt, ## args); +#define xge_ctrace(trace, fmt...) xge_debug_ll(trace, fmt); + +#define BUFALIGN(buffer_length) \ + if((buffer_length % 128) != 0) { \ + buffer_length += (128 - (buffer_length % 128)); \ + } + +static inline void * +xge_malloc(unsigned long size) { + void *vaddr = malloc(size, M_DEVBUF, M_NOWAIT); + bzero(vaddr, size); + return vaddr; +} + +#define SINGLE_ALLOC 0 +#define MULTI_ALLOC 1 +#define SAVE 0 +#define RESTORE 1 +#define UP 1 +#define DOWN 0 +#define XGE_DEFAULT_USER_HARDCODED -1 +#define MAX_MBUF_FRAGS 20 /* Maximum number of fragments */ +#define MAX_SEGS 100 /* Maximum number of segments */ +#define XGELL_TX_LEVEL_LOW 16 +#define XGE_RING_COUNT XGE_HAL_MIN_RING_NUM +#define BUFFER_SIZE 20 + +/* Default values to configuration parameters */ +#define XGE_DEFAULT_INITIAL_MTU 1500 +#define XGE_DEFAULT_LATENCY_TIMER -1 +#define XGE_DEFAULT_MAX_SPLITS_TRANS -1 +#define XGE_DEFAULT_MMRB_COUNT -1 +#define XGE_DEFAULT_SHARED_SPLITS 0 +#define XGE_DEFAULT_ISR_POLLING_CNT 8 +#define XGE_DEFAULT_STATS_REFRESH_TIME_SEC 4 +#define XGE_DEFAULT_MAC_RMAC_BCAST_EN 1 +#define XGE_DEFAULT_MAC_TMAC_UTIL_PERIOD 5 +#define XGE_DEFAULT_MAC_RMAC_UTIL_PERIOD 5 +#define XGE_DEFAULT_MAC_RMAC_PAUSE_GEN_EN 1 +#define XGE_DEFAULT_MAC_RMAC_PAUSE_RCV_EN 1 +#define XGE_DEFAULT_MAC_RMAC_PAUSE_TIME 65535 +#define XGE_DEFAULT_MAC_MC_PAUSE_THRESHOLD_Q0Q3 187 +#define XGE_DEFAULT_MAC_MC_PAUSE_THRESHOLD_Q4Q7 187 +#define XGE_DEFAULT_FIFO_MEMBLOCK_SIZE PAGE_SIZE +#define XGE_DEFAULT_FIFO_RESERVE_THRESHOLD 0 +#define XGE_DEFAULT_FIFO_MAX_FRAGS 64 +#define XGE_DEFAULT_FIFO_QUEUE_INTR 0 +#define XGE_DEFAULT_FIFO_QUEUE_MAX 2048 +#define XGE_DEFAULT_FIFO_QUEUE_INITIAL 2048 +#define XGE_DEFAULT_FIFO_QUEUE_TTI_URANGE_A 5 +#define XGE_DEFAULT_FIFO_QUEUE_TTI_URANGE_B 10 +#define XGE_DEFAULT_FIFO_QUEUE_TTI_URANGE_C 20 +#define XGE_DEFAULT_FIFO_QUEUE_TTI_UFC_A 15 +#define XGE_DEFAULT_FIFO_QUEUE_TTI_UFC_B 30 +#define XGE_DEFAULT_FIFO_QUEUE_TTI_UFC_C 45 +#define XGE_DEFAULT_FIFO_QUEUE_TTI_UFC_D 60 +#define XGE_DEFAULT_FIFO_QUEUE_TTI_TIMER_CI_EN 1 +#define XGE_DEFAULT_FIFO_QUEUE_TTI_TIMER_AC_EN 1 +#define XGE_DEFAULT_FIFO_QUEUE_TTI_TIMER_VAL_US 8000 +#define XGE_DEFAULT_FIFO_ALIGNMENT_SIZE sizeof(u64) +#define XGE_DEFAULT_RING_MEMBLOCK_SIZE PAGE_SIZE +#define XGE_DEFAULT_RING_STRIP_VLAN_TAG 1 +#define XGE_DEFAULT_RING_QUEUE_MAX 16 +#define XGE_DEFAULT_RING_QUEUE_INITIAL 16 +#define XGE_DEFAULT_RING_QUEUE_DRAM_SIZE_MB 32 +#define XGE_DEFAULT_RING_QUEUE_INDICATE_MAX_PKTS 16 +#define XGE_DEFAULT_RING_QUEUE_BACKOFF_INTERVAL_US 1000 +#define XGE_DEFAULT_RING_QUEUE_RTI_URANGE_A 5 +#define XGE_DEFAULT_RING_QUEUE_RTI_URANGE_B 10 +#define XGE_DEFAULT_RING_QUEUE_RTI_URANGE_C 50 +#define XGE_DEFAULT_RING_QUEUE_RTI_UFC_A 1 +#define XGE_DEFAULT_RING_QUEUE_RTI_UFC_B 8 +#define XGE_DEFAULT_RING_QUEUE_RTI_UFC_C 16 +#define XGE_DEFAULT_RING_QUEUE_RTI_UFC_D 32 +#define XGE_DEFAULT_RING_QUEUE_RTI_TIMER_AC_EN 1 +#define XGE_DEFAULT_RING_QUEUE_RTI_TIMER_VAL_US 250 + +/* Values to identify the requests from getinfo tool in ioctl */ +#define XGE_QUERY_STATS 1 +#define XGE_QUERY_PCICONF 2 +#define XGE_QUERY_INTRSTATS 3 +#define XGE_QUERY_DEVCONF 4 +#define XGE_READ_VERSION 5 +#define XGE_QUERY_TCODE 6 +#define XGE_SET_BUFFER_MODE_1 7 +#define XGE_SET_BUFFER_MODE_2 8 +#define XGE_SET_BUFFER_MODE_3 9 +#define XGE_SET_BUFFER_MODE_5 10 +#define XGE_QUERY_BUFFER_MODE 11 + +#define XGE_OFFSET_OF_LAST_REG 0x3180 + +#define VENDOR_ID_AMD 0x1022 +#define DEVICE_ID_8131_PCI_BRIDGE 0x7450 + +typedef struct mbuf *mbuf_t; + +typedef enum xgell_event_e { + XGE_LL_EVENT_TRY_XMIT_AGAIN = XGE_LL_EVENT_BASE + 1, + XGE_LL_EVENT_DEVICE_RESETTING = XGE_LL_EVENT_BASE + 2, +} xgell_event_e; + +/* Adapter structure */ +typedef struct xgelldev { + device_t device; /* Device */ + struct ifnet *ifnetp; /* Interface ifnet structure */ + struct resource *irq; /* Resource structure for IRQ */ + void *irqhandle; /* IRQ handle */ + pci_info_t *pdev; + struct ifmedia xge_media; /* In-kernel representation of a */ + /* single supported media type */ + xge_hal_device_t *devh; /* HAL: Device Handle */ + xge_hal_channel_h ring_channel[XGE_HAL_MAX_FIFO_NUM]; + /* Ring channel */ + xge_hal_channel_h fifo_channel_0; /* FIFO channel */ + struct mtx xge_lock; /* Mutex - Default */ + struct callout timer; /* Timer for polling */ + struct xge_hal_stats_hw_info_t *hwstats; /* Hardware Statistics */ + int saved_regs[16]; /* To save register space */ + int xge_mtu; /* MTU */ + int initialized; /* Flag: Initialized or not */ + bus_dma_tag_t dma_tag_tx; /* Tag for dtr dma mapping (Tx) */ + bus_dma_tag_t dma_tag_rx; /* Tag for dtr dma mapping (Rx) */ + int all_multicast; /* All multicast flag */ + int macaddr_count; /* Multicast address count */ + int in_detach; /* To avoid ioctl during detach */ + int buffer_mode; /* Buffer Mode */ + int rxd_mbuf_cnt; /* Number of buffers used */ + int rxd_mbuf_len[5];/* Buffer lengths */ +} xgelldev_t; + +/* Rx descriptor private structure */ +typedef struct { + mbuf_t *bufferArray; + struct xge_dma_mbuf dmainfo[5]; +} xgell_rx_priv_t; + +/* Tx descriptor private structure */ +typedef struct { + mbuf_t buffer; + bus_dmamap_t dma_map; +} xgell_tx_priv_t; + +/* BAR0 Register */ +typedef struct barregister { + char option[2]; + u64 offset; + u64 value; +}bar0reg_t; + +void xge_init_params(xge_hal_device_config_t *dconfig, device_t dev); +void xge_init(void *); +void xge_init_locked(void *); +void xge_stop(xgelldev_t *); +void freeResources(device_t, int); +void xgell_callback_link_up(void *); +void xgell_callback_link_down(void *); +void xgell_callback_crit_err(void *, xge_hal_event_e, u64); +void xgell_callback_event(xge_queue_item_t *); +int xge_ifmedia_change(struct ifnet *); +void xge_ifmedia_status(struct ifnet *, struct ifmediareq *); +int xge_ioctl(struct ifnet *, unsigned long, caddr_t); +void xge_timer(void *); +int xge_intr_filter(void *); +void xge_intr(void *); +int xgell_rx_open(int, xgelldev_t *, xge_hal_channel_reopen_e); +int xgell_tx_open(xgelldev_t *, xge_hal_channel_reopen_e); +int xgell_channel_close(xgelldev_t *, xge_hal_channel_reopen_e); +int xgell_channel_open(xgelldev_t *, xge_hal_channel_reopen_e); +xge_hal_status_e xgell_rx_compl(xge_hal_channel_h, xge_hal_dtr_h, u8, void *); +xge_hal_status_e xgell_tx_compl(xge_hal_channel_h, xge_hal_dtr_h, u8, void *); +xge_hal_status_e xgell_tx_initial_replenish(xge_hal_channel_h, xge_hal_dtr_h, + int, void *, xge_hal_channel_reopen_e); +xge_hal_status_e xgell_rx_initial_replenish(xge_hal_channel_h, xge_hal_dtr_h, + int, void *, xge_hal_channel_reopen_e); +void xgell_rx_term(xge_hal_channel_h, xge_hal_dtr_h, xge_hal_dtr_state_e, + void *, xge_hal_channel_reopen_e); +void xgell_tx_term(xge_hal_channel_h, xge_hal_dtr_h, xge_hal_dtr_state_e, + void *, xge_hal_channel_reopen_e); +void xgell_set_mbuf_cflags(mbuf_t); +void xge_send(struct ifnet *); +void xge_send_locked(struct ifnet *); +int xgell_get_multimode_normalbuf(xge_hal_dtr_h dtrh, xgell_rx_priv_t *rxd_priv, + xgelldev_t *lldev); +int xgell_get_multimode_jumbobuf(xge_hal_dtr_h dtrh, xgell_rx_priv_t *rxd_priv, + xgelldev_t *lldev, int lock); +int xgell_get_second_buffer(xgell_rx_priv_t *rxd_priv, xgelldev_t *lldev); +int xgell_get_buf(xge_hal_dtr_h dtrh, xgell_rx_priv_t *rxd_priv, + xgelldev_t *lldev, int index); +int xge_ring_dtr_get(mbuf_t mbuf_up, xge_hal_channel_h channelh, xge_hal_dtr_h dtr, + xgelldev_t *lldev, xgell_rx_priv_t *rxd_priv); +int xgell_get_buf_3b_5b(xge_hal_dtr_h dtrh, xgell_rx_priv_t *rxd_priv, + xgelldev_t *lldev); +void dmamap_cb(void *, bus_dma_segment_t *, int, int); +void xgell_reset(xgelldev_t *); +void xge_setmulti(xgelldev_t *); +void xge_enable_promisc(xgelldev_t *); +void xge_disable_promisc(xgelldev_t *); +int changeMtu(xgelldev_t *, int); +int changeBufmode(xgelldev_t *, int); +void xge_initialize(device_t, xge_hal_channel_reopen_e); +void xge_terminate(device_t, xge_hal_channel_reopen_e); +void if_up_locked(xgelldev_t *); +void if_down_locked(xgelldev_t *); +int xge_probe(device_t); +int xge_driver_initialize(void); +void xge_media_init(device_t); +void xge_pci_space_save(device_t); +void xge_pci_space_restore(device_t); +int xge_attach(device_t); +int xge_interface_setup(device_t); +int xge_detach(device_t); +int xge_shutdown(device_t); +int xge_suspend(device_t); +int xge_resume(device_t); + +#endif // _IF_XGE_H + diff --git a/sys/dev/nxge/include/build-version.h b/sys/dev/nxge/include/build-version.h new file mode 100644 index 0000000..b9b5e00 --- /dev/null +++ b/sys/dev/nxge/include/build-version.h @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +#ifndef BUILD_VERSION_H +#define BUILD_VERSION_H +/* Do not edit! Automatically generated when released.*/ +#define GENERATED_BUILD_VERSION "10294" +#endif /* BUILD_VERSION_H */ diff --git a/sys/dev/nxge/include/version.h b/sys/dev/nxge/include/version.h new file mode 100644 index 0000000..0a212f4 --- /dev/null +++ b/sys/dev/nxge/include/version.h @@ -0,0 +1,53 @@ +/*- + * 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$ + */ + +/* + * FileName : version.h + * + * Description: versioning file + * + * Created: 3 September 2004 + */ + +#ifndef VERSION_H +#define VERSION_H + +#include <dev/nxge/include/build-version.h> + +#define XGE_HAL_VERSION_MAJOR "2" +#define XGE_HAL_VERSION_MINOR "5" +#define XGE_HAL_VERSION_FIX "0" +#define XGE_HAL_VERSION_BUILD GENERATED_BUILD_VERSION +#define XGE_HAL_VERSION XGE_HAL_VERSION_MAJOR"."XGE_HAL_VERSION_MINOR"."\ + XGE_HAL_VERSION_FIX"."XGE_HAL_VERSION_BUILD +#define XGE_HAL_DESC XGE_DRIVER_NAME" v."XGE_HAL_VERSION + +/* Link Layer versioning */ +#include <dev/nxge/xgell-version.h> + +#endif /* VERSION_H */ diff --git a/sys/dev/nxge/include/xge-debug.h b/sys/dev/nxge/include/xge-debug.h new file mode 100644 index 0000000..a4efbcb --- /dev/null +++ b/sys/dev/nxge/include/xge-debug.h @@ -0,0 +1,568 @@ +/*- + * 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$ + */ + +/* + * FileName : xge-debug.h + * + * Description: debug facilities + * + * Created: 6 May 2004 + */ + +#ifndef XGE_DEBUG_H +#define XGE_DEBUG_H + +#include <dev/nxge/include/xge-os-pal.h> + +__EXTERN_BEGIN_DECLS + +/* + * __FUNCTION__ is, together with __PRETTY_FUNCTION__ or something similar, + * a gcc extension. we'll have to #ifdef around that, and provide some + * meaningful replacement for those, so to make some gcc versions happier + */ +#ifndef __func__ +#ifdef __FUNCTION__ +#define __func__ __FUNCTION__ +#endif +#endif + + +#ifdef XGE_DEBUG_FP +#define XGE_DEBUG_FP_DEVICE 0x1 +#define XGE_DEBUG_FP_CHANNEL 0x2 +#define XGE_DEBUG_FP_FIFO 0x4 +#define XGE_DEBUG_FP_RING 0x8 +#endif + +/** + * enum xge_debug_level_e + * @XGE_NONE: debug disabled + * @XGE_ERR: all errors going to be logged out + * @XGE_TRACE: all errors plus all kind of verbose tracing print outs + * going to be logged out. Very noisy. + * + * This enumeration going to be used to switch between different + * debug levels during runtime if DEBUG macro defined during + * compilation. If DEBUG macro not defined than code will be + * compiled out. + */ +typedef enum xge_debug_level_e { + XGE_NONE = 0, + XGE_TRACE = 1, + XGE_ERR = 2, +} xge_debug_level_e; + +#define XGE_DEBUG_MODULE_MASK_DEF 0x30000030 +#define XGE_DEBUG_LEVEL_DEF XGE_ERR + +#if defined(XGE_DEBUG_TRACE_MASK) || defined(XGE_DEBUG_ERR_MASK) + +extern unsigned long *g_module_mask; +extern int *g_level; + +#ifndef XGE_DEBUG_TRACE_MASK +#define XGE_DEBUG_TRACE_MASK 0 +#endif + +#ifndef XGE_DEBUG_ERR_MASK +#define XGE_DEBUG_ERR_MASK 0 +#endif + +/* + * @XGE_COMPONENT_HAL_CONFIG: do debug for xge core config module + * @XGE_COMPONENT_HAL_FIFO: do debug for xge core fifo module + * @XGE_COMPONENT_HAL_RING: do debug for xge core ring module + * @XGE_COMPONENT_HAL_CHANNEL: do debug for xge core channel module + * @XGE_COMPONENT_HAL_DEVICE: do debug for xge core device module + * @XGE_COMPONENT_HAL_DMQ: do debug for xge core DMQ module + * @XGE_COMPONENT_HAL_UMQ: do debug for xge core UMQ module + * @XGE_COMPONENT_HAL_SQ: do debug for xge core SQ module + * @XGE_COMPONENT_HAL_SRQ: do debug for xge core SRQ module + * @XGE_COMPONENT_HAL_CQRQ: do debug for xge core CRQ module + * @XGE_COMPONENT_HAL_POOL: do debug for xge core memory pool module + * @XGE_COMPONENT_HAL_BITMAP: do debug for xge core BITMAP module + * @XGE_COMPONENT_CORE: do debug for xge KMA core module + * @XGE_COMPONENT_OSDEP: do debug for xge KMA os dependent parts + * @XGE_COMPONENT_LL: do debug for xge link layer module + * @XGE_COMPONENT_ALL: activate debug for all modules with no exceptions + * + * This enumeration going to be used to distinguish modules + * or libraries during compilation and runtime. Makefile must declare + * XGE_DEBUG_MODULE_MASK macro and set it to proper value. + */ +#define XGE_COMPONENT_HAL_CONFIG 0x00000001 +#define XGE_COMPONENT_HAL_FIFO 0x00000002 +#define XGE_COMPONENT_HAL_RING 0x00000004 +#define XGE_COMPONENT_HAL_CHANNEL 0x00000008 +#define XGE_COMPONENT_HAL_DEVICE 0x00000010 +#define XGE_COMPONENT_HAL_MM 0x00000020 +#define XGE_COMPONENT_HAL_QUEUE 0x00000040 +#define XGE_COMPONENT_HAL_INTERRUPT 0x00000080 +#define XGE_COMPONENT_HAL_STATS 0x00000100 +#ifdef XGEHAL_RNIC +#define XGE_COMPONENT_HAL_DMQ 0x00000200 +#define XGE_COMPONENT_HAL_UMQ 0x00000400 +#define XGE_COMPONENT_HAL_SQ 0x00000800 +#define XGE_COMPONENT_HAL_SRQ 0x00001000 +#define XGE_COMPONENT_HAL_CQRQ 0x00002000 +#define XGE_COMPONENT_HAL_POOL 0x00004000 +#define XGE_COMPONENT_HAL_BITMAP 0x00008000 +#endif + + /* space for CORE_XXX */ +#define XGE_COMPONENT_OSDEP 0x10000000 +#define XGE_COMPONENT_LL 0x20000000 +#define XGE_COMPONENT_ALL 0xffffffff + +#ifndef XGE_DEBUG_MODULE_MASK +#error "XGE_DEBUG_MODULE_MASK macro must be defined for DEBUG mode..." +#endif + +#ifndef __GNUC__ +#ifdef XGE_TRACE_INTO_CIRCULAR_ARR + #define xge_trace_aux(fmt) xge_os_vatrace(g_xge_os_tracebuf, fmt) +#else + #define xge_trace_aux(fmt) xge_os_vaprintf(fmt) +#endif + +/** + * xge_debug + * @level: level of debug verbosity. + * @fmt: printf like format string + * + * Provides logging facilities. Can be customized on per-module + * basis or/and with debug levels. Input parameters, except + * module and level, are the same as posix printf. This function + * may be compiled out if DEBUG macro was never defined. + * See also: xge_debug_level_e{}. + */ +#define xge_debug(module, level, fmt) { \ +if (((level >= XGE_TRACE && ((module & XGE_DEBUG_TRACE_MASK) == module)) || \ + (level >= XGE_ERR && ((module & XGE_DEBUG_ERR_MASK) == module))) && \ + level >= *g_level && module & *(unsigned int *)g_module_mask) { \ + xge_trace_aux(fmt); \ + } \ +} +#else /* __GNUC__ */ + +#ifdef XGE_TRACE_INTO_CIRCULAR_ARR + #define xge_trace_aux(fmt...) xge_os_trace(g_xge_os_tracebuf, fmt) +#else + #define xge_trace_aux(fmt...) xge_os_printf(fmt) +#endif + +#define xge_debug(module, level, fmt...) { \ +if (((level >= XGE_TRACE && ((module & XGE_DEBUG_TRACE_MASK) == module)) || \ + (level >= XGE_ERR && ((module & XGE_DEBUG_ERR_MASK) == module))) && \ + level >= *g_level && module & *(unsigned int *)g_module_mask) { \ + xge_trace_aux(fmt); \ + } \ +} +#endif /* __GNUC__ */ + +#if (XGE_COMPONENT_HAL_STATS & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_stats(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_STATS; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_stats(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_STATS, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_stats(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_stats(level, fmt...) +#endif /* __GNUC__ */ +#endif + +/* Interrupt Related */ +#if (XGE_COMPONENT_HAL_INTERRUPT & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_interrupt(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_INTERRUPT; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_interrupt(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_INTERRUPT, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_interrupt(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_interrupt(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_HAL_QUEUE & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_queue(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_QUEUE; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_queue(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_QUEUE, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_queue(xge_debug_level_e level, char *fmt, +...) {} +#else /* __GNUC__ */ +#define xge_debug_queue(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_HAL_MM & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_mm(xge_debug_level_e level, char *fmt, ...) +{ + u32 module = XGE_COMPONENT_HAL_MM; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_mm(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_MM, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_mm(xge_debug_level_e level, char *fmt, ...) +{} +#else /* __GNUC__ */ +#define xge_debug_mm(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_HAL_CONFIG & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_config(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_CONFIG; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_config(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_CONFIG, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_config(xge_debug_level_e level, char *fmt, +...) {} +#else /* __GNUC__ */ +#define xge_debug_config(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_HAL_FIFO & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_fifo(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_FIFO; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_fifo(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_FIFO, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_fifo(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_fifo(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_HAL_RING & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_ring(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_RING; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_ring(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_RING, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_ring(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_ring(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_HAL_CHANNEL & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_channel(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_CHANNEL; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_channel(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_CHANNEL, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_channel(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_channel(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_HAL_DEVICE & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_device(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_DEVICE; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_device(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_DEVICE, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_device(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_device(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#ifdef XGEHAL_RNIC + +#if (XGE_COMPONENT_HAL_DMQ & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_dmq(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_DMQ; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_dmq(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_DMQ, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_dmq(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_dmq(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_HAL_UMQ & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_umq(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_UMQ; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_umq(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_UMQ, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_umq(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_umq(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_HAL_SQ & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_sq(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_SQ; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_sq(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_SQ, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_sq(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_sq(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_HAL_SRQ & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_srq(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_SRQ; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_srq(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_SRQ, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_srq(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_srq(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_HAL_CQRQ & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_cqrq(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_CQRQ; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_cqrq(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_CQRQ, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_cqrq(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_cqrq(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_HAL_POOL & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_pool(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_POOL; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_pool(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_POOL, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_pool(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_pool(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_HAL_BITMAP & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_bitmap(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_HAL_BITMAP; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_bitmap(level, fmt...) \ + xge_debug(XGE_COMPONENT_HAL_BITMAP, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_bitmap(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_bitmap(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#endif + +#if (XGE_COMPONENT_OSDEP & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_osdep(xge_debug_level_e level, char *fmt, ...) { + u32 module = XGE_COMPONENT_OSDEP; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_osdep(level, fmt...) \ + xge_debug(XGE_COMPONENT_OSDEP, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_osdep(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_osdep(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#if (XGE_COMPONENT_LL & XGE_DEBUG_MODULE_MASK) +#ifndef __GNUC__ +static inline void xge_debug_ll(xge_debug_level_e level, char *fmt, ...) +{ + u32 module = XGE_COMPONENT_LL; + xge_debug(module, level, fmt); +} +#else /* __GNUC__ */ +#define xge_debug_ll(level, fmt...) \ + xge_debug(XGE_COMPONENT_LL, level, fmt) +#endif /* __GNUC__ */ +#else +#ifndef __GNUC__ +static inline void xge_debug_ll(xge_debug_level_e level, char *fmt, ...) {} +#else /* __GNUC__ */ +#define xge_debug_ll(level, fmt...) +#endif /* __GNUC__ */ +#endif + +#else + +static inline void xge_debug_interrupt(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_stats(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_queue(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_mm(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_config(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_fifo(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_ring(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_channel(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_device(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_dmq(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_umq(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_sq(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_srq(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_cqrq(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_pool(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_bitmap(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_hal(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_osdep(xge_debug_level_e level, char *fmt, ...) {} +static inline void xge_debug_ll(xge_debug_level_e level, char *fmt, ...) {} + +#endif /* end of XGE_DEBUG_*_MASK */ + +#ifdef XGE_DEBUG_ASSERT + +/** + * xge_assert + * @test: C-condition to check + * @fmt: printf like format string + * + * This function implements traditional assert. By default assertions + * are enabled. It can be disabled by defining XGE_DEBUG_ASSERT macro in + * compilation + * time. + */ +#define xge_assert(test) { \ + if (!(test)) xge_os_bug("bad cond: "#test" at %s:%d\n", \ + __FILE__, __LINE__); } +#else +#define xge_assert(test) +#endif /* end of XGE_DEBUG_ASSERT */ + +__EXTERN_END_DECLS + +#endif /* XGE_DEBUG_H */ diff --git a/sys/dev/nxge/include/xge-defs.h b/sys/dev/nxge/include/xge-defs.h new file mode 100644 index 0000000..744a6b9 --- /dev/null +++ b/sys/dev/nxge/include/xge-defs.h @@ -0,0 +1,149 @@ +/*- + * 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$ + */ + +/* + * FileName : xge-defs.h + * + * Description: global definitions + * + * Created: 13 May 2004 + */ + +#ifndef XGE_DEFS_H +#define XGE_DEFS_H + +#define XGE_PCI_VENDOR_ID 0x17D5 +#define XGE_PCI_DEVICE_ID_XENA_1 0x5731 +#define XGE_PCI_DEVICE_ID_XENA_2 0x5831 +#define XGE_PCI_DEVICE_ID_HERC_1 0x5732 +#define XGE_PCI_DEVICE_ID_HERC_2 0x5832 +#define XGE_PCI_DEVICE_ID_TITAN_1 0x5733 +#define XGE_PCI_DEVICE_ID_TITAN_2 0x5833 + +#define XGE_DRIVER_NAME "Xge driver" +#define XGE_DRIVER_VENDOR "Neterion, Inc" +#define XGE_CHIP_FAMILY "Xframe" +#define XGE_SUPPORTED_MEDIA_0 "Fiber" + +#include <dev/nxge/include/version.h> + +#if defined(__cplusplus) +#define __EXTERN_BEGIN_DECLS extern "C" { +#define __EXTERN_END_DECLS } +#else +#define __EXTERN_BEGIN_DECLS +#define __EXTERN_END_DECLS +#endif + +__EXTERN_BEGIN_DECLS + +/*---------------------------- DMA attributes ------------------------------*/ +/* Used in xge_os_dma_malloc() and xge_os_dma_map() */ +/*---------------------------- DMA attributes ------------------------------*/ + +/* XGE_OS_DMA_REQUIRES_SYNC - should be defined or + NOT defined in the Makefile */ +#define XGE_OS_DMA_CACHELINE_ALIGNED 0x1 +/* Either STREAMING or CONSISTENT should be used. + The combination of both or none is invalid */ +#define XGE_OS_DMA_STREAMING 0x2 +#define XGE_OS_DMA_CONSISTENT 0x4 +#define XGE_OS_SPRINTF_STRLEN 64 + +/*---------------------------- common stuffs -------------------------------*/ + +#define XGE_OS_LLXFMT "%llx" +#define XGE_OS_NEWLINE "\n" +#ifdef XGE_OS_MEMORY_CHECK +typedef struct { + void *ptr; + int size; + char *file; + int line; +} xge_os_malloc_t; + +#define XGE_OS_MALLOC_CNT_MAX 64*1024 +extern xge_os_malloc_t g_malloc_arr[XGE_OS_MALLOC_CNT_MAX]; +extern int g_malloc_cnt; + +#define XGE_OS_MEMORY_CHECK_MALLOC(_vaddr, _size, _file, _line) { \ + if (_vaddr) { \ + int i; \ + for (i=0; i<g_malloc_cnt; i++) { \ + if (g_malloc_arr[i].ptr == NULL) { \ + break; \ + } \ + } \ + if (i == g_malloc_cnt) { \ + g_malloc_cnt++; \ + if (g_malloc_cnt >= XGE_OS_MALLOC_CNT_MAX) { \ + xge_os_bug("g_malloc_cnt exceed %d", \ + XGE_OS_MALLOC_CNT_MAX); \ + } \ + } \ + g_malloc_arr[i].ptr = _vaddr; \ + g_malloc_arr[i].size = _size; \ + g_malloc_arr[i].file = _file; \ + g_malloc_arr[i].line = _line; \ + for (i=0; i<_size; i++) { \ + *((char *)_vaddr+i) = 0x5a; \ + } \ + } \ +} + +#define XGE_OS_MEMORY_CHECK_FREE(_vaddr, _check_size) { \ + int i; \ + for (i=0; i<XGE_OS_MALLOC_CNT_MAX; i++) { \ + if (g_malloc_arr[i].ptr == _vaddr) { \ + g_malloc_arr[i].ptr = NULL; \ + if(_check_size && g_malloc_arr[i].size!=_check_size) { \ + xge_os_printf("OSPAL: freeing with wrong " \ + "size %d! allocated at %s:%d:"XGE_OS_LLXFMT":%d", \ + (int)_check_size, \ + 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); \ + } \ + break; \ + } \ + } \ + if (i == XGE_OS_MALLOC_CNT_MAX) { \ + xge_os_printf("OSPAL: ptr "XGE_OS_LLXFMT" not found!", \ + (unsigned long long)(ulong_t)_vaddr); \ + } \ +} +#else +#define XGE_OS_MEMORY_CHECK_MALLOC(ptr, size, file, line) +#define XGE_OS_MEMORY_CHECK_FREE(vaddr, check_size) +#endif + +__EXTERN_END_DECLS + +#endif /* XGE_DEFS_H */ diff --git a/sys/dev/nxge/include/xge-list.h b/sys/dev/nxge/include/xge-list.h new file mode 100644 index 0000000..c49424d --- /dev/null +++ b/sys/dev/nxge/include/xge-list.h @@ -0,0 +1,203 @@ +/*- + * 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$ + */ + +/* + * FileName : xge-list.h + * + * Description: Generic bi-directional linked list implementation + * + * Created: 14 May 2004 + */ + +#ifndef XGE_LIST_H +#define XGE_LIST_H + +#include <dev/nxge/include/xge-debug.h> + +__EXTERN_BEGIN_DECLS + +/** + * struct xge_list_t - List item. + * @prev: Previous list item. + * @next: Next list item. + * + * Item of a bi-directional linked list. + */ +typedef struct xge_list_t { + struct xge_list_t* prev; + struct xge_list_t* next; +} xge_list_t; + +/** + * xge_list_init - Initialize linked list. + * header: first element of the list (head) + * + * Initialize linked list. + * See also: xge_list_t{}. + */ +static inline void xge_list_init (xge_list_t *header) +{ + header->next = header; + header->prev = header; +} + +/** + * xge_list_is_empty - Is the list empty? + * header: first element of the list (head) + * + * Determine whether the bi-directional list is empty. Return '1' in + * case of 'empty'. + * See also: xge_list_t{}. + */ +static inline int xge_list_is_empty(xge_list_t *header) +{ + xge_assert(header != NULL); + + return header->next == header; +} + +/** + * xge_list_first_get - Return the first item from the linked list. + * header: first element of the list (head) + * + * Returns the next item from the header. + * Returns NULL if the next item is header itself + * See also: xge_list_remove(), xge_list_insert(), xge_list_t{}. + */ +static inline xge_list_t *xge_list_first_get(xge_list_t *header) +{ + xge_assert(header != NULL); + xge_assert(header->next != NULL); + xge_assert(header->prev != NULL); + + if(header->next == header) + return NULL; + else + return header->next; +} + +/** + * xge_list_remove - Remove the specified item from the linked list. + * item: element of the list + * + * Remove item from a list. + * See also: xge_list_insert(), xge_list_t{}. + */ +static inline void xge_list_remove(xge_list_t *item) +{ + xge_assert(item != NULL); + xge_assert(item->next != NULL); + xge_assert(item->prev != NULL); + + item->next->prev = item->prev; + item->prev->next = item->next; +#ifdef XGE_DEBUG_ASSERT + item->next = item->prev = NULL; +#endif +} + +/** + * xge_list_insert - Insert a new item after the specified item. + * new_item: new element of the list + * prev_item: element of the list after which the new element is + * inserted + * + * Insert new item (new_item) after given item (prev_item). + * See also: xge_list_remove(), xge_list_insert_before(), xge_list_t{}. + */ +static inline void xge_list_insert (xge_list_t *new_item, + xge_list_t *prev_item) +{ + xge_assert(new_item != NULL); + xge_assert(prev_item != NULL); + xge_assert(prev_item->next != NULL); + + new_item->next = prev_item->next; + new_item->prev = prev_item; + prev_item->next->prev = new_item; + prev_item->next = new_item; +} + +/** + * xge_list_insert_before - Insert a new item before the specified item. + * new_item: new element of the list + * next_item: element of the list after which the new element is inserted + * + * Insert new item (new_item) before given item (next_item). + */ +static inline void xge_list_insert_before (xge_list_t *new_item, + xge_list_t *next_item) +{ + xge_assert(new_item != NULL); + xge_assert(next_item != NULL); + xge_assert(next_item->next != NULL); + + new_item->next = next_item; + new_item->prev = next_item->prev; + next_item->prev->next = new_item; + next_item->prev = new_item; +} + +#define xge_list_for_each(_p, _h) \ + for (_p = (_h)->next, xge_os_prefetch(_p->next); _p != (_h); \ + _p = _p->next, xge_os_prefetch(_p->next)) + +#define xge_list_for_each_safe(_p, _n, _h) \ + for (_p = (_h)->next, _n = _p->next; _p != (_h); \ + _p = _n, _n = _p->next) + +#ifdef __GNUC__ +/** + * xge_container_of - Given a member, return the containing structure. + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + * Cast a member of a structure out to the containing structure. + */ +#define xge_container_of(ptr, type, member) ({ \ + __typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)(void *)( (char *)__mptr - ((size_t) &((type *)0)->member) );}) +#else +/* type unsafe version */ +#define xge_container_of(ptr, type, member) \ + ((type*)(void*)((char*)(ptr) - ((size_t) &((type *)0)->member))) +#endif + +/** + * xge_offsetof - Offset of the member in the containing structure. + * @t: struct name. + * @m: the name of the member within the struct. + * + * Return the offset of the member @m in the structure @t. + */ +#define xge_offsetof(t, m) ((size_t) (&((t *)0)->m)) + +__EXTERN_END_DECLS + +#endif /* XGE_LIST_H */ diff --git a/sys/dev/nxge/include/xge-os-pal.h b/sys/dev/nxge/include/xge-os-pal.h new file mode 100644 index 0000000..5c92fe6 --- /dev/null +++ b/sys/dev/nxge/include/xge-os-pal.h @@ -0,0 +1,138 @@ +/*- + * 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$ + */ + +/* + * FileName : xge-os-pal.h + * + * Description: top-level header file. works just like switching between + * os-depndent parts + * + * Created: 6st May 2004 + */ + +#ifndef XGE_OS_PAL_H +#define XGE_OS_PAL_H + +#include <dev/nxge/include/xge-defs.h> + +__EXTERN_BEGIN_DECLS + +/*--------------------------- platform switch ------------------------------*/ + +/* platform specific header */ +#include <dev/nxge/xge-osdep.h> +#ifdef XGEHAL_RNIC +#define IN +#define OUT +#endif + +#if !defined(XGE_OS_PLATFORM_64BIT) && !defined(XGE_OS_PLATFORM_32BIT) +#error "either 32bit or 64bit switch must be defined!" +#endif + +#if !defined(XGE_OS_HOST_BIG_ENDIAN) && !defined(XGE_OS_HOST_LITTLE_ENDIAN) +#error "either little endian or big endian switch must be defined!" +#endif + +#if defined(XGE_OS_PLATFORM_64BIT) +#define XGE_OS_MEMORY_DEADCODE_PAT 0x5a5a5a5a5a5a5a5a +#else +#define XGE_OS_MEMORY_DEADCODE_PAT 0x5a5a5a5a +#endif + +#define XGE_OS_TRACE_MSGBUF_MAX 512 +typedef struct xge_os_tracebuf_t { + int wrapped_once; /* circular buffer been wrapped */ + int timestamp; /* whether timestamps are enabled */ + volatile int offset; /* offset within the tracebuf */ + int size; /* total size of trace buffer */ + char msg[XGE_OS_TRACE_MSGBUF_MAX]; /* each individual buffer */ + int msgbuf_max; /* actual size of msg buffer */ + char *data; /* pointer to data buffer */ +} xge_os_tracebuf_t; +extern xge_os_tracebuf_t *g_xge_os_tracebuf; + +#ifdef XGE_TRACE_INTO_CIRCULAR_ARR +extern xge_os_tracebuf_t *g_xge_os_tracebuf; +extern char *dmesg_start; + +/* Calculate the size of the msg and copy it into the global buffer */ +#define __xge_trace(tb) { \ + int msgsize = xge_os_strlen(tb->msg) + 2; \ + int offset = tb->offset; \ + if (msgsize != 2 && msgsize < tb->msgbuf_max) { \ + int leftsize = tb->size - offset; \ + if ((msgsize + tb->msgbuf_max) > leftsize) { \ + xge_os_memzero(tb->data + offset, leftsize); \ + offset = 0; \ + tb->wrapped_once = 1; \ + } \ + xge_os_memcpy(tb->data + offset, tb->msg, msgsize-1); \ + *(tb->data + offset + msgsize-1) = '\n'; \ + *(tb->data + offset + msgsize) = 0; \ + offset += msgsize; \ + tb->offset = offset; \ + dmesg_start = tb->data + offset; \ + *tb->msg = 0; \ + } \ +} + +#define xge_os_vatrace(tb, fmt) { \ + if (tb != NULL) { \ + char *_p = tb->msg; \ + if (tb->timestamp) { \ + xge_os_timestamp(tb->msg); \ + _p = tb->msg + xge_os_strlen(tb->msg); \ + } \ + xge_os_vasprintf(_p, fmt); \ + __xge_trace(tb); \ + } \ +} + +#ifdef __GNUC__ +#define xge_os_trace(tb, fmt...) { \ + if (tb != NULL) { \ + if (tb->timestamp) { \ + xge_os_timestamp(tb->msg); \ + } \ + xge_os_sprintf(tb->msg + xge_os_strlen(tb->msg), fmt); \ + __xge_trace(tb); \ + } \ +} +#endif /* __GNUC__ */ + +#else +#define xge_os_vatrace(tb, fmt) +#ifdef __GNUC__ +#define xge_os_trace(tb, fmt...) +#endif /* __GNUC__ */ +#endif + +__EXTERN_END_DECLS + +#endif /* XGE_OS_PAL_H */ diff --git a/sys/dev/nxge/include/xge-os-template.h b/sys/dev/nxge/include/xge-os-template.h new file mode 100644 index 0000000..4d50e6e --- /dev/null +++ b/sys/dev/nxge/include/xge-os-template.h @@ -0,0 +1,614 @@ +/*- + * 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$ + */ + +/* + * FileName : xge-os-template.h + * + * Description: Template for creating platform-dependent "glue" code. + * + * Created: 6 May 2004 + */ + +#ifndef XGE_OS_TEMPLATE_H +#define XGE_OS_TEMPLATE_H + +#ifndef TEMPLATE +# error "should not be compiled for platforms other than TEMPLATE..." +#endif + +/* ------------------------- includes and defines ------------------------- */ + +/* + * Note: + * + * - on some operating systems like Linux & FreeBSD, there is a macro + * by using which it is possible to determine endiennes automatically + */ +#define XGE_OS_HOST_BIG_ENDIAN TEMPLATE + +#define XGE_OS_HOST_PAGE_SIZE TEMPLATE + +/* ---------------------- fixed size primitive types -----------------------*/ + +/* + * Note: + * + * - u## - means ## bits unsigned int/long + * - all names must be preserved since HAL using them. + * - ulong_t is platform specific, i.e. for 64bit - 64bit size, for + * 32bit - 32bit size + */ +#define TEMPLATE u8 +#define TEMPLATE u16 +#define TEMPLATE u32 +#define TEMPLATE u64 +#define TEMPLATE ulong_t +#define TEMPLATE ptrdiff_t +#define TEMPLATE dma_addr_t +#define TEMPLATE spinlock_t +typedef TEMPLATE pci_dev_h; +typedef TEMPLATE pci_reg_h; +typedef TEMPLATE pci_dma_h; +typedef TEMPLATE pci_irq_h; +typedef TEMPLATE pci_cfg_h; +typedef TEMPLATE pci_dma_acc_h; + +/* -------------------------- "libc" functionality -------------------------*/ + +/* + * Note: + * + * - "libc" functionality maps one-to-one to be posix-like + */ +/* Note: use typedef: xge_os_memzero(void* mem, int size); */ +#define xge_os_memzero TEMPLATE + +/* Note: the 1st argument MUST be destination, like in: + * void *memcpy(void *dest, const void *src, size_t n); + */ +#define xge_os_memcpy TEMPLATE + +/* Note: should accept format (the 1st argument) and a variable + * number of arguments thereafter.. */ +#define xge_os_printf(fmt...) TEMPLATE + +#define xge_os_vasprintf(buf, fmt...) TEMPLATE + +#define xge_os_sprintf(buf, fmt, ...) TEMPLATE + +#define xge_os_timestamp(buf) TEMPLATE + +#define xge_os_println TEMPLATE + +/* -------------------- synchronization primitives -------------------------*/ + +/* + * Note: + * + * - use spin_lock in interrupts or in threads when there is no races + * with interrupt + * - use spin_lock_irqsave in threads if there is a race with interrupt + * - use spin_lock_irqsave for nested locks + */ + +/* + * Initialize the spin lock. + */ +#define xge_os_spin_lock_init(lockp, ctxh) TEMPLATE +/* + * Initialize the spin lock (IRQ version). + */ +#define xge_os_spin_lock_init_irq(lockp, ctxh) TEMPLATE +/* + * Destroy the lock. + */ +#define xge_os_spin_lock_destroy(lockp, ctxh) TEMPLATE + +/* + * Destroy the lock (IRQ version). + */ +#define xge_os_spin_lock_destroy_irq(lockp, ctxh) TEMPLATE +/* + * Acquire the lock. + */ +#define xge_os_spin_lock(lockp) TEMPLATE +/* + * Release the lock. + */ +#define xge_os_spin_unlock(lockp) TEMPLATE +/* + * Acquire the lock(IRQ version). + */ +#define xge_os_spin_lock_irq(lockp, flags) TEMPLATE +/* + * Release the lock(IRQ version). + */ +#define xge_os_spin_unlock_irq(lockp, flags) TEMPLATE +/* + * Write memory barrier. + */ +#define xge_os_wmb() TEMPLATE +/* + * Delay (in micro seconds). + */ +#define xge_os_udelay(us) TEMPLATE +/* + * Delay (in milli seconds). + */ +#define xge_os_mdelay(ms) TEMPLATE +/* + * Compare and exchange. + */ +#define xge_os_cmpxchg(targetp, cmp, newval) TEMPLATE + + + +/* ------------------------- misc primitives -------------------------------*/ + +#define xge_os_prefetch TEMPLATE +#define xge_os_prefetchw TEMPLATE +#define xge_os_bug(fmt...) TEMPLATE + +/* -------------------------- compiler stuffs ------------------------------*/ + +#define __xge_os_attr_cacheline_aligned TEMPLATE + +/* ---------------------- memory primitives --------------------------------*/ + +/** + * xge_os_malloc - Allocate non DMA-able memory. + * @pdev: Device context. Some OSs require device context to perform + * operations on memory. + * @size: Size to allocate. + * + * Allocate @size bytes of memory. This allocation can sleep, and + * therefore, and therefore it requires process context. In other words, + * xge_os_malloc() cannot be called from the interrupt context. + * Use xge_os_free() to free the allocated block. + * + * Returns: Pointer to allocated memory, NULL - on failure. + * + * See also: xge_os_free(). + */ +static inline void *xge_os_malloc(IN pci_dev_h pdev, + IN unsigned long size) +{ TEMPLATE; } + +/** + * xge_os_free - Free non DMA-able memory. + * @pdev: Device context. Some OSs require device context to perform + * operations on memory. + * @vaddr: Address of the allocated memory block. + * @size: Some OS's require to provide size on free + * + * Free the memory area obtained via xge_os_malloc(). + * This call may also sleep, and therefore it cannot be used inside + * interrupt. + * + * See also: xge_os_malloc(). + */ +static inline void xge_os_free(IN pci_dev_h pdev, + IN const void *vaddr, + IN unsigned long size) +{ TEMPLATE; } + +/** + * xge_os_vaddr - Get Virtual address for the given physical address. + * @pdev: Device context. Some OSs require device context to perform + * operations on memory. + * @vaddr: Physical Address of the memory block. + * @size: Some OS's require to provide size + * + * Get the virtual address for physical address. + * This call may also sleep, and therefore it cannot be used inside + * interrupt. + * + * See also: xge_os_malloc(). + */ +static inline void xge_os_vaddr(IN pci_dev_h pdev, + IN const void *vaddr, + IN unsigned long size) +{ TEMPLATE; } + +/** + * xge_os_dma_malloc - Allocate DMA-able memory. + * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. + * @size: Size (in bytes) to allocate. + * @dma_flags: XGE_OS_DMA_CACHELINE_ALIGNED, + * XGE_OS_DMA_STREAMING, + * XGE_OS_DMA_CONSISTENT + * Note that the last two flags are mutually exclusive. + * @p_dmah: Handle used to map the memory onto the corresponding device memory + * space. See xge_os_dma_map(). The handle is an out-parameter + * returned by the function. + * @p_dma_acch: One more DMA handle used subsequently to free the + * DMA object (via xge_os_dma_free()). + * Note that this and the previous handle have + * physical meaning for Solaris; on Windows and Linux the + * corresponding value will be simply a pointer to PCI device. + * The value is returned by this function. + * + * Allocate DMA-able contiguous memory block of the specified @size. + * This memory can be subsequently freed using xge_os_dma_free(). + * Note: can be used inside interrupt context. + * + * Returns: Pointer to allocated memory(DMA-able), NULL on failure. + * + */ +static inline void *xge_os_dma_malloc(IN pci_dev_h pdev, + IN unsigned long size, + IN int dma_flags, + OUT pci_dma_h *p_dmah, + OUT pci_dma_acc_h *p_dma_acch) +{ TEMPLATE; } + +/** + * xge_os_dma_free - Free previously allocated DMA-able memory. + * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. + * @vaddr: Virtual address of the DMA-able memory. + * @p_dma_acch: DMA handle used to free the resource. + * @p_dmah: DMA handle used for mapping. See xge_os_dma_malloc(). + * + * Free DMA-able memory originally allocated by xge_os_dma_malloc(). + * Note: can be used inside interrupt. + * See also: xge_os_dma_malloc(). + */ +static inline void xge_os_dma_free (IN pci_dev_h pdev, + IN const void *vaddr, + IN pci_dma_acc_h *p_dma_acch, + IN pci_dma_h *p_dmah) +{ TEMPLATE; } + +/* ----------------------- io/pci/dma primitives ---------------------------*/ + +#define XGE_OS_DMA_DIR_TODEVICE TEMPLATE +#define XGE_OS_DMA_DIR_FROMDEVICE TEMPLATE +#define XGE_OS_DMA_DIR_BIDIRECTIONAL TEMPLATE + +/** + * xge_os_pci_read8 - Read one byte from device PCI configuration. + * @pdev: Device context. Some OSs require device context to perform + * PIO and/or config space IO. + * @cfgh: PCI configuration space handle. + * @where: Offset in the PCI configuration space. + * @val: Address of the result. + * + * Read byte value from the specified @regh PCI configuration space at the + * specified offset = @where. + * Returns: 0 - success, non-zero - failure. + */ +static inline int xge_os_pci_read8(IN pci_dev_h pdev, + IN pci_cfg_h cfgh, + IN int where, + IN u8 *val) +{ TEMPLATE; } + +/** + * xge_os_pci_write8 - Write one byte into device PCI configuration. + * @pdev: Device context. Some OSs require device context to perform + * PIO and/or config space IO. + * @cfgh: PCI configuration space handle. + * @where: Offset in the PCI configuration space. + * @val: Value to write. + * + * Write byte value into the specified PCI configuration space + * Returns: 0 - success, non-zero - failure. + */ +static inline int xge_os_pci_write8(IN pci_dev_h pdev, + IN pci_cfg_h cfgh, + IN int where, + IN u8 val) +{ TEMPLATE; } + +/** + * xge_os_pci_read16 - Read 16bit word from device PCI configuration. + * @pdev: Device context. Some OSs require device context to perform + * PIO and/or config space IO. + * @cfgh: PCI configuration space handle. + * @where: Offset in the PCI configuration space. + * @val: Address of the 16bit result. + * + * Read 16bit value from the specified PCI configuration space at the + * specified offset. + * Returns: 0 - success, non-zero - failure. + */ +static inline int xge_os_pci_read16(IN pci_dev_h pdev, + IN pci_cfg_h cfgh, + IN int where, + IN u16 *val) +{ TEMPLATE; } + +/** + * xge_os_pci_write16 - Write 16bit word into device PCI configuration. + * @pdev: Device context. Some OSs require device context to perform + * PIO and/or config space IO. + * @cfgh: PCI configuration space handle. + * @where: Offset in the PCI configuration space. + * @val: Value to write. + * + * Write 16bit value into the specified @offset in PCI + * configuration space. + * Returns: 0 - success, non-zero - failure. + */ +static inline int xge_os_pci_write16(IN pci_dev_h pdev, + IN pci_cfg_h cfgh, + IN int where, + IN u16 val) +{ TEMPLATE; } + +/** + * xge_os_pci_read32 - Read 32bit word from device PCI configuration. + * @pdev: Device context. Some OSs require device context to perform + * PIO and/or config space IO. + * @cfgh: PCI configuration space handle. + * @where: Offset in the PCI configuration space. + * @val: Address of 32bit result. + * + * Read 32bit value from the specified PCI configuration space at the + * specified offset. + * Returns: 0 - success, non-zero - failure. + */ +static inline int xge_os_pci_read32(IN pci_dev_h pdev, + IN pci_cfg_h cfgh, + IN int where, + IN u32 *val) +{ TEMPLATE; } + +/** + * xge_os_pci_write32 - Write 32bit word into device PCI configuration. + * @pdev: Device context. Some OSs require device context to perform + * PIO and/or config space IO. + * @cfgh: PCI configuration space handle. + * @where: Offset in the PCI configuration space. + * @val: Value to write. + * + * Write 32bit value into the specified @offset in PCI + * configuration space. + * Returns: 0 - success, non-zero - failure. + */ +static inline int xge_os_pci_write32(IN pci_dev_h pdev, + IN pci_cfg_h cfgh, + IN int where, + IN u32 val) +{ TEMPLATE; } + +/** + * xge_os_pio_mem_read8 - Read 1 byte from device memory mapped space. + * @pdev: Device context. Some OSs require device context to perform + * PIO and/or config space IO.. + * @regh: PCI configuration space handle. + * @addr: Address in device memory space. + * + * Returns: 1 byte value read from the specified (mapped) memory space address. + */ +static inline u8 xge_os_pio_mem_read8(IN pci_dev_h pdev, + IN pci_reg_h regh, + IN void *addr) +{ TEMPLATE; } + +/** + * xge_os_pio_mem_write64 - Write 1 byte into device memory mapped + * space. + * @pdev: Device context. Some OSs require device context to perform + * PIO and/or config space IO.. + * @regh: PCI configuration space handle. + * @val: Value to write. + * @addr: Address in device memory space. + * + * Write byte value into the specified (mapped) device memory space. + */ +static inline void xge_os_pio_mem_write8(IN pci_dev_h pdev, + IN pci_reg_h regh, + IN u8 val, + IN void *addr) +{ TEMPLATE; } + +/** + * xge_os_pio_mem_read16 - Read 16bit from device memory mapped space. + * @pdev: Device context. Some OSs require device context to perform + * PIO. + * @regh: PCI configuration space handle. + * @addr: Address in device memory space. + * + * Returns: 16bit value read from the specified (mapped) memory space address. + */ +static inline u16 xge_os_pio_mem_read16(IN pci_dev_h pdev, + IN pci_reg_h regh, + IN void *addr) +{ +TEMPLATE; } + +/** + * xge_os_pio_mem_write16 - Write 16bit into device memory mapped space. + * @pdev: Device context. Some OSs require device context to perform + * PIO. + * @regh: PCI configuration space handle. + * @val: Value to write. + * @addr: Address in device memory space. + * + * Write 16bit value into the specified (mapped) device memory space. + */ +static inline void xge_os_pio_mem_write16(IN pci_dev_h pdev, + IN pci_reg_h regh, + IN u16 val, + IN void *addr) +{ TEMPLATE; } + +/** + * xge_os_pio_mem_read32 - Read 32bit from device memory mapped space. + * @pdev: Device context. Some OSs require device context to perform + * PIO. + * @regh: PCI configuration space handle. + * @addr: Address in device memory space. + * + * Returns: 32bit value read from the specified (mapped) memory space address. + */ +static inline u32 xge_os_pio_mem_read32(IN pci_dev_h pdev, + IN pci_reg_h regh, + IN void *addr) +{ TEMPLATE; } + +/** + * xge_os_pio_mem_write32 - Write 32bit into device memory space. + * @pdev: Device context. Some OSs require device context to perform + * PIO. + * @regh: PCI configuration space handle. + * @val: Value to write. + * @addr: Address in device memory space. + * + * Write 32bit value into the specified (mapped) device memory space. + */ +static inline void xge_os_pio_mem_write32(IN pci_dev_h pdev, + IN pci_reg_h regh, + IN u32 val, + IN void *addr) +{ TEMPLATE; } + +/** + * xge_os_pio_mem_read64 - Read 64bit from device memory mapped space. + * @pdev: Device context. Some OSs require device context to perform + * PIO. + * @regh: PCI configuration space handle. + * @addr: Address in device memory space. + * + * Returns: 64bit value read from the specified (mapped) memory space address. + */ +static inline u64 xge_os_pio_mem_read64(IN pci_dev_h pdev, + IN pci_reg_h regh, + IN void *addr) +{ TEMPLATE; } + +/** + * xge_os_pio_mem_write64 - Write 64bit into device memory space. + * @pdev: Device context. Some OSs require device context to perform + * PIO. + * @regh: PCI configuration space handle. + * @val: Value to write. + * @addr: Address in device memory space. + * + * Write 64bit value into the specified (mapped) device memory space. + */ +static inline void xge_os_pio_mem_write64(IN pci_dev_h pdev, + IN pci_reg_h regh, + IN u64 val, + IN void *addr) +{ TEMPLATE; } + +/** + * xge_os_flush_bridge - Flush the bridge. + * @pdev: Device context. Some OSs require device context to perform + * PIO. + * @regh: PCI configuration space handle. + * @addr: Address in device memory space. + * + * Flush the bridge. + */ +static inline void xge_os_flush_bridge(IN pci_dev_h pdev, + IN pci_reg_h regh, + IN void *addr) +{ TEMPLATE; } + +/** + * xge_os_dma_map - Map DMA-able memory block to, or from, or + * to-and-from device. + * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. + * @dmah: DMA handle used to map the memory block. Obtained via + * xge_os_dma_malloc(). + * @vaddr: Virtual address of the DMA-able memory. + * @size: Size (in bytes) to be mapped. + * @dir: Direction of this operation (XGE_OS_DMA_DIR_TODEVICE, etc.) + * @dma_flags: XGE_OS_DMA_CACHELINE_ALIGNED, + * XGE_OS_DMA_STREAMING, + * XGE_OS_DMA_CONSISTENT + * Note that the last two flags are mutually exclusive. + * + * Map a single memory block. + * + * Returns: DMA address of the memory block, + * XGE_OS_INVALID_DMA_ADDR on failure. + * + * See also: xge_os_dma_malloc(), xge_os_dma_unmap(), + * xge_os_dma_sync(). + */ +static inline dma_addr_t xge_os_dma_map(IN pci_dev_h pdev, + IN pci_dma_h dmah, + IN void *vaddr, + IN size_t size, + IN int dir, + IN int dma_flags) +{ TEMPLATE; } + +/** + * xge_os_dma_unmap - Unmap DMA-able memory. + * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. + * @dmah: DMA handle used to map the memory block. Obtained via + * xge_os_dma_malloc(). + * @dma_addr: DMA address of the block. Obtained via xge_os_dma_map(). + * @size: Size (in bytes) to be unmapped. + * @dir: Direction of this operation (XGE_OS_DMA_DIR_TODEVICE, etc.) + * + * Unmap a single DMA-able memory block that was previously mapped + * using xge_os_dma_map(). + * See also: xge_os_dma_malloc(), xge_os_dma_map(). + */ +static inline void xge_os_dma_unmap(IN pci_dev_h pdev, + IN pci_dma_h dmah, + IN dma_addr_t dma_addr, + IN size_t size, + IN int dir) +{ TEMPLATE; } + +/** + * xge_os_dma_sync - Synchronize mapped memory. + * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. + * @dmah: DMA handle used to map the memory block. Obtained via + * xge_os_dma_malloc(). + * @dma_addr: DMA address of the block. Obtained via xge_os_dma_map(). + * @dma_offset: Offset from start of the blocke. Used by Solaris only. + * @length: Size of the block. + * @dir: Direction of this operation (XGE_OS_DMA_DIR_TODEVICE, etc.) + * + * Make physical and CPU memory consistent for a single + * streaming mode DMA translation. + * This API compiles to NOP on cache-coherent platforms. + * On non cache-coherent platforms, depending on the direction + * of the "sync" operation, this API will effectively + * either invalidate CPU cache (that might contain old data), + * or flush CPU cache to update physical memory. + * See also: xge_os_dma_malloc(), xge_os_dma_map(), + * xge_os_dma_unmap(). + */ +static inline void xge_os_dma_sync(IN pci_dev_h pdev, + IN pci_dma_h dmah, + IN dma_addr_t dma_addr, + IN u64 dma_offset, + IN size_t length, + IN int dir) +{ TEMPLATE; } + +#endif /* XGE_OS_TEMPLATE_H */ diff --git a/sys/dev/nxge/include/xge-queue.h b/sys/dev/nxge/include/xge-queue.h new file mode 100644 index 0000000..6745888 --- /dev/null +++ b/sys/dev/nxge/include/xge-queue.h @@ -0,0 +1,185 @@ +/*- + * 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$ + */ + +/* + * FileName : xge-queue.h + * + * Description: serialized event queue + * + * Created: 7 June 2004 + */ + +#ifndef XGE_QUEUE_H +#define XGE_QUEUE_H + +#include <dev/nxge/include/xge-os-pal.h> +#include <dev/nxge/include/xge-defs.h> +#include <dev/nxge/include/xge-list.h> +#include <dev/nxge/include/xgehal-event.h> + +__EXTERN_BEGIN_DECLS + +#define XGE_QUEUE_BUF_SIZE 0x1000 +#define XGE_DEFAULT_EVENT_MAX_DATA_SIZE 16 + +/** + * enum xge_queue_status_e - Enumerates return codes of the xge_queue + * manipulation APIs. + * @XGE_QUEUE_IS_FULL: Queue is full, need to grow. + * @XGE_QUEUE_IS_EMPTY: Queue is empty. + * @XGE_QUEUE_OUT_OF_MEMORY: Out of memory. + * @XGE_QUEUE_NOT_ENOUGH_SPACE: Exceeded specified event size, + * see xge_queue_consume(). + * @XGE_QUEUE_OK: Neither one of the codes listed above. + * + * Enumerates return codes of xge_queue_consume() + * and xge_queue_produce() APIs. + */ +typedef enum xge_queue_status_e { + XGE_QUEUE_OK = 0, + XGE_QUEUE_IS_FULL = 1, + XGE_QUEUE_IS_EMPTY = 2, + XGE_QUEUE_OUT_OF_MEMORY = 3, + XGE_QUEUE_NOT_ENOUGH_SPACE = 4 +} xge_queue_status_e; + +typedef void* xge_queue_h; + +/** + * struct xge_queue_item_t - Queue item. + * @item: List item. Note that the queue is "built" on top of + * the bi-directional linked list. + * @event_type: Event type. Includes (but is not restricted to) + * one of the xge_hal_event_e{} enumerated types. + * @data_size: Size of the enqueued user data. Note that xge_queue_t + * items are allowed to have variable sizes. + * @is_critical: For critical events, e.g. ECC. + * @context: Opaque (void*) "context", for instance event producer object. + * + * Item of the xge_queue_t{}. The queue is protected + * in terms of multi-threaded concurrent access. + * See also: xge_queue_t{}. + */ +typedef struct xge_queue_item_t { + xge_list_t item; + xge_hal_event_e event_type; + int data_size; + int is_critical; + void *context; +} xge_queue_item_t; + +/** + * function xge_queued_f - Item-enqueued callback. + * @data: Per-queue context independent of the event. E.g., device handle. + * @event_type: HAL or ULD-defined event type. Note that HAL own + * events are enumerated by xge_hal_event_e{}. + * + * Per-queue optional callback. If not NULL, called by HAL each + * time an event gets added to the queue. + */ +typedef void (*xge_queued_f) (void *data, int event_type); + +/** + * struct xge_queue_t - Protected dynamic queue of variable-size items. + * @start_ptr: Points to the start of the queue. + * @end_ptr: Points to the end of the queue. + * @head_ptr: Points to the head of the queue. It gets changed during queue + * produce/consume operations. + * @tail_ptr: Points to the tail of the queue. It gets changed during queue + * produce/consume operations. + * @lock: Lock for queue operations(syncronization purpose). + * @pages_initial:Number of pages to be initially allocated at the time + * of queue creation. + * @pages_max: Max number of pages that can be allocated in the queue. + * @pages_current: Number of pages currently allocated + * @list_head: Points to the list of queue elements that are produced, but yet + * to be consumed. + * @signal_callback: (TODO) + * @pdev: PCI device handle + * @irqh: PCI device IRQ handle. + * @queued_func: Optional callback function to be called each time a new + * item is added to the queue. + * @queued_data: Arguments to the callback function. + * @has_critical_event: Non-zero, if the queue contains a critical event, + * see xge_hal_event_e{}. + * Protected dynamically growing queue. The queue is used to support multiple + * producer/consumer type scenarios. The queue is a strict FIFO: first come + * first served. + * Queue users may "produce" (see xge_queue_produce()) and "consume" + * (see xge_queue_consume()) items (a.k.a. events) variable sizes. + * See also: xge_queue_item_t{}. + */ +typedef struct xge_queue_t { + void *start_ptr; + void *end_ptr; + void *head_ptr; + void *tail_ptr; + spinlock_t lock; + unsigned int pages_initial; + unsigned int pages_max; + unsigned int pages_current; + xge_list_t list_head; + pci_dev_h pdev; + pci_irq_h irqh; + xge_queued_f queued_func; + void *queued_data; + int has_critical_event; +} xge_queue_t; + +/* ========================== PUBLIC API ================================= */ + +xge_queue_h xge_queue_create(pci_dev_h pdev, pci_irq_h irqh, int pages_initial, + int pages_max, xge_queued_f queued_func, void *queued_data); + +void xge_queue_destroy(xge_queue_h queueh); + +void* xge_queue_item_data(xge_queue_item_t *item); + +xge_queue_status_e +xge_queue_produce(xge_queue_h queueh, int event_type, void *context, + int is_critical, const int data_size, void *data); + +static inline xge_queue_status_e +xge_queue_produce_context(xge_queue_h queueh, int event_type, void *context) { + return xge_queue_produce(queueh, event_type, context, 0, 0, 0); +} + +xge_queue_status_e xge_queue_consume(xge_queue_h queueh, int data_max_size, + xge_queue_item_t *item); + +void xge_queue_flush(xge_queue_h queueh); + +/* ========================== PRIVATE API ================================= */ + +xge_queue_status_e __io_queue_grow(xge_queue_h qh); + +int __queue_get_reset_critical (xge_queue_h qh); + +__EXTERN_END_DECLS + +#endif /* XGE_QUEUE_H */ diff --git a/sys/dev/nxge/include/xgehal-channel.h b/sys/dev/nxge/include/xgehal-channel.h new file mode 100644 index 0000000..8d82530 --- /dev/null +++ b/sys/dev/nxge/include/xgehal-channel.h @@ -0,0 +1,507 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-channel.h + * + * Description: HAL channel object functionality + * + * Created: 19 May 2004 + */ + +#ifndef XGE_HAL_CHANNEL_H +#define XGE_HAL_CHANNEL_H + +#include <dev/nxge/include/xge-os-pal.h> +#include <dev/nxge/include/xge-list.h> +#include <dev/nxge/include/xgehal-types.h> +#include <dev/nxge/include/xgehal-stats.h> + +__EXTERN_BEGIN_DECLS + +/** + * enum xge_hal_channel_type_e - Enumerated channel types. + * @XGE_HAL_CHANNEL_TYPE_FIFO: fifo. + * @XGE_HAL_CHANNEL_TYPE_RING: ring. + * @XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: Send Queue + * @XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: Receive Queue + * @XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: Receive queue completion queue + * @XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: Up message queue + * @XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: Down message queue + * @XGE_HAL_CHANNEL_TYPE_MAX: Maximum number of HAL-supported + * (and recognized) channel types. Currently: two. + * + * Enumerated channel types. Currently there are only two link-layer + * channels - Xframe fifo and Xframe ring. In the future the list will grow. + */ +typedef enum xge_hal_channel_type_e { + XGE_HAL_CHANNEL_TYPE_FIFO, + XGE_HAL_CHANNEL_TYPE_RING, + XGE_HAL_CHANNEL_TYPE_SEND_QUEUE, + XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE, + XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE, + XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE, + XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE, + XGE_HAL_CHANNEL_TYPE_MAX +} xge_hal_channel_type_e; + +/** + * enum xge_hal_channel_flag_e - Channel flags. + * @XGE_HAL_CHANNEL_FLAG_NONE: zero (nil) flag. + * @XGE_HAL_CHANNEL_FLAG_USE_TX_LOCK: use lock when posting transmit + * descriptor. + * @XGE_HAL_CHANNEL_FLAG_FREE_RXD: to-be-defined. + * + * Channel opening flags. Reserved for future usage. + */ +typedef enum xge_hal_channel_flag_e { + XGE_HAL_CHANNEL_FLAG_NONE = 0x0, + XGE_HAL_CHANNEL_FLAG_USE_TX_LOCK = 0x1, + XGE_HAL_CHANNEL_FLAG_FREE_RXD = 0x2 +} xge_hal_channel_flag_e; + +/** + * enum xge_hal_dtr_state_e - Descriptor (DTR) state. + * @XGE_HAL_DTR_STATE_NONE: Invalid state. + * @XGE_HAL_DTR_STATE_AVAIL: Descriptor is available for reservation + * (via xge_hal_fifo_dtr_reserve(), xge_hal_ring_dtr_reserve(), etc.). + * @XGE_HAL_DTR_STATE_POSTED: Descriptor is posted for processing by the + * device. + * @XGE_HAL_DTR_STATE_FREED: Descriptor is free and can be reused for + * filling-in and posting later. + * + * Xframe/HAL descriptor states. For more on descriptor states and transitions + * please refer to ch_intern{}. + * + * See also: xge_hal_channel_dtr_term_f{}. + */ +typedef enum xge_hal_dtr_state_e { + XGE_HAL_DTR_STATE_NONE = 0, + XGE_HAL_DTR_STATE_AVAIL = 1, + XGE_HAL_DTR_STATE_POSTED = 2, + XGE_HAL_DTR_STATE_FREED = 3 +} xge_hal_dtr_state_e; + +/** + * enum xge_hal_channel_reopen_e - Channel open, close, or reopen option. + * @XGE_HAL_CHANNEL_RESET_ONLY: Do not (de)allocate channel; used with + * xge_hal_channel_open(), xge_hal_channel_close(). + * @XGE_HAL_CHANNEL_OC_NORMAL: Do (de)allocate channel; used with + * xge_hal_channel_open(), xge_hal_channel_close(). + * + * Enumerates options used with channel open and close operations. + * The @XGE_HAL_CHANNEL_RESET_ONLY can be used when resetting the device; + * in this case there is actually no need to free and then again malloc + * the memory (including DMA-able memory) used for channel operation. + */ +typedef enum xge_hal_channel_reopen_e { + XGE_HAL_CHANNEL_RESET_ONLY = 1, + XGE_HAL_CHANNEL_OC_NORMAL = 2 +} xge_hal_channel_reopen_e; + +/** + * function xge_hal_channel_callback_f - Channel callback. + * @channelh: Channel "containing" 1 or more completed descriptors. + * @dtrh: First completed descriptor. + * @t_code: Transfer code, as per Xframe User Guide. + * Returned by HAL. + * @host_control: Opaque 64bit data stored by ULD inside the Xframe + * descriptor prior to posting the latter on the channel + * via xge_hal_fifo_dtr_post() or xge_hal_ring_dtr_post(). + * The @host_control is returned as is to the ULD with each + * completed descriptor. + * @userdata: Opaque per-channel data specified at channel open + * time, via xge_hal_channel_open(). + * + * Channel completion callback (type declaration). A single per-channel + * callback is specified at channel open time, via + * xge_hal_channel_open(). + * Typically gets called as part of the processing of the Interrupt + * Service Routine. + * + * Channel callback gets called by HAL if, and only if, there is at least + * one new completion on a given ring or fifo channel. Upon processing the + * first @dtrh ULD is _supposed_ to continue consuming completions + * usingáone of the following HAL APIs: + * - xge_hal_fifo_dtr_next_completed() + * or + * - xge_hal_ring_dtr_next_completed(). + * + * Note that failure to process new completions in a timely fashion + * leads to XGE_HAL_INF_OUT_OF_DESCRIPTORS condition. + * + * Non-zero @t_code means failure to process (transmit or receive, depending + * on the channel type) the descriptor. + * + * In the "transmit" case the failure could happen, for instance, when the + * link is down, in which case Xframe completes the descriptor because it + * is not able to send the data out. + * + * For details please refer to Xframe User Guide. + * + * See also: xge_hal_fifo_dtr_next_completed(), + * xge_hal_ring_dtr_next_completed(), xge_hal_channel_dtr_term_f{}. + */ +typedef xge_hal_status_e (*xge_hal_channel_callback_f) + (xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + u8 t_code, void *userdata); + +/** + * function xge_hal_channel_dtr_init_f - Initialize descriptor callback. + * @channelh: Channel "containing" the @dtrh descriptor. + * @dtrh: Descriptor. + * @index: Index of the descriptor in the channel's set of descriptors. + * @userdata: Per-channel user data (a.k.a. context) specified at + * channel open time, via xge_hal_channel_open(). + * @reopen: See xge_hal_channel_reopen_e{}. + * + * Initialize descriptor callback. Unless NULL is specified in the + * xge_hal_channel_attr_t{} structure passed to xge_hal_channel_open()), + * HAL invokes the callback as part of the xge_hal_channel_open() + * implementation. + * For the ring type of channel the ULD is expected to fill in this descriptor + * with buffer(s) and control information. + * For the fifo type of channel the ULD could use the callback to + * pre-set DMA mappings and/or alignment buffers. + * + * See also: xge_hal_channel_attr_t{}, xge_hal_channel_dtr_term_f{}. + */ +typedef xge_hal_status_e (*xge_hal_channel_dtr_init_f) + (xge_hal_channel_h channelh, + xge_hal_dtr_h dtrh, + int index, + void *userdata, + xge_hal_channel_reopen_e reopen); + +/** + * function xge_hal_channel_dtr_term_f - Terminate descriptor callback. + * @channelh: Channel "containing" the @dtrh descriptor. + * @dtrh: First completed descriptor. + * @state: One of the xge_hal_dtr_state_e{} enumerated states. + * @userdata: Per-channel user data (a.k.a. context) specified at + * channel open time, via xge_hal_channel_open(). + * @reopen: See xge_hal_channel_reopen_e{}. + * + * Terminate descriptor callback. Unless NULL is specified in the + * xge_hal_channel_attr_t{} structure passed to xge_hal_channel_open()), + * HAL invokes the callback as part of closing the corresponding + * channel, prior to de-allocating the channel and associated data + * structures (including descriptors). + * ULD should utilize the callback to (for instance) unmap + * and free DMA data buffers associated with the posted (state = + * XGE_HAL_DTR_STATE_POSTED) descriptors, + * as well as other relevant cleanup functions. + * + * See also: xge_hal_channel_attr_t{}, xge_hal_channel_dtr_init_f{}. + */ +typedef void (*xge_hal_channel_dtr_term_f) (xge_hal_channel_h channelh, + xge_hal_dtr_h dtrh, + xge_hal_dtr_state_e state, + void *userdata, + xge_hal_channel_reopen_e reopen); + + +/** + * struct xge_hal_channel_attr_t - Channel open "template". + * @type: xge_hal_channel_type_e channel type. + * @vp_id: Virtual path id + * @post_qid: Queue ID to post descriptors. For the link layer this + * number should be in the 0..7 range. + * @compl_qid: Completion queue ID. Must be set to zero for the link layer. + * @callback: Channel completion callback. HAL invokes the callback when there + * are new completions on that channel. In many implementations + * the @callback executes in the hw interrupt context. + * @dtr_init: Channel's descriptor-initialize callback. + * See xge_hal_channel_dtr_init_f{}. + * If not NULL, HAL invokes the callback when opening + * the channel via xge_hal_channel_open(). + * @dtr_term: Channel's descriptor-terminate callback. If not NULL, + * HAL invokes the callback when closing the corresponding channel. + * See also xge_hal_channel_dtr_term_f{}. + * @userdata: User-defined "context" of _that_ channel. Passed back to the + * user as one of the @callback, @dtr_init, and @dtr_term arguments. + * @per_dtr_space: If specified (i.e., greater than zero): extra space + * reserved by HAL per each transmit or receive (depending on the + * channel type) descriptor. Can be used to store, + * and retrieve on completion, information specific + * to the upper-layer. + * @flags: xge_hal_channel_flag_e enumerated flags. + * + * Channel open "template". User fills the structure with channel + * attributes and passes it to xge_hal_channel_open(). + * Usage: See ex_open{}. + */ +typedef struct xge_hal_channel_attr_t { + xge_hal_channel_type_e type; +#ifdef XGEHAL_RNIC + u32 vp_id; +#endif + int post_qid; + int compl_qid; + xge_hal_channel_callback_f callback; + xge_hal_channel_dtr_init_f dtr_init; + xge_hal_channel_dtr_term_f dtr_term; + void *userdata; + int per_dtr_space; + xge_hal_channel_flag_e flags; +} xge_hal_channel_attr_t; + +/* + * xge_hal_channel_t + * ---------- complete/free section --------------- + * @item: List item; used to maintain a list of open channels. + * @callback: Channel completion callback. See + * xge_hal_channel_callback_f. + * @compl_index: Completion index. At any point in time points on the + * position in the channel, which will contain next + * to-be-completed descriptor. + * @length: Channel length. Currently allocated number of descriptors. + * The channel length "grows" when more descriptors get allocated. + * See _hal_mempool_grow. + * @free_arr: Free array. Contains completed descriptors that were freed + * (i.e., handed over back to HAL) by ULD. + * See xge_hal_fifo_dtr_free(), xge_hal_ring_dtr_free(). + * @free_lock: Lock to protect @free_arr. + * ----------- reserve/post section --------------- + * @post_index: Post index. At any point in time points on the + * position in the channel, which'll contain next to-be-posted + * descriptor. + * @post_lock: Lock to serialize multiple concurrent "posters" of descriptors + * on the given channel. + * @reserve_arr: Reserve array. Contains descriptors that can be reserved + * by ULD for the subsequent send or receive operation. + * See xge_hal_fifo_dtr_reserve(), + * xge_hal_ring_dtr_reserve(). + * @reserve_length: Length of the @reserve_arr. The length dynamically + * changes: it decrements each time descriptor is reserved. + * @reserve_lock: Lock to serialize multiple concurrent threads accessing + * @reserve_arr. + * @reserve_threshold: Reserve threshold. Minimal number of free descriptors + * that ought to be preserved in the channel at all times. + * Note that @reserve_threshold >= 0 && + * @reserve_threshold < @reserve_max. + * ------------ common section -------------------- + * @devh: Device handle. HAL device object that contains _this_ channel. + * @dmah: Channel's DMA address. Used to synchronize (to/from device) + * descriptors. + * @regh0: Base address of the device memory space handle. Copied from HAL device + * at channel open time. + * @regh1: Base address of the device memory space handle. Copied from HAL device + * at channel open time. + * @userdata: Per-channel opaque (void*) user-defined context, which may be + * upper-layer driver object, ULP connection, etc. + * Once channel is open, @userdata is passed back to user via + * xge_hal_channel_callback_f. + * @work_arr: Work array. Contains descriptors posted to the channel. + * Note that at any point in time @work_arr contains 3 types of + * descriptors: + * 1) posted but not yet consumed by Xframe device; + * 2) consumed but not yet completed; + * 3) completed but not yet freed + * (via xge_hal_fifo_dtr_free() or xge_hal_ring_dtr_free()) + * @saved_arr: Array used internally to optimize channel full-duplex + * operation. + * @stats: Channel statistcis. Includes HAL internal counters, including + * for instance, number of times out-of-descriptors + * (see XGE_HAL_INF_OUT_OF_DESCRIPTORS) condition happened. + * ------------- "slow" section ------------------ + * @type: Channel type. See xge_hal_channel_type_e{}. + * @vp_id: Virtual path id + * @post_qid: Identifies Xframe queue used for posting descriptors. + * @compl_qid: Identifies Xframe completion queue. + * @flags: Channel flags. See xge_hal_channel_flag_e{}. + * @reserve_initial: Initial number of descriptors allocated at channel open + * time (see xge_hal_channel_open()). The number of + * channel descriptors can grow at runtime + * up to @reserve_max value. + * @reserve_max: Maximum number of channel descriptors. See @reserve_initial. + * @is_open: True, if channel is open; false - otherwise. + * @per_dtr_space: Per-descriptor space (in bytes) that channel user can utilize + * to store per-operation control information. + * HAL channel object. HAL devices (see xge_hal_device_t{}) contains + * zero or more channels. HAL channel contains zero or more descriptors. The + * latter are used by ULD(s) to manage the device and/or send and receive data + * to remote peer(s) via the channel. + * + * See also: xge_hal_channel_type_e{}, xge_hal_channel_flag_e, + * xge_hal_channel_callback_f{} + */ +typedef struct { + /* complete/free section */ + xge_list_t item; + xge_hal_channel_callback_f callback; + void **free_arr; + int length; + int free_length; +#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ) || \ + defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE) + spinlock_t free_lock; +#endif + int compl_index; + unsigned int usage_cnt; + unsigned int poll_bytes; + int unused0; + + /* reserve/post data path section */ +#ifdef __XGE_WIN__ + int __xge_os_attr_cacheline_aligned + post_index; +#else + int post_index + __xge_os_attr_cacheline_aligned; +#endif + spinlock_t reserve_lock; + spinlock_t post_lock; + + void **reserve_arr; + int reserve_length; + int reserve_threshold; + int reserve_top; + int unused1; + + /* common section */ + xge_hal_device_h devh; + pci_dev_h pdev; + pci_reg_h regh0; + pci_reg_h regh1; + void *userdata; + void **work_arr; + void **saved_arr; + void **orig_arr; + xge_hal_stats_channel_info_t stats; + + /* slow section */ + xge_hal_channel_type_e type; +#ifdef XGEHAL_RNIC + u32 vp_id; +#endif + int post_qid; + int compl_qid; + xge_hal_channel_flag_e flags; + int reserve_initial; + int reserve_max; + int is_open; + int per_dtr_space; + xge_hal_channel_dtr_term_f dtr_term; + xge_hal_channel_dtr_init_f dtr_init; + /* MSI stuff */ + u32 msi_msg; + u8 rti; + u8 tti; + u16 unused2; + /* MSI-X stuff */ + u64 msix_address; + u32 msix_data; + int msix_idx; + volatile int in_interrupt; + unsigned int magic; +#ifdef __XGE_WIN__ +} __xge_os_attr_cacheline_aligned xge_hal_channel_t ; +#else +} xge_hal_channel_t __xge_os_attr_cacheline_aligned; +#endif + +/* ========================== CHANNEL PRIVATE API ========================= */ + +xge_hal_status_e +__hal_channel_initialize(xge_hal_channel_h channelh, + xge_hal_channel_attr_t *attr, void **reserve_arr, + int reserve_initial, int reserve_max, int reserve_threshold); + +void __hal_channel_terminate(xge_hal_channel_h channelh); + +xge_hal_channel_t* +__hal_channel_allocate(xge_hal_device_h devh, int post_qid, +#ifdef XGEHAL_RNIC + u32 vp_id, +#endif + xge_hal_channel_type_e type); + +void __hal_channel_free(xge_hal_channel_t *channel); + +#if defined(XGE_DEBUG_FP) && (XGE_DEBUG_FP & XGE_DEBUG_FP_CHANNEL) +#define __HAL_STATIC_CHANNEL +#define __HAL_INLINE_CHANNEL + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_channel_dtr_alloc(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_channel_dtr_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_channel_dtr_try_complete(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_channel_dtr_complete(xge_hal_channel_h channelh); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_channel_dtr_free(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_channel_dtr_dealloc(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_channel_dtr_restore(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + int offset); + +/* ========================== CHANNEL PUBLIC API ========================= */ + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int +xge_hal_channel_dtr_count(xge_hal_channel_h channelh); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void* +xge_hal_channel_userdata(xge_hal_channel_h channelh); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int +xge_hal_channel_id(xge_hal_channel_h channelh); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int +xge_hal_check_alignment(dma_addr_t dma_pointer, int size, int alignment, + int copy_size); + +#else /* XGE_FASTPATH_EXTERN */ +#define __HAL_STATIC_CHANNEL static +#define __HAL_INLINE_CHANNEL inline +#include <dev/nxge/xgehal/xgehal-channel-fp.c> +#endif /* XGE_FASTPATH_INLINE */ + +xge_hal_status_e +xge_hal_channel_open(xge_hal_device_h hldev, xge_hal_channel_attr_t *attr, + xge_hal_channel_h *channel, + xge_hal_channel_reopen_e reopen); + +void xge_hal_channel_close(xge_hal_channel_h channelh, + xge_hal_channel_reopen_e reopen); + +void xge_hal_channel_abort(xge_hal_channel_h channelh, + xge_hal_channel_reopen_e reopen); + +__EXTERN_END_DECLS + +#endif /* XGE_HAL_CHANNEL_H */ diff --git a/sys/dev/nxge/include/xgehal-config.h b/sys/dev/nxge/include/xgehal-config.h new file mode 100644 index 0000000..c7bde29 --- /dev/null +++ b/sys/dev/nxge/include/xgehal-config.h @@ -0,0 +1,1012 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-config.h + * + * Description: Xframe configuration. + * + * Created: 14 May 2004 + */ + +#ifndef XGE_HAL_CONFIG_H +#define XGE_HAL_CONFIG_H + +#include <dev/nxge/include/xge-os-pal.h> +#include <dev/nxge/include/xgehal-types.h> +#include <dev/nxge/include/xge-queue.h> + +__EXTERN_BEGIN_DECLS + +#define XGE_HAL_DEFAULT_USE_HARDCODE -1 + +#ifdef XGEHAL_RNIC +#define XGE_HAL_MAX_VIRTUAL_PATHS 17 +#else +#define XGE_HAL_MAX_VIRTUAL_PATHS 8 +#endif +#define XGE_HAL_MAX_INTR_PER_VP 4 + + +/** + * struct xge_hal_tti_config_t - Xframe Tx interrupt configuration. + * @enabled: Set to 1, if TTI feature is enabled. + * @urange_a: Link utilization range A. The value from 0 to 100%. + * @ufc_a: Frame count for the utilization range A. Interrupt will be generated + * each time when (and only when) the line is utilized no more + * than @urange_a percent in the transmit direction, + * and number of transmitted frames is greater or equal @ufc_a. + * @urange_b: Link utilization range B. + * @ufc_b: Frame count for the utilization range B. + * @urange_c: Link utilization range C. + * @ufc_c: Frame count for the utilization range C. + * @urange_d: Link utilization range D. + * @ufc_d: Frame count for the utilization range D. + * @timer_val_us: Interval of time, in microseconds, at which transmit timer + * interrupt is to be generated. Note that unless @timer_ci_en + * is set, the timer interrupt is generated only in presence + * of the transmit traffic. Note also that timer interrupt + * and utilization interrupt are two separate interrupt + * sources. + * @timer_ac_en: Enable auto-cancel. That is, reset the timer if utilization + * interrupt was generated during the interval. + * @timer_ci_en: Enable/disable continuous interrupt. Set this value + * to 1 in order to generate continuous interrupt + * at fixed @timer_val intervals of time, independently + * of whether there is transmit traffic or not. + * @enabled: Set to 1, if TTI feature is enabled. + * + * Xframe transmit interrupt configuration. + * See Xframe User Guide, Section 3.5 "Device Interrupts" + * for more details. Note also (min, max) + * ranges in the body of the xge_hal_tx_intr_config_t structure. + * Note: Valid (min, max) range for each attribute is specified in the body of + * the xge_hal_tti_config_t{} structure. Please refer to the + * corresponding header file. + */ +typedef struct xge_hal_tti_config_t { + + int enabled; +#define XGE_HAL_TTI_ENABLE 1 +#define XGE_HAL_TTI_DISABLE 0 + + /* Line utilization interrupts */ + + int urange_a; +#define XGE_HAL_MIN_TX_URANGE_A 0 +#define XGE_HAL_MAX_TX_URANGE_A 100 + + int ufc_a; +#define XGE_HAL_MIN_TX_UFC_A 0 +#define XGE_HAL_MAX_TX_UFC_A 65535 + + int urange_b; +#define XGE_HAL_MIN_TX_URANGE_B 0 +#define XGE_HAL_MAX_TX_URANGE_B 100 + + int ufc_b; +#define XGE_HAL_MIN_TX_UFC_B 0 +#define XGE_HAL_MAX_TX_UFC_B 65535 + + int urange_c; +#define XGE_HAL_MIN_TX_URANGE_C 0 +#define XGE_HAL_MAX_TX_URANGE_C 100 + + int ufc_c; +#define XGE_HAL_MIN_TX_UFC_C 0 +#define XGE_HAL_MAX_TX_UFC_C 65535 + + int ufc_d; +#define XGE_HAL_MIN_TX_UFC_D 0 +#define XGE_HAL_MAX_TX_UFC_D 65535 + + int timer_val_us; +#define XGE_HAL_MIN_TX_TIMER_VAL 0 +#define XGE_HAL_MAX_TX_TIMER_VAL 65535 + + int timer_ac_en; +#define XGE_HAL_MIN_TX_TIMER_AC_EN 0 +#define XGE_HAL_MAX_TX_TIMER_AC_EN 1 + + int timer_ci_en; +#define XGE_HAL_MIN_TX_TIMER_CI_EN 0 +#define XGE_HAL_MAX_TX_TIMER_CI_EN 1 + + +} xge_hal_tti_config_t; + +/** + * struct xge_hal_rti_config_t - Xframe Rx interrupt configuration. + * @urange_a: Link utilization range A. The value from 0 to 100%. + * @ufc_a: Frame count for the utilization range A. Interrupt will be generated + * each time when (and only when) the line is utilized no more + * than @urange_a percent inbound, + * and number of received frames is greater or equal @ufc_a. + * @urange_b: Link utilization range B. + * @ufc_b: Frame count for the utilization range B. + * @urange_c: Link utilization range C. + * @ufc_c: Frame count for the utilization range C. + * @urange_d: Link utilization range D. + * @ufc_d: Frame count for the utilization range D. + * @timer_ac_en: Enable auto-cancel. That is, reset the timer if utilization + * interrupt was generated during the interval. + * @timer_val_us: Interval of time, in microseconds, at which receive timer + * interrupt is to be generated. The timer interrupt is generated + * only in presence of the inbound traffic. Note also that timer + * interrupt and utilization interrupt are two separate interrupt + * sources. + * + * Xframe receive interrupt configuration. + * See Xframe User Guide, Section 3.5 "Device Interrupts" + * for more details. Note also (min, max) + * ranges in the body of the xge_hal_intr_config_t structure. + * Note: Valid (min, max) range for each attribute is specified in the body of + * the xge_hal_rti_config_t{} structure. Please refer to the + * corresponding header file. + */ +typedef struct xge_hal_rti_config_t { + + int urange_a; +#define XGE_HAL_MIN_RX_URANGE_A 0 +#define XGE_HAL_MAX_RX_URANGE_A 127 + + int ufc_a; +#define XGE_HAL_MIN_RX_UFC_A 0 +#define XGE_HAL_MAX_RX_UFC_A 65535 + + int urange_b; +#define XGE_HAL_MIN_RX_URANGE_B 0 +#define XGE_HAL_MAX_RX_URANGE_B 127 + + int ufc_b; +#define XGE_HAL_MIN_RX_UFC_B 0 +#define XGE_HAL_MAX_RX_UFC_B 65535 + + int urange_c; +#define XGE_HAL_MIN_RX_URANGE_C 0 +#define XGE_HAL_MAX_RX_URANGE_C 127 + + int ufc_c; +#define XGE_HAL_MIN_RX_UFC_C 0 +#define XGE_HAL_MAX_RX_UFC_C 65535 + + int ufc_d; +#define XGE_HAL_MIN_RX_UFC_D 0 +#define XGE_HAL_MAX_RX_UFC_D 65535 + + int timer_ac_en; +#define XGE_HAL_MIN_RX_TIMER_AC_EN 0 +#define XGE_HAL_MAX_RX_TIMER_AC_EN 1 + + int timer_val_us; +#define XGE_HAL_MIN_RX_TIMER_VAL 0 +#define XGE_HAL_MAX_RX_TIMER_VAL 65535 + +} xge_hal_rti_config_t; + +/** + * struct xge_hal_fifo_queue_t - Single fifo configuration. + * @max: Max numbers of TxDLs (that is, lists of Tx descriptors) per queue. + * @initial: Initial numbers of TxDLs per queue (can grow up to @max). + * @intr: Boolean. Use 1 to generate interrupt for each completed TxDL. + * Use 0 otherwise. + * @intr_vector: TBD + * @no_snoop_bits: If non-zero, specifies no-snoop PCI operation, + * which generally improves latency of the host bridge operation + * (see PCI specification). For valid values please refer + * to xge_hal_fifo_queue_t{} in the driver sources. + * @priority: TBD + * @configured: Boolean. Use 1 to specify that the fifo is configured. + * Only "configured" fifos can be activated and used to post + * Tx descriptors. Any subset of 8 available fifos can be + * "configured". + * @tti: TBD + * + * Single fifo configuration. + * Note: Valid (min, max) range for each attribute is specified in the body of + * the xge_hal_fifo_queue_t{} structure. Please refer to the + * corresponding header file. + * See also: xge_hal_fifo_config_t{} + */ +typedef struct xge_hal_fifo_queue_t { + int max; + int initial; +#define XGE_HAL_MIN_FIFO_QUEUE_LENGTH 2 +#define XGE_HAL_MAX_FIFO_QUEUE_LENGTH 8192 + + int intr; +#define XGE_HAL_MIN_FIFO_QUEUE_INTR 0 +#define XGE_HAL_MAX_FIFO_QUEUE_INTR 1 + + int intr_vector; +#define XGE_HAL_MIN_FIFO_QUEUE_INTR_VECTOR 0 +#define XGE_HAL_MAX_FIFO_QUEUE_INTR_VECTOR 64 + + int no_snoop_bits; +#define XGE_HAL_MIN_FIFO_QUEUE_NO_SNOOP_DISABLED 0 +#define XGE_HAL_MAX_FIFO_QUEUE_NO_SNOOP_TXD 1 +#define XGE_HAL_MAX_FIFO_QUEUE_NO_SNOOP_BUFFER 2 +#define XGE_HAL_MAX_FIFO_QUEUE_NO_SNOOP_ALL 3 + + int priority; +#define XGE_HAL_MIN_FIFO_PRIORITY 0 +#define XGE_HAL_MAX_FIFO_PRIORITY 63 + + int configured; +#define XGE_HAL_MIN_FIFO_CONFIGURED 0 +#define XGE_HAL_MAX_FIFO_CONFIGURED 1 + +#define XGE_HAL_MAX_FIFO_TTI_NUM 7 +#define XGE_HAL_MAX_FIFO_TTI_RING_0 56 + xge_hal_tti_config_t tti[XGE_HAL_MAX_FIFO_TTI_NUM]; + +} xge_hal_fifo_queue_t; + +/** + * struct xge_hal_fifo_config_t - Configuration of all 8 fifos. + * @max_frags: Max number of Tx buffers per TxDL (that is, per single + * transmit operation). + * No more than 256 transmit buffers can be specified. + * @max_aligned_frags: Number of fragments to be aligned out of + * maximum fragments (see @max_frags). + * @reserve_threshold: Descriptor reservation threshold. + * At least @reserve_threshold descriptors will remain + * unallocated at all times. + * @memblock_size: Fifo descriptors are allocated in blocks of @mem_block_size + * bytes. Setting @memblock_size to page size ensures + * by-page allocation of descriptors. 128K bytes is the + * maximum supported block size. + * @queue: Array of per-fifo configurations. + * @alignment_size: per Tx fragment DMA-able memory used to align transmit data + * (e.g., to align on a cache line). + * + * Configuration of all Xframe fifos. Includes array of xge_hal_fifo_queue_t + * structures. + * Note: Valid (min, max) range for each attribute is specified in the body of + * the xge_hal_fifo_config_t{} structure. Please refer to the + * corresponding header file. + * See also: xge_hal_ring_queue_t{}. + */ +typedef struct xge_hal_fifo_config_t { + int max_frags; +#define XGE_HAL_MIN_FIFO_FRAGS 1 +#define XGE_HAL_MAX_FIFO_FRAGS 256 + + int reserve_threshold; +#define XGE_HAL_MIN_FIFO_RESERVE_THRESHOLD 0 +#define XGE_HAL_MAX_FIFO_RESERVE_THRESHOLD 8192 + + int memblock_size; +#define XGE_HAL_MIN_FIFO_MEMBLOCK_SIZE 4096 +#define XGE_HAL_MAX_FIFO_MEMBLOCK_SIZE 131072 + + int alignment_size; +#define XGE_HAL_MIN_ALIGNMENT_SIZE 0 +#define XGE_HAL_MAX_ALIGNMENT_SIZE 65536 + + int max_aligned_frags; + /* range: (1, @max_frags) */ + +#define XGE_HAL_MIN_FIFO_NUM 1 +#define XGE_HAL_MAX_FIFO_NUM_HERC 8 +#define XGE_HAL_MAX_FIFO_NUM_TITAN (XGE_HAL_MAX_VIRTUAL_PATHS - 1) +#define XGE_HAL_MAX_FIFO_NUM (XGE_HAL_MAX_VIRTUAL_PATHS) + xge_hal_fifo_queue_t queue[XGE_HAL_MAX_FIFO_NUM]; +} xge_hal_fifo_config_t; + +/** + * struct xge_hal_rts_port_t - RTS port entry + * @num: Port number + * @udp: Port is UDP (default TCP) + * @src: Port is Source (default Destination) + */ +typedef struct xge_hal_rts_port_t { + int num; + int udp; + int src; +} xge_hal_rts_port_t; + +/** + * struct xge_hal_ring_queue_t - Single ring configuration. + * @max: Max numbers of RxD blocks per queue + * @initial: Initial numbers of RxD blocks per queue + * (can grow up to @max) + * @buffer_mode: Receive buffer mode (1, 2, 3, or 5); for details please refer + * to Xframe User Guide. + * @dram_size_mb: Size (in MB) of Xframe DRAM used for _that_ ring. + * Note that 64MB of available + * on-board DRAM is shared between receive rings. + * If a single ring is used, @dram_size_mb can be set to 64. + * Sum of all rings' @dram_size_mb cannot exceed 64. + * @intr_vector: TBD + * @backoff_interval_us: Time (in microseconds), after which Xframe + * tries to download RxDs posted by the host. + * Note that the "backoff" does not happen if host posts receive + * descriptors in the timely fashion. + * @max_frm_len: Maximum frame length that can be received on _that_ ring. + * Setting this field to -1 ensures that the ring will + * "accept" MTU-size frames (note that MTU can be changed at + * runtime). + * Any value other than (-1) specifies a certain "hard" + * limit on the receive frame sizes. + * The field can be used to activate receive frame-length based + * steering. + * @priority: Ring priority. 0 - highest, 7 - lowest. The value is used + * to give prioritized access to PCI-X. See Xframe documentation + * for details. + * @rth_en: Enable Receive Traffic Hashing (RTH). + * @no_snoop_bits: If non-zero, specifies no-snoop PCI operation, + * which generally improves latency of the host bridge operation + * (see PCI specification). For valid values please refer + * to xge_hal_ring_queue_t{} in the driver sources. + * @indicate_max_pkts: Sets maximum number of received frames to be processed + * within single interrupt. + * @configured: Boolean. Use 1 to specify that the ring is configured. + * Only "configured" rings can be activated and used to post + * Rx descriptors. Any subset of 8 available rings can be + * "configured". + * @rts_mac_en: 1 - To enable Receive MAC address steering. + * 0 - To disable Receive MAC address steering. + * @rth_en: TBD + * @rts_port_en: TBD + * @rts_ports: TBD + * @rti: Xframe receive interrupt configuration. + * + * Single ring configuration. + * Note: Valid (min, max) range for each attribute is specified in the body of + * the xge_hal_ring_queue_t{} structure. Please refer to the + * corresponding header file. + * See also: xge_hal_fifo_config_t{}. + */ +typedef struct xge_hal_ring_queue_t { + int max; + int initial; +#define XGE_HAL_MIN_RING_QUEUE_BLOCKS 1 +#define XGE_HAL_MAX_RING_QUEUE_BLOCKS 64 + + int buffer_mode; +#define XGE_HAL_RING_QUEUE_BUFFER_MODE_1 1 +#define XGE_HAL_RING_QUEUE_BUFFER_MODE_2 2 +#define XGE_HAL_RING_QUEUE_BUFFER_MODE_3 3 +#define XGE_HAL_RING_QUEUE_BUFFER_MODE_5 5 + + int dram_size_mb; +#define XGE_HAL_MIN_RING_QUEUE_SIZE 0 +#define XGE_HAL_MAX_RING_QUEUE_SIZE_XENA 64 +#define XGE_HAL_MAX_RING_QUEUE_SIZE_HERC 32 + + int intr_vector; +#define XGE_HAL_MIN_RING_QUEUE_INTR_VECTOR 0 +#define XGE_HAL_MAX_RING_QUEUE_INTR_VECTOR 64 + + int backoff_interval_us; +#define XGE_HAL_MIN_BACKOFF_INTERVAL_US 1 +#define XGE_HAL_MAX_BACKOFF_INTERVAL_US 125000 + + int max_frm_len; +#define XGE_HAL_MIN_MAX_FRM_LEN -1 +#define XGE_HAL_MAX_MAX_FRM_LEN 9622 + + int priority; +#define XGE_HAL_MIN_RING_PRIORITY 0 +#define XGE_HAL_MAX_RING_PRIORITY 7 + + int no_snoop_bits; +#define XGE_HAL_MIN_RING_QUEUE_NO_SNOOP_DISABLED 0 +#define XGE_HAL_MAX_RING_QUEUE_NO_SNOOP_RXD 1 +#define XGE_HAL_MAX_RING_QUEUE_NO_SNOOP_BUFFER 2 +#define XGE_HAL_MAX_RING_QUEUE_NO_SNOOP_ALL 3 + + int indicate_max_pkts; +#define XGE_HAL_MIN_RING_INDICATE_MAX_PKTS 1 +#define XGE_HAL_MAX_RING_INDICATE_MAX_PKTS 65536 + + int configured; +#define XGE_HAL_MIN_RING_CONFIGURED 0 +#define XGE_HAL_MAX_RING_CONFIGURED 1 + + int rts_mac_en; +#define XGE_HAL_MIN_RING_RTS_MAC_EN 0 +#define XGE_HAL_MAX_RING_RTS_MAC_EN 1 + + int rth_en; +#define XGE_HAL_MIN_RING_RTH_EN 0 +#define XGE_HAL_MAX_RING_RTH_EN 1 + + int rts_port_en; +#define XGE_HAL_MIN_RING_RTS_PORT_EN 0 +#define XGE_HAL_MAX_RING_RTS_PORT_EN 1 + +#define XGE_HAL_MAX_STEERABLE_PORTS 32 + xge_hal_rts_port_t rts_ports[XGE_HAL_MAX_STEERABLE_PORTS]; + + xge_hal_rti_config_t rti; + +} xge_hal_ring_queue_t; + +/** + * struct xge_hal_ring_config_t - Array of ring configurations. + * @memblock_size: Ring descriptors are allocated in blocks of @mem_block_size + * bytes. Setting @memblock_size to page size ensures + * by-page allocation of descriptors. 128K bytes is the + * upper limit. + * @scatter_mode: Xframe supports two receive scatter modes: A and B. + * For details please refer to Xframe User Guide. + * @strip_vlan_tag: TBD + * @queue: Array of all Xframe ring configurations. + * + * Array of ring configurations. + * See also: xge_hal_ring_queue_t{}. + */ +typedef struct xge_hal_ring_config_t { + + int memblock_size; +#define XGE_HAL_MIN_RING_MEMBLOCK_SIZE 4096 +#define XGE_HAL_MAX_RING_MEMBLOCK_SIZE 131072 + + int scatter_mode; +#define XGE_HAL_RING_QUEUE_SCATTER_MODE_A 0 +#define XGE_HAL_RING_QUEUE_SCATTER_MODE_B 1 + + int strip_vlan_tag; +#define XGE_HAL_RING_DONOT_STRIP_VLAN_TAG 0 +#define XGE_HAL_RING_STRIP_VLAN_TAG 1 + +#define XGE_HAL_MIN_RING_NUM 1 +#define XGE_HAL_MAX_RING_NUM_HERC 8 +#define XGE_HAL_MAX_RING_NUM_TITAN (XGE_HAL_MAX_VIRTUAL_PATHS - 1) +#define XGE_HAL_MAX_RING_NUM (XGE_HAL_MAX_VIRTUAL_PATHS) + xge_hal_ring_queue_t queue[XGE_HAL_MAX_RING_NUM]; + +} xge_hal_ring_config_t; + +/** + * struct xge_hal_mac_config_t - MAC configuration. + * @media: Transponder type. + * @tmac_util_period: The sampling period over which the transmit utilization + * is calculated. + * @rmac_util_period: The sampling period over which the receive utilization + * is calculated. + * @rmac_strip_pad: Determines whether padding of received frames is removed by + * the MAC or sent to the host. + * @rmac_bcast_en: Enable frames containing broadcast address to be + * passed to the host. + * @rmac_pause_gen_en: Received pause generation enable. + * @rmac_pause_rcv_en: Receive pause enable. + * @rmac_pause_time: The value to be inserted in outgoing pause frames. + * Has units of pause quanta (one pause quanta = 512 bit times). + * @mc_pause_threshold_q0q3: Contains thresholds for pause frame generation + * for queues 0 through 3. The threshold value indicates portion of the + * individual receive buffer queue size. Thresholds have a range of 0 to + * 255, allowing 256 possible watermarks in a queue. + * @mc_pause_threshold_q4q7: Contains thresholds for pause frame generation + * for queues 4 through 7. The threshold value indicates portion of the + * individual receive buffer queue size. Thresholds have a range of 0 to + * 255, allowing 256 possible watermarks in a queue. + * + * MAC configuration. This includes various aspects of configuration, including: + * - Pause frame threshold; + * - sampling rate to calculate link utilization; + * - enabling/disabling broadcasts. + * + * See Xframe User Guide for more details. + * Note: Valid (min, max) range for each attribute is specified in the body of + * the xge_hal_mac_config_t{} structure. Please refer to the + * corresponding include file. + */ +typedef struct xge_hal_mac_config_t { + int media; +#define XGE_HAL_MIN_MEDIA 0 +#define XGE_HAL_MEDIA_SR 0 +#define XGE_HAL_MEDIA_SW 1 +#define XGE_HAL_MEDIA_LR 2 +#define XGE_HAL_MEDIA_LW 3 +#define XGE_HAL_MEDIA_ER 4 +#define XGE_HAL_MEDIA_EW 5 +#define XGE_HAL_MAX_MEDIA 5 + + int tmac_util_period; +#define XGE_HAL_MIN_TMAC_UTIL_PERIOD 0 +#define XGE_HAL_MAX_TMAC_UTIL_PERIOD 15 + + int rmac_util_period; +#define XGE_HAL_MIN_RMAC_UTIL_PERIOD 0 +#define XGE_HAL_MAX_RMAC_UTIL_PERIOD 15 + + int rmac_bcast_en; +#define XGE_HAL_MIN_RMAC_BCAST_EN 0 +#define XGE_HAL_MAX_RMAC_BCAST_EN 1 + + int rmac_pause_gen_en; +#define XGE_HAL_MIN_RMAC_PAUSE_GEN_EN 0 +#define XGE_HAL_MAX_RMAC_PAUSE_GEN_EN 1 + + int rmac_pause_rcv_en; +#define XGE_HAL_MIN_RMAC_PAUSE_RCV_EN 0 +#define XGE_HAL_MAX_RMAC_PAUSE_RCV_EN 1 + + int rmac_pause_time; +#define XGE_HAL_MIN_RMAC_HIGH_PTIME 16 +#define XGE_HAL_MAX_RMAC_HIGH_PTIME 65535 + + int mc_pause_threshold_q0q3; +#define XGE_HAL_MIN_MC_PAUSE_THRESHOLD_Q0Q3 0 +#define XGE_HAL_MAX_MC_PAUSE_THRESHOLD_Q0Q3 254 + + int mc_pause_threshold_q4q7; +#define XGE_HAL_MIN_MC_PAUSE_THRESHOLD_Q4Q7 0 +#define XGE_HAL_MAX_MC_PAUSE_THRESHOLD_Q4Q7 254 + +} xge_hal_mac_config_t; + +#ifdef XGEHAL_RNIC + +/* + * struct xge_hal_vp_config_t - Configuration of virtual path + * @vp_id: Virtual Path Id + * @vp_valid: Flag specifies if the configuration is valid + * @bitmap_intr_num: Interrupt Number associated with the bitmap + * @nce_oid_start: The start of the NCE ID range + * @nce_oid_end: The end of the NCE ID range + * @session_oid_start: The start of the Session ID range + * @session_oid_end: The end of the Session ID range + * @srq_oid_start: The start of the HSRQ ID range + * @srq_oid_end: The end of the SRQ ID range + * @cqrq_oid_start: The start of the CQRQ range + * @cqrq_oid_end: The end of the CQRQ range + * @umq_length: Length of up message queue + * @umq_int_ctrl: Interrupt control for up Message queue + * @umq_gen_compl: Generate completion for up message queue + * @dmq_length: Length of down message queue + * @dmq_int_ctrl: Interrupt control for down Message queue + * @dmq_gen_compl: Generate completion for up message queue + * + * This structure is used by the driver to pass the configuration parameters to + * configure Virtual Path. + */ +typedef struct xge_hal_vp_config_t{ + u32 vp_id; + u32 vp_valid; +#define XGE_HAL_VP_CONFIG_INVALID 0 +#define XGE_HAL_VP_CONFIG_VALID 1 + + int bitmap_intr_num; +#define XGE_HAL_BITMAP_INTR_NUM_MIN 0 +#define XGE_HAL_BITMAP_INTR_NUM_MAX 3 + + u32 nce_oid_start; + u32 nce_oid_end; + u32 session_oid_start; + u32 session_oid_end; + u32 srq_oid_start; + u32 srq_oid_end; + u32 cqrq_oid_start; + u32 cqrq_oid_end; + u32 umq_length; + u32 umq_int_ctrl; + u32 umq_gen_compl; + u32 dmq_length; + u32 dmq_int_ctrl; + u32 dmq_gen_compl; +}xge_hal_vp_config_t; + +#endif + +/** + * struct xge_hal_device_config_t - Device configuration. + * @mtu: Current mtu size. + * @isr_polling_cnt: Maximum number of times to "poll" for Tx and Rx + * completions. Used in xge_hal_device_handle_irq(). + * @latency_timer: Specifies, in units of PCI bus clocks, and in conformance + * with the PCI Specification, the value of the Latency Timer + * for this PCI bus master. + * Specify either zero or -1 to use BIOS default. + * @napi_weight: (TODO) + * @max_splits_trans: Maximum number of PCI-X split transactions. + * Specify (-1) to use BIOS default. + * @mmrb_count: Maximum Memory Read Byte Count. Use (-1) to use default + * BIOS value. Otherwise: mmrb_count = 0 corresponds to 512B; + * 1 - 1KB, 2 - 2KB, and 3 - 4KB. + * @shared_splits: The number of Outstanding Split Transactions that is + * shared by Tx and Rx requests. The device stops issuing Tx + * requests once the number of Outstanding Split Transactions is + * equal to the value of Shared_Splits. + * A value of zero indicates that the Tx and Rx share all allocated + * Split Requests, i.e. the device can issue both types (Tx and Rx) + * of read requests until the number of Maximum Outstanding Split + * Transactions is reached. + * @stats_refresh_time_sec: Sets the default interval for automatic stats transfer + * to the host. This includes MAC stats as well as PCI stats. + * See xge_hal_stats_hw_info_t{}. + * @pci_freq_mherz: PCI clock frequency, e.g.: 133 for 133MHz. + * @intr_mode: Line, MSI, or MSI-X interrupt. + * @sched_timer_us: If greater than zero, specifies time interval + * (in microseconds) for the device to generate + * interrupt. Note that unlike tti and rti interrupts, + * the scheduled interrupt is generated independently of + * whether there is transmit or receive traffic, respectively. + * @sched_timer_one_shot: 1 - generate scheduled interrupt only once. + * 0 - generate scheduled interrupt periodically at the specified + * @sched_timer_us interval. + * + * @ring: See xge_hal_ring_config_t{}. + * @mac: See xge_hal_mac_config_t{}. + * @tti: See xge_hal_tti_config_t{}. + * @fifo: See xge_hal_fifo_config_t{}. + * + * @dump_on_serr: Dump adapter state ("about", statistics, registers) on SERR#. + * @dump_on_eccerr: Dump adapter state ("about", statistics, registers) on + * ECC error. + * @dump_on_parityerr: Dump adapter state ("about", statistics, registers) on + * parity error. + * @rth_en: Enable Receive Traffic Hashing(RTH) using IT(Indirection Table). + * @rth_bucket_size: RTH bucket width (in bits). For valid range please see + * xge_hal_device_config_t{} in the driver sources. + * @rth_spdm_en: Enable Receive Traffic Hashing(RTH) using SPDM(Socket Pair + * Direct Match). + * @rth_spdm_use_l4: Set to 1, if the L4 ports are used in the calculation of + * hash value in the RTH SPDM based steering. + * @rxufca_intr_thres: (TODO) + * @rxufca_lo_lim: (TODO) + * @rxufca_hi_lim: (TODO) + * @rxufca_lbolt_period: (TODO) + * @link_valid_cnt: link-valid counting is done only at device-open time, + * to determine with the specified certainty that the link is up. See also + * @link_retry_cnt. + * @link_retry_cnt: Max number of polls for link-up. Done only at device + * open time. Reducing this value as well as the previous @link_valid_cnt, + * speeds up device startup, which may be important if the driver + * is compiled into OS. + * @link_stability_period: Specify the period for which the link must be + * stable in order for the adapter to declare "LINK UP". + * The enumerated settings (see Xframe-II UG) are: + * 0 ........... instantaneous + * 1 ........... 500 ´s + * 2 ........... 1 ms + * 3 ........... 64 ms + * 4 ........... 256 ms + * 5 ........... 512 ms + * 6 ........... 1 s + * 7 ........... 2 s + * @device_poll_millis: Specify the interval (in mulliseconds) between + * successive xge_hal_device_poll() runs. + * stable in order for the adapter to declare "LINK UP". + * @no_isr_events: TBD + * @lro_sg_size: TBD + * @lro_frm_len: TBD + * @bimodal_interrupts: Enable bimodal interrupts in device + * @bimodal_timer_lo_us: TBD + * @bimodal_timer_hi_us: TBD + * @rts_mac_en: Enable Receive Traffic Steering using MAC destination address + * @rts_qos_en: TBD + * @rts_port_en: TBD + * @vp_config: Configuration for virtual paths + * @max_cqe_groups: The maximum number of adapter CQE group blocks a CQRQ + * can own at any one time. + * @max_num_wqe_od_groups: The maximum number of WQE Headers/OD Groups that + * this S-RQ can own at any one time. + * @no_wqe_threshold: Maximum number of times adapter polls WQE Hdr blocks for + * WQEs before generating a message or interrupt. + * @refill_threshold_high:This field provides a hysteresis upper bound for + * automatic adapter refill operations. + * @refill_threshold_low:This field provides a hysteresis lower bound for + * automatic adapter refill operations. + * @eol_policy:This field sets the policy for handling the end of list condition.
+ * 2'b00 - When EOL is reached,poll until last block wrapper size is no longer 0.
+ * 2'b01 - Send UMQ message when EOL is reached.
+ * 2'b1x - Poll until the poll_count_max is reached and if still EOL,send UMQ message + * @eol_poll_count_max:sets the maximum number of times the queue manager will poll for + * a non-zero block wrapper before giving up and sending a UMQ message + * @ack_blk_limit: Limit on the maximum number of ACK list blocks that can be held + * by a session at any one time. + * @poll_or_doorbell: TBD + * + * Xframe configuration. + * Contains per-device configuration parameters, including: + * - latency timer (settable via PCI configuration space); + * - maximum number of split transactions; + * - maximum number of shared splits; + * - stats sampling interval, etc. + * + * In addition, xge_hal_device_config_t{} includes "subordinate" + * configurations, including: + * - fifos and rings; + * - MAC (see xge_hal_mac_config_t{}). + * + * See Xframe User Guide for more details. + * Note: Valid (min, max) range for each attribute is specified in the body of + * the xge_hal_device_config_t{} structure. Please refer to the + * corresponding include file. + * See also: xge_hal_tti_config_t{}, xge_hal_stats_hw_info_t{}, + * xge_hal_mac_config_t{}. + */ +typedef struct xge_hal_device_config_t { + int mtu; +#define XGE_HAL_MIN_INITIAL_MTU XGE_HAL_MIN_MTU +#define XGE_HAL_MAX_INITIAL_MTU XGE_HAL_MAX_MTU + + int isr_polling_cnt; +#define XGE_HAL_MIN_ISR_POLLING_CNT 0 +#define XGE_HAL_MAX_ISR_POLLING_CNT 65536 + + int latency_timer; +#define XGE_HAL_USE_BIOS_DEFAULT_LATENCY -1 +#define XGE_HAL_MIN_LATENCY_TIMER 8 +#define XGE_HAL_MAX_LATENCY_TIMER 255 + + int napi_weight; +#define XGE_HAL_DEF_NAPI_WEIGHT 64 + + int max_splits_trans; +#define XGE_HAL_USE_BIOS_DEFAULT_SPLITS -1 +#define XGE_HAL_ONE_SPLIT_TRANSACTION 0 +#define XGE_HAL_TWO_SPLIT_TRANSACTION 1 +#define XGE_HAL_THREE_SPLIT_TRANSACTION 2 +#define XGE_HAL_FOUR_SPLIT_TRANSACTION 3 +#define XGE_HAL_EIGHT_SPLIT_TRANSACTION 4 +#define XGE_HAL_TWELVE_SPLIT_TRANSACTION 5 +#define XGE_HAL_SIXTEEN_SPLIT_TRANSACTION 6 +#define XGE_HAL_THIRTYTWO_SPLIT_TRANSACTION 7 + + int mmrb_count; +#define XGE_HAL_DEFAULT_BIOS_MMRB_COUNT -1 +#define XGE_HAL_MIN_MMRB_COUNT 0 /* 512b */ +#define XGE_HAL_MAX_MMRB_COUNT 3 /* 4k */ + + int shared_splits; +#define XGE_HAL_MIN_SHARED_SPLITS 0 +#define XGE_HAL_MAX_SHARED_SPLITS 31 + + int stats_refresh_time_sec; +#define XGE_HAL_STATS_REFRESH_DISABLE 0 +#define XGE_HAL_MIN_STATS_REFRESH_TIME 1 +#define XGE_HAL_MAX_STATS_REFRESH_TIME 300 + + int pci_freq_mherz; +#define XGE_HAL_PCI_FREQ_MHERZ_33 33 +#define XGE_HAL_PCI_FREQ_MHERZ_66 66 +#define XGE_HAL_PCI_FREQ_MHERZ_100 100 +#define XGE_HAL_PCI_FREQ_MHERZ_133 133 +#define XGE_HAL_PCI_FREQ_MHERZ_266 266 + + int intr_mode; +#define XGE_HAL_INTR_MODE_IRQLINE 0 +#define XGE_HAL_INTR_MODE_MSI 1 +#define XGE_HAL_INTR_MODE_MSIX 2 + + int sched_timer_us; +#define XGE_HAL_SCHED_TIMER_DISABLED 0 +#define XGE_HAL_SCHED_TIMER_MIN 0 +#define XGE_HAL_SCHED_TIMER_MAX 0xFFFFF + + int sched_timer_one_shot; +#define XGE_HAL_SCHED_TIMER_ON_SHOT_DISABLE 0 +#define XGE_HAL_SCHED_TIMER_ON_SHOT_ENABLE 1 + + xge_hal_ring_config_t ring; + xge_hal_mac_config_t mac; + xge_hal_fifo_config_t fifo; + + int dump_on_serr; +#define XGE_HAL_DUMP_ON_SERR_DISABLE 0 +#define XGE_HAL_DUMP_ON_SERR_ENABLE 1 + + int dump_on_eccerr; +#define XGE_HAL_DUMP_ON_ECCERR_DISABLE 0 +#define XGE_HAL_DUMP_ON_ECCERR_ENABLE 1 + + int dump_on_parityerr; +#define XGE_HAL_DUMP_ON_PARITYERR_DISABLE 0 +#define XGE_HAL_DUMP_ON_PARITYERR_ENABLE 1 + + int rth_en; +#define XGE_HAL_RTH_DISABLE 0 +#define XGE_HAL_RTH_ENABLE 1 + + int rth_bucket_size; +#define XGE_HAL_MIN_RTH_BUCKET_SIZE 1 +#define XGE_HAL_MAX_RTH_BUCKET_SIZE 8 + + int rth_spdm_en; +#define XGE_HAL_RTH_SPDM_DISABLE 0 +#define XGE_HAL_RTH_SPDM_ENABLE 1 + + int rth_spdm_use_l4; +#define XGE_HAL_RTH_SPDM_USE_L4 1 + + int rxufca_intr_thres; +#define XGE_HAL_RXUFCA_INTR_THRES_MIN 1 +#define XGE_HAL_RXUFCA_INTR_THRES_MAX 4096 + + int rxufca_lo_lim; +#define XGE_HAL_RXUFCA_LO_LIM_MIN 1 +#define XGE_HAL_RXUFCA_LO_LIM_MAX 16 + + int rxufca_hi_lim; +#define XGE_HAL_RXUFCA_HI_LIM_MIN 1 +#define XGE_HAL_RXUFCA_HI_LIM_MAX 256 + + int rxufca_lbolt_period; +#define XGE_HAL_RXUFCA_LBOLT_PERIOD_MIN 1 +#define XGE_HAL_RXUFCA_LBOLT_PERIOD_MAX 1024 + + int link_valid_cnt; +#define XGE_HAL_LINK_VALID_CNT_MIN 0 +#define XGE_HAL_LINK_VALID_CNT_MAX 127 + + int link_retry_cnt; +#define XGE_HAL_LINK_RETRY_CNT_MIN 0 +#define XGE_HAL_LINK_RETRY_CNT_MAX 127 + + int link_stability_period; +#define XGE_HAL_DEFAULT_LINK_STABILITY_PERIOD 2 /* 1ms */ +#define XGE_HAL_MIN_LINK_STABILITY_PERIOD 0 /* instantaneous */ +#define XGE_HAL_MAX_LINK_STABILITY_PERIOD 7 /* 2s */ + + int device_poll_millis; +#define XGE_HAL_DEFAULT_DEVICE_POLL_MILLIS 1000 +#define XGE_HAL_MIN_DEVICE_POLL_MILLIS 1 +#define XGE_HAL_MAX_DEVICE_POLL_MILLIS 100000 + + int no_isr_events; +#define XGE_HAL_NO_ISR_EVENTS_MIN 0 +#define XGE_HAL_NO_ISR_EVENTS_MAX 1 + + int lro_sg_size; +#define XGE_HAL_LRO_DEFAULT_SG_SIZE 10 +#define XGE_HAL_LRO_MIN_SG_SIZE 1 +#define XGE_HAL_LRO_MAX_SG_SIZE 64 + + int lro_frm_len; +#define XGE_HAL_LRO_DEFAULT_FRM_LEN 65536 +#define XGE_HAL_LRO_MIN_FRM_LEN 4096 +#define XGE_HAL_LRO_MAX_FRM_LEN 65536 + + int bimodal_interrupts; +#define XGE_HAL_BIMODAL_INTR_MIN -1 +#define XGE_HAL_BIMODAL_INTR_MAX 1 + + int bimodal_timer_lo_us; +#define XGE_HAL_BIMODAL_TIMER_LO_US_MIN 1 +#define XGE_HAL_BIMODAL_TIMER_LO_US_MAX 127 + + int bimodal_timer_hi_us; +#define XGE_HAL_BIMODAL_TIMER_HI_US_MIN 128 +#define XGE_HAL_BIMODAL_TIMER_HI_US_MAX 65535 + + int rts_mac_en; +#define XGE_HAL_RTS_MAC_DISABLE 0 +#define XGE_HAL_RTS_MAC_ENABLE 1 + + int rts_qos_en; +#define XGE_HAL_RTS_QOS_DISABLE 0 +#define XGE_HAL_RTS_QOS_ENABLE 1 + + int rts_port_en; +#define XGE_HAL_RTS_PORT_DISABLE 0 +#define XGE_HAL_RTS_PORT_ENABLE 1 + +#ifdef XGEHAL_RNIC + + xge_hal_vp_config_t vp_config[XGE_HAL_MAX_VIRTUAL_PATHS]; + + int max_cqe_groups; +#define XGE_HAL_MAX_CQE_GROUPS_MIN 1 +#define XGE_HAL_MAX_CQE_GROUPS_MAX 16 + + int max_num_wqe_od_groups; +#define XGE_HAL_MAX_NUM_OD_GROUPS_MIN 1 +#define XGE_HAL_MAX_NUM_OD_GROUPS_MAX 16 + + int no_wqe_threshold; +#define XGE_HAL_NO_WQE_THRESHOLD_MIN 1 +#define XGE_HAL_NO_WQE_THRESHOLD_MAX 16 + + int refill_threshold_high; +#define XGE_HAL_REFILL_THRESHOLD_HIGH_MIN 1 +#define XGE_HAL_REFILL_THRESHOLD_HIGH_MAX 16 + + int refill_threshold_low; +#define XGE_HAL_REFILL_THRESHOLD_LOW_MIN 1 +#define XGE_HAL_REFILL_THRESHOLD_LOW_MAX 16 + + int ack_blk_limit; +#define XGE_HAL_ACK_BLOCK_LIMIT_MIN 1 +#define XGE_HAL_ACK_BLOCK_LIMIT_MAX 16 + + int poll_or_doorbell; +#define XGE_HAL_POLL_OR_DOORBELL_POLL 1 +#define XGE_HAL_POLL_OR_DOORBELL_DOORBELL 0 + + +#endif + +} xge_hal_device_config_t; + +/** + * struct xge_hal_driver_config_t - HAL (layer) configuration. + * @periodic_poll_interval_millis: Interval, in milliseconds, which is used to + * periodically poll HAL, i.e, invoke + * xge_hal_device_poll(). + * Note that HAL does not maintain its own + * polling context. HAL relies on ULD to + * provide one. + * @queue_size_initial: Initial size of the HAL protected event queue. + * The queue is shared by HAL and upper-layer drivers. + * The queue is used to exchange and process slow-path + * events. See xge_hal_event_e. + * @queue_size_max: Maximum size of the HAL queue. Depending on the load, + * the queue may grow at run-time up to @queue_max_size. + * @tracebuf_size: Size of the trace buffer. Set it to '0' to disable. + * HAL configuration. (Note: do not confuse HAL layer with (possibly multiple) + * HAL devices.) + * Currently this structure contains just a few basic values. + * Note: Valid (min, max) range for each attribute is specified in the body of + * the structure. Please refer to the corresponding header file. + * See also: xge_hal_device_poll() + */ +typedef struct xge_hal_driver_config_t { + int queue_size_initial; +#define XGE_HAL_MIN_QUEUE_SIZE_INITIAL 1 +#define XGE_HAL_MAX_QUEUE_SIZE_INITIAL 16 + + int queue_size_max; +#define XGE_HAL_MIN_QUEUE_SIZE_MAX 1 +#define XGE_HAL_MAX_QUEUE_SIZE_MAX 16 + +#ifdef XGE_TRACE_INTO_CIRCULAR_ARR + int tracebuf_size; +#define XGE_HAL_MIN_CIRCULAR_ARR 4096 +#define XGE_HAL_MAX_CIRCULAR_ARR 1048576 +#define XGE_HAL_DEF_CIRCULAR_ARR XGE_OS_HOST_PAGE_SIZE + + int tracebuf_timestamp_en; +#define XGE_HAL_MIN_TIMESTAMP_EN 0 +#define XGE_HAL_MAX_TIMESTAMP_EN 1 +#endif + +} xge_hal_driver_config_t; + + +/* ========================== PRIVATE API ================================= */ + +xge_hal_status_e +__hal_device_config_check_common (xge_hal_device_config_t *new_config); + +xge_hal_status_e +__hal_device_config_check_xena (xge_hal_device_config_t *new_config); + +xge_hal_status_e +__hal_device_config_check_herc (xge_hal_device_config_t *new_config); + +xge_hal_status_e +__hal_driver_config_check (xge_hal_driver_config_t *new_config); + +__EXTERN_END_DECLS + +#endif /* XGE_HAL_CONFIG_H */ diff --git a/sys/dev/nxge/include/xgehal-device.h b/sys/dev/nxge/include/xgehal-device.h new file mode 100644 index 0000000..22bc792 --- /dev/null +++ b/sys/dev/nxge/include/xgehal-device.h @@ -0,0 +1,1036 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-device.h + * + * Description: HAL device object functionality + * + * Created: 14 May 2004 + */ + +#ifndef XGE_HAL_DEVICE_H +#define XGE_HAL_DEVICE_H + +#include <dev/nxge/include/xge-os-pal.h> +#include <dev/nxge/include/xge-queue.h> +#include <dev/nxge/include/xgehal-event.h> +#include <dev/nxge/include/xgehal-config.h> +#include <dev/nxge/include/xgehal-regs.h> +#include <dev/nxge/include/xgehal-channel.h> +#include <dev/nxge/include/xgehal-stats.h> +#include <dev/nxge/include/xgehal-ring.h> +#ifdef XGEHAL_RNIC +#include "xgehal-common-regs.h" +#include "xgehal-pcicfg-mgmt-regs.h" +#include "xgehal-mrpcim-regs.h" +#include "xgehal-srpcim-regs.h" +#include "xgehal-vpath-regs.h" +#include "xgehal-bitmap.h" +#include "xgehal-virtualpath.h" +#include "xgehal-lbwrapper.h" +#include "xgehal-blockpool.h" +#include "xgehal-regpool.h" +#endif + +__EXTERN_BEGIN_DECLS + +#define XGE_HAL_VPD_LENGTH 80 +#define XGE_HAL_CARD_XENA_VPD_ADDR 0x50 +#define XGE_HAL_CARD_HERC_VPD_ADDR 0x80 +#define XGE_HAL_VPD_READ_COMPLETE 0x80 +#define XGE_HAL_VPD_BUFFER_SIZE 128 +#define XGE_HAL_DEVICE_XMSI_WAIT_MAX_MILLIS 500 +#define XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS 500 +#define XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS 500 +#define XGE_HAL_DEVICE_FAULT_WAIT_MAX_MILLIS 50 +#define XGE_HAL_DEVICE_RESET_WAIT_MAX_MILLIS 250 +#define XGE_HAL_DEVICE_SPDM_READY_WAIT_MAX_MILLIS 250 /* TODO */ + +#define XGE_HAL_MAGIC 0x12345678 +#define XGE_HAL_DEAD 0xDEADDEAD +#define XGE_HAL_DUMP_BUF_SIZE 0x4000 + +#define XGE_HAL_LRO_MAX_BUCKETS 32 + +/** + * enum xge_hal_card_e - Xframe adapter type. + * @XGE_HAL_CARD_UNKNOWN: Unknown device. + * @XGE_HAL_CARD_XENA: Xframe I device. + * @XGE_HAL_CARD_HERC: Xframe II (PCI-266Mhz) device. + * @XGE_HAL_CARD_TITAN: Xframe ER (PCI-266Mhz) device. + * + * Enumerates Xframe adapter types. The corresponding PCI device + * IDs are listed in the file xgehal-defs.h. + * (See XGE_PCI_DEVICE_ID_XENA_1, etc.) + * + * See also: xge_hal_device_check_id(). + */ +typedef enum xge_hal_card_e { + XGE_HAL_CARD_UNKNOWN = 0, + XGE_HAL_CARD_XENA = 1, + XGE_HAL_CARD_HERC = 2, + XGE_HAL_CARD_TITAN = 3, +} xge_hal_card_e; + +/** + * struct xge_hal_device_attr_t - Device memory spaces. + * @regh0: BAR0 mapped memory handle (Solaris), or simply PCI device @pdev + * (Linux and the rest.) + * @regh1: BAR1 mapped memory handle. Same comment as above. + * @bar0: BAR0 virtual address. + * @bar1: BAR1 virtual address. + * @irqh: IRQ handle (Solaris). + * @cfgh: Configuration space handle (Solaris), or PCI device @pdev (Linux). + * @pdev: PCI device object. + * + * Device memory spaces. Includes configuration, BAR0, BAR1, etc. per device + * mapped memories. Also, includes a pointer to OS-specific PCI device object. + */ +typedef struct xge_hal_device_attr_t { + pci_reg_h regh0; + pci_reg_h regh1; + pci_reg_h regh2; + char *bar0; + char *bar1; + char *bar2; + pci_irq_h irqh; + pci_cfg_h cfgh; + pci_dev_h pdev; +} xge_hal_device_attr_t; + +/** + * enum xge_hal_device_link_state_e - Link state enumeration. + * @XGE_HAL_LINK_NONE: Invalid link state. + * @XGE_HAL_LINK_DOWN: Link is down. + * @XGE_HAL_LINK_UP: Link is up. + * + */ +typedef enum xge_hal_device_link_state_e { + XGE_HAL_LINK_NONE, + XGE_HAL_LINK_DOWN, + XGE_HAL_LINK_UP +} xge_hal_device_link_state_e; + + +/** + * enum xge_hal_pci_mode_e - PIC bus speed and mode specific enumeration. + * @XGE_HAL_PCI_33MHZ_MODE: 33 MHZ pci mode. + * @XGE_HAL_PCI_66MHZ_MODE: 66 MHZ pci mode. + * @XGE_HAL_PCIX_M1_66MHZ_MODE: PCIX M1 66MHZ mode. + * @XGE_HAL_PCIX_M1_100MHZ_MODE: PCIX M1 100MHZ mode. + * @XGE_HAL_PCIX_M1_133MHZ_MODE: PCIX M1 133MHZ mode. + * @XGE_HAL_PCIX_M2_66MHZ_MODE: PCIX M2 66MHZ mode. + * @XGE_HAL_PCIX_M2_100MHZ_MODE: PCIX M2 100MHZ mode. + * @XGE_HAL_PCIX_M2_133MHZ_MODE: PCIX M3 133MHZ mode. + * @XGE_HAL_PCIX_M1_RESERVED: PCIX M1 reserved mode. + * @XGE_HAL_PCIX_M1_66MHZ_NS: PCIX M1 66MHZ mode not supported. + * @XGE_HAL_PCIX_M1_100MHZ_NS: PCIX M1 100MHZ mode not supported. + * @XGE_HAL_PCIX_M1_133MHZ_NS: PCIX M1 133MHZ not supported. + * @XGE_HAL_PCIX_M2_RESERVED: PCIX M2 reserved. + * @XGE_HAL_PCIX_533_RESERVED: PCIX 533 reserved. + * @XGE_HAL_PCI_BASIC_MODE: PCI basic mode, XENA specific value. + * @XGE_HAL_PCIX_BASIC_MODE: PCIX basic mode, XENA specific value. + * @XGE_HAL_PCI_INVALID_MODE: Invalid PCI or PCIX mode. + * + */ +typedef enum xge_hal_pci_mode_e { + XGE_HAL_PCI_33MHZ_MODE = 0x0, + XGE_HAL_PCI_66MHZ_MODE = 0x1, + XGE_HAL_PCIX_M1_66MHZ_MODE = 0x2, + XGE_HAL_PCIX_M1_100MHZ_MODE = 0x3, + XGE_HAL_PCIX_M1_133MHZ_MODE = 0x4, + XGE_HAL_PCIX_M2_66MHZ_MODE = 0x5, + XGE_HAL_PCIX_M2_100MHZ_MODE = 0x6, + XGE_HAL_PCIX_M2_133MHZ_MODE = 0x7, + XGE_HAL_PCIX_M1_RESERVED = 0x8, + XGE_HAL_PCIX_M1_66MHZ_NS = 0xA, + XGE_HAL_PCIX_M1_100MHZ_NS = 0xB, + XGE_HAL_PCIX_M1_133MHZ_NS = 0xC, + XGE_HAL_PCIX_M2_RESERVED = 0xD, + XGE_HAL_PCIX_533_RESERVED = 0xE, + XGE_HAL_PCI_BASIC_MODE = 0x10, + XGE_HAL_PCIX_BASIC_MODE = 0x11, + XGE_HAL_PCI_INVALID_MODE = 0x12, +} xge_hal_pci_mode_e; + +/** + * enum xge_hal_pci_bus_frequency_e - PCI bus frequency enumeration. + * @XGE_HAL_PCI_BUS_FREQUENCY_33MHZ: PCI bus frequency 33MHZ + * @XGE_HAL_PCI_BUS_FREQUENCY_66MHZ: PCI bus frequency 66MHZ + * @XGE_HAL_PCI_BUS_FREQUENCY_100MHZ: PCI bus frequency 100MHZ + * @XGE_HAL_PCI_BUS_FREQUENCY_133MHZ: PCI bus frequency 133MHZ + * @XGE_HAL_PCI_BUS_FREQUENCY_200MHZ: PCI bus frequency 200MHZ + * @XGE_HAL_PCI_BUS_FREQUENCY_250MHZ: PCI bus frequency 250MHZ + * @XGE_HAL_PCI_BUS_FREQUENCY_266MHZ: PCI bus frequency 266MHZ + * @XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN: Unrecognized PCI bus frequency value. + * + */ +typedef enum xge_hal_pci_bus_frequency_e { + XGE_HAL_PCI_BUS_FREQUENCY_33MHZ = 33, + XGE_HAL_PCI_BUS_FREQUENCY_66MHZ = 66, + XGE_HAL_PCI_BUS_FREQUENCY_100MHZ = 100, + XGE_HAL_PCI_BUS_FREQUENCY_133MHZ = 133, + XGE_HAL_PCI_BUS_FREQUENCY_200MHZ = 200, + XGE_HAL_PCI_BUS_FREQUENCY_250MHZ = 250, + XGE_HAL_PCI_BUS_FREQUENCY_266MHZ = 266, + XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN = 0 +} xge_hal_pci_bus_frequency_e; + +/** + * enum xge_hal_pci_bus_width_e - PCI bus width enumeration. + * @XGE_HAL_PCI_BUS_WIDTH_64BIT: 64 bit bus width. + * @XGE_HAL_PCI_BUS_WIDTH_32BIT: 32 bit bus width. + * @XGE_HAL_PCI_BUS_WIDTH_UNKNOWN: unknown bus width. + * + */ +typedef enum xge_hal_pci_bus_width_e { + XGE_HAL_PCI_BUS_WIDTH_64BIT = 0, + XGE_HAL_PCI_BUS_WIDTH_32BIT = 1, + XGE_HAL_PCI_BUS_WIDTH_UNKNOWN = 2, +} xge_hal_pci_bus_width_e; + +#if defined (XGE_HAL_CONFIG_LRO) + +#define IP_TOTAL_LENGTH_OFFSET 2 +#define IP_FAST_PATH_HDR_MASK 0x45 +#define TCP_FAST_PATH_HDR_MASK1 0x50 +#define TCP_FAST_PATH_HDR_MASK2 0x10 +#define TCP_FAST_PATH_HDR_MASK3 0x18 +#define IP_SOURCE_ADDRESS_OFFSET 12 +#define IP_DESTINATION_ADDRESS_OFFSET 16 +#define TCP_DESTINATION_PORT_OFFSET 2 +#define TCP_SOURCE_PORT_OFFSET 0 +#define TCP_DATA_OFFSET_OFFSET 12 +#define TCP_WINDOW_OFFSET 14 +#define TCP_SEQUENCE_NUMBER_OFFSET 4 +#define TCP_ACKNOWLEDGEMENT_NUMBER_OFFSET 8 + +typedef struct tcplro { + u16 source; + u16 dest; + u32 seq; + u32 ack_seq; + u8 doff_res; + u8 ctrl; + u16 window; + u16 check; + u16 urg_ptr; +} tcplro_t; + +typedef struct iplro { + u8 version_ihl; + u8 tos; + u16 tot_len; + u16 id; + u16 frag_off; + u8 ttl; + u8 protocol; + u16 check; + u32 saddr; + u32 daddr; + /*The options start here. */ +} iplro_t; + +/* + * LRO object, one per each LRO session. +*/ +typedef struct lro { + /* non-linear: contains scatter-gather list of + xframe-mapped received buffers */ + OS_NETSTACK_BUF os_buf; + OS_NETSTACK_BUF os_buf_end; + + /* link layer header of the first frame; + remains intack throughout the processing */ + u8 *ll_hdr; + + /* IP header - gets _collapsed_ */ + iplro_t *ip_hdr; + + /* transport header - gets _collapsed_ */ + tcplro_t *tcp_hdr; + + /* Next tcp sequence number */ + u32 tcp_next_seq_num; + /* Current tcp seq & ack */ + u32 tcp_seq_num; + u32 tcp_ack_num; + + /* total number of accumulated (so far) frames */ + int sg_num; + + /* total data length */ + int total_length; + + /* receive side hash value, available from Hercules */ + u32 rth_value; + + /* In use */ + u8 in_use; + + /* Total length of the fragments clubbed with the inital frame */ + u32 frags_len; + + /* LRO frame contains time stamp, if (ts_off != -1) */ + int ts_off; + +} lro_t; +#endif + +/* + * xge_hal_spdm_entry_t + * + * Represents a single spdm entry in the SPDM table. + */ +typedef struct xge_hal_spdm_entry_t { + xge_hal_ipaddr_t src_ip; + xge_hal_ipaddr_t dst_ip; + u32 jhash_value; + u16 l4_sp; + u16 l4_dp; + u16 spdm_entry; + u8 in_use; + u8 is_tcp; + u8 is_ipv4; + u8 tgt_queue; +} xge_hal_spdm_entry_t; + +#if defined(XGE_HAL_CONFIG_LRO) +typedef struct { + lro_t lro_pool[XGE_HAL_LRO_MAX_BUCKETS]; + int lro_next_idx; + lro_t *lro_recent; +} xge_hal_lro_desc_t; +#endif +/* + * xge_hal_vpd_data_t + * + * Represents vpd capabilty structure + */ +typedef struct xge_hal_vpd_data_t { + u8 product_name[XGE_HAL_VPD_LENGTH]; + u8 serial_num[XGE_HAL_VPD_LENGTH]; +} xge_hal_vpd_data_t; + +/* + * xge_hal_device_t + * + * HAL device object. Represents Xframe. + */ +typedef struct { + unsigned int magic; + pci_reg_h regh0; + pci_reg_h regh1; + pci_reg_h regh2; + char *bar0; + char *isrbar0; + char *bar1; + char *bar2; + pci_irq_h irqh; + pci_cfg_h cfgh; + pci_dev_h pdev; + xge_hal_pci_config_t pci_config_space; + xge_hal_pci_config_t pci_config_space_bios; + xge_hal_device_config_t config; + xge_list_t free_channels; + xge_list_t fifo_channels; + xge_list_t ring_channels; +#ifdef XGEHAL_RNIC + __hal_bitmap_entry_t bitmap_table[XGE_HAL_MAX_BITMAP_BITS]; + __hal_virtualpath_t virtual_paths[XGE_HAL_MAX_VIRTUAL_PATHS]; + __hal_blockpool_t block_pool; + __hal_regpool_t reg_pool; +#endif + volatile int is_initialized; + volatile int terminating; + xge_hal_stats_t stats; + macaddr_t macaddr[1]; + xge_queue_h queueh; + volatile int mcast_refcnt; + int is_promisc; + volatile xge_hal_device_link_state_e link_state; + void *upper_layer_info; + xge_hal_device_attr_t orig_attr; + u16 device_id; + u8 revision; + int msi_enabled; + int hw_is_initialized; + u64 inject_serr; + u64 inject_ecc; + u8 inject_bad_tcode; + int inject_bad_tcode_for_chan_type; + int reset_needed_after_close; + int tti_enabled; + xge_hal_tti_config_t bimodal_tti[XGE_HAL_MAX_RING_NUM]; + int bimodal_timer_val_us; + int bimodal_urange_a_en; + int bimodal_intr_cnt; + char *spdm_mem_base; + u16 spdm_max_entries; + xge_hal_spdm_entry_t **spdm_table; + spinlock_t spdm_lock; + u32 msi_mask; +#if defined(XGE_HAL_CONFIG_LRO) + xge_hal_lro_desc_t lro_desc[XGE_HAL_MAX_RING_NUM]; +#endif + spinlock_t xena_post_lock; + + /* bimodal workload stats */ + int irq_workload_rxd[XGE_HAL_MAX_RING_NUM]; + int irq_workload_rxcnt[XGE_HAL_MAX_RING_NUM]; + int irq_workload_rxlen[XGE_HAL_MAX_RING_NUM]; + int irq_workload_txd[XGE_HAL_MAX_FIFO_NUM]; + int irq_workload_txcnt[XGE_HAL_MAX_FIFO_NUM]; + int irq_workload_txlen[XGE_HAL_MAX_FIFO_NUM]; + + int mtu_first_time_set; + u64 rxufca_lbolt; + u64 rxufca_lbolt_time; + u64 rxufca_intr_thres; + char* dump_buf; + xge_hal_pci_mode_e pci_mode; + xge_hal_pci_bus_frequency_e bus_frequency; + xge_hal_pci_bus_width_e bus_width; + xge_hal_vpd_data_t vpd_data; + volatile int in_poll; + u64 msix_vector_table[XGE_HAL_MAX_MSIX_MESSAGES_WITH_ADDR]; +} xge_hal_device_t; + + +/* ========================== PRIVATE API ================================= */ + +void +__hal_device_event_queued(void *data, int event_type); + +xge_hal_status_e +__hal_device_set_swapper(xge_hal_device_t *hldev); + +xge_hal_status_e +__hal_device_rth_it_configure(xge_hal_device_t *hldev); + +xge_hal_status_e +__hal_device_rth_spdm_configure(xge_hal_device_t *hldev); + +xge_hal_status_e +__hal_verify_pcc_idle(xge_hal_device_t *hldev, u64 adp_status); + +xge_hal_status_e +__hal_device_handle_pic(xge_hal_device_t *hldev, u64 reason); + +xge_hal_status_e +__hal_read_spdm_entry_line(xge_hal_device_t *hldev, u8 spdm_line, + u16 spdm_entry, u64 *spdm_line_val); + +void __hal_pio_mem_write32_upper(pci_dev_h pdev, pci_reg_h regh, u32 val, + void *addr); + +void __hal_pio_mem_write32_lower(pci_dev_h pdev, pci_reg_h regh, u32 val, + void *addr); +void __hal_device_get_vpd_data(xge_hal_device_t *hldev); + +xge_hal_status_e +__hal_device_handle_txpic(xge_hal_device_t *hldev, u64 reason); + +xge_hal_status_e +__hal_device_handle_txdma(xge_hal_device_t *hldev, u64 reason); + +xge_hal_status_e +__hal_device_handle_txmac(xge_hal_device_t *hldev, u64 reason); + +xge_hal_status_e +__hal_device_handle_txxgxs(xge_hal_device_t *hldev, u64 reason); + +xge_hal_status_e +__hal_device_handle_rxpic(xge_hal_device_t *hldev, u64 reason); + +xge_hal_status_e +__hal_device_handle_rxdma(xge_hal_device_t *hldev, u64 reason); + +xge_hal_status_e +__hal_device_handle_rxmac(xge_hal_device_t *hldev, u64 reason); + +xge_hal_status_e +__hal_device_handle_rxxgxs(xge_hal_device_t *hldev, u64 reason); + +xge_hal_status_e +__hal_device_handle_mc(xge_hal_device_t *hldev, u64 reason); + +xge_hal_status_e +__hal_device_register_poll(xge_hal_device_t *hldev, u64 *reg, int op, u64 mask, + int max_millis); +xge_hal_status_e +__hal_device_rts_mac_configure(xge_hal_device_t *hldev); + +xge_hal_status_e +__hal_device_rts_qos_configure(xge_hal_device_t *hldev); + +xge_hal_status_e +__hal_device_rts_port_configure(xge_hal_device_t *hldev); + +xge_hal_status_e +__hal_device_rti_configure(xge_hal_device_t *hldev, int runtime); + +void +__hal_device_msi_intr_endis(xge_hal_device_t *hldev, int flag); + +void +__hal_device_msix_intr_endis(xge_hal_device_t *hldev, + xge_hal_channel_t *channel, int flag); + +/* =========================== PUBLIC API ================================= */ + +unsigned int +__hal_fix_time_ival_herc(xge_hal_device_t *hldev, + unsigned int time_ival); +xge_hal_status_e +xge_hal_rts_rth_itable_set(xge_hal_device_t *hldev, u8 *itable, + u32 itable_size); + +void +xge_hal_rts_rth_set(xge_hal_device_t *hldev, u8 def_q, u64 hash_type, + u16 bucket_size); + +void +xge_hal_rts_rth_init(xge_hal_device_t *hldev); + +void +xge_hal_rts_rth_clr(xge_hal_device_t *hldev); + +void +xge_hal_rts_rth_start(xge_hal_device_t *hldev); + +void +xge_hal_rts_rth_stop(xge_hal_device_t *hldev); + +void +xge_hal_device_rts_rth_key_set(xge_hal_device_t *hldev, u8 KeySize, u8 *Key); + +xge_hal_status_e +xge_hal_device_rts_mac_enable(xge_hal_device_h devh, int index, macaddr_t macaddr); + +xge_hal_status_e +xge_hal_device_rts_mac_disable(xge_hal_device_h devh, int index); + +int xge_hal_reinitialize_hw(xge_hal_device_t * hldev); + +/** + * xge_hal_device_rti_reconfigure + * @hldev: Hal Device + */ +static inline xge_hal_status_e +xge_hal_device_rti_reconfigure(xge_hal_device_t *hldev) +{ + return __hal_device_rti_configure(hldev, 1); +} + +/** + * xge_hal_device_rts_port_reconfigure + * @hldev: Hal Device + */ +static inline xge_hal_status_e +xge_hal_device_rts_port_reconfigure(xge_hal_device_t *hldev) +{ + return __hal_device_rts_port_configure(hldev); +} + +/** + * xge_hal_device_is_initialized - Returns 0 if device is not + * initialized, non-zero otherwise. + * @devh: HAL device handle. + * + * Returns 0 if device is not initialized, non-zero otherwise. + */ +static inline int +xge_hal_device_is_initialized(xge_hal_device_h devh) +{ + return ((xge_hal_device_t*)devh)->is_initialized; +} + + +/** + * xge_hal_device_in_poll - non-zero, if xge_hal_device_poll() is executing. + * @devh: HAL device handle. + * + * Returns non-zero if xge_hal_device_poll() is executing, and 0 - otherwise. + */ +static inline int +xge_hal_device_in_poll(xge_hal_device_h devh) +{ + return ((xge_hal_device_t*)devh)->in_poll; +} + + +/** + * xge_hal_device_inject_ecc - Inject ECC error. + * @devh: HAL device, pointer to xge_hal_device_t structure. + * @err_reg: Contains the error register. + * + * This function is used to inject ECC error into the driver flow. + * This facility can be used to test the driver flow in the + * case of ECC error is reported by the firmware. + * + * Returns: void + * See also: xge_hal_device_inject_serr(), + * xge_hal_device_inject_bad_tcode() + */ +static inline void +xge_hal_device_inject_ecc(xge_hal_device_h devh, u64 err_reg) +{ + ((xge_hal_device_t*)devh)->inject_ecc = err_reg; +} + + +/** + * xge_hal_device_inject_serr - Inject SERR error. + * @devh: HAL device, pointer to xge_hal_device_t structure. + * @err_reg: Contains the error register. + * + * This function is used to inject SERR error into the driver flow. + * This facility can be used to test the driver flow in the + * case of SERR error is reported by firmware. + * + * Returns: void + * See also: xge_hal_device_inject_ecc(), + * xge_hal_device_inject_bad_tcode() + */ +static inline void +xge_hal_device_inject_serr(xge_hal_device_h devh, u64 err_reg) +{ + ((xge_hal_device_t*)devh)->inject_serr = err_reg; +} + + +/** + * xge_hal_device_inject_bad_tcode - Inject Bad transfer code. + * @devh: HAL device, pointer to xge_hal_device_t structure. + * @chan_type: Channel type (fifo/ring). + * @t_code: Transfer code. + * + * This function is used to inject bad (Tx/Rx Data)transfer code + * into the driver flow. + * + * This facility can be used to test the driver flow in the + * case of bad transfer code reported by firmware for a Tx/Rx data + * transfer. + * + * Returns: void + * See also: xge_hal_device_inject_ecc(), xge_hal_device_inject_serr() + */ +static inline void +xge_hal_device_inject_bad_tcode(xge_hal_device_h devh, int chan_type, u8 t_code) +{ + ((xge_hal_device_t*)devh)->inject_bad_tcode_for_chan_type = chan_type; + ((xge_hal_device_t*)devh)->inject_bad_tcode = t_code; +} + +void xge_hal_device_msi_enable(xge_hal_device_h devh); + +/* + * xge_hal_device_msi_mode - Is MSI enabled? + * @devh: HAL device handle. + * + * Returns 0 if MSI is enabled for the specified device, + * non-zero otherwise. + */ +static inline int +xge_hal_device_msi_mode(xge_hal_device_h devh) +{ + return ((xge_hal_device_t*)devh)->msi_enabled; +} + +/** + * xge_hal_device_queue - Get per-device event queue. + * @devh: HAL device handle. + * + * Returns: event queue associated with the specified HAL device. + */ +static inline xge_queue_h +xge_hal_device_queue (xge_hal_device_h devh) +{ + return ((xge_hal_device_t*)devh)->queueh; +} + +/** + * xge_hal_device_attr - Get original (user-specified) device + * attributes. + * @devh: HAL device handle. + * + * Returns: original (user-specified) device attributes. + */ +static inline xge_hal_device_attr_t* +xge_hal_device_attr(xge_hal_device_h devh) +{ + return &((xge_hal_device_t*)devh)->orig_attr; +} + +/** + * xge_hal_device_private_set - Set ULD context. + * @devh: HAL device handle. + * @data: pointer to ULD context + * + * Use HAL device to set upper-layer driver (ULD) context. + * + * See also: xge_hal_device_from_private(), xge_hal_device_private() + */ +static inline void +xge_hal_device_private_set(xge_hal_device_h devh, void *data) +{ + ((xge_hal_device_t*)devh)->upper_layer_info = data; +} + +/** + * xge_hal_device_private - Get ULD context. + * @devh: HAL device handle. + * + * Use HAL device to get upper-layer driver (ULD) context. + * + * Returns: ULD context. + * + * See also: xge_hal_device_from_private(), xge_hal_device_private_set() + */ +static inline void* +xge_hal_device_private(xge_hal_device_h devh) +{ + return ((xge_hal_device_t*)devh)->upper_layer_info; +} + +/** + * xge_hal_device_from_private - Get HAL device object from private. + * @info_ptr: ULD context. + * + * Use ULD context to get HAL device. + * + * Returns: Device handle. + * + * See also: xge_hal_device_private(), xge_hal_device_private_set() + */ +static inline xge_hal_device_h +xge_hal_device_from_private(void *info_ptr) +{ + return xge_container_of((void ** ) info_ptr, xge_hal_device_t, + upper_layer_info); +} + +/** + * xge_hal_device_mtu_check - check MTU value for ranges + * @hldev: the device + * @new_mtu: new MTU value to check + * + * Will do sanity check for new MTU value. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_MTU_SIZE - MTU is invalid. + * + * See also: xge_hal_device_mtu_set() + */ +static inline xge_hal_status_e +xge_hal_device_mtu_check(xge_hal_device_t *hldev, int new_mtu) +{ + if ((new_mtu < XGE_HAL_MIN_MTU) || (new_mtu > XGE_HAL_MAX_MTU)) { + return XGE_HAL_ERR_INVALID_MTU_SIZE; + } + + return XGE_HAL_OK; +} + +void xge_hal_device_bcast_enable(xge_hal_device_h devh); + +void xge_hal_device_bcast_disable(xge_hal_device_h devh); + +void xge_hal_device_terminating(xge_hal_device_h devh); + +xge_hal_status_e xge_hal_device_initialize(xge_hal_device_t *hldev, + xge_hal_device_attr_t *attr, xge_hal_device_config_t *config); + +void xge_hal_device_terminate(xge_hal_device_t *hldev); + +xge_hal_status_e xge_hal_device_reset(xge_hal_device_t *hldev); + +xge_hal_status_e xge_hal_device_macaddr_get(xge_hal_device_t *hldev, + int index, macaddr_t *macaddr); + +xge_hal_status_e xge_hal_device_macaddr_set(xge_hal_device_t *hldev, + int index, macaddr_t macaddr); + +xge_hal_status_e xge_hal_device_macaddr_clear(xge_hal_device_t *hldev, + int index); + +int xge_hal_device_macaddr_find(xge_hal_device_t *hldev, macaddr_t wanted); + +xge_hal_status_e xge_hal_device_mtu_set(xge_hal_device_t *hldev, int new_mtu); + +xge_hal_status_e xge_hal_device_status(xge_hal_device_t *hldev, u64 *hw_status); + +void xge_hal_device_intr_enable(xge_hal_device_t *hldev); + +void xge_hal_device_intr_disable(xge_hal_device_t *hldev); + +xge_hal_status_e xge_hal_device_mcast_enable(xge_hal_device_t *hldev); + +xge_hal_status_e xge_hal_device_mcast_disable(xge_hal_device_t *hldev); + +void xge_hal_device_promisc_enable(xge_hal_device_t *hldev); + +void xge_hal_device_promisc_disable(xge_hal_device_t *hldev); + +xge_hal_status_e xge_hal_device_disable(xge_hal_device_t *hldev); + +xge_hal_status_e xge_hal_device_enable(xge_hal_device_t *hldev); + +xge_hal_status_e xge_hal_device_handle_tcode(xge_hal_channel_h channelh, + xge_hal_dtr_h dtrh, + u8 t_code); + +xge_hal_status_e xge_hal_device_link_state(xge_hal_device_h devh, + xge_hal_device_link_state_e *ls); + +void xge_hal_device_sched_timer(xge_hal_device_h devh, int interval_us, + int one_shot); + +void xge_hal_device_poll(xge_hal_device_h devh); + +xge_hal_card_e xge_hal_device_check_id(xge_hal_device_h devh); + +int xge_hal_device_is_slot_freeze(xge_hal_device_h devh); + +xge_hal_status_e +xge_hal_device_pci_info_get(xge_hal_device_h devh, xge_hal_pci_mode_e *pci_mode, + xge_hal_pci_bus_frequency_e *bus_frequency, + xge_hal_pci_bus_width_e *bus_width); + +xge_hal_status_e +xge_hal_spdm_entry_add(xge_hal_device_h devh, xge_hal_ipaddr_t *src_ip, + xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp, + u8 is_tcp, u8 is_ipv4, u8 tgt_queue); + +xge_hal_status_e +xge_hal_spdm_entry_remove(xge_hal_device_h devh, xge_hal_ipaddr_t *src_ip, + xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp, + u8 is_tcp, u8 is_ipv4); + +xge_hal_status_e +xge_hal_device_rts_section_enable(xge_hal_device_h devh, int index); + +int +xge_hal_device_is_closed (xge_hal_device_h devh); + +/* private functions, don't use them in ULD */ + +void __hal_serial_mem_write64(xge_hal_device_t *hldev, u64 value, u64 *reg); + +u64 __hal_serial_mem_read64(xge_hal_device_t *hldev, u64 *reg); + + +/* Some function protoypes for MSI implementation. */ +xge_hal_status_e +xge_hal_channel_msi_set (xge_hal_channel_h channelh, int msi, + u32 msg_val); +void +xge_hal_mask_msi(xge_hal_device_t *hldev); + +void +xge_hal_unmask_msi(xge_hal_channel_h channelh); + +xge_hal_status_e +xge_hal_channel_msix_set(xge_hal_channel_h channelh, int msix_idx); + +xge_hal_status_e +xge_hal_mask_msix(xge_hal_device_h devh, int msi_id); + +xge_hal_status_e +xge_hal_unmask_msix(xge_hal_device_h devh, int msi_id); + +#if defined(XGE_HAL_CONFIG_LRO) +xge_hal_status_e +xge_hal_lro_init(u32 lro_scale, xge_hal_device_t *hldev); +#endif + +#if defined(XGE_DEBUG_FP) && (XGE_DEBUG_FP & XGE_DEBUG_FP_DEVICE) +#define __HAL_STATIC_DEVICE +#define __HAL_INLINE_DEVICE + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE int +xge_hal_device_rev(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_begin_irq(xge_hal_device_t *hldev, u64 *reason); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_clear_rx(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_clear_tx(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_continue_irq(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_handle_irq(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE char * +xge_hal_device_bar0(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE char * +xge_hal_device_isrbar0(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE char * +xge_hal_device_bar1(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_bar0_set(xge_hal_device_t *hldev, char *bar0); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_isrbar0_set(xge_hal_device_t *hldev, char *isrbar0); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_bar1_set(xge_hal_device_t *hldev, xge_hal_channel_h channelh, + char *bar1); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_mask_tx(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_mask_rx(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_mask_all(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_unmask_tx(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_unmask_rx(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_unmask_all(xge_hal_device_t *hldev); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_poll_tx_channels(xge_hal_device_t *hldev, int *got_tx); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_poll_rx_channels(xge_hal_device_t *hldev, int *got_rx); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_poll_rx_channel(xge_hal_channel_t *channel, int *got_rx); + +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_poll_tx_channel(xge_hal_channel_t *channel, int *got_tx); + +#if defined (XGE_HAL_CONFIG_LRO) +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL u8 +__hal_header_parse_token_u8(u8 *string,u16 offset); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL u16 +__hal_header_parse_token_u16(u8 *string,u16 offset); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL u32 +__hal_header_parse_token_u32(u8 *string,u16 offset); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_header_update_u8(u8 *string, u16 offset, u8 val); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_header_update_u16(u8 *string, u16 offset, u16 val); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_header_update_u32(u8 *string, u16 offset, u32 val); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL u16 +__hal_tcp_seg_len(iplro_t *ip, tcplro_t *tcp); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_ip_lro_capable(iplro_t *ip, xge_hal_dtr_info_t *ext_info); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_tcp_lro_capable(iplro_t *ip, tcplro_t *tcp, lro_t *lro, int *ts_off); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_lro_capable(u8 *buffer, iplro_t **ip, tcplro_t **tcp, + xge_hal_dtr_info_t *ext_info); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_get_lro_session(u8 *eth_hdr, iplro_t *ip, tcplro_t *tcp, lro_t **lro, + xge_hal_dtr_info_t *ext_info, xge_hal_device_t *hldev, + xge_hal_lro_desc_t *ring_lro, lro_t **lro_end3); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_lro_under_optimal_thresh(iplro_t *ip, tcplro_t *tcp, lro_t *lro, + xge_hal_device_t *hldev); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_collapse_ip_hdr(iplro_t *ip, tcplro_t *tcp, lro_t *lro, + xge_hal_device_t *hldev); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_collapse_tcp_hdr(iplro_t *ip, tcplro_t *tcp, lro_t *lro, + xge_hal_device_t *hldev); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_append_lro(iplro_t *ip, tcplro_t **tcp, u32 *seg_len, lro_t *lro, + xge_hal_device_t *hldev); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +xge_hal_lro_process_rx(int ring, u8 *eth_hdr, u8 *ip_hdr, tcplro_t **tcp, + u32 *seglen, lro_t **p_lro, + xge_hal_dtr_info_t *ext_info, xge_hal_device_t *hldev, + lro_t **lro_end3); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +xge_hal_accumulate_large_rx(u8 *buffer, tcplro_t **tcp, u32 *seglen, + lro_t **lro, xge_hal_dtr_info_t *ext_info, + xge_hal_device_t *hldev, lro_t **lro_end3); + +void +xge_hal_lro_terminate(u32 lro_scale, xge_hal_device_t *hldev); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL lro_t * +xge_hal_lro_next_session (xge_hal_device_t *hldev, int ring); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL lro_t * +xge_hal_lro_get_next_session(xge_hal_device_t *hldev); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_open_lro_session (u8 *buffer, iplro_t *ip, tcplro_t *tcp, lro_t **lro, + xge_hal_device_t *hldev, xge_hal_lro_desc_t *ring_lro, + int slot, u32 tcp_seg_len, int ts_off); + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int +__hal_lro_get_free_slot (xge_hal_lro_desc_t *ring_lro); +#endif + +#else /* XGE_FASTPATH_EXTERN */ +#define __HAL_STATIC_DEVICE static +#define __HAL_INLINE_DEVICE inline +#include <dev/nxge/xgehal/xgehal-device-fp.c> +#endif /* XGE_FASTPATH_INLINE */ + + +__EXTERN_END_DECLS + +#endif /* XGE_HAL_DEVICE_H */ diff --git a/sys/dev/nxge/include/xgehal-driver.h b/sys/dev/nxge/include/xgehal-driver.h new file mode 100644 index 0000000..e669368 --- /dev/null +++ b/sys/dev/nxge/include/xgehal-driver.h @@ -0,0 +1,322 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-driver.h + * + * Description: HAL driver object functionality + * + * Created: 14 May 2004 + */ + +#ifndef XGE_HAL_DRIVER_H +#define XGE_HAL_DRIVER_H + +#include <dev/nxge/include/xge-os-pal.h> +#include <dev/nxge/include/xge-list.h> +#include <dev/nxge/include/xge-queue.h> +#include <dev/nxge/include/xgehal-types.h> +#include <dev/nxge/include/xgehal-config.h> +#include <dev/nxge/include/xgehal-event.h> + +__EXTERN_BEGIN_DECLS + +/* maximum number of events consumed in a syncle poll() cycle */ +#define XGE_HAL_DRIVER_QUEUE_CONSUME_MAX 5 + + +/** + * function xge_uld_sched_timer_cb_f - Per-device periodic timer + * callback. + * @devh: HAL device handle. + * @userdata: Per-device user data (a.k.a. context) specified via + * xge_hal_device_initialize(). + * + * Periodic or one-shot timer callback. If specified (that is, not NULL) + * HAL invokes this callback periodically. The call is performed in the + * interrupt context, or more exactly, in the context of HAL's ISR + * xge_hal_device_continue_irq(). + * + * See also: xge_hal_device_initialize{} + */ +typedef void (*xge_uld_sched_timer_cb_f)(xge_hal_device_h devh, void *userdata); + +/** + * function xge_uld_link_up_f - Link-Up callback provided by upper-layer + * driver. + * @userdata: Opaque context set by the ULD via + * xge_hal_device_private_set() + * (typically - at HAL device iinitialization time). + * + * Link-up notification callback provided by the ULD. + * This is one of the per-driver callbacks, see xge_hal_uld_cbs_t{}. + * + * See also: xge_hal_uld_cbs_t{}, xge_uld_link_down_f{}, + * xge_hal_driver_initialize(), xge_hal_device_private_set(). + */ +typedef void (*xge_uld_link_up_f) (void *userdata); + +/** + * function xge_uld_link_down_f - Link-Down callback provided by + * upper-layer driver. + * @userdata: Opaque context set by the ULD via + * xge_hal_device_private_set() + * (typically - at HAL device iinitialization time). + * + * Link-Down notification callback provided by the upper-layer driver. + * This is one of the per-driver callbacks, see xge_hal_uld_cbs_t{}. + * + * See also: xge_hal_uld_cbs_t{}, xge_uld_link_up_f{}, + * xge_hal_driver_initialize(), xge_hal_device_private_set(). + */ +typedef void (*xge_uld_link_down_f) (void *userdata); + +/** + * function xge_uld_crit_err_f - Critical Error notification callback. + * @userdata: Opaque context set by the ULD via + * xge_hal_device_private_set() + * (typically - at HAL device iinitialization time). + * @type: Enumerated hw error, e.g.: double ECC. + * @serr_data: Xframe status. + * @ext_data: Extended data. The contents depends on the @type. + * + * Link-Down notification callback provided by the upper-layer driver. + * This is one of the per-driver callbacks, see xge_hal_uld_cbs_t{}. + * + * See also: xge_hal_uld_cbs_t{}, xge_hal_event_e{}, + * xge_hal_device_private_set(), xge_hal_driver_initialize(). + */ +typedef void (*xge_uld_crit_err_f) (void *userdata, xge_hal_event_e type, + u64 ext_data); + +/** + * function xge_uld_event_queued_f - Event-enqueued notification + * callback. + * @devh: HAL device handle. + * @event_type: HAL- or ULD-defined event type. Note that HAL + * events are enumerated by xge_hal_event_e{}. + * + * "Event-was-enqueued" notification callback provided by the upper-layer + * driver. The callback is invoked (if defined, i.e., not NULL in the + * xge_hal_uld_cbs_t{} structure) each time immediately after an event + * is enqueued. + * + * See also: xge_hal_uld_cbs_t{}, xge_hal_device_private_set(), + * xge_hal_driver_initialize(). + */ +typedef void (*xge_uld_event_queued_f) (xge_hal_device_h devh, int event_type); + +/** + * function xge_uld_event_f - ULD event callback. + * @item: ULD-defined event, item of the xge_queue_t. + * + * ULD event callback. + * Upper-layer driver can use HAL queue to serialize certain slow-path + * events. HAL periodically polls the queue as part of the + * xge_hal_device_poll() processing. When/if HAL discovers in the queue + * an unkown event type it simply invokes the event callback + * (which must be non-NULL and supplied by the ULD in this case). + * + * See also: xge_hal_uld_cbs_t{}, xge_hal_device_poll(), xge_queue_t{}, + * xge_hal_driver_initialize(), xge_queue_item_t{}. + */ +typedef void (*xge_uld_event_f) (xge_queue_item_t *item); + +/** + * function xge_uld_before_device_poll_f - ULD "before-poll" callback. + * @devh: HAL device handle. + * + * HAL invokes the callback from inside its xge_hal_device_poll() + * implementation %prior to accessing the @devh device. This allows ULD to + * perform per-device locking and/or context mapping, if required.. + * The interface is currently used by AIX driver only. + * To avoid using/implementing the callback set the corresponding field + * in the xge_hal_uld_cbs_t{} structure to NULL. + * + * Returns: 0 on success, non-zero on failure. + * + * See also: xge_hal_driver_initialize(), xge_hal_uld_cbs_t{}, + * xge_hal_device_poll(). + */ +typedef int (*xge_uld_before_device_poll_f) (xge_hal_device_h devh); + +/** + * function xge_uld_after_device_poll_f - ULD "after-poll" callback. + * @devh: HAL device handle. + * + * Unless NULL is specified, + * HAL invokes the callback from inside its xge_hal_device_poll() + * implementation immediately %after it has completed polling the @devh + * device. This allows ULD to undo the affects of + * xge_uld_before_device_poll_f{}. + * The interface is currently used by AIX driver only. + * + * See also: xge_hal_driver_initialize(), xge_hal_uld_cbs_t{}, + * xge_hal_device_poll(). + */ +typedef void (*xge_uld_after_device_poll_f) (xge_hal_device_h devh); + +/** + * function xge_uld_xpak_alarm_log_f - ULD "XPAK alarm log" callback. + * @devh: HAL device handle. + * @type: TODO + * + * Unless NULL is specified, + * HAL invokes the callback from inside __hal_chk_xpak_counter() + */ +typedef void (*xge_uld_xpak_alarm_log_f) (xge_hal_device_h devh, xge_hal_xpak_alarm_type_e type); + +/** + * struct xge_hal_uld_cbs_t - Upper-layer driver "slow-path" callbacks. + * @link_up: See xge_uld_link_up_f{}. + * @link_down: See xge_uld_link_down_f{}. + * @crit_err: See xge_uld_crit_err_f{}. + * @event: See xge_uld_event_f{}. + * @event_queued: See xge_uld_event_queued_f{}. + * @before_device_poll: See xge_uld_before_device_poll_f{}. + * @after_device_poll: See xge_uld_after_device_poll_f{}. + * @sched_timer: See xge_uld_sched_timer_cb_f{}. + * @xpak_alarm_log: TODO + * + * Upper layer driver slow-path (per-driver) callbacks. + * Implemented by ULD and provided to HAL via + * xge_hal_driver_initialize(). + * Note that these callbacks are not mandatory: HAL will not invoke + * a callback if NULL is specified. + * + * Note that in addition to those, there are curently 2 per-channel callbacks + * (completion and abort) specified at channel open time + * via xge_hal_channel_open(). + * + * See also: xge_hal_driver_initialize(). + */ +typedef struct xge_hal_uld_cbs_t { + xge_uld_link_up_f link_up; + xge_uld_link_down_f link_down; + xge_uld_crit_err_f crit_err; + xge_uld_event_f event; + xge_uld_event_queued_f event_queued; + xge_uld_before_device_poll_f before_device_poll; + xge_uld_after_device_poll_f after_device_poll; + xge_uld_sched_timer_cb_f sched_timer; + xge_uld_xpak_alarm_log_f xpak_alarm_log; +} xge_hal_uld_cbs_t; + +/** + * struct xge_hal_driver_t - Represents HAL object. + * @config: HAL configuration. + * @devices: List of all PCI-enumerated Xframe devices in the system. + * A single xge_hal_driver_t instance contains zero or more + * Xframe devices. + * @devices_lock: Lock to protect %devices when inserting/removing. + * @is_initialized: True if HAL is initialized; false otherwise. + * @uld_callbacks: Upper-layer driver callbacks. See xge_hal_uld_cbs_t{}. + * @debug_module_mask: 32bit mask that defines which components of the + * driver are to be traced. The trace-able components are: + * XGE_COMPONENT_HAL_CONFIG 0x1 + * XGE_COMPONENT_HAL_FIFO 0x2 + * XGE_COMPONENT_HAL_RING 0x4 + * XGE_COMPONENT_HAL_CHANNEL 0x8 + * XGE_COMPONENT_HAL_DEVICE 0x10 + * XGE_COMPONENT_HAL_MM 0x20 + * XGE_COMPONENT_HAL_QUEUE 0x40 + * XGE_COMPONENT_HAL_STATS 0x100 + * XGE_COMPONENT_OSDEP 0x1000 + * XGE_COMPONENT_LL 0x2000 + * XGE_COMPONENT_TOE 0x4000 + * XGE_COMPONENT_RDMA 0x8000 + * XGE_COMPONENT_ALL 0xffffffff + * The @debug_module_mask allows to switch off and on tracing at runtime. + * In addition, the traces for the same trace-able components can be + * compiled out, based on the same mask provided via Makefile. + * @debug_level: See xge_debug_level_e{}. + * + * HAL (driver) object. There is a single instance of this structure per HAL. + */ +typedef struct xge_hal_driver_t { + xge_hal_driver_config_t config; + int is_initialized; + xge_hal_uld_cbs_t uld_callbacks; + u32 debug_module_mask; + int debug_level; +} xge_hal_driver_t; + +extern xge_hal_driver_t *g_xge_hal_driver; + +static inline int +xge_hal_driver_is_initialized(void) { + return g_xge_hal_driver->is_initialized; +} + +static inline int +xge_hal_driver_debug_module_mask(void) +{ + return g_xge_hal_driver->debug_module_mask; +} + +static inline void +xge_hal_driver_debug_module_mask_set(u32 new_mask) +{ +#if (defined(XGE_DEBUG_TRACE_MASK) && XGE_DEBUG_TRACE_MASK > 0) || \ + (defined(XGE_DEBUG_ERR_MASK) && XGE_DEBUG_ERR_MASK > 0) + g_xge_hal_driver->debug_module_mask = new_mask; + g_module_mask = (unsigned long *)&g_xge_hal_driver->debug_module_mask; +#endif +} + +static inline int +xge_hal_driver_debug_level(void) { return g_xge_hal_driver->debug_level; } + +static inline void +xge_hal_driver_debug_level_set(int new_level) +{ +#if (defined(XGE_DEBUG_TRACE_MASK) && XGE_DEBUG_TRACE_MASK > 0) || \ + (defined(XGE_DEBUG_ERR_MASK) && XGE_DEBUG_ERR_MASK > 0) + g_xge_hal_driver->debug_level = new_level; + g_level = &g_xge_hal_driver->debug_level; +#endif +} + +xge_hal_status_e xge_hal_driver_initialize(xge_hal_driver_config_t *config, + xge_hal_uld_cbs_t *uld_callbacks); + +void xge_hal_driver_terminate(void); + +#ifdef XGE_TRACE_INTO_CIRCULAR_ARR +void xge_hal_driver_tracebuf_dump(void); + +xge_hal_status_e +xge_hal_driver_tracebuf_read(int bufsize, char *retbuf, int *retsize); +#else +#define xge_hal_driver_tracebuf_dump() +#define xge_hal_driver_tracebuf_read(a, b, c) (0); +#endif + +__EXTERN_END_DECLS + +#endif /* XGE_HAL_DRIVER_H */ diff --git a/sys/dev/nxge/include/xgehal-event.h b/sys/dev/nxge/include/xgehal-event.h new file mode 100644 index 0000000..7d560d2 --- /dev/null +++ b/sys/dev/nxge/include/xgehal-event.h @@ -0,0 +1,85 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-event.h + * + * Description: event types + * + * Created: 7 June 2004 + */ + +#ifndef XGE_HAL_EVENT_H +#define XGE_HAL_EVENT_H + +#include <dev/nxge/include/xge-os-pal.h> + +__EXTERN_BEGIN_DECLS + +#define XGE_HAL_EVENT_BASE 0 +#define XGE_LL_EVENT_BASE 100 + +/** + * enum xge_hal_event_e - Enumerates slow-path HAL events. + * @XGE_HAL_EVENT_UNKNOWN: Unknown (and invalid) event. + * @XGE_HAL_EVENT_SERR: Serious hardware error event. + * @XGE_HAL_EVENT_LINK_IS_UP: The link state has changed from 'down' to + * 'up'; upper-layer driver (typically, link layer) is + * supposed to wake the queue, etc. + * @XGE_HAL_EVENT_LINK_IS_DOWN: Link-down event. + * The link state has changed from 'down' to 'up'; + * upper-layer driver is supposed to stop traffic, etc. + * @XGE_HAL_EVENT_ECCERR: ECC error event. + * @XGE_HAL_EVENT_PARITYERR: Parity error event. + * @XGE_HAL_EVENT_TARGETABORT: Target abort event. Used when device + * aborts transmit operation with the corresponding transfer code + * (for T_CODE enum see xgehal-fifo.h and xgehal-ring.h) + * @XGE_HAL_EVENT_SLOT_FREEZE: Slot-freeze event. Driver tries to distinguish + * slot-freeze from the rest critical events (e.g. ECC) when it is + * impossible to PIO read "through" the bus, i.e. when getting all-foxes. + * + * xge_hal_event_e enumerates slow-path HAL eventis. + * + * See also: xge_hal_uld_cbs_t{}, xge_uld_link_up_f{}, + * xge_uld_link_down_f{}. + */ +typedef enum xge_hal_event_e { + XGE_HAL_EVENT_UNKNOWN = 0, + /* HAL events */ + XGE_HAL_EVENT_SERR = XGE_HAL_EVENT_BASE + 1, + XGE_HAL_EVENT_LINK_IS_UP = XGE_HAL_EVENT_BASE + 2, + XGE_HAL_EVENT_LINK_IS_DOWN = XGE_HAL_EVENT_BASE + 3, + XGE_HAL_EVENT_ECCERR = XGE_HAL_EVENT_BASE + 4, + XGE_HAL_EVENT_PARITYERR = XGE_HAL_EVENT_BASE + 5, + XGE_HAL_EVENT_TARGETABORT = XGE_HAL_EVENT_BASE + 6, + XGE_HAL_EVENT_SLOT_FREEZE = XGE_HAL_EVENT_BASE + 7, +} xge_hal_event_e; + +__EXTERN_END_DECLS + +#endif /* XGE_HAL_EVENT_H */ diff --git a/sys/dev/nxge/include/xgehal-fifo.h b/sys/dev/nxge/include/xgehal-fifo.h new file mode 100644 index 0000000..6de6048 --- /dev/null +++ b/sys/dev/nxge/include/xgehal-fifo.h @@ -0,0 +1,363 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-fifo.h + * + * Description: Tx fifo object functionality + * + * Created: 19 May 2004 + */ + +#ifndef XGE_HAL_FIFO_H +#define XGE_HAL_FIFO_H + +#include <dev/nxge/include/xgehal-channel.h> +#include <dev/nxge/include/xgehal-config.h> +#include <dev/nxge/include/xgehal-mm.h> + +__EXTERN_BEGIN_DECLS + +/* HW fifo configuration */ +#define XGE_HAL_FIFO_INT_PER_LIST_THRESHOLD 65 +#define XGE_HAL_FIFO_MAX_WRR 5 +#define XGE_HAL_FIFO_MAX_PARTITION 4 +#define XGE_HAL_FIFO_MAX_WRR_STATE 36 +#define XGE_HAL_FIFO_HW_PAIR_OFFSET 0x20000 + +/* HW FIFO Weight Calender */ +#define XGE_HAL_FIFO_WRR_0 0x0706050407030602ULL +#define XGE_HAL_FIFO_WRR_1 0x0507040601070503ULL +#define XGE_HAL_FIFO_WRR_2 0x0604070205060700ULL +#define XGE_HAL_FIFO_WRR_3 0x0403060705010207ULL +#define XGE_HAL_FIFO_WRR_4 0x0604050300000000ULL +/* + * xge_hal_fifo_hw_pair_t + * + * Represent a single fifo in the BAR1 memory space. + */ +typedef struct { + u64 txdl_pointer; /* offset 0x0 */ + + u64 reserved[2]; + + u64 list_control; /* offset 0x18 */ +#define XGE_HAL_TX_FIFO_LAST_TXD_NUM( val) vBIT(val,0,8) +#define XGE_HAL_TX_FIFO_FIRST_LIST BIT(14) +#define XGE_HAL_TX_FIFO_LAST_LIST BIT(15) +#define XGE_HAL_TX_FIFO_FIRSTNLAST_LIST vBIT(3,14,2) +#define XGE_HAL_TX_FIFO_SPECIAL_FUNC BIT(23) +#define XGE_HAL_TX_FIFO_NO_SNOOP(n) vBIT(n,30,2) +} xge_hal_fifo_hw_pair_t; + + +/* Bad TxDL transfer codes */ +#define XGE_HAL_TXD_T_CODE_OK 0x0 +#define XGE_HAL_TXD_T_CODE_UNUSED_1 0x1 +#define XGE_HAL_TXD_T_CODE_ABORT_BUFFER 0x2 +#define XGE_HAL_TXD_T_CODE_ABORT_DTOR 0x3 +#define XGE_HAL_TXD_T_CODE_UNUSED_5 0x5 +#define XGE_HAL_TXD_T_CODE_PARITY 0x7 +#define XGE_HAL_TXD_T_CODE_LOSS_OF_LINK 0xA +#define XGE_HAL_TXD_T_CODE_GENERAL_ERR 0xF + + +/** + * struct xge_hal_fifo_txd_t - TxD. + * @control_1: Control_1. + * @control_2: Control_2. + * @buffer_pointer: Buffer_Address. + * @host_control: Host_Control.Opaque 64bit data stored by ULD inside the Xframe + * descriptor prior to posting the latter on the channel + * via xge_hal_fifo_dtr_post() or xge_hal_ring_dtr_post(). + * The %host_control is returned as is to the ULD with each + * completed descriptor. + * + * Transmit descriptor (TxD).Fifo descriptor contains configured number + * (list) of TxDs. * For more details please refer to Xframe User Guide, + * Section 5.4.2 "Transmit Descriptor (TxD) Format". + */ +typedef struct xge_hal_fifo_txd_t { + u64 control_1; +#define XGE_HAL_TXD_LIST_OWN_XENA BIT(7) +#define XGE_HAL_TXD_T_CODE (BIT(12)|BIT(13)|BIT(14)|BIT(15)) +#define XGE_HAL_GET_TXD_T_CODE(val) ((val & XGE_HAL_TXD_T_CODE)>>48) +#define XGE_HAL_SET_TXD_T_CODE(x, val) (x |= (((u64)val & 0xF) << 48)) +#define XGE_HAL_TXD_GATHER_CODE (BIT(22) | BIT(23)) +#define XGE_HAL_TXD_GATHER_CODE_FIRST BIT(22) +#define XGE_HAL_TXD_GATHER_CODE_LAST BIT(23) +#define XGE_HAL_TXD_NO_LSO 0 +#define XGE_HAL_TXD_UDF_COF 1 +#define XGE_HAL_TXD_TCP_LSO 2 +#define XGE_HAL_TXD_UDP_LSO 3 +#define XGE_HAL_TXD_LSO_COF_CTRL(val) vBIT(val,30,2) +#define XGE_HAL_TXD_TCP_LSO_MSS(val) vBIT(val,34,14) +#define XGE_HAL_TXD_BUFFER0_SIZE(val) vBIT(val,48,16) +#define XGE_HAL_TXD_GET_LSO_BYTES_SENT(val) ((val & vBIT(0xFFFF,16,16))>>32) + u64 control_2; +#define XGE_HAL_TXD_TX_CKO_CONTROL (BIT(5)|BIT(6)|BIT(7)) +#define XGE_HAL_TXD_TX_CKO_IPV4_EN BIT(5) +#define XGE_HAL_TXD_TX_CKO_TCP_EN BIT(6) +#define XGE_HAL_TXD_TX_CKO_UDP_EN BIT(7) +#define XGE_HAL_TXD_VLAN_ENABLE BIT(15) +#define XGE_HAL_TXD_VLAN_TAG(val) vBIT(val,16,16) +#define XGE_HAL_TXD_INT_NUMBER(val) vBIT(val,34,6) +#define XGE_HAL_TXD_INT_TYPE_PER_LIST BIT(47) +#define XGE_HAL_TXD_INT_TYPE_UTILZ BIT(46) +#define XGE_HAL_TXD_SET_MARKER vBIT(0x6,0,4) + + u64 buffer_pointer; + + u64 host_control; + +} xge_hal_fifo_txd_t; + +typedef xge_hal_fifo_txd_t* xge_hal_fifo_txdl_t; + +/** + * struct xge_hal_fifo_t - Fifo channel. + * @channel: Channel "base" of this fifo, the common part of all HAL + * channels. + * @post_lock_ptr: Points to a lock that serializes (pointer, control) PIOs. + * Note that for Xena the serialization is done across all device + * fifos. + * @hw_pair: Per-fifo (Pointer, Control) pair used to send descriptors to the + * Xframe hardware (for details see Xframe user guide). + * @config: Fifo configuration, part of device configuration + * (see xge_hal_device_config_t{}). + * @no_snoop_bits: See xge_hal_fifo_config_t{}. + * @txdl_per_memblock: Number of TxDLs (TxD lists) per memblock. + * on TxDL please refer to Xframe UG. + * @interrupt_type: FIXME: to-be-defined. + * @txdl_size: Configured TxDL size (i.e., number of TxDs in a list), plus + * per-TxDL HAL private space (xge_hal_fifo_txdl_priv_t). + * @priv_size: Per-Tx descriptor space reserved for upper-layer driver + * usage. + * @mempool: Memory pool, from which descriptors get allocated. + * @align_size: TBD + * + * Fifo channel. + * Note: The structure is cache line aligned. + */ +typedef struct xge_hal_fifo_t { + xge_hal_channel_t channel; + spinlock_t *post_lock_ptr; + xge_hal_fifo_hw_pair_t *hw_pair; + xge_hal_fifo_config_t *config; + int no_snoop_bits; + int txdl_per_memblock; + u64 interrupt_type; + int txdl_size; + int priv_size; + xge_hal_mempool_t *mempool; + int align_size; +} __xge_os_attr_cacheline_aligned xge_hal_fifo_t; + +/** + * struct xge_hal_fifo_txdl_priv_t - Transmit descriptor HAL-private + * data. + * @dma_addr: DMA (mapped) address of _this_ descriptor. + * @dma_handle: DMA handle used to map the descriptor onto device. + * @dma_offset: Descriptor's offset in the memory block. HAL allocates + * descriptors in memory blocks (see + * xge_hal_fifo_config_t{}) + * Each memblock is a contiguous block of DMA-able memory. + * @frags: Total number of fragments (that is, contiguous data buffers) + * carried by this TxDL. + * @align_vaddr_start: (TODO). + * @align_vaddr: Virtual address of the per-TxDL area in memory used for + * alignement. Used to place one or more mis-aligned fragments + * (the maximum defined by configration variable + * @max_aligned_frags). + * @align_dma_addr: DMA address translated from the @align_vaddr. + * @align_dma_handle: DMA handle that corresponds to @align_dma_addr. + * @align_dma_acch: DMA access handle corresponds to @align_dma_addr. + * @align_dma_offset: The current offset into the @align_vaddr area. + * Grows while filling the descriptor, gets reset. + * @align_used_frags: (TODO). + * @alloc_frags: Total number of fragments allocated. + * @dang_frags: Number of fragments kept from release until this TxDL is freed. + * @bytes_sent: TODO + * @unused: TODO + * @dang_txdl: (TODO). + * @next_txdl_priv: (TODO). + * @first_txdp: (TODO). + * @dang_dtrh: Pointer to TxDL (list) kept from release until this TxDL + * is freed. + * @linked_txdl_priv: Pointer to any linked TxDL for creating contiguous + * TxDL list. + * @dtrh: Corresponding dtrh to this TxDL. + * @memblock: Pointer to the TxDL memory block or memory page. + * on the next send operation. + * @dma_object: DMA address and handle of the memory block that contains + * the descriptor. This member is used only in the "checked" + * version of the HAL (to enforce certain assertions); + * otherwise it gets compiled out. + * @allocated: True if the descriptor is reserved, 0 otherwise. Internal usage. + * + * Per-transmit decsriptor HAL-private data. HAL uses the space to keep DMA + * information associated with the descriptor. Note that ULD can ask HAL + * to allocate additional per-descriptor space for its own (ULD-specific) + * purposes. + * + * See also: xge_hal_ring_rxd_priv_t{}. + */ +typedef struct xge_hal_fifo_txdl_priv_t { + dma_addr_t dma_addr; + pci_dma_h dma_handle; + ptrdiff_t dma_offset; + int frags; + char *align_vaddr_start; + char *align_vaddr; + dma_addr_t align_dma_addr; + pci_dma_h align_dma_handle; + pci_dma_acc_h align_dma_acch; + ptrdiff_t align_dma_offset; + int align_used_frags; + int alloc_frags; + int dang_frags; + unsigned int bytes_sent; + int unused; + xge_hal_fifo_txd_t *dang_txdl; + struct xge_hal_fifo_txdl_priv_t *next_txdl_priv; + xge_hal_fifo_txd_t *first_txdp; + void *memblock; +#ifdef XGE_DEBUG_ASSERT + xge_hal_mempool_dma_t *dma_object; +#endif +#ifdef XGE_OS_MEMORY_CHECK + int allocated; +#endif +} xge_hal_fifo_txdl_priv_t; + +/** + * xge_hal_fifo_get_max_frags_cnt - Return the max fragments allocated + * for the fifo. + * @channelh: Channel handle. + */ +static inline int +xge_hal_fifo_get_max_frags_cnt(xge_hal_channel_h channelh) +{ + return ((xge_hal_fifo_t *)channelh)->config->max_frags; +} +/* ========================= FIFO PRIVATE API ============================= */ + +xge_hal_status_e __hal_fifo_open(xge_hal_channel_h channelh, + xge_hal_channel_attr_t *attr); + +void __hal_fifo_close(xge_hal_channel_h channelh); + +void __hal_fifo_hw_initialize(xge_hal_device_h hldev); + +xge_hal_status_e +__hal_fifo_dtr_align_alloc_map(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); + +void +__hal_fifo_dtr_align_free_unmap(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); + +#if defined(XGE_DEBUG_FP) && (XGE_DEBUG_FP & XGE_DEBUG_FP_FIFO) +#define __HAL_STATIC_FIFO +#define __HAL_INLINE_FIFO + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_fifo_txdl_priv_t* +__hal_fifo_txdl_priv(xge_hal_dtr_h dtrh); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +__hal_fifo_dtr_post_single(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + u64 ctrl_1); +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +__hal_fifo_txdl_restore_many(xge_hal_channel_h channelh, + xge_hal_fifo_txd_t *txdp, int txdl_count); + +/* ========================= FIFO PUBLIC API ============================== */ + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e +xge_hal_fifo_dtr_reserve(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void* +xge_hal_fifo_dtr_private(xge_hal_dtr_h dtrh); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO int +xge_hal_fifo_dtr_buffer_cnt(xge_hal_dtr_h dtrh); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e +xge_hal_fifo_dtr_reserve_sp(xge_hal_channel_h channel, int dtr_sp_size, + xge_hal_dtr_h dtr_sp); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_post_many(xge_hal_channel_h channelh, int num, + xge_hal_dtr_h dtrs[]); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e +xge_hal_fifo_dtr_next_completed(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh, + u8 *t_code); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_free(xge_hal_channel_h channelh, xge_hal_dtr_h dtr); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_buffer_set(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + int frag_idx, dma_addr_t dma_pointer, int size); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e +xge_hal_fifo_dtr_buffer_set_aligned(xge_hal_channel_h channelh, + xge_hal_dtr_h dtrh, int frag_idx, void *vaddr, + dma_addr_t dma_pointer, int size, int misaligned_size); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e +xge_hal_fifo_dtr_buffer_append(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + void *vaddr, int size); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_buffer_finalize(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + int frag_idx); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_mss_set(xge_hal_dtr_h dtrh, int mss); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_cksum_set_bits(xge_hal_dtr_h dtrh, u64 cksum_bits); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_vlan_set(xge_hal_dtr_h dtrh, u16 vlan_tag); + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e +xge_hal_fifo_is_next_dtr_completed(xge_hal_channel_h channelh); + +#else /* XGE_FASTPATH_EXTERN */ +#define __HAL_STATIC_FIFO static +#define __HAL_INLINE_FIFO inline +#include <dev/nxge/xgehal/xgehal-fifo-fp.c> +#endif /* XGE_FASTPATH_INLINE */ + +__EXTERN_END_DECLS + +#endif /* XGE_HAL_FIFO_H */ diff --git a/sys/dev/nxge/include/xgehal-mgmt.h b/sys/dev/nxge/include/xgehal-mgmt.h new file mode 100644 index 0000000..061320e --- /dev/null +++ b/sys/dev/nxge/include/xgehal-mgmt.h @@ -0,0 +1,228 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-mgmt.h + * + * Description: management API + * + * Created: 1 September 2004 + */ + +#ifndef XGE_HAL_MGMT_H +#define XGE_HAL_MGMT_H + +#include <dev/nxge/include/xge-os-pal.h> +#include <dev/nxge/include/xge-debug.h> +#include <dev/nxge/include/xgehal-types.h> +#include <dev/nxge/include/xgehal-config.h> +#include <dev/nxge/include/xgehal-stats.h> +#include <dev/nxge/include/xgehal-regs.h> +#include <dev/nxge/include/xgehal-device.h> + +__EXTERN_BEGIN_DECLS + +/** + * struct xge_hal_mgmt_about_info_t - About info. + * @vendor: PCI Vendor ID. + * @device: PCI Device ID. + * @subsys_vendor: PCI Subsystem Vendor ID. + * @subsys_device: PCI Subsystem Device ID. + * @board_rev: PCI Board revision, e.g. 3 - for Xena 3. + * @vendor_name: Neterion, Inc. + * @chip_name: Xframe. + * @media: Fiber, copper. + * @hal_major: HAL major version number. + * @hal_minor: HAL minor version number. + * @hal_fix: HAL fix number. + * @hal_build: HAL build number. + * @ll_major: Link-layer ULD major version number. + * @ll_minor: Link-layer ULD minor version number. + * @ll_fix: Link-layer ULD fix version number. + * @ll_build: Link-layer ULD build number. + * @transponder_temperature: TODO + */ +typedef struct xge_hal_mgmt_about_info_t { + u16 vendor; + u16 device; + u16 subsys_vendor; + u16 subsys_device; + u8 board_rev; + char vendor_name[16]; + char chip_name[16]; + char media[16]; + char hal_major[4]; + char hal_minor[4]; + char hal_fix[4]; + char hal_build[16]; + char ll_major[4]; + char ll_minor[4]; + char ll_fix[4]; + char ll_build[16]; + u32 transponder_temperature; +} xge_hal_mgmt_about_info_t; + +typedef xge_hal_stats_hw_info_t xge_hal_mgmt_hw_stats_t; +typedef xge_hal_stats_pcim_info_t xge_hal_mgmt_pcim_stats_t; +typedef xge_hal_stats_sw_err_t xge_hal_mgmt_sw_stats_t; +typedef xge_hal_stats_device_info_t xge_hal_mgmt_device_stats_t; +typedef xge_hal_stats_channel_info_t xge_hal_mgmt_channel_stats_t; +typedef xge_hal_device_config_t xge_hal_mgmt_device_config_t; +typedef xge_hal_driver_config_t xge_hal_mgmt_driver_config_t; +typedef xge_hal_pci_config_t xge_hal_mgmt_pci_config_t; + +xge_hal_status_e +xge_hal_mgmt_about(xge_hal_device_h devh, xge_hal_mgmt_about_info_t *about_info, + int size); + +xge_hal_status_e +xge_hal_mgmt_hw_stats(xge_hal_device_h devh, xge_hal_mgmt_hw_stats_t *hw_stats, + int size); + +xge_hal_status_e +xge_hal_mgmt_hw_stats_off(xge_hal_device_h devh, int off, int size, char *out); + +xge_hal_status_e +xge_hal_mgmt_pcim_stats(xge_hal_device_h devh, + xge_hal_mgmt_pcim_stats_t *pcim_stats, int size); + +xge_hal_status_e +xge_hal_mgmt_pcim_stats_off(xge_hal_device_h devh, int off, int size, + char *out); + +xge_hal_status_e +xge_hal_mgmt_sw_stats(xge_hal_device_h devh, xge_hal_mgmt_sw_stats_t *hw_stats, + int size); + +xge_hal_status_e +xge_hal_mgmt_device_stats(xge_hal_device_h devh, + xge_hal_mgmt_device_stats_t *device_stats, int size); + +xge_hal_status_e +xge_hal_mgmt_channel_stats(xge_hal_channel_h channelh, + xge_hal_mgmt_channel_stats_t *channel_stats, int size); + +xge_hal_status_e +xge_hal_mgmt_reg_read(xge_hal_device_h devh, int bar_id, unsigned int offset, + u64 *value); + +xge_hal_status_e +xge_hal_mgmt_reg_write(xge_hal_device_h devh, int bar_id, unsigned int offset, + u64 value); + +xge_hal_status_e +xge_hal_mgmt_pcireg_read(xge_hal_device_h devh, unsigned int offset, + int bits, u32 *value); + +xge_hal_status_e +xge_hal_mgmt_device_config(xge_hal_device_h devh, + xge_hal_mgmt_device_config_t *dev_config, int size); + +xge_hal_status_e +xge_hal_mgmt_driver_config(xge_hal_mgmt_driver_config_t *drv_config, + int size); + +xge_hal_status_e +xge_hal_mgmt_pci_config(xge_hal_device_h devh, + xge_hal_mgmt_pci_config_t *pci_config, int size); + +xge_hal_status_e +xge_hal_pma_loopback( xge_hal_device_h devh, int enable ); + +xge_hal_status_e +xge_hal_rldram_test(xge_hal_device_h devh, u64 * data); + +u16 +xge_hal_mdio_read( xge_hal_device_h devh, u32 mmd_type, u64 addr ); + +xge_hal_status_e +xge_hal_mdio_write( xge_hal_device_h devh, u32 mmd_type, u64 addr, u32 value ); + +u32 +xge_hal_read_xfp_current_temp(xge_hal_device_h devh); + +xge_hal_status_e +xge_hal_read_eeprom(xge_hal_device_h devh, int off, u32* data); + +xge_hal_status_e +xge_hal_write_eeprom(xge_hal_device_h devh, int off, u32 data, int cnt); + +xge_hal_status_e +xge_hal_register_test(xge_hal_device_h devh, u64 *data); + +xge_hal_status_e +xge_hal_eeprom_test(xge_hal_device_h devh, u64 *data); + +xge_hal_status_e +xge_hal_bist_test(xge_hal_device_h devh, u64 *data); + +xge_hal_status_e +xge_hal_link_test(xge_hal_device_h devh, u64 *data); + +int +xge_hal_setpause_data(xge_hal_device_h devh, int tx, int rx); + +void +xge_hal_getpause_data(xge_hal_device_h devh, int *tx, int *rx); + +void +__hal_updt_stats_xpak(xge_hal_device_t *hldev); + +void +__hal_chk_xpak_counter(xge_hal_device_t *hldev, int type, u32 value); + +#ifdef XGE_TRACE_INTO_CIRCULAR_ARR +xge_hal_status_e +xge_hal_mgmt_trace_read(char *buffer, unsigned buf_size, unsigned *offset, + unsigned *read_length); +#endif + +void +xge_hal_restore_link_led(xge_hal_device_h devh); + + +void +xge_hal_flick_link_led(xge_hal_device_h devh); + +/* + * Some set of Xena3 Cards were known to have some link LED + * Problems. This macro identifies if the card is among them + * given its Sub system ID. + */ +#define CARDS_WITH_FAULTY_LINK_INDICATORS(subid) \ + ((((subid >= 0x600B) && (subid <= 0x600D)) || \ + ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0) +#define CHECKBIT(value, nbit) (value & (1 << nbit)) + +#ifdef XGE_HAL_USE_MGMT_AUX +#include <dev/nxge/include/xgehal-mgmtaux.h> +#endif + +__EXTERN_END_DECLS + +#endif /* XGE_HAL_MGMT_H */ diff --git a/sys/dev/nxge/include/xgehal-mgmtaux.h b/sys/dev/nxge/include/xgehal-mgmtaux.h new file mode 100644 index 0000000..6d4922e --- /dev/null +++ b/sys/dev/nxge/include/xgehal-mgmtaux.h @@ -0,0 +1,95 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-mgmtaux.h + * + * Description: management auxiliary API + * + * Created: 1 September 2004 + */ + +#ifndef XGE_HAL_MGMTAUX_H +#define XGE_HAL_MGMTAUX_H + +#include <dev/nxge/include/xgehal-mgmt.h> + +__EXTERN_BEGIN_DECLS + +#define XGE_HAL_AUX_SEPA ' ' + +xge_hal_status_e xge_hal_aux_about_read(xge_hal_device_h devh, int bufsize, + char *retbuf, int *retsize); + +xge_hal_status_e xge_hal_aux_stats_tmac_read(xge_hal_device_h devh, int bufsize, + char *retbuf, int *retsize); + +xge_hal_status_e xge_hal_aux_stats_rmac_read(xge_hal_device_h devh, int bufsize, + char *retbuf, int *retsize); + +xge_hal_status_e xge_hal_aux_stats_sw_dev_read(xge_hal_device_h devh, + int bufsize, char *retbuf, int *retsize); + +xge_hal_status_e xge_hal_aux_stats_pci_read(xge_hal_device_h devh, int bufsize, + char *retbuf, int *retsize); + +xge_hal_status_e xge_hal_aux_stats_hal_read(xge_hal_device_h devh, int bufsize, + char *retbuf, int *retsize); + +xge_hal_status_e xge_hal_aux_bar0_read(xge_hal_device_h devh, + unsigned int offset, int bufsize, char *retbuf, + int *retsize); + +xge_hal_status_e xge_hal_aux_bar0_write(xge_hal_device_h devh, + unsigned int offset, u64 value); + +xge_hal_status_e xge_hal_aux_bar1_read(xge_hal_device_h devh, + unsigned int offset, int bufsize, char *retbuf, + int *retsize); + +xge_hal_status_e xge_hal_aux_pci_config_read(xge_hal_device_h devh, int bufsize, + char *retbuf, int *retsize); + +xge_hal_status_e xge_hal_aux_stats_herc_enchanced(xge_hal_device_h devh, + int bufsize, char *retbuf, int *retsize); + +xge_hal_status_e xge_hal_aux_channel_read(xge_hal_device_h devh, int bufsize, + char *retbuf, int *retsize); + +xge_hal_status_e xge_hal_aux_device_dump(xge_hal_device_h devh); + + +xge_hal_status_e xge_hal_aux_driver_config_read(int bufsize, char *retbuf, + int *retsize); + +xge_hal_status_e xge_hal_aux_device_config_read(xge_hal_device_h devh, + int bufsize, char *retbuf, int *retsize); + +__EXTERN_END_DECLS + +#endif /* XGE_HAL_MGMTAUX_H */ diff --git a/sys/dev/nxge/include/xgehal-mm.h b/sys/dev/nxge/include/xgehal-mm.h new file mode 100644 index 0000000..5a8f836 --- /dev/null +++ b/sys/dev/nxge/include/xgehal-mm.h @@ -0,0 +1,174 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-mm.h + * + * Description: memory pool object + * + * Created: 28 May 2004 + */ + +#ifndef XGE_HAL_MM_H +#define XGE_HAL_MM_H + +#include <dev/nxge/include/xge-os-pal.h> +#include <dev/nxge/include/xge-debug.h> +#include <dev/nxge/include/xgehal-types.h> +#include <dev/nxge/include/xgehal-driver.h> + +__EXTERN_BEGIN_DECLS + +typedef void* xge_hal_mempool_h; + +/* + * struct xge_hal_mempool_dma_t - Represents DMA objects passed to the + caller. + */ +typedef struct xge_hal_mempool_dma_t { + dma_addr_t addr; + pci_dma_h handle; + pci_dma_acc_h acc_handle; +} xge_hal_mempool_dma_t; + +/* + * xge_hal_mempool_item_f - Mempool item alloc/free callback + * @mempoolh: Memory pool handle. + * @item: Item that gets allocated or freed. + * @index: Item's index in the memory pool. + * @is_last: True, if this item is the last one in the pool; false - otherwise. + * userdat: Per-pool user context. + * + * Memory pool allocation/deallocation callback. + */ +typedef xge_hal_status_e (*xge_hal_mempool_item_f) (xge_hal_mempool_h mempoolh, + void *memblock, int memblock_index, + xge_hal_mempool_dma_t *dma_object, void *item, + int index, int is_last, void *userdata); + +/* + * struct xge_hal_mempool_t - Memory pool. + */ +typedef struct xge_hal_mempool_t { + xge_hal_mempool_item_f item_func_alloc; + xge_hal_mempool_item_f item_func_free; + void *userdata; + void **memblocks_arr; + void **memblocks_priv_arr; + xge_hal_mempool_dma_t *memblocks_dma_arr; + pci_dev_h pdev; + int memblock_size; + int memblocks_max; + int memblocks_allocated; + int item_size; + int items_max; + int items_initial; + int items_current; + int items_per_memblock; + void **items_arr; + void **shadow_items_arr; + int items_priv_size; +} xge_hal_mempool_t; + +/* + * __hal_mempool_item - Returns pointer to the item in the mempool + * items array. + */ +static inline void* +__hal_mempool_item(xge_hal_mempool_t *mempool, int index) +{ + return mempool->items_arr[index]; +} + +/* + * __hal_mempool_item_priv - will return pointer on per item private space + */ +static inline void* +__hal_mempool_item_priv(xge_hal_mempool_t *mempool, int memblock_idx, + void *item, int *memblock_item_idx) +{ + ptrdiff_t offset; + void *memblock = mempool->memblocks_arr[memblock_idx]; + + xge_assert(memblock); + + offset = (int)((char * )item - (char *)memblock); + xge_assert(offset >= 0 && offset < mempool->memblock_size); + + (*memblock_item_idx) = (int) offset / mempool->item_size; + xge_assert((*memblock_item_idx) < mempool->items_per_memblock); + + return (char*)mempool->memblocks_priv_arr[memblock_idx] + + (*memblock_item_idx) * mempool->items_priv_size; +} + +/* + * __hal_mempool_items_arr - will return pointer to the items array in the + * mempool. + */ +static inline void* +__hal_mempool_items_arr(xge_hal_mempool_t *mempool) +{ + return mempool->items_arr; +} + +/* + * __hal_mempool_memblock - will return pointer to the memblock in the + * mempool memblocks array. + */ +static inline void* +__hal_mempool_memblock(xge_hal_mempool_t *mempool, int memblock_idx) +{ + xge_assert(mempool->memblocks_arr[memblock_idx]); + return mempool->memblocks_arr[memblock_idx]; +} + +/* + * __hal_mempool_memblock_dma - will return pointer to the dma block + * corresponds to the memblock(identified by memblock_idx) in the mempool. + */ +static inline xge_hal_mempool_dma_t* +__hal_mempool_memblock_dma(xge_hal_mempool_t *mempool, int memblock_idx) +{ + return mempool->memblocks_dma_arr + memblock_idx; +} + +xge_hal_status_e __hal_mempool_grow(xge_hal_mempool_t *mempool, + int num_allocate, int *num_allocated); + +xge_hal_mempool_t* __hal_mempool_create(pci_dev_h pdev, int memblock_size, + int item_size, int private_size, int items_initial, + int items_max, xge_hal_mempool_item_f item_func_alloc, + xge_hal_mempool_item_f item_func_free, void *userdata); + +void __hal_mempool_destroy(xge_hal_mempool_t *mempool); + + +__EXTERN_END_DECLS + +#endif /* XGE_HAL_MM_H */ diff --git a/sys/dev/nxge/include/xgehal-regs.h b/sys/dev/nxge/include/xgehal-regs.h new file mode 100644 index 0000000..89a2c4a --- /dev/null +++ b/sys/dev/nxge/include/xgehal-regs.h @@ -0,0 +1,1377 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-regs.h + * + * Description: Xframe mem-mapped register space + * + * Created: 14 May 2004 + */ + +#ifndef XGE_HAL_REGS_H +#define XGE_HAL_REGS_H + +typedef struct { + +/* General Control-Status Registers */ + u64 general_int_status; +#define XGE_HAL_GEN_INTR_TXPIC BIT(0) +#define XGE_HAL_GEN_INTR_TXDMA BIT(1) +#define XGE_HAL_GEN_INTR_TXMAC BIT(2) +#define XGE_HAL_GEN_INTR_TXXGXS BIT(3) +#define XGE_HAL_GEN_INTR_TXTRAFFIC BIT(8) +#define XGE_HAL_GEN_INTR_RXPIC BIT(32) +#define XGE_HAL_GEN_INTR_RXDMA BIT(33) +#define XGE_HAL_GEN_INTR_RXMAC BIT(34) +#define XGE_HAL_GEN_INTR_MC BIT(35) +#define XGE_HAL_GEN_INTR_RXXGXS BIT(36) +#define XGE_HAL_GEN_INTR_RXTRAFFIC BIT(40) +#define XGE_HAL_GEN_ERROR_INTR (XGE_HAL_GEN_INTR_TXPIC | \ + XGE_HAL_GEN_INTR_RXPIC | \ + XGE_HAL_GEN_INTR_TXDMA | \ + XGE_HAL_GEN_INTR_RXDMA | \ + XGE_HAL_GEN_INTR_TXMAC | \ + XGE_HAL_GEN_INTR_RXMAC | \ + XGE_HAL_GEN_INTR_TXXGXS | \ + XGE_HAL_GEN_INTR_RXXGXS | \ + XGE_HAL_GEN_INTR_MC) + + u64 general_int_mask; + + u8 unused0[0x100 - 0x10]; + + u64 sw_reset; + +/* XGXS must be removed from reset only once. */ +#define XGE_HAL_SW_RESET_XENA vBIT(0xA5,0,8) +#define XGE_HAL_SW_RESET_FLASH vBIT(0xA5,8,8) +#define XGE_HAL_SW_RESET_EOI vBIT(0xA5,16,8) +#define XGE_HAL_SW_RESET_XGXS vBIT(0xA5,24,8) +#define XGE_HAL_SW_RESET_ALL (XGE_HAL_SW_RESET_XENA | \ + XGE_HAL_SW_RESET_FLASH | \ + XGE_HAL_SW_RESET_EOI | \ + XGE_HAL_SW_RESET_XGXS) + +/* The SW_RESET register must read this value after a successful reset. */ +#if defined(XGE_OS_HOST_BIG_ENDIAN) && !defined(XGE_OS_PIO_LITTLE_ENDIAN) +#define XGE_HAL_SW_RESET_RAW_VAL_XENA 0xA500000000ULL +#define XGE_HAL_SW_RESET_RAW_VAL_HERC 0xA5A500000000ULL +#else +#define XGE_HAL_SW_RESET_RAW_VAL_XENA 0xA5000000ULL +#define XGE_HAL_SW_RESET_RAW_VAL_HERC 0xA5A50000ULL +#endif + + + u64 adapter_status; +#define XGE_HAL_ADAPTER_STATUS_TDMA_READY BIT(0) +#define XGE_HAL_ADAPTER_STATUS_RDMA_READY BIT(1) +#define XGE_HAL_ADAPTER_STATUS_PFC_READY BIT(2) +#define XGE_HAL_ADAPTER_STATUS_TMAC_BUF_EMPTY BIT(3) +#define XGE_HAL_ADAPTER_STATUS_PIC_QUIESCENT BIT(5) +#define XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT BIT(6) +#define XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT BIT(7) +#define XGE_HAL_ADAPTER_STATUS_RMAC_PCC_IDLE vBIT(0xFF,8,8) +#define XGE_HAL_ADAPTER_STATUS_RMAC_PCC_4_IDLE vBIT(0x0F,8,8) +#define XGE_HAL_ADAPTER_PCC_ENABLE_FOUR vBIT(0x0F,0,8) + +#define XGE_HAL_ADAPTER_STATUS_RC_PRC_QUIESCENT vBIT(0xFF,16,8) +#define XGE_HAL_ADAPTER_STATUS_MC_DRAM_READY BIT(24) +#define XGE_HAL_ADAPTER_STATUS_MC_QUEUES_READY BIT(25) +#define XGE_HAL_ADAPTER_STATUS_M_PLL_LOCK BIT(30) +#define XGE_HAL_ADAPTER_STATUS_P_PLL_LOCK BIT(31) + + u64 adapter_control; +#define XGE_HAL_ADAPTER_CNTL_EN BIT(7) +#define XGE_HAL_ADAPTER_EOI_TX_ON BIT(15) +#define XGE_HAL_ADAPTER_LED_ON BIT(23) +#define XGE_HAL_ADAPTER_UDPI(val) vBIT(val,36,4) +#define XGE_HAL_ADAPTER_WAIT_INT BIT(48) +#define XGE_HAL_ADAPTER_ECC_EN BIT(55) + + u64 serr_source; +#define XGE_HAL_SERR_SOURCE_PIC BIT(0) +#define XGE_HAL_SERR_SOURCE_TXDMA BIT(1) +#define XGE_HAL_SERR_SOURCE_RXDMA BIT(2) +#define XGE_HAL_SERR_SOURCE_MAC BIT(3) +#define XGE_HAL_SERR_SOURCE_MC BIT(4) +#define XGE_HAL_SERR_SOURCE_XGXS BIT(5) +#define XGE_HAL_SERR_SOURCE_ANY (XGE_HAL_SERR_SOURCE_PIC | \ + XGE_HAL_SERR_SOURCE_TXDMA | \ + XGE_HAL_SERR_SOURCE_RXDMA | \ + XGE_HAL_SERR_SOURCE_MAC | \ + XGE_HAL_SERR_SOURCE_MC | \ + XGE_HAL_SERR_SOURCE_XGXS) + + u64 pci_info; +#define XGE_HAL_PCI_INFO vBIT(0xF,0,4) +#define XGE_HAL_PCI_32_BIT BIT(8) + + u8 unused0_1[0x160 - 0x128]; + + u64 ric_status; + + u8 unused0_2[0x558 - 0x168]; + + u64 mbist_status; + + u8 unused0_3[0x800 - 0x560]; + +/* PCI-X Controller registers */ + u64 pic_int_status; + u64 pic_int_mask; +#define XGE_HAL_PIC_INT_TX BIT(0) +#define XGE_HAL_PIC_INT_FLSH BIT(1) +#define XGE_HAL_PIC_INT_MDIO BIT(2) +#define XGE_HAL_PIC_INT_IIC BIT(3) +#define XGE_HAL_PIC_INT_MISC BIT(4) +#define XGE_HAL_PIC_INT_RX BIT(32) + + u64 txpic_int_reg; +#define XGE_HAL_TXPIC_INT_SCHED_INTR BIT(42) + u64 txpic_int_mask; +#define XGE_HAL_PCIX_INT_REG_ECC_SG_ERR BIT(0) +#define XGE_HAL_PCIX_INT_REG_ECC_DB_ERR BIT(1) +#define XGE_HAL_PCIX_INT_REG_FLASHR_R_FSM_ERR BIT(8) +#define XGE_HAL_PCIX_INT_REG_FLASHR_W_FSM_ERR BIT(9) +#define XGE_HAL_PCIX_INT_REG_INI_TX_FSM_SERR BIT(10) +#define XGE_HAL_PCIX_INT_REG_INI_TXO_FSM_ERR BIT(11) +#define XGE_HAL_PCIX_INT_REG_TRT_FSM_SERR BIT(13) +#define XGE_HAL_PCIX_INT_REG_SRT_FSM_SERR BIT(14) +#define XGE_HAL_PCIX_INT_REG_PIFR_FSM_SERR BIT(15) +#define XGE_HAL_PCIX_INT_REG_WRC_TX_SEND_FSM_SERR BIT(21) +#define XGE_HAL_PCIX_INT_REG_RRC_TX_REQ_FSM_SERR BIT(23) +#define XGE_HAL_PCIX_INT_REG_INI_RX_FSM_SERR BIT(48) +#define XGE_HAL_PCIX_INT_REG_RA_RX_FSM_SERR BIT(50) +/* +#define XGE_HAL_PCIX_INT_REG_WRC_RX_SEND_FSM_SERR BIT(52) +#define XGE_HAL_PCIX_INT_REG_RRC_RX_REQ_FSM_SERR BIT(54) +#define XGE_HAL_PCIX_INT_REG_RRC_RX_SPLIT_FSM_SERR BIT(58) +*/ + u64 txpic_alarms; + u64 rxpic_int_reg; +#define XGE_HAL_RX_PIC_INT_REG_SPDM_READY BIT(0) +#define XGE_HAL_RX_PIC_INT_REG_SPDM_OVERWRITE_ERR BIT(44) +#define XGE_HAL_RX_PIC_INT_REG_SPDM_PERR BIT(55) + u64 rxpic_int_mask; + u64 rxpic_alarms; + + u64 flsh_int_reg; + u64 flsh_int_mask; +#define XGE_HAL_PIC_FLSH_INT_REG_CYCLE_FSM_ERR BIT(63) +#define XGE_HAL_PIC_FLSH_INT_REG_ERR BIT(62) + u64 flash_alarms; + + u64 mdio_int_reg; + u64 mdio_int_mask; +#define XGE_HAL_MDIO_INT_REG_MDIO_BUS_ERR BIT(0) +#define XGE_HAL_MDIO_INT_REG_DTX_BUS_ERR BIT(8) +#define XGE_HAL_MDIO_INT_REG_LASI BIT(39) + u64 mdio_alarms; + + u64 iic_int_reg; + u64 iic_int_mask; +#define XGE_HAL_IIC_INT_REG_BUS_FSM_ERR BIT(4) +#define XGE_HAL_IIC_INT_REG_BIT_FSM_ERR BIT(5) +#define XGE_HAL_IIC_INT_REG_CYCLE_FSM_ERR BIT(6) +#define XGE_HAL_IIC_INT_REG_REQ_FSM_ERR BIT(7) +#define XGE_HAL_IIC_INT_REG_ACK_ERR BIT(8) + u64 iic_alarms; + + u64 msi_pending_reg; + + u64 misc_int_reg; +#define XGE_HAL_MISC_INT_REG_DP_ERR_INT BIT(0) +#define XGE_HAL_MISC_INT_REG_LINK_DOWN_INT BIT(1) +#define XGE_HAL_MISC_INT_REG_LINK_UP_INT BIT(2) + u64 misc_int_mask; + u64 misc_alarms; + + u64 msi_triggered_reg; + + u64 xfp_gpio_int_reg; + u64 xfp_gpio_int_mask; + u64 xfp_alarms; + + u8 unused5[0x8E0 - 0x8C8]; + + u64 tx_traffic_int; +#define XGE_HAL_TX_TRAFFIC_INT_n(n) BIT(n) + u64 tx_traffic_mask; + + u64 rx_traffic_int; +#define XGE_HAL_RX_TRAFFIC_INT_n(n) BIT(n) + u64 rx_traffic_mask; + +/* PIC Control registers */ + u64 pic_control; +#define XGE_HAL_PIC_CNTL_RX_ALARM_MAP_1 BIT(0) +#define XGE_HAL_PIC_CNTL_ONE_SHOT_TINT BIT(1) +#define XGE_HAL_PIC_CNTL_SHARED_SPLITS(n) vBIT(n,11,4) + + u64 swapper_ctrl; +#define XGE_HAL_SWAPPER_CTRL_PIF_R_FE BIT(0) +#define XGE_HAL_SWAPPER_CTRL_PIF_R_SE BIT(1) +#define XGE_HAL_SWAPPER_CTRL_PIF_W_FE BIT(8) +#define XGE_HAL_SWAPPER_CTRL_PIF_W_SE BIT(9) +#define XGE_HAL_SWAPPER_CTRL_RTH_FE BIT(10) +#define XGE_HAL_SWAPPER_CTRL_RTH_SE BIT(11) +#define XGE_HAL_SWAPPER_CTRL_TXP_FE BIT(16) +#define XGE_HAL_SWAPPER_CTRL_TXP_SE BIT(17) +#define XGE_HAL_SWAPPER_CTRL_TXD_R_FE BIT(18) +#define XGE_HAL_SWAPPER_CTRL_TXD_R_SE BIT(19) +#define XGE_HAL_SWAPPER_CTRL_TXD_W_FE BIT(20) +#define XGE_HAL_SWAPPER_CTRL_TXD_W_SE BIT(21) +#define XGE_HAL_SWAPPER_CTRL_TXF_R_FE BIT(22) +#define XGE_HAL_SWAPPER_CTRL_TXF_R_SE BIT(23) +#define XGE_HAL_SWAPPER_CTRL_RXD_R_FE BIT(32) +#define XGE_HAL_SWAPPER_CTRL_RXD_R_SE BIT(33) +#define XGE_HAL_SWAPPER_CTRL_RXD_W_FE BIT(34) +#define XGE_HAL_SWAPPER_CTRL_RXD_W_SE BIT(35) +#define XGE_HAL_SWAPPER_CTRL_RXF_W_FE BIT(36) +#define XGE_HAL_SWAPPER_CTRL_RXF_W_SE BIT(37) +#define XGE_HAL_SWAPPER_CTRL_XMSI_FE BIT(40) +#define XGE_HAL_SWAPPER_CTRL_XMSI_SE BIT(41) +#define XGE_HAL_SWAPPER_CTRL_STATS_FE BIT(48) +#define XGE_HAL_SWAPPER_CTRL_STATS_SE BIT(49) + + u64 pif_rd_swapper_fb; +#define XGE_HAL_IF_RD_SWAPPER_FB 0x0123456789ABCDEFULL + + u64 scheduled_int_ctrl; +#define XGE_HAL_SCHED_INT_CTRL_TIMER_EN BIT(0) +#define XGE_HAL_SCHED_INT_CTRL_ONE_SHOT BIT(1) +#define XGE_HAL_SCHED_INT_CTRL_INT2MSI(val) vBIT(val,10,6) +#define XGE_HAL_SCHED_INT_PERIOD(val) vBIT(val,32,32) +#define XGE_HAL_SCHED_INT_PERIOD_MASK 0xFFFFFFFF00000000ULL + + + u64 txreqtimeout; +#define XGE_HAL_TXREQTO_VAL(val) vBIT(val,0,32) +#define XGE_HAL_TXREQTO_EN BIT(63) + + u64 statsreqtimeout; +#define XGE_HAL_STATREQTO_VAL(n) TBD +#define XGE_HAL_STATREQTO_EN BIT(63) + + u64 read_retry_delay; + u64 read_retry_acceleration; + u64 write_retry_delay; + u64 write_retry_acceleration; + + u64 xmsi_control; +#define XGE_HAL_XMSI_EN BIT(0) +#define XGE_HAL_XMSI_DIS_TINT_SERR BIT(1) +#define XGE_HAL_XMSI_BYTE_COUNT(val) vBIT(val,13,3) + + u64 xmsi_access; +#define XGE_HAL_XMSI_WR_RDN BIT(7) +#define XGE_HAL_XMSI_STROBE BIT(15) +#define XGE_HAL_XMSI_NO(val) vBIT(val,26,6) + + u64 xmsi_address; + u64 xmsi_data; + + u64 rx_mat; +#define XGE_HAL_SET_RX_MAT(ring, msi) vBIT(msi, (8 * ring), 8) + + u8 unused6[0x8]; + + u64 tx_mat[8]; +#define XGE_HAL_SET_TX_MAT(fifo, msi) vBIT(msi, (8 * fifo), 8) + + u64 xmsi_mask_reg; + + /* Automated statistics collection */ + u64 stat_byte_cnt; + u64 stat_cfg; +#define XGE_HAL_STAT_CFG_STAT_EN BIT(0) +#define XGE_HAL_STAT_CFG_ONE_SHOT_EN BIT(1) +#define XGE_HAL_STAT_CFG_STAT_NS_EN BIT(8) +#define XGE_HAL_STAT_CFG_STAT_RO BIT(9) +#define XGE_HAL_XENA_PER_SEC 0x208d5 +#define XGE_HAL_SET_UPDT_PERIOD(n) vBIT(n,32,32) + + u64 stat_addr; + + /* General Configuration */ + u64 mdio_control; +#define XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(n) vBIT(n,0,16) +#define XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(n) vBIT(n,19,5) +#define XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(n) vBIT(n,27,5) +#define XGE_HAL_MDIO_CONTROL_MMD_DATA(n) vBIT(n,32,16) +#define XGE_HAL_MDIO_CONTROL_MMD_CTRL(n) vBIT(n,56,4) +#define XGE_HAL_MDIO_CONTROL_MMD_OP(n) vBIT(n,60,2) +#define XGE_HAL_MDIO_CONTROL_MMD_DATA_GET(n) ((n>>16)&0xFFFF) +#define XGE_HAL_MDIO_MMD_PMA_DEV_ADDR 0x01 +#define XGE_HAL_MDIO_DOM_REG_ADDR 0xA100 +#define XGE_HAL_MDIO_ALARM_FLAGS_ADDR 0xA070 +#define XGE_HAL_MDIO_WARN_FLAGS_ADDR 0xA074 +#define XGE_HAL_MDIO_CTRL_START 0xE +#define XGE_HAL_MDIO_OP_ADDRESS 0x0 +#define XGE_HAL_MDIO_OP_WRITE 0x1 +#define XGE_HAL_MDIO_OP_READ 0x3 +#define XGE_HAL_MDIO_OP_READ_POST_INCREMENT 0x2 +#define XGE_HAL_MDIO_ALARM_TEMPHIGH 0x0080 +#define XGE_HAL_MDIO_ALARM_TEMPLOW 0x0040 +#define XGE_HAL_MDIO_ALARM_BIASHIGH 0x0008 +#define XGE_HAL_MDIO_ALARM_BIASLOW 0x0004 +#define XGE_HAL_MDIO_ALARM_POUTPUTHIGH 0x0002 +#define XGE_HAL_MDIO_ALARM_POUTPUTLOW 0x0001 +#define XGE_HAL_MDIO_WARN_TEMPHIGH 0x0080 +#define XGE_HAL_MDIO_WARN_TEMPLOW 0x0040 +#define XGE_HAL_MDIO_WARN_BIASHIGH 0x0008 +#define XGE_HAL_MDIO_WARN_BIASLOW 0x0004 +#define XGE_HAL_MDIO_WARN_POUTPUTHIGH 0x0002 +#define XGE_HAL_MDIO_WARN_POUTPUTLOW 0x0001 + + u64 dtx_control; + + u64 i2c_control; +#define XGE_HAL_I2C_CONTROL_DEV_ID(id) vBIT(id,1,3) +#define XGE_HAL_I2C_CONTROL_ADDR(addr) vBIT(addr,5,11) +#define XGE_HAL_I2C_CONTROL_BYTE_CNT(cnt) vBIT(cnt,22,2) +#define XGE_HAL_I2C_CONTROL_READ BIT(24) +#define XGE_HAL_I2C_CONTROL_NACK BIT(25) +#define XGE_HAL_I2C_CONTROL_CNTL_START vBIT(0xE,28,4) +#define XGE_HAL_I2C_CONTROL_CNTL_END(val) (val & vBIT(0x1,28,4)) +#define XGE_HAL_I2C_CONTROL_GET_DATA(val) (u32)(val & 0xFFFFFFFF) +#define XGE_HAL_I2C_CONTROL_SET_DATA(val) vBIT(val,32,32) + + u64 beacon_control; + u64 misc_control; +#define XGE_HAL_MISC_CONTROL_LINK_STABILITY_PERIOD(val) vBIT(val,29,3) +#define XGE_HAL_MISC_CONTROL_EXT_REQ_EN BIT(1) +#define XGE_HAL_MISC_CONTROL_LINK_FAULT BIT(0) + + u64 xfb_control; + u64 gpio_control; +#define XGE_HAL_GPIO_CTRL_GPIO_0 BIT(8) + + u64 txfifo_dw_mask; + u64 split_table_line_no; + u64 sc_timeout; + u64 pic_control_2; +#define XGE_HAL_TXD_WRITE_BC(n) vBIT(n, 13, 3) + u64 ini_dperr_ctrl; + u64 wreq_split_mask; + u64 qw_per_rxd; + u8 unused7[0x300 - 0x250]; + + u64 pic_status; + u64 txp_status; + u64 txp_err_context; + u64 spdm_bir_offset; +#define XGE_HAL_SPDM_PCI_BAR_NUM(spdm_bir_offset) \ + (u8)(spdm_bir_offset >> 61) +#define XGE_HAL_SPDM_PCI_BAR_OFFSET(spdm_bir_offset) \ + (u32)((spdm_bir_offset >> 32) & 0x1FFFFFFF) + u64 spdm_overwrite; +#define XGE_HAL_SPDM_OVERWRITE_ERR_SPDM_ENTRY(spdm_overwrite) \ + (u8)((spdm_overwrite >> 48) & 0xff) +#define XGE_HAL_SPDM_OVERWRITE_ERR_SPDM_DW(spdm_overwrite) \ + (u8)((spdm_overwrite >> 40) & 0x3) +#define XGE_HAL_SPDM_OVERWRITE_ERR_SPDM_LINE(spdm_overwrite) \ + (u8)((spdm_overwrite >> 32) & 0x7) + u64 cfg_addr_on_dperr; + u64 pif_addr_on_dperr; + u64 tags_in_use; + u64 rd_req_types; + u64 split_table_line; + u64 unxp_split_add_ph; + u64 unexp_split_attr_ph; + u64 split_message; + u64 spdm_structure; +#define XGE_HAL_SPDM_MAX_ENTRIES(spdm_structure) (u16)(spdm_structure >> 48) +#define XGE_HAL_SPDM_INT_QW_PER_ENTRY(spdm_structure) \ + (u8)((spdm_structure >> 40) & 0xff) +#define XGE_HAL_SPDM_PCI_QW_PER_ENTRY(spdm_structure) \ + (u8)((spdm_structure >> 32) & 0xff) + + u64 txdw_ptr_cnt_0; + u64 txdw_ptr_cnt_1; + u64 txdw_ptr_cnt_2; + u64 txdw_ptr_cnt_3; + u64 txdw_ptr_cnt_4; + u64 txdw_ptr_cnt_5; + u64 txdw_ptr_cnt_6; + u64 txdw_ptr_cnt_7; + u64 rxdw_cnt_ring_0; + u64 rxdw_cnt_ring_1; + u64 rxdw_cnt_ring_2; + u64 rxdw_cnt_ring_3; + u64 rxdw_cnt_ring_4; + u64 rxdw_cnt_ring_5; + u64 rxdw_cnt_ring_6; + u64 rxdw_cnt_ring_7; + + u8 unused8[0x410]; + +/* TxDMA registers */ + u64 txdma_int_status; + u64 txdma_int_mask; +#define XGE_HAL_TXDMA_PFC_INT BIT(0) +#define XGE_HAL_TXDMA_TDA_INT BIT(1) +#define XGE_HAL_TXDMA_PCC_INT BIT(2) +#define XGE_HAL_TXDMA_TTI_INT BIT(3) +#define XGE_HAL_TXDMA_LSO_INT BIT(4) +#define XGE_HAL_TXDMA_TPA_INT BIT(5) +#define XGE_HAL_TXDMA_SM_INT BIT(6) + u64 pfc_err_reg; +#define XGE_HAL_PFC_ECC_SG_ERR BIT(7) +#define XGE_HAL_PFC_ECC_DB_ERR BIT(15) +#define XGE_HAL_PFC_SM_ERR_ALARM BIT(23) +#define XGE_HAL_PFC_MISC_0_ERR BIT(31) +#define XGE_HAL_PFC_MISC_1_ERR BIT(32) +#define XGE_HAL_PFC_PCIX_ERR BIT(39) + u64 pfc_err_mask; + u64 pfc_err_alarm; + + u64 tda_err_reg; +#define XGE_HAL_TDA_Fn_ECC_SG_ERR vBIT(0xff,0,8) +#define XGE_HAL_TDA_Fn_ECC_DB_ERR vBIT(0xff,8,8) +#define XGE_HAL_TDA_SM0_ERR_ALARM BIT(22) +#define XGE_HAL_TDA_SM1_ERR_ALARM BIT(23) +#define XGE_HAL_TDA_PCIX_ERR BIT(39) + u64 tda_err_mask; + u64 tda_err_alarm; + + u64 pcc_err_reg; +#define XGE_HAL_PCC_FB_ECC_SG_ERR vBIT(0xFF,0,8) +#define XGE_HAL_PCC_TXB_ECC_SG_ERR vBIT(0xFF,8,8) +#define XGE_HAL_PCC_FB_ECC_DB_ERR vBIT(0xFF,16, 8) +#define XGE_HAL_PCC_TXB_ECC_DB_ERR vBIT(0xff,24,8) +#define XGE_HAL_PCC_SM_ERR_ALARM vBIT(0xff,32,8) +#define XGE_HAL_PCC_WR_ERR_ALARM vBIT(0xff,40,8) +#define XGE_HAL_PCC_N_SERR vBIT(0xff,48,8) +#define XGE_HAL_PCC_ENABLE_FOUR vBIT(0x0F,0,8) +#define XGE_HAL_PCC_6_COF_OV_ERR BIT(56) +#define XGE_HAL_PCC_7_COF_OV_ERR BIT(57) +#define XGE_HAL_PCC_6_LSO_OV_ERR BIT(58) +#define XGE_HAL_PCC_7_LSO_OV_ERR BIT(59) + u64 pcc_err_mask; + u64 pcc_err_alarm; + + u64 tti_err_reg; +#define XGE_HAL_TTI_ECC_SG_ERR BIT(7) +#define XGE_HAL_TTI_ECC_DB_ERR BIT(15) +#define XGE_HAL_TTI_SM_ERR_ALARM BIT(23) + u64 tti_err_mask; + u64 tti_err_alarm; + + u64 lso_err_reg; +#define XGE_HAL_LSO6_SEND_OFLOW BIT(12) +#define XGE_HAL_LSO7_SEND_OFLOW BIT(13) +#define XGE_HAL_LSO6_ABORT BIT(14) +#define XGE_HAL_LSO7_ABORT BIT(15) +#define XGE_HAL_LSO6_SM_ERR_ALARM BIT(22) +#define XGE_HAL_LSO7_SM_ERR_ALARM BIT(23) + u64 lso_err_mask; + u64 lso_err_alarm; + + u64 tpa_err_reg; +#define XGE_HAL_TPA_TX_FRM_DROP BIT(7) +#define XGE_HAL_TPA_SM_ERR_ALARM BIT(23) + u64 tpa_err_mask; + u64 tpa_err_alarm; + + u64 sm_err_reg; +#define XGE_HAL_SM_SM_ERR_ALARM BIT(15) + u64 sm_err_mask; + u64 sm_err_alarm; + + u8 unused9[0x100 - 0xB8]; + +/* TxDMA arbiter */ + u64 tx_dma_wrap_stat; + +/* Tx FIFO controller */ +#define XGE_HAL_X_MAX_FIFOS 8 +#define XGE_HAL_X_FIFO_MAX_LEN 0x1FFF /*8191 */ + u64 tx_fifo_partition_0; +#define XGE_HAL_TX_FIFO_PARTITION_EN BIT(0) +#define XGE_HAL_TX_FIFO_PARTITION_0_PRI(val) vBIT(val,5,3) +#define XGE_HAL_TX_FIFO_PARTITION_0_LEN(val) vBIT(val,19,13) +#define XGE_HAL_TX_FIFO_PARTITION_1_PRI(val) vBIT(val,37,3) +#define XGE_HAL_TX_FIFO_PARTITION_1_LEN(val) vBIT(val,51,13 ) + + u64 tx_fifo_partition_1; +#define XGE_HAL_TX_FIFO_PARTITION_2_PRI(val) vBIT(val,5,3) +#define XGE_HAL_TX_FIFO_PARTITION_2_LEN(val) vBIT(val,19,13) +#define XGE_HAL_TX_FIFO_PARTITION_3_PRI(val) vBIT(val,37,3) +#define XGE_HAL_TX_FIFO_PARTITION_3_LEN(val) vBIT(val,51,13) + + u64 tx_fifo_partition_2; +#define XGE_HAL_TX_FIFO_PARTITION_4_PRI(val) vBIT(val,5,3) +#define XGE_HAL_TX_FIFO_PARTITION_4_LEN(val) vBIT(val,19,13) +#define XGE_HAL_TX_FIFO_PARTITION_5_PRI(val) vBIT(val,37,3) +#define XGE_HAL_TX_FIFO_PARTITION_5_LEN(val) vBIT(val,51,13) + + u64 tx_fifo_partition_3; +#define XGE_HAL_TX_FIFO_PARTITION_6_PRI(val) vBIT(val,5,3) +#define XGE_HAL_TX_FIFO_PARTITION_6_LEN(val) vBIT(val,19,13) +#define XGE_HAL_TX_FIFO_PARTITION_7_PRI(val) vBIT(val,37,3) +#define XGE_HAL_TX_FIFO_PARTITION_7_LEN(val) vBIT(val,51,13) + +#define XGE_HAL_TX_FIFO_PARTITION_PRI_0 0 /* highest */ +#define XGE_HAL_TX_FIFO_PARTITION_PRI_1 1 +#define XGE_HAL_TX_FIFO_PARTITION_PRI_2 2 +#define XGE_HAL_TX_FIFO_PARTITION_PRI_3 3 +#define XGE_HAL_TX_FIFO_PARTITION_PRI_4 4 +#define XGE_HAL_TX_FIFO_PARTITION_PRI_5 5 +#define XGE_HAL_TX_FIFO_PARTITION_PRI_6 6 +#define XGE_HAL_TX_FIFO_PARTITION_PRI_7 7 /* lowest */ + + u64 tx_w_round_robin_0; + u64 tx_w_round_robin_1; + u64 tx_w_round_robin_2; + u64 tx_w_round_robin_3; + u64 tx_w_round_robin_4; + + u64 tti_command_mem; +#define XGE_HAL_TTI_CMD_MEM_WE BIT(7) +#define XGE_HAL_TTI_CMD_MEM_STROBE_NEW_CMD BIT(15) +#define XGE_HAL_TTI_CMD_MEM_STROBE_BEING_EXECUTED BIT(15) +#define XGE_HAL_TTI_CMD_MEM_OFFSET(n) vBIT(n,26,6) + + u64 tti_data1_mem; +#define XGE_HAL_TTI_DATA1_MEM_TX_TIMER_VAL(n) vBIT(n,6,26) +#define XGE_HAL_TTI_DATA1_MEM_TX_TIMER_AC_CI(n) vBIT(n,38,2) +#define XGE_HAL_TTI_DATA1_MEM_TX_TIMER_AC_EN BIT(38) +#define XGE_HAL_TTI_DATA1_MEM_TX_TIMER_CI_EN BIT(39) +#define XGE_HAL_TTI_DATA1_MEM_TX_URNG_A(n) vBIT(n,41,7) +#define XGE_HAL_TTI_DATA1_MEM_TX_URNG_B(n) vBIT(n,49,7) +#define XGE_HAL_TTI_DATA1_MEM_TX_URNG_C(n) vBIT(n,57,7) + + u64 tti_data2_mem; +#define XGE_HAL_TTI_DATA2_MEM_TX_UFC_A(n) vBIT(n,0,16) +#define XGE_HAL_TTI_DATA2_MEM_TX_UFC_B(n) vBIT(n,16,16) +#define XGE_HAL_TTI_DATA2_MEM_TX_UFC_C(n) vBIT(n,32,16) +#define XGE_HAL_TTI_DATA2_MEM_TX_UFC_D(n) vBIT(n,48,16) + +/* Tx Protocol assist */ + u64 tx_pa_cfg; +#define XGE_HAL_TX_PA_CFG_IGNORE_FRM_ERR BIT(1) +#define XGE_HAL_TX_PA_CFG_IGNORE_SNAP_OUI BIT(2) +#define XGE_HAL_TX_PA_CFG_IGNORE_LLC_CTRL BIT(3) +#define XGE_HAL_TX_PA_CFG_IGNORE_L2_ERR BIT(6) + +/* Recent add, used only debug purposes. */ + u64 pcc_enable; + + u64 pfc_monitor_0; + u64 pfc_monitor_1; + u64 pfc_monitor_2; + u64 pfc_monitor_3; + u64 txd_ownership_ctrl; + u64 pfc_read_cntrl; + u64 pfc_read_data; + + u8 unused10[0x1700 - 0x11B0]; + + u64 txdma_debug_ctrl; + + u8 unused11[0x1800 - 0x1708]; + +/* RxDMA Registers */ + u64 rxdma_int_status; +#define XGE_HAL_RXDMA_RC_INT BIT(0) +#define XGE_HAL_RXDMA_RPA_INT BIT(1) +#define XGE_HAL_RXDMA_RDA_INT BIT(2) +#define XGE_HAL_RXDMA_RTI_INT BIT(3) + + u64 rxdma_int_mask; +#define XGE_HAL_RXDMA_INT_RC_INT_M BIT(0) +#define XGE_HAL_RXDMA_INT_RPA_INT_M BIT(1) +#define XGE_HAL_RXDMA_INT_RDA_INT_M BIT(2) +#define XGE_HAL_RXDMA_INT_RTI_INT_M BIT(3) + + u64 rda_err_reg; +#define XGE_HAL_RDA_RXDn_ECC_SG_ERR vBIT(0xFF,0,8) +#define XGE_HAL_RDA_RXDn_ECC_DB_ERR vBIT(0xFF,8,8) +#define XGE_HAL_RDA_FRM_ECC_SG_ERR BIT(23) +#define XGE_HAL_RDA_FRM_ECC_DB_N_AERR BIT(31) +#define XGE_HAL_RDA_SM1_ERR_ALARM BIT(38) +#define XGE_HAL_RDA_SM0_ERR_ALARM BIT(39) +#define XGE_HAL_RDA_MISC_ERR BIT(47) +#define XGE_HAL_RDA_PCIX_ERR BIT(55) +#define XGE_HAL_RDA_RXD_ECC_DB_SERR BIT(63) + u64 rda_err_mask; + u64 rda_err_alarm; + + u64 rc_err_reg; +#define XGE_HAL_RC_PRCn_ECC_SG_ERR vBIT(0xFF,0,8) +#define XGE_HAL_RC_PRCn_ECC_DB_ERR vBIT(0xFF,8,8) +#define XGE_HAL_RC_FTC_ECC_SG_ERR BIT(23) +#define XGE_HAL_RC_FTC_ECC_DB_ERR BIT(31) +#define XGE_HAL_RC_PRCn_SM_ERR_ALARM vBIT(0xFF,32,8) +#define XGE_HAL_RC_FTC_SM_ERR_ALARM BIT(47) +#define XGE_HAL_RC_RDA_FAIL_WR_Rn vBIT(0xFF,48,8) + u64 rc_err_mask; + u64 rc_err_alarm; + + u64 prc_pcix_err_reg; +#define XGE_HAL_PRC_PCI_AB_RD_Rn vBIT(0xFF,0,8) +#define XGE_HAL_PRC_PCI_DP_RD_Rn vBIT(0xFF,8,8) +#define XGE_HAL_PRC_PCI_AB_WR_Rn vBIT(0xFF,16,8) +#define XGE_HAL_PRC_PCI_DP_WR_Rn vBIT(0xFF,24,8) +#define XGE_HAL_PRC_PCI_AB_F_WR_Rn vBIT(0xFF,32,8) +#define XGE_HAL_PRC_PCI_DP_F_WR_Rn vBIT(0xFF,40,8) + u64 prc_pcix_err_mask; + u64 prc_pcix_err_alarm; + + u64 rpa_err_reg; +#define XGE_HAL_RPA_ECC_SG_ERR BIT(7) +#define XGE_HAL_RPA_ECC_DB_ERR BIT(15) +#define XGE_HAL_RPA_FLUSH_REQUEST BIT(22) +#define XGE_HAL_RPA_SM_ERR_ALARM BIT(23) +#define XGE_HAL_RPA_CREDIT_ERR BIT(31) + u64 rpa_err_mask; + u64 rpa_err_alarm; + + u64 rti_err_reg; +#define XGE_HAL_RTI_ECC_SG_ERR BIT(7) +#define XGE_HAL_RTI_ECC_DB_ERR BIT(15) +#define XGE_HAL_RTI_SM_ERR_ALARM BIT(23) + u64 rti_err_mask; + u64 rti_err_alarm; + + u8 unused12[0x100 - 0x88]; + +/* DMA arbiter */ + u64 rx_queue_priority; +#define XGE_HAL_RX_QUEUE_0_PRIORITY(val) vBIT(val,5,3) +#define XGE_HAL_RX_QUEUE_1_PRIORITY(val) vBIT(val,13,3) +#define XGE_HAL_RX_QUEUE_2_PRIORITY(val) vBIT(val,21,3) +#define XGE_HAL_RX_QUEUE_3_PRIORITY(val) vBIT(val,29,3) +#define XGE_HAL_RX_QUEUE_4_PRIORITY(val) vBIT(val,37,3) +#define XGE_HAL_RX_QUEUE_5_PRIORITY(val) vBIT(val,45,3) +#define XGE_HAL_RX_QUEUE_6_PRIORITY(val) vBIT(val,53,3) +#define XGE_HAL_RX_QUEUE_7_PRIORITY(val) vBIT(val,61,3) + +#define XGE_HAL_RX_QUEUE_PRI_0 0 /* highest */ +#define XGE_HAL_RX_QUEUE_PRI_1 1 +#define XGE_HAL_RX_QUEUE_PRI_2 2 +#define XGE_HAL_RX_QUEUE_PRI_3 3 +#define XGE_HAL_RX_QUEUE_PRI_4 4 +#define XGE_HAL_RX_QUEUE_PRI_5 5 +#define XGE_HAL_RX_QUEUE_PRI_6 6 +#define XGE_HAL_RX_QUEUE_PRI_7 7 /* lowest */ + + u64 rx_w_round_robin_0; + u64 rx_w_round_robin_1; + u64 rx_w_round_robin_2; + u64 rx_w_round_robin_3; + u64 rx_w_round_robin_4; + + /* Per-ring controller regs */ +#define XGE_HAL_RX_MAX_RINGS 8 + u64 prc_rxd0_n[XGE_HAL_RX_MAX_RINGS]; + u64 prc_ctrl_n[XGE_HAL_RX_MAX_RINGS]; +#define XGE_HAL_PRC_CTRL_RC_ENABLED BIT(7) +#define XGE_HAL_PRC_CTRL_RING_MODE (BIT(14)|BIT(15)) +#define XGE_HAL_PRC_CTRL_RING_MODE_1 vBIT(0,14,2) +#define XGE_HAL_PRC_CTRL_RING_MODE_3 vBIT(1,14,2) +#define XGE_HAL_PRC_CTRL_RING_MODE_5 vBIT(2,14,2) +#define XGE_HAL_PRC_CTRL_RING_MODE_x vBIT(3,14,2) +#define XGE_HAL_PRC_CTRL_NO_SNOOP(n) vBIT(n,22,2) +#define XGE_HAL_PRC_CTRL_RTH_DISABLE BIT(31) +#define XGE_HAL_PRC_CTRL_BIMODAL_INTERRUPT BIT(37) +#define XGE_HAL_PRC_CTRL_GROUP_READS BIT(38) +#define XGE_HAL_PRC_CTRL_RXD_BACKOFF_INTERVAL(val) vBIT(val,40,24) + + u64 prc_alarm_action; +#define XGE_HAL_PRC_ALARM_ACTION_RR_R0_STOP BIT(3) +#define XGE_HAL_PRC_ALARM_ACTION_RW_R0_STOP BIT(7) +#define XGE_HAL_PRC_ALARM_ACTION_RR_R1_STOP BIT(11) +#define XGE_HAL_PRC_ALARM_ACTION_RW_R1_STOP BIT(15) +#define XGE_HAL_PRC_ALARM_ACTION_RR_R2_STOP BIT(19) +#define XGE_HAL_PRC_ALARM_ACTION_RW_R2_STOP BIT(23) +#define XGE_HAL_PRC_ALARM_ACTION_RR_R3_STOP BIT(27) +#define XGE_HAL_PRC_ALARM_ACTION_RW_R3_STOP BIT(31) +#define XGE_HAL_PRC_ALARM_ACTION_RR_R4_STOP BIT(35) +#define XGE_HAL_PRC_ALARM_ACTION_RW_R4_STOP BIT(39) +#define XGE_HAL_PRC_ALARM_ACTION_RR_R5_STOP BIT(43) +#define XGE_HAL_PRC_ALARM_ACTION_RW_R5_STOP BIT(47) +#define XGE_HAL_PRC_ALARM_ACTION_RR_R6_STOP BIT(51) +#define XGE_HAL_PRC_ALARM_ACTION_RW_R6_STOP BIT(55) +#define XGE_HAL_PRC_ALARM_ACTION_RR_R7_STOP BIT(59) +#define XGE_HAL_PRC_ALARM_ACTION_RW_R7_STOP BIT(63) + +/* Receive traffic interrupts */ + u64 rti_command_mem; +#define XGE_HAL_RTI_CMD_MEM_WE BIT(7) +#define XGE_HAL_RTI_CMD_MEM_STROBE BIT(15) +#define XGE_HAL_RTI_CMD_MEM_STROBE_NEW_CMD BIT(15) +#define XGE_HAL_RTI_CMD_MEM_STROBE_CMD_BEING_EXECUTED BIT(15) +#define XGE_HAL_RTI_CMD_MEM_OFFSET(n) vBIT(n,29,3) + + u64 rti_data1_mem; +#define XGE_HAL_RTI_DATA1_MEM_RX_TIMER_VAL(n) vBIT(n,3,29) +#define XGE_HAL_RTI_DATA1_MEM_RX_TIMER_AC_EN BIT(38) +#define XGE_HAL_RTI_DATA1_MEM_RX_TIMER_CI_EN BIT(39) +#define XGE_HAL_RTI_DATA1_MEM_RX_URNG_A(n) vBIT(n,41,7) +#define XGE_HAL_RTI_DATA1_MEM_RX_URNG_B(n) vBIT(n,49,7) +#define XGE_HAL_RTI_DATA1_MEM_RX_URNG_C(n) vBIT(n,57,7) + + u64 rti_data2_mem; +#define XGE_HAL_RTI_DATA2_MEM_RX_UFC_A(n) vBIT(n,0,16) +#define XGE_HAL_RTI_DATA2_MEM_RX_UFC_B(n) vBIT(n,16,16) +#define XGE_HAL_RTI_DATA2_MEM_RX_UFC_C(n) vBIT(n,32,16) +#define XGE_HAL_RTI_DATA2_MEM_RX_UFC_D(n) vBIT(n,48,16) + + u64 rx_pa_cfg; +#define XGE_HAL_RX_PA_CFG_IGNORE_FRM_ERR BIT(1) +#define XGE_HAL_RX_PA_CFG_IGNORE_SNAP_OUI BIT(2) +#define XGE_HAL_RX_PA_CFG_IGNORE_LLC_CTRL BIT(3) +#define XGE_HAL_RX_PA_CFG_SCATTER_MODE(n) vBIT(n,6,1) +#define XGE_HAL_RX_PA_CFG_STRIP_VLAN_TAG_MODE(n) vBIT(n,15,1) + + u8 unused13_0[0x8]; + + u64 ring_bump_counter1; + u64 ring_bump_counter2; +#define XGE_HAL_RING_BUMP_CNT(i, val) (u16)(val >> (48 - (16 * (i % 4)))) + + u8 unused13[0x700 - 0x1f0]; + + u64 rxdma_debug_ctrl; + + u8 unused14[0x2000 - 0x1f08]; + +/* Media Access Controller Register */ + u64 mac_int_status; + u64 mac_int_mask; +#define XGE_HAL_MAC_INT_STATUS_TMAC_INT BIT(0) +#define XGE_HAL_MAC_INT_STATUS_RMAC_INT BIT(1) + + u64 mac_tmac_err_reg; +#define XGE_HAL_TMAC_ECC_DB_ERR BIT(15) +#define XGE_HAL_TMAC_TX_BUF_OVRN BIT(23) +#define XGE_HAL_TMAC_TX_CRI_ERR BIT(31) +#define XGE_HAL_TMAC_TX_SM_ERR BIT(39) + u64 mac_tmac_err_mask; + u64 mac_tmac_err_alarm; + + u64 mac_rmac_err_reg; +#define XGE_HAL_RMAC_RX_BUFF_OVRN BIT(0) +#define XGE_HAL_RMAC_RTH_SPDM_ECC_SG_ERR BIT(0) +#define XGE_HAL_RMAC_RTS_ECC_DB_ERR BIT(0) +#define XGE_HAL_RMAC_ECC_DB_ERR BIT(0) +#define XGE_HAL_RMAC_RTH_SPDM_ECC_DB_ERR BIT(0) +#define XGE_HAL_RMAC_LINK_STATE_CHANGE_INT BIT(0) +#define XGE_HAL_RMAC_RX_SM_ERR BIT(39) + u64 mac_rmac_err_mask; + u64 mac_rmac_err_alarm; + + u8 unused15[0x100 - 0x40]; + + u64 mac_cfg; +#define XGE_HAL_MAC_CFG_TMAC_ENABLE BIT(0) +#define XGE_HAL_MAC_CFG_RMAC_ENABLE BIT(1) +#define XGE_HAL_MAC_CFG_LAN_NOT_WAN BIT(2) +#define XGE_HAL_MAC_CFG_TMAC_LOOPBACK BIT(3) +#define XGE_HAL_MAC_CFG_TMAC_APPEND_PAD BIT(4) +#define XGE_HAL_MAC_CFG_RMAC_STRIP_FCS BIT(5) +#define XGE_HAL_MAC_CFG_RMAC_STRIP_PAD BIT(6) +#define XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE BIT(7) +#define XGE_HAL_MAC_RMAC_DISCARD_PFRM BIT(8) +#define XGE_HAL_MAC_RMAC_BCAST_ENABLE BIT(9) +#define XGE_HAL_MAC_RMAC_ALL_ADDR_ENABLE BIT(10) +#define XGE_HAL_MAC_RMAC_INVLD_IPG_THR(val) vBIT(val,16,8) + + u64 tmac_avg_ipg; +#define XGE_HAL_TMAC_AVG_IPG(val) vBIT(val,0,8) + + u64 rmac_max_pyld_len; +#define XGE_HAL_RMAC_MAX_PYLD_LEN(val) vBIT(val,2,14) + + u64 rmac_err_cfg; +#define XGE_HAL_RMAC_ERR_FCS BIT(0) +#define XGE_HAL_RMAC_ERR_FCS_ACCEPT BIT(1) +#define XGE_HAL_RMAC_ERR_TOO_LONG BIT(1) +#define XGE_HAL_RMAC_ERR_TOO_LONG_ACCEPT BIT(1) +#define XGE_HAL_RMAC_ERR_RUNT BIT(2) +#define XGE_HAL_RMAC_ERR_RUNT_ACCEPT BIT(2) +#define XGE_HAL_RMAC_ERR_LEN_MISMATCH BIT(3) +#define XGE_HAL_RMAC_ERR_LEN_MISMATCH_ACCEPT BIT(3) + + u64 rmac_cfg_key; +#define XGE_HAL_RMAC_CFG_KEY(val) vBIT(val,0,16) + +#define XGE_HAL_MAX_MAC_ADDRESSES 64 +#define XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET 63 +#define XGE_HAL_MAX_MAC_ADDRESSES_HERC 256 +#define XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET_HERC 255 + + u64 rmac_addr_cmd_mem; +#define XGE_HAL_RMAC_ADDR_CMD_MEM_WE BIT(7) +#define XGE_HAL_RMAC_ADDR_CMD_MEM_RD 0 +#define XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD BIT(15) +#define XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING BIT(15) +#define XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET(n) vBIT(n,26,6) + + u64 rmac_addr_data0_mem; +#define XGE_HAL_RMAC_ADDR_DATA0_MEM_ADDR(n) vBIT(n,0,48) +#define XGE_HAL_RMAC_ADDR_DATA0_MEM_USER BIT(48) + + u64 rmac_addr_data1_mem; +#define XGE_HAL_RMAC_ADDR_DATA1_MEM_MASK(n) vBIT(n,0,48) + + u8 unused16[0x8]; + +/* + u64 rmac_addr_cfg; +#define XGE_HAL_RMAC_ADDR_UCASTn_EN(n) mBIT(0)_n(n) +#define XGE_HAL_RMAC_ADDR_MCASTn_EN(n) mBIT(0)_n(n) +#define XGE_HAL_RMAC_ADDR_BCAST_EN vBIT(0)_48 +#define XGE_HAL_RMAC_ADDR_ALL_ADDR_EN vBIT(0)_49 +*/ + u64 tmac_ipg_cfg; + + u64 rmac_pause_cfg; +#define XGE_HAL_RMAC_PAUSE_GEN_EN BIT(0) +#define XGE_HAL_RMAC_PAUSE_RCV_EN BIT(1) +#define XGE_HAL_RMAC_PAUSE_HG_PTIME_DEF vBIT(0xFFFF,16,16) +#define XGE_HAL_RMAC_PAUSE_HG_PTIME(val) vBIT(val,16,16) + + u64 rmac_red_cfg; + + u64 rmac_red_rate_q0q3; + u64 rmac_red_rate_q4q7; + + u64 mac_link_util; +#define XGE_HAL_MAC_TX_LINK_UTIL vBIT(0xFE,1,7) +#define XGE_HAL_MAC_TX_LINK_UTIL_DISABLE vBIT(0xF, 8,4) +#define XGE_HAL_MAC_TX_LINK_UTIL_VAL( n ) vBIT(n,8,4) +#define XGE_HAL_MAC_RX_LINK_UTIL vBIT(0xFE,33,7) +#define XGE_HAL_MAC_RX_LINK_UTIL_DISABLE vBIT(0xF,40,4) +#define XGE_HAL_MAC_RX_LINK_UTIL_VAL( n ) vBIT(n,40,4) + +#define XGE_HAL_MAC_LINK_UTIL_DISABLE (XGE_HAL_MAC_TX_LINK_UTIL_DISABLE | \ + XGE_HAL_MAC_RX_LINK_UTIL_DISABLE) + + u64 rmac_invalid_ipg; + +/* rx traffic steering */ +#define XGE_HAL_MAC_RTS_FRM_LEN_SET(len) vBIT(len,2,14) + u64 rts_frm_len_n[8]; + + u64 rts_qos_steering; + +#define XGE_HAL_MAX_DIX_MAP 4 + u64 rts_dix_map_n[XGE_HAL_MAX_DIX_MAP]; +#define XGE_HAL_RTS_DIX_MAP_ETYPE(val) vBIT(val,0,16) +#define XGE_HAL_RTS_DIX_MAP_SCW(val) BIT(val,21) + + u64 rts_q_alternates; + u64 rts_default_q; +#define XGE_HAL_RTS_DEFAULT_Q(n) vBIT(n,5,3) + + u64 rts_ctrl; +#define XGE_HAL_RTS_CTRL_IGNORE_SNAP_OUI BIT(2) +#define XGE_HAL_RTS_CTRL_IGNORE_LLC_CTRL BIT(3) +#define XGE_HAL_RTS_CTRL_ENHANCED_MODE BIT(7) + + u64 rts_pn_cam_ctrl; +#define XGE_HAL_RTS_PN_CAM_CTRL_WE BIT(7) +#define XGE_HAL_RTS_PN_CAM_CTRL_STROBE_NEW_CMD BIT(15) +#define XGE_HAL_RTS_PN_CAM_CTRL_STROBE_BEING_EXECUTED BIT(15) +#define XGE_HAL_RTS_PN_CAM_CTRL_OFFSET(n) vBIT(n,24,8) + u64 rts_pn_cam_data; +#define XGE_HAL_RTS_PN_CAM_DATA_TCP_SELECT BIT(7) +#define XGE_HAL_RTS_PN_CAM_DATA_PORT(val) vBIT(val,8,16) +#define XGE_HAL_RTS_PN_CAM_DATA_SCW(val) vBIT(val,24,8) + + u64 rts_ds_mem_ctrl; +#define XGE_HAL_RTS_DS_MEM_CTRL_WE BIT(7) +#define XGE_HAL_RTS_DS_MEM_CTRL_STROBE_NEW_CMD BIT(15) +#define XGE_HAL_RTS_DS_MEM_CTRL_STROBE_CMD_BEING_EXECUTED BIT(15) +#define XGE_HAL_RTS_DS_MEM_CTRL_OFFSET(n) vBIT(n,26,6) + u64 rts_ds_mem_data; +#define XGE_HAL_RTS_DS_MEM_DATA(n) vBIT(n,0,8) + + u8 unused16_1[0x308 - 0x220]; + + u64 rts_vid_mem_ctrl; + u64 rts_vid_mem_data; + u64 rts_p0_p3_map; + u64 rts_p4_p7_map; + u64 rts_p8_p11_map; + u64 rts_p12_p15_map; + + u64 rts_mac_cfg; +#define XGE_HAL_RTS_MAC_SECT0_EN BIT(0) +#define XGE_HAL_RTS_MAC_SECT1_EN BIT(1) +#define XGE_HAL_RTS_MAC_SECT2_EN BIT(2) +#define XGE_HAL_RTS_MAC_SECT3_EN BIT(3) +#define XGE_HAL_RTS_MAC_SECT4_EN BIT(4) +#define XGE_HAL_RTS_MAC_SECT5_EN BIT(5) +#define XGE_HAL_RTS_MAC_SECT6_EN BIT(6) +#define XGE_HAL_RTS_MAC_SECT7_EN BIT(7) + + u8 unused16_2[0x380 - 0x340]; + + u64 rts_rth_cfg; +#define XGE_HAL_RTS_RTH_EN BIT(3) +#define XGE_HAL_RTS_RTH_BUCKET_SIZE(n) vBIT(n,4,4) +#define XGE_HAL_RTS_RTH_ALG_SEL_MS BIT(11) +#define XGE_HAL_RTS_RTH_TCP_IPV4_EN BIT(15) +#define XGE_HAL_RTS_RTH_UDP_IPV4_EN BIT(19) +#define XGE_HAL_RTS_RTH_IPV4_EN BIT(23) +#define XGE_HAL_RTS_RTH_TCP_IPV6_EN BIT(27) +#define XGE_HAL_RTS_RTH_UDP_IPV6_EN BIT(31) +#define XGE_HAL_RTS_RTH_IPV6_EN BIT(35) +#define XGE_HAL_RTS_RTH_TCP_IPV6_EX_EN BIT(39) +#define XGE_HAL_RTS_RTH_UDP_IPV6_EX_EN BIT(43) +#define XGE_HAL_RTS_RTH_IPV6_EX_EN BIT(47) + + u64 rts_rth_map_mem_ctrl; +#define XGE_HAL_RTS_RTH_MAP_MEM_CTRL_WE BIT(7) +#define XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE BIT(15) +#define XGE_HAL_RTS_RTH_MAP_MEM_CTRL_OFFSET(n) vBIT(n,24,8) + + u64 rts_rth_map_mem_data; +#define XGE_HAL_RTS_RTH_MAP_MEM_DATA_ENTRY_EN BIT(3) +#define XGE_HAL_RTS_RTH_MAP_MEM_DATA(n) vBIT(n,5,3) + + u64 rts_rth_spdm_mem_ctrl; +#define XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_STROBE BIT(15) +#define XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_LINE_SEL(n) vBIT(n,21,3) +#define XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_OFFSET(n) vBIT(n,24,8) + + u64 rts_rth_spdm_mem_data; + + u64 rts_rth_jhash_cfg; +#define XGE_HAL_RTS_RTH_JHASH_GOLDEN(n) vBIT(n,0,32) +#define XGE_HAL_RTS_RTH_JHASH_INIT_VAL(n) vBIT(n,32,32) + + u64 rts_rth_hash_mask[5]; /* rth mask's 0...4 */ + u64 rts_rth_hash_mask_5; +#define XGE_HAL_RTH_HASH_MASK_5(n) vBIT(n,0,32) + + u64 rts_rth_status; +#define XGE_HAL_RTH_STATUS_SPDM_USE_L4 BIT(3) + + u8 unused17[0x400 - 0x3E8]; + + u64 rmac_red_fine_q0q3; + u64 rmac_red_fine_q4q7; + u64 rmac_pthresh_cross; + u64 rmac_rthresh_cross; + u64 rmac_pnum_range[32]; + + u64 rmac_mp_crc_0; + u64 rmac_mp_mask_a_0; + u64 rmac_mp_mask_b_0; + + u64 rmac_mp_crc_1; + u64 rmac_mp_mask_a_1; + u64 rmac_mp_mask_b_1; + + u64 rmac_mp_crc_2; + u64 rmac_mp_mask_a_2; + u64 rmac_mp_mask_b_2; + + u64 rmac_mp_crc_3; + u64 rmac_mp_mask_a_3; + u64 rmac_mp_mask_b_3; + + u64 rmac_mp_crc_4; + u64 rmac_mp_mask_a_4; + u64 rmac_mp_mask_b_4; + + u64 rmac_mp_crc_5; + u64 rmac_mp_mask_a_5; + u64 rmac_mp_mask_b_5; + + u64 rmac_mp_crc_6; + u64 rmac_mp_mask_a_6; + u64 rmac_mp_mask_b_6; + + u64 rmac_mp_crc_7; + u64 rmac_mp_mask_a_7; + u64 rmac_mp_mask_b_7; + + u64 mac_ctrl; + u64 activity_control; + + u8 unused17_2[0x700 - 0x5F0]; + + u64 mac_debug_ctrl; +#define XGE_HAL_MAC_DBG_ACTIVITY_VALUE 0x411040400000000ULL + + u8 unused18[0x2800 - 0x2708]; + +/* memory controller registers */ + u64 mc_int_status; +#define XGE_HAL_MC_INT_STATUS_MC_INT BIT(0) + u64 mc_int_mask; +#define XGE_HAL_MC_INT_MASK_MC_INT BIT(0) + + u64 mc_err_reg; +#define XGE_HAL_MC_ERR_REG_ITQ_ECC_SG_ERR_L BIT(2) /* non-Xena */ +#define XGE_HAL_MC_ERR_REG_ITQ_ECC_SG_ERR_U BIT(3) /* non-Xena */ +#define XGE_HAL_MC_ERR_REG_RLD_ECC_SG_ERR_L BIT(4) /* non-Xena */ +#define XGE_HAL_MC_ERR_REG_RLD_ECC_SG_ERR_U BIT(5) /* non-Xena */ +#define XGE_HAL_MC_ERR_REG_ETQ_ECC_SG_ERR_L BIT(6) +#define XGE_HAL_MC_ERR_REG_ETQ_ECC_SG_ERR_U BIT(7) +#define XGE_HAL_MC_ERR_REG_ITQ_ECC_DB_ERR_L BIT(10) /* non-Xena */ +#define XGE_HAL_MC_ERR_REG_ITQ_ECC_DB_ERR_U BIT(11) /* non-Xena */ +#define XGE_HAL_MC_ERR_REG_RLD_ECC_DB_ERR_L BIT(12) /* non-Xena */ +#define XGE_HAL_MC_ERR_REG_RLD_ECC_DB_ERR_U BIT(13) /* non-Xena */ +#define XGE_HAL_MC_ERR_REG_ETQ_ECC_DB_ERR_L BIT(14) +#define XGE_HAL_MC_ERR_REG_ETQ_ECC_DB_ERR_U BIT(15) +#define XGE_HAL_MC_ERR_REG_MIRI_ECC_SG_ERR_0 BIT(17) +#define XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_0 BIT(18) /* Xena: reset */ +#define XGE_HAL_MC_ERR_REG_MIRI_ECC_SG_ERR_1 BIT(19) +#define XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_1 BIT(20) /* Xena: reset */ +#define XGE_HAL_MC_ERR_REG_MIRI_CRI_ERR_0 BIT(22) +#define XGE_HAL_MC_ERR_REG_MIRI_CRI_ERR_1 BIT(23) +#define XGE_HAL_MC_ERR_REG_SM_ERR BIT(31) +#define XGE_HAL_MC_ERR_REG_PL_LOCK_N BIT(39) + + u64 mc_err_mask; + u64 mc_err_alarm; + + u8 unused19[0x100 - 0x28]; + +/* MC configuration */ + u64 rx_queue_cfg; +#define XGE_HAL_RX_QUEUE_CFG_Q0_SZ(n) vBIT(n,0,8) +#define XGE_HAL_RX_QUEUE_CFG_Q1_SZ(n) vBIT(n,8,8) +#define XGE_HAL_RX_QUEUE_CFG_Q2_SZ(n) vBIT(n,16,8) +#define XGE_HAL_RX_QUEUE_CFG_Q3_SZ(n) vBIT(n,24,8) +#define XGE_HAL_RX_QUEUE_CFG_Q4_SZ(n) vBIT(n,32,8) +#define XGE_HAL_RX_QUEUE_CFG_Q5_SZ(n) vBIT(n,40,8) +#define XGE_HAL_RX_QUEUE_CFG_Q6_SZ(n) vBIT(n,48,8) +#define XGE_HAL_RX_QUEUE_CFG_Q7_SZ(n) vBIT(n,56,8) + + u64 mc_rldram_mrs; +#define XGE_HAL_MC_RLDRAM_QUEUE_SIZE_ENABLE BIT(39) +#define XGE_HAL_MC_RLDRAM_MRS_ENABLE BIT(47) + + u64 mc_rldram_interleave; + + u64 mc_pause_thresh_q0q3; + u64 mc_pause_thresh_q4q7; + + u64 mc_red_thresh_q[8]; + + u8 unused20[0x200 - 0x168]; + u64 mc_rldram_ref_per; + u8 unused21[0x220 - 0x208]; + u64 mc_rldram_test_ctrl; +#define XGE_HAL_MC_RLDRAM_TEST_MODE BIT(47) +#define XGE_HAL_MC_RLDRAM_TEST_WRITE BIT(7) +#define XGE_HAL_MC_RLDRAM_TEST_GO BIT(15) +#define XGE_HAL_MC_RLDRAM_TEST_DONE BIT(23) +#define XGE_HAL_MC_RLDRAM_TEST_PASS BIT(31) + + u8 unused22[0x240 - 0x228]; + u64 mc_rldram_test_add; + u8 unused23[0x260 - 0x248]; + u64 mc_rldram_test_d0; + u8 unused24[0x280 - 0x268]; + u64 mc_rldram_test_d1; + u8 unused25[0x300 - 0x288]; + u64 mc_rldram_test_d2; + u8 unused26_1[0x2C00 - 0x2B08]; + u64 mc_rldram_test_read_d0; + u8 unused26_2[0x20 - 0x8]; + u64 mc_rldram_test_read_d1; + u8 unused26_3[0x40 - 0x28]; + u64 mc_rldram_test_read_d2; + u8 unused26_4[0x60 - 0x48]; + u64 mc_rldram_test_add_bkg; + u8 unused26_5[0x80 - 0x68]; + u64 mc_rldram_test_d0_bkg; + u8 unused26_6[0xD00 - 0xC88]; + u64 mc_rldram_test_d1_bkg; + u8 unused26_7[0x20 - 0x8]; + u64 mc_rldram_test_d2_bkg; + u8 unused26_8[0x40 - 0x28]; + u64 mc_rldram_test_read_d0_bkg; + u8 unused26_9[0x60 - 0x48]; + u64 mc_rldram_test_read_d1_bkg; + u8 unused26_10[0x80 - 0x68]; + u64 mc_rldram_test_read_d2_bkg; + u8 unused26_11[0xE00 - 0xD88]; + u64 mc_rldram_generation; + u8 unused26_12[0x20 - 0x8]; + u64 mc_driver; + u8 unused26_13[0x40 - 0x28]; + u64 mc_rldram_ref_per_herc; +#define XGE_HAL_MC_RLDRAM_SET_REF_PERIOD(n) vBIT(n, 0, 16) + u8 unused26_14[0x660 - 0x648]; + u64 mc_rldram_mrs_herc; +#define XGE_HAL_MC_RLDRAM_MRS(n) vBIT(n, 14, 17) + u8 unused26_15[0x700 - 0x668]; + u64 mc_debug_ctrl; + + u8 unused27[0x3000 - 0x2f08]; + +/* XGXG */ + /* XGXS control registers */ + + u64 xgxs_int_status; +#define XGE_HAL_XGXS_INT_STATUS_TXGXS BIT(0) +#define XGE_HAL_XGXS_INT_STATUS_RXGXS BIT(1) + u64 xgxs_int_mask; +#define XGE_HAL_XGXS_INT_MASK_TXGXS BIT(0) +#define XGE_HAL_XGXS_INT_MASK_RXGXS BIT(1) + + u64 xgxs_txgxs_err_reg; +#define XGE_HAL_TXGXS_ECC_SG_ERR BIT(7) +#define XGE_HAL_TXGXS_ECC_DB_ERR BIT(15) +#define XGE_HAL_TXGXS_ESTORE_UFLOW BIT(31) +#define XGE_HAL_TXGXS_TX_SM_ERR BIT(39) + u64 xgxs_txgxs_err_mask; + u64 xgxs_txgxs_err_alarm; + + u64 xgxs_rxgxs_err_reg; +#define XGE_HAL_RXGXS_ESTORE_OFLOW BIT(7) +#define XGE_HAL_RXGXS_RX_SM_ERR BIT(39) + u64 xgxs_rxgxs_err_mask; + u64 xgxs_rxgxs_err_alarm; + + u64 spi_err_reg; + u64 spi_err_mask; + u64 spi_err_alarm; + + u8 unused28[0x100 - 0x58]; + + u64 xgxs_cfg; + u64 xgxs_status; + + u64 xgxs_cfg_key; + u64 xgxs_efifo_cfg; /* CHANGED */ + u64 rxgxs_ber_0; /* CHANGED */ + u64 rxgxs_ber_1; /* CHANGED */ + + u64 spi_control; + u64 spi_data; + u64 spi_write_protect; + + u8 unused29[0x80 - 0x48]; + + u64 xgxs_cfg_1; +} xge_hal_pci_bar0_t; + +/* Using this strcture to calculate offsets */ +typedef struct xge_hal_pci_config_le_t { + u16 vendor_id; // 0x00 + u16 device_id; // 0x02 + + u16 command; // 0x04 + u16 status; // 0x06 + + u8 revision; // 0x08 + u8 pciClass[3]; // 0x09 + + u8 cache_line_size; // 0x0c + u8 latency_timer; // 0x0d + u8 header_type; // 0x0e + u8 bist; // 0x0f + + u32 base_addr0_lo; // 0x10 + u32 base_addr0_hi; // 0x14 + + u32 base_addr1_lo; // 0x18 + u32 base_addr1_hi; // 0x1C + + u32 not_Implemented1; // 0x20 + u32 not_Implemented2; // 0x24 + + u32 cardbus_cis_pointer; // 0x28 + + u16 subsystem_vendor_id; // 0x2c + u16 subsystem_id; // 0x2e + + u32 rom_base; // 0x30 + u8 capabilities_pointer; // 0x34 + u8 rsvd_35[3]; // 0x35 + u32 rsvd_38; // 0x38 + + u8 interrupt_line; // 0x3c + u8 interrupt_pin; // 0x3d + u8 min_grant; // 0x3e + u8 max_latency; // 0x3f + + u8 msi_cap_id; // 0x40 + u8 msi_next_ptr; // 0x41 + u16 msi_control; // 0x42 + u32 msi_lower_address; // 0x44 + u32 msi_higher_address; // 0x48 + u16 msi_data; // 0x4c + u16 msi_unused; // 0x4e + + u8 vpd_cap_id; // 0x50 + u8 vpd_next_cap; // 0x51 + u16 vpd_addr; // 0x52 + u32 vpd_data; // 0x54 + + u8 rsvd_b0[8]; // 0x58 + + u8 pcix_cap; // 0x60 + u8 pcix_next_cap; // 0x61 + u16 pcix_command; // 0x62 + + u32 pcix_status; // 0x64 + + u8 rsvd_b1[XGE_HAL_PCI_XFRAME_CONFIG_SPACE_SIZE-0x68]; +} xge_hal_pci_config_le_t; // 0x100 + +typedef struct xge_hal_pci_config_t { +#ifdef XGE_OS_HOST_BIG_ENDIAN + u16 device_id; // 0x02 + u16 vendor_id; // 0x00 + + u16 status; // 0x06 + u16 command; // 0x04 + + u8 pciClass[3]; // 0x09 + u8 revision; // 0x08 + + u8 bist; // 0x0f + u8 header_type; // 0x0e + u8 latency_timer; // 0x0d + u8 cache_line_size; // 0x0c + + u32 base_addr0_lo; // 0x10 + u32 base_addr0_hi; // 0x14 + + u32 base_addr1_lo; // 0x18 + u32 base_addr1_hi; // 0x1C + + u32 not_Implemented1; // 0x20 + u32 not_Implemented2; // 0x24 + + u32 cardbus_cis_pointer; // 0x28 + + u16 subsystem_id; // 0x2e + u16 subsystem_vendor_id; // 0x2c + + u32 rom_base; // 0x30 + u8 rsvd_35[3]; // 0x35 + u8 capabilities_pointer; // 0x34 + u32 rsvd_38; // 0x38 + + u8 max_latency; // 0x3f + u8 min_grant; // 0x3e + u8 interrupt_pin; // 0x3d + u8 interrupt_line; // 0x3c + + u16 msi_control; // 0x42 + u8 msi_next_ptr; // 0x41 + u8 msi_cap_id; // 0x40 + u32 msi_lower_address; // 0x44 + u32 msi_higher_address; // 0x48 + u16 msi_unused; // 0x4e + u16 msi_data; // 0x4c + + u16 vpd_addr; // 0x52 + u8 vpd_next_cap; // 0x51 + u8 vpd_cap_id; // 0x50 + u32 vpd_data; // 0x54 + + u8 rsvd_b0[8]; // 0x58 + + u16 pcix_command; // 0x62 + u8 pcix_next_cap; // 0x61 + u8 pcix_cap; // 0x60 + + u32 pcix_status; // 0x64 +#else + u16 vendor_id; // 0x00 + u16 device_id; // 0x02 + + u16 command; // 0x04 + u16 status; // 0x06 + + u8 revision; // 0x08 + u8 pciClass[3]; // 0x09 + + u8 cache_line_size; // 0x0c + u8 latency_timer; // 0x0d + u8 header_type; // 0x0e + u8 bist; // 0x0f + + u32 base_addr0_lo; // 0x10 + u32 base_addr0_hi; // 0x14 + + u32 base_addr1_lo; // 0x18 + u32 base_addr1_hi; // 0x1C + + u32 not_Implemented1; // 0x20 + u32 not_Implemented2; // 0x24 + + u32 cardbus_cis_pointer; // 0x28 + + u16 subsystem_vendor_id; // 0x2c + u16 subsystem_id; // 0x2e + + u32 rom_base; // 0x30 + u8 capabilities_pointer; // 0x34 + u8 rsvd_35[3]; // 0x35 + u32 rsvd_38; // 0x38 + + u8 interrupt_line; // 0x3c + u8 interrupt_pin; // 0x3d + u8 min_grant; // 0x3e + u8 max_latency; // 0x3f + + u8 msi_cap_id; // 0x40 + u8 msi_next_ptr; // 0x41 + u16 msi_control; // 0x42 + u32 msi_lower_address; // 0x44 + u32 msi_higher_address; // 0x48 + u16 msi_data; // 0x4c + u16 msi_unused; // 0x4e + + u8 vpd_cap_id; // 0x50 + u8 vpd_next_cap; // 0x51 + u16 vpd_addr; // 0x52 + u32 vpd_data; // 0x54 + + u8 rsvd_b0[8]; // 0x58 + + u8 pcix_cap; // 0x60 + u8 pcix_next_cap; // 0x61 + u16 pcix_command; // 0x62 + + u32 pcix_status; // 0x64 + +#endif + u8 rsvd_b1[XGE_HAL_PCI_XFRAME_CONFIG_SPACE_SIZE-0x68]; +} xge_hal_pci_config_t; // 0x100 + +#define XGE_HAL_REG_SPACE sizeof(xge_hal_pci_bar0_t) +#define XGE_HAL_EEPROM_SIZE (0x01 << 11) + +#endif /* XGE_HAL_REGS_H */ diff --git a/sys/dev/nxge/include/xgehal-ring.h b/sys/dev/nxge/include/xgehal-ring.h new file mode 100644 index 0000000..c3efdf0 --- /dev/null +++ b/sys/dev/nxge/include/xgehal-ring.h @@ -0,0 +1,473 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-ring.h + * + * Description: HAL Rx ring object functionality + * + * Created: 19 May 2004 + */ + +#ifndef XGE_HAL_RING_H +#define XGE_HAL_RING_H + +#include <dev/nxge/include/xgehal-channel.h> +#include <dev/nxge/include/xgehal-config.h> +#include <dev/nxge/include/xgehal-mm.h> + +__EXTERN_BEGIN_DECLS + +/* HW ring configuration */ +#define XGE_HAL_RING_RXDBLOCK_SIZE 0x1000 + +#define XGE_HAL_RXD_T_CODE_OK 0x0 +#define XGE_HAL_RXD_T_CODE_PARITY 0x1 +#define XGE_HAL_RXD_T_CODE_ABORT 0x2 +#define XGE_HAL_RXD_T_CODE_PARITY_ABORT 0x3 +#define XGE_HAL_RXD_T_CODE_RDA_FAILURE 0x4 +#define XGE_HAL_RXD_T_CODE_UNKNOWN_PROTO 0x5 +#define XGE_HAL_RXD_T_CODE_BAD_FCS 0x6 +#define XGE_HAL_RXD_T_CODE_BUFF_SIZE 0x7 +#define XGE_HAL_RXD_T_CODE_BAD_ECC 0x8 +#define XGE_HAL_RXD_T_CODE_UNUSED_C 0xC +#define XGE_HAL_RXD_T_CODE_UNKNOWN 0xF + +#define XGE_HAL_RING_USE_MTU -1 + +/* control_1 and control_2 formatting - same for all buffer modes */ +#define XGE_HAL_RXD_GET_L3_CKSUM(control_1) ((u16)(control_1>>16) & 0xFFFF) +#define XGE_HAL_RXD_GET_L4_CKSUM(control_1) ((u16)(control_1 & 0xFFFF)) + +#define XGE_HAL_RXD_MASK_VLAN_TAG vBIT(0xFFFF,48,16) +#define XGE_HAL_RXD_SET_VLAN_TAG(control_2, val) control_2 |= (u16)val +#define XGE_HAL_RXD_GET_VLAN_TAG(control_2) ((u16)(control_2 & 0xFFFF)) + +#define XGE_HAL_RXD_POSTED_4_XFRAME BIT(7) /* control_1 */ +#define XGE_HAL_RXD_NOT_COMPLETED BIT(0) /* control_2 */ +#define XGE_HAL_RXD_T_CODE (BIT(12)|BIT(13)|BIT(14)|BIT(15)) +#define XGE_HAL_RXD_GET_T_CODE(control_1) \ + ((control_1 & XGE_HAL_RXD_T_CODE)>>48) +#define XGE_HAL_RXD_SET_T_CODE(control_1, val) \ + (control_1 |= (((u64)val & 0xF) << 48)) + +#define XGE_HAL_RXD_MASK_FRAME_TYPE vBIT(0x3,25,2) +#define XGE_HAL_RXD_MASK_FRAME_PROTO vBIT(0xFFFF,24,8) +#define XGE_HAL_RXD_GET_FRAME_TYPE(control_1) \ + (u8)(0x3 & ((control_1 & XGE_HAL_RXD_MASK_FRAME_TYPE) >> 37)) +#define XGE_HAL_RXD_GET_FRAME_PROTO(control_1) \ + (u8)((control_1 & XGE_HAL_RXD_MASK_FRAME_PROTO) >> 32) +#define XGE_HAL_RXD_FRAME_PROTO_VLAN_TAGGED BIT(24) +#define XGE_HAL_RXD_FRAME_PROTO_IPV4 BIT(27) +#define XGE_HAL_RXD_FRAME_PROTO_IPV6 BIT(28) +#define XGE_HAL_RXD_FRAME_PROTO_IP_FRAGMENTED BIT(29) +#define XGE_HAL_RXD_FRAME_PROTO_TCP BIT(30) +#define XGE_HAL_RXD_FRAME_PROTO_UDP BIT(31) +#define XGE_HAL_RXD_FRAME_TCP_OR_UDP (XGE_HAL_RXD_FRAME_PROTO_TCP | \ + XGE_HAL_RXD_FRAME_PROTO_UDP) + +/** + * enum xge_hal_frame_type_e - Ethernet frame format. + * @XGE_HAL_FRAME_TYPE_DIX: DIX (Ethernet II) format. + * @XGE_HAL_FRAME_TYPE_LLC: LLC format. + * @XGE_HAL_FRAME_TYPE_SNAP: SNAP format. + * @XGE_HAL_FRAME_TYPE_IPX: IPX format. + * + * Ethernet frame format. + */ +typedef enum xge_hal_frame_type_e { + XGE_HAL_FRAME_TYPE_DIX = 0x0, + XGE_HAL_FRAME_TYPE_LLC = 0x1, + XGE_HAL_FRAME_TYPE_SNAP = 0x2, + XGE_HAL_FRAME_TYPE_IPX = 0x3, +} xge_hal_frame_type_e; + +/** + * enum xge_hal_frame_proto_e - Higher-layer ethernet protocols. + * @XGE_HAL_FRAME_PROTO_VLAN_TAGGED: VLAN. + * @XGE_HAL_FRAME_PROTO_IPV4: IPv4. + * @XGE_HAL_FRAME_PROTO_IPV6: IPv6. + * @XGE_HAL_FRAME_PROTO_IP_FRAGMENTED: IP fragmented. + * @XGE_HAL_FRAME_PROTO_TCP: TCP. + * @XGE_HAL_FRAME_PROTO_UDP: UDP. + * @XGE_HAL_FRAME_PROTO_TCP_OR_UDP: TCP or UDP. + * + * Higher layer ethernet protocols and options. + */ +typedef enum xge_hal_frame_proto_e { + XGE_HAL_FRAME_PROTO_VLAN_TAGGED = 0x80, + XGE_HAL_FRAME_PROTO_IPV4 = 0x10, + XGE_HAL_FRAME_PROTO_IPV6 = 0x08, + XGE_HAL_FRAME_PROTO_IP_FRAGMENTED = 0x04, + XGE_HAL_FRAME_PROTO_TCP = 0x02, + XGE_HAL_FRAME_PROTO_UDP = 0x01, + XGE_HAL_FRAME_PROTO_TCP_OR_UDP = (XGE_HAL_FRAME_PROTO_TCP | \ + XGE_HAL_FRAME_PROTO_UDP) +} xge_hal_frame_proto_e; + +/* + * xge_hal_ring_rxd_1_t + */ +typedef struct { + u64 host_control; + u64 control_1; + u64 control_2; +#define XGE_HAL_RXD_1_MASK_BUFFER0_SIZE vBIT(0xFFFF,0,16) +#define XGE_HAL_RXD_1_SET_BUFFER0_SIZE(val) vBIT(val,0,16) +#define XGE_HAL_RXD_1_GET_BUFFER0_SIZE(Control_2) \ + (int)((Control_2 & vBIT(0xFFFF,0,16))>>48) +#define XGE_HAL_RXD_1_GET_RTH_VALUE(Control_2) \ + (u32)((Control_2 & vBIT(0xFFFFFFFF,16,32))>>16) + u64 buffer0_ptr; +} xge_hal_ring_rxd_1_t; + +/* + * xge_hal_ring_rxd_3_t + */ +typedef struct { + u64 host_control; + u64 control_1; + + u64 control_2; +#define XGE_HAL_RXD_3_MASK_BUFFER0_SIZE vBIT(0xFF,8,8) +#define XGE_HAL_RXD_3_SET_BUFFER0_SIZE(val) vBIT(val,8,8) +#define XGE_HAL_RXD_3_MASK_BUFFER1_SIZE vBIT(0xFFFF,16,16) +#define XGE_HAL_RXD_3_SET_BUFFER1_SIZE(val) vBIT(val,16,16) +#define XGE_HAL_RXD_3_MASK_BUFFER2_SIZE vBIT(0xFFFF,32,16) +#define XGE_HAL_RXD_3_SET_BUFFER2_SIZE(val) vBIT(val,32,16) + + +#define XGE_HAL_RXD_3_GET_BUFFER0_SIZE(Control_2) \ + (int)((Control_2 & vBIT(0xFF,8,8))>>48) +#define XGE_HAL_RXD_3_GET_BUFFER1_SIZE(Control_2) \ + (int)((Control_2 & vBIT(0xFFFF,16,16))>>32) +#define XGE_HAL_RXD_3_GET_BUFFER2_SIZE(Control_2) \ + (int)((Control_2 & vBIT(0xFFFF,32,16))>>16) + + u64 buffer0_ptr; + u64 buffer1_ptr; + u64 buffer2_ptr; +} xge_hal_ring_rxd_3_t; + +/* + * xge_hal_ring_rxd_5_t + */ +typedef struct { +#ifdef XGE_OS_HOST_BIG_ENDIAN + u32 host_control; + u32 control_3; +#else + u32 control_3; + u32 host_control; +#endif + + +#define XGE_HAL_RXD_5_MASK_BUFFER3_SIZE vBIT(0xFFFF,32,16) +#define XGE_HAL_RXD_5_SET_BUFFER3_SIZE(val) vBIT(val,32,16) +#define XGE_HAL_RXD_5_MASK_BUFFER4_SIZE vBIT(0xFFFF,48,16) +#define XGE_HAL_RXD_5_SET_BUFFER4_SIZE(val) vBIT(val,48,16) + +#define XGE_HAL_RXD_5_GET_BUFFER3_SIZE(Control_3) \ + (int)((Control_3 & vBIT(0xFFFF,32,16))>>16) +#define XGE_HAL_RXD_5_GET_BUFFER4_SIZE(Control_3) \ + (int)((Control_3 & vBIT(0xFFFF,48,16))) + + u64 control_1; + u64 control_2; + +#define XGE_HAL_RXD_5_MASK_BUFFER0_SIZE vBIT(0xFFFF,0,16) +#define XGE_HAL_RXD_5_SET_BUFFER0_SIZE(val) vBIT(val,0,16) +#define XGE_HAL_RXD_5_MASK_BUFFER1_SIZE vBIT(0xFFFF,16,16) +#define XGE_HAL_RXD_5_SET_BUFFER1_SIZE(val) vBIT(val,16,16) +#define XGE_HAL_RXD_5_MASK_BUFFER2_SIZE vBIT(0xFFFF,32,16) +#define XGE_HAL_RXD_5_SET_BUFFER2_SIZE(val) vBIT(val,32,16) + + +#define XGE_HAL_RXD_5_GET_BUFFER0_SIZE(Control_2) \ + (int)((Control_2 & vBIT(0xFFFF,0,16))>>48) +#define XGE_HAL_RXD_5_GET_BUFFER1_SIZE(Control_2) \ + (int)((Control_2 & vBIT(0xFFFF,16,16))>>32) +#define XGE_HAL_RXD_5_GET_BUFFER2_SIZE(Control_2) \ + (int)((Control_2 & vBIT(0xFFFF,32,16))>>16) + u64 buffer0_ptr; + u64 buffer1_ptr; + u64 buffer2_ptr; + u64 buffer3_ptr; + u64 buffer4_ptr; +} xge_hal_ring_rxd_5_t; + +#define XGE_HAL_RXD_GET_RTH_SPDM_HIT(Control_1) \ + (u8)((Control_1 & BIT(18))>>45) +#define XGE_HAL_RXD_GET_RTH_IT_HIT(Control_1) \ + (u8)((Control_1 & BIT(19))>>44) +#define XGE_HAL_RXD_GET_RTH_HASH_TYPE(Control_1) \ + (u8)((Control_1 & vBIT(0xF,20,4))>>40) + +#define XGE_HAL_RXD_HASH_TYPE_NONE 0x0 +#define XGE_HAL_RXD_HASH_TYPE_TCP_IPV4 0x1 +#define XGE_HAL_RXD_HASH_TYPE_UDP_IPV4 0x2 +#define XGE_HAL_RXD_HASH_TYPE_IPV4 0x3 +#define XGE_HAL_RXD_HASH_TYPE_TCP_IPV6 0x4 +#define XGE_HAL_RXD_HASH_TYPE_UDP_IPV6 0x5 +#define XGE_HAL_RXD_HASH_TYPE_IPV6 0x6 +#define XGE_HAL_RXD_HASH_TYPE_TCP_IPV6_EX 0x7 +#define XGE_HAL_RXD_HASH_TYPE_UDP_IPV6_EX 0x8 +#define XGE_HAL_RXD_HASH_TYPE_IPV6_EX 0x9 + +typedef u8 xge_hal_ring_block_t[XGE_HAL_RING_RXDBLOCK_SIZE]; + +#define XGE_HAL_RING_NEXT_BLOCK_POINTER_OFFSET 0xFF8 +#define XGE_HAL_RING_MEMBLOCK_IDX_OFFSET 0xFF0 + +#define XGE_HAL_RING_RXD_SIZEOF(n) \ + (n==1 ? sizeof(xge_hal_ring_rxd_1_t) : \ + (n==3 ? sizeof(xge_hal_ring_rxd_3_t) : \ + sizeof(xge_hal_ring_rxd_5_t))) + +#define XGE_HAL_RING_RXDS_PER_BLOCK(n) \ + (n==1 ? 127 : (n==3 ? 85 : 63)) + +/** + * struct xge_hal_ring_rxd_priv_t - Receive descriptor HAL-private data. + * @dma_addr: DMA (mapped) address of _this_ descriptor. + * @dma_handle: DMA handle used to map the descriptor onto device. + * @dma_offset: Descriptor's offset in the memory block. HAL allocates + * descriptors in memory blocks of + * %XGE_HAL_RING_RXDBLOCK_SIZE + * bytes. Each memblock is contiguous DMA-able memory. Each + * memblock contains 1 or more 4KB RxD blocks visible to the + * Xframe hardware. + * @dma_object: DMA address and handle of the memory block that contains + * the descriptor. This member is used only in the "checked" + * version of the HAL (to enforce certain assertions); + * otherwise it gets compiled out. + * @allocated: True if the descriptor is reserved, 0 otherwise. Internal usage. + * + * Per-receive decsriptor HAL-private data. HAL uses the space to keep DMA + * information associated with the descriptor. Note that ULD can ask HAL + * to allocate additional per-descriptor space for its own (ULD-specific) + * purposes. + */ +typedef struct xge_hal_ring_rxd_priv_t { + dma_addr_t dma_addr; + pci_dma_h dma_handle; + ptrdiff_t dma_offset; +#ifdef XGE_DEBUG_ASSERT + xge_hal_mempool_dma_t *dma_object; +#endif +#ifdef XGE_OS_MEMORY_CHECK + int allocated; +#endif +} xge_hal_ring_rxd_priv_t; + +/** + * struct xge_hal_ring_t - Ring channel. + * @channel: Channel "base" of this ring, the common part of all HAL + * channels. + * @buffer_mode: 1, 3, or 5. The value specifies a receive buffer mode, + * as per Xframe User Guide. + * @indicate_max_pkts: Maximum number of packets processed within a single + * interrupt. Can be used to limit the time spent inside hw + * interrupt. + * @config: Ring configuration, part of device configuration + * (see xge_hal_device_config_t{}). + * @rxd_size: RxD sizes for 1-, 3- or 5- buffer modes. As per Xframe spec, + * 1-buffer mode descriptor is 32 byte long, etc. + * @rxd_priv_size: Per RxD size reserved (by HAL) for ULD to keep per-descriptor + * data (e.g., DMA handle for Solaris) + * @rxds_per_block: Number of descriptors per hardware-defined RxD + * block. Depends on the (1-,3-,5-) buffer mode. + * @mempool: Memory pool, the pool from which descriptors get allocated. + * (See xge_hal_mm.h). + * @rxdblock_priv_size: Reserved at the end of each RxD block. HAL internal + * usage. Not to confuse with @rxd_priv_size. + * @reserved_rxds_arr: Array of RxD pointers. At any point in time each + * entry in this array is available for allocation + * (via xge_hal_ring_dtr_reserve()) and posting. + * @cmpl_cnt: Completion counter. Is reset to zero upon entering the ISR. + * Used in conjunction with @indicate_max_pkts. + * Ring channel. + * + * Note: The structure is cache line aligned to better utilize + * CPU cache performance. + */ +typedef struct xge_hal_ring_t { + xge_hal_channel_t channel; + int buffer_mode; + int indicate_max_pkts; + xge_hal_ring_config_t *config; + int rxd_size; + int rxd_priv_size; + int rxds_per_block; + xge_hal_mempool_t *mempool; + int rxdblock_priv_size; + void **reserved_rxds_arr; + int cmpl_cnt; +} __xge_os_attr_cacheline_aligned xge_hal_ring_t; + +/** + * struct xge_hal_dtr_info_t - Extended information associated with a + * completed ring descriptor. + * @l3_cksum: Result of IP checksum check (by Xframe hardware). + * This field containing XGE_HAL_L3_CKSUM_OK would mean that + * the checksum is correct, otherwise - the datagram is + * corrupted. + * @l4_cksum: Result of TCP/UDP checksum check (by Xframe hardware). + * This field containing XGE_HAL_L4_CKSUM_OK would mean that + * the checksum is correct. Otherwise - the packet is + * corrupted. + * @frame: See xge_hal_frame_type_e{}. + * @proto: Reporting bits for various higher-layer protocols, including (but + * note restricted to) TCP and UDP. See xge_hal_frame_proto_e{}. + * @vlan: VLAN tag extracted from the received frame. + * @rth_value: Receive Traffic Hashing(RTH) hash value. Produced by Xframe II + * hardware if RTH is enabled. + * @rth_it_hit: Set, If RTH hash value calculated by the Xframe II hardware + * has a matching entry in the Indirection table. + * @rth_spdm_hit: Set, If RTH hash value calculated by the Xframe II hardware + * has a matching entry in the Socket Pair Direct Match table. + * @rth_hash_type: RTH hash code of the function used to calculate the hash. + * @reserved_pad: Unused byte. + */ +typedef struct xge_hal_dtr_info_t { + int l3_cksum; + int l4_cksum; + int frame; /* zero or more of xge_hal_frame_type_e flags */ + int proto; /* zero or more of xge_hal_frame_proto_e flags */ + int vlan; + u32 rth_value; + u8 rth_it_hit; + u8 rth_spdm_hit; + u8 rth_hash_type; + u8 reserved_pad; +} xge_hal_dtr_info_t; + +/* ========================== RING PRIVATE API ============================ */ + +xge_hal_status_e __hal_ring_open(xge_hal_channel_h channelh, + xge_hal_channel_attr_t *attr); + +void __hal_ring_close(xge_hal_channel_h channelh); + +void __hal_ring_hw_initialize(xge_hal_device_h devh); + +void __hal_ring_mtu_set(xge_hal_device_h devh, int new_mtu); + +void __hal_ring_prc_enable(xge_hal_channel_h channelh); + +void __hal_ring_prc_disable(xge_hal_channel_h channelh); + +xge_hal_status_e __hal_ring_initial_replenish(xge_hal_channel_t *channel, + xge_hal_channel_reopen_e reopen); + +#if defined(XGE_DEBUG_FP) && (XGE_DEBUG_FP & XGE_DEBUG_FP_RING) +#define __HAL_STATIC_RING +#define __HAL_INLINE_RING + +__HAL_STATIC_RING __HAL_INLINE_RING int +__hal_ring_block_memblock_idx(xge_hal_ring_block_t *block); + +__HAL_STATIC_RING __HAL_INLINE_RING void +__hal_ring_block_memblock_idx_set(xge_hal_ring_block_t*block, int memblock_idx); + +__HAL_STATIC_RING __HAL_INLINE_RING dma_addr_t +__hal_ring_block_next_pointer(xge_hal_ring_block_t *block); + +__HAL_STATIC_RING __HAL_INLINE_RING void +__hal_ring_block_next_pointer_set(xge_hal_ring_block_t*block, + dma_addr_t dma_next); + +__HAL_STATIC_RING __HAL_INLINE_RING xge_hal_ring_rxd_priv_t* +__hal_ring_rxd_priv(xge_hal_ring_t *ring, xge_hal_dtr_h dtrh); + +/* =========================== RING PUBLIC API ============================ */ + +__HAL_STATIC_RING __HAL_INLINE_RING xge_hal_status_e +xge_hal_ring_dtr_reserve(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh); + +__HAL_STATIC_RING __HAL_INLINE_RING void* +xge_hal_ring_dtr_private(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); + +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_1b_set(xge_hal_dtr_h dtrh, dma_addr_t dma_pointer, int size); + +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_info_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + xge_hal_dtr_info_t *ext_info); + +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_1b_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + dma_addr_t *dma_pointer, int *pkt_length); + +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_3b_set(xge_hal_dtr_h dtrh, dma_addr_t dma_pointers[], + int sizes[]); + +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_3b_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + dma_addr_t dma_pointers[], int sizes[]); + +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_5b_set(xge_hal_dtr_h dtrh, dma_addr_t dma_pointers[], + int sizes[]); + +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_5b_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + dma_addr_t dma_pointer[], int sizes[]); + +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); + +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_pre_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); + +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_post_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); + +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_post_post_wmb(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); + +__HAL_STATIC_RING __HAL_INLINE_RING xge_hal_status_e +xge_hal_ring_dtr_next_completed(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh, + u8 *t_code); + +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_free(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); + +__HAL_STATIC_RING __HAL_INLINE_RING xge_hal_status_e +xge_hal_ring_is_next_dtr_completed(xge_hal_channel_h channelh); + +#else /* XGE_FASTPATH_EXTERN */ +#define __HAL_STATIC_RING static +#define __HAL_INLINE_RING inline +#include <dev/nxge/xgehal/xgehal-ring-fp.c> +#endif /* XGE_FASTPATH_INLINE */ + +__EXTERN_END_DECLS + +#endif /* XGE_HAL_RING_H */ diff --git a/sys/dev/nxge/include/xgehal-stats.h b/sys/dev/nxge/include/xgehal-stats.h new file mode 100644 index 0000000..ffe0e6e --- /dev/null +++ b/sys/dev/nxge/include/xgehal-stats.h @@ -0,0 +1,1601 @@ +/*- + * 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$ + */ + +/* + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + * FileName : xgehal-stats.h + * + * Description: HW statistics object + * + * Created: 2 June 2004 + */ + +#ifndef XGE_HAL_STATS_H +#define XGE_HAL_STATS_H + +#include <dev/nxge/include/xge-os-pal.h> +#include <dev/nxge/include/xge-debug.h> +#include <dev/nxge/include/xgehal-types.h> +#include <dev/nxge/include/xgehal-config.h> + +__EXTERN_BEGIN_DECLS + +/** + * struct xge_hal_stats_hw_info_t - Xframe hardware statistics. + * Transmit MAC Statistics: + * + * @tmac_frms: Count of successfully transmitted MAC + * frames Note that this statistic may be inaccurate. The correct statistic may + * be derived by calcualating (tmac_ttl_octets - tmac_ttl_less_fb_octets) / 8 + * + * @tmac_data_octets: Count of data and padding octets of successfully + * transmitted frames. + * + * @tmac_drop_frms: Count of frames that could not be sent for no other reason + * than internal MAC processing. Increments once whenever the + * transmit buffer is flushed (due to an ECC error on a memory descriptor). + * + * @tmac_mcst_frms: Count of successfully transmitted frames to a multicast + * address. Does not include frames sent to the broadcast address. + * + * @tmac_bcst_frms: Count of successfully transmitted frames to the broadcast + * address. + * + * @tmac_pause_ctrl_frms: Count of MAC PAUSE control frames that are + * transmitted. Since, the only control frames supported by this device + * are PAUSE frames, this register is a count of all transmitted MAC control + * frames. + * + * @tmac_ttl_octets: Count of total octets of transmitted frames, including + * framing characters. + * + * @tmac_ucst_frms: Count of transmitted frames containing a unicast address. + * @tmac_nucst_frms: Count of transmitted frames containing a non-unicast + * (broadcast, multicast) address. + * + * @tmac_any_err_frms: Count of transmitted frames containing any error that + * prevents them from being passed to the network. Increments if there is an ECC + * while reading the frame out of the transmit buffer. + * + * @tmac_ttl_less_fb_octets: Count of total octets of transmitted + * frames, not including framing characters (i.e. less framing bits) + * + * @tmac_vld_ip_octets: Count of total octets of transmitted IP datagrams that + * were passed to the network. Frames that are padded by the host have + * their padding counted as part of the IP datagram. + * + * @tmac_vld_ip: Count of transmitted IP datagrams that were passed to the + * network. + * + * @tmac_drop_ip: Count of transmitted IP datagrams that could not be passed to + * the network. Increments because of 1) an internal processing error (such as + * an uncorrectable ECC error); 2) a frame parsing error during IP checksum + * calculation. + * + * @tmac_icmp: Count of transmitted ICMP messages. Includes messages not sent + * due to problems within ICMP. + * + * @tmac_rst_tcp: Count of transmitted TCP segments containing the RST flag. + * + * @tmac_tcp: Count of transmitted TCP segments. Note that Xena has + * no knowledge of retransmission. + * + * @tmac_udp: Count of transmitted UDP datagrams. + * @reserved_0: Reserved. + * + * Receive MAC Statistics: + * @rmac_vld_frms: Count of successfully received MAC frames. Does not include + * frames received with frame-too-long, FCS, or length errors. + * + * @rmac_data_octets: Count of data and padding octets of successfully received + * frames. Does not include frames received with frame-too-long, FCS, or length + * errors. + * + * @rmac_fcs_err_frms: Count of received MAC frames that do not pass FCS. Does + * not include frames received with frame-too-long or frame-too-short error. + * + * @rmac_drop_frms: Count of received frames that could not be passed to the + * host because of 1) Random Early Discard (RED); 2) Frame steering algorithm + * found no available queue; 3) Receive ingress buffer overflow. + * + * @rmac_vld_mcst_frms: Count of successfully received MAC frames containing a + * multicast address. Does not include frames received with frame-too-long, FCS, + * or length errors. + * + * @rmac_vld_bcst_frms: Count of successfully received MAC frames containing a + * broadcast address. Does not include frames received with frame-too-long, FCS, + * or length errors. + * + * @rmac_in_rng_len_err_frms: Count of received frames with a length/type field + * value between 46 (42 for VLANtagged frames) and 1500 (also 1500 for + * VLAN-tagged frames), inclusive, that does not match the number of data octets + * (including pad) received. Also contains a count of received frames with a + * length/type field less than 46 (42 for VLAN-tagged frames) and the number of + * data octets (including pad) received is greater than 46 (42 for VLAN-tagged + * frames). + * + * @rmac_out_rng_len_err_frms: Count of received frames with length/type field + * between 1501 and 1535 decimal, inclusive. + * + * @rmac_long_frms: Count of received frames that are longer than + * rmac_max_pyld_len + 18 bytes (+22 bytes if VLAN-tagged). + * + * @rmac_pause_ctrl_frms: Count of received MAC PAUSE control frames. + * + * @rmac_unsup_ctrl_frms: Count of received MAC control frames + * that do not contain the PAUSE opcode. The sum of MAC_PAUSE_CTRL_FRMS and this + * register is a count of all received MAC control frames. + * + * @rmac_ttl_octets: Count of total octets of received frames, including framing + * characters. + * + * @rmac_accepted_ucst_frms: Count of successfully received frames + * containing a unicast address. Only includes frames that are passed to the + * system. + * + * @rmac_accepted_nucst_frms: Count of successfully received frames + * containing a non-unicast (broadcast or multicast) address. Only includes + * frames that are passed to the system. Could include, for instance, + * non-unicast frames that contain FCS errors if the MAC_ERROR_CFG register is + * set to pass FCSerrored frames to the host. + * + * @rmac_discarded_frms: Count of received frames containing any error that + * prevents them from being passed to the system. Includes, for example, + * received pause frames that are discarded by the MAC and frames discarded + * because of their destination address. + * + * @rmac_drop_events: Because the RMAC drops one frame at a time, this stat + * matches rmac_drop_frms. + * + * @reserved_1: Reserved. + * @rmac_ttl_less_fb_octets: Count of total octets of received frames, + * not including framing characters (i.e. less framing bits). + * + * @rmac_ttl_frms: Count of all received MAC frames, including frames received + * with frame-too-long, FCS, or length errors. + * + * @reserved_2: Reserved. + * @reserved_3: Reserved. + * @rmac_usized_frms: Count of received frames of length (including FCS, but not + * framing bits) less than 64 octets, that are otherwise well-formed. + * + * @rmac_osized_frms: Count of received frames of length (including FCS, but not + * framing bits) more than 1518 octets, that are otherwise well-formed. + * + * @rmac_frag_frms: Count of received frames of length (including FCS, but not + * framing bits) less than 64 octets that had bad FCS. In other words, counts + * fragments (i.e. runts). + * + * @rmac_jabber_frms: Count of received frames of length (including FCS, but not + * framing bits) more than MTU octets that had bad FCS. In other words, counts + * jabbers. + * + * @reserved_4: Reserved. + * @rmac_ttl_64_frms: Count of all received MAC frames with length (including + * FCS, but not framing bits) of exactly 64 octets. Includes frames received + * with frame-too-long, FCS, or length errors. + * + * @rmac_ttl_65_127_frms: Count of all received MAC frames with length + * (including FCS, but not framing bits) of between 65 and 127 octets + * inclusive. Includes frames received with frame-too-long, FCS, or length + * errors. + * @reserved_5: Reserved. + * @rmac_ttl_128_255_frms: Count of all received MAC frames with length + * (including FCS, but not framing bits) of between 128 and 255 octets + * inclusive. Includes frames received with frame-too-long, FCS, or length + * errors. + * + * @rmac_ttl_256_511_frms: Count of all received MAC frames with length + * (including FCS, but not framing bits) of between 256 and 511 octets + * inclusive. Includes frames received with frame-too-long, FCS, or length + * errors. + * + * @reserved_6: Reserved. + * @rmac_ttl_512_1023_frms: Count of all received MAC frames with length + * (including FCS, but not framing bits) of between 512 and 1023 octets + * inclusive. Includes frames received with frame-too-long, FCS, or length + * errors. + * + * @rmac_ttl_1024_1518_frms: Count of all received MAC frames with length + * (including FCS, but not framing bits) of between 1024 and 1518 octets + * inclusive. Includes frames received with frame-too-long, FCS, or length + * errors. + * @reserved_7: Reserved. + * @rmac_ip: Count of received IP datagrams. Includes errored IP datagrams. + * + * @rmac_ip_octets: Count of number of octets in received IP datagrams. Includes + * errored IP datagrams. + * + * @rmac_hdr_err_ip: Count of received IP datagrams that are discarded due to IP + * header errors. + * + * @rmac_drop_ip: Count of received IP datagrams that could not be passed to the + * host because of 1) Random Early Discard (RED); 2) Frame steering algorithm + * found no available queue; 3) Receive ingress buffer overflow. + * @rmac_icmp: Count of received ICMP messages. Includes errored ICMP messages + * (due to ICMP checksum fail). + * + * @reserved_8: Reserved. + * @rmac_tcp: Count of received TCP segments. Since Xena is unaware of + * connection context, counts all received TCP segments, regardless of whether + * or not they pertain to an established connection. + * + * @rmac_udp: Count of received UDP datagrams. + * @rmac_err_drp_udp: Count of received UDP datagrams that were not delivered to + * the system because of 1) Random Early Discard (RED); 2) Frame steering + * algorithm found no available queue; 3) Receive ingress buffer overflow. + * + * @rmac_xgmii_err_sym: Count of the number of symbol errors in the received + * XGMII data (i.e. PHY indicates "Receive Error" on the XGMII). Only includes + * symbol errors that are observed between the XGMII Start Frame Delimiter + * and End Frame Delimiter, inclusive. And only increments the count by one for + * each frame. + * + * @rmac_frms_q0: Count of number of frames that pass through queue 0 of receive + * buffer. + * @rmac_frms_q1: Count of number of frames that pass through queue 1 of receive + * buffer. + * @rmac_frms_q2: Count of number of frames that pass through queue 2 of receive + * buffer. + * @rmac_frms_q3: Count of number of frames that pass through queue 3 of receive + * buffer. + * @rmac_frms_q4: Count of number of frames that pass through queue 4 of receive + * buffer. + * @rmac_frms_q5: Count of number of frames that pass through queue 5 of receive + * buffer. + * @rmac_frms_q6: Count of number of frames that pass through queue 6 of receive + * buffer. + * @rmac_frms_q7: Count of number of frames that pass through queue 7 of receive + * buffer. + * @rmac_full_q0: Count of number of times that receive buffer queue 0 has + * filled up. If a queue is size 0, then this stat is incremented to a value of + * 1 when MAC receives its first frame. + * + * @rmac_full_q1: Count of number of times that receive buffer queue 1 has + * filled up. If a queue is size 0, then this stat is incremented to a value of + * 1 when MAC receives its first frame. + * + * @rmac_full_q2: Count of number of times that receive buffer queue 2 has + * filled up. If a queue is size 0, then this stat is incremented to a value of + * 1 when MAC receives its first frame. + * + * @rmac_full_q3: Count of number of times that receive buffer queue 3 has + * filled up. If a queue is size 0, then this stat is incremented to a value of + * 1 when MAC receives its first frame. + * + * @rmac_full_q4: Count of number of times that receive buffer queue 4 has + * filled up. If a queue is size 0, then this stat is incremented to a value of + * 1 when MAC receives its first frame. + * + * @rmac_full_q5: Count of number of times that receive buffer queue 5 has + * filled up. If a queue is size 0, then this stat is incremented to a value of + * 1 when MAC receives its first frame. + * + * @rmac_full_q6: Count of number of times that receive buffer queue 6 has + * filled up. If a queue is size 0, then this stat is incremented to a value of + * 1 when MAC receives its first frame. + * + * @rmac_full_q7: Count of number of times that receive buffer queue 7 has + * filled up. If a queue is size 0, then this stat is incremented to a value of + * 1 when MAC receives its first frame. + * + * @rmac_pause_cnt: Count of number of pause quanta that the MAC has been in the + * paused state. Recall, one pause quantum equates to 512 bit times. + * @reserved_9: Reserved. + * @rmac_xgmii_data_err_cnt: This counter is incremented when either 1) The + * Reconcilliation Sublayer (RS) is expecting one control character and gets + * another (i.e. expecting Start control character and gets another control + * character); 2) Start control character is not in lane 0 or lane 4; 3) The RS + * gets a Start control character, but the start frame delimiter is not found in + * the correct location. + * @rmac_xgmii_ctrl_err_cnt: Maintains a count of unexpected or + * misplaced control characters occuring outside of normal data transmission + * (i.e. not included in RMAC_XGMII_DATA_ERR_CNT). + * + * @rmac_accepted_ip: Count of received IP datagrams that were passed to the + * system. + * + * @rmac_err_tcp: Count of received TCP segments containing errors. For example, + * bad TCP checksum. + * + * PCI (bus) Statistics: + * @rd_req_cnt: Counts the total number of read requests made by the device. + * @new_rd_req_cnt: Counts the requests made for a new read sequence (request + * made for the same sequence after a retry or disconnect response are not + * counted). + * @new_rd_req_rtry_cnt: Counts the Retry responses received on the start of + * the new read sequences. + * @rd_rtry_cnt: Counts the Retry responses received for read requests. + * @wr_rtry_rd_ack_cnt: Increments whenever a read request is accepted by + * the target after a write request was terminated with retry. + * @wr_req_cnt: Counts the total number of Write requests made by the device. + * @new_wr_req_cnt: Counts the requests made for a new write sequence (request + * made for the same sequence after a retry or disconnect response are not + * counted). + * @new_wr_req_rtry_cnt: Counts the requests made for a new write sequence + * (request made for the same sequence after a retry or disconnect response are + * not counted). + * + * @wr_rtry_cnt: Counts the Retry responses received for write requests. + * @wr_disc_cnt: Write Disconnect. Counts the target initiated disconnects + * on write transactions. + * @rd_rtry_wr_ack_cnt: Increments whenever a write request is accepted by the + * target after a read request was terminated with retry. + * + * @txp_wr_cnt: Counts the host write transactions to the Tx Pointer + * FIFOs. + * @txd_rd_cnt: Count of the Transmit Descriptor (TxD) read requests. + * @txd_wr_cnt: Count of the TxD write requests. + * @rxd_rd_cnt: Count of the Receive Descriptor (RxD) read requests. + * @rxd_wr_cnt: Count of the RxD write requests. + * @txf_rd_cnt: Count of transmit frame read requests. This will not + * equal the number of frames transmitted, as frame data is typically spread + * across multiple PCI transactions. + * @rxf_wr_cnt: Count of receive frame write requests. + * + * @tmac_frms_oflow: tbd + * @tmac_data_octets_oflow: tbd + * @tmac_mcst_frms_oflow: tbd + * @tmac_bcst_frms_oflow: tbd + * @tmac_ttl_octets_oflow: tbd + * @tmac_ucst_frms_oflow: tbd + * @tmac_nucst_frms_oflow: tbd + * @tmac_any_err_frms_oflow: tbd + * @tmac_vlan_frms: tbd + * @tmac_vld_ip_oflow: tbd + * @tmac_drop_ip_oflow: tbd + * @tmac_icmp_oflow: tbd + * @tmac_rst_tcp_oflow: tbd + * @tmac_udp_oflow: tbd + * @reserved_10: tbd + * @tpa_unknown_protocol: tbd + * @tpa_parse_failure: tbd + * @rmac_vld_frms_oflow: tbd + * @rmac_data_octets_oflow: tbd + * @rmac_vld_mcst_frms_oflow: tbd + * @rmac_vld_bcst_frms_oflow: tbd + * @rmac_ttl_octets_oflow: tbd + * @rmac_accepted_ucst_frms_oflow: tbd + * @rmac_accepted_nucst_frms_oflow: tbd + * @rmac_discarded_frms_oflow: tbd + * @rmac_drop_events_oflow: tbd + * @rmac_usized_frms_oflow: tbd + * @rmac_osized_frms_oflow: tbd + * @rmac_frag_frms_oflow: tbd + * @rmac_jabber_frms_oflow: tbd + * @rmac_ip_oflow: tbd + * @rmac_drop_ip_oflow: tbd + * @rmac_icmp_oflow: tbd + * @rmac_udp_oflow: tbd + * @reserved_11: tbd + * @rmac_err_drp_udp_oflow: tbd + * @rmac_pause_cnt_oflow: tbd + * @rmac_ttl_1519_4095_frms: tbd + * @rmac_ttl_4096_8191_frms: tbd + * @rmac_ttl_8192_max_frms: tbd + * @rmac_ttl_gt_max_frms: tbd + * @rmac_osized_alt_frms: tbd + * @rmac_jabber_alt_frms: tbd + * @rmac_gt_max_alt_frms: tbd + * @rmac_vlan_frms: tbd + * @rmac_fcs_discard: tbd + * @rmac_len_discard: tbd + * @rmac_da_discard: tbd + * @rmac_pf_discard: tbd + * @rmac_rts_discard: tbd + * @rmac_wol_discard: tbd + * @rmac_red_discard: tbd + * @rmac_ingm_full_discard: tbd + * @rmac_accepted_ip_oflow: tbd + * @reserved_12: tbd + * @link_fault_cnt: TBD + * @reserved_13: tbd + * Xframe hardware statistics. + */ +typedef struct xge_hal_stats_hw_info_t { +#ifdef XGE_OS_HOST_BIG_ENDIAN +/* Tx MAC statistics counters. */ + u32 tmac_frms; + u32 tmac_data_octets; + u64 tmac_drop_frms; + u32 tmac_mcst_frms; + u32 tmac_bcst_frms; + u64 tmac_pause_ctrl_frms; + u32 tmac_ttl_octets; + u32 tmac_ucst_frms; + u32 tmac_nucst_frms; + u32 tmac_any_err_frms; + u64 tmac_ttl_less_fb_octets; + u64 tmac_vld_ip_octets; + u32 tmac_vld_ip; + u32 tmac_drop_ip; + u32 tmac_icmp; + u32 tmac_rst_tcp; + u64 tmac_tcp; + u32 tmac_udp; + u32 reserved_0; + +/* Rx MAC Statistics counters. */ + u32 rmac_vld_frms; + u32 rmac_data_octets; + u64 rmac_fcs_err_frms; + u64 rmac_drop_frms; + u32 rmac_vld_mcst_frms; + u32 rmac_vld_bcst_frms; + u32 rmac_in_rng_len_err_frms; + u32 rmac_out_rng_len_err_frms; + u64 rmac_long_frms; + u64 rmac_pause_ctrl_frms; + u64 rmac_unsup_ctrl_frms; + u32 rmac_ttl_octets; + u32 rmac_accepted_ucst_frms; + u32 rmac_accepted_nucst_frms; + u32 rmac_discarded_frms; + u32 rmac_drop_events; + u32 reserved_1; + u64 rmac_ttl_less_fb_octets; + u64 rmac_ttl_frms; + u64 reserved_2; + u32 reserved_3; + u32 rmac_usized_frms; + u32 rmac_osized_frms; + u32 rmac_frag_frms; + u32 rmac_jabber_frms; + u32 reserved_4; + u64 rmac_ttl_64_frms; + u64 rmac_ttl_65_127_frms; + u64 reserved_5; + u64 rmac_ttl_128_255_frms; + u64 rmac_ttl_256_511_frms; + u64 reserved_6; + u64 rmac_ttl_512_1023_frms; + u64 rmac_ttl_1024_1518_frms; + u32 reserved_7; + u32 rmac_ip; + u64 rmac_ip_octets; + u32 rmac_hdr_err_ip; + u32 rmac_drop_ip; + u32 rmac_icmp; + u32 reserved_8; + u64 rmac_tcp; + u32 rmac_udp; + u32 rmac_err_drp_udp; + u64 rmac_xgmii_err_sym; + u64 rmac_frms_q0; + u64 rmac_frms_q1; + u64 rmac_frms_q2; + u64 rmac_frms_q3; + u64 rmac_frms_q4; + u64 rmac_frms_q5; + u64 rmac_frms_q6; + u64 rmac_frms_q7; + u16 rmac_full_q0; + u16 rmac_full_q1; + u16 rmac_full_q2; + u16 rmac_full_q3; + u16 rmac_full_q4; + u16 rmac_full_q5; + u16 rmac_full_q6; + u16 rmac_full_q7; + u32 rmac_pause_cnt; + u32 reserved_9; + u64 rmac_xgmii_data_err_cnt; + u64 rmac_xgmii_ctrl_err_cnt; + u32 rmac_accepted_ip; + u32 rmac_err_tcp; + +/* PCI/PCI-X Read transaction statistics. */ + u32 rd_req_cnt; + u32 new_rd_req_cnt; + u32 new_rd_req_rtry_cnt; + u32 rd_rtry_cnt; + u32 wr_rtry_rd_ack_cnt; + +/* PCI/PCI-X write transaction statistics. */ + u32 wr_req_cnt; + u32 new_wr_req_cnt; + u32 new_wr_req_rtry_cnt; + u32 wr_rtry_cnt; + u32 wr_disc_cnt; + u32 rd_rtry_wr_ack_cnt; + +/* DMA Transaction statistics. */ + u32 txp_wr_cnt; + u32 txd_rd_cnt; + u32 txd_wr_cnt; + u32 rxd_rd_cnt; + u32 rxd_wr_cnt; + u32 txf_rd_cnt; + u32 rxf_wr_cnt; + +/* Enhanced Herc statistics */ + u32 tmac_frms_oflow; + u32 tmac_data_octets_oflow; + u32 tmac_mcst_frms_oflow; + u32 tmac_bcst_frms_oflow; + u32 tmac_ttl_octets_oflow; + u32 tmac_ucst_frms_oflow; + u32 tmac_nucst_frms_oflow; + u32 tmac_any_err_frms_oflow; + u64 tmac_vlan_frms; + u32 tmac_vld_ip_oflow; + u32 tmac_drop_ip_oflow; + u32 tmac_icmp_oflow; + u32 tmac_rst_tcp_oflow; + u32 tmac_udp_oflow; + u32 tpa_unknown_protocol; + u32 tpa_parse_failure; + u32 reserved_10; + u32 rmac_vld_frms_oflow; + u32 rmac_data_octets_oflow; + u32 rmac_vld_mcst_frms_oflow; + u32 rmac_vld_bcst_frms_oflow; + u32 rmac_ttl_octets_oflow; + u32 rmac_accepted_ucst_frms_oflow; + u32 rmac_accepted_nucst_frms_oflow; + u32 rmac_discarded_frms_oflow; + u32 rmac_drop_events_oflow; + u32 rmac_usized_frms_oflow; + u32 rmac_osized_frms_oflow; + u32 rmac_frag_frms_oflow; + u32 rmac_jabber_frms_oflow; + u32 rmac_ip_oflow; + u32 rmac_drop_ip_oflow; + u32 rmac_icmp_oflow; + u32 rmac_udp_oflow; + u32 rmac_err_drp_udp_oflow; + u32 rmac_pause_cnt_oflow; + u32 reserved_11; + u64 rmac_ttl_1519_4095_frms; + u64 rmac_ttl_4096_8191_frms; + u64 rmac_ttl_8192_max_frms; + u64 rmac_ttl_gt_max_frms; + u64 rmac_osized_alt_frms; + u64 rmac_jabber_alt_frms; + u64 rmac_gt_max_alt_frms; + u64 rmac_vlan_frms; + u32 rmac_fcs_discard; + u32 rmac_len_discard; + u32 rmac_da_discard; + u32 rmac_pf_discard; + u32 rmac_rts_discard; + u32 rmac_wol_discard; + u32 rmac_red_discard; + u32 rmac_ingm_full_discard; + u32 rmac_accepted_ip_oflow; + u32 reserved_12; + u32 link_fault_cnt; + u32 reserved_13; +#else +/* Tx MAC statistics counters. */ + u32 tmac_data_octets; + u32 tmac_frms; + u64 tmac_drop_frms; + u32 tmac_bcst_frms; + u32 tmac_mcst_frms; + u64 tmac_pause_ctrl_frms; + u32 tmac_ucst_frms; + u32 tmac_ttl_octets; + u32 tmac_any_err_frms; + u32 tmac_nucst_frms; + u64 tmac_ttl_less_fb_octets; + u64 tmac_vld_ip_octets; + u32 tmac_drop_ip; + u32 tmac_vld_ip; + u32 tmac_rst_tcp; + u32 tmac_icmp; + u64 tmac_tcp; + u32 reserved_0; + u32 tmac_udp; + +/* Rx MAC Statistics counters. */ + u32 rmac_data_octets; + u32 rmac_vld_frms; + u64 rmac_fcs_err_frms; + u64 rmac_drop_frms; + u32 rmac_vld_bcst_frms; + u32 rmac_vld_mcst_frms; + u32 rmac_out_rng_len_err_frms; + u32 rmac_in_rng_len_err_frms; + u64 rmac_long_frms; + u64 rmac_pause_ctrl_frms; + u64 rmac_unsup_ctrl_frms; + u32 rmac_accepted_ucst_frms; + u32 rmac_ttl_octets; + u32 rmac_discarded_frms; + u32 rmac_accepted_nucst_frms; + u32 reserved_1; + u32 rmac_drop_events; + u64 rmac_ttl_less_fb_octets; + u64 rmac_ttl_frms; + u64 reserved_2; + u32 rmac_usized_frms; + u32 reserved_3; + u32 rmac_frag_frms; + u32 rmac_osized_frms; + u32 reserved_4; + u32 rmac_jabber_frms; + u64 rmac_ttl_64_frms; + u64 rmac_ttl_65_127_frms; + u64 reserved_5; + u64 rmac_ttl_128_255_frms; + u64 rmac_ttl_256_511_frms; + u64 reserved_6; + u64 rmac_ttl_512_1023_frms; + u64 rmac_ttl_1024_1518_frms; + u32 rmac_ip; + u32 reserved_7; + u64 rmac_ip_octets; + u32 rmac_drop_ip; + u32 rmac_hdr_err_ip; + u32 reserved_8; + u32 rmac_icmp; + u64 rmac_tcp; + u32 rmac_err_drp_udp; + u32 rmac_udp; + u64 rmac_xgmii_err_sym; + u64 rmac_frms_q0; + u64 rmac_frms_q1; + u64 rmac_frms_q2; + u64 rmac_frms_q3; + u64 rmac_frms_q4; + u64 rmac_frms_q5; + u64 rmac_frms_q6; + u64 rmac_frms_q7; + u16 rmac_full_q3; + u16 rmac_full_q2; + u16 rmac_full_q1; + u16 rmac_full_q0; + u16 rmac_full_q7; + u16 rmac_full_q6; + u16 rmac_full_q5; + u16 rmac_full_q4; + u32 reserved_9; + u32 rmac_pause_cnt; + u64 rmac_xgmii_data_err_cnt; + u64 rmac_xgmii_ctrl_err_cnt; + u32 rmac_err_tcp; + u32 rmac_accepted_ip; + +/* PCI/PCI-X Read transaction statistics. */ + u32 new_rd_req_cnt; + u32 rd_req_cnt; + u32 rd_rtry_cnt; + u32 new_rd_req_rtry_cnt; + +/* PCI/PCI-X Write/Read transaction statistics. */ + u32 wr_req_cnt; + u32 wr_rtry_rd_ack_cnt; + u32 new_wr_req_rtry_cnt; + u32 new_wr_req_cnt; + u32 wr_disc_cnt; + u32 wr_rtry_cnt; + +/* PCI/PCI-X Write / DMA Transaction statistics. */ + u32 txp_wr_cnt; + u32 rd_rtry_wr_ack_cnt; + u32 txd_wr_cnt; + u32 txd_rd_cnt; + u32 rxd_wr_cnt; + u32 rxd_rd_cnt; + u32 rxf_wr_cnt; + u32 txf_rd_cnt; + +/* Enhanced Herc statistics */ + u32 tmac_data_octets_oflow; + u32 tmac_frms_oflow; + u32 tmac_bcst_frms_oflow; + u32 tmac_mcst_frms_oflow; + u32 tmac_ucst_frms_oflow; + u32 tmac_ttl_octets_oflow; + u32 tmac_any_err_frms_oflow; + u32 tmac_nucst_frms_oflow; + u64 tmac_vlan_frms; + u32 tmac_drop_ip_oflow; + u32 tmac_vld_ip_oflow; + u32 tmac_rst_tcp_oflow; + u32 tmac_icmp_oflow; + u32 tpa_unknown_protocol; + u32 tmac_udp_oflow; + u32 reserved_10; + u32 tpa_parse_failure; + u32 rmac_data_octets_oflow; + u32 rmac_vld_frms_oflow; + u32 rmac_vld_bcst_frms_oflow; + u32 rmac_vld_mcst_frms_oflow; + u32 rmac_accepted_ucst_frms_oflow; + u32 rmac_ttl_octets_oflow; + u32 rmac_discarded_frms_oflow; + u32 rmac_accepted_nucst_frms_oflow; + u32 rmac_usized_frms_oflow; + u32 rmac_drop_events_oflow; + u32 rmac_frag_frms_oflow; + u32 rmac_osized_frms_oflow; + u32 rmac_ip_oflow; + u32 rmac_jabber_frms_oflow; + u32 rmac_icmp_oflow; + u32 rmac_drop_ip_oflow; + u32 rmac_err_drp_udp_oflow; + u32 rmac_udp_oflow; + u32 reserved_11; + u32 rmac_pause_cnt_oflow; + u64 rmac_ttl_1519_4095_frms; + u64 rmac_ttl_4096_8191_frms; + u64 rmac_ttl_8192_max_frms; + u64 rmac_ttl_gt_max_frms; + u64 rmac_osized_alt_frms; + u64 rmac_jabber_alt_frms; + u64 rmac_gt_max_alt_frms; + u64 rmac_vlan_frms; + u32 rmac_len_discard; + u32 rmac_fcs_discard; + u32 rmac_pf_discard; + u32 rmac_da_discard; + u32 rmac_wol_discard; + u32 rmac_rts_discard; + u32 rmac_ingm_full_discard; + u32 rmac_red_discard; + u32 reserved_12; + u32 rmac_accepted_ip_oflow; + u32 reserved_13; + u32 link_fault_cnt; +#endif +} xge_hal_stats_hw_info_t; + +/** + * struct xge_hal_stats_channel_into_t - HAL channel statistics. + * @full_cnt: TBD + * @usage_max: TBD + * @reserve_free_swaps_cnt: Reserve/free swap counter. Internal usage. + * @max_compl_per_intr_cnt: Maximum number of completions per interrupt. + * @avg_compl_per_intr_cnt: Average number of completions per interrupt. + * Note that a total number of completed descriptors + * for the given channel can be calculated as + * (@traffic_intr_cnt * @avg_compl_per_intr_cnt). + * @total_compl_cnt: Total completion count. + * @total_compl_cnt == (@traffic_intr_cnt * @avg_compl_per_intr_cnt). + * @total_posts: Total number of descriptor postings on the channel. + * Counts the number of xge_hal_ring_dtr_post() + * or xge_hal_fifo_dtr_post() calls by ULD, for ring and fifo + * channel, respectively. + * @total_posts_many: Total number of posts on the channel that involved + * more than one descriptor. Counts the number of + * xge_hal_fifo_dtr_post_many() calls performed by ULD. + * @total_buffers: Total number of buffers posted on the channel. + * @copied_frags: TBD + * @copied_buffers: TBD + * @avg_buffers_per_post: Average number of buffers transferred in a single + * post operation. + * Calculated as @total_buffers/@total_posts. + * @avg_buffer_size: Average buffer size transferred by a single post + * operation on a fifo channel. The counter is not supported for a ring + * channel. Calculated as a total number of transmitted octets divided + * by @total_buffers. + * @avg_post_size: Average amount of data transferred by a single post. + * Calculated as a total number of transmitted octets divided by + * @total_posts. + * @ring_bump_cnt: Ring "bump" count. Number of times the hardware could + * not post receive data (and had to continue keeping it on-board) + * because of unavailable receive descriptor(s). + * @total_posts_dtrs_many: Total number of posts on the channel that involving + * more than one descriptor. + * @total_posts_frags_many: Total number of fragments posted on the channel + * during post requests of multiple descriptors. + * @total_posts_dang_dtrs: Total number of posts on the channel involving + * dangling descriptors. + * @total_posts_dang_frags: Total number of dangling fragments posted on the channel + * during post request containing multiple descriptors. + * + * HAL channel counters. + * See also: xge_hal_stats_device_info_t{}. + */ +typedef struct xge_hal_stats_channel_info_t { + u32 full_cnt; + u32 usage_max; + u32 reserve_free_swaps_cnt; + u32 avg_compl_per_intr_cnt; + u32 total_compl_cnt; + u32 total_posts; + u32 total_posts_many; + u32 total_buffers; + u32 copied_frags; + u32 copied_buffers; + u32 avg_buffers_per_post; + u32 avg_buffer_size; + u32 avg_post_size; + u32 ring_bump_cnt; + u32 total_posts_dtrs_many; + u32 total_posts_frags_many; + u32 total_posts_dang_dtrs; + u32 total_posts_dang_frags; +} xge_hal_stats_channel_info_t; + +/** + * struct xge_hal_xpak_counter_t - HAL xpak error counters + * @excess_temp: excess transceiver_temperature count + * @excess_bias_current: excess laser_bias_current count + * @excess_laser_output: excess laser_output_power count + * @tick_period: tick count for each cycle + */ +typedef struct xge_hal_xpak_counter_t { + u32 excess_temp; + u32 excess_bias_current; + u32 excess_laser_output; + u32 tick_period; +} xge_hal_xpak_counter_t; + +/** + * struct xge_hal_stats_xpak_t - HAL xpak stats + * @alarm_transceiver_temp_high: alarm_transceiver_temp_high count value + * @alarm_transceiver_temp_low : alarm_transceiver_temp_low count value + * @alarm_laser_bias_current_high: alarm_laser_bias_current_high count value + * @alarm_laser_bias_current_low: alarm_laser_bias_current_low count value + * @alarm_laser_output_power_high: alarm_laser_output_power_high count value + * @alarm_laser_output_power_low: alarm_laser_output_power_low count value + * @warn_transceiver_temp_high: warn_transceiver_temp_high count value + * @warn_transceiver_temp_low: warn_transceiver_temp_low count value + * @warn_laser_bias_current_high: warn_laser_bias_current_high count value + * @warn_laser_bias_current_low: warn_laser_bias_current_low count value + * @warn_laser_output_power_high: warn_laser_output_power_high count value + * @warn_laser_output_power_low: warn_laser_output_power_low count value + */ +typedef struct xge_hal_stats_xpak_t { + u16 alarm_transceiver_temp_high; + u16 alarm_transceiver_temp_low; + u16 alarm_laser_bias_current_high; + u16 alarm_laser_bias_current_low; + u16 alarm_laser_output_power_high; + u16 alarm_laser_output_power_low; + u16 warn_transceiver_temp_high; + u16 warn_transceiver_temp_low; + u16 warn_laser_bias_current_high; + u16 warn_laser_bias_current_low; + u16 warn_laser_output_power_high; + u16 warn_laser_output_power_low; +} xge_hal_stats_xpak_t; + + + +/** + * struct xge_hal_stats_sw_err_t - HAL device error statistics. + * @sm_err_cnt: TBD + * @single_ecc_err_cnt: TBD + * @double_ecc_err_cnt: TBD + * @ecc_err_cnt: ECC error count. + * @parity_err_cnt: Parity error count. + * @serr_cnt: Number of exceptions indicated to the host via PCI SERR#. + * @rxd_t_code_err_cnt: Array of receive transfer codes. The position + * (index) in this array reflects the transfer code type, for instance + * 0x7 - for "invalid receive buffer size", or 0x8 - for ECC. + * Value rxd_t_code_err_cnt[i] reflects the + * number of times the corresponding transfer code was encountered. + * + * @txd_t_code_err_cnt: Array of transmit transfer codes. The position + * (index) in this array reflects the transfer code type, for instance + * 0xA - "loss of link". + * Value txd_t_code_err_cnt[i] reflects the + * number of times the corresponding transfer code was encountered. + * @stats_xpak: TBD + * @xpak_counter: TBD + */ +typedef struct xge_hal_stats_sw_err_t { + u32 sm_err_cnt; + u32 single_ecc_err_cnt; + u32 double_ecc_err_cnt; + u32 ecc_err_cnt; + u32 parity_err_cnt; + u32 serr_cnt; + u32 rxd_t_code_err_cnt[16]; + u32 txd_t_code_err_cnt[16]; + xge_hal_stats_xpak_t stats_xpak; + xge_hal_xpak_counter_t xpak_counter; +} xge_hal_stats_sw_err_t; + +/** + * struct xge_hal_stats_device_info_t - HAL own per-device statistics. + * + * @rx_traffic_intr_cnt: TBD + * @tx_traffic_intr_cnt: TBD + * @txpic_intr_cnt: TBD + * @txdma_intr_cnt: TBD + * @txmac_intr_cnt: TBD + * @txxgxs_intr_cnt: TBD + * @rxpic_intr_cnt: TBD + * @rxdma_intr_cnt: TBD + * @rxmac_intr_cnt: TBD + * @rxxgxs_intr_cnt: TBD + * @mc_intr_cnt: TBD + * @not_traffic_intr_cnt: Number of times the host was interrupted + * without new completions. + * "Non-traffic interrupt counter". + * @not_xge_intr_cnt: TBD + * @traffic_intr_cnt: Number of traffic interrupts for the device. + * @total_intr_cnt: Total number of traffic interrupts for the device. + * @total_intr_cnt == @traffic_intr_cnt + + * @not_traffic_intr_cnt + * @soft_reset_cnt: Number of times soft reset is done on this device. + * @rxufca_hi_adjust_cnt: TODO + * @rxufca_lo_adjust_cnt: TODO + * @bimodal_hi_adjust_cnt: TODO + * @bimodal_lo_adjust_cnt: TODO + * + * @tot_frms_lroised: TBD + * @tot_lro_sessions: TBD + * @lro_frm_len_exceed_cnt: TBD + * @lro_sg_exceed_cnt: TBD + * @lro_out_of_seq_pkt_cnt: TBD + * @lro_dup_pkt_cnt: TBD + * + * HAL per-device statistics. + * See also: xge_hal_stats_channel_info_t{}. + */ +typedef struct xge_hal_stats_device_info_t { + u32 rx_traffic_intr_cnt; + u32 tx_traffic_intr_cnt; + u32 txpic_intr_cnt; + u32 txdma_intr_cnt; + u32 pfc_err_cnt; + u32 tda_err_cnt; + u32 pcc_err_cnt; + u32 tti_err_cnt; + u32 lso_err_cnt; + u32 tpa_err_cnt; + u32 sm_err_cnt; + u32 txmac_intr_cnt; + u32 mac_tmac_err_cnt; + u32 txxgxs_intr_cnt; + u32 xgxs_txgxs_err_cnt; + u32 rxpic_intr_cnt; + u32 rxdma_intr_cnt; + u32 rc_err_cnt; + u32 rpa_err_cnt; + u32 rda_err_cnt; + u32 rti_err_cnt; + u32 rxmac_intr_cnt; + u32 mac_rmac_err_cnt; + u32 rxxgxs_intr_cnt; + u32 xgxs_rxgxs_err_cnt; + u32 mc_intr_cnt; + u32 not_traffic_intr_cnt; + u32 not_xge_intr_cnt; + u32 traffic_intr_cnt; + u32 total_intr_cnt; + u32 soft_reset_cnt; + u32 rxufca_hi_adjust_cnt; + u32 rxufca_lo_adjust_cnt; + u32 bimodal_hi_adjust_cnt; + u32 bimodal_lo_adjust_cnt; +#ifdef XGE_HAL_CONFIG_LRO + u32 tot_frms_lroised; + u32 tot_lro_sessions; + u32 lro_frm_len_exceed_cnt; + u32 lro_sg_exceed_cnt; + u32 lro_out_of_seq_pkt_cnt; + u32 lro_dup_pkt_cnt; +#endif +} xge_hal_stats_device_info_t; + +#ifdef XGEHAL_RNIC + +/** + * struct xge_hal_vp_statistics_t - Virtual Path Statistics + * + * @no_nces: Number of NCEs on Adapter in this VP + * @no_sqs: Number of SQs on Adapter in this VP + * @no_srqs: Number of SRQs on Adapter in this VP + * @no_cqrqs: Number of CQRQs on Adapter in this VP + * @no_tcp_sessions: Number of TCP sessions on Adapter in this VP + * @no_lro_sessions: Number of LRO sessions on Adapter in this VP + * @no_spdm_sessions: Number of SPDM sessions on Adapter in this VP + * + * This structure contains fields to keep statistics of virtual path + */ +typedef struct xge_hal_vp_statistics_t { + u32 no_nces; + u32 no_sqs; + u32 no_srqs; + u32 no_cqrqs; + u32 no_tcp_sessions; + u32 no_lro_sessions; + u32 no_spdm_sessions; +}xge_hal_vp_statistics_t; + +#endif + + +/* ========================== XFRAME ER STATISTICS ======================== */ +#define XGE_HAL_MAC_LINKS 3 +#define XGE_HAL_MAC_AGGREGATORS 2 +#define XGE_HAL_VPATHS 17 +/** + * struct xge_hal_stats_link_info_t - XGMAC statistics for a link + * + * @tx_frms: Count of transmitted MAC frames for mac the link. + * @tx_ttl_eth_octets: Count of total octets of transmitted frames + * for mac the link. + * @tx_data_octets: Count of data and padding octets of transmitted + * frames for mac the link. + * @tx_mcst_frms: Count of multicast MAC frames for mac the link. + * @tx_bcst_frms: Count of broadcast MAC frames for mac the link. + * @tx_ucst_frms: Count of unicast MAC frames for mac the link. + * @tx_tagged_frms: Count of transmitted frames containing a VLAN tag + * for mac the link. + * @tx_vld_ip: Count of transmitted IP datagrams for mac the link. + * @tx_vld_ip_octets: Count of transmitted IP octets for mac the link. + * @tx_icmp: Count of transmitted ICMP messages for mac the link. + * @tx_tcp: Count of transmitted TCP segments for mac the link. + * @tx_rst_tcp: Count of transmitted TCP segments containing the RST + * flag mac the link. + * @tx_udp: Count of transmitted UDP datagrams for mac the link. + * @tx_unknown_protocol: Count of transmitted packets of unknown + * protocol for mac the link. + * @tx_parse_error: Count of transmitted packets with parsing errors + * for mac the link. + * @tx_pause_ctrl_frms: Count of MAC PAUSE control frames for mac + * the link. + * @tx_lacpdu_frms: Count of LACPDUs transmitted for mac the link. + * @tx_marker_pdu_frms: Count of Marker PDUs transmitted for mac the + * link. + * @tx_marker_resp_pdu_frms: Count of Marker Response PDUs transmitted + * for mac the link. + * @tx_drop_ip: Count of dropped IP packets from the transmission path + * for mac the link. + * @tx_xgmii_char1_match: Count of the number of transmitted XGMII + * characters that match first pattern, for mac the link. + * @tx_xgmii_char2_match: Count of the number of transmitted XGMII + * characters that match second pattern, for mac the link. + * @tx_xgmii_column1_match: Count of the number of transmitted XGMII + * columns that match first pattern, for mac the link. + * @tx_xgmii_column2_match: Count of the number of transmitted XGMII + * columns that match second pattern, for mac the link. + * @tx_drop_frms: Count of frames dropped due to internal errors during + * transmission for mac the link. + * @tx_any_err_frms: Count of frames dropped due to any error during + * transmission for mac the link. + * @rx_ttl_frms: Count of all received MAC frames for mac the link. + * @rx_vld_frms: Count of all successfully received MAC frames for mac + * the link. + * @rx_offld_frms: Count of all offloaded received MAC frames for mac + * the link. + * @rx_ttl_eth_octets: Count of total octets of received frames, not + * including framing characters for mac the link. + * @rx_data_octets: Count of data and padding octets of successfully + * received frames for mac the link. + * @rx_offld_octets: Count of total octets, not including framing + * characters, of offloaded received frames for mac the link. + * @rx_vld_mcst_frms: Count of successfully received multicast MAC + * frames for mac the link. + * @rx_vld_bcst_frms: Count of successfully received broadcast MAC + * frames for mac the link. + * @rx_accepted_ucst_frms: Count of successfully received unicast MAC + * frames for mac the link. + * @rx_accepted_nucst_frms: Count of successfully received non-unicast + * MAC frames for mac the link. + * @rx_tagged_frms: Count of received frames containing a VLAN tag for + * mac the link. + * @rx_long_frms: Count of received frames that are longer than + * RX_MAX_PYLD_LEN + 18 bytes (+ 22 bytes if VLAN-tagged) for mac the link. + * @rx_usized_frms: Count of received frames of length less than 64 + * octets, for mac the link. + * @rx_osized_frms: Count of received frames of length more than 1518 + * octets for mac the link. + * @rx_frag_frms: Count of received frames of length less than 64 + * octets that had bad FCS, for mac the link. + * @rx_jabber_frms: Count of received frames of length more than 1518 + * octets that had bad FCS, for mac the link. + * @rx_ttl_64_frms: Count of all received MAC frames with length of + * exactly 64 octets, for mac the link. + * @rx_ttl_65_127_frms: Count of all received MAC frames with length + * of between 65 and 127 octets inclusive, for mac the link. + * @rx_ttl_128_255_frms: Count of all received MAC frames with length + * of between 128 and 255 octets inclusive, for mac the link. + * @rx_ttl_256_511_frms: Count of all received MAC frames with length + * of between 246 and 511 octets inclusive, for mac the link. + * @rx_ttl_512_1023_frms: Count of all received MAC frames with length + * of between 512 and 1023 octets inclusive, for mac the link. + * @rx_ttl_1024_1518_frms: Count of all received MAC frames with length + * of between 1024 and 1518 octets inclusive, for mac the link. + * @rx_ttl_1519_4095_frms: Count of all received MAC frames with length + * of between 1519 and 4095 octets inclusive, for mac the link. + * @rx_ttl_40956_8191_frms: Count of all received MAC frames with length + * of between 4096 and 8191 octets inclusive, for mac the link. + * @rx_ttl_8192_max_frms: Count of all received MAC frames with length + * of between 8192 and RX_MAX_PYLD_LEN+18 octets inclusive, for mac the link. + * @rx_ttl_gt_max_frms: Count of all received MAC frames with length + * exceeding RX_MAX_PYLD_LEN+18 octets inclusive, for mac the link. + * @rx_ip: Count of received IP datagrams, for mac the link. + * @rx_accepted_ip: Count of received and accepted IP datagrams, + * for mac the link. + * @rx_ip_octets: Count of number of octets in received IP datagrams, + * for mac the link. + * @rx_hdr_err_ip: Count of received IP datagrams that are discarded + * due to IP header errors, for mac the link. + * @rx_icmp: Count of received ICMP messages for mac the link. + * @rx_tcp: Count of received TCP segments for mac the link. + * @rx_udp: Count of received UDP datagrams for mac the link. + * @rx_err_tcp: Count of received TCP segments containing errors for + * mac the link. + * @rx_pause_cnt: Count of number of pause quanta that the MAC has + * been in the paused state, for mac the link. + * @rx_pause_ctrl_frms: Count of received MAC PAUSE control frames for + * mac the link. + * @rx_unsup_ctrl_frms: Count of received MAC control frames that do + * not contain the PAUSE opcode for mac the link. + * @rx_fcs_err_frms: Count of received MAC frames that do not pass FCS + * for mac the link. + * @rx_in_rng_len_err_frms: Count of received frames with a length/type + * field value between 46 and 1500 inclusive, that does not match the number + * of data octets received, for mac the link. + * @rx_out_rng_len_err_frms: Count of received frames with length/type + * field between 1501 and 1535 decimal, inclusive. for mac the link. + * @rx_drop_frms: Count of dropped frames from receive path for mac + * the link. + * @rx_discarded_frms: Count of discarded frames from receive path for + * mac the link. + * @rx_drop_ip: Count of droppen IP datagrams from receive path for + * mac the link. + * @rx_err_drp_udp: Count of droppen UDP datagrams from receive path + * for mac the link. + * @rx_lacpdu_frms: Count of valid LACPDUs received for mac the link. + * @rx_marker_pdu_frms: Count of valid Marker PDUs received for mac + * the link. + * @rx_marker_resp_pdu_frms: Count of valid Marker Response PDUs + * received for mac the link. + * @rx_unknown_pdu_frms: Count of unknown PDUs received for mac the link. + * @rx_illegal_pdu_frms: Count of illegal PDUs received for mac the link. + * @rx_fcs_discard: Count of discarded PDUs received for mac the link. + * @rx_len_discard: Count of received frames that were discarded + * because of an invalid frame length, for mac the link. + * @rx_len_discard: Count of received frames that were discarded + * because of an invalid destination MAC address, for mac the link. + * @rx_pf_discard: Count of received frames that were discarded for + * mac the link. + * @rx_trash_discard: Count of received frames that were steered to the + * trash queue for mac the link. + * @rx_rts_discard: Count of received frames that were discarded by RTS + * logic for mac the link. + * @rx_wol_discard: Count of received frames that were discarded by WOL + * logic for mac the link. + * @rx_red_discard: Count of received frames that were discarded by RED + * logic for mac the link. + * @rx_ingm_full_discard: Count of received frames that were discarded + * because the internal ingress memory was full for mac the link. + * @rx_xgmii_data_err_cnt: Count of unexpected control characters + * during normal data transmission for mac the link. + * @rx_xgmii_ctrl_err_cnt: Count of unexpected or misplaced control + * characters occuring between times of normal data transmission for mac + * the link. + * @rx_xgmii_err_sym: Count of the number of symbol errors in the + * received XGMII data for mac the link. + * @rx_xgmii_char1_match: Count of the number of XGMII characters + * that match first pattern defined in MAC_STATS_RX_XGMII_CHAR_LINK_N. + * @rx_xgmii_char2_match: Count of the number of XGMII characters + * that match second pattern defined in MAC_STATS_RX_XGMII_CHAR_LINK_N. + * @rx_xgmii_column1_match: Count of the number of XGMII columns + * that match a pattern defined in MAC_STATS_RX_XGMII_COLUMN1_LINK_N. + * @rx_xgmii_column2_match: Count of the number of XGMII columns + * that match a pattern defined in MAC_STATS_RX_XGMII_COLUMN1_LINK_N. + * @rx_local_fault: Count of the number of local faults for mac the link. + * @rx_remote_fault: Count of the number of remote faults for mac the + * link. + * @rx_queue_full: Count of the number of frame destined for a full + * queue for mac the link. + */ +typedef struct xge_hal_stats_link_info_t { + u64 tx_frms; + u64 tx_ttl_eth_octets; + u64 tx_data_octets; + u64 tx_mcst_frms; + u64 tx_bcst_frms; + u64 tx_ucst_frms; + u64 tx_tagged_frms; + u64 tx_vld_ip; + u64 tx_vld_ip_octets; + u64 tx_icmp; + u64 tx_tcp; + u64 tx_rst_tcp; + u64 tx_udp; + u64 tx_unknown_protocol; + u64 tx_parse_error; + u64 tx_pause_ctrl_frms; + u64 tx_lacpdu_frms; + u64 tx_marker_pdu_frms; + u64 tx_marker_resp_pdu_frms; + u64 tx_drop_ip; + u64 tx_xgmii_char1_match; + u64 tx_xgmii_char2_match; + u64 tx_xgmii_column1_match; + u64 tx_xgmii_column2_match; + u64 tx_drop_frms; + u64 tx_any_err_frms; + u64 rx_ttl_frms; + u64 rx_vld_frms; + u64 rx_offld_frms; + u64 rx_ttl_eth_octets; + u64 rx_data_octets; + u64 rx_offld_octets; + u64 rx_vld_mcst_frms; + u64 rx_vld_bcst_frms; + u64 rx_accepted_ucst_frms; + u64 rx_accepted_nucst_frms; + u64 rx_tagged_frms; + u64 rx_long_frms; + u64 rx_usized_frms; + u64 rx_osized_frms; + u64 rx_frag_frms; + u64 rx_jabber_frms; + u64 rx_ttl_64_frms; + u64 rx_ttl_65_127_frms; + u64 rx_ttl_128_255_frms; + u64 rx_ttl_256_511_frms; + u64 rx_ttl_512_1023_frms; + u64 rx_ttl_1024_1518_frms; + u64 rx_ttl_1519_4095_frms; + u64 rx_ttl_40956_8191_frms; + u64 rx_ttl_8192_max_frms; + u64 rx_ttl_gt_max_frms; + u64 rx_ip; + u64 rx_ip_octets; + u64 rx_hdr_err_ip; + u64 rx_icmp; + u64 rx_tcp; + u64 rx_udp; + u64 rx_err_tcp; + u64 rx_pause_cnt; + u64 rx_pause_ctrl_frms; + u64 rx_unsup_ctrl_frms; + u64 rx_in_rng_len_err_frms; + u64 rx_out_rng_len_err_frms; + u64 rx_drop_frms; + u64 rx_discarded_frms; + u64 rx_drop_ip; + u64 rx_err_drp_udp; + u64 rx_lacpdu_frms; + u64 rx_marker_pdu_frms; + u64 rx_marker_resp_pdu_frms; + u64 rx_unknown_pdu_frms; + u64 rx_illegal_pdu_frms; + u64 rx_fcs_discard; + u64 rx_len_discard; + u64 rx_pf_discard; + u64 rx_trash_discard; + u64 rx_rts_discard; + u64 rx_wol_discard; + u64 rx_red_discard; + u64 rx_ingm_full_discard; + u64 rx_xgmii_data_err_cnt; + u64 rx_xgmii_ctrl_err_cnt; + u64 rx_xgmii_err_sym; + u64 rx_xgmii_char1_match; + u64 rx_xgmii_char2_match; + u64 rx_xgmii_column1_match; + u64 rx_xgmii_column2_match; + u64 rx_local_fault; + u64 rx_remote_fault; + u64 rx_queue_full; +}xge_hal_stats_link_info_t; + +/** + * struct xge_hal_stats_aggr_info_t - XGMAC statistics for an aggregator + * + * @tx_frms: Count of data frames transmitted for the aggregator. + * @tx_mcst_frms: Count of multicast data frames transmitted for + * the aggregator. + * @tx_bcst_frms: Count of broadcast data frames transmitted for + * the aggregator. + * @tx_discarded_frms: Count of discarded data frames transmitted for + * the aggregator. + * @tx_errored_frms: Count of errored data frames transmitted for + * the aggregator. + * @rx_frms: Count of received frames for aggregators + * @rx_data_octets: Count of data and padding octets of frames received + * the aggregator. + * @rx_mcst_frms: Count of multicast frames received the aggregator. + * @rx_bcst_frms: Count of broadast frames received the aggregator. + * @rx_discarded_frms: Count of discarded frames received the aggregator. + * @rx_errored_frms: Count of errored frames received the aggregator. + * @rx_unknown_protocol_frms: Count of unknown protocol frames received + * the aggregator. +*/ +typedef struct xge_hal_stats_aggr_info_t { + u64 tx_frms; + u64 tx_mcst_frms; + u64 tx_bcst_frms; + u64 tx_discarded_frms; + u64 tx_errored_frms; + u64 rx_frms; + u64 rx_data_octets; + u64 rx_mcst_frms; + u64 rx_bcst_frms; + u64 rx_discarded_frms; + u64 rx_errored_frms; + u64 rx_unknown_protocol_frms; +}xge_hal_stats_aggr_info_t; + +/** + * struct xge_hal_stats_vpath_info_t - XGMAC statistics for a vpath. + * + * @tx_frms: Count of transmitted MAC frames for the vpath. + * @tx_ttl_eth_octets: Count of total octets of transmitted frames + * for the vpath. + * @tx_data_octets: Count of data and padding octets of transmitted + * frames for the vpath. + * @tx_mcst_frms: Count of multicast MAC frames for the vpath. + * @tx_bcst_frms: Count of broadcast MAC frames for the vpath. + * @tx_ucst_frms: Count of unicast MAC frames for the vpath. + * @tx_tagged_frms: Count of transmitted frames containing a VLAN + * tag for the vpath. + * @tx_vld_ip: Count of transmitted IP datagrams for the vpath. + * @tx_vld_ip_octets: Count of transmitted IP octets for the vpath. + * @tx_icmp: Count of transmitted ICMP messages for the vpath. + * @tx_tcp: Count of transmitted TCP segments for the vpath. + * @tx_rst_tcp: Count of transmitted TCP segments containing the RST + * flag the vpath. + * @tx_udp: Count of transmitted UDP datagrams for the vpath. + * @tx_unknown_protocol: Count of transmitted packets of unknown + * protocol for the vpath. + * @tx_parse_error: Count of transmitted packets with parsing errors + * for the vpath. + * @rx_ttl_frms: Count of all received MAC frames for the vpath. + * @rx_vld_frms: Count of all successfully received MAC frames for + * the vpath. + * @rx_offld_frms: Count of all offloaded received MAC frames for + * the vpath. + * @rx_ttl_eth_octets: Count of total octets of received frames, not + * including framing characters for the vpath. + * @rx_data_octets: Count of data and padding octets of successfully + * received frames for the vpath. + * @rx_offld_octets: Count of total octets, not including framing + * characters, of offloaded received frames for the vpath. + * @rx_vld_mcst_frms: Count of successfully received multicast MAC + * frames for the vpath. + * @rx_vld_bcst_frms: Count of successfully received broadcast MAC + * frames for the vpath. + * @rx_accepted_ucst_frms: Count of successfully received unicast + * MAC frames for the vpath. + * @rx_accepted_nucst_frms: Count of successfully received + * non-unicast MAC frames for the vpath. + * @rx_tagged_frms: Count of received frames containing a VLAN tag + * for the vpath. + * @rx_long_frms: Count of received frames that are longer than + * RX_MAX_PYLD_LEN + 18 bytes (+ 22 bytes if VLAN-tagged) for the vpath. + * @rx_usized_frms: Count of received frames of length less than 64 + * octets, for the vpath. + * @rx_usized_frms: Count of received frames of length more than + * 1518 octets, for the vpath. + * @rx_osized_frms: Count of received frames of length more than + * 1518 octets for the vpath. + * @rx_frag_frms: Count of received frames of length less than 64 + * octets that had bad FCS, for the vpath. + * @rx_jabber_frms: Count of received frames of length more than + * 1518 octets that had bad FCS, for the vpath. + * @rx_ttl_64_frms: Count of all received MAC frames with length of + * exactly 64 octets, for the vpath. + * @rx_ttl_65_127_frms: Count of all received MAC frames with length + * of between 65 and 127 octets inclusive, for the vpath. + * @rx_ttl_128_255_frms: Count of all received MAC frames with + * length of between 128 and 255 octets inclusive, for the vpath. + * @rx_ttl_256_511_frms: Count of all received MAC frames with + * length of between 246 and 511 octets inclusive, for the vpath. + * @rx_ttl_512_1023_frms: Count of all received MAC frames with + * length of between 512 and 1023 octets inclusive, for the vpath. + * @rx_ttl_1024_1518_frms: Count of all received MAC frames with + * length of between 1024 and 1518 octets inclusive, for the vpath. + * @rx_ttl_1519_4095_frms: Count of all received MAC frames with + * length of between 1519 and 4095 octets inclusive, for the vpath. + * @rx_ttl_40956_8191_frms: Count of all received MAC frames with + * of between 4096 and 8191 octets inclusive, for the vpath. + * @rx_ttl_8192_max_frms: Count of all received MAC frames with + * length of between 8192 and RX_MAX_PYLD_LEN+18 octets inclusive, for the + * vpath. + * @rx_ttl_gt_max_frms: Count of all received MAC frames with length + * exceeding RX_MAX_PYLD_LEN+18 octets inclusive, for the vpath. + * @rx_ip: Count of received IP datagrams, for the vpath. + * @rx_accepted_ip: Count of received and accepted IP datagrams, + * for the vpath. + * @rx_ip_octets: Count of number of octets in received IP datagrams + * for the vpath. + * @rx_hdr_err_ip: Count of received IP datagrams that are discarded + * due to IP header errors, for the vpath. + * @rx_icmp: Count of received ICMP messages for the vpath. + * @rx_tcp: Count of received TCP segments for the vpath. + * @rx_udp: Count of received UDP datagrams for the vpath. + * @rx_err_tcp: Count of received TCP segments containing errors for + * the vpath. + * @rx_mpa_ok_frms: Count of received frames that pass the MPA + * checks for vptah. + * @rx_mpa_crc_fail_frms: Count of received frames that fail the MPA + * CRC check for the vpath. + * @rx_mpa_mrk_fail_frms: Count of received frames that fail the + * MPA marker check for the vpath. + * @rx_mpa_len_fail_frms: Count of received frames that fail the MPA + * length check for the vpath. + * @rx_wol_frms: Count of received "magic packet" frames for + * the vpath. + */ +typedef struct xge_hal_stats_vpath_info_t { + u64 tx_frms; + u64 tx_ttl_eth_octets; + u64 tx_data_octets; + u64 tx_mcst_frms; + u64 tx_bcst_frms; + u64 tx_ucst_frms; + u64 tx_tagged_frms; + u64 tx_vld_ip; + u64 tx_vld_ip_octets; + u64 tx_icmp; + u64 tx_tcp; + u64 tx_rst_tcp; + u64 tx_udp; + u64 tx_unknown_protocol; + u64 tx_parse_error; + u64 rx_ttl_frms; + u64 rx_vld_frms; + u64 rx_offld_frms; + u64 rx_ttl_eth_octets; + u64 rx_data_octets; + u64 rx_offld_octets; + u64 rx_vld_mcst_frms; + u64 rx_vld_bcst_frms; + u64 rx_accepted_ucst_frms; + u64 rx_accepted_nucst_frms; + u64 rx_tagged_frms; + u64 rx_long_frms; + u64 rx_usized_frms; + u64 rx_osized_frms; + u64 rx_frag_frms; + u64 rx_jabber_frms; + u64 rx_ttl_64_frms; + u64 rx_ttl_65_127_frms; + u64 rx_ttl_128_255_frms; + u64 rx_ttl_256_511_frms; + u64 rx_ttl_512_1023_frms; + u64 rx_ttl_1024_1518_frms; + u64 rx_ttl_1519_4095_frms; + u64 rx_ttl_40956_8191_frms; + u64 rx_ttl_8192_max_frms; + u64 rx_ttl_gt_max_frms; + u64 rx_ip; + u64 rx_accepted_ip; + u64 rx_ip_octets; + u64 rx_hdr_err_ip; + u64 rx_icmp; + u64 rx_tcp; + u64 rx_udp; + u64 rx_err_tcp; + u64 rx_mpa_ok_frms; + u64 rx_mpa_crc_fail_frms; + u64 rx_mpa_mrk_fail_frms; + u64 rx_mpa_len_fail_frms; + u64 rx_wol_frms; +}xge_hal_stats_vpath_info_t; + +/** + * struct xge_hal_stats_pcim_info_t - Contains PCIM statistics + * + * @link_info: PCIM links info for link 0, 1, and 2. + * @aggr_info: PCIM aggregators info for aggregator 0 and 1. + * See also: xge_hal_stats_link_info_t{}, xge_hal_stats_aggr_info_t{}. + */ +typedef struct xge_hal_stats_pcim_info_t { + xge_hal_stats_link_info_t link_info[XGE_HAL_MAC_LINKS]; + xge_hal_stats_aggr_info_t aggr_info[XGE_HAL_MAC_AGGREGATORS]; +}xge_hal_stats_pcim_info_t; + +/** + * struct xge_hal_stats_t - Contains HAL per-device statistics, + * including hw. + * @devh: HAL device handle. + * @dma_addr: DMA addres of the %hw_info. Given to device to fill-in the stats. + * @hw_info_dmah: DMA handle used to map hw statistics onto the device memory + * space. + * @hw_info_dma_acch: One more DMA handle used subsequently to free the + * DMA object. Note that this and the previous handle have + * physical meaning for Solaris; on Windows and Linux the + * corresponding value will be simply pointer to PCI device. + * + * @hw_info: Xframe statistics maintained by the hardware. + * @hw_info_saved: TBD + * @hw_info_latest: TBD + * @pcim_info: Xframe PCIM statistics maintained by the hardware. + * @pcim_info_saved: TBD + * @pcim_info_latest: TBD + * @sw_dev_info_stats: HAL's "soft" device informational statistics, e.g. number + * of completions per interrupt. + * @sw_dev_err_stats: HAL's "soft" device error statistics. + * + * @is_initialized: True, if all the subordinate structures are allocated and + * initialized. + * @is_enabled: True, if device stats collection is enabled. + * + * Structure-container of HAL per-device statistics. Note that per-channel + * statistics are kept in separate structures under HAL's fifo and ring + * channels. + * See also: xge_hal_stats_hw_info_t{}, xge_hal_stats_sw_err_t{}, + * xge_hal_stats_device_info_t{}. + * See also: xge_hal_stats_channel_info_t{}. + */ +typedef struct xge_hal_stats_t { + /* handles */ + xge_hal_device_h devh; + dma_addr_t dma_addr; + pci_dma_h hw_info_dmah; + pci_dma_acc_h hw_info_dma_acch; + + /* HAL device hardware statistics */ + xge_hal_stats_hw_info_t *hw_info; + xge_hal_stats_hw_info_t hw_info_saved; + xge_hal_stats_hw_info_t hw_info_latest; + + /* HAL device hardware statistics for XFRAME ER */ + xge_hal_stats_pcim_info_t *pcim_info; + xge_hal_stats_pcim_info_t *pcim_info_saved; + xge_hal_stats_pcim_info_t *pcim_info_latest; + + /* HAL device "soft" stats */ + xge_hal_stats_sw_err_t sw_dev_err_stats; + xge_hal_stats_device_info_t sw_dev_info_stats; + + /* flags */ + int is_initialized; + int is_enabled; +} xge_hal_stats_t; + +/* ========================== STATS PRIVATE API ========================= */ + +xge_hal_status_e __hal_stats_initialize(xge_hal_stats_t *stats, + xge_hal_device_h devh); + +void __hal_stats_terminate(xge_hal_stats_t *stats); + +void __hal_stats_enable(xge_hal_stats_t *stats); + +void __hal_stats_disable(xge_hal_stats_t *stats); + +void __hal_stats_soft_reset(xge_hal_device_h devh, int reset_all); + +/* ========================== STATS PUBLIC API ========================= */ + +xge_hal_status_e xge_hal_stats_hw(xge_hal_device_h devh, + xge_hal_stats_hw_info_t **hw_info); + +xge_hal_status_e xge_hal_stats_pcim(xge_hal_device_h devh, + xge_hal_stats_pcim_info_t **pcim_info); + +xge_hal_status_e xge_hal_stats_device(xge_hal_device_h devh, + xge_hal_stats_device_info_t **device_info); + +xge_hal_status_e xge_hal_stats_channel(xge_hal_channel_h channelh, + xge_hal_stats_channel_info_t **channel_info); + +xge_hal_status_e xge_hal_stats_reset(xge_hal_device_h devh); + + +__EXTERN_END_DECLS + +#endif /* XGE_HAL_STATS_H */ diff --git a/sys/dev/nxge/include/xgehal-types.h b/sys/dev/nxge/include/xgehal-types.h new file mode 100644 index 0000000..ec1942b --- /dev/null +++ b/sys/dev/nxge/include/xgehal-types.h @@ -0,0 +1,626 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-types.h + * + * Description: HAL commonly used types and enumerations + * + * Created: 19 May 2004 + */ + +#ifndef XGE_HAL_TYPES_H +#define XGE_HAL_TYPES_H + +#include <dev/nxge/include/xge-os-pal.h> + +__EXTERN_BEGIN_DECLS + +/* + * BIT(loc) - set bit at offset + */ +#define BIT(loc) (0x8000000000000000ULL >> (loc)) + +/* + * vBIT(val, loc, sz) - set bits at offset + */ +#define vBIT(val, loc, sz) (((u64)(val)) << (64-(loc)-(sz))) +#define vBIT32(val, loc, sz) (((u32)(val)) << (32-(loc)-(sz))) + +/* + * bVALx(bits, loc) - Get the value of x bits at location + */ +#define bVAL1(bits, loc) ((((u64)bits) >> (64-(loc+1))) & 0x1) +#define bVAL2(bits, loc) ((((u64)bits) >> (64-(loc+2))) & 0x3) +#define bVAL3(bits, loc) ((((u64)bits) >> (64-(loc+3))) & 0x7) +#define bVAL4(bits, loc) ((((u64)bits) >> (64-(loc+4))) & 0xF) +#define bVAL5(bits, loc) ((((u64)bits) >> (64-(loc+5))) & 0x1F) +#define bVAL6(bits, loc) ((((u64)bits) >> (64-(loc+6))) & 0x3F) +#define bVAL7(bits, loc) ((((u64)bits) >> (64-(loc+7))) & 0x7F) +#define bVAL8(bits, loc) ((((u64)bits) >> (64-(loc+8))) & 0xFF) +#define bVAL12(bits, loc) ((((u64)bits) >> (64-(loc+12))) & 0xFFF) +#define bVAL14(bits, loc) ((((u64)bits) >> (64-(loc+14))) & 0x3FFF) +#define bVAL16(bits, loc) ((((u64)bits) >> (64-(loc+16))) & 0xFFFF) +#define bVAL20(bits, loc) ((((u64)bits) >> (64-(loc+20))) & 0xFFFFF) +#define bVAL22(bits, loc) ((((u64)bits) >> (64-(loc+22))) & 0x3FFFFF) +#define bVAL24(bits, loc) ((((u64)bits) >> (64-(loc+24))) & 0xFFFFFF) +#define bVAL28(bits, loc) ((((u64)bits) >> (64-(loc+28))) & 0xFFFFFFF) +#define bVAL32(bits, loc) ((((u64)bits) >> (64-(loc+32))) & 0xFFFFFFFF) +#define bVAL36(bits, loc) ((((u64)bits) >> (64-(loc+36))) & 0xFFFFFFFFF) +#define bVAL40(bits, loc) ((((u64)bits) >> (64-(loc+40))) & 0xFFFFFFFFFF) +#define bVAL44(bits, loc) ((((u64)bits) >> (64-(loc+44))) & 0xFFFFFFFFFFF) +#define bVAL48(bits, loc) ((((u64)bits) >> (64-(loc+48))) & 0xFFFFFFFFFFFF) +#define bVAL52(bits, loc) ((((u64)bits) >> (64-(loc+52))) & 0xFFFFFFFFFFFFF) +#define bVAL56(bits, loc) ((((u64)bits) >> (64-(loc+56))) & 0xFFFFFFFFFFFFFF) +#define bVAL60(bits, loc) ((((u64)bits) >> (64-(loc+60))) & 0xFFFFFFFFFFFFFFF) + +#define XGE_HAL_BASE_INF 100 +#define XGE_HAL_BASE_ERR 200 +#define XGE_HAL_BASE_BADCFG 300 + +#define XGE_HAL_ALL_FOXES 0xFFFFFFFFFFFFFFFFULL + +/** + * enum xge_hal_status_e - HAL return codes. + * @XGE_HAL_OK: Success. + * @XGE_HAL_FAIL: Failure. + * @XGE_HAL_COMPLETIONS_REMAIN: There are more completions on a channel. + * (specific to polling mode completion processing). + * @XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS: No more completed + * descriptors. See xge_hal_fifo_dtr_next_completed(). + * @XGE_HAL_INF_OUT_OF_DESCRIPTORS: Out of descriptors. Channel + * descriptors + * are reserved (via xge_hal_fifo_dtr_reserve(), + * xge_hal_fifo_dtr_reserve()) + * and not yet freed (via xge_hal_fifo_dtr_free(), + * xge_hal_ring_dtr_free()). + * @XGE_HAL_INF_CHANNEL_IS_NOT_READY: Channel is not ready for + * operation. + * @XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING: Indicates that host needs to + * poll until PIO is executed. + * @XGE_HAL_INF_STATS_IS_NOT_READY: Cannot retrieve statistics because + * HAL and/or device is not yet initialized. + * @XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS: No descriptors left to + * reserve. Internal use only. + * @XGE_HAL_INF_IRQ_POLLING_CONTINUE: Returned by the ULD channel + * callback when instructed to exit descriptor processing loop + * prematurely. Typical usage: polling mode of processing completed + * descriptors. + * Upon getting LRO_ISED, ll driver shall + * 1) initialise lro struct with mbuf if sg_num == 1. + * 2) else it will update m_data_ptr_of_mbuf to tcp pointer and + * append the new mbuf to the tail of mbuf chain in lro struct. + * + * @XGE_HAL_INF_LRO_BEGIN: Returned by ULD LRO module, when new LRO is + * being initiated. + * @XGE_HAL_INF_LRO_CONT: Returned by ULD LRO module, when new frame + * is appended at the end of existing LRO. + * @XGE_HAL_INF_LRO_UNCAPABLE: Returned by ULD LRO module, when new + * frame is not LRO capable. + * @XGE_HAL_INF_LRO_END_1: Returned by ULD LRO module, when new frame + * triggers LRO flush. + * @XGE_HAL_INF_LRO_END_2: Returned by ULD LRO module, when new + * frame triggers LRO flush. Lro frame should be flushed first then + * new frame should be flushed next. + * @XGE_HAL_INF_LRO_END_3: Returned by ULD LRO module, when new + * frame triggers close of current LRO session and opening of new LRO session + * with the frame. + * @XGE_HAL_INF_LRO_SESSIONS_XCDED: Returned by ULD LRO module, when no + * more LRO sessions can be added. + * @XGE_HAL_INF_NOT_ENOUGH_HW_CQES: TBD + * @XGE_HAL_ERR_DRIVER_NOT_INITIALIZED: HAL is not initialized. + * @XGE_HAL_ERR_OUT_OF_MEMORY: Out of memory (example, when and + * allocating descriptors). + * @XGE_HAL_ERR_CHANNEL_NOT_FOUND: xge_hal_channel_open will return this + * error if corresponding channel is not configured. + * @XGE_HAL_ERR_WRONG_IRQ: Returned by HAL's ISR when the latter is + * invoked not because of the Xframe-generated interrupt. + * @XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES: Returned when user tries to + * configure more than XGE_HAL_MAX_MAC_ADDRESSES mac addresses. + * @XGE_HAL_ERR_BAD_DEVICE_ID: Unknown device PCI ID. + * @XGE_HAL_ERR_OUT_ALIGNED_FRAGS: Too many unaligned fragments + * in a scatter-gather list. + * @XGE_HAL_ERR_DEVICE_NOT_INITIALIZED: Device is not initialized. + * Typically means wrong sequence of API calls. + * @XGE_HAL_ERR_SWAPPER_CTRL: Error during device initialization: failed + * to set Xframe byte swapper in accordnace with the host + * endian-ness. + * @XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT: Failed to restore the device to + * a "quiescent" state. + * @XGE_HAL_ERR_INVALID_MTU_SIZE: Returned when MTU size specified by + * caller is not in the (64, 9600) range. + * @XGE_HAL_ERR_OUT_OF_MAPPING: Failed to map DMA-able memory. + * @XGE_HAL_ERR_BAD_SUBSYSTEM_ID: Bad PCI subsystem ID. (Currently we + * check for zero/non-zero only.) + * @XGE_HAL_ERR_INVALID_BAR_ID: Invalid BAR ID. Xframe supports two Base + * Address Register Spaces: BAR0 (id=0) and BAR1 (id=1). + * @XGE_HAL_ERR_INVALID_OFFSET: Invalid offset. Example, attempt to read + * register value (with offset) outside of the BAR0 space. + * @XGE_HAL_ERR_INVALID_DEVICE: Invalid device. The HAL device handle + * (passed by ULD) is invalid. + * @XGE_HAL_ERR_OUT_OF_SPACE: Out-of-provided-buffer-space. Returned by + * management "get" routines when the retrieved information does + * not fit into the provided buffer. + * @XGE_HAL_ERR_INVALID_VALUE_BIT_SIZE: Invalid bit size. + * @XGE_HAL_ERR_VERSION_CONFLICT: Upper-layer driver and HAL (versions) + * are not compatible. + * @XGE_HAL_ERR_INVALID_MAC_ADDRESS: Invalid MAC address. + * @XGE_HAL_ERR_SPDM_NOT_ENABLED: SPDM support is not enabled. + * @XGE_HAL_ERR_SPDM_TABLE_FULL: SPDM table is full. + * @XGE_HAL_ERR_SPDM_INVALID_ENTRY: Invalid SPDM entry. + * @XGE_HAL_ERR_SPDM_ENTRY_NOT_FOUND: Unable to locate the entry in the + * SPDM table. + * @XGE_HAL_ERR_SPDM_TABLE_DATA_INCONSISTENT: Local SPDM table is not in + * synch ith the actual one. + * @XGE_HAL_ERR_INVALID_PCI_INFO: Invalid or unrecognized PCI frequency, + * and or width, and or mode (Xframe-II only, see UG on PCI_INFO register). + * @XGE_HAL_ERR_CRITICAL: Critical error. Returned by HAL APIs + * (including xge_hal_device_handle_tcode()) on: ECC, parity, SERR. + * Also returned when PIO read does not go through ("all-foxes") + * because of "slot-freeze". + * @XGE_HAL_ERR_RESET_FAILED: Failed to soft-reset the device. + * Returned by xge_hal_device_reset(). One circumstance when it could + * happen: slot freeze by the system (see @XGE_HAL_ERR_CRITICAL). + * @XGE_HAL_ERR_TOO_MANY: This error is returned if there were laready + * maximum number of sessions or queues allocated + * @XGE_HAL_ERR_PKT_DROP: TBD + * @XGE_HAL_BADCFG_TX_URANGE_A: Invalid Tx link utilization range A. See + * the structure xge_hal_tti_config_t{} for valid values. + * @XGE_HAL_BADCFG_TX_UFC_A: Invalid frame count for Tx link utilization + * range A. See the structure xge_hal_tti_config_t{} for valid values. + * @XGE_HAL_BADCFG_TX_URANGE_B: Invalid Tx link utilization range B. See + * the structure xge_hal_tti_config_t{} for valid values. + * @XGE_HAL_BADCFG_TX_UFC_B: Invalid frame count for Tx link utilization + * range B. See the strucuture xge_hal_tti_config_t{} for valid values. + * @XGE_HAL_BADCFG_TX_URANGE_C: Invalid Tx link utilization range C. See + * the structure xge_hal_tti_config_t{} for valid values. + * @XGE_HAL_BADCFG_TX_UFC_C: Invalid frame count for Tx link utilization + * range C. See the structure xge_hal_tti_config_t{} for valid values. + * @XGE_HAL_BADCFG_TX_UFC_D: Invalid frame count for Tx link utilization + * range D. See the structure xge_hal_tti_config_t{} for valid values. + * @XGE_HAL_BADCFG_TX_TIMER_VAL: Invalid Tx timer value. See the + * structure xge_hal_tti_config_t{} for valid values. + * @XGE_HAL_BADCFG_TX_TIMER_CI_EN: Invalid Tx timer continuous interrupt + * enable. See the structure xge_hal_tti_config_t{} for valid values. + * @XGE_HAL_BADCFG_RX_URANGE_A: Invalid Rx link utilization range A. See + * the structure xge_hal_rti_config_t{} for valid values. + * @XGE_HAL_BADCFG_RX_UFC_A: Invalid frame count for Rx link utilization + * range A. See the structure xge_hal_rti_config_t{} for valid values. + * @XGE_HAL_BADCFG_RX_URANGE_B: Invalid Rx link utilization range B. See + * the structure xge_hal_rti_config_t{} for valid values. + * @XGE_HAL_BADCFG_RX_UFC_B: Invalid frame count for Rx link utilization + * range B. See the structure xge_hal_rti_config_t{} for valid values. + * @XGE_HAL_BADCFG_RX_URANGE_C: Invalid Rx link utilization range C. See + * the structure xge_hal_rti_config_t{} for valid values. + * @XGE_HAL_BADCFG_RX_UFC_C: Invalid frame count for Rx link utilization + * range C. See the structure xge_hal_rti_config_t{} for valid values. + * @XGE_HAL_BADCFG_RX_UFC_D: Invalid frame count for Rx link utilization + * range D. See the structure xge_hal_rti_config_t{} for valid values. + * @XGE_HAL_BADCFG_RX_TIMER_VAL: Invalid Rx timer value. See the + * structure xge_hal_rti_config_t{} for valid values. + * @XGE_HAL_BADCFG_FIFO_QUEUE_INITIAL_LENGTH: Invalid initial fifo queue + * length. See the structure xge_hal_fifo_queue_t for valid values. + * @XGE_HAL_BADCFG_FIFO_QUEUE_MAX_LENGTH: Invalid fifo queue max length. + * See the structure xge_hal_fifo_queue_t for valid values. + * @XGE_HAL_BADCFG_FIFO_QUEUE_INTR: Invalid fifo queue interrupt mode. + * See the structure xge_hal_fifo_queue_t for valid values. + * @XGE_HAL_BADCFG_RING_QUEUE_INITIAL_BLOCKS: Invalid Initial number of + * RxD blocks for the ring. See the structure xge_hal_ring_queue_t for + * valid values. + * @XGE_HAL_BADCFG_RING_QUEUE_MAX_BLOCKS: Invalid maximum number of RxD + * blocks for the ring. See the structure xge_hal_ring_queue_t for + * valid values. + * @XGE_HAL_BADCFG_RING_QUEUE_BUFFER_MODE: Invalid ring buffer mode. See + * the structure xge_hal_ring_queue_t for valid values. + * @XGE_HAL_BADCFG_RING_QUEUE_SIZE: Invalid ring queue size. See the + * structure xge_hal_ring_queue_t for valid values. + * @XGE_HAL_BADCFG_BACKOFF_INTERVAL_US: Invalid backoff timer interval + * for the ring. See the structure xge_hal_ring_queue_t for valid values. + * @XGE_HAL_BADCFG_MAX_FRM_LEN: Invalid ring max frame length. See the + * structure xge_hal_ring_queue_t for valid values. + * @XGE_HAL_BADCFG_RING_PRIORITY: Invalid ring priority. See the + * structure xge_hal_ring_queue_t for valid values. + * @XGE_HAL_BADCFG_TMAC_UTIL_PERIOD: Invalid tmac util period. See the + * structure xge_hal_mac_config_t{} for valid values. + * @XGE_HAL_BADCFG_RMAC_UTIL_PERIOD: Invalid rmac util period. See the + * structure xge_hal_mac_config_t{} for valid values. + * @XGE_HAL_BADCFG_RMAC_BCAST_EN: Invalid rmac brodcast enable. See the + * structure xge_hal_mac_config_t{} for valid values. + * @XGE_HAL_BADCFG_RMAC_HIGH_PTIME: Invalid rmac pause time. See the + * structure xge_hal_mac_config_t{} for valid values. + * @XGE_HAL_BADCFG_MC_PAUSE_THRESHOLD_Q0Q3: Invalid threshold for pause + * frame generation for queues 0 through 3. See the structure + * xge_hal_mac_config_t{} for valid values. + * @XGE_HAL_BADCFG_MC_PAUSE_THRESHOLD_Q4Q7:Invalid threshold for pause + * frame generation for queues 4 through 7. See the structure + * xge_hal_mac_config_t{} for valid values. + * @XGE_HAL_BADCFG_FIFO_FRAGS: Invalid fifo max fragments length. See + * the structure xge_hal_fifo_config_t{} for valid values. + * @XGE_HAL_BADCFG_FIFO_RESERVE_THRESHOLD: Invalid fifo reserve + * threshold. See the structure xge_hal_fifo_config_t{} for valid values. + * @XGE_HAL_BADCFG_FIFO_MEMBLOCK_SIZE: Invalid fifo descriptors memblock + * size. See the structure xge_hal_fifo_config_t{} for valid values. + * @XGE_HAL_BADCFG_RING_MEMBLOCK_SIZE: Invalid ring descriptors memblock + * size. See the structure xge_hal_ring_config_t{} for valid values. + * @XGE_HAL_BADCFG_MAX_MTU: Invalid max mtu for the device. See the + * structure xge_hal_device_config_t{} for valid values. + * @XGE_HAL_BADCFG_ISR_POLLING_CNT: Invalid isr polling count. See the + * structure xge_hal_device_config_t{} for valid values. + * @XGE_HAL_BADCFG_LATENCY_TIMER: Invalid Latency timer. See the + * structure xge_hal_device_config_t{} for valid values. + * @XGE_HAL_BADCFG_MAX_SPLITS_TRANS: Invalid maximum number of pci-x + * split transactions. See the structure xge_hal_device_config_t{} for valid + * values. + * @XGE_HAL_BADCFG_MMRB_COUNT: Invalid mmrb count. See the structure + * xge_hal_device_config_t{} for valid values. + * @XGE_HAL_BADCFG_SHARED_SPLITS: Invalid number of outstanding split + * transactions that is shared by Tx and Rx requests. See the structure + * xge_hal_device_config_t{} for valid values. + * @XGE_HAL_BADCFG_STATS_REFRESH_TIME: Invalid time interval for + * automatic statistics transfer to the host. See the structure + * xge_hal_device_config_t{} for valid values. + * @XGE_HAL_BADCFG_PCI_FREQ_MHERZ: Invalid pci clock frequency. See the + * structure xge_hal_device_config_t{} for valid values. + * @XGE_HAL_BADCFG_PCI_MODE: Invalid pci mode. See the structure + * xge_hal_device_config_t{} for valid values. + * @XGE_HAL_BADCFG_INTR_MODE: Invalid interrupt mode. See the structure + * xge_hal_device_config_t{} for valid values. + * @XGE_HAL_BADCFG_SCHED_TIMER_US: Invalid scheduled timer interval to + * generate interrupt. See the structure xge_hal_device_config_t{} + * for valid values. + * @XGE_HAL_BADCFG_SCHED_TIMER_ON_SHOT: Invalid scheduled timer one + * shot. See the structure xge_hal_device_config_t{} for valid values. + * @XGE_HAL_BADCFG_QUEUE_SIZE_INITIAL: Invalid driver queue initial + * size. See the structure xge_hal_driver_config_t{} for valid values. + * @XGE_HAL_BADCFG_QUEUE_SIZE_MAX: Invalid driver queue max size. See + * the structure xge_hal_driver_config_t{} for valid values. + * @XGE_HAL_BADCFG_RING_RTH_EN: Invalid value of RTH-enable. See + * the structure xge_hal_ring_queue_t for valid values. + * @XGE_HAL_BADCFG_RING_INDICATE_MAX_PKTS: Invalid value configured for + * indicate_max_pkts variable. + * @XGE_HAL_BADCFG_TX_TIMER_AC_EN: Invalid value for Tx timer + * auto-cancel. See xge_hal_tti_config_t{}. + * @XGE_HAL_BADCFG_RX_TIMER_AC_EN: Invalid value for Rx timer + * auto-cancel. See xge_hal_rti_config_t{}. + * @XGE_HAL_BADCFG_RXUFCA_INTR_THRES: TODO + * @XGE_HAL_BADCFG_RXUFCA_LO_LIM: TODO + * @XGE_HAL_BADCFG_RXUFCA_HI_LIM: TODO + * @XGE_HAL_BADCFG_RXUFCA_LBOLT_PERIOD: TODO + * @XGE_HAL_BADCFG_TRACEBUF_SIZE: Bad configuration: the size of the circular + * (in memory) trace buffer either too large or too small. See the + * the corresponding header file or README for the acceptable range. + * @XGE_HAL_BADCFG_LINK_VALID_CNT: Bad configuration: the link-valid + * counter cannot have the specified value. Note that the link-valid + * counting is done only at device-open time, to determine with the + * specified certainty that the link is up. See the + * the corresponding header file or README for the acceptable range. + * See also @XGE_HAL_BADCFG_LINK_RETRY_CNT. + * @XGE_HAL_BADCFG_LINK_RETRY_CNT: Bad configuration: the specified + * link-up retry count is out of the valid range. Note that the link-up + * retry counting is done only at device-open time. + * See also xge_hal_device_config_t{}. + * @XGE_HAL_BADCFG_LINK_STABILITY_PERIOD: Invalid link stability period. + * @XGE_HAL_BADCFG_DEVICE_POLL_MILLIS: Invalid device poll interval. + * @XGE_HAL_BADCFG_RMAC_PAUSE_GEN_EN: TBD + * @XGE_HAL_BADCFG_RMAC_PAUSE_RCV_EN: TBD + * @XGE_HAL_BADCFG_MEDIA: TBD + * @XGE_HAL_BADCFG_NO_ISR_EVENTS: TBD + * See the structure xge_hal_device_config_t{} for valid values. + * @XGE_HAL_EOF_TRACE_BUF: End of the circular (in memory) trace buffer. + * Returned by xge_hal_mgmt_trace_read(), when user tries to read the trace + * past the buffer limits. Used to enable user to load the trace in two + * or more reads. + * @XGE_HAL_BADCFG_RING_RTS_MAC_EN: Invalid value of RTS_MAC_EN enable. See + * the structure xge_hal_ring_queue_t for valid values. + * @XGE_HAL_BADCFG_LRO_SG_SIZE : Invalid value of LRO scatter gatter size. + * See the structure xge_hal_device_config_t for valid values. + * @XGE_HAL_BADCFG_LRO_FRM_LEN : Invalid value of LRO frame length. + * See the structure xge_hal_device_config_t for valid values. + * @XGE_HAL_BADCFG_WQE_NUM_ODS: TBD + * @XGE_HAL_BADCFG_BIMODAL_INTR: Invalid value to configure bimodal interrupts + * Enumerates status and error codes returned by HAL public + * API functions. + * @XGE_HAL_BADCFG_BIMODAL_TIMER_LO_US: TBD + * @XGE_HAL_BADCFG_BIMODAL_TIMER_HI_US: TBD + * @XGE_HAL_BADCFG_BIMODAL_XENA_NOT_ALLOWED: TBD + * @XGE_HAL_BADCFG_RTS_QOS_EN: TBD + * @XGE_HAL_BADCFG_FIFO_QUEUE_INTR_VECTOR: TBD + * @XGE_HAL_BADCFG_RING_QUEUE_INTR_VECTOR: TBD + * @XGE_HAL_BADCFG_RTS_PORT_EN: TBD + * @XGE_HAL_BADCFG_RING_RTS_PORT_EN: TBD + * + */ +typedef enum xge_hal_status_e { + XGE_HAL_OK = 0, + XGE_HAL_FAIL = 1, + XGE_HAL_COMPLETIONS_REMAIN = 2, + + XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS = XGE_HAL_BASE_INF + 1, + XGE_HAL_INF_OUT_OF_DESCRIPTORS = XGE_HAL_BASE_INF + 2, + XGE_HAL_INF_CHANNEL_IS_NOT_READY = XGE_HAL_BASE_INF + 3, + XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING = XGE_HAL_BASE_INF + 4, + XGE_HAL_INF_STATS_IS_NOT_READY = XGE_HAL_BASE_INF + 5, + XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS = XGE_HAL_BASE_INF + 6, + XGE_HAL_INF_IRQ_POLLING_CONTINUE = XGE_HAL_BASE_INF + 7, + XGE_HAL_INF_LRO_BEGIN = XGE_HAL_BASE_INF + 8, + XGE_HAL_INF_LRO_CONT = XGE_HAL_BASE_INF + 9, + XGE_HAL_INF_LRO_UNCAPABLE = XGE_HAL_BASE_INF + 10, + XGE_HAL_INF_LRO_END_1 = XGE_HAL_BASE_INF + 11, + XGE_HAL_INF_LRO_END_2 = XGE_HAL_BASE_INF + 12, + XGE_HAL_INF_LRO_END_3 = XGE_HAL_BASE_INF + 13, + XGE_HAL_INF_LRO_SESSIONS_XCDED = XGE_HAL_BASE_INF + 14, + XGE_HAL_INF_NOT_ENOUGH_HW_CQES = XGE_HAL_BASE_INF + 15, + XGE_HAL_ERR_DRIVER_NOT_INITIALIZED = XGE_HAL_BASE_ERR + 1, + XGE_HAL_ERR_OUT_OF_MEMORY = XGE_HAL_BASE_ERR + 4, + XGE_HAL_ERR_CHANNEL_NOT_FOUND = XGE_HAL_BASE_ERR + 5, + XGE_HAL_ERR_WRONG_IRQ = XGE_HAL_BASE_ERR + 6, + XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES = XGE_HAL_BASE_ERR + 7, + XGE_HAL_ERR_SWAPPER_CTRL = XGE_HAL_BASE_ERR + 8, + XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT = XGE_HAL_BASE_ERR + 9, + XGE_HAL_ERR_INVALID_MTU_SIZE = XGE_HAL_BASE_ERR + 10, + XGE_HAL_ERR_OUT_OF_MAPPING = XGE_HAL_BASE_ERR + 11, + XGE_HAL_ERR_BAD_SUBSYSTEM_ID = XGE_HAL_BASE_ERR + 12, + XGE_HAL_ERR_INVALID_BAR_ID = XGE_HAL_BASE_ERR + 13, + XGE_HAL_ERR_INVALID_OFFSET = XGE_HAL_BASE_ERR + 14, + XGE_HAL_ERR_INVALID_DEVICE = XGE_HAL_BASE_ERR + 15, + XGE_HAL_ERR_OUT_OF_SPACE = XGE_HAL_BASE_ERR + 16, + XGE_HAL_ERR_INVALID_VALUE_BIT_SIZE = XGE_HAL_BASE_ERR + 17, + XGE_HAL_ERR_VERSION_CONFLICT = XGE_HAL_BASE_ERR + 18, + XGE_HAL_ERR_INVALID_MAC_ADDRESS = XGE_HAL_BASE_ERR + 19, + XGE_HAL_ERR_BAD_DEVICE_ID = XGE_HAL_BASE_ERR + 20, + XGE_HAL_ERR_OUT_ALIGNED_FRAGS = XGE_HAL_BASE_ERR + 21, + XGE_HAL_ERR_DEVICE_NOT_INITIALIZED = XGE_HAL_BASE_ERR + 22, + XGE_HAL_ERR_SPDM_NOT_ENABLED = XGE_HAL_BASE_ERR + 23, + XGE_HAL_ERR_SPDM_TABLE_FULL = XGE_HAL_BASE_ERR + 24, + XGE_HAL_ERR_SPDM_INVALID_ENTRY = XGE_HAL_BASE_ERR + 25, + XGE_HAL_ERR_SPDM_ENTRY_NOT_FOUND = XGE_HAL_BASE_ERR + 26, + XGE_HAL_ERR_SPDM_TABLE_DATA_INCONSISTENT= XGE_HAL_BASE_ERR + 27, + XGE_HAL_ERR_INVALID_PCI_INFO = XGE_HAL_BASE_ERR + 28, + XGE_HAL_ERR_CRITICAL = XGE_HAL_BASE_ERR + 29, + XGE_HAL_ERR_RESET_FAILED = XGE_HAL_BASE_ERR + 30, + XGE_HAL_ERR_TOO_MANY = XGE_HAL_BASE_ERR + 32, + XGE_HAL_ERR_PKT_DROP = XGE_HAL_BASE_ERR + 33, + + XGE_HAL_BADCFG_TX_URANGE_A = XGE_HAL_BASE_BADCFG + 1, + XGE_HAL_BADCFG_TX_UFC_A = XGE_HAL_BASE_BADCFG + 2, + XGE_HAL_BADCFG_TX_URANGE_B = XGE_HAL_BASE_BADCFG + 3, + XGE_HAL_BADCFG_TX_UFC_B = XGE_HAL_BASE_BADCFG + 4, + XGE_HAL_BADCFG_TX_URANGE_C = XGE_HAL_BASE_BADCFG + 5, + XGE_HAL_BADCFG_TX_UFC_C = XGE_HAL_BASE_BADCFG + 6, + XGE_HAL_BADCFG_TX_UFC_D = XGE_HAL_BASE_BADCFG + 8, + XGE_HAL_BADCFG_TX_TIMER_VAL = XGE_HAL_BASE_BADCFG + 9, + XGE_HAL_BADCFG_TX_TIMER_CI_EN = XGE_HAL_BASE_BADCFG + 10, + XGE_HAL_BADCFG_RX_URANGE_A = XGE_HAL_BASE_BADCFG + 11, + XGE_HAL_BADCFG_RX_UFC_A = XGE_HAL_BASE_BADCFG + 12, + XGE_HAL_BADCFG_RX_URANGE_B = XGE_HAL_BASE_BADCFG + 13, + XGE_HAL_BADCFG_RX_UFC_B = XGE_HAL_BASE_BADCFG + 14, + XGE_HAL_BADCFG_RX_URANGE_C = XGE_HAL_BASE_BADCFG + 15, + XGE_HAL_BADCFG_RX_UFC_C = XGE_HAL_BASE_BADCFG + 16, + XGE_HAL_BADCFG_RX_UFC_D = XGE_HAL_BASE_BADCFG + 17, + XGE_HAL_BADCFG_RX_TIMER_VAL = XGE_HAL_BASE_BADCFG + 18, + XGE_HAL_BADCFG_FIFO_QUEUE_INITIAL_LENGTH= XGE_HAL_BASE_BADCFG + 19, + XGE_HAL_BADCFG_FIFO_QUEUE_MAX_LENGTH = XGE_HAL_BASE_BADCFG + 20, + XGE_HAL_BADCFG_FIFO_QUEUE_INTR = XGE_HAL_BASE_BADCFG + 21, + XGE_HAL_BADCFG_RING_QUEUE_INITIAL_BLOCKS=XGE_HAL_BASE_BADCFG + 22, + XGE_HAL_BADCFG_RING_QUEUE_MAX_BLOCKS = XGE_HAL_BASE_BADCFG + 23, + XGE_HAL_BADCFG_RING_QUEUE_BUFFER_MODE = XGE_HAL_BASE_BADCFG + 24, + XGE_HAL_BADCFG_RING_QUEUE_SIZE = XGE_HAL_BASE_BADCFG + 25, + XGE_HAL_BADCFG_BACKOFF_INTERVAL_US = XGE_HAL_BASE_BADCFG + 26, + XGE_HAL_BADCFG_MAX_FRM_LEN = XGE_HAL_BASE_BADCFG + 27, + XGE_HAL_BADCFG_RING_PRIORITY = XGE_HAL_BASE_BADCFG + 28, + XGE_HAL_BADCFG_TMAC_UTIL_PERIOD = XGE_HAL_BASE_BADCFG + 29, + XGE_HAL_BADCFG_RMAC_UTIL_PERIOD = XGE_HAL_BASE_BADCFG + 30, + XGE_HAL_BADCFG_RMAC_BCAST_EN = XGE_HAL_BASE_BADCFG + 31, + XGE_HAL_BADCFG_RMAC_HIGH_PTIME = XGE_HAL_BASE_BADCFG + 32, + XGE_HAL_BADCFG_MC_PAUSE_THRESHOLD_Q0Q3 = XGE_HAL_BASE_BADCFG +33, + XGE_HAL_BADCFG_MC_PAUSE_THRESHOLD_Q4Q7 = XGE_HAL_BASE_BADCFG + 34, + XGE_HAL_BADCFG_FIFO_FRAGS = XGE_HAL_BASE_BADCFG + 35, + XGE_HAL_BADCFG_FIFO_RESERVE_THRESHOLD = XGE_HAL_BASE_BADCFG + 37, + XGE_HAL_BADCFG_FIFO_MEMBLOCK_SIZE = XGE_HAL_BASE_BADCFG + 38, + XGE_HAL_BADCFG_RING_MEMBLOCK_SIZE = XGE_HAL_BASE_BADCFG + 39, + XGE_HAL_BADCFG_MAX_MTU = XGE_HAL_BASE_BADCFG + 40, + XGE_HAL_BADCFG_ISR_POLLING_CNT = XGE_HAL_BASE_BADCFG + 41, + XGE_HAL_BADCFG_LATENCY_TIMER = XGE_HAL_BASE_BADCFG + 42, + XGE_HAL_BADCFG_MAX_SPLITS_TRANS = XGE_HAL_BASE_BADCFG + 43, + XGE_HAL_BADCFG_MMRB_COUNT = XGE_HAL_BASE_BADCFG + 44, + XGE_HAL_BADCFG_SHARED_SPLITS = XGE_HAL_BASE_BADCFG + 45, + XGE_HAL_BADCFG_STATS_REFRESH_TIME = XGE_HAL_BASE_BADCFG + 46, + XGE_HAL_BADCFG_PCI_FREQ_MHERZ = XGE_HAL_BASE_BADCFG + 47, + XGE_HAL_BADCFG_PCI_MODE = XGE_HAL_BASE_BADCFG + 48, + XGE_HAL_BADCFG_INTR_MODE = XGE_HAL_BASE_BADCFG + 49, + XGE_HAL_BADCFG_SCHED_TIMER_US = XGE_HAL_BASE_BADCFG + 50, + XGE_HAL_BADCFG_SCHED_TIMER_ON_SHOT = XGE_HAL_BASE_BADCFG + 51, + XGE_HAL_BADCFG_QUEUE_SIZE_INITIAL = XGE_HAL_BASE_BADCFG + 52, + XGE_HAL_BADCFG_QUEUE_SIZE_MAX = XGE_HAL_BASE_BADCFG + 53, + XGE_HAL_BADCFG_RING_RTH_EN = XGE_HAL_BASE_BADCFG + 54, + XGE_HAL_BADCFG_RING_INDICATE_MAX_PKTS = XGE_HAL_BASE_BADCFG + 55, + XGE_HAL_BADCFG_TX_TIMER_AC_EN = XGE_HAL_BASE_BADCFG + 56, + XGE_HAL_BADCFG_RX_TIMER_AC_EN = XGE_HAL_BASE_BADCFG + 57, + XGE_HAL_BADCFG_RXUFCA_INTR_THRES = XGE_HAL_BASE_BADCFG + 58, + XGE_HAL_BADCFG_RXUFCA_LO_LIM = XGE_HAL_BASE_BADCFG + 59, + XGE_HAL_BADCFG_RXUFCA_HI_LIM = XGE_HAL_BASE_BADCFG + 60, + XGE_HAL_BADCFG_RXUFCA_LBOLT_PERIOD = XGE_HAL_BASE_BADCFG + 61, + XGE_HAL_BADCFG_TRACEBUF_SIZE = XGE_HAL_BASE_BADCFG + 62, + XGE_HAL_BADCFG_LINK_VALID_CNT = XGE_HAL_BASE_BADCFG + 63, + XGE_HAL_BADCFG_LINK_RETRY_CNT = XGE_HAL_BASE_BADCFG + 64, + XGE_HAL_BADCFG_LINK_STABILITY_PERIOD = XGE_HAL_BASE_BADCFG + 65, + XGE_HAL_BADCFG_DEVICE_POLL_MILLIS = XGE_HAL_BASE_BADCFG + 66, + XGE_HAL_BADCFG_RMAC_PAUSE_GEN_EN = XGE_HAL_BASE_BADCFG + 67, + XGE_HAL_BADCFG_RMAC_PAUSE_RCV_EN = XGE_HAL_BASE_BADCFG + 68, + XGE_HAL_BADCFG_MEDIA = XGE_HAL_BASE_BADCFG + 69, + XGE_HAL_BADCFG_NO_ISR_EVENTS = XGE_HAL_BASE_BADCFG + 70, + XGE_HAL_BADCFG_RING_RTS_MAC_EN = XGE_HAL_BASE_BADCFG + 71, + XGE_HAL_BADCFG_LRO_SG_SIZE = XGE_HAL_BASE_BADCFG + 72, + XGE_HAL_BADCFG_LRO_FRM_LEN = XGE_HAL_BASE_BADCFG + 73, + XGE_HAL_BADCFG_WQE_NUM_ODS = XGE_HAL_BASE_BADCFG + 74, + XGE_HAL_BADCFG_BIMODAL_INTR = XGE_HAL_BASE_BADCFG + 75, + XGE_HAL_BADCFG_BIMODAL_TIMER_LO_US = XGE_HAL_BASE_BADCFG + 76, + XGE_HAL_BADCFG_BIMODAL_TIMER_HI_US = XGE_HAL_BASE_BADCFG + 77, + XGE_HAL_BADCFG_BIMODAL_XENA_NOT_ALLOWED = XGE_HAL_BASE_BADCFG + 78, + XGE_HAL_BADCFG_RTS_QOS_EN = XGE_HAL_BASE_BADCFG + 79, + XGE_HAL_BADCFG_FIFO_QUEUE_INTR_VECTOR = XGE_HAL_BASE_BADCFG + 80, + XGE_HAL_BADCFG_RING_QUEUE_INTR_VECTOR = XGE_HAL_BASE_BADCFG + 81, + XGE_HAL_BADCFG_RTS_PORT_EN = XGE_HAL_BASE_BADCFG + 82, + XGE_HAL_BADCFG_RING_RTS_PORT_EN = XGE_HAL_BASE_BADCFG + 83, + XGE_HAL_BADCFG_TRACEBUF_TIMESTAMP = XGE_HAL_BASE_BADCFG + 84, + XGE_HAL_EOF_TRACE_BUF = -1 +} xge_hal_status_e; + +#define XGE_HAL_ETH_ALEN 6 +typedef u8 macaddr_t[XGE_HAL_ETH_ALEN]; + +#define XGE_HAL_PCI_XFRAME_CONFIG_SPACE_SIZE 0x100 + +/* frames sizes */ +#define XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE 14 +#define XGE_HAL_HEADER_802_2_SIZE 3 +#define XGE_HAL_HEADER_SNAP_SIZE 5 +#define XGE_HAL_HEADER_VLAN_SIZE 4 +#define XGE_HAL_MAC_HEADER_MAX_SIZE \ + (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE + \ + XGE_HAL_HEADER_802_2_SIZE + \ + XGE_HAL_HEADER_SNAP_SIZE) + +#define XGE_HAL_TCPIP_HEADER_MAX_SIZE (64 + 64) + +/* 32bit alignments */ +#define XGE_HAL_HEADER_ETHERNET_II_802_3_ALIGN 2 +#define XGE_HAL_HEADER_802_2_SNAP_ALIGN 2 +#define XGE_HAL_HEADER_802_2_ALIGN 3 +#define XGE_HAL_HEADER_SNAP_ALIGN 1 + +#define XGE_HAL_L3_CKSUM_OK 0xFFFF +#define XGE_HAL_L4_CKSUM_OK 0xFFFF +#define XGE_HAL_MIN_MTU 46 +#define XGE_HAL_MAX_MTU 9600 +#define XGE_HAL_DEFAULT_MTU 1500 + +#define XGE_HAL_SEGEMENT_OFFLOAD_MAX_SIZE 81920 + +#define XGE_HAL_PCISIZE_XENA 26 /* multiples of dword */ +#define XGE_HAL_PCISIZE_HERC 64 /* multiples of dword */ + +#define XGE_HAL_MAX_MSIX_MESSAGES 64 +#define XGE_HAL_MAX_MSIX_MESSAGES_WITH_ADDR XGE_HAL_MAX_MSIX_MESSAGES * 2 +/* Highest level interrupt blocks */ +#define XGE_HAL_TX_PIC_INTR (0x0001<<0) +#define XGE_HAL_TX_DMA_INTR (0x0001<<1) +#define XGE_HAL_TX_MAC_INTR (0x0001<<2) +#define XGE_HAL_TX_XGXS_INTR (0x0001<<3) +#define XGE_HAL_TX_TRAFFIC_INTR (0x0001<<4) +#define XGE_HAL_RX_PIC_INTR (0x0001<<5) +#define XGE_HAL_RX_DMA_INTR (0x0001<<6) +#define XGE_HAL_RX_MAC_INTR (0x0001<<7) +#define XGE_HAL_RX_XGXS_INTR (0x0001<<8) +#define XGE_HAL_RX_TRAFFIC_INTR (0x0001<<9) +#define XGE_HAL_MC_INTR (0x0001<<10) +#define XGE_HAL_SCHED_INTR (0x0001<<11) +#define XGE_HAL_ALL_INTRS (XGE_HAL_TX_PIC_INTR | \ + XGE_HAL_TX_DMA_INTR | \ + XGE_HAL_TX_MAC_INTR | \ + XGE_HAL_TX_XGXS_INTR | \ + XGE_HAL_TX_TRAFFIC_INTR | \ + XGE_HAL_RX_PIC_INTR | \ + XGE_HAL_RX_DMA_INTR | \ + XGE_HAL_RX_MAC_INTR | \ + XGE_HAL_RX_XGXS_INTR | \ + XGE_HAL_RX_TRAFFIC_INTR | \ + XGE_HAL_MC_INTR | \ + XGE_HAL_SCHED_INTR) +#define XGE_HAL_GEN_MASK_INTR (0x0001<<12) + +/* Interrupt masks for the general interrupt mask register */ +#define XGE_HAL_ALL_INTRS_DIS 0xFFFFFFFFFFFFFFFFULL + +#define XGE_HAL_TXPIC_INT_M BIT(0) +#define XGE_HAL_TXDMA_INT_M BIT(1) +#define XGE_HAL_TXMAC_INT_M BIT(2) +#define XGE_HAL_TXXGXS_INT_M BIT(3) +#define XGE_HAL_TXTRAFFIC_INT_M BIT(8) +#define XGE_HAL_PIC_RX_INT_M BIT(32) +#define XGE_HAL_RXDMA_INT_M BIT(33) +#define XGE_HAL_RXMAC_INT_M BIT(34) +#define XGE_HAL_MC_INT_M BIT(35) +#define XGE_HAL_RXXGXS_INT_M BIT(36) +#define XGE_HAL_RXTRAFFIC_INT_M BIT(40) + +/* MSI level Interrupts */ +#define XGE_HAL_MAX_MSIX_VECTORS (16) + +typedef struct xge_hal_ipv4 { + u32 addr; +}xge_hal_ipv4; + +typedef struct xge_hal_ipv6 { + u64 addr[2]; +}xge_hal_ipv6; + +typedef union xge_hal_ipaddr_t { + xge_hal_ipv4 ipv4; + xge_hal_ipv6 ipv6; +}xge_hal_ipaddr_t; + +/* DMA level Interrupts */ +#define XGE_HAL_TXDMA_PFC_INT_M BIT(0) + +/* PFC block interrupts */ +#define XGE_HAL_PFC_MISC_ERR_1 BIT(0) /* Interrupt to indicate FIFO +full */ + +/* basic handles */ +typedef void* xge_hal_device_h; +typedef void* xge_hal_dtr_h; +typedef void* xge_hal_channel_h; +#ifdef XGEHAL_RNIC +typedef void* xge_hal_towi_h; +typedef void* xge_hal_hw_wqe_h; +typedef void* xge_hal_hw_cqe_h; +typedef void* xge_hal_lro_wqe_h; +typedef void* xge_hal_lro_cqe_h; +typedef void* xge_hal_up_msg_h; +typedef void* xge_hal_down_msg_h; +typedef void* xge_hal_channel_callback_fh; +typedef void* xge_hal_msg_queueh; +typedef void* xge_hal_pblist_h; +#endif +/* + * I2C device id. Used in I2C control register for accessing EEPROM device + * memory. + */ +#define XGE_DEV_ID 5 + +typedef enum xge_hal_xpak_alarm_type_e { + XGE_HAL_XPAK_ALARM_EXCESS_TEMP = 1, + XGE_HAL_XPAK_ALARM_EXCESS_BIAS_CURRENT = 2, + XGE_HAL_XPAK_ALARM_EXCESS_LASER_OUTPUT = 3, +} xge_hal_xpak_alarm_type_e; + + +__EXTERN_END_DECLS + +#endif /* XGE_HAL_TYPES_H */ diff --git a/sys/dev/nxge/include/xgehal.h b/sys/dev/nxge/include/xgehal.h new file mode 100644 index 0000000..4c3c08a --- /dev/null +++ b/sys/dev/nxge/include/xgehal.h @@ -0,0 +1,53 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal.h + * + * Description: Consolidated header. Upper layers should include it to + * avoid include order problems. + * + * Created: 14 May 2004 + */ + +#ifndef XGE_HAL_H +#define XGE_HAL_H + +#include <dev/nxge/include/xge-defs.h> +#include <dev/nxge/include/xge-os-pal.h> +#include <dev/nxge/include/xge-debug.h> +#include <dev/nxge/include/xgehal-types.h> +#include <dev/nxge/include/xgehal-driver.h> +#include <dev/nxge/include/xgehal-config.h> +#include <dev/nxge/include/xgehal-device.h> +#include <dev/nxge/include/xgehal-channel.h> +#include <dev/nxge/include/xgehal-fifo.h> +#include <dev/nxge/include/xgehal-ring.h> +#include <dev/nxge/include/xgehal-mgmt.h> + +#endif /* XGE_HAL_H */ diff --git a/sys/dev/nxge/xge-osdep.h b/sys/dev/nxge/xge-osdep.h new file mode 100644 index 0000000..b2c448d --- /dev/null +++ b/sys/dev/nxge/xge-osdep.h @@ -0,0 +1,758 @@ +/*- + * 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$ + */ + +/* + * xge-osdep.h + * + * Platform-dependent "glue" code + */ + +#ifndef XGE_OSDEP_H +#define XGE_OSDEP_H + +/****************************************** + * Includes and defines + ******************************************/ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/rman.h> +#include <sys/stddef.h> +#include <sys/types.h> +#include <sys/sockio.h> +#include <sys/proc.h> +#include <sys/mutex.h> +#include <sys/types.h> +#include <sys/endian.h> +#include <machine/bus.h> +#include <machine/resource.h> +#include <machine/clock.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pci_private.h> +#include <net/if.h> +#include <net/if_arp.h> +#include <net/ethernet.h> +#include <net/if_dl.h> +#include <net/if_media.h> +#include <net/if_var.h> +#include <net/bpf.h> +#include <net/if_types.h> + + +#define XGE_OS_PLATFORM_64BIT + +#if BYTE_ORDER == BIG_ENDIAN +#define XGE_OS_HOST_BIG_ENDIAN 1 +#elif BYTE_ORDER == LITTLE_ENDIAN +#define XGE_OS_HOST_LITTLE_ENDIAN 1 +#endif + +#define XGE_HAL_USE_5B_MODE 1 +#define XGE_HAL_PROCESS_LINK_INT_IN_ISR 1 +#define OS_NETSTACK_BUF struct mbuf * +#define XGE_LL_IP_FAST_CSUM(hdr, len) 0 + +#define xge_os_ntohs ntohs +#define xge_os_ntohl ntohl +#define xge_os_htons htons +#define xge_os_htonl htonl + +#ifndef __DECONST +#define __DECONST(type, var) ((type)(uintrptr_t)(const void *)(var)) +#endif + +typedef struct busresources { + bus_space_tag_t bus_tag; /* DMA Tag */ + bus_space_handle_t bus_handle; /* Bus handle */ + struct resource *bar_start_addr;/* BAR start address */ +} busresource_t; + +typedef struct xge_dma_alloc { + bus_addr_t dma_phyaddr; /* Physical Address */ + caddr_t dma_viraddr; /* Virtual Address */ + bus_dma_tag_t dma_tag; /* DMA Tag */ + bus_dmamap_t dma_map; /* DMA Map */ + bus_dma_segment_t dma_segment; /* DMA Segment */ + bus_size_t dma_size; /* Size */ + int dma_nseg; /* Maximum scatter-gather segs. */ +} xdma; + +struct xge_dma_mbuf { + bus_addr_t dma_phyaddr; /* Physical Address */ + bus_dmamap_t dma_map; /* DMA Map */ +}; + +typedef struct pci_info { + device_t device; /* Device */ + struct resource *regmap0; /* Resource for BAR0 */ + struct resource *regmap1; /* Resource for BAR1 */ + void *bar0resource; /* BAR0 tag and handle */ + void *bar1resource; /* BAR1 tag and handle */ +} pci_info_t; + + +/****************************************** + * Fixed size primitive types + ******************************************/ +#define u8 uint8_t +#define u16 uint16_t +#define u32 uint32_t +#define u64 uint64_t +#define ulong_t unsigned long +#define uint unsigned int +#define ptrdiff_t ptrdiff_t +typedef bus_addr_t dma_addr_t; +typedef struct mtx spinlock_t; +typedef pci_info_t *pci_dev_h; +typedef busresource_t *pci_reg_h; +typedef struct xge_dma_alloc pci_dma_h; +typedef struct resource *pci_irq_h; +typedef pci_info_t *pci_cfg_h; +typedef struct xge_dma_alloc pci_dma_acc_h; + +/****************************************** + * "libc" functionality + ******************************************/ +#define xge_os_memzero(addr, size) bzero(addr, size) +#define xge_os_memcpy(dst, src, size) bcopy(src, dst, size) +#define xge_os_memcmp memcmp +#define xge_os_strcpy strcpy +#define xge_os_strlen strlen +#define xge_os_snprintf snprintf +#define xge_os_sprintf sprintf +#define xge_os_printf(fmt...) { \ + printf(fmt); \ + printf("\n"); \ +} + +#define xge_os_vaprintf(fmt) { \ + sprintf(fmt, fmt, "\n"); \ + va_list va; \ + va_start(va, fmt); \ + vprintf(fmt, va); \ + va_end(va); \ +} + +#define xge_os_vasprintf(buf, fmt) { \ + va_list va; \ + va_start(va, fmt); \ + (void) vaprintf(buf, fmt, va); \ + va_end(va); \ +} + +#define xge_os_timestamp(buf) { \ + struct timeval current_time; \ + gettimeofday(¤t_time, 0); \ + sprintf(buf, "%08li.%08li: ", current_time.tv_sec, \ + current_time.tv_usec); \ +} + +#define xge_os_println xge_os_printf + +/****************************************** + * Synchronization Primitives + ******************************************/ +/* Initialize the spin lock */ +#define xge_os_spin_lock_init(lockp, ctxh) \ + if(mtx_initialized(lockp) == 0) { \ + mtx_init((lockp), "xge", MTX_NETWORK_LOCK, MTX_DEF); \ + } + +/* Initialize the spin lock (IRQ version) */ +#define xge_os_spin_lock_init_irq(lockp, ctxh) \ + if(mtx_initialized(lockp) == 0) { \ + mtx_init((lockp), "xge", MTX_NETWORK_LOCK, MTX_DEF); \ + } + +/* Destroy the lock */ +#define xge_os_spin_lock_destroy(lockp, ctxh) \ + if(mtx_initialized(lockp) != 0) { \ + mtx_destroy(lockp); \ + } + +/* Destroy the lock (IRQ version) */ +#define xge_os_spin_lock_destroy_irq(lockp, ctxh) \ + if(mtx_initialized(lockp) != 0) { \ + mtx_destroy(lockp); \ + } + +/* Acquire the lock */ +#define xge_os_spin_lock(lockp) \ + if(mtx_owned(lockp) == 0) mtx_lock(lockp) + +/* Release the lock */ +#define xge_os_spin_unlock(lockp) mtx_unlock(lockp) + +/* Acquire the lock (IRQ version) */ +#define xge_os_spin_lock_irq(lockp, flags) { \ + flags = MTX_QUIET; \ + if(mtx_owned(lockp) == 0) mtx_lock_flags(lockp, flags); \ +} + +/* Release the lock (IRQ version) */ +#define xge_os_spin_unlock_irq(lockp, flags) { \ + flags = MTX_QUIET; \ + mtx_unlock_flags(lockp, flags); \ +} + +/* Write memory barrier */ +#define xge_os_wmb() + +/* Delay (in micro seconds) */ +#define xge_os_udelay(us) DELAY(us) + +/* Delay (in milli seconds) */ +#define xge_os_mdelay(ms) DELAY(ms * 1000) + +/* Compare and exchange */ +//#define xge_os_cmpxchg(targetp, cmd, newval) + +/****************************************** + * Misc primitives + ******************************************/ +#define xge_os_unlikely(x) (x) +#define xge_os_prefetch(x) (x=x) +#define xge_os_prefetchw(x) (x=x) +#define xge_os_bug(fmt...) printf(fmt...) +#define xge_os_htohs ntohs +#define xge_os_ntohl ntohl +#define xge_os_htons htons +#define xge_os_htonl htonl + +/****************************************** + * Compiler Stuffs + ******************************************/ +#define __xge_os_attr_cacheline_aligned +#define __xge_os_cacheline_size 32 + +/****************************************** + * Memory Primitives + ******************************************/ +#define XGE_OS_INVALID_DMA_ADDR ((dma_addr_t)0) + +/****************************************** + * xge_os_malloc - Allocate non DMA-able memory. + * @pdev: Device context. + * @size: Size to allocate. + * + * Allocate @size bytes of memory. This allocation can sleep, and + * therefore, and therefore it requires process context. In other words, + * xge_os_malloc() cannot be called from the interrupt context. + * Use xge_os_free() to free the allocated block. + * + * Returns: Pointer to allocated memory, NULL - on failure. + * + * See also: xge_os_free(). + ******************************************/ +static inline void * +xge_os_malloc(pci_dev_h pdev, unsigned long size) { + void *vaddr = malloc((size), M_DEVBUF, M_NOWAIT); + xge_os_memzero(vaddr, size); + XGE_OS_MEMORY_CHECK_MALLOC(vaddr, size, file, line); + return (vaddr); +} + +/****************************************** + * xge_os_free - Free non DMA-able memory. + * @pdev: Device context. + * @vaddr: Address of the allocated memory block. + * @size: Some OS's require to provide size on free + * + * Free the memory area obtained via xge_os_malloc(). + * This call may also sleep, and therefore it cannot be used inside + * interrupt. + * + * See also: xge_os_malloc(). + ******************************************/ +static inline void +xge_os_free(pci_dev_h pdev, const void *vaddr, unsigned long size) { + XGE_OS_MEMORY_CHECK_FREE(vaddr, size); + free(__DECONST(void *, vaddr), M_DEVBUF); +} + +static void +xge_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) { + if(error) return; + *(bus_addr_t *) arg = segs->ds_addr; + return; +} + +/****************************************** + * xge_os_dma_malloc - Allocate DMA-able memory. + * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. + * @size: Size (in bytes) to allocate. + * @dma_flags: XGE_OS_DMA_CACHELINE_ALIGNED, + * XGE_OS_DMA_STREAMING, + * XGE_OS_DMA_CONSISTENT + * Note that the last two flags are mutually exclusive. + * @p_dmah: Handle used to map the memory onto the corresponding device memory + * space. See xge_os_dma_map(). The handle is an out-parameter + * returned by the function. + * @p_dma_acch: One more DMA handle used subsequently to free the + * DMA object (via xge_os_dma_free()). + * + * Allocate DMA-able contiguous memory block of the specified @size. + * This memory can be subsequently freed using xge_os_dma_free(). + * Note: can be used inside interrupt context. + * + * Returns: Pointer to allocated memory(DMA-able), NULL on failure. + * + ******************************************/ +static inline void * +xge_os_dma_malloc(pci_dev_h pdev, unsigned long size, int dma_flags, + pci_dma_h *p_dmah, pci_dma_acc_h *p_dma_acch) { + int retValue = bus_dma_tag_create( + bus_get_dma_tag(pdev->device), /* Parent */ + PAGE_SIZE, /* Alignment no specific alignment */ + 0, /* Bounds */ + BUS_SPACE_MAXADDR, /* Low Address */ + BUS_SPACE_MAXADDR, /* High Address */ + NULL, /* Filter */ + NULL, /* Filter arg */ + size, /* Max Size */ + 1, /* n segments */ + size, /* max segment size */ + BUS_DMA_ALLOCNOW, /* Flags */ + NULL, /* lockfunction */ + NULL, /* lock arg */ + &p_dmah->dma_tag); /* DMA tag */ + if(retValue != 0) { + xge_os_printf("bus_dma_tag_create failed\n"); + goto fail_1; + } + p_dmah->dma_size = size; + retValue = bus_dmamem_alloc(p_dmah->dma_tag, + (void **)&p_dmah->dma_viraddr, BUS_DMA_NOWAIT, &p_dmah->dma_map); + if(retValue != 0) { + xge_os_printf("bus_dmamem_alloc failed\n"); + goto fail_2; + } + return(p_dmah->dma_viraddr); + +fail_2: bus_dma_tag_destroy(p_dmah->dma_tag); +fail_1: return(NULL); +} + +/****************************************** + * xge_os_dma_free - Free previously allocated DMA-able memory. + * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. + * @vaddr: Virtual address of the DMA-able memory. + * @p_dma_acch: DMA handle used to free the resource. + * @p_dmah: DMA handle used for mapping. See xge_os_dma_malloc(). + * + * Free DMA-able memory originally allocated by xge_os_dma_malloc(). + * Note: can be used inside interrupt. + * See also: xge_os_dma_malloc(). + ******************************************/ +static inline void +xge_os_dma_free(pci_dev_h pdev, const void *vaddr, int size, + pci_dma_acc_h *p_dma_acch, pci_dma_h *p_dmah) { + XGE_OS_MEMORY_CHECK_FREE(p_dmah->dma_viraddr, size); + bus_dmamem_free(p_dmah->dma_tag, p_dmah->dma_viraddr, p_dmah->dma_map); + bus_dma_tag_destroy(p_dmah->dma_tag); + p_dmah->dma_map = NULL; + p_dmah->dma_tag = NULL; + p_dmah->dma_viraddr = NULL; + return; +} + +/****************************************** + * IO/PCI/DMA Primitives + ******************************************/ +#define XGE_OS_DMA_DIR_TODEVICE 0 +#define XGE_OS_DMA_DIR_FROMDEVICE 1 +#define XGE_OS_DMA_DIR_BIDIRECTIONAL 2 + +/****************************************** + * xge_os_pci_read8 - Read one byte from device PCI configuration. + * @pdev: Device context. Some OSs require device context to perform + * PIO and/or config space IO. + * @cfgh: PCI configuration space handle. + * @where: Offset in the PCI configuration space. + * @val: Address of the result. + * + * Read byte value from the specified @regh PCI configuration space at the + * specified offset = @where. + * Returns: 0 - success, non-zero - failure. + ******************************************/ +#define xge_os_pci_read8(pdev, cfgh, where, val) \ + (*(val) = pci_read_config(pdev->device, where, 1)) + +/****************************************** + * xge_os_pci_write8 - Write one byte into device PCI configuration. + * @pdev: Device context. Some OSs require device context to perform + * PIO and/or config space IO. + * @cfgh: PCI configuration space handle. + * @where: Offset in the PCI configuration space. + * @val: Value to write. + * + * Write byte value into the specified PCI configuration space + * Returns: 0 - success, non-zero - failure. + ******************************************/ +#define xge_os_pci_write8(pdev, cfgh, where, val) \ + pci_write_config(pdev->device, where, val, 1) + +/****************************************** + * xge_os_pci_read16 - Read 16bit word from device PCI configuration. + * @pdev: Device context. + * @cfgh: PCI configuration space handle. + * @where: Offset in the PCI configuration space. + * @val: Address of the 16bit result. + * + * Read 16bit value from the specified PCI configuration space at the + * specified offset. + * Returns: 0 - success, non-zero - failure. + ******************************************/ +#define xge_os_pci_read16(pdev, cfgh, where, val) \ + (*(val) = pci_read_config(pdev->device, where, 2)) + +/****************************************** + * xge_os_pci_write16 - Write 16bit word into device PCI configuration. + * @pdev: Device context. + * @cfgh: PCI configuration space handle. + * @where: Offset in the PCI configuration space. + * @val: Value to write. + * + * Write 16bit value into the specified @offset in PCI + * configuration space. + * Returns: 0 - success, non-zero - failure. + ******************************************/ +#define xge_os_pci_write16(pdev, cfgh, where, val) \ + pci_write_config(pdev->device, where, val, 2) + +/****************************************** + * xge_os_pci_read32 - Read 32bit word from device PCI configuration. + * @pdev: Device context. + * @cfgh: PCI configuration space handle. + * @where: Offset in the PCI configuration space. + * @val: Address of 32bit result. + * + * Read 32bit value from the specified PCI configuration space at the + * specified offset. + * Returns: 0 - success, non-zero - failure. + ******************************************/ +#define xge_os_pci_read32(pdev, cfgh, where, val) \ + (*(val) = pci_read_config(pdev->device, where, 4)) + +/****************************************** + * xge_os_pci_write32 - Write 32bit word into device PCI configuration. + * @pdev: Device context. + * @cfgh: PCI configuration space handle. + * @where: Offset in the PCI configuration space. + * @val: Value to write. + * + * Write 32bit value into the specified @offset in PCI + * configuration space. + * Returns: 0 - success, non-zero - failure. + ******************************************/ +#define xge_os_pci_write32(pdev, cfgh, where, val) \ + pci_write_config(pdev->device, where, val, 4) + +/****************************************** + * xge_os_pio_mem_read8 - Read 1 byte from device memory mapped space. + * @pdev: Device context. + * @regh: PCI configuration space handle. + * @addr: Address in device memory space. + * + * Returns: 1 byte value read from the specified (mapped) memory space address. + ******************************************/ +static inline u8 +xge_os_pio_mem_read8(pci_dev_h pdev, pci_reg_h regh, void *addr) +{ + bus_space_tag_t tag = + (bus_space_tag_t)(((busresource_t *)regh)->bus_tag); + bus_space_handle_t handle = + (bus_space_handle_t)(((busresource_t *)regh)->bus_handle); + caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr); + + return bus_space_read_1(tag, handle, (caddr_t)(addr) - addrss); +} + +/****************************************** + * xge_os_pio_mem_write8 - Write 1 byte into device memory mapped + * space. + * @pdev: Device context. + * @regh: PCI configuration space handle. + * @val: Value to write. + * @addr: Address in device memory space. + * + * Write byte value into the specified (mapped) device memory space. + ******************************************/ +static inline void +xge_os_pio_mem_write8(pci_dev_h pdev, pci_reg_h regh, u8 val, void *addr) +{ + bus_space_tag_t tag = + (bus_space_tag_t)(((busresource_t *)regh)->bus_tag); + bus_space_handle_t handle = + (bus_space_handle_t)(((busresource_t *)regh)->bus_handle); + caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr); + + bus_space_write_1(tag, handle, (caddr_t)(addr) - addrss, val); +} + +/****************************************** + * xge_os_pio_mem_read16 - Read 16bit from device memory mapped space. + * @pdev: Device context. + * @regh: PCI configuration space handle. + * @addr: Address in device memory space. + * + * Returns: 16bit value read from the specified (mapped) memory space address. + ******************************************/ +static inline u16 +xge_os_pio_mem_read16(pci_dev_h pdev, pci_reg_h regh, void *addr) +{ + bus_space_tag_t tag = + (bus_space_tag_t)(((busresource_t *)regh)->bus_tag); + bus_space_handle_t handle = + (bus_space_handle_t)(((busresource_t *)regh)->bus_handle); + caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr); + + return bus_space_read_2(tag, handle, (caddr_t)(addr) - addrss); +} + +/****************************************** + * xge_os_pio_mem_write16 - Write 16bit into device memory mapped space. + * @pdev: Device context. + * @regh: PCI configuration space handle. + * @val: Value to write. + * @addr: Address in device memory space. + * + * Write 16bit value into the specified (mapped) device memory space. + ******************************************/ +static inline void +xge_os_pio_mem_write16(pci_dev_h pdev, pci_reg_h regh, u16 val, void *addr) +{ + bus_space_tag_t tag = + (bus_space_tag_t)(((busresource_t *)regh)->bus_tag); + bus_space_handle_t handle = + (bus_space_handle_t)(((busresource_t *)regh)->bus_handle); + caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr); + + bus_space_write_2(tag, handle, (caddr_t)(addr) - addrss, val); +} + +/****************************************** + * xge_os_pio_mem_read32 - Read 32bit from device memory mapped space. + * @pdev: Device context. + * @regh: PCI configuration space handle. + * @addr: Address in device memory space. + * + * Returns: 32bit value read from the specified (mapped) memory space address. + ******************************************/ +static inline u32 +xge_os_pio_mem_read32(pci_dev_h pdev, pci_reg_h regh, void *addr) +{ + bus_space_tag_t tag = + (bus_space_tag_t)(((busresource_t *)regh)->bus_tag); + bus_space_handle_t handle = + (bus_space_handle_t)(((busresource_t *)regh)->bus_handle); + caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr); + + return bus_space_read_4(tag, handle, (caddr_t)(addr) - addrss); +} + +/****************************************** + * xge_os_pio_mem_write32 - Write 32bit into device memory space. + * @pdev: Device context. + * @regh: PCI configuration space handle. + * @val: Value to write. + * @addr: Address in device memory space. + * + * Write 32bit value into the specified (mapped) device memory space. + ******************************************/ +static inline void +xge_os_pio_mem_write32(pci_dev_h pdev, pci_reg_h regh, u32 val, void *addr) +{ + bus_space_tag_t tag = + (bus_space_tag_t)(((busresource_t *)regh)->bus_tag); + bus_space_handle_t handle = + (bus_space_handle_t)(((busresource_t *)regh)->bus_handle); + caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr); + bus_space_write_4(tag, handle, (caddr_t)(addr) - addrss, val); +} + +/****************************************** + * xge_os_pio_mem_read64 - Read 64bit from device memory mapped space. + * @pdev: Device context. + * @regh: PCI configuration space handle. + * @addr: Address in device memory space. + * + * Returns: 64bit value read from the specified (mapped) memory space address. + ******************************************/ +static inline u64 +xge_os_pio_mem_read64(pci_dev_h pdev, pci_reg_h regh, void *addr) +{ + u64 value1, value2; + + bus_space_tag_t tag = + (bus_space_tag_t)(((busresource_t *)regh)->bus_tag); + bus_space_handle_t handle = + (bus_space_handle_t)(((busresource_t *)regh)->bus_handle); + caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr); + + value1 = bus_space_read_4(tag, handle, (caddr_t)(addr) + 4 - addrss); + value1 <<= 32; + value2 = bus_space_read_4(tag, handle, (caddr_t)(addr) - addrss); + value1 |= value2; + return value1; +} + +/****************************************** + * xge_os_pio_mem_write64 - Write 32bit into device memory space. + * @pdev: Device context. + * @regh: PCI configuration space handle. + * @val: Value to write. + * @addr: Address in device memory space. + * + * Write 64bit value into the specified (mapped) device memory space. + ******************************************/ +static inline void +xge_os_pio_mem_write64(pci_dev_h pdev, pci_reg_h regh, u64 val, void *addr) +{ + u32 vall = val & 0xffffffff; + xge_os_pio_mem_write32(pdev, regh, vall, addr); + xge_os_pio_mem_write32(pdev, regh, val >> 32, ((caddr_t)(addr) + 4)); +} + +/****************************************** + * FIXME: document + ******************************************/ +#define xge_os_flush_bridge xge_os_pio_mem_read64 + +/****************************************** + * xge_os_dma_map - Map DMA-able memory block to, or from, or + * to-and-from device. + * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. + * @dmah: DMA handle used to map the memory block. Obtained via + * xge_os_dma_malloc(). + * @vaddr: Virtual address of the DMA-able memory. + * @size: Size (in bytes) to be mapped. + * @dir: Direction of this operation (XGE_OS_DMA_DIR_TODEVICE, etc.) + * @dma_flags: XGE_OS_DMA_CACHELINE_ALIGNED, + * XGE_OS_DMA_STREAMING, + * XGE_OS_DMA_CONSISTENT + * Note that the last two flags are mutually exclusive. + * + * Map a single memory block. + * + * Returns: DMA address of the memory block, + * XGE_OS_INVALID_DMA_ADDR on failure. + * + * See also: xge_os_dma_malloc(), xge_os_dma_unmap(), + * xge_os_dma_sync(). + ******************************************/ +static inline dma_addr_t +xge_os_dma_map(pci_dev_h pdev, pci_dma_h dmah, void *vaddr, size_t size, + int dir, int dma_flags) +{ + int retValue = + bus_dmamap_load(dmah.dma_tag, dmah.dma_map, dmah.dma_viraddr, + dmah.dma_size, xge_dmamap_cb, &dmah.dma_phyaddr, BUS_DMA_NOWAIT); + if(retValue != 0) { + xge_os_printf("bus_dmamap_load_ failed\n"); + return XGE_OS_INVALID_DMA_ADDR; + } + dmah.dma_size = size; + return dmah.dma_phyaddr; +} + +/****************************************** + * xge_os_dma_unmap - Unmap DMA-able memory. + * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. + * @dmah: DMA handle used to map the memory block. Obtained via + * xge_os_dma_malloc(). + * @dma_addr: DMA address of the block. Obtained via xge_os_dma_map(). + * @size: Size (in bytes) to be unmapped. + * @dir: Direction of this operation (XGE_OS_DMA_DIR_TODEVICE, etc.) + * + * Unmap a single DMA-able memory block that was previously mapped + * using xge_os_dma_map(). + * See also: xge_os_dma_malloc(), xge_os_dma_map(). + ******************************************/ +static inline void +xge_os_dma_unmap(pci_dev_h pdev, pci_dma_h dmah, dma_addr_t dma_addr, + size_t size, int dir) +{ + bus_dmamap_unload(dmah.dma_tag, dmah.dma_map); + return; +} + +/****************************************** + * xge_os_dma_sync - Synchronize mapped memory. + * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. + * @dmah: DMA handle used to map the memory block. Obtained via + * xge_os_dma_malloc(). + * @dma_addr: DMA address of the block. Obtained via xge_os_dma_map(). + * @dma_offset: Offset from start of the blocke. Used by Solaris only. + * @length: Size of the block. + * @dir: Direction of this operation (XGE_OS_DMA_DIR_TODEVICE, etc.) + * + * Make physical and CPU memory consistent for a single + * streaming mode DMA translation. + * This API compiles to NOP on cache-coherent platforms. + * On non cache-coherent platforms, depending on the direction + * of the "sync" operation, this API will effectively + * either invalidate CPU cache (that might contain old data), + * or flush CPU cache to update physical memory. + * See also: xge_os_dma_malloc(), xge_os_dma_map(), + * xge_os_dma_unmap(). + ******************************************/ +static inline void +xge_os_dma_sync(pci_dev_h pdev, pci_dma_h dmah, dma_addr_t dma_addr, + u64 dma_offset, size_t length, int dir) +{ + bus_dmasync_op_t syncop; + switch(dir) { + case XGE_OS_DMA_DIR_TODEVICE: + syncop = BUS_DMASYNC_PREWRITE | BUS_DMASYNC_POSTWRITE; + break; + + case XGE_OS_DMA_DIR_FROMDEVICE: + syncop = BUS_DMASYNC_PREREAD | BUS_DMASYNC_POSTREAD; + break; + + case XGE_OS_DMA_DIR_BIDIRECTIONAL: + syncop = BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREWRITE; + break; + } + bus_dmamap_sync(dmah.dma_tag, dmah.dma_map, syncop); + return; +} + +#endif /* XGE_OSDEP_H */ diff --git a/sys/dev/nxge/xgehal/xge-queue.c b/sys/dev/nxge/xgehal/xge-queue.c new file mode 100644 index 0000000..925f44f --- /dev/null +++ b/sys/dev/nxge/xgehal/xge-queue.c @@ -0,0 +1,460 @@ +/*- + * 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$ + */ + +/* + * FileName : xge-queue.c + * + * Description: serialized event queue + * + * Created: 7 June 2004 + */ + +#include <dev/nxge/include/xge-queue.h> + +/** + * xge_queue_item_data - Get item's data. + * @item: Queue item. + * + * Returns: item data(variable size). Note that xge_queue_t + * contains items comprized of a fixed xge_queue_item_t "header" + * and a variable size data. This function returns the variable + * user-defined portion of the queue item. + */ +void* xge_queue_item_data(xge_queue_item_t *item) +{ + return (char *)item + sizeof(xge_queue_item_t); +} + +/* + * __queue_consume - (Lockless) dequeue an item from the specified queue. + * + * @queue: Event queue. + * See xge_queue_consume(). + */ +static xge_queue_status_e +__queue_consume(xge_queue_t *queue, int data_max_size, xge_queue_item_t *item) +{ + int real_size; + xge_queue_item_t *elem; + + if (xge_list_is_empty(&queue->list_head)) + return XGE_QUEUE_IS_EMPTY; + + elem = (xge_queue_item_t *)queue->list_head.next; + if (elem->data_size > data_max_size) + return XGE_QUEUE_NOT_ENOUGH_SPACE; + + xge_list_remove(&elem->item); + real_size = elem->data_size + sizeof(xge_queue_item_t); + if (queue->head_ptr == elem) { + queue->head_ptr = (char *)queue->head_ptr + real_size; + xge_debug_queue(XGE_TRACE, + "event_type: %d removing from the head: " + "0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT + ":0x"XGE_OS_LLXFMT" elem 0x"XGE_OS_LLXFMT" length %d", + elem->event_type, + (u64)(ulong_t)queue->start_ptr, + (u64)(ulong_t)queue->head_ptr, + (u64)(ulong_t)queue->tail_ptr, + (u64)(ulong_t)queue->end_ptr, + (u64)(ulong_t)elem, + real_size); + } else if ((char *)queue->tail_ptr - real_size == (char*)elem) { + queue->tail_ptr = (char *)queue->tail_ptr - real_size; + xge_debug_queue(XGE_TRACE, + "event_type: %d removing from the tail: " + "0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT + ":0x"XGE_OS_LLXFMT" elem 0x"XGE_OS_LLXFMT" length %d", + elem->event_type, + (u64)(ulong_t)queue->start_ptr, + (u64)(ulong_t)queue->head_ptr, + (u64)(ulong_t)queue->tail_ptr, + (u64)(ulong_t)queue->end_ptr, + (u64)(ulong_t)elem, + real_size); + } else { + xge_debug_queue(XGE_TRACE, + "event_type: %d removing from the list: " + "0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT + ":0x"XGE_OS_LLXFMT" elem 0x"XGE_OS_LLXFMT" length %d", + elem->event_type, + (u64)(ulong_t)queue->start_ptr, + (u64)(ulong_t)queue->head_ptr, + (u64)(ulong_t)queue->tail_ptr, + (u64)(ulong_t)queue->end_ptr, + (u64)(ulong_t)elem, + real_size); + } + xge_assert(queue->tail_ptr >= queue->head_ptr); + xge_assert(queue->tail_ptr >= queue->start_ptr && + queue->tail_ptr <= queue->end_ptr); + xge_assert(queue->head_ptr >= queue->start_ptr && + queue->head_ptr < queue->end_ptr); + xge_os_memcpy(item, elem, sizeof(xge_queue_item_t)); + xge_os_memcpy(xge_queue_item_data(item), xge_queue_item_data(elem), + elem->data_size); + + if (xge_list_is_empty(&queue->list_head)) { + /* reset buffer pointers just to be clean */ + queue->head_ptr = queue->tail_ptr = queue->start_ptr; + } + return XGE_QUEUE_OK; +} + +/** + * xge_queue_produce - Enqueue an item (see xge_queue_item_t{}) + * into the specified queue. + * @queueh: Queue handle. + * @event_type: Event type. One of the enumerated event types + * that both consumer and producer "understand". + * For an example, please refer to xge_hal_event_e. + * @context: Opaque (void*) "context", for instance event producer object. + * @is_critical: For critical event, e.g. ECC. + * @data_size: Size of the @data. + * @data: User data of variable @data_size that is _copied_ into + * the new queue item (see xge_queue_item_t{}). Upon return + * from the call the @data memory can be re-used or released. + * + * Enqueue a new item. + * + * Returns: XGE_QUEUE_OK - success. + * XGE_QUEUE_IS_FULL - Queue is full. + * XGE_QUEUE_OUT_OF_MEMORY - Memory allocation failed. + * + * See also: xge_queue_item_t{}, xge_queue_consume(). + */ +xge_queue_status_e +xge_queue_produce(xge_queue_h queueh, int event_type, void *context, + int is_critical, const int data_size, void *data) +{ + xge_queue_t *queue = (xge_queue_t *)queueh; + int real_size = data_size + sizeof(xge_queue_item_t); + xge_queue_item_t *elem; + unsigned long flags = 0; + + xge_assert(real_size <= XGE_QUEUE_BUF_SIZE); + + xge_os_spin_lock_irq(&queue->lock, flags); + + if (is_critical && !queue->has_critical_event) { + unsigned char item_buf[sizeof(xge_queue_item_t) + + XGE_DEFAULT_EVENT_MAX_DATA_SIZE]; + xge_queue_item_t *item = (xge_queue_item_t *)(void *)item_buf; + xge_os_memzero(item_buf, (sizeof(xge_queue_item_t) + + XGE_DEFAULT_EVENT_MAX_DATA_SIZE)); + + while (__queue_consume(queue, + XGE_DEFAULT_EVENT_MAX_DATA_SIZE, + item) != XGE_QUEUE_IS_EMPTY) + ; /* do nothing */ + } + +try_again: + if ((char *)queue->tail_ptr + real_size <= (char *)queue->end_ptr) { + elem = (xge_queue_item_t *) queue->tail_ptr; + queue->tail_ptr = (void *)((char *)queue->tail_ptr + real_size); + xge_debug_queue(XGE_TRACE, + "event_type: %d adding to the tail: " + "0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT + ":0x"XGE_OS_LLXFMT" elem 0x"XGE_OS_LLXFMT" length %d", + event_type, + (u64)(ulong_t)queue->start_ptr, + (u64)(ulong_t)queue->head_ptr, + (u64)(ulong_t)queue->tail_ptr, + (u64)(ulong_t)queue->end_ptr, + (u64)(ulong_t)elem, + real_size); + } else if ((char *)queue->head_ptr - real_size >= + (char *)queue->start_ptr) { + elem = (xge_queue_item_t *) ((char *)queue->head_ptr - real_size); + queue->head_ptr = elem; + xge_debug_queue(XGE_TRACE, + "event_type: %d adding to the head: " + "0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT + ":0x"XGE_OS_LLXFMT" length %d", + event_type, + (u64)(ulong_t)queue->start_ptr, + (u64)(ulong_t)queue->head_ptr, + (u64)(ulong_t)queue->tail_ptr, + (u64)(ulong_t)queue->end_ptr, + real_size); + } else { + xge_queue_status_e status; + + if (queue->pages_current >= queue->pages_max) { + xge_os_spin_unlock_irq(&queue->lock, flags); + return XGE_QUEUE_IS_FULL; + } + + if (queue->has_critical_event) { + xge_os_spin_unlock_irq(&queue->lock, flags); + return XGE_QUEUE_IS_FULL; + } + + /* grow */ + status = __io_queue_grow(queueh); + if (status != XGE_QUEUE_OK) { + xge_os_spin_unlock_irq(&queue->lock, flags); + return status; + } + + goto try_again; + } + xge_assert(queue->tail_ptr >= queue->head_ptr); + xge_assert(queue->tail_ptr >= queue->start_ptr && + queue->tail_ptr <= queue->end_ptr); + xge_assert(queue->head_ptr >= queue->start_ptr && + queue->head_ptr < queue->end_ptr); + elem->data_size = data_size; + elem->event_type = (xge_hal_event_e) event_type; + elem->is_critical = is_critical; + if (is_critical) + queue->has_critical_event = 1; + elem->context = context; + xge_os_memcpy(xge_queue_item_data(elem), data, data_size); + xge_list_insert_before(&elem->item, &queue->list_head); + xge_os_spin_unlock_irq(&queue->lock, flags); + + /* no lock taken! */ + queue->queued_func(queue->queued_data, event_type); + + return XGE_QUEUE_OK; +} + + +/** + * xge_queue_create - Create protected first-in-first-out queue. + * @pdev: PCI device handle. + * @irqh: PCI device IRQ handle. + * @pages_initial: Number of pages to be initially allocated at the + * time of queue creation. + * @pages_max: Max number of pages that can be allocated in the queue. + * @queued: Optional callback function to be called each time a new item is + * added to the queue. + * @queued_data: Argument to the callback function. + * + * Create protected (fifo) queue. + * + * Returns: Pointer to xge_queue_t structure, + * NULL - on failure. + * + * See also: xge_queue_item_t{}, xge_queue_destroy(). + */ +xge_queue_h +xge_queue_create(pci_dev_h pdev, pci_irq_h irqh, int pages_initial, + int pages_max, xge_queued_f queued, void *queued_data) +{ + xge_queue_t *queue; + + if ((queue = (xge_queue_t *) xge_os_malloc(pdev, sizeof(xge_queue_t))) == NULL) + return NULL; + + queue->queued_func = queued; + queue->queued_data = queued_data; + queue->pdev = pdev; + queue->irqh = irqh; + queue->pages_current = pages_initial; + queue->start_ptr = xge_os_malloc(pdev, queue->pages_current * + XGE_QUEUE_BUF_SIZE); + if (queue->start_ptr == NULL) { + xge_os_free(pdev, queue, sizeof(xge_queue_t)); + return NULL; + } + queue->head_ptr = queue->tail_ptr = queue->start_ptr; + queue->end_ptr = (char *)queue->start_ptr + + queue->pages_current * XGE_QUEUE_BUF_SIZE; + xge_os_spin_lock_init_irq(&queue->lock, irqh); + queue->pages_initial = pages_initial; + queue->pages_max = pages_max; + xge_list_init(&queue->list_head); + + return queue; +} + +/** + * xge_queue_destroy - Destroy xge_queue_t object. + * @queueh: Queue handle. + * + * Destroy the specified xge_queue_t object. + * + * See also: xge_queue_item_t{}, xge_queue_create(). + */ +void xge_queue_destroy(xge_queue_h queueh) +{ + xge_queue_t *queue = (xge_queue_t *)queueh; + xge_os_spin_lock_destroy_irq(&queue->lock, queue->irqh); + if (!xge_list_is_empty(&queue->list_head)) { + xge_debug_queue(XGE_ERR, "destroying non-empty queue 0x" + XGE_OS_LLXFMT, (u64)(ulong_t)queue); + } + xge_os_free(queue->pdev, queue->start_ptr, queue->pages_current * + XGE_QUEUE_BUF_SIZE); + + xge_os_free(queue->pdev, queue, sizeof(xge_queue_t)); +} + +/* + * __io_queue_grow - Dynamically increases the size of the queue. + * @queueh: Queue handle. + * + * This function is called in the case of no slot avaialble in the queue + * to accomodate the newly received event. + * Note that queue cannot grow beyond the max size specified for the + * queue. + * + * Returns XGE_QUEUE_OK: On success. + * XGE_QUEUE_OUT_OF_MEMORY : No memory is available. + */ +xge_queue_status_e +__io_queue_grow(xge_queue_h queueh) +{ + xge_queue_t *queue = (xge_queue_t *)queueh; + void *newbuf, *oldbuf; + xge_list_t *item; + xge_queue_item_t *elem; + + xge_debug_queue(XGE_TRACE, "queue 0x"XGE_OS_LLXFMT":%d is growing", + (u64)(ulong_t)queue, queue->pages_current); + + newbuf = xge_os_malloc(queue->pdev, + (queue->pages_current + 1) * XGE_QUEUE_BUF_SIZE); + if (newbuf == NULL) + return XGE_QUEUE_OUT_OF_MEMORY; + + xge_os_memcpy(newbuf, queue->start_ptr, + queue->pages_current * XGE_QUEUE_BUF_SIZE); + oldbuf = queue->start_ptr; + + /* adjust queue sizes */ + queue->start_ptr = newbuf; + queue->end_ptr = (char *)newbuf + + (queue->pages_current + 1) * XGE_QUEUE_BUF_SIZE; + queue->tail_ptr = (char *)newbuf + ((char *)queue->tail_ptr - + (char *)oldbuf); + queue->head_ptr = (char *)newbuf + ((char *)queue->head_ptr - + (char *)oldbuf); + xge_assert(!xge_list_is_empty(&queue->list_head)); + queue->list_head.next = (xge_list_t *) (void *)((char *)newbuf + + ((char *)queue->list_head.next - (char *)oldbuf)); + queue->list_head.prev = (xge_list_t *) (void *)((char *)newbuf + + ((char *)queue->list_head.prev - (char *)oldbuf)); + /* adjust queue list */ + xge_list_for_each(item, &queue->list_head) { + elem = xge_container_of(item, xge_queue_item_t, item); + if (elem->item.next != &queue->list_head) { + elem->item.next = + (xge_list_t*)(void *)((char *)newbuf + + ((char *)elem->item.next - (char *)oldbuf)); + } + if (elem->item.prev != &queue->list_head) { + elem->item.prev = + (xge_list_t*) (void *)((char *)newbuf + + ((char *)elem->item.prev - (char *)oldbuf)); + } + } + xge_os_free(queue->pdev, oldbuf, + queue->pages_current * XGE_QUEUE_BUF_SIZE); + queue->pages_current++; + + return XGE_QUEUE_OK; +} + +/** + * xge_queue_consume - Dequeue an item from the specified queue. + * @queueh: Queue handle. + * @data_max_size: Maximum expected size of the item. + * @item: Memory area into which the item is _copied_ upon return + * from the function. + * + * Dequeue an item from the queue. The caller is required to provide + * enough space for the item. + * + * Returns: XGE_QUEUE_OK - success. + * XGE_QUEUE_IS_EMPTY - Queue is empty. + * XGE_QUEUE_NOT_ENOUGH_SPACE - Requested item size(@data_max_size) + * is too small to accomodate an item from the queue. + * + * See also: xge_queue_item_t{}, xge_queue_produce(). + */ +xge_queue_status_e +xge_queue_consume(xge_queue_h queueh, int data_max_size, xge_queue_item_t *item) +{ + xge_queue_t *queue = (xge_queue_t *)queueh; + unsigned long flags = 0; + xge_queue_status_e status; + + xge_os_spin_lock_irq(&queue->lock, flags); + status = __queue_consume(queue, data_max_size, item); + xge_os_spin_unlock_irq(&queue->lock, flags); + + return status; +} + + +/** + * xge_queue_flush - Flush, or empty, the queue. + * @queueh: Queue handle. + * + * Flush the queue, i.e. make it empty by consuming all events + * without invoking the event processing logic (callbacks, etc.) + */ +void xge_queue_flush(xge_queue_h queueh) +{ + unsigned char item_buf[sizeof(xge_queue_item_t) + + XGE_DEFAULT_EVENT_MAX_DATA_SIZE]; + xge_queue_item_t *item = (xge_queue_item_t *)(void *)item_buf; + xge_os_memzero(item_buf, (sizeof(xge_queue_item_t) + + XGE_DEFAULT_EVENT_MAX_DATA_SIZE)); + + /* flush queue by consuming all enqueued items */ + while (xge_queue_consume(queueh, + XGE_DEFAULT_EVENT_MAX_DATA_SIZE, + item) != XGE_QUEUE_IS_EMPTY) { + /* do nothing */ + xge_debug_queue(XGE_TRACE, "item "XGE_OS_LLXFMT"(%d) flushed", + item, item->event_type); + } + (void) __queue_get_reset_critical (queueh); +} + +/* + * __queue_get_reset_critical - Check for critical events in the queue, + * @qh: Queue handle. + * + * Check for critical event(s) in the queue, and reset the + * "has-critical-event" flag upon return. + * Returns: 1 - if the queue contains atleast one critical event. + * 0 - If there are no critical events in the queue. + */ +int __queue_get_reset_critical (xge_queue_h qh) { + xge_queue_t* queue = (xge_queue_t*)qh; + int c = queue->has_critical_event; + + queue->has_critical_event = 0; + return c; +} diff --git a/sys/dev/nxge/xgehal/xgehal-channel-fp.c b/sys/dev/nxge/xgehal/xgehal-channel-fp.c new file mode 100644 index 0000000..0417ca0 --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-channel-fp.c @@ -0,0 +1,299 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-channel-fp.c + * + * Description: HAL channel object functionality (fast path) + * + * Created: 10 June 2004 + */ + +#ifdef XGE_DEBUG_FP +#include <dev/nxge/include/xgehal-channel.h> +#endif + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_channel_dtr_alloc(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh) +{ + void **tmp_arr; + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; +#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ) + unsigned long flags = 0; +#endif + + if (channel->reserve_length - channel->reserve_top > + channel->reserve_threshold) { + +_alloc_after_swap: + *dtrh = channel->reserve_arr[--channel->reserve_length]; + + xge_debug_channel(XGE_TRACE, "dtrh 0x"XGE_OS_LLXFMT" allocated, " + "channel %d:%d:%d, reserve_idx %d", + (unsigned long long)(ulong_t)*dtrh, + channel->type, channel->post_qid, + channel->compl_qid, channel->reserve_length); + + return XGE_HAL_OK; + } + +#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ) + xge_os_spin_lock_irq(&channel->free_lock, flags); +#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE) + xge_os_spin_lock(&channel->free_lock); +#endif + + /* switch between empty and full arrays */ + + /* the idea behind such a design is that by having free and reserved + * arrays separated we basically separated irq and non-irq parts. + * i.e. no additional lock need to be done when we free a resource */ + + if (channel->reserve_initial - channel->free_length > + channel->reserve_threshold) { + + tmp_arr = channel->reserve_arr; + channel->reserve_arr = channel->free_arr; + channel->reserve_length = channel->reserve_initial; + channel->free_arr = tmp_arr; + channel->reserve_top = channel->free_length; + channel->free_length = channel->reserve_initial; + + channel->stats.reserve_free_swaps_cnt++; + + xge_debug_channel(XGE_TRACE, + "switch on channel %d:%d:%d, reserve_length %d, " + "free_length %d", channel->type, channel->post_qid, + channel->compl_qid, channel->reserve_length, + channel->free_length); + +#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ) + xge_os_spin_unlock_irq(&channel->free_lock, flags); +#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE) + xge_os_spin_unlock(&channel->free_lock); +#endif + + goto _alloc_after_swap; + } + +#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ) + xge_os_spin_unlock_irq(&channel->free_lock, flags); +#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE) + xge_os_spin_unlock(&channel->free_lock); +#endif + + xge_debug_channel(XGE_TRACE, "channel %d:%d:%d is empty!", + channel->type, channel->post_qid, + channel->compl_qid); + + channel->stats.full_cnt++; + + *dtrh = NULL; + return XGE_HAL_INF_OUT_OF_DESCRIPTORS; +} + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_channel_dtr_restore(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + int offset) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + + /* restore a previously allocated dtrh at current offset and update + * the available reserve length accordingly. If dtrh is null just + * update the reserve length, only */ + + if (dtrh) { + channel->reserve_arr[channel->reserve_length + offset] = dtrh; + xge_debug_channel(XGE_TRACE, "dtrh 0x"XGE_OS_LLXFMT" restored for " + "channel %d:%d:%d, offset %d at reserve index %d, ", + (unsigned long long)(ulong_t)dtrh, channel->type, + channel->post_qid, channel->compl_qid, offset, + channel->reserve_length + offset); + } + else { + channel->reserve_length += offset; + xge_debug_channel(XGE_TRACE, "channel %d:%d:%d, restored " + "for offset %d, new reserve_length %d, free length %d", + channel->type, channel->post_qid, channel->compl_qid, + offset, channel->reserve_length, channel->free_length); + } +} + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_channel_dtr_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t*)channelh; + + xge_assert(channel->work_arr[channel->post_index] == NULL); + + channel->work_arr[channel->post_index++] = dtrh; + + /* wrap-around */ + if (channel->post_index == channel->length) + channel->post_index = 0; +} + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_channel_dtr_try_complete(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + + xge_assert(channel->work_arr); + xge_assert(channel->compl_index < channel->length); + + *dtrh = channel->work_arr[channel->compl_index]; +} + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_channel_dtr_complete(xge_hal_channel_h channelh) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + + channel->work_arr[channel->compl_index] = NULL; + + /* wrap-around */ + if (++channel->compl_index == channel->length) + channel->compl_index = 0; + + channel->stats.total_compl_cnt++; +} + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_channel_dtr_free(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + + channel->free_arr[--channel->free_length] = dtrh; + + xge_debug_channel(XGE_TRACE, "dtrh 0x"XGE_OS_LLXFMT" freed, " + "channel %d:%d:%d, new free_length %d", + (unsigned long long)(ulong_t)dtrh, + channel->type, channel->post_qid, + channel->compl_qid, channel->free_length); +} + +/** + * xge_hal_channel_dtr_count + * @channelh: Channel handle. Obtained via xge_hal_channel_open(). + * + * Retreive number of DTRs available. This function can not be called + * from data path. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int +xge_hal_channel_dtr_count(xge_hal_channel_h channelh) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + + return ((channel->reserve_length - channel->reserve_top) + + (channel->reserve_initial - channel->free_length) - + channel->reserve_threshold); +} + +/** + * xge_hal_channel_userdata - Get user-specified channel context. + * @channelh: Channel handle. Obtained via xge_hal_channel_open(). + * + * Returns: per-channel "user data", which can be any ULD-defined context. + * The %userdata "gets" into the channel at open time + * (see xge_hal_channel_open()). + * + * See also: xge_hal_channel_open(). + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void* +xge_hal_channel_userdata(xge_hal_channel_h channelh) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + + return channel->userdata; +} + +/** + * xge_hal_channel_id - Get channel ID. + * @channelh: Channel handle. Obtained via xge_hal_channel_open(). + * + * Returns: channel ID. For link layer channel id is the number + * in the range from 0 to 7 that identifies hardware ring or fifo, + * depending on the channel type. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int +xge_hal_channel_id(xge_hal_channel_h channelh) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + + return channel->post_qid; +} + +/** + * xge_hal_check_alignment - Check buffer alignment and calculate the + * "misaligned" portion. + * @dma_pointer: DMA address of the buffer. + * @size: Buffer size, in bytes. + * @alignment: Alignment "granularity" (see below), in bytes. + * @copy_size: Maximum number of bytes to "extract" from the buffer + * (in order to spost it as a separate scatter-gather entry). See below. + * + * Check buffer alignment and calculate "misaligned" portion, if exists. + * The buffer is considered aligned if its address is multiple of + * the specified @alignment. If this is the case, + * xge_hal_check_alignment() returns zero. + * Otherwise, xge_hal_check_alignment() uses the last argument, + * @copy_size, + * to calculate the size to "extract" from the buffer. The @copy_size + * may or may not be equal @alignment. The difference between these two + * arguments is that the @alignment is used to make the decision: aligned + * or not aligned. While the @copy_size is used to calculate the portion + * of the buffer to "extract", i.e. to post as a separate entry in the + * transmit descriptor. For example, the combination + * @alignment=8 and @copy_size=64 will work okay on AMD Opteron boxes. + * + * Note: @copy_size should be a multiple of @alignment. In many practical + * cases @copy_size and @alignment will probably be equal. + * + * See also: xge_hal_fifo_dtr_buffer_set_aligned(). + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int +xge_hal_check_alignment(dma_addr_t dma_pointer, int size, int alignment, + int copy_size) +{ + int misaligned_size; + + misaligned_size = (int)(dma_pointer & (alignment - 1)); + if (!misaligned_size) { + return 0; + } + + if (size > copy_size) { + misaligned_size = (int)(dma_pointer & (copy_size - 1)); + misaligned_size = copy_size - misaligned_size; + } else { + misaligned_size = size; + } + + return misaligned_size; +} + diff --git a/sys/dev/nxge/xgehal/xgehal-channel.c b/sys/dev/nxge/xgehal/xgehal-channel.c new file mode 100644 index 0000000..dad39f2 --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-channel.c @@ -0,0 +1,759 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-channel.c + * + * Description: chipset channel abstraction + * + * Created: 10 May 2004 + */ + +#include <dev/nxge/include/xgehal-channel.h> +#include <dev/nxge/include/xgehal-fifo.h> +#include <dev/nxge/include/xgehal-ring.h> +#include <dev/nxge/include/xgehal-device.h> +#include <dev/nxge/include/xgehal-regs.h> +#ifdef XGEHAL_RNIC +#include <dev/nxge/include/xgehal-types.h> +#include "xgehal-iov.h" +#endif + +/* + * __hal_channel_dtr_next_reservelist + * + * Walking through the all available DTRs. + */ +static xge_hal_status_e +__hal_channel_dtr_next_reservelist(xge_hal_channel_h channelh, + xge_hal_dtr_h *dtrh) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + + if (channel->reserve_top >= channel->reserve_length) { + return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS; + } + + *dtrh = channel->reserve_arr[channel->reserve_top++]; + + return XGE_HAL_OK; +} + +/* + * __hal_channel_dtr_next_freelist + * + * Walking through the "freed" DTRs. + */ +static xge_hal_status_e +__hal_channel_dtr_next_freelist(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + + if (channel->reserve_initial == channel->free_length) { + return XGE_HAL_INF_NO_MORE_FREED_DESCRIPTORS; + } + + *dtrh = channel->free_arr[channel->free_length++]; + + return XGE_HAL_OK; +} + +/* + * __hal_channel_dtr_next_not_completed - Get the _next_ posted but + * not completed descriptor. + * + * Walking through the "not completed" DTRs. + */ +static xge_hal_status_e +__hal_channel_dtr_next_not_completed(xge_hal_channel_h channelh, + xge_hal_dtr_h *dtrh) +{ +#ifndef XGEHAL_RNIC + xge_hal_ring_rxd_1_t *rxdp; /* doesn't matter 1, 3 or 5... */ +#endif + + __hal_channel_dtr_try_complete(channelh, dtrh); + if (*dtrh == NULL) { + return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS; + } + +#ifndef XGEHAL_RNIC + rxdp = (xge_hal_ring_rxd_1_t *)*dtrh; + xge_assert(rxdp->host_control!=0); +#endif + + __hal_channel_dtr_complete(channelh); + + return XGE_HAL_OK; +} + +xge_hal_channel_t* +__hal_channel_allocate(xge_hal_device_h devh, int post_qid, +#ifdef XGEHAL_RNIC + u32 vp_id, +#endif + xge_hal_channel_type_e type) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_channel_t *channel; + int size = 0; + + switch(type) { + case XGE_HAL_CHANNEL_TYPE_FIFO: + xge_assert(post_qid + 1 >= XGE_HAL_MIN_FIFO_NUM && + post_qid + 1 <= XGE_HAL_MAX_FIFO_NUM); + size = sizeof(xge_hal_fifo_t); + break; + case XGE_HAL_CHANNEL_TYPE_RING: + xge_assert(post_qid + 1 >= XGE_HAL_MIN_RING_NUM && + post_qid + 1 <= XGE_HAL_MAX_RING_NUM); + size = sizeof(xge_hal_ring_t); + break; +#ifdef XGEHAL_RNIC + case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: + size = sizeof(__hal_sq_t); + break; + case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: + size = sizeof(__hal_srq_t); + break; + case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: + size = sizeof(__hal_cqrq_t); + break; + case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: + size = sizeof(__hal_umq_t); + break; + case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: + size = sizeof(__hal_dmq_t); + break; +#endif + default : + xge_assert(size); + break; + + } + + + /* allocate FIFO channel */ + channel = (xge_hal_channel_t *) xge_os_malloc(hldev->pdev, size); + if (channel == NULL) { + return NULL; + } + xge_os_memzero(channel, size); + + channel->pdev = hldev->pdev; + channel->regh0 = hldev->regh0; + channel->regh1 = hldev->regh1; + channel->type = type; + channel->devh = devh; +#ifdef XGEHAL_RNIC + channel->vp_id = vp_id; +#endif + channel->post_qid = post_qid; + channel->compl_qid = 0; + + return channel; +} + +void __hal_channel_free(xge_hal_channel_t *channel) +{ + int size = 0; + + xge_assert(channel->pdev); + + switch(channel->type) { + case XGE_HAL_CHANNEL_TYPE_FIFO: + size = sizeof(xge_hal_fifo_t); + break; + case XGE_HAL_CHANNEL_TYPE_RING: + size = sizeof(xge_hal_ring_t); + break; +#ifdef XGEHAL_RNIC + case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: + size = sizeof(__hal_sq_t); + break; + case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: + size = sizeof(__hal_srq_t); + break; + case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: + size = sizeof(__hal_cqrq_t); + break; + case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: + size = sizeof(__hal_umq_t); + break; + case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: + size = sizeof(__hal_dmq_t); + break; +#else + case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: + case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: + case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: + case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: + case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: + xge_assert(size); + break; +#endif + default: + break; + } + + xge_os_free(channel->pdev, channel, size); +} + +xge_hal_status_e +__hal_channel_initialize (xge_hal_channel_h channelh, + xge_hal_channel_attr_t *attr, void **reserve_arr, + int reserve_initial, int reserve_max, int reserve_threshold) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + xge_hal_device_t *hldev; + + hldev = (xge_hal_device_t *)channel->devh; + + channel->dtr_term = attr->dtr_term; + channel->dtr_init = attr->dtr_init; + channel->callback = attr->callback; + channel->userdata = attr->userdata; + channel->flags = attr->flags; + channel->per_dtr_space = attr->per_dtr_space; + + channel->reserve_arr = reserve_arr; + channel->reserve_initial = reserve_initial; + channel->reserve_max = reserve_max; + channel->reserve_length = channel->reserve_initial; + channel->reserve_threshold = reserve_threshold; + channel->reserve_top = 0; + channel->saved_arr = (void **) xge_os_malloc(hldev->pdev, + sizeof(void*)*channel->reserve_max); + if (channel->saved_arr == NULL) { + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + xge_os_memzero(channel->saved_arr, sizeof(void*)*channel->reserve_max); + channel->free_arr = channel->saved_arr; + channel->free_length = channel->reserve_initial; + channel->work_arr = (void **) xge_os_malloc(hldev->pdev, + sizeof(void*)*channel->reserve_max); + if (channel->work_arr == NULL) { + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + xge_os_memzero(channel->work_arr, + sizeof(void*)*channel->reserve_max); + channel->post_index = 0; + channel->compl_index = 0; + channel->length = channel->reserve_initial; + + channel->orig_arr = (void **) xge_os_malloc(hldev->pdev, + sizeof(void*)*channel->reserve_max); + if (channel->orig_arr == NULL) + return XGE_HAL_ERR_OUT_OF_MEMORY; + + xge_os_memzero(channel->orig_arr, sizeof(void*)*channel->reserve_max); + +#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ) + xge_os_spin_lock_init_irq(&channel->free_lock, hldev->irqh); +#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE) + xge_os_spin_lock_init(&channel->free_lock, hldev->pdev); +#endif + + return XGE_HAL_OK; +} + +void __hal_channel_terminate(xge_hal_channel_h channelh) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + xge_hal_device_t *hldev; + + hldev = (xge_hal_device_t *)channel->devh; + + xge_assert(channel->pdev); + /* undo changes made at channel_initialize() */ + if (channel->work_arr) { + xge_os_free(channel->pdev, channel->work_arr, + sizeof(void*)*channel->reserve_max); + channel->work_arr = NULL; + } + + if (channel->saved_arr) { + xge_os_free(channel->pdev, channel->saved_arr, + sizeof(void*)*channel->reserve_max); + channel->saved_arr = NULL; + } + + if (channel->orig_arr) { + xge_os_free(channel->pdev, channel->orig_arr, + sizeof(void*)*channel->reserve_max); + channel->orig_arr = NULL; + } + +#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ) + xge_os_spin_lock_destroy_irq(&channel->free_lock, hldev->irqh); +#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE) + xge_os_spin_lock_destroy(&channel->free_lock, hldev->pdev); +#endif +} + +/** + * xge_hal_channel_open - Open communication channel. + * @devh: HAL device, pointer to xge_hal_device_t structure. + * @attr: Contains attributes required to open + * the channel. + * @channelh: The channel handle. On success (XGE_HAL_OK) HAL fills + * this "out" parameter with a valid channel handle. + * @reopen: See xge_hal_channel_reopen_e{}. + * + * Open communication channel with the device. + * + * HAL uses (persistent) channel configuration to allocate both channel + * and Xframe Tx and Rx descriptors. + * Notes: + * 1) The channel config data is fed into HAL prior to + * xge_hal_channel_open(). + * + * 2) The corresponding hardware queues must be already configured and + * enabled. + * + * 3) Either down or up queue may be omitted, in which case the channel + * is treated as _unidirectional_. + * + * 4) Post and completion queue may be the same, in which case the channel + * is said to have "in-band completions". + * + * Note that free_channels list is not protected. i.e. caller must provide + * safe context. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_CHANNEL_NOT_FOUND - Unable to locate the channel. + * XGE_HAL_ERR_OUT_OF_MEMORY - Memory allocation failed. + * + * See also: xge_hal_channel_attr_t{}. + * Usage: See ex_open{}. + */ +xge_hal_status_e +xge_hal_channel_open(xge_hal_device_h devh, + xge_hal_channel_attr_t *attr, + xge_hal_channel_h *channelh, + xge_hal_channel_reopen_e reopen) +{ + xge_list_t *item; + int i; + xge_hal_status_e status = XGE_HAL_OK; + xge_hal_channel_t *channel = NULL; + xge_hal_device_t *device = (xge_hal_device_t *)devh; + + xge_assert(device); + xge_assert(attr); + + *channelh = NULL; + +#ifdef XGEHAL_RNIC + if((attr->type == XGE_HAL_CHANNEL_TYPE_FIFO) || + (attr->type == XGE_HAL_CHANNEL_TYPE_RING)) { +#endif + /* find channel */ + xge_list_for_each(item, &device->free_channels) { + xge_hal_channel_t *tmp; + + tmp = xge_container_of(item, xge_hal_channel_t, item); + if (tmp->type == attr->type && + tmp->post_qid == attr->post_qid && + tmp->compl_qid == attr->compl_qid) { + channel = tmp; + break; + } + } + + if (channel == NULL) { + return XGE_HAL_ERR_CHANNEL_NOT_FOUND; + } + +#ifdef XGEHAL_RNIC + } + else { + channel = __hal_channel_allocate(devh, attr->post_qid, +#ifdef XGEHAL_RNIC + attr->vp_id, +#endif + attr->type); + if (channel == NULL) { + xge_debug_device(XGE_ERR, + "__hal_channel_allocate failed"); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + } +#endif + +#ifndef XGEHAL_RNIC + xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) || + (channel->type == XGE_HAL_CHANNEL_TYPE_RING)); +#endif + +#ifdef XGEHAL_RNIC + if((reopen == XGE_HAL_CHANNEL_OC_NORMAL) || + ((channel->type != XGE_HAL_CHANNEL_TYPE_FIFO) && + (channel->type != XGE_HAL_CHANNEL_TYPE_RING))) { +#else + if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) { +#endif + /* allocate memory, initialize pointers, etc */ + switch(channel->type) { + case XGE_HAL_CHANNEL_TYPE_FIFO: + status = __hal_fifo_open(channel, attr); + break; + case XGE_HAL_CHANNEL_TYPE_RING: + status = __hal_ring_open(channel, attr); + break; +#ifdef XGEHAL_RNIC + case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: + status = __hal_sq_open(channel, attr); + break; + case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: + status = __hal_srq_open(channel, attr); + break; + case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: + status = __hal_cqrq_open(channel, attr); + break; + case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: + status = __hal_umq_open(channel, attr); + break; + case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: + status = __hal_dmq_open(channel, attr); + break; +#else + case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: + case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: + case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: + case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: + case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: + status = XGE_HAL_FAIL; + break; +#endif + default: + break; + } + + if (status == XGE_HAL_OK) { + for (i = 0; i < channel->reserve_initial; i++) { + channel->orig_arr[i] = + channel->reserve_arr[i]; + } + } + else + return status; + } else { + xge_assert(reopen == XGE_HAL_CHANNEL_RESET_ONLY); + + for (i = 0; i < channel->reserve_initial; i++) { + channel->reserve_arr[i] = channel->orig_arr[i]; + channel->free_arr[i] = NULL; + } + channel->free_length = channel->reserve_initial; + channel->reserve_length = channel->reserve_initial; + channel->reserve_top = 0; + channel->post_index = 0; + channel->compl_index = 0; + if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { + status = __hal_ring_initial_replenish(channel, + reopen); + if (status != XGE_HAL_OK) + return status; + } + } + + /* move channel to the open state list */ + + switch(channel->type) { + case XGE_HAL_CHANNEL_TYPE_FIFO: + xge_list_remove(&channel->item); + xge_list_insert(&channel->item, &device->fifo_channels); + break; + case XGE_HAL_CHANNEL_TYPE_RING: + xge_list_remove(&channel->item); + xge_list_insert(&channel->item, &device->ring_channels); + break; +#ifdef XGEHAL_RNIC + case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: + xge_list_insert(&channel->item, + &device->virtual_paths[attr->vp_id].sq_channels); + device->virtual_paths[attr->vp_id].stats.no_sqs++; + break; + case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: + xge_list_insert(&channel->item, + &device->virtual_paths[attr->vp_id].srq_channels); + device->virtual_paths[attr->vp_id].stats.no_srqs++; + break; + case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: + xge_list_insert(&channel->item, + &device->virtual_paths[attr->vp_id].cqrq_channels); + device->virtual_paths[attr->vp_id].stats.no_cqrqs++; + break; + case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: + xge_list_init(&channel->item); + device->virtual_paths[attr->vp_id].umq_channelh = channel; + break; + case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: + xge_list_init(&channel->item); + device->virtual_paths[attr->vp_id].dmq_channelh = channel; + break; +#else + case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: + case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: + case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: + case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: + case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: + xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO || + channel->type == XGE_HAL_CHANNEL_TYPE_RING); + break; +#endif + default: + break; + } + channel->is_open = 1; + /* + * The magic check the argument validity, has to be + * removed before 03/01/2005. + */ + channel->magic = XGE_HAL_MAGIC; + + *channelh = channel; + + return XGE_HAL_OK; +} + +/** + * xge_hal_channel_abort - Abort the channel. + * @channelh: Channel handle. + * @reopen: See xge_hal_channel_reopen_e{}. + * + * Terminate (via xge_hal_channel_dtr_term_f{}) all channel descriptors. + * Currently used internally only by HAL, as part of its + * xge_hal_channel_close() and xge_hal_channel_open() in case + * of fatal error. + * + * See also: xge_hal_channel_dtr_term_f{}. + */ +void xge_hal_channel_abort(xge_hal_channel_h channelh, + xge_hal_channel_reopen_e reopen) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + xge_hal_dtr_h dtr; +#ifdef XGE_OS_MEMORY_CHECK + int check_cnt = 0; +#endif + int free_length_sav; + int reserve_top_sav; + + if (channel->dtr_term == NULL) { + return; + } + + free_length_sav = channel->free_length; + while (__hal_channel_dtr_next_freelist(channelh, &dtr) == XGE_HAL_OK) { +#ifdef XGE_OS_MEMORY_CHECK +#ifdef XGE_DEBUG_ASSERT + if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { + xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated); + } else { + if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { + xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated); + } + } +#endif + check_cnt++; +#endif + channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_FREED, + channel->userdata, reopen); + } + channel->free_length = free_length_sav; + + while (__hal_channel_dtr_next_not_completed(channelh, &dtr) == + XGE_HAL_OK) { +#ifdef XGE_OS_MEMORY_CHECK +#ifdef XGE_DEBUG_ASSERT + if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { + xge_assert(__hal_fifo_txdl_priv(dtr)->allocated); + } else { + if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { + xge_assert(__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr) + ->allocated); + } + } +#endif + check_cnt++; +#endif + channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_POSTED, + channel->userdata, reopen); + + } + + reserve_top_sav = channel->reserve_top; + while (__hal_channel_dtr_next_reservelist(channelh, &dtr) == + XGE_HAL_OK) { +#ifdef XGE_OS_MEMORY_CHECK +#ifdef XGE_DEBUG_ASSERT + if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { + xge_assert(!__hal_fifo_txdl_priv(dtr)->allocated); + } else { + if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { + xge_assert(!__hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtr)->allocated); + } + } +#endif + check_cnt++; +#endif + channel->dtr_term(channel, dtr, XGE_HAL_DTR_STATE_AVAIL, + channel->userdata, reopen); + } + channel->reserve_top = reserve_top_sav; + + xge_assert(channel->reserve_length == + (channel->free_length + channel->reserve_top)); + +#ifdef XGE_OS_MEMORY_CHECK + xge_assert(check_cnt == channel->reserve_initial); +#endif + +} + +/** + * xge_hal_channel_close - Close communication channel. + * @channelh: The channel handle. + * @reopen: See xge_hal_channel_reopen_e{}. + * + * Will close previously opened channel and deallocate associated resources. + * Channel must be opened otherwise assert will be generated. + * Note that free_channels list is not protected. i.e. caller must provide + * safe context. + */ +void xge_hal_channel_close(xge_hal_channel_h channelh, + xge_hal_channel_reopen_e reopen) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + xge_hal_device_t *hldev; + xge_list_t *item; +#ifdef XGEHAL_RNIC + u32 vp_id; +#endif + xge_assert(channel); + xge_assert(channel->type < XGE_HAL_CHANNEL_TYPE_MAX); + + hldev = (xge_hal_device_t *)channel->devh; + channel->is_open = 0; + channel->magic = XGE_HAL_DEAD; + +#ifdef XGEHAL_RNIC + vp_id = channel->vp_id; + + if((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) || + (channel->type == XGE_HAL_CHANNEL_TYPE_RING)) { +#endif + /* sanity check: make sure channel is not in free list */ + xge_list_for_each(item, &hldev->free_channels) { + xge_hal_channel_t *tmp; + + tmp = xge_container_of(item, xge_hal_channel_t, item); + xge_assert(!tmp->is_open); + if (channel == tmp) { + return; + } + } +#ifdef XGEHAL_RNIC + } +#endif + + xge_hal_channel_abort(channel, reopen); + +#ifndef XGEHAL_RNIC + xge_assert((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) || + (channel->type == XGE_HAL_CHANNEL_TYPE_RING)); +#endif + + if (reopen == XGE_HAL_CHANNEL_OC_NORMAL) { + /* de-allocate */ + switch(channel->type) { + case XGE_HAL_CHANNEL_TYPE_FIFO: + __hal_fifo_close(channelh); + break; + case XGE_HAL_CHANNEL_TYPE_RING: + __hal_ring_close(channelh); + break; +#ifdef XGEHAL_RNIC + case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: + __hal_sq_close(channelh); + hldev->virtual_paths[vp_id].stats.no_sqs--; + break; + case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: + __hal_srq_close(channelh); + hldev->virtual_paths[vp_id].stats.no_srqs--; + break; + case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: + __hal_cqrq_close(channelh); + hldev->virtual_paths[vp_id].stats.no_cqrqs--; + break; + case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: + __hal_umq_close(channelh); + break; + case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: + __hal_dmq_close(channelh); + break; +#else + case XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: + case XGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: + case XGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: + case XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: + case XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: + xge_assert(channel->type == XGE_HAL_CHANNEL_TYPE_FIFO || + channel->type == XGE_HAL_CHANNEL_TYPE_RING); + break; +#endif + default: + break; + } + } + else + xge_assert(reopen == XGE_HAL_CHANNEL_RESET_ONLY); + + /* move channel back to free state list */ + xge_list_remove(&channel->item); +#ifdef XGEHAL_RNIC + if((channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) || + (channel->type == XGE_HAL_CHANNEL_TYPE_RING)) { +#endif + xge_list_insert(&channel->item, &hldev->free_channels); + + if (xge_list_is_empty(&hldev->fifo_channels) && + xge_list_is_empty(&hldev->ring_channels)) { + /* clear msix_idx in case of following HW reset */ + hldev->reset_needed_after_close = 1; + } +#ifdef XGEHAL_RNIC + } + else { + __hal_channel_free(channel); + } +#endif + +} diff --git a/sys/dev/nxge/xgehal/xgehal-config.c b/sys/dev/nxge/xgehal/xgehal-config.c new file mode 100644 index 0000000..45a82e9 --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-config.c @@ -0,0 +1,761 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-config.c + * + * Description: configuration functionality + * + * Created: 14 May 2004 + */ + +#include <dev/nxge/include/xgehal-config.h> +#include <dev/nxge/include/xge-debug.h> + +/* + * __hal_tti_config_check - Check tti configuration + * @new_config: tti configuration information + * + * Returns: XGE_HAL_OK - success, + * otherwise one of the xge_hal_status_e{} enumerated error codes. + */ +static xge_hal_status_e +__hal_tti_config_check (xge_hal_tti_config_t *new_config) +{ + if ((new_config->urange_a < XGE_HAL_MIN_TX_URANGE_A) || + (new_config->urange_a > XGE_HAL_MAX_TX_URANGE_A)) { + return XGE_HAL_BADCFG_TX_URANGE_A; + } + + if ((new_config->ufc_a < XGE_HAL_MIN_TX_UFC_A) || + (new_config->ufc_a > XGE_HAL_MAX_TX_UFC_A)) { + return XGE_HAL_BADCFG_TX_UFC_A; + } + + if ((new_config->urange_b < XGE_HAL_MIN_TX_URANGE_B) || + (new_config->urange_b > XGE_HAL_MAX_TX_URANGE_B)) { + return XGE_HAL_BADCFG_TX_URANGE_B; + } + + if ((new_config->ufc_b < XGE_HAL_MIN_TX_UFC_B) || + (new_config->ufc_b > XGE_HAL_MAX_TX_UFC_B)) { + return XGE_HAL_BADCFG_TX_UFC_B; + } + + if ((new_config->urange_c < XGE_HAL_MIN_TX_URANGE_C) || + (new_config->urange_c > XGE_HAL_MAX_TX_URANGE_C)) { + return XGE_HAL_BADCFG_TX_URANGE_C; + } + + if ((new_config->ufc_c < XGE_HAL_MIN_TX_UFC_C) || + (new_config->ufc_c > XGE_HAL_MAX_TX_UFC_C)) { + return XGE_HAL_BADCFG_TX_UFC_C; + } + + if ((new_config->ufc_d < XGE_HAL_MIN_TX_UFC_D) || + (new_config->ufc_d > XGE_HAL_MAX_TX_UFC_D)) { + return XGE_HAL_BADCFG_TX_UFC_D; + } + + if ((new_config->timer_val_us < XGE_HAL_MIN_TX_TIMER_VAL) || + (new_config->timer_val_us > XGE_HAL_MAX_TX_TIMER_VAL)) { + return XGE_HAL_BADCFG_TX_TIMER_VAL; + } + + if ((new_config->timer_ci_en < XGE_HAL_MIN_TX_TIMER_CI_EN) || + (new_config->timer_ci_en > XGE_HAL_MAX_TX_TIMER_CI_EN)) { + return XGE_HAL_BADCFG_TX_TIMER_CI_EN; + } + + if ((new_config->timer_ac_en < XGE_HAL_MIN_TX_TIMER_AC_EN) || + (new_config->timer_ac_en > XGE_HAL_MAX_TX_TIMER_AC_EN)) { + return XGE_HAL_BADCFG_TX_TIMER_AC_EN; + } + + return XGE_HAL_OK; +} + +/* + * __hal_rti_config_check - Check rti configuration + * @new_config: rti configuration information + * + * Returns: XGE_HAL_OK - success, + * otherwise one of the xge_hal_status_e{} enumerated error codes. + */ +static xge_hal_status_e +__hal_rti_config_check (xge_hal_rti_config_t *new_config) +{ + if ((new_config->urange_a < XGE_HAL_MIN_RX_URANGE_A) || + (new_config->urange_a > XGE_HAL_MAX_RX_URANGE_A)) { + return XGE_HAL_BADCFG_RX_URANGE_A; + } + + if ((new_config->ufc_a < XGE_HAL_MIN_RX_UFC_A) || + (new_config->ufc_a > XGE_HAL_MAX_RX_UFC_A)) { + return XGE_HAL_BADCFG_RX_UFC_A; + } + + if ((new_config->urange_b < XGE_HAL_MIN_RX_URANGE_B) || + (new_config->urange_b > XGE_HAL_MAX_RX_URANGE_B)) { + return XGE_HAL_BADCFG_RX_URANGE_B; + } + + if ((new_config->ufc_b < XGE_HAL_MIN_RX_UFC_B) || + (new_config->ufc_b > XGE_HAL_MAX_RX_UFC_B)) { + return XGE_HAL_BADCFG_RX_UFC_B; + } + + if ((new_config->urange_c < XGE_HAL_MIN_RX_URANGE_C) || + (new_config->urange_c > XGE_HAL_MAX_RX_URANGE_C)) { + return XGE_HAL_BADCFG_RX_URANGE_C; + } + + if ((new_config->ufc_c < XGE_HAL_MIN_RX_UFC_C) || + (new_config->ufc_c > XGE_HAL_MAX_RX_UFC_C)) { + return XGE_HAL_BADCFG_RX_UFC_C; + } + + if ((new_config->ufc_d < XGE_HAL_MIN_RX_UFC_D) || + (new_config->ufc_d > XGE_HAL_MAX_RX_UFC_D)) { + return XGE_HAL_BADCFG_RX_UFC_D; + } + + if ((new_config->timer_val_us < XGE_HAL_MIN_RX_TIMER_VAL) || + (new_config->timer_val_us > XGE_HAL_MAX_RX_TIMER_VAL)) { + return XGE_HAL_BADCFG_RX_TIMER_VAL; + } + + if ((new_config->timer_ac_en < XGE_HAL_MIN_RX_TIMER_AC_EN) || + (new_config->timer_ac_en > XGE_HAL_MAX_RX_TIMER_AC_EN)) { + return XGE_HAL_BADCFG_RX_TIMER_AC_EN; + } + + return XGE_HAL_OK; +} + + +/* + * __hal_fifo_queue_check - Check fifo queue configuration + * @new_config: fifo queue configuration information + * + * Returns: XGE_HAL_OK - success, + * otherwise one of the xge_hal_status_e{} enumerated error codes. + */ +static xge_hal_status_e +__hal_fifo_queue_check (xge_hal_fifo_config_t *new_config, + xge_hal_fifo_queue_t *new_queue) +{ + int i; + + if ((new_queue->initial < XGE_HAL_MIN_FIFO_QUEUE_LENGTH) || + (new_queue->initial > XGE_HAL_MAX_FIFO_QUEUE_LENGTH)) { + return XGE_HAL_BADCFG_FIFO_QUEUE_INITIAL_LENGTH; + } + + /* FIXME: queue "grow" feature is not supported. + * Use "initial" queue size as the "maximum"; + * Remove the next line when fixed. */ + new_queue->max = new_queue->initial; + + if ((new_queue->max < XGE_HAL_MIN_FIFO_QUEUE_LENGTH) || + (new_queue->max > XGE_HAL_MAX_FIFO_QUEUE_LENGTH)) { + return XGE_HAL_BADCFG_FIFO_QUEUE_MAX_LENGTH; + } + + if (new_queue->max < new_config->reserve_threshold) { + return XGE_HAL_BADCFG_FIFO_RESERVE_THRESHOLD; + } + + if ((new_queue->intr < XGE_HAL_MIN_FIFO_QUEUE_INTR) || + (new_queue->intr > XGE_HAL_MAX_FIFO_QUEUE_INTR)) { + return XGE_HAL_BADCFG_FIFO_QUEUE_INTR; + } + + if ((new_queue->intr_vector < XGE_HAL_MIN_FIFO_QUEUE_INTR_VECTOR) || + (new_queue->intr_vector > XGE_HAL_MAX_FIFO_QUEUE_INTR_VECTOR)) { + return XGE_HAL_BADCFG_FIFO_QUEUE_INTR_VECTOR; + } + + for(i = 0; i < XGE_HAL_MAX_FIFO_TTI_NUM; i++) { + /* + * Validate the tti configuration parameters only if + * the TTI feature is enabled. + */ + if (new_queue->tti[i].enabled) { + xge_hal_status_e status; + + if ((status = __hal_tti_config_check( + &new_queue->tti[i])) != XGE_HAL_OK) { + return status; + } + } + } + + return XGE_HAL_OK; +} + +/* + * __hal_ring_queue_check - Check ring queue configuration + * @new_config: ring queue configuration information + * + * Returns: XGE_HAL_OK - success, + * otherwise one of the xge_hal_status_e{} enumerated error codes. + */ +static xge_hal_status_e +__hal_ring_queue_check (xge_hal_ring_queue_t *new_config) +{ + + if ((new_config->initial < XGE_HAL_MIN_RING_QUEUE_BLOCKS) || + (new_config->initial > XGE_HAL_MAX_RING_QUEUE_BLOCKS)) { + return XGE_HAL_BADCFG_RING_QUEUE_INITIAL_BLOCKS; + } + + /* FIXME: queue "grow" feature is not supported. + * Use "initial" queue size as the "maximum"; + * Remove the next line when fixed. */ + new_config->max = new_config->initial; + + if ((new_config->max < XGE_HAL_MIN_RING_QUEUE_BLOCKS) || + (new_config->max > XGE_HAL_MAX_RING_QUEUE_BLOCKS)) { + return XGE_HAL_BADCFG_RING_QUEUE_MAX_BLOCKS; + } + + if ((new_config->buffer_mode != XGE_HAL_RING_QUEUE_BUFFER_MODE_1) && + (new_config->buffer_mode != XGE_HAL_RING_QUEUE_BUFFER_MODE_3) && + (new_config->buffer_mode != XGE_HAL_RING_QUEUE_BUFFER_MODE_5)) { + return XGE_HAL_BADCFG_RING_QUEUE_BUFFER_MODE; + } + + /* + * Herc has less DRAM; the check is done later inside + * device_initialize() + */ + if (((new_config->dram_size_mb < XGE_HAL_MIN_RING_QUEUE_SIZE) || + (new_config->dram_size_mb > XGE_HAL_MAX_RING_QUEUE_SIZE_XENA)) && + new_config->dram_size_mb != XGE_HAL_DEFAULT_USE_HARDCODE) + return XGE_HAL_BADCFG_RING_QUEUE_SIZE; + + if ((new_config->backoff_interval_us < + XGE_HAL_MIN_BACKOFF_INTERVAL_US) || + (new_config->backoff_interval_us > + XGE_HAL_MAX_BACKOFF_INTERVAL_US)) { + return XGE_HAL_BADCFG_BACKOFF_INTERVAL_US; + } + + if ((new_config->max_frm_len < XGE_HAL_MIN_MAX_FRM_LEN) || + (new_config->max_frm_len > XGE_HAL_MAX_MAX_FRM_LEN)) { + return XGE_HAL_BADCFG_MAX_FRM_LEN; + } + + if ((new_config->priority < XGE_HAL_MIN_RING_PRIORITY) || + (new_config->priority > XGE_HAL_MAX_RING_PRIORITY)) { + return XGE_HAL_BADCFG_RING_PRIORITY; + } + + if ((new_config->rth_en < XGE_HAL_MIN_RING_RTH_EN) || + (new_config->rth_en > XGE_HAL_MAX_RING_RTH_EN)) { + return XGE_HAL_BADCFG_RING_RTH_EN; + } + + if ((new_config->rts_mac_en < XGE_HAL_MIN_RING_RTS_MAC_EN) || + (new_config->rts_mac_en > XGE_HAL_MAX_RING_RTS_MAC_EN)) { + return XGE_HAL_BADCFG_RING_RTS_MAC_EN; + } + + if ((new_config->rts_mac_en < XGE_HAL_MIN_RING_RTS_PORT_EN) || + (new_config->rts_mac_en > XGE_HAL_MAX_RING_RTS_PORT_EN)) { + return XGE_HAL_BADCFG_RING_RTS_PORT_EN; + } + + if ((new_config->intr_vector < XGE_HAL_MIN_RING_QUEUE_INTR_VECTOR) || + (new_config->intr_vector > XGE_HAL_MAX_RING_QUEUE_INTR_VECTOR)) { + return XGE_HAL_BADCFG_RING_QUEUE_INTR_VECTOR; + } + + if (new_config->indicate_max_pkts < + XGE_HAL_MIN_RING_INDICATE_MAX_PKTS || + new_config->indicate_max_pkts > + XGE_HAL_MAX_RING_INDICATE_MAX_PKTS) { + return XGE_HAL_BADCFG_RING_INDICATE_MAX_PKTS; + } + + return __hal_rti_config_check(&new_config->rti); +} + +/* + * __hal_mac_config_check - Check mac configuration + * @new_config: mac configuration information + * + * Returns: XGE_HAL_OK - success, + * otherwise one of the xge_hal_status_e{} enumerated error codes. + */ +static xge_hal_status_e +__hal_mac_config_check (xge_hal_mac_config_t *new_config) +{ + if ((new_config->tmac_util_period < XGE_HAL_MIN_TMAC_UTIL_PERIOD) || + (new_config->tmac_util_period > XGE_HAL_MAX_TMAC_UTIL_PERIOD)) { + return XGE_HAL_BADCFG_TMAC_UTIL_PERIOD; + } + + if ((new_config->rmac_util_period < XGE_HAL_MIN_RMAC_UTIL_PERIOD) || + (new_config->rmac_util_period > XGE_HAL_MAX_RMAC_UTIL_PERIOD)) { + return XGE_HAL_BADCFG_RMAC_UTIL_PERIOD; + } + + if ((new_config->rmac_bcast_en < XGE_HAL_MIN_RMAC_BCAST_EN) || + (new_config->rmac_bcast_en > XGE_HAL_MAX_RMAC_BCAST_EN)) { + return XGE_HAL_BADCFG_RMAC_BCAST_EN; + } + + if ((new_config->rmac_pause_gen_en < XGE_HAL_MIN_RMAC_PAUSE_GEN_EN) || + (new_config->rmac_pause_gen_en>XGE_HAL_MAX_RMAC_PAUSE_GEN_EN)) { + return XGE_HAL_BADCFG_RMAC_PAUSE_GEN_EN; + } + + if ((new_config->rmac_pause_rcv_en < XGE_HAL_MIN_RMAC_PAUSE_RCV_EN) || + (new_config->rmac_pause_rcv_en>XGE_HAL_MAX_RMAC_PAUSE_RCV_EN)) { + return XGE_HAL_BADCFG_RMAC_PAUSE_RCV_EN; + } + + if ((new_config->rmac_pause_time < XGE_HAL_MIN_RMAC_HIGH_PTIME) || + (new_config->rmac_pause_time > XGE_HAL_MAX_RMAC_HIGH_PTIME)) { + return XGE_HAL_BADCFG_RMAC_HIGH_PTIME; + } + + if ((new_config->media < XGE_HAL_MIN_MEDIA) || + (new_config->media > XGE_HAL_MAX_MEDIA)) { + return XGE_HAL_BADCFG_MEDIA; + } + + if ((new_config->mc_pause_threshold_q0q3 < + XGE_HAL_MIN_MC_PAUSE_THRESHOLD_Q0Q3) || + (new_config->mc_pause_threshold_q0q3 > + XGE_HAL_MAX_MC_PAUSE_THRESHOLD_Q0Q3)) { + return XGE_HAL_BADCFG_MC_PAUSE_THRESHOLD_Q0Q3; + } + + if ((new_config->mc_pause_threshold_q4q7 < + XGE_HAL_MIN_MC_PAUSE_THRESHOLD_Q4Q7) || + (new_config->mc_pause_threshold_q4q7 > + XGE_HAL_MAX_MC_PAUSE_THRESHOLD_Q4Q7)) { + return XGE_HAL_BADCFG_MC_PAUSE_THRESHOLD_Q4Q7; + } + + return XGE_HAL_OK; +} + +/* + * __hal_fifo_config_check - Check fifo configuration + * @new_config: fifo configuration information + * + * Returns: XGE_HAL_OK - success, + * otherwise one of the xge_hal_status_e{} enumerated error codes. + */ +static xge_hal_status_e +__hal_fifo_config_check (xge_hal_fifo_config_t *new_config) +{ + int i; + int total_fifo_length = 0; + + /* + * recompute max_frags to be multiple of 4, + * which means, multiple of 128 for TxDL + */ + new_config->max_frags = ((new_config->max_frags + 3) >> 2) << 2; + + if ((new_config->max_frags < XGE_HAL_MIN_FIFO_FRAGS) || + (new_config->max_frags > XGE_HAL_MAX_FIFO_FRAGS)) { + return XGE_HAL_BADCFG_FIFO_FRAGS; + } + + if ((new_config->reserve_threshold < + XGE_HAL_MIN_FIFO_RESERVE_THRESHOLD) || + (new_config->reserve_threshold > + XGE_HAL_MAX_FIFO_RESERVE_THRESHOLD)) { + return XGE_HAL_BADCFG_FIFO_RESERVE_THRESHOLD; + } + + if ((new_config->memblock_size < XGE_HAL_MIN_FIFO_MEMBLOCK_SIZE) || + (new_config->memblock_size > XGE_HAL_MAX_FIFO_MEMBLOCK_SIZE)) { + return XGE_HAL_BADCFG_FIFO_MEMBLOCK_SIZE; + } + + for(i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) { + xge_hal_status_e status; + + if (!new_config->queue[i].configured) + continue; + + if ((status = __hal_fifo_queue_check(new_config, + &new_config->queue[i])) != XGE_HAL_OK) { + return status; + } + + total_fifo_length += new_config->queue[i].max; + } + + if(total_fifo_length > XGE_HAL_MAX_FIFO_QUEUE_LENGTH){ + return XGE_HAL_BADCFG_FIFO_QUEUE_MAX_LENGTH; + } + + return XGE_HAL_OK; +} + +/* + * __hal_ring_config_check - Check ring configuration + * @new_config: Ring configuration information + * + * Returns: XGE_HAL_OK - success, + * otherwise one of the xge_hal_status_e{} enumerated error codes. + */ +static xge_hal_status_e +__hal_ring_config_check (xge_hal_ring_config_t *new_config) +{ + int i; + + if ((new_config->memblock_size < XGE_HAL_MIN_RING_MEMBLOCK_SIZE) || + (new_config->memblock_size > XGE_HAL_MAX_RING_MEMBLOCK_SIZE)) { + return XGE_HAL_BADCFG_RING_MEMBLOCK_SIZE; + } + + for(i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { + xge_hal_status_e status; + + if (!new_config->queue[i].configured) + continue; + + if ((status = __hal_ring_queue_check(&new_config->queue[i])) + != XGE_HAL_OK) { + return status; + } + } + + return XGE_HAL_OK; +} + + +/* + * __hal_device_config_check_common - Check device configuration. + * @new_config: Device configuration information + * + * Check part of configuration that is common to + * Xframe-I and Xframe-II. + * + * Returns: XGE_HAL_OK - success, + * otherwise one of the xge_hal_status_e{} enumerated error codes. + * + * See also: __hal_device_config_check_xena(). + */ +xge_hal_status_e +__hal_device_config_check_common (xge_hal_device_config_t *new_config) +{ + xge_hal_status_e status; + + if ((new_config->mtu < XGE_HAL_MIN_MTU) || + (new_config->mtu > XGE_HAL_MAX_MTU)) { + return XGE_HAL_BADCFG_MAX_MTU; + } + + if ((new_config->bimodal_interrupts < XGE_HAL_BIMODAL_INTR_MIN) || + (new_config->bimodal_interrupts > XGE_HAL_BIMODAL_INTR_MAX)) { + return XGE_HAL_BADCFG_BIMODAL_INTR; + } + + if (new_config->bimodal_interrupts && + ((new_config->bimodal_timer_lo_us < XGE_HAL_BIMODAL_TIMER_LO_US_MIN) || + (new_config->bimodal_timer_lo_us > XGE_HAL_BIMODAL_TIMER_LO_US_MAX))) { + return XGE_HAL_BADCFG_BIMODAL_TIMER_LO_US; + } + + if (new_config->bimodal_interrupts && + ((new_config->bimodal_timer_hi_us < XGE_HAL_BIMODAL_TIMER_HI_US_MIN) || + (new_config->bimodal_timer_hi_us > XGE_HAL_BIMODAL_TIMER_HI_US_MAX))) { + return XGE_HAL_BADCFG_BIMODAL_TIMER_HI_US; + } + + if ((new_config->no_isr_events < XGE_HAL_NO_ISR_EVENTS_MIN) || + (new_config->no_isr_events > XGE_HAL_NO_ISR_EVENTS_MAX)) { + return XGE_HAL_BADCFG_NO_ISR_EVENTS; + } + + if ((new_config->isr_polling_cnt < XGE_HAL_MIN_ISR_POLLING_CNT) || + (new_config->isr_polling_cnt > XGE_HAL_MAX_ISR_POLLING_CNT)) { + return XGE_HAL_BADCFG_ISR_POLLING_CNT; + } + + if (new_config->latency_timer && + new_config->latency_timer != XGE_HAL_USE_BIOS_DEFAULT_LATENCY) { + if ((new_config->latency_timer < XGE_HAL_MIN_LATENCY_TIMER) || + (new_config->latency_timer > XGE_HAL_MAX_LATENCY_TIMER)) { + return XGE_HAL_BADCFG_LATENCY_TIMER; + } + } + + if (new_config->max_splits_trans != XGE_HAL_USE_BIOS_DEFAULT_SPLITS) { + if ((new_config->max_splits_trans < + XGE_HAL_ONE_SPLIT_TRANSACTION) || + (new_config->max_splits_trans > + XGE_HAL_THIRTYTWO_SPLIT_TRANSACTION)) + return XGE_HAL_BADCFG_MAX_SPLITS_TRANS; + } + + if (new_config->mmrb_count != XGE_HAL_DEFAULT_BIOS_MMRB_COUNT) + { + if ((new_config->mmrb_count < XGE_HAL_MIN_MMRB_COUNT) || + (new_config->mmrb_count > XGE_HAL_MAX_MMRB_COUNT)) { + return XGE_HAL_BADCFG_MMRB_COUNT; + } + } + + if ((new_config->shared_splits < XGE_HAL_MIN_SHARED_SPLITS) || + (new_config->shared_splits > XGE_HAL_MAX_SHARED_SPLITS)) { + return XGE_HAL_BADCFG_SHARED_SPLITS; + } + + if (new_config->stats_refresh_time_sec != + XGE_HAL_STATS_REFRESH_DISABLE) { + if ((new_config->stats_refresh_time_sec < + XGE_HAL_MIN_STATS_REFRESH_TIME) || + (new_config->stats_refresh_time_sec > + XGE_HAL_MAX_STATS_REFRESH_TIME)) { + return XGE_HAL_BADCFG_STATS_REFRESH_TIME; + } + } + + if ((new_config->intr_mode != XGE_HAL_INTR_MODE_IRQLINE) && + (new_config->intr_mode != XGE_HAL_INTR_MODE_MSI) && + (new_config->intr_mode != XGE_HAL_INTR_MODE_MSIX)) { + return XGE_HAL_BADCFG_INTR_MODE; + } + + if ((new_config->sched_timer_us < XGE_HAL_SCHED_TIMER_MIN) || + (new_config->sched_timer_us > XGE_HAL_SCHED_TIMER_MAX)) { + return XGE_HAL_BADCFG_SCHED_TIMER_US; + } + + if ((new_config->sched_timer_one_shot != + XGE_HAL_SCHED_TIMER_ON_SHOT_DISABLE) && + (new_config->sched_timer_one_shot != + XGE_HAL_SCHED_TIMER_ON_SHOT_ENABLE)) { + return XGE_HAL_BADCFG_SCHED_TIMER_ON_SHOT; + } + + /* + * Check adaptive schema parameters. Note that there are two + * configuration variables needs to be enabled in ULD: + * + * a) sched_timer_us should not be zero; + * b) rxufca_hi_lim should not be equal to rxufca_lo_lim. + * + * The code bellow checking for those conditions. + */ + if (new_config->sched_timer_us && + new_config->rxufca_hi_lim != new_config->rxufca_lo_lim) { + if ((new_config->rxufca_intr_thres < + XGE_HAL_RXUFCA_INTR_THRES_MIN) || + (new_config->rxufca_intr_thres > + XGE_HAL_RXUFCA_INTR_THRES_MAX)) { + return XGE_HAL_BADCFG_RXUFCA_INTR_THRES; + } + + if ((new_config->rxufca_hi_lim < XGE_HAL_RXUFCA_HI_LIM_MIN) || + (new_config->rxufca_hi_lim > XGE_HAL_RXUFCA_HI_LIM_MAX)) { + return XGE_HAL_BADCFG_RXUFCA_HI_LIM; + } + + if ((new_config->rxufca_lo_lim < XGE_HAL_RXUFCA_LO_LIM_MIN) || + (new_config->rxufca_lo_lim > XGE_HAL_RXUFCA_LO_LIM_MAX) || + (new_config->rxufca_lo_lim > new_config->rxufca_hi_lim)) { + return XGE_HAL_BADCFG_RXUFCA_LO_LIM; + } + + if ((new_config->rxufca_lbolt_period < + XGE_HAL_RXUFCA_LBOLT_PERIOD_MIN) || + (new_config->rxufca_lbolt_period > + XGE_HAL_RXUFCA_LBOLT_PERIOD_MAX)) { + return XGE_HAL_BADCFG_RXUFCA_LBOLT_PERIOD; + } + } + + if ((new_config->link_valid_cnt < XGE_HAL_LINK_VALID_CNT_MIN) || + (new_config->link_valid_cnt > XGE_HAL_LINK_VALID_CNT_MAX)) { + return XGE_HAL_BADCFG_LINK_VALID_CNT; + } + + if ((new_config->link_retry_cnt < XGE_HAL_LINK_RETRY_CNT_MIN) || + (new_config->link_retry_cnt > XGE_HAL_LINK_RETRY_CNT_MAX)) { + return XGE_HAL_BADCFG_LINK_RETRY_CNT; + } + + if (new_config->link_valid_cnt > new_config->link_retry_cnt) + return XGE_HAL_BADCFG_LINK_VALID_CNT; + + if (new_config->link_stability_period != XGE_HAL_DEFAULT_USE_HARDCODE) { + if ((new_config->link_stability_period < + XGE_HAL_MIN_LINK_STABILITY_PERIOD) || + (new_config->link_stability_period > + XGE_HAL_MAX_LINK_STABILITY_PERIOD)) { + return XGE_HAL_BADCFG_LINK_STABILITY_PERIOD; + } + } + + if (new_config->device_poll_millis != + XGE_HAL_DEFAULT_USE_HARDCODE) { + if ((new_config->device_poll_millis < + XGE_HAL_MIN_DEVICE_POLL_MILLIS) || + (new_config->device_poll_millis > + XGE_HAL_MAX_DEVICE_POLL_MILLIS)) { + return XGE_HAL_BADCFG_DEVICE_POLL_MILLIS; + } + } + + if ((new_config->rts_port_en < XGE_HAL_MIN_RING_RTS_PORT_EN) || + (new_config->rts_port_en > XGE_HAL_MAX_RING_RTS_PORT_EN)) { + return XGE_HAL_BADCFG_RTS_PORT_EN; + } + + if ((new_config->rts_qos_en < XGE_HAL_RTS_QOS_DISABLE) || + (new_config->rts_qos_en > XGE_HAL_RTS_QOS_ENABLE)) { + return XGE_HAL_BADCFG_RTS_QOS_EN; + } + +#if defined(XGE_HAL_CONFIG_LRO) + if (new_config->lro_sg_size != + XGE_HAL_DEFAULT_USE_HARDCODE) { + if ((new_config->lro_sg_size < XGE_HAL_LRO_MIN_SG_SIZE) || + (new_config->lro_sg_size > XGE_HAL_LRO_MAX_SG_SIZE)) { + return XGE_HAL_BADCFG_LRO_SG_SIZE; + } + } + + if (new_config->lro_frm_len != + XGE_HAL_DEFAULT_USE_HARDCODE) { + if ((new_config->lro_frm_len < XGE_HAL_LRO_MIN_FRM_LEN) || + (new_config->lro_frm_len > XGE_HAL_LRO_MAX_FRM_LEN)) { + return XGE_HAL_BADCFG_LRO_FRM_LEN; + } + } +#endif + + if ((status = __hal_ring_config_check(&new_config->ring)) + != XGE_HAL_OK) { + return status; + } + + if ((status = __hal_mac_config_check(&new_config->mac)) != + XGE_HAL_OK) { + return status; + } + + if ((status = __hal_fifo_config_check(&new_config->fifo)) != + XGE_HAL_OK) { + return status; + } + + return XGE_HAL_OK; +} + +/* + * __hal_device_config_check_xena - Check Xframe-I configuration + * @new_config: Device configuration. + * + * Check part of configuration that is relevant only to Xframe-I. + * + * Returns: XGE_HAL_OK - success, + * otherwise one of the xge_hal_status_e{} enumerated error codes. + * + * See also: __hal_device_config_check_common(). + */ +xge_hal_status_e +__hal_device_config_check_xena (xge_hal_device_config_t *new_config) +{ + if ((new_config->pci_freq_mherz != XGE_HAL_PCI_FREQ_MHERZ_33) && + (new_config->pci_freq_mherz != XGE_HAL_PCI_FREQ_MHERZ_66) && + (new_config->pci_freq_mherz != XGE_HAL_PCI_FREQ_MHERZ_100) && + (new_config->pci_freq_mherz != XGE_HAL_PCI_FREQ_MHERZ_133) && + (new_config->pci_freq_mherz != XGE_HAL_PCI_FREQ_MHERZ_266) && + (new_config->pci_freq_mherz != XGE_HAL_DEFAULT_USE_HARDCODE)) { + return XGE_HAL_BADCFG_PCI_FREQ_MHERZ; + } + + return XGE_HAL_OK; +} + +/* + * __hal_device_config_check_herc - Check device configuration + * @new_config: Device configuration. + * + * Check part of configuration that is relevant only to Xframe-II. + * + * Returns: XGE_HAL_OK - success, + * otherwise one of the xge_hal_status_e{} enumerated error codes. + * + * See also: __hal_device_config_check_common(). + */ +xge_hal_status_e +__hal_device_config_check_herc (xge_hal_device_config_t *new_config) +{ + return XGE_HAL_OK; +} + + +/* + * __hal_driver_config_check - Check HAL configuration + * @new_config: Driver configuration information + * + * Returns: XGE_HAL_OK - success, + * otherwise one of the xge_hal_status_e{} enumerated error codes. + */ +xge_hal_status_e +__hal_driver_config_check (xge_hal_driver_config_t *new_config) +{ + if ((new_config->queue_size_initial < + XGE_HAL_MIN_QUEUE_SIZE_INITIAL) || + (new_config->queue_size_initial > + XGE_HAL_MAX_QUEUE_SIZE_INITIAL)) { + return XGE_HAL_BADCFG_QUEUE_SIZE_INITIAL; + } + + if ((new_config->queue_size_max < XGE_HAL_MIN_QUEUE_SIZE_MAX) || + (new_config->queue_size_max > XGE_HAL_MAX_QUEUE_SIZE_MAX)) { + return XGE_HAL_BADCFG_QUEUE_SIZE_MAX; + } + +#ifdef XGE_TRACE_INTO_CIRCULAR_ARR + if ((new_config->tracebuf_size < XGE_HAL_MIN_CIRCULAR_ARR) || + (new_config->tracebuf_size > XGE_HAL_MAX_CIRCULAR_ARR)) { + return XGE_HAL_BADCFG_TRACEBUF_SIZE; + } + if ((new_config->tracebuf_timestamp_en < XGE_HAL_MIN_TIMESTAMP_EN) || + (new_config->tracebuf_timestamp_en > XGE_HAL_MAX_TIMESTAMP_EN)) { + return XGE_HAL_BADCFG_TRACEBUF_SIZE; + } +#endif + + return XGE_HAL_OK; +} diff --git a/sys/dev/nxge/xgehal/xgehal-device-fp.c b/sys/dev/nxge/xgehal/xgehal-device-fp.c new file mode 100644 index 0000000..5e2faf1 --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-device-fp.c @@ -0,0 +1,1432 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-device-fp.c + * + * Description: HAL device object functionality (fast path) + * + * Created: 10 June 2004 + */ + +#ifdef XGE_DEBUG_FP +#include <dev/nxge/include/xgehal-device.h> +#endif + +#include <dev/nxge/include/xgehal-ring.h> +#include <dev/nxge/include/xgehal-fifo.h> + +/** + * xge_hal_device_bar0 - Get BAR0 mapped address. + * @hldev: HAL device handle. + * + * Returns: BAR0 address of the specified device. + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE char * +xge_hal_device_bar0(xge_hal_device_t *hldev) +{ + return hldev->bar0; +} + +/** + * xge_hal_device_isrbar0 - Get BAR0 mapped address. + * @hldev: HAL device handle. + * + * Returns: BAR0 address of the specified device. + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE char * +xge_hal_device_isrbar0(xge_hal_device_t *hldev) +{ + return hldev->isrbar0; +} + +/** + * xge_hal_device_bar1 - Get BAR1 mapped address. + * @hldev: HAL device handle. + * + * Returns: BAR1 address of the specified device. + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE char * +xge_hal_device_bar1(xge_hal_device_t *hldev) +{ + return hldev->bar1; +} + +/** + * xge_hal_device_bar0_set - Set BAR0 mapped address. + * @hldev: HAL device handle. + * @bar0: BAR0 mapped address. + * * Set BAR0 address in the HAL device object. + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_bar0_set(xge_hal_device_t *hldev, char *bar0) +{ + xge_assert(bar0); + hldev->bar0 = bar0; +} + +/** + * xge_hal_device_isrbar0_set - Set BAR0 mapped address. + * @hldev: HAL device handle. + * @isrbar0: BAR0 mapped address. + * * Set BAR0 address in the HAL device object. + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_isrbar0_set(xge_hal_device_t *hldev, char *isrbar0) +{ + xge_assert(isrbar0); + hldev->isrbar0 = isrbar0; +} + +/** + * xge_hal_device_bar1_set - Set BAR1 mapped address. + * @hldev: HAL device handle. + * @channelh: Channel handle. + * @bar1: BAR1 mapped address. + * + * Set BAR1 address for the given channel. + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_bar1_set(xge_hal_device_t *hldev, xge_hal_channel_h channelh, + char *bar1) +{ + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + + xge_assert(bar1); + xge_assert(fifo); + + /* Initializing the BAR1 address as the start of + * the FIFO queue pointer and as a location of FIFO control + * word. */ + fifo->hw_pair = + (xge_hal_fifo_hw_pair_t *) (bar1 + + (fifo->channel.post_qid * XGE_HAL_FIFO_HW_PAIR_OFFSET)); + hldev->bar1 = bar1; +} + + +/** + * xge_hal_device_rev - Get Device revision number. + * @hldev: HAL device handle. + * + * Returns: Device revision number + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE int +xge_hal_device_rev(xge_hal_device_t *hldev) +{ + return hldev->revision; +} + + +/** + * xge_hal_device_begin_irq - Begin IRQ processing. + * @hldev: HAL device handle. + * @reason: "Reason" for the interrupt, the value of Xframe's + * general_int_status register. + * + * The function performs two actions, It first checks whether (shared IRQ) the + * interrupt was raised by the device. Next, it masks the device interrupts. + * + * Note: + * xge_hal_device_begin_irq() does not flush MMIO writes through the + * bridge. Therefore, two back-to-back interrupts are potentially possible. + * It is the responsibility of the ULD to make sure that only one + * xge_hal_device_continue_irq() runs at a time. + * + * Returns: 0, if the interrupt is not "ours" (note that in this case the + * device remain enabled). + * Otherwise, xge_hal_device_begin_irq() returns 64bit general adapter + * status. + * See also: xge_hal_device_handle_irq() + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_begin_irq(xge_hal_device_t *hldev, u64 *reason) +{ + u64 val64; + xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0; + + hldev->stats.sw_dev_info_stats.total_intr_cnt++; + + val64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &isrbar0->general_int_status); + if (xge_os_unlikely(!val64)) { + /* not Xframe interrupt */ + hldev->stats.sw_dev_info_stats.not_xge_intr_cnt++; + *reason = 0; + return XGE_HAL_ERR_WRONG_IRQ; + } + + if (xge_os_unlikely(val64 == XGE_HAL_ALL_FOXES)) { + u64 adapter_status = + xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->adapter_status); + if (adapter_status == XGE_HAL_ALL_FOXES) { + (void) xge_queue_produce(hldev->queueh, + XGE_HAL_EVENT_SLOT_FREEZE, + hldev, + 1, /* critical: slot freeze */ + sizeof(u64), + (void*)&adapter_status); + *reason = 0; + return XGE_HAL_ERR_CRITICAL; + } + } + + *reason = val64; + + /* separate fast path, i.e. no errors */ + if (val64 & XGE_HAL_GEN_INTR_RXTRAFFIC) { + hldev->stats.sw_dev_info_stats.rx_traffic_intr_cnt++; + return XGE_HAL_OK; + } + if (val64 & XGE_HAL_GEN_INTR_TXTRAFFIC) { + hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt++; + return XGE_HAL_OK; + } + + hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt++; + if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_TXPIC)) { + xge_hal_status_e status; + hldev->stats.sw_dev_info_stats.txpic_intr_cnt++; + status = __hal_device_handle_txpic(hldev, val64); + if (status != XGE_HAL_OK) { + return status; + } + } + + if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_TXDMA)) { + xge_hal_status_e status; + hldev->stats.sw_dev_info_stats.txdma_intr_cnt++; + status = __hal_device_handle_txdma(hldev, val64); + if (status != XGE_HAL_OK) { + return status; + } + } + + if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_TXMAC)) { + xge_hal_status_e status; + hldev->stats.sw_dev_info_stats.txmac_intr_cnt++; + status = __hal_device_handle_txmac(hldev, val64); + if (status != XGE_HAL_OK) { + return status; + } + } + + if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_TXXGXS)) { + xge_hal_status_e status; + hldev->stats.sw_dev_info_stats.txxgxs_intr_cnt++; + status = __hal_device_handle_txxgxs(hldev, val64); + if (status != XGE_HAL_OK) { + return status; + } + } + + if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_RXPIC)) { + xge_hal_status_e status; + hldev->stats.sw_dev_info_stats.rxpic_intr_cnt++; + status = __hal_device_handle_rxpic(hldev, val64); + if (status != XGE_HAL_OK) { + return status; + } + } + + if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_RXDMA)) { + xge_hal_status_e status; + hldev->stats.sw_dev_info_stats.rxdma_intr_cnt++; + status = __hal_device_handle_rxdma(hldev, val64); + if (status != XGE_HAL_OK) { + return status; + } + } + + if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_RXMAC)) { + xge_hal_status_e status; + hldev->stats.sw_dev_info_stats.rxmac_intr_cnt++; + status = __hal_device_handle_rxmac(hldev, val64); + if (status != XGE_HAL_OK) { + return status; + } + } + + if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_RXXGXS)) { + xge_hal_status_e status; + hldev->stats.sw_dev_info_stats.rxxgxs_intr_cnt++; + status = __hal_device_handle_rxxgxs(hldev, val64); + if (status != XGE_HAL_OK) { + return status; + } + } + + if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_MC)) { + xge_hal_status_e status; + hldev->stats.sw_dev_info_stats.mc_intr_cnt++; + status = __hal_device_handle_mc(hldev, val64); + if (status != XGE_HAL_OK) { + return status; + } + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_clear_rx - Acknowledge (that is, clear) the + * condition that has caused the RX interrupt. + * @hldev: HAL device handle. + * + * Acknowledge (that is, clear) the condition that has caused + * the Rx interrupt. + * See also: xge_hal_device_begin_irq(), xge_hal_device_continue_irq(), + * xge_hal_device_clear_tx(), xge_hal_device_mask_rx(). + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_clear_rx(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0xFFFFFFFFFFFFFFFFULL, + &isrbar0->rx_traffic_int); +} + +/** + * xge_hal_device_clear_tx - Acknowledge (that is, clear) the + * condition that has caused the TX interrupt. + * @hldev: HAL device handle. + * + * Acknowledge (that is, clear) the condition that has caused + * the Tx interrupt. + * See also: xge_hal_device_begin_irq(), xge_hal_device_continue_irq(), + * xge_hal_device_clear_rx(), xge_hal_device_mask_tx(). + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_clear_tx(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0xFFFFFFFFFFFFFFFFULL, + &isrbar0->tx_traffic_int); +} + +/** + * xge_hal_device_poll_rx_channel - Poll Rx channel for completed + * descriptors and process the same. + * @channel: HAL channel. + * @got_rx: Buffer to return the flag set if receive interrupt is occured + * + * The function polls the Rx channel for the completed descriptors and calls + * the upper-layer driver (ULD) via supplied completion callback. + * + * Returns: XGE_HAL_OK, if the polling is completed successful. + * XGE_HAL_COMPLETIONS_REMAIN: There are still more completed + * descriptors available which are yet to be processed. + * + * See also: xge_hal_device_poll_tx_channel() + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_poll_rx_channel(xge_hal_channel_t *channel, int *got_rx) +{ + xge_hal_status_e ret = XGE_HAL_OK; + xge_hal_dtr_h first_dtrh; + xge_hal_device_t *hldev = (xge_hal_device_t *)channel->devh; + u8 t_code; + int got_bytes; + + /* for each opened rx channel */ + got_bytes = *got_rx = 0; + ((xge_hal_ring_t *)channel)->cmpl_cnt = 0; + channel->poll_bytes = 0; + if ((ret = xge_hal_ring_dtr_next_completed (channel, &first_dtrh, + &t_code)) == XGE_HAL_OK) { + if (channel->callback(channel, first_dtrh, + t_code, channel->userdata) != XGE_HAL_OK) { + (*got_rx) += ((xge_hal_ring_t *)channel)->cmpl_cnt + 1; + got_bytes += channel->poll_bytes + 1; + ret = XGE_HAL_COMPLETIONS_REMAIN; + } else { + (*got_rx) += ((xge_hal_ring_t *)channel)->cmpl_cnt + 1; + got_bytes += channel->poll_bytes + 1; + } + } + + if (*got_rx) { + hldev->irq_workload_rxd[channel->post_qid] += *got_rx; + hldev->irq_workload_rxcnt[channel->post_qid] ++; + } + hldev->irq_workload_rxlen[channel->post_qid] += got_bytes; + + return ret; +} + +/** + * xge_hal_device_poll_tx_channel - Poll Tx channel for completed + * descriptors and process the same. + * @channel: HAL channel. + * @got_tx: Buffer to return the flag set if transmit interrupt is occured + * + * The function polls the Tx channel for the completed descriptors and calls + * the upper-layer driver (ULD) via supplied completion callback. + * + * Returns: XGE_HAL_OK, if the polling is completed successful. + * XGE_HAL_COMPLETIONS_REMAIN: There are still more completed + * descriptors available which are yet to be processed. + * + * See also: xge_hal_device_poll_rx_channel(). + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_poll_tx_channel(xge_hal_channel_t *channel, int *got_tx) +{ + xge_hal_dtr_h first_dtrh; + xge_hal_device_t *hldev = (xge_hal_device_t *)channel->devh; + u8 t_code; + int got_bytes; + + /* for each opened tx channel */ + got_bytes = *got_tx = 0; + channel->poll_bytes = 0; + if (xge_hal_fifo_dtr_next_completed (channel, &first_dtrh, + &t_code) == XGE_HAL_OK) { + if (channel->callback(channel, first_dtrh, + t_code, channel->userdata) != XGE_HAL_OK) { + (*got_tx)++; + got_bytes += channel->poll_bytes + 1; + return XGE_HAL_COMPLETIONS_REMAIN; + } + (*got_tx)++; + got_bytes += channel->poll_bytes + 1; + } + + if (*got_tx) { + hldev->irq_workload_txd[channel->post_qid] += *got_tx; + hldev->irq_workload_txcnt[channel->post_qid] ++; + } + hldev->irq_workload_txlen[channel->post_qid] += got_bytes; + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_poll_rx_channels - Poll Rx channels for completed + * descriptors and process the same. + * @hldev: HAL device handle. + * @got_rx: Buffer to return flag set if receive is ready + * + * The function polls the Rx channels for the completed descriptors and calls + * the upper-layer driver (ULD) via supplied completion callback. + * + * Returns: XGE_HAL_OK, if the polling is completed successful. + * XGE_HAL_COMPLETIONS_REMAIN: There are still more completed + * descriptors available which are yet to be processed. + * + * See also: xge_hal_device_poll_tx_channels(), xge_hal_device_continue_irq(). + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_poll_rx_channels(xge_hal_device_t *hldev, int *got_rx) +{ + xge_list_t *item; + xge_hal_channel_t *channel; + + /* for each opened rx channel */ + xge_list_for_each(item, &hldev->ring_channels) { + if (hldev->terminating) + return XGE_HAL_OK; + channel = xge_container_of(item, xge_hal_channel_t, item); + (void) xge_hal_device_poll_rx_channel(channel, got_rx); + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_poll_tx_channels - Poll Tx channels for completed + * descriptors and process the same. + * @hldev: HAL device handle. + * @got_tx: Buffer to return flag set if transmit is ready + * + * The function polls the Tx channels for the completed descriptors and calls + * the upper-layer driver (ULD) via supplied completion callback. + * + * Returns: XGE_HAL_OK, if the polling is completed successful. + * XGE_HAL_COMPLETIONS_REMAIN: There are still more completed + * descriptors available which are yet to be processed. + * + * See also: xge_hal_device_poll_rx_channels(), xge_hal_device_continue_irq(). + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_poll_tx_channels(xge_hal_device_t *hldev, int *got_tx) +{ + xge_list_t *item; + xge_hal_channel_t *channel; + + /* for each opened tx channel */ + xge_list_for_each(item, &hldev->fifo_channels) { + if (hldev->terminating) + return XGE_HAL_OK; + channel = xge_container_of(item, xge_hal_channel_t, item); + (void) xge_hal_device_poll_tx_channel(channel, got_tx); + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_mask_tx - Mask Tx interrupts. + * @hldev: HAL device handle. + * + * Mask Tx device interrupts. + * + * See also: xge_hal_device_unmask_tx(), xge_hal_device_mask_rx(), + * xge_hal_device_clear_tx(). + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_mask_tx(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0xFFFFFFFFFFFFFFFFULL, + &isrbar0->tx_traffic_mask); +} + +/** + * xge_hal_device_mask_rx - Mask Rx interrupts. + * @hldev: HAL device handle. + * + * Mask Rx device interrupts. + * + * See also: xge_hal_device_unmask_rx(), xge_hal_device_mask_tx(), + * xge_hal_device_clear_rx(). + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_mask_rx(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0xFFFFFFFFFFFFFFFFULL, + &isrbar0->rx_traffic_mask); +} + +/** + * xge_hal_device_mask_all - Mask all device interrupts. + * @hldev: HAL device handle. + * + * Mask all device interrupts. + * + * See also: xge_hal_device_unmask_all() + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_mask_all(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0xFFFFFFFFFFFFFFFFULL, + &isrbar0->general_int_mask); +} + +/** + * xge_hal_device_unmask_tx - Unmask Tx interrupts. + * @hldev: HAL device handle. + * + * Unmask Tx device interrupts. + * + * See also: xge_hal_device_mask_tx(), xge_hal_device_clear_tx(). + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_unmask_tx(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0x0ULL, + &isrbar0->tx_traffic_mask); +} + +/** + * xge_hal_device_unmask_rx - Unmask Rx interrupts. + * @hldev: HAL device handle. + * + * Unmask Rx device interrupts. + * + * See also: xge_hal_device_mask_rx(), xge_hal_device_clear_rx(). + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_unmask_rx(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0x0ULL, + &isrbar0->rx_traffic_mask); +} + +/** + * xge_hal_device_unmask_all - Unmask all device interrupts. + * @hldev: HAL device handle. + * + * Unmask all device interrupts. + * + * See also: xge_hal_device_mask_all() + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void +xge_hal_device_unmask_all(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0x0ULL, + &isrbar0->general_int_mask); +} + + +/** + * xge_hal_device_continue_irq - Continue handling IRQ: process all + * completed descriptors. + * @hldev: HAL device handle. + * + * Process completed descriptors and unmask the device interrupts. + * + * The xge_hal_device_continue_irq() walks all open channels + * and calls upper-layer driver (ULD) via supplied completion + * callback. Note that the completion callback is specified at channel open + * time, see xge_hal_channel_open(). + * + * Note that the xge_hal_device_continue_irq is part of the _fast_ path. + * To optimize the processing, the function does _not_ check for + * errors and alarms. + * + * The latter is done in a polling fashion, via xge_hal_device_poll(). + * + * Returns: XGE_HAL_OK. + * + * See also: xge_hal_device_handle_irq(), xge_hal_device_poll(), + * xge_hal_ring_dtr_next_completed(), + * xge_hal_fifo_dtr_next_completed(), xge_hal_channel_callback_f{}. + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_continue_irq(xge_hal_device_t *hldev) +{ + int got_rx = 1, got_tx = 1; + int isr_polling_cnt = hldev->config.isr_polling_cnt; + int count = 0; + + do + { + if (got_rx) + (void) xge_hal_device_poll_rx_channels(hldev, &got_rx); + if (got_tx && hldev->tti_enabled) + (void) xge_hal_device_poll_tx_channels(hldev, &got_tx); + + if (!got_rx && !got_tx) + break; + + count += (got_rx + got_tx); + }while (isr_polling_cnt--); + + if (!count) + hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt++; + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_handle_irq - Handle device IRQ. + * @hldev: HAL device handle. + * + * Perform the complete handling of the line interrupt. The function + * performs two calls. + * First it uses xge_hal_device_begin_irq() to check the reason for + * the interrupt and mask the device interrupts. + * Second, it calls xge_hal_device_continue_irq() to process all + * completed descriptors and re-enable the interrupts. + * + * Returns: XGE_HAL_OK - success; + * XGE_HAL_ERR_WRONG_IRQ - (shared) IRQ produced by other device. + * + * See also: xge_hal_device_begin_irq(), xge_hal_device_continue_irq(). + */ +__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e +xge_hal_device_handle_irq(xge_hal_device_t *hldev) +{ + u64 reason; + xge_hal_status_e status; + + xge_hal_device_mask_all(hldev); + + status = xge_hal_device_begin_irq(hldev, &reason); + if (status != XGE_HAL_OK) { + xge_hal_device_unmask_all(hldev); + return status; + } + + if (reason & XGE_HAL_GEN_INTR_RXTRAFFIC) { + xge_hal_device_clear_rx(hldev); + } + + status = xge_hal_device_continue_irq(hldev); + + xge_hal_device_clear_tx(hldev); + + xge_hal_device_unmask_all(hldev); + + return status; +} + +#if defined(XGE_HAL_CONFIG_LRO) + + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int +__hal_lro_check_for_session_match(lro_t *lro, tcplro_t *tcp, iplro_t *ip) +{ + + /* Match Source address field */ + if ((lro->ip_hdr->saddr != ip->saddr)) + return XGE_HAL_FAIL; + + /* Match Destination address field */ + if ((lro->ip_hdr->daddr != ip->daddr)) + return XGE_HAL_FAIL; + + /* Match Source Port field */ + if ((lro->tcp_hdr->source != tcp->source)) + return XGE_HAL_FAIL; + + /* Match Destination Port field */ + if ((lro->tcp_hdr->dest != tcp->dest)) + return XGE_HAL_FAIL; + + return XGE_HAL_OK; +} + +/* + * __hal_tcp_seg_len: Find the tcp seg len. + * @ip: ip header. + * @tcp: tcp header. + * returns: Tcp seg length. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL u16 +__hal_tcp_seg_len(iplro_t *ip, tcplro_t *tcp) +{ + u16 ret; + + ret = (xge_os_ntohs(ip->tot_len) - + ((ip->version_ihl & 0x0F)<<2) - + ((tcp->doff_res)>>2)); + return (ret); +} + +/* + * __hal_ip_lro_capable: Finds whether ip is lro capable. + * @ip: ip header. + * @ext_info: descriptor info. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_ip_lro_capable(iplro_t *ip, + xge_hal_dtr_info_t *ext_info) +{ + +#ifdef XGE_LL_DEBUG_DUMP_PKT + { + u16 i; + u8 ch, *iph = (u8 *)ip; + + xge_debug_ring(XGE_TRACE, "Dump Ip:" ); + for (i =0; i < 40; i++) { + ch = ntohs(*((u8 *)(iph + i)) ); + printf("i:%d %02x, ",i,ch); + } + } +#endif + + if (ip->version_ihl != IP_FAST_PATH_HDR_MASK) { + xge_debug_ring(XGE_ERR, "iphdr !=45 :%d",ip->version_ihl); + return XGE_HAL_FAIL; + } + + if (ext_info->proto & XGE_HAL_FRAME_PROTO_IP_FRAGMENTED) { + xge_debug_ring(XGE_ERR, "IP fragmented"); + return XGE_HAL_FAIL; + } + + return XGE_HAL_OK; +} + +/* + * __hal_tcp_lro_capable: Finds whether tcp is lro capable. + * @ip: ip header. + * @tcp: tcp header. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_tcp_lro_capable(iplro_t *ip, tcplro_t *tcp, lro_t *lro, int *ts_off) +{ +#ifdef XGE_LL_DEBUG_DUMP_PKT + { + u8 ch; + u16 i; + + xge_debug_ring(XGE_TRACE, "Dump Tcp:" ); + for (i =0; i < 20; i++) { + ch = ntohs(*((u8 *)((u8 *)tcp + i)) ); + xge_os_printf("i:%d %02x, ",i,ch); + } + } +#endif + if ((TCP_FAST_PATH_HDR_MASK2 != tcp->ctrl) && + (TCP_FAST_PATH_HDR_MASK3 != tcp->ctrl)) + goto _exit_fail; + + *ts_off = -1; + if (TCP_FAST_PATH_HDR_MASK1 != tcp->doff_res) { + u16 tcp_hdr_len = tcp->doff_res >> 2; /* TCP header len */ + u16 off = 20; /* Start of tcp options */ + int i, diff; + + /* Does Packet can contain time stamp */ + if (tcp_hdr_len < 32) { + /* + * If the session is not opened, we can consider + * this packet for LRO + */ + if (lro == NULL) + return XGE_HAL_OK; + + goto _exit_fail; + } + + /* Ignore No-operation 0x1 */ + while (((u8 *)tcp)[off] == 0x1) + off++; + + /* Next option == Timestamp */ + if (((u8 *)tcp)[off] != 0x8) { + /* + * If the session ie not opened, we can consider + * this packet for LRO + */ + if (lro == NULL) + return XGE_HAL_OK; + + goto _exit_fail; + } + + *ts_off = off; + if (lro == NULL) + return XGE_HAL_OK; + + /* + * Now the session is opened. If the LRO frame doesn't + * have time stamp, we cannot consider current packet for + * LRO. + */ + if (lro->ts_off == -1) { + xge_debug_ring(XGE_ERR, "Pkt received with time stamp after session opened with no time stamp : %02x %02x", tcp->doff_res, tcp->ctrl); + return XGE_HAL_FAIL; + } + + /* + * If the difference is greater than three, then there are + * more options possible. + * else, there are two cases: + * case 1: remaining are padding bytes. + * case 2: remaining can contain options or padding + */ + off += ((u8 *)tcp)[off+1]; + diff = tcp_hdr_len - off; + if (diff > 3) { + /* + * Probably contains more options. + */ + xge_debug_ring(XGE_ERR, "tcphdr not fastpth : pkt received with tcp options in addition to time stamp after the session is opened %02x %02x ", tcp->doff_res, tcp->ctrl); + return XGE_HAL_FAIL; + } + + for (i = 0; i < diff; i++) { + u8 byte = ((u8 *)tcp)[off+i]; + + /* Ignore No-operation 0x1 */ + if ((byte == 0x0) || (byte == 0x1)) + continue; + xge_debug_ring(XGE_ERR, "tcphdr not fastpth : pkt received with tcp options in addition to time stamp after the session is opened %02x %02x ", tcp->doff_res, tcp->ctrl); + return XGE_HAL_FAIL; + } + + /* + * Update the time stamp of LRO frame. + */ + xge_os_memcpy(((char *)lro->tcp_hdr + lro->ts_off + 2), + (char *)((char *)tcp + (*ts_off) + 2), 8); + } + + return XGE_HAL_OK; + +_exit_fail: + xge_debug_ring(XGE_ERR, "tcphdr not fastpth %02x %02x", tcp->doff_res, tcp->ctrl); + return XGE_HAL_FAIL; + +} + +/* + * __hal_lro_capable: Finds whether frame is lro capable. + * @buffer: Ethernet frame. + * @ip: ip frame. + * @tcp: tcp frame. + * @ext_info: Descriptor info. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_lro_capable( u8 *buffer, + iplro_t **ip, + tcplro_t **tcp, + xge_hal_dtr_info_t *ext_info) +{ + u8 ip_off, ip_length; + + if (!(ext_info->proto & XGE_HAL_FRAME_PROTO_TCP)) { + xge_debug_ring(XGE_ERR, "Cant do lro %d", ext_info->proto); + return XGE_HAL_FAIL; + } + + if ( !*ip ) + { +#ifdef XGE_LL_DEBUG_DUMP_PKT + { + u8 ch; + u16 i; + + xge_os_printf("Dump Eth:" ); + for (i =0; i < 60; i++) { + ch = ntohs(*((u8 *)(buffer + i)) ); + xge_os_printf("i:%d %02x, ",i,ch); + } + } +#endif + + switch (ext_info->frame) { + case XGE_HAL_FRAME_TYPE_DIX: + ip_off = XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE; + break; + case XGE_HAL_FRAME_TYPE_LLC: + ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE + + XGE_HAL_HEADER_802_2_SIZE); + break; + case XGE_HAL_FRAME_TYPE_SNAP: + ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE + + XGE_HAL_HEADER_SNAP_SIZE); + break; + default: // XGE_HAL_FRAME_TYPE_IPX, etc. + return XGE_HAL_FAIL; + } + + + if (ext_info->proto & XGE_HAL_FRAME_PROTO_VLAN_TAGGED) { + ip_off += XGE_HAL_HEADER_VLAN_SIZE; + } + + /* Grab ip, tcp headers */ + *ip = (iplro_t *)((char*)buffer + ip_off); + } /* !*ip */ + + ip_length = (u8)((*ip)->version_ihl & 0x0F); + ip_length = ip_length <<2; + *tcp = (tcplro_t *)((char *)*ip + ip_length); + + xge_debug_ring(XGE_TRACE, "ip_length:%d ip:"XGE_OS_LLXFMT + " tcp:"XGE_OS_LLXFMT"", (int)ip_length, + (unsigned long long)(ulong_t)*ip, (unsigned long long)(ulong_t)*tcp); + + return XGE_HAL_OK; + +} + + +/* + * __hal_open_lro_session: Open a new LRO session. + * @buffer: Ethernet frame. + * @ip: ip header. + * @tcp: tcp header. + * @lro: lro pointer + * @ext_info: Descriptor info. + * @hldev: Hal context. + * @ring_lro: LRO descriptor per rx ring. + * @slot: Bucket no. + * @tcp_seg_len: Length of tcp segment. + * @ts_off: time stamp offset in the packet. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +__hal_open_lro_session (u8 *buffer, iplro_t *ip, tcplro_t *tcp, lro_t **lro, + xge_hal_device_t *hldev, xge_hal_lro_desc_t *ring_lro, int slot, + u32 tcp_seg_len, int ts_off) +{ + + lro_t *lro_new = &ring_lro->lro_pool[slot]; + + lro_new->in_use = 1; + lro_new->ll_hdr = buffer; + lro_new->ip_hdr = ip; + lro_new->tcp_hdr = tcp; + lro_new->tcp_next_seq_num = tcp_seg_len + xge_os_ntohl( + tcp->seq); + lro_new->tcp_seq_num = tcp->seq; + lro_new->tcp_ack_num = tcp->ack_seq; + lro_new->sg_num = 1; + lro_new->total_length = xge_os_ntohs(ip->tot_len); + lro_new->frags_len = 0; + lro_new->ts_off = ts_off; + + hldev->stats.sw_dev_info_stats.tot_frms_lroised++; + hldev->stats.sw_dev_info_stats.tot_lro_sessions++; + + *lro = ring_lro->lro_recent = lro_new; + return; +} +/* + * __hal_lro_get_free_slot: Get a free LRO bucket. + * @ring_lro: LRO descriptor per ring. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int +__hal_lro_get_free_slot (xge_hal_lro_desc_t *ring_lro) +{ + int i; + + for (i = 0; i < XGE_HAL_LRO_MAX_BUCKETS; i++) { + lro_t *lro_temp = &ring_lro->lro_pool[i]; + + if (!lro_temp->in_use) + return i; + } + return -1; +} + +/* + * __hal_get_lro_session: Gets matching LRO session or creates one. + * @eth_hdr: Ethernet header. + * @ip: ip header. + * @tcp: tcp header. + * @lro: lro pointer + * @ext_info: Descriptor info. + * @hldev: Hal context. + * @ring_lro: LRO descriptor per rx ring + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_get_lro_session (u8 *eth_hdr, + iplro_t *ip, + tcplro_t *tcp, + lro_t **lro, + xge_hal_dtr_info_t *ext_info, + xge_hal_device_t *hldev, + xge_hal_lro_desc_t *ring_lro, + lro_t **lro_end3 /* Valid only when ret=END_3 */) +{ + lro_t *lro_match; + int i, free_slot = -1; + u32 tcp_seg_len; + int ts_off = -1; + + *lro = lro_match = NULL; + /* + * Compare the incoming frame with the lro session left from the + * previous call. There is a good chance that this incoming frame + * matches the lro session. + */ + if (ring_lro->lro_recent && ring_lro->lro_recent->in_use) { + if (__hal_lro_check_for_session_match(ring_lro->lro_recent, + tcp, ip) + == XGE_HAL_OK) + lro_match = ring_lro->lro_recent; + } + + if (!lro_match) { + /* + * Search in the pool of LROs for the session that matches + * the incoming frame. + */ + for (i = 0; i < XGE_HAL_LRO_MAX_BUCKETS; i++) { + lro_t *lro_temp = &ring_lro->lro_pool[i]; + + if (!lro_temp->in_use) { + if (free_slot == -1) + free_slot = i; + continue; + } + + if (__hal_lro_check_for_session_match(lro_temp, tcp, + ip) == XGE_HAL_OK) { + lro_match = lro_temp; + break; + } + } + } + + + if (lro_match) { + /* + * Matching LRO Session found + */ + *lro = lro_match; + + if (lro_match->tcp_next_seq_num != xge_os_ntohl(tcp->seq)) { + xge_debug_ring(XGE_ERR, "**retransmit **" + "found***"); + hldev->stats.sw_dev_info_stats.lro_out_of_seq_pkt_cnt++; + return XGE_HAL_INF_LRO_END_2; + } + + if (XGE_HAL_OK != __hal_ip_lro_capable(ip, ext_info)) + { + return XGE_HAL_INF_LRO_END_2; + } + + if (XGE_HAL_OK != __hal_tcp_lro_capable(ip, tcp, lro_match, + &ts_off)) { + /* + * Close the current session and open a new + * LRO session with this packet, + * provided it has tcp payload + */ + tcp_seg_len = __hal_tcp_seg_len(ip, tcp); + if (tcp_seg_len == 0) + { + return XGE_HAL_INF_LRO_END_2; + } + + /* Get a free bucket */ + free_slot = __hal_lro_get_free_slot(ring_lro); + if (free_slot == -1) + { + return XGE_HAL_INF_LRO_END_2; + } + + /* + * Open a new LRO session + */ + __hal_open_lro_session (eth_hdr, ip, tcp, lro_end3, + hldev, ring_lro, free_slot, tcp_seg_len, + ts_off); + + return XGE_HAL_INF_LRO_END_3; + } + + /* + * The frame is good, in-sequence, can be LRO-ed; + * take its (latest) ACK - unless it is a dupack. + * Note: to be exact need to check window size as well.. + */ + if (lro_match->tcp_ack_num == tcp->ack_seq && + lro_match->tcp_seq_num == tcp->seq) { + hldev->stats.sw_dev_info_stats.lro_dup_pkt_cnt++; + return XGE_HAL_INF_LRO_END_2; + } + + lro_match->tcp_seq_num = tcp->seq; + lro_match->tcp_ack_num = tcp->ack_seq; + lro_match->frags_len += __hal_tcp_seg_len(ip, tcp); + + ring_lro->lro_recent = lro_match; + + return XGE_HAL_INF_LRO_CONT; + } + + /* ********** New Session ***************/ + if (free_slot == -1) + return XGE_HAL_INF_LRO_UNCAPABLE; + + if (XGE_HAL_FAIL == __hal_ip_lro_capable(ip, ext_info)) + return XGE_HAL_INF_LRO_UNCAPABLE; + + if (XGE_HAL_FAIL == __hal_tcp_lro_capable(ip, tcp, NULL, &ts_off)) + return XGE_HAL_INF_LRO_UNCAPABLE; + + xge_debug_ring(XGE_TRACE, "Creating lro session."); + + /* + * Open a LRO session, provided the packet contains payload. + */ + tcp_seg_len = __hal_tcp_seg_len(ip, tcp); + if (tcp_seg_len == 0) + return XGE_HAL_INF_LRO_UNCAPABLE; + + __hal_open_lro_session (eth_hdr, ip, tcp, lro, hldev, ring_lro, free_slot, + tcp_seg_len, ts_off); + + return XGE_HAL_INF_LRO_BEGIN; +} + +/* + * __hal_lro_under_optimal_thresh: Finds whether combined session is optimal. + * @ip: ip header. + * @tcp: tcp header. + * @lro: lro pointer + * @hldev: Hal context. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_lro_under_optimal_thresh (iplro_t *ip, + tcplro_t *tcp, + lro_t *lro, + xge_hal_device_t *hldev) +{ + if (!lro) return XGE_HAL_FAIL; + + if ((lro->total_length + __hal_tcp_seg_len(ip, tcp) ) > + hldev->config.lro_frm_len) { + xge_debug_ring(XGE_TRACE, "Max LRO frame len exceeded:" + "max length %d ", hldev->config.lro_frm_len); + hldev->stats.sw_dev_info_stats.lro_frm_len_exceed_cnt++; + return XGE_HAL_FAIL; + } + + if (lro->sg_num == hldev->config.lro_sg_size) { + xge_debug_ring(XGE_TRACE, "Max sg count exceeded:" + "max sg %d ", hldev->config.lro_sg_size); + hldev->stats.sw_dev_info_stats.lro_sg_exceed_cnt++; + return XGE_HAL_FAIL; + } + + return XGE_HAL_OK; +} + +/* + * __hal_collapse_ip_hdr: Collapses ip header. + * @ip: ip header. + * @tcp: tcp header. + * @lro: lro pointer + * @hldev: Hal context. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_collapse_ip_hdr ( iplro_t *ip, + tcplro_t *tcp, + lro_t *lro, + xge_hal_device_t *hldev) +{ + + lro->total_length += __hal_tcp_seg_len(ip, tcp); + + /* May be we have to handle time stamps or more options */ + + return XGE_HAL_OK; + +} + +/* + * __hal_collapse_tcp_hdr: Collapses tcp header. + * @ip: ip header. + * @tcp: tcp header. + * @lro: lro pointer + * @hldev: Hal context. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_collapse_tcp_hdr ( iplro_t *ip, + tcplro_t *tcp, + lro_t *lro, + xge_hal_device_t *hldev) +{ + lro->tcp_next_seq_num += __hal_tcp_seg_len(ip, tcp); + return XGE_HAL_OK; + +} + +/* + * __hal_append_lro: Appends new frame to existing LRO session. + * @ip: ip header. + * @tcp: IN tcp header, OUT tcp payload. + * @seg_len: tcp payload length. + * @lro: lro pointer + * @hldev: Hal context. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +__hal_append_lro(iplro_t *ip, + tcplro_t **tcp, + u32 *seg_len, + lro_t *lro, + xge_hal_device_t *hldev) +{ + (void) __hal_collapse_ip_hdr(ip, *tcp, lro, hldev); + (void) __hal_collapse_tcp_hdr(ip, *tcp, lro, hldev); + // Update mbuf chain will be done in ll driver. + // xge_hal_accumulate_large_rx on success of appending new frame to + // lro will return to ll driver tcpdata pointer, and tcp payload length. + // along with return code lro frame appended. + + lro->sg_num++; + *seg_len = __hal_tcp_seg_len(ip, *tcp); + *tcp = (tcplro_t *)((char *)*tcp + (((*tcp)->doff_res)>>2)); + + return XGE_HAL_OK; + +} + +/** + * __xge_hal_accumulate_large_rx: LRO a given frame + * frames + * @ring: rx ring number + * @eth_hdr: ethernet header. + * @ip_hdr: ip header (optional) + * @tcp: tcp header. + * @seglen: packet length. + * @p_lro: lro pointer. + * @ext_info: descriptor info, see xge_hal_dtr_info_t{}. + * @hldev: HAL device. + * @lro_end3: for lro_end3 output + * + * LRO the newly received frame, i.e. attach it (if possible) to the + * already accumulated (i.e., already LRO-ed) received frames (if any), + * to form one super-sized frame for the subsequent processing + * by the stack. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +xge_hal_lro_process_rx(int ring, u8 *eth_hdr, u8 *ip_hdr, tcplro_t **tcp, + u32 *seglen, lro_t **p_lro, + xge_hal_dtr_info_t *ext_info, xge_hal_device_t *hldev, + lro_t **lro_end3) +{ + iplro_t *ip = (iplro_t *)ip_hdr; + xge_hal_status_e ret; + lro_t *lro; + + xge_debug_ring(XGE_TRACE, "Entered accumu lro. "); + if (XGE_HAL_OK != __hal_lro_capable(eth_hdr, &ip, (tcplro_t **)tcp, + ext_info)) + return XGE_HAL_INF_LRO_UNCAPABLE; + + /* + * This function shall get matching LRO or else + * create one and return it + */ + ret = __hal_get_lro_session(eth_hdr, ip, (tcplro_t *)*tcp, + p_lro, ext_info, hldev, &hldev->lro_desc[ring], + lro_end3); + xge_debug_ring(XGE_TRACE, "ret from get_lro:%d ",ret); + lro = *p_lro; + if (XGE_HAL_INF_LRO_CONT == ret) { + if (XGE_HAL_OK == __hal_lro_under_optimal_thresh(ip, + (tcplro_t *)*tcp, lro, hldev)) { + (void) __hal_append_lro(ip,(tcplro_t **) tcp, seglen, + lro, hldev); + hldev->stats.sw_dev_info_stats.tot_frms_lroised++; + + if (lro->sg_num >= hldev->config.lro_sg_size) { + hldev->stats.sw_dev_info_stats.lro_sg_exceed_cnt++; + ret = XGE_HAL_INF_LRO_END_1; + } + + } else ret = XGE_HAL_INF_LRO_END_2; + } + + /* + * Since its time to flush, + * update ip header so that it can be sent up + */ + if ((ret == XGE_HAL_INF_LRO_END_1) || + (ret == XGE_HAL_INF_LRO_END_2) || + (ret == XGE_HAL_INF_LRO_END_3)) { + lro->ip_hdr->tot_len = xge_os_htons((*p_lro)->total_length); + lro->ip_hdr->check = xge_os_htons(0); + lro->ip_hdr->check = XGE_LL_IP_FAST_CSUM(((u8 *)(lro->ip_hdr)), + (lro->ip_hdr->version_ihl & 0x0F)); + lro->tcp_hdr->ack_seq = lro->tcp_ack_num; + } + + return (ret); +} + +/** + * xge_hal_accumulate_large_rx: LRO a given frame + * frames + * @buffer: Ethernet frame. + * @tcp: tcp header. + * @seglen: packet length. + * @p_lro: lro pointer. + * @ext_info: descriptor info, see xge_hal_dtr_info_t{}. + * @hldev: HAL device. + * @lro_end3: for lro_end3 output + * + * LRO the newly received frame, i.e. attach it (if possible) to the + * already accumulated (i.e., already LRO-ed) received frames (if any), + * to form one super-sized frame for the subsequent processing + * by the stack. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e +xge_hal_accumulate_large_rx(u8 *buffer, tcplro_t **tcp, u32 *seglen, +lro_t **p_lro, xge_hal_dtr_info_t *ext_info, xge_hal_device_t *hldev, +lro_t **lro_end3) +{ + int ring = 0; + return xge_hal_lro_process_rx(ring, buffer, NULL, tcp, seglen, p_lro, + ext_info, hldev, lro_end3); +} + +/** + * xge_hal_lro_close_session: Close LRO session + * @lro: LRO Session. + * @hldev: HAL Context. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void +xge_hal_lro_close_session (lro_t *lro) +{ + lro->in_use = 0; +} + +/** + * xge_hal_lro_next_session: Returns next LRO session in the list or NULL + * if none exists. + * @hldev: HAL Context. + * @ring: rx ring number. + */ +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL lro_t * +xge_hal_lro_next_session (xge_hal_device_t *hldev, int ring) +{ +xge_hal_lro_desc_t *ring_lro = &hldev->lro_desc[ring]; + int i; + int start_idx = ring_lro->lro_next_idx; + + for(i = start_idx; i < XGE_HAL_LRO_MAX_BUCKETS; i++) { + lro_t *lro = &ring_lro->lro_pool[i]; + + if (!lro->in_use) + continue; + + lro->ip_hdr->tot_len = xge_os_htons(lro->total_length); + lro->ip_hdr->check = xge_os_htons(0); + lro->ip_hdr->check = XGE_LL_IP_FAST_CSUM(((u8 *)(lro->ip_hdr)), + (lro->ip_hdr->version_ihl & 0x0F)); + ring_lro->lro_next_idx = i + 1; + return lro; + } + + ring_lro->lro_next_idx = 0; + return NULL; + +} + +__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL lro_t * +xge_hal_lro_get_next_session(xge_hal_device_t *hldev) +{ + int ring = 0; /* assume default ring=0 */ + return xge_hal_lro_next_session(hldev, ring); +} +#endif diff --git a/sys/dev/nxge/xgehal/xgehal-device.c b/sys/dev/nxge/xgehal/xgehal-device.c new file mode 100644 index 0000000..0ba7562 --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-device.c @@ -0,0 +1,7247 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-device.c + * + * Description: HAL device object functionality + * + * Created: 10 May 2004 + */ + +#include <dev/nxge/include/xgehal-device.h> +#include <dev/nxge/include/xgehal-channel.h> +#include <dev/nxge/include/xgehal-fifo.h> +#include <dev/nxge/include/xgehal-ring.h> +#include <dev/nxge/include/xgehal-driver.h> +#include <dev/nxge/include/xgehal-mgmt.h> + +#define SWITCH_SIGN 0xA5A5A5A5A5A5A5A5ULL +#define END_SIGN 0x0 + +#ifdef XGE_HAL_HERC_EMULATION +#undef XGE_HAL_PROCESS_LINK_INT_IN_ISR +#endif + +/* + * Jenkins hash key length(in bytes) + */ +#define XGE_HAL_JHASH_MSG_LEN 50 + +/* + * mix(a,b,c) used in Jenkins hash algorithm + */ +#define mix(a,b,c) { \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ +} + + +/* + * __hal_device_event_queued + * @data: pointer to xge_hal_device_t structure + * + * Will be called when new event succesfully queued. + */ +void +__hal_device_event_queued(void *data, int event_type) +{ + xge_assert(((xge_hal_device_t*)data)->magic == XGE_HAL_MAGIC); + if (g_xge_hal_driver->uld_callbacks.event_queued) { + g_xge_hal_driver->uld_callbacks.event_queued(data, event_type); + } +} + +/* + * __hal_pio_mem_write32_upper + * + * Endiann-aware implementation of xge_os_pio_mem_write32(). + * Since Xframe has 64bit registers, we differintiate uppper and lower + * parts. + */ +void +__hal_pio_mem_write32_upper(pci_dev_h pdev, pci_reg_h regh, u32 val, void *addr) +{ +#if defined(XGE_OS_HOST_BIG_ENDIAN) && !defined(XGE_OS_PIO_LITTLE_ENDIAN) + xge_os_pio_mem_write32(pdev, regh, val, addr); +#else + xge_os_pio_mem_write32(pdev, regh, val, (void *)((char *)addr + 4)); +#endif +} + +/* + * __hal_pio_mem_write32_upper + * + * Endiann-aware implementation of xge_os_pio_mem_write32(). + * Since Xframe has 64bit registers, we differintiate uppper and lower + * parts. + */ +void +__hal_pio_mem_write32_lower(pci_dev_h pdev, pci_reg_h regh, u32 val, + void *addr) +{ +#if defined(XGE_OS_HOST_BIG_ENDIAN) && !defined(XGE_OS_PIO_LITTLE_ENDIAN) + xge_os_pio_mem_write32(pdev, regh, val, + (void *) ((char *)addr + 4)); +#else + xge_os_pio_mem_write32(pdev, regh, val, addr); +#endif +} + +/* + * __hal_device_register_poll + * @hldev: pointer to xge_hal_device_t structure + * @reg: register to poll for + * @op: 0 - bit reset, 1 - bit set + * @mask: mask for logical "and" condition based on %op + * @max_millis: maximum time to try to poll in milliseconds + * + * Will poll certain register for specified amount of time. + * Will poll until masked bit is not cleared. + */ +xge_hal_status_e +__hal_device_register_poll(xge_hal_device_t *hldev, u64 *reg, + int op, u64 mask, int max_millis) +{ + u64 val64; + int i = 0; + xge_hal_status_e ret = XGE_HAL_FAIL; + + xge_os_udelay(10); + + do { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, reg); + if (op == 0 && !(val64 & mask)) + return XGE_HAL_OK; + else if (op == 1 && (val64 & mask) == mask) + return XGE_HAL_OK; + xge_os_udelay(100); + } while (++i <= 9); + + do { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, reg); + if (op == 0 && !(val64 & mask)) + return XGE_HAL_OK; + else if (op == 1 && (val64 & mask) == mask) + return XGE_HAL_OK; + xge_os_udelay(1000); + } while (++i < max_millis); + + return ret; +} + +/* + * __hal_device_wait_quiescent + * @hldev: the device + * @hw_status: hw_status in case of error + * + * Will wait until device is quiescent for some blocks. + */ +static xge_hal_status_e +__hal_device_wait_quiescent(xge_hal_device_t *hldev, u64 *hw_status) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + + /* poll and wait first */ +#ifdef XGE_HAL_HERC_EMULATION + (void) __hal_device_register_poll(hldev, &bar0->adapter_status, 1, + (XGE_HAL_ADAPTER_STATUS_TDMA_READY | + XGE_HAL_ADAPTER_STATUS_RDMA_READY | + XGE_HAL_ADAPTER_STATUS_PFC_READY | + XGE_HAL_ADAPTER_STATUS_TMAC_BUF_EMPTY | + XGE_HAL_ADAPTER_STATUS_PIC_QUIESCENT | + XGE_HAL_ADAPTER_STATUS_MC_DRAM_READY | + XGE_HAL_ADAPTER_STATUS_MC_QUEUES_READY | + XGE_HAL_ADAPTER_STATUS_M_PLL_LOCK), + XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS); +#else + (void) __hal_device_register_poll(hldev, &bar0->adapter_status, 1, + (XGE_HAL_ADAPTER_STATUS_TDMA_READY | + XGE_HAL_ADAPTER_STATUS_RDMA_READY | + XGE_HAL_ADAPTER_STATUS_PFC_READY | + XGE_HAL_ADAPTER_STATUS_TMAC_BUF_EMPTY | + XGE_HAL_ADAPTER_STATUS_PIC_QUIESCENT | + XGE_HAL_ADAPTER_STATUS_MC_DRAM_READY | + XGE_HAL_ADAPTER_STATUS_MC_QUEUES_READY | + XGE_HAL_ADAPTER_STATUS_M_PLL_LOCK | + XGE_HAL_ADAPTER_STATUS_P_PLL_LOCK), + XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS); +#endif + + return xge_hal_device_status(hldev, hw_status); +} + +/** + * xge_hal_device_is_slot_freeze + * @devh: the device + * + * Returns non-zero if the slot is freezed. + * The determination is made based on the adapter_status + * register which will never give all FFs, unless PCI read + * cannot go through. + */ +int +xge_hal_device_is_slot_freeze(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u16 device_id; + u64 adapter_status = + xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_status); + xge_os_pci_read16(hldev->pdev,hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, device_id), + &device_id); +#ifdef TX_DEBUG + if (adapter_status == XGE_HAL_ALL_FOXES) + { + u64 dummy; + dummy = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->pcc_enable); + printf(">>> Slot is frozen!\n"); + brkpoint(0); + } +#endif + return((adapter_status == XGE_HAL_ALL_FOXES) || (device_id == 0xffff)); +} + + +/* + * __hal_device_led_actifity_fix + * @hldev: pointer to xge_hal_device_t structure + * + * SXE-002: Configure link and activity LED to turn it off + */ +static void +__hal_device_led_actifity_fix(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u16 subid; + u64 val64; + + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, subsystem_id), &subid); + + /* + * In the case of Herc, there is a new register named beacon control + * is added which was not present in Xena. + * Beacon control register in Herc is at the same offset as + * gpio control register in Xena. It means they are one and same in + * the case of Xena. Also, gpio control register offset in Herc and + * Xena is different. + * The current register map represents Herc(It means we have + * both beacon and gpio control registers in register map). + * WRT transition from Xena to Herc, all the code in Xena which was + * using gpio control register for LED handling would have to + * use beacon control register in Herc and the rest of the code + * which uses gpio control in Xena would use the same register + * in Herc. + * WRT LED handling(following code), In the case of Herc, beacon + * control register has to be used. This is applicable for Xena also, + * since it represents the gpio control register in Xena. + */ + if ((subid & 0xFF) >= 0x07) { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->beacon_control); + val64 |= 0x0000800000000000ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->beacon_control); + val64 = 0x0411040400000000ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + (void *) ((u8 *)bar0 + 0x2700)); + } +} + +/* Constants for Fixing the MacAddress problem seen mostly on + * Alpha machines. + */ +static u64 xena_fix_mac[] = { + 0x0060000000000000ULL, 0x0060600000000000ULL, + 0x0040600000000000ULL, 0x0000600000000000ULL, + 0x0020600000000000ULL, 0x0060600000000000ULL, + 0x0020600000000000ULL, 0x0060600000000000ULL, + 0x0020600000000000ULL, 0x0060600000000000ULL, + 0x0020600000000000ULL, 0x0060600000000000ULL, + 0x0020600000000000ULL, 0x0060600000000000ULL, + 0x0020600000000000ULL, 0x0060600000000000ULL, + 0x0020600000000000ULL, 0x0060600000000000ULL, + 0x0020600000000000ULL, 0x0060600000000000ULL, + 0x0020600000000000ULL, 0x0060600000000000ULL, + 0x0020600000000000ULL, 0x0060600000000000ULL, + 0x0020600000000000ULL, 0x0000600000000000ULL, + 0x0040600000000000ULL, 0x0060600000000000ULL, + END_SIGN +}; + +/* + * __hal_device_fix_mac + * @hldev: HAL device handle. + * + * Fix for all "FFs" MAC address problems observed on Alpha platforms. + */ +static void +__hal_device_xena_fix_mac(xge_hal_device_t *hldev) +{ + int i = 0; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + + /* + * In the case of Herc, there is a new register named beacon control + * is added which was not present in Xena. + * Beacon control register in Herc is at the same offset as + * gpio control register in Xena. It means they are one and same in + * the case of Xena. Also, gpio control register offset in Herc and + * Xena is different. + * The current register map represents Herc(It means we have + * both beacon and gpio control registers in register map). + * WRT transition from Xena to Herc, all the code in Xena which was + * using gpio control register for LED handling would have to + * use beacon control register in Herc and the rest of the code + * which uses gpio control in Xena would use the same register + * in Herc. + * In the following code(xena_fix_mac), beacon control register has + * to be used in the case of Xena, since it represents gpio control + * register. In the case of Herc, there is no change required. + */ + while (xena_fix_mac[i] != END_SIGN) { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + xena_fix_mac[i++], &bar0->beacon_control); + xge_os_mdelay(1); + } +} + +/* + * xge_hal_device_bcast_enable + * @hldev: HAL device handle. + * + * Enable receiving broadcasts. + * The host must first write RMAC_CFG_KEY "key" + * register, and then - MAC_CFG register. + */ +void +xge_hal_device_bcast_enable(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mac_cfg); + val64 |= XGE_HAL_MAC_RMAC_BCAST_ENABLE; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); + + __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, + (u32)(val64 >> 32), &bar0->mac_cfg); + + xge_debug_device(XGE_TRACE, "mac_cfg 0x"XGE_OS_LLXFMT": broadcast %s", + (unsigned long long)val64, + hldev->config.mac.rmac_bcast_en ? "enabled" : "disabled"); +} + +/* + * xge_hal_device_bcast_disable + * @hldev: HAL device handle. + * + * Disable receiving broadcasts. + * The host must first write RMAC_CFG_KEY "key" + * register, and then - MAC_CFG register. + */ +void +xge_hal_device_bcast_disable(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mac_cfg); + + val64 &= ~(XGE_HAL_MAC_RMAC_BCAST_ENABLE); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); + + __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, + (u32)(val64 >> 32), &bar0->mac_cfg); + + xge_debug_device(XGE_TRACE, "mac_cfg 0x"XGE_OS_LLXFMT": broadcast %s", + (unsigned long long)val64, + hldev->config.mac.rmac_bcast_en ? "enabled" : "disabled"); +} + +/* + * __hal_device_shared_splits_configure + * @hldev: HAL device handle. + * + * TxDMA will stop Read request if the number of read split had exceeded + * the limit set by shared_splits + */ +static void +__hal_device_shared_splits_configure(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->pic_control); + val64 |= + XGE_HAL_PIC_CNTL_SHARED_SPLITS(hldev->config.shared_splits); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->pic_control); + xge_debug_device(XGE_TRACE, "%s", "shared splits configured"); +} + +/* + * __hal_device_rmac_padding_configure + * @hldev: HAL device handle. + * + * Configure RMAC frame padding. Depends on configuration, it + * can be send to host or removed by MAC. + */ +static void +__hal_device_rmac_padding_configure(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mac_cfg); + val64 &= ( ~XGE_HAL_MAC_RMAC_ALL_ADDR_ENABLE ); + val64 &= ( ~XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE ); + val64 |= XGE_HAL_MAC_CFG_TMAC_APPEND_PAD; + + /* + * If the RTH enable bit is not set, strip the FCS + */ + if (!hldev->config.rth_en || + !(xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rts_rth_cfg) & XGE_HAL_RTS_RTH_EN)) { + val64 |= XGE_HAL_MAC_CFG_RMAC_STRIP_FCS; + } + + val64 &= ( ~XGE_HAL_MAC_CFG_RMAC_STRIP_PAD ); + val64 |= XGE_HAL_MAC_RMAC_DISCARD_PFRM; + + __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, + (u32)(val64 >> 32), (char*)&bar0->mac_cfg); + xge_os_mdelay(1); + + xge_debug_device(XGE_TRACE, + "mac_cfg 0x"XGE_OS_LLXFMT": frame padding configured", + (unsigned long long)val64); +} + +/* + * __hal_device_pause_frames_configure + * @hldev: HAL device handle. + * + * Set Pause threshold. + * + * Pause frame is generated if the amount of data outstanding + * on any queue exceeded the ratio of + * (mac_control.mc_pause_threshold_q0q3 or q4q7)/256 + */ +static void +__hal_device_pause_frames_configure(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + int i; + u64 val64; + + switch (hldev->config.mac.media) { + case XGE_HAL_MEDIA_SR: + case XGE_HAL_MEDIA_SW: + val64=0xfffbfffbfffbfffbULL; + break; + case XGE_HAL_MEDIA_LR: + case XGE_HAL_MEDIA_LW: + val64=0xffbbffbbffbbffbbULL; + break; + case XGE_HAL_MEDIA_ER: + case XGE_HAL_MEDIA_EW: + default: + val64=0xffbbffbbffbbffbbULL; + break; + } + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->mc_pause_thresh_q0q3); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->mc_pause_thresh_q4q7); + + /* Set the time value to be inserted in the pause frame generated + * by Xframe */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rmac_pause_cfg); + if (hldev->config.mac.rmac_pause_gen_en) + val64 |= XGE_HAL_RMAC_PAUSE_GEN_EN; + else + val64 &= ~(XGE_HAL_RMAC_PAUSE_GEN_EN); + if (hldev->config.mac.rmac_pause_rcv_en) + val64 |= XGE_HAL_RMAC_PAUSE_RCV_EN; + else + val64 &= ~(XGE_HAL_RMAC_PAUSE_RCV_EN); + val64 &= ~(XGE_HAL_RMAC_PAUSE_HG_PTIME(0xffff)); + val64 |= XGE_HAL_RMAC_PAUSE_HG_PTIME(hldev->config.mac.rmac_pause_time); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rmac_pause_cfg); + + val64 = 0; + for (i = 0; i<4; i++) { + val64 |= + (((u64)0xFF00|hldev->config.mac.mc_pause_threshold_q0q3) + <<(i*2*8)); + } + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mc_pause_thresh_q0q3); + + val64 = 0; + for (i = 0; i<4; i++) { + val64 |= + (((u64)0xFF00|hldev->config.mac.mc_pause_threshold_q4q7) + <<(i*2*8)); + } + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mc_pause_thresh_q4q7); + xge_debug_device(XGE_TRACE, "%s", "pause frames configured"); +} + +/* + * Herc's clock rate doubled, unless the slot is 33MHz. + */ +unsigned int __hal_fix_time_ival_herc(xge_hal_device_t *hldev, + unsigned int time_ival) +{ + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) + return time_ival; + + xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC); + + if (hldev->bus_frequency != XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN && + hldev->bus_frequency != XGE_HAL_PCI_BUS_FREQUENCY_33MHZ) + time_ival *= 2; + + return time_ival; +} + + +/* + * __hal_device_bus_master_disable + * @hldev: HAL device handle. + * + * Disable bus mastership. + */ +static void +__hal_device_bus_master_disable (xge_hal_device_t *hldev) +{ + u16 cmd; + u16 bus_master = 4; + + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, command), &cmd); + cmd &= ~bus_master; + xge_os_pci_write16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, command), cmd); +} + +/* + * __hal_device_bus_master_enable + * @hldev: HAL device handle. + * + * Disable bus mastership. + */ +static void +__hal_device_bus_master_enable (xge_hal_device_t *hldev) +{ + u16 cmd; + u16 bus_master = 4; + + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, command), &cmd); + + /* already enabled? do nothing */ + if (cmd & bus_master) + return; + + cmd |= bus_master; + xge_os_pci_write16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, command), cmd); +} +/* + * __hal_device_intr_mgmt + * @hldev: HAL device handle. + * @mask: mask indicating which Intr block must be modified. + * @flag: if true - enable, otherwise - disable interrupts. + * + * Disable or enable device interrupts. Mask is used to specify + * which hardware blocks should produce interrupts. For details + * please refer to Xframe User Guide. + */ +static void +__hal_device_intr_mgmt(xge_hal_device_t *hldev, u64 mask, int flag) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64 = 0, temp64 = 0; + u64 gim, gim_saved; + + gim_saved = gim = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->general_int_mask); + + /* Top level interrupt classification */ + /* PIC Interrupts */ + if ((mask & (XGE_HAL_TX_PIC_INTR/* | XGE_HAL_RX_PIC_INTR*/))) { + /* Enable PIC Intrs in the general intr mask register */ + val64 = XGE_HAL_TXPIC_INT_M/* | XGE_HAL_PIC_RX_INT_M*/; + if (flag) { + gim &= ~((u64) val64); + temp64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->pic_int_mask); + + temp64 &= ~XGE_HAL_PIC_INT_TX; +#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR + if (xge_hal_device_check_id(hldev) == + XGE_HAL_CARD_HERC) { + temp64 &= ~XGE_HAL_PIC_INT_MISC; + } +#endif + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + temp64, &bar0->pic_int_mask); +#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR + if (xge_hal_device_check_id(hldev) == + XGE_HAL_CARD_HERC) { + /* + * Unmask only Link Up interrupt + */ + temp64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->misc_int_mask); + temp64 &= ~XGE_HAL_MISC_INT_REG_LINK_UP_INT; + xge_os_pio_mem_write64(hldev->pdev, + hldev->regh0, temp64, + &bar0->misc_int_mask); + xge_debug_device(XGE_TRACE, + "unmask link up flag "XGE_OS_LLXFMT, + (unsigned long long)temp64); + } +#endif + } else { /* flag == 0 */ + +#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR + if (xge_hal_device_check_id(hldev) == + XGE_HAL_CARD_HERC) { + /* + * Mask both Link Up and Down interrupts + */ + temp64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->misc_int_mask); + temp64 |= XGE_HAL_MISC_INT_REG_LINK_UP_INT; + temp64 |= XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; + xge_os_pio_mem_write64(hldev->pdev, + hldev->regh0, temp64, + &bar0->misc_int_mask); + xge_debug_device(XGE_TRACE, + "mask link up/down flag "XGE_OS_LLXFMT, + (unsigned long long)temp64); + } +#endif + /* Disable PIC Intrs in the general intr mask + * register */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, + &bar0->pic_int_mask); + gim |= val64; + } + } + + /* DMA Interrupts */ + /* Enabling/Disabling Tx DMA interrupts */ + if (mask & XGE_HAL_TX_DMA_INTR) { + /* Enable TxDMA Intrs in the general intr mask register */ + val64 = XGE_HAL_TXDMA_INT_M; + if (flag) { + gim &= ~((u64) val64); + /* Enable all TxDMA interrupts */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0x0, &bar0->txdma_int_mask); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0x0, &bar0->pfc_err_mask); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0x0, &bar0->tda_err_mask); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0x0, &bar0->pcc_err_mask); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0x0, &bar0->tti_err_mask); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0x0, &bar0->lso_err_mask); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0x0, &bar0->tpa_err_mask); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0x0, &bar0->sm_err_mask); + + } else { /* flag == 0 */ + + /* Disable TxDMA Intrs in the general intr mask + * register */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, + &bar0->txdma_int_mask); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, + &bar0->pfc_err_mask); + + gim |= val64; + } + } + + /* Enabling/Disabling Rx DMA interrupts */ + if (mask & XGE_HAL_RX_DMA_INTR) { + /* Enable RxDMA Intrs in the general intr mask register */ + val64 = XGE_HAL_RXDMA_INT_M; + if (flag) { + + gim &= ~((u64) val64); + /* All RxDMA block interrupts are disabled for now + * TODO */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, + &bar0->rxdma_int_mask); + + } else { /* flag == 0 */ + + /* Disable RxDMA Intrs in the general intr mask + * register */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, + &bar0->rxdma_int_mask); + + gim |= val64; + } + } + + /* MAC Interrupts */ + /* Enabling/Disabling MAC interrupts */ + if (mask & (XGE_HAL_TX_MAC_INTR | XGE_HAL_RX_MAC_INTR)) { + val64 = XGE_HAL_TXMAC_INT_M | XGE_HAL_RXMAC_INT_M; + if (flag) { + + gim &= ~((u64) val64); + + /* All MAC block error inter. are disabled for now. */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, &bar0->mac_int_mask); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, &bar0->mac_rmac_err_mask); + + } else { /* flag == 0 */ + + /* Disable MAC Intrs in the general intr mask + * register */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, &bar0->mac_int_mask); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, &bar0->mac_rmac_err_mask); + + gim |= val64; + } + } + + /* XGXS Interrupts */ + if (mask & (XGE_HAL_TX_XGXS_INTR | XGE_HAL_RX_XGXS_INTR)) { + val64 = XGE_HAL_TXXGXS_INT_M | XGE_HAL_RXXGXS_INT_M; + if (flag) { + + gim &= ~((u64) val64); + /* All XGXS block error interrupts are disabled for now + * TODO */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, &bar0->xgxs_int_mask); + + } else { /* flag == 0 */ + + /* Disable MC Intrs in the general intr mask register */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, &bar0->xgxs_int_mask); + + gim |= val64; + } + } + + /* Memory Controller(MC) interrupts */ + if (mask & XGE_HAL_MC_INTR) { + val64 = XGE_HAL_MC_INT_M; + if (flag) { + + gim &= ~((u64) val64); + + /* Enable all MC blocks error interrupts */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0x0ULL, &bar0->mc_int_mask); + + } else { /* flag == 0 */ + + /* Disable MC Intrs in the general intr mask + * register */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, &bar0->mc_int_mask); + + gim |= val64; + } + } + + + /* Tx traffic interrupts */ + if (mask & XGE_HAL_TX_TRAFFIC_INTR) { + val64 = XGE_HAL_TXTRAFFIC_INT_M; + if (flag) { + + gim &= ~((u64) val64); + + /* Enable all the Tx side interrupts */ + /* '0' Enables all 64 TX interrupt levels. */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x0, + &bar0->tx_traffic_mask); + + } else { /* flag == 0 */ + + /* Disable Tx Traffic Intrs in the general intr mask + * register. */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, + &bar0->tx_traffic_mask); + gim |= val64; + } + } + + /* Rx traffic interrupts */ + if (mask & XGE_HAL_RX_TRAFFIC_INTR) { + val64 = XGE_HAL_RXTRAFFIC_INT_M; + if (flag) { + gim &= ~((u64) val64); + /* '0' Enables all 8 RX interrupt levels. */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x0, + &bar0->rx_traffic_mask); + + } else { /* flag == 0 */ + + /* Disable Rx Traffic Intrs in the general intr mask + * register. + */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_ALL_INTRS_DIS, + &bar0->rx_traffic_mask); + + gim |= val64; + } + } + + /* Sched Timer interrupt */ + if (mask & XGE_HAL_SCHED_INTR) { + if (flag) { + temp64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->txpic_int_mask); + temp64 &= ~XGE_HAL_TXPIC_INT_SCHED_INTR; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + temp64, &bar0->txpic_int_mask); + + xge_hal_device_sched_timer(hldev, + hldev->config.sched_timer_us, + hldev->config.sched_timer_one_shot); + } else { + temp64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->txpic_int_mask); + temp64 |= XGE_HAL_TXPIC_INT_SCHED_INTR; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + temp64, &bar0->txpic_int_mask); + + xge_hal_device_sched_timer(hldev, + XGE_HAL_SCHED_TIMER_DISABLED, + XGE_HAL_SCHED_TIMER_ON_SHOT_ENABLE); + } + } + + if (gim != gim_saved) { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, gim, + &bar0->general_int_mask); + xge_debug_device(XGE_TRACE, "general_int_mask updated " + XGE_OS_LLXFMT" => "XGE_OS_LLXFMT, + (unsigned long long)gim_saved, (unsigned long long)gim); + } +} + +/* + * __hal_device_bimodal_configure + * @hldev: HAL device handle. + * + * Bimodal parameters initialization. + */ +static void +__hal_device_bimodal_configure(xge_hal_device_t *hldev) +{ + int i; + + for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) { + xge_hal_tti_config_t *tti; + xge_hal_rti_config_t *rti; + + if (!hldev->config.ring.queue[i].configured) + continue; + rti = &hldev->config.ring.queue[i].rti; + tti = &hldev->bimodal_tti[i]; + + tti->enabled = 1; + tti->urange_a = hldev->bimodal_urange_a_en * 10; + tti->urange_b = 20; + tti->urange_c = 30; + tti->ufc_a = hldev->bimodal_urange_a_en * 8; + tti->ufc_b = 16; + tti->ufc_c = 32; + tti->ufc_d = 64; + tti->timer_val_us = hldev->bimodal_timer_val_us; + tti->timer_ac_en = 1; + tti->timer_ci_en = 0; + + rti->urange_a = 10; + rti->urange_b = 20; + rti->urange_c = 30; + rti->ufc_a = 1; /* <= for netpipe type of tests */ + rti->ufc_b = 4; + rti->ufc_c = 4; + rti->ufc_d = 4; /* <= 99% of a bandwidth traffic counts here */ + rti->timer_ac_en = 1; + rti->timer_val_us = 5; /* for optimal bus efficiency usage */ + } +} + +/* + * __hal_device_tti_apply + * @hldev: HAL device handle. + * + * apply TTI configuration. + */ +static xge_hal_status_e +__hal_device_tti_apply(xge_hal_device_t *hldev, xge_hal_tti_config_t *tti, + int num, int runtime) +{ + u64 val64, data1 = 0, data2 = 0; + xge_hal_pci_bar0_t *bar0; + + if (runtime) + bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; + else + bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + + if (tti->timer_val_us) { + unsigned int tx_interval; + + if (hldev->config.pci_freq_mherz) { + tx_interval = hldev->config.pci_freq_mherz * + tti->timer_val_us / 64; + tx_interval = + __hal_fix_time_ival_herc(hldev, + tx_interval); + } else { + tx_interval = tti->timer_val_us; + } + data1 |= XGE_HAL_TTI_DATA1_MEM_TX_TIMER_VAL(tx_interval); + if (tti->timer_ac_en) { + data1 |= XGE_HAL_TTI_DATA1_MEM_TX_TIMER_AC_EN; + } + if (tti->timer_ci_en) { + data1 |= XGE_HAL_TTI_DATA1_MEM_TX_TIMER_CI_EN; + } + + if (!runtime) { + xge_debug_device(XGE_TRACE, "TTI[%d] timer enabled to %d, ci %s", + num, tx_interval, tti->timer_ci_en ? + "enabled": "disabled"); + } + } + + if (tti->urange_a || + tti->urange_b || + tti->urange_c || + tti->ufc_a || + tti->ufc_b || + tti->ufc_c || + tti->ufc_d ) { + data1 |= XGE_HAL_TTI_DATA1_MEM_TX_URNG_A(tti->urange_a) | + XGE_HAL_TTI_DATA1_MEM_TX_URNG_B(tti->urange_b) | + XGE_HAL_TTI_DATA1_MEM_TX_URNG_C(tti->urange_c); + + data2 |= XGE_HAL_TTI_DATA2_MEM_TX_UFC_A(tti->ufc_a) | + XGE_HAL_TTI_DATA2_MEM_TX_UFC_B(tti->ufc_b) | + XGE_HAL_TTI_DATA2_MEM_TX_UFC_C(tti->ufc_c) | + XGE_HAL_TTI_DATA2_MEM_TX_UFC_D(tti->ufc_d); + } + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, data1, + &bar0->tti_data1_mem); + (void)xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->tti_data1_mem); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, data2, + &bar0->tti_data2_mem); + (void)xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->tti_data2_mem); + xge_os_wmb(); + + val64 = XGE_HAL_TTI_CMD_MEM_WE | XGE_HAL_TTI_CMD_MEM_STROBE_NEW_CMD | + XGE_HAL_TTI_CMD_MEM_OFFSET(num); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->tti_command_mem); + + if (!runtime && __hal_device_register_poll(hldev, &bar0->tti_command_mem, + 0, XGE_HAL_TTI_CMD_MEM_STROBE_NEW_CMD, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + /* upper layer may require to repeat */ + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + + if (!runtime) { + xge_debug_device(XGE_TRACE, "TTI[%d] configured: tti_data1_mem 0x" + XGE_OS_LLXFMT, num, + (unsigned long long)xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->tti_data1_mem)); + } + + return XGE_HAL_OK; +} + +/* + * __hal_device_tti_configure + * @hldev: HAL device handle. + * + * TTI Initialization. + * Initialize Transmit Traffic Interrupt Scheme. + */ +static xge_hal_status_e +__hal_device_tti_configure(xge_hal_device_t *hldev, int runtime) +{ + int i; + + for (i=0; i<XGE_HAL_MAX_FIFO_NUM; i++) { + int j; + + if (!hldev->config.fifo.queue[i].configured) + continue; + + for (j=0; j<XGE_HAL_MAX_FIFO_TTI_NUM; j++) { + xge_hal_status_e status; + + if (!hldev->config.fifo.queue[i].tti[j].enabled) + continue; + + /* at least some TTI enabled. Record it. */ + hldev->tti_enabled = 1; + + status = __hal_device_tti_apply(hldev, + &hldev->config.fifo.queue[i].tti[j], + i * XGE_HAL_MAX_FIFO_TTI_NUM + j, runtime); + if (status != XGE_HAL_OK) + return status; + } + } + + /* processing bimodal TTIs */ + for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) { + xge_hal_status_e status; + + if (!hldev->bimodal_tti[i].enabled) + continue; + + /* at least some bimodal TTI enabled. Record it. */ + hldev->tti_enabled = 1; + + status = __hal_device_tti_apply(hldev, &hldev->bimodal_tti[i], + XGE_HAL_MAX_FIFO_TTI_RING_0 + i, runtime); + if (status != XGE_HAL_OK) + return status; + + } + + return XGE_HAL_OK; +} + +/* + * __hal_device_rti_configure + * @hldev: HAL device handle. + * + * RTI Initialization. + * Initialize Receive Traffic Interrupt Scheme. + */ +xge_hal_status_e +__hal_device_rti_configure(xge_hal_device_t *hldev, int runtime) +{ + xge_hal_pci_bar0_t *bar0; + u64 val64, data1 = 0, data2 = 0; + int i; + + if (runtime) { + /* + * we don't want to re-configure RTI in case when + * bimodal interrupts are in use. Instead reconfigure TTI + * with new RTI values. + */ + if (hldev->config.bimodal_interrupts) { + __hal_device_bimodal_configure(hldev); + return __hal_device_tti_configure(hldev, 1); + } + bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; + } else + bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + + for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) { + xge_hal_rti_config_t *rti = &hldev->config.ring.queue[i].rti; + + if (!hldev->config.ring.queue[i].configured) + continue; + + if (rti->timer_val_us) { + unsigned int rx_interval; + + if (hldev->config.pci_freq_mherz) { + rx_interval = hldev->config.pci_freq_mherz * + rti->timer_val_us / 8; + rx_interval = + __hal_fix_time_ival_herc(hldev, + rx_interval); + } else { + rx_interval = rti->timer_val_us; + } + data1 |=XGE_HAL_RTI_DATA1_MEM_RX_TIMER_VAL(rx_interval); + if (rti->timer_ac_en) { + data1 |= XGE_HAL_RTI_DATA1_MEM_RX_TIMER_AC_EN; + } + data1 |= XGE_HAL_RTI_DATA1_MEM_RX_TIMER_CI_EN; + } + + if (rti->urange_a || + rti->urange_b || + rti->urange_c || + rti->ufc_a || + rti->ufc_b || + rti->ufc_c || + rti->ufc_d) { + data1 |=XGE_HAL_RTI_DATA1_MEM_RX_URNG_A(rti->urange_a) | + XGE_HAL_RTI_DATA1_MEM_RX_URNG_B(rti->urange_b) | + XGE_HAL_RTI_DATA1_MEM_RX_URNG_C(rti->urange_c); + + data2 |= XGE_HAL_RTI_DATA2_MEM_RX_UFC_A(rti->ufc_a) | + XGE_HAL_RTI_DATA2_MEM_RX_UFC_B(rti->ufc_b) | + XGE_HAL_RTI_DATA2_MEM_RX_UFC_C(rti->ufc_c) | + XGE_HAL_RTI_DATA2_MEM_RX_UFC_D(rti->ufc_d); + } + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, data1, + &bar0->rti_data1_mem); + (void)xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->rti_data1_mem); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, data2, + &bar0->rti_data2_mem); + (void)xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->rti_data2_mem); + xge_os_wmb(); + + val64 = XGE_HAL_RTI_CMD_MEM_WE | + XGE_HAL_RTI_CMD_MEM_STROBE_NEW_CMD; + val64 |= XGE_HAL_RTI_CMD_MEM_OFFSET(i); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rti_command_mem); + + if (!runtime && __hal_device_register_poll(hldev, + &bar0->rti_command_mem, 0, + XGE_HAL_RTI_CMD_MEM_STROBE_NEW_CMD, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + /* upper layer may require to repeat */ + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + + if (!runtime) { + xge_debug_device(XGE_TRACE, + "RTI[%d] configured: rti_data1_mem 0x"XGE_OS_LLXFMT, + i, + (unsigned long long)xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->rti_data1_mem)); + } + } + + return XGE_HAL_OK; +} + + +/* Constants to be programmed into the Xena's registers to configure + * the XAUI. */ +static u64 default_xena_mdio_cfg[] = { + /* Reset PMA PLL */ + 0xC001010000000000ULL, 0xC0010100000000E0ULL, + 0xC0010100008000E4ULL, + /* Remove Reset from PMA PLL */ + 0xC001010000000000ULL, 0xC0010100000000E0ULL, + 0xC0010100000000E4ULL, + END_SIGN +}; + +static u64 default_herc_mdio_cfg[] = { + END_SIGN +}; + +static u64 default_xena_dtx_cfg[] = { + 0x8000051500000000ULL, 0x80000515000000E0ULL, + 0x80000515D93500E4ULL, 0x8001051500000000ULL, + 0x80010515000000E0ULL, 0x80010515001E00E4ULL, + 0x8002051500000000ULL, 0x80020515000000E0ULL, + 0x80020515F21000E4ULL, + /* Set PADLOOPBACKN */ + 0x8002051500000000ULL, 0x80020515000000E0ULL, + 0x80020515B20000E4ULL, 0x8003051500000000ULL, + 0x80030515000000E0ULL, 0x80030515B20000E4ULL, + 0x8004051500000000ULL, 0x80040515000000E0ULL, + 0x80040515B20000E4ULL, 0x8005051500000000ULL, + 0x80050515000000E0ULL, 0x80050515B20000E4ULL, + SWITCH_SIGN, + /* Remove PADLOOPBACKN */ + 0x8002051500000000ULL, 0x80020515000000E0ULL, + 0x80020515F20000E4ULL, 0x8003051500000000ULL, + 0x80030515000000E0ULL, 0x80030515F20000E4ULL, + 0x8004051500000000ULL, 0x80040515000000E0ULL, + 0x80040515F20000E4ULL, 0x8005051500000000ULL, + 0x80050515000000E0ULL, 0x80050515F20000E4ULL, + END_SIGN +}; + +/* +static u64 default_herc_dtx_cfg[] = { + 0x80000515BA750000ULL, 0x80000515BA7500E0ULL, + 0x80000515BA750004ULL, 0x80000515BA7500E4ULL, + 0x80010515003F0000ULL, 0x80010515003F00E0ULL, + 0x80010515003F0004ULL, 0x80010515003F00E4ULL, + 0x80020515F2100000ULL, 0x80020515F21000E0ULL, + 0x80020515F2100004ULL, 0x80020515F21000E4ULL, + END_SIGN +}; +*/ + +static u64 default_herc_dtx_cfg[] = { + 0x8000051536750000ULL, 0x80000515367500E0ULL, + 0x8000051536750004ULL, 0x80000515367500E4ULL, + + 0x80010515003F0000ULL, 0x80010515003F00E0ULL, + 0x80010515003F0004ULL, 0x80010515003F00E4ULL, + + 0x801205150D440000ULL, 0x801205150D4400E0ULL, + 0x801205150D440004ULL, 0x801205150D4400E4ULL, + + 0x80020515F2100000ULL, 0x80020515F21000E0ULL, + 0x80020515F2100004ULL, 0x80020515F21000E4ULL, + END_SIGN +}; + + +void +__hal_serial_mem_write64(xge_hal_device_t *hldev, u64 value, u64 *reg) +{ + __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, + (u32)(value>>32), reg); + xge_os_wmb(); + __hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, + (u32)value, reg); + xge_os_wmb(); + xge_os_mdelay(1); +} + +u64 +__hal_serial_mem_read64(xge_hal_device_t *hldev, u64 *reg) +{ + u64 val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + reg); + xge_os_mdelay(1); + return val64; +} + +/* + * __hal_device_xaui_configure + * @hldev: HAL device handle. + * + * Configure XAUI Interface of Xena. + * + * To Configure the Xena's XAUI, one has to write a series + * of 64 bit values into two registers in a particular + * sequence. Hence a macro 'SWITCH_SIGN' has been defined + * which will be defined in the array of configuration values + * (default_dtx_cfg & default_mdio_cfg) at appropriate places + * to switch writing from one regsiter to another. We continue + * writing these values until we encounter the 'END_SIGN' macro. + * For example, After making a series of 21 writes into + * dtx_control register the 'SWITCH_SIGN' appears and hence we + * start writing into mdio_control until we encounter END_SIGN. + */ +static void +__hal_device_xaui_configure(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + int mdio_cnt = 0, dtx_cnt = 0; + u64 *default_dtx_cfg = NULL, *default_mdio_cfg = NULL; + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { + default_dtx_cfg = default_xena_dtx_cfg; + default_mdio_cfg = default_xena_mdio_cfg; + } else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + default_dtx_cfg = default_herc_dtx_cfg; + default_mdio_cfg = default_herc_mdio_cfg; + } else { + xge_assert(default_dtx_cfg); + return; + } + + do { + dtx_cfg: + while (default_dtx_cfg[dtx_cnt] != END_SIGN) { + if (default_dtx_cfg[dtx_cnt] == SWITCH_SIGN) { + dtx_cnt++; + goto mdio_cfg; + } + __hal_serial_mem_write64(hldev, default_dtx_cfg[dtx_cnt], + &bar0->dtx_control); + dtx_cnt++; + } + mdio_cfg: + while (default_mdio_cfg[mdio_cnt] != END_SIGN) { + if (default_mdio_cfg[mdio_cnt] == SWITCH_SIGN) { + mdio_cnt++; + goto dtx_cfg; + } + __hal_serial_mem_write64(hldev, default_mdio_cfg[mdio_cnt], + &bar0->mdio_control); + mdio_cnt++; + } + } while ( !((default_dtx_cfg[dtx_cnt] == END_SIGN) && + (default_mdio_cfg[mdio_cnt] == END_SIGN)) ); + + xge_debug_device(XGE_TRACE, "%s", "XAUI interface configured"); +} + +/* + * __hal_device_mac_link_util_set + * @hldev: HAL device handle. + * + * Set sampling rate to calculate link utilization. + */ +static void +__hal_device_mac_link_util_set(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + val64 = XGE_HAL_MAC_TX_LINK_UTIL_VAL( + hldev->config.mac.tmac_util_period) | + XGE_HAL_MAC_RX_LINK_UTIL_VAL( + hldev->config.mac.rmac_util_period); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mac_link_util); + xge_debug_device(XGE_TRACE, "%s", + "bandwidth link utilization configured"); +} + +/* + * __hal_device_set_swapper + * @hldev: HAL device handle. + * + * Set the Xframe's byte "swapper" in accordance with + * endianness of the host. + */ +xge_hal_status_e +__hal_device_set_swapper(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + /* + * from 32bit errarta: + * + * The SWAPPER_CONTROL register determines how the adapter accesses + * host memory as well as how it responds to read and write requests + * from the host system. Writes to this register should be performed + * carefully, since the byte swappers could reverse the order of bytes. + * When configuring this register keep in mind that writes to the PIF + * read and write swappers could reverse the order of the upper and + * lower 32-bit words. This means that the driver may have to write + * to the upper 32 bits of the SWAPPER_CONTROL twice in order to + * configure the entire register. */ + + /* + * The device by default set to a big endian format, so a big endian + * driver need not set anything. + */ + +#if defined(XGE_HAL_CUSTOM_HW_SWAPPER) + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0xffffffffffffffffULL, &bar0->swapper_ctrl); + + val64 = XGE_HAL_CUSTOM_HW_SWAPPER; + + xge_os_wmb(); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->swapper_ctrl); + + xge_debug_device(XGE_TRACE, "using custom HW swapper 0x"XGE_OS_LLXFMT, + (unsigned long long)val64); + +#elif !defined(XGE_OS_HOST_BIG_ENDIAN) + + /* + * Initially we enable all bits to make it accessible by the driver, + * then we selectively enable only those bits that we want to set. + * i.e. force swapper to swap for the first time since second write + * will overwrite with the final settings. + * + * Use only for little endian platforms. + */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0xffffffffffffffffULL, &bar0->swapper_ctrl); + xge_os_wmb(); + val64 = (XGE_HAL_SWAPPER_CTRL_PIF_R_FE | + XGE_HAL_SWAPPER_CTRL_PIF_R_SE | + XGE_HAL_SWAPPER_CTRL_PIF_W_FE | + XGE_HAL_SWAPPER_CTRL_PIF_W_SE | + XGE_HAL_SWAPPER_CTRL_RTH_FE | + XGE_HAL_SWAPPER_CTRL_RTH_SE | + XGE_HAL_SWAPPER_CTRL_TXP_FE | + XGE_HAL_SWAPPER_CTRL_TXP_SE | + XGE_HAL_SWAPPER_CTRL_TXD_R_FE | + XGE_HAL_SWAPPER_CTRL_TXD_R_SE | + XGE_HAL_SWAPPER_CTRL_TXD_W_FE | + XGE_HAL_SWAPPER_CTRL_TXD_W_SE | + XGE_HAL_SWAPPER_CTRL_TXF_R_FE | + XGE_HAL_SWAPPER_CTRL_RXD_R_FE | + XGE_HAL_SWAPPER_CTRL_RXD_R_SE | + XGE_HAL_SWAPPER_CTRL_RXD_W_FE | + XGE_HAL_SWAPPER_CTRL_RXD_W_SE | + XGE_HAL_SWAPPER_CTRL_RXF_W_FE | + XGE_HAL_SWAPPER_CTRL_XMSI_FE | + XGE_HAL_SWAPPER_CTRL_STATS_FE | XGE_HAL_SWAPPER_CTRL_STATS_SE); + + /* + if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { + val64 |= XGE_HAL_SWAPPER_CTRL_XMSI_SE; + } */ + __hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, (u32)val64, + &bar0->swapper_ctrl); + xge_os_wmb(); + __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, (u32)(val64>>32), + &bar0->swapper_ctrl); + xge_os_wmb(); + __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, (u32)(val64>>32), + &bar0->swapper_ctrl); + xge_debug_device(XGE_TRACE, "%s", "using little endian set"); +#endif + + /* Verifying if endian settings are accurate by reading a feedback + * register. */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->pif_rd_swapper_fb); + if (val64 != XGE_HAL_IF_RD_SWAPPER_FB) { + xge_debug_device(XGE_ERR, "pif_rd_swapper_fb read "XGE_OS_LLXFMT, + (unsigned long long) val64); + return XGE_HAL_ERR_SWAPPER_CTRL; + } + + xge_debug_device(XGE_TRACE, "%s", "be/le swapper enabled"); + + return XGE_HAL_OK; +} + +/* + * __hal_device_rts_mac_configure - Configure RTS steering based on + * destination mac address. + * @hldev: HAL device handle. + * + */ +xge_hal_status_e +__hal_device_rts_mac_configure(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + if (!hldev->config.rts_mac_en) { + return XGE_HAL_OK; + } + + /* + * Set the receive traffic steering mode from default(classic) + * to enhanced. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rts_ctrl); + val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->rts_ctrl); + return XGE_HAL_OK; +} + +/* + * __hal_device_rts_port_configure - Configure RTS steering based on + * destination or source port number. + * @hldev: HAL device handle. + * + */ +xge_hal_status_e +__hal_device_rts_port_configure(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + int rnum; + + if (!hldev->config.rts_port_en) { + return XGE_HAL_OK; + } + + /* + * Set the receive traffic steering mode from default(classic) + * to enhanced. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rts_ctrl); + val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->rts_ctrl); + + /* + * Initiate port steering according to per-ring configuration + */ + for (rnum = 0; rnum < XGE_HAL_MAX_RING_NUM; rnum++) { + int pnum; + xge_hal_ring_queue_t *queue = &hldev->config.ring.queue[rnum]; + + if (!queue->configured || queue->rts_port_en) + continue; + + for (pnum = 0; pnum < XGE_HAL_MAX_STEERABLE_PORTS; pnum++) { + xge_hal_rts_port_t *port = &queue->rts_ports[pnum]; + + /* + * Skip and clear empty ports + */ + if (!port->num) { + /* + * Clear CAM memory + */ + xge_os_pio_mem_write64(hldev->pdev, + hldev->regh0, 0ULL, + &bar0->rts_pn_cam_data); + + val64 = BIT(7) | BIT(15); + } else { + /* + * Assign new Port values according + * to configuration + */ + val64 = vBIT(port->num,8,16) | + vBIT(rnum,37,3) | BIT(63); + if (port->src) + val64 = BIT(47); + if (!port->udp) + val64 = BIT(7); + xge_os_pio_mem_write64(hldev->pdev, + hldev->regh0, val64, + &bar0->rts_pn_cam_data); + + val64 = BIT(7) | BIT(15) | vBIT(pnum,24,8); + } + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->rts_pn_cam_ctrl); + + /* poll until done */ + if (__hal_device_register_poll(hldev, + &bar0->rts_pn_cam_ctrl, 0, + XGE_HAL_RTS_PN_CAM_CTRL_STROBE_BEING_EXECUTED, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != + XGE_HAL_OK) { + /* upper layer may require to repeat */ + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + } + } + return XGE_HAL_OK; +} + +/* + * __hal_device_rts_qos_configure - Configure RTS steering based on + * qos. + * @hldev: HAL device handle. + * + */ +xge_hal_status_e +__hal_device_rts_qos_configure(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + int j, rx_ring_num; + + if (!hldev->config.rts_qos_en) { + return XGE_HAL_OK; + } + + /* First clear the RTS_DS_MEM_DATA */ + val64 = 0; + for (j = 0; j < 64; j++ ) + { + /* First clear the value */ + val64 = XGE_HAL_RTS_DS_MEM_DATA(0); + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_ds_mem_data); + + val64 = XGE_HAL_RTS_DS_MEM_CTRL_WE | + XGE_HAL_RTS_DS_MEM_CTRL_STROBE_NEW_CMD | + XGE_HAL_RTS_DS_MEM_CTRL_OFFSET ( j ); + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_ds_mem_ctrl); + + + /* poll until done */ + if (__hal_device_register_poll(hldev, + &bar0->rts_ds_mem_ctrl, 0, + XGE_HAL_RTS_DS_MEM_CTRL_STROBE_CMD_BEING_EXECUTED, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + /* upper layer may require to repeat */ + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + + } + + rx_ring_num = 0; + for (j = 0; j < XGE_HAL_MAX_RING_NUM; j++) { + if (hldev->config.ring.queue[j].configured) + rx_ring_num++; + } + + switch (rx_ring_num) { + case 1: + val64 = 0x0; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); + break; + case 2: + val64 = 0x0001000100010001ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); + val64 = 0x0001000100000000ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); + break; + case 3: + val64 = 0x0001020001020001ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); + val64 = 0x0200010200010200ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); + val64 = 0x0102000102000102ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); + val64 = 0x0001020001020001ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); + val64 = 0x0200010200000000ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); + break; + case 4: + val64 = 0x0001020300010203ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); + val64 = 0x0001020300000000ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); + break; + case 5: + val64 = 0x0001020304000102ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); + val64 = 0x0304000102030400ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); + val64 = 0x0102030400010203ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); + val64 = 0x0400010203040001ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); + val64 = 0x0203040000000000ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); + break; + case 6: + val64 = 0x0001020304050001ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); + val64 = 0x0203040500010203ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); + val64 = 0x0405000102030405ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); + val64 = 0x0001020304050001ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); + val64 = 0x0203040500000000ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); + break; + case 7: + val64 = 0x0001020304050600ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); + val64 = 0x0102030405060001ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); + val64 = 0x0203040506000102ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); + val64 = 0x0304050600010203ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); + val64 = 0x0405060000000000ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); + break; + case 8: + val64 = 0x0001020304050607ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); + val64 = 0x0001020300000000ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); + break; + } + + return XGE_HAL_OK; +} + +/* + * xge__hal_device_rts_mac_enable + * + * @devh: HAL device handle. + * @index: index number where the MAC addr will be stored + * @macaddr: MAC address + * + * - Enable RTS steering for the given MAC address. This function has to be + * called with lock acquired. + * + * NOTE: + * 1. ULD has to call this function with the index value which + * statisfies the following condition: + * ring_num = (index % 8) + * 2.ULD also needs to make sure that the index is not + * occupied by any MAC address. If that index has any MAC address + * it will be overwritten and HAL will not check for it. + * + */ +xge_hal_status_e +xge_hal_device_rts_mac_enable(xge_hal_device_h devh, int index, macaddr_t macaddr) +{ + int max_addr = XGE_HAL_MAX_MAC_ADDRESSES; + xge_hal_status_e status; + + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) + max_addr = XGE_HAL_MAX_MAC_ADDRESSES_HERC; + + if ( index >= max_addr ) + return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; + + /* + * Set the MAC address at the given location marked by index. + */ + status = xge_hal_device_macaddr_set(hldev, index, macaddr); + if (status != XGE_HAL_OK) { + xge_debug_device(XGE_ERR, "%s", + "Not able to set the mac addr"); + return status; + } + + return xge_hal_device_rts_section_enable(hldev, index); +} + +/* + * xge__hal_device_rts_mac_disable + * @hldev: HAL device handle. + * @index: index number where to disable the MAC addr + * + * Disable RTS Steering based on the MAC address. + * This function should be called with lock acquired. + * + */ +xge_hal_status_e +xge_hal_device_rts_mac_disable(xge_hal_device_h devh, int index) +{ + xge_hal_status_e status; + u8 macaddr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + int max_addr = XGE_HAL_MAX_MAC_ADDRESSES; + + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + + xge_debug_ll(XGE_TRACE, "the index value is %d ", index); + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) + max_addr = XGE_HAL_MAX_MAC_ADDRESSES_HERC; + + if ( index >= max_addr ) + return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; + + /* + * Disable MAC address @ given index location + */ + status = xge_hal_device_macaddr_set(hldev, index, macaddr); + if (status != XGE_HAL_OK) { + xge_debug_device(XGE_ERR, "%s", + "Not able to set the mac addr"); + return status; + } + + return XGE_HAL_OK; +} + + +/* + * __hal_device_rth_configure - Configure RTH for the device + * @hldev: HAL device handle. + * + * Using IT (Indirection Table). + */ +xge_hal_status_e +__hal_device_rth_it_configure(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + int rings[XGE_HAL_MAX_RING_NUM]={0}; + int rnum; + int rmax; + int buckets_num; + int bucket; + + if (!hldev->config.rth_en) { + return XGE_HAL_OK; + } + + /* + * Set the receive traffic steering mode from default(classic) + * to enhanced. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rts_ctrl); + val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->rts_ctrl); + + buckets_num = (1 << hldev->config.rth_bucket_size); + + rmax=0; + for (rnum = 0; rnum < XGE_HAL_MAX_RING_NUM; rnum++) { + if (hldev->config.ring.queue[rnum].configured && + hldev->config.ring.queue[rnum].rth_en) + rings[rmax++] = rnum; + } + + rnum = 0; + /* for starters: fill in all the buckets with rings "equally" */ + for (bucket = 0; bucket < buckets_num; bucket++) { + + if (rnum == rmax) + rnum = 0; + + /* write data */ + val64 = XGE_HAL_RTS_RTH_MAP_MEM_DATA_ENTRY_EN | + XGE_HAL_RTS_RTH_MAP_MEM_DATA(rings[rnum]); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_rth_map_mem_data); + + /* execute */ + val64 = XGE_HAL_RTS_RTH_MAP_MEM_CTRL_WE | + XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE | + XGE_HAL_RTS_RTH_MAP_MEM_CTRL_OFFSET(bucket); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_rth_map_mem_ctrl); + + /* poll until done */ + if (__hal_device_register_poll(hldev, + &bar0->rts_rth_map_mem_ctrl, 0, + XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + + rnum++; + } + + val64 = XGE_HAL_RTS_RTH_EN; + val64 |= XGE_HAL_RTS_RTH_BUCKET_SIZE(hldev->config.rth_bucket_size); + val64 |= XGE_HAL_RTS_RTH_TCP_IPV4_EN | XGE_HAL_RTS_RTH_UDP_IPV4_EN | XGE_HAL_RTS_RTH_IPV4_EN | + XGE_HAL_RTS_RTH_TCP_IPV6_EN |XGE_HAL_RTS_RTH_UDP_IPV6_EN | XGE_HAL_RTS_RTH_IPV6_EN | + XGE_HAL_RTS_RTH_TCP_IPV6_EX_EN | XGE_HAL_RTS_RTH_UDP_IPV6_EX_EN | XGE_HAL_RTS_RTH_IPV6_EX_EN; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_rth_cfg); + + xge_debug_device(XGE_TRACE, "RTH configured, bucket_size %d", + hldev->config.rth_bucket_size); + + return XGE_HAL_OK; +} + + +/* + * __hal_spdm_entry_add - Add a new entry to the SPDM table. + * + * Add a new entry to the SPDM table + * + * This function add a new entry to the SPDM table. + * + * Note: + * This function should be called with spdm_lock. + * + * See also: xge_hal_spdm_entry_add , xge_hal_spdm_entry_remove. + */ +static xge_hal_status_e +__hal_spdm_entry_add(xge_hal_device_t *hldev, xge_hal_ipaddr_t *src_ip, + xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp, u8 is_tcp, + u8 is_ipv4, u8 tgt_queue, u32 jhash_value, u16 spdm_entry) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + u64 spdm_line_arr[8]; + u8 line_no; + + /* + * Clear the SPDM READY bit + */ + val64 = XGE_HAL_RX_PIC_INT_REG_SPDM_READY; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rxpic_int_reg); + + xge_debug_device(XGE_TRACE, + "L4 SP %x:DP %x: hash %x tgt_queue %d ", + l4_sp, l4_dp, jhash_value, tgt_queue); + + xge_os_memzero(&spdm_line_arr, sizeof(spdm_line_arr)); + + /* + * Construct the SPDM entry. + */ + spdm_line_arr[0] = vBIT(l4_sp,0,16) | + vBIT(l4_dp,16,32) | + vBIT(tgt_queue,53,3) | + vBIT(is_tcp,59,1) | + vBIT(is_ipv4,63,1); + + + if (is_ipv4) { + spdm_line_arr[1] = vBIT(src_ip->ipv4.addr,0,32) | + vBIT(dst_ip->ipv4.addr,32,32); + + } else { + xge_os_memcpy(&spdm_line_arr[1], &src_ip->ipv6.addr[0], 8); + xge_os_memcpy(&spdm_line_arr[2], &src_ip->ipv6.addr[1], 8); + xge_os_memcpy(&spdm_line_arr[3], &dst_ip->ipv6.addr[0], 8); + xge_os_memcpy(&spdm_line_arr[4], &dst_ip->ipv6.addr[1], 8); + } + + spdm_line_arr[7] = vBIT(jhash_value,0,32) | + BIT(63); /* entry enable bit */ + + /* + * Add the entry to the SPDM table + */ + for(line_no = 0; line_no < 8; line_no++) { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + spdm_line_arr[line_no], + (void *)((char *)hldev->spdm_mem_base + + (spdm_entry * 64) + + (line_no * 8))); + } + + /* + * Wait for the operation to be completed. + */ + if (__hal_device_register_poll(hldev, &bar0->rxpic_int_reg, 1, + XGE_HAL_RX_PIC_INT_REG_SPDM_READY, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + + /* + * Add this information to a local SPDM table. The purpose of + * maintaining a local SPDM table is to avoid a search in the + * adapter SPDM table for spdm entry lookup which is very costly + * in terms of time. + */ + hldev->spdm_table[spdm_entry]->in_use = 1; + xge_os_memcpy(&hldev->spdm_table[spdm_entry]->src_ip, src_ip, + sizeof(xge_hal_ipaddr_t)); + xge_os_memcpy(&hldev->spdm_table[spdm_entry]->dst_ip, dst_ip, + sizeof(xge_hal_ipaddr_t)); + hldev->spdm_table[spdm_entry]->l4_sp = l4_sp; + hldev->spdm_table[spdm_entry]->l4_dp = l4_dp; + hldev->spdm_table[spdm_entry]->is_tcp = is_tcp; + hldev->spdm_table[spdm_entry]->is_ipv4 = is_ipv4; + hldev->spdm_table[spdm_entry]->tgt_queue = tgt_queue; + hldev->spdm_table[spdm_entry]->jhash_value = jhash_value; + hldev->spdm_table[spdm_entry]->spdm_entry = spdm_entry; + + return XGE_HAL_OK; +} + +/* + * __hal_device_rth_spdm_configure - Configure RTH for the device + * @hldev: HAL device handle. + * + * Using SPDM (Socket-Pair Direct Match). + */ +xge_hal_status_e +__hal_device_rth_spdm_configure(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64; + u8 spdm_bar_num; + u32 spdm_bar_offset; + int spdm_table_size; + int i; + + if (!hldev->config.rth_spdm_en) { + return XGE_HAL_OK; + } + + /* + * Retrieve the base address of SPDM Table. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->spdm_bir_offset); + + spdm_bar_num = XGE_HAL_SPDM_PCI_BAR_NUM(val64); + spdm_bar_offset = XGE_HAL_SPDM_PCI_BAR_OFFSET(val64); + + + /* + * spdm_bar_num specifies the PCI bar num register used to + * address the memory space. spdm_bar_offset specifies the offset + * of the SPDM memory with in the bar num memory space. + */ + switch (spdm_bar_num) { + case 0: + { + hldev->spdm_mem_base = (char *)bar0 + + (spdm_bar_offset * 8); + break; + } + case 1: + { + char *bar1 = (char *)hldev->bar1; + hldev->spdm_mem_base = bar1 + (spdm_bar_offset * 8); + break; + } + default: + xge_assert(((spdm_bar_num != 0) && (spdm_bar_num != 1))); + } + + /* + * Retrieve the size of SPDM table(number of entries). + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->spdm_structure); + hldev->spdm_max_entries = XGE_HAL_SPDM_MAX_ENTRIES(val64); + + + spdm_table_size = hldev->spdm_max_entries * + sizeof(xge_hal_spdm_entry_t); + if (hldev->spdm_table == NULL) { + void *mem; + + /* + * Allocate memory to hold the copy of SPDM table. + */ + if ((hldev->spdm_table = (xge_hal_spdm_entry_t **) + xge_os_malloc( + hldev->pdev, + (sizeof(xge_hal_spdm_entry_t *) * + hldev->spdm_max_entries))) == NULL) { + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + + if ((mem = xge_os_malloc(hldev->pdev, spdm_table_size)) == NULL) + { + xge_os_free(hldev->pdev, hldev->spdm_table, + (sizeof(xge_hal_spdm_entry_t *) * + hldev->spdm_max_entries)); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + + xge_os_memzero(mem, spdm_table_size); + for (i = 0; i < hldev->spdm_max_entries; i++) { + hldev->spdm_table[i] = (xge_hal_spdm_entry_t *) + ((char *)mem + + i * sizeof(xge_hal_spdm_entry_t)); + } + xge_os_spin_lock_init(&hldev->spdm_lock, hldev->pdev); + } else { + /* + * We are here because the host driver tries to + * do a soft reset on the device. + * Since the device soft reset clears the SPDM table, copy + * the entries from the local SPDM table to the actual one. + */ + xge_os_spin_lock(&hldev->spdm_lock); + for (i = 0; i < hldev->spdm_max_entries; i++) { + xge_hal_spdm_entry_t *spdm_entry = hldev->spdm_table[i]; + + if (spdm_entry->in_use) { + if (__hal_spdm_entry_add(hldev, + &spdm_entry->src_ip, + &spdm_entry->dst_ip, + spdm_entry->l4_sp, + spdm_entry->l4_dp, + spdm_entry->is_tcp, + spdm_entry->is_ipv4, + spdm_entry->tgt_queue, + spdm_entry->jhash_value, + spdm_entry->spdm_entry) + != XGE_HAL_OK) { + /* Log an warning */ + xge_debug_device(XGE_ERR, + "SPDM table update from local" + " memory failed"); + } + } + } + xge_os_spin_unlock(&hldev->spdm_lock); + } + + /* + * Set the receive traffic steering mode from default(classic) + * to enhanced. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->rts_ctrl); + val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->rts_ctrl); + + /* + * We may not need to configure rts_rth_jhash_cfg register as the + * default values are good enough to calculate the hash. + */ + + /* + * As of now, set all the rth mask registers to zero. TODO. + */ + for(i = 0; i < 5; i++) { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0, &bar0->rts_rth_hash_mask[i]); + } + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0, &bar0->rts_rth_hash_mask_5); + + if (hldev->config.rth_spdm_use_l4) { + val64 = XGE_HAL_RTH_STATUS_SPDM_USE_L4; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->rts_rth_status); + } + + val64 = XGE_HAL_RTS_RTH_EN; + val64 |= XGE_HAL_RTS_RTH_IPV4_EN | XGE_HAL_RTS_RTH_TCP_IPV4_EN; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_rth_cfg); + + + return XGE_HAL_OK; +} + +/* + * __hal_device_pci_init + * @hldev: HAL device handle. + * + * Initialize certain PCI/PCI-X configuration registers + * with recommended values. Save config space for future hw resets. + */ +static void +__hal_device_pci_init(xge_hal_device_t *hldev) +{ + int i, pcisize = 0; + u16 cmd = 0; + u8 val; + + /* Store PCI device ID and revision for future references where in we + * decide Xena revision using PCI sub system ID */ + xge_os_pci_read16(hldev->pdev,hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, device_id), + &hldev->device_id); + xge_os_pci_read8(hldev->pdev,hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, revision), + &hldev->revision); + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) + pcisize = XGE_HAL_PCISIZE_HERC; + else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) + pcisize = XGE_HAL_PCISIZE_XENA; + + /* save original PCI config space to restore it on device_terminate() */ + for (i = 0; i < pcisize; i++) { + xge_os_pci_read32(hldev->pdev, hldev->cfgh, i*4, + (u32*)&hldev->pci_config_space_bios + i); + } + + /* Set the PErr Repconse bit and SERR in PCI command register. */ + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, command), &cmd); + cmd |= 0x140; + xge_os_pci_write16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, command), cmd); + + /* Set user spcecified value for the PCI Latency Timer */ + if (hldev->config.latency_timer && + hldev->config.latency_timer != XGE_HAL_USE_BIOS_DEFAULT_LATENCY) { + xge_os_pci_write8(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, + latency_timer), + (u8)hldev->config.latency_timer); + } + /* Read back latency timer to reflect it into user level */ + xge_os_pci_read8(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, latency_timer), &val); + hldev->config.latency_timer = val; + + /* Enable Data Parity Error Recovery in PCI-X command register. */ + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, pcix_command), &cmd); + cmd |= 1; + xge_os_pci_write16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, pcix_command), cmd); + + /* Set MMRB count in PCI-X command register. */ + if (hldev->config.mmrb_count != XGE_HAL_DEFAULT_BIOS_MMRB_COUNT) { + cmd &= 0xFFF3; + cmd |= hldev->config.mmrb_count << 2; + xge_os_pci_write16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, pcix_command), + cmd); + } + /* Read back MMRB count to reflect it into user level */ + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, pcix_command), + &cmd); + cmd &= 0x000C; + hldev->config.mmrb_count = cmd>>2; + + /* Setting Maximum outstanding splits based on system type. */ + if (hldev->config.max_splits_trans != XGE_HAL_USE_BIOS_DEFAULT_SPLITS) { + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, pcix_command), + &cmd); + cmd &= 0xFF8F; + cmd |= hldev->config.max_splits_trans << 4; + xge_os_pci_write16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, pcix_command), + cmd); + } + + /* Read back max split trans to reflect it into user level */ + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, pcix_command), &cmd); + cmd &= 0x0070; + hldev->config.max_splits_trans = cmd>>4; + + /* Forcibly disabling relaxed ordering capability of the card. */ + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, pcix_command), &cmd); + cmd &= 0xFFFD; + xge_os_pci_write16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, pcix_command), cmd); + + /* save PCI config space for future resets */ + for (i = 0; i < pcisize; i++) { + xge_os_pci_read32(hldev->pdev, hldev->cfgh, i*4, + (u32*)&hldev->pci_config_space + i); + } + + if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSI || + hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { + /* Upper limit of the MSI number enabled by the system */ + xge_os_pci_read32(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, msi_control), + &hldev->msi_mask); + hldev->msi_mask &= 0x70; + if (!hldev->msi_mask) + return; + hldev->msi_mask >>= 4; + /* + * This number's power of 2 is the number + * of MSIs enabled. + */ + hldev->msi_mask = (0x1 << hldev->msi_mask); + /* + * If 32 MSIs are enabled, then MSI numbers range from 0 - 31. + */ + hldev->msi_mask -= 1; + } +} + +/* + * __hal_device_pci_info_get - Get PCI bus informations such as width, frequency + * and mode. + * @devh: HAL device handle. + * @pci_mode: pointer to a variable of enumerated type + * xge_hal_pci_mode_e{}. + * @bus_frequency: pointer to a variable of enumerated type + * xge_hal_pci_bus_frequency_e{}. + * @bus_width: pointer to a variable of enumerated type + * xge_hal_pci_bus_width_e{}. + * + * Get pci mode, frequency, and PCI bus width. + * + * Returns: one of the xge_hal_status_e{} enumerated types. + * XGE_HAL_OK - for success. + * XGE_HAL_ERR_INVALID_PCI_INFO - for invalid PCI information from the card. + * XGE_HAL_ERR_BAD_DEVICE_ID - for invalid card. + * + * See Also: xge_hal_pci_mode_e, xge_hal_pci_mode_e, xge_hal_pci_width_e. + */ +static xge_hal_status_e +__hal_device_pci_info_get(xge_hal_device_h devh, xge_hal_pci_mode_e *pci_mode, + xge_hal_pci_bus_frequency_e *bus_frequency, + xge_hal_pci_bus_width_e *bus_width) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + xge_hal_status_e rc_status = XGE_HAL_OK; + xge_hal_card_e card_id = xge_hal_device_check_id (devh); + +#ifdef XGE_HAL_HERC_EMULATION + hldev->config.pci_freq_mherz = + XGE_HAL_PCI_BUS_FREQUENCY_66MHZ; + *bus_frequency = + XGE_HAL_PCI_BUS_FREQUENCY_66MHZ; + *pci_mode = XGE_HAL_PCI_66MHZ_MODE; +#else + if (card_id == XGE_HAL_CARD_HERC) { + xge_hal_pci_bar0_t *bar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 pci_info = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->pci_info); + if (XGE_HAL_PCI_32_BIT & pci_info) + *bus_width = XGE_HAL_PCI_BUS_WIDTH_32BIT; + else + *bus_width = XGE_HAL_PCI_BUS_WIDTH_64BIT; + switch((pci_info & XGE_HAL_PCI_INFO)>>60) + { + case XGE_HAL_PCI_33MHZ_MODE: + *bus_frequency = + XGE_HAL_PCI_BUS_FREQUENCY_33MHZ; + *pci_mode = XGE_HAL_PCI_33MHZ_MODE; + break; + case XGE_HAL_PCI_66MHZ_MODE: + *bus_frequency = + XGE_HAL_PCI_BUS_FREQUENCY_66MHZ; + *pci_mode = XGE_HAL_PCI_66MHZ_MODE; + break; + case XGE_HAL_PCIX_M1_66MHZ_MODE: + *bus_frequency = + XGE_HAL_PCI_BUS_FREQUENCY_66MHZ; + *pci_mode = XGE_HAL_PCIX_M1_66MHZ_MODE; + break; + case XGE_HAL_PCIX_M1_100MHZ_MODE: + *bus_frequency = + XGE_HAL_PCI_BUS_FREQUENCY_100MHZ; + *pci_mode = XGE_HAL_PCIX_M1_100MHZ_MODE; + break; + case XGE_HAL_PCIX_M1_133MHZ_MODE: + *bus_frequency = + XGE_HAL_PCI_BUS_FREQUENCY_133MHZ; + *pci_mode = XGE_HAL_PCIX_M1_133MHZ_MODE; + break; + case XGE_HAL_PCIX_M2_66MHZ_MODE: + *bus_frequency = + XGE_HAL_PCI_BUS_FREQUENCY_133MHZ; + *pci_mode = XGE_HAL_PCIX_M2_66MHZ_MODE; + break; + case XGE_HAL_PCIX_M2_100MHZ_MODE: + *bus_frequency = + XGE_HAL_PCI_BUS_FREQUENCY_200MHZ; + *pci_mode = XGE_HAL_PCIX_M2_100MHZ_MODE; + break; + case XGE_HAL_PCIX_M2_133MHZ_MODE: + *bus_frequency = + XGE_HAL_PCI_BUS_FREQUENCY_266MHZ; + *pci_mode = XGE_HAL_PCIX_M2_133MHZ_MODE; + break; + case XGE_HAL_PCIX_M1_RESERVED: + case XGE_HAL_PCIX_M1_66MHZ_NS: + case XGE_HAL_PCIX_M1_100MHZ_NS: + case XGE_HAL_PCIX_M1_133MHZ_NS: + case XGE_HAL_PCIX_M2_RESERVED: + case XGE_HAL_PCIX_533_RESERVED: + default: + rc_status = XGE_HAL_ERR_INVALID_PCI_INFO; + xge_debug_device(XGE_ERR, + "invalid pci info "XGE_OS_LLXFMT, + (unsigned long long)pci_info); + break; + } + if (rc_status != XGE_HAL_ERR_INVALID_PCI_INFO) + xge_debug_device(XGE_TRACE, "PCI info: mode %d width " + "%d frequency %d", *pci_mode, *bus_width, + *bus_frequency); + if (hldev->config.pci_freq_mherz == + XGE_HAL_DEFAULT_USE_HARDCODE) { + hldev->config.pci_freq_mherz = *bus_frequency; + } + } + /* for XENA, we report PCI mode, only. PCI bus frequency, and bus width + * are set to unknown */ + else if (card_id == XGE_HAL_CARD_XENA) { + u32 pcix_status; + u8 dev_num, bus_num; + /* initialize defaults for XENA */ + *bus_frequency = XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN; + *bus_width = XGE_HAL_PCI_BUS_WIDTH_UNKNOWN; + xge_os_pci_read32(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, pcix_status), + &pcix_status); + dev_num = (u8)((pcix_status & 0xF8) >> 3); + bus_num = (u8)((pcix_status & 0xFF00) >> 8); + if (dev_num == 0 && bus_num == 0) + *pci_mode = XGE_HAL_PCI_BASIC_MODE; + else + *pci_mode = XGE_HAL_PCIX_BASIC_MODE; + xge_debug_device(XGE_TRACE, "PCI info: mode %d", *pci_mode); + if (hldev->config.pci_freq_mherz == + XGE_HAL_DEFAULT_USE_HARDCODE) { + /* + * There is no way to detect BUS frequency on Xena, + * so, in case of automatic configuration we hopelessly + * assume 133MHZ. + */ + hldev->config.pci_freq_mherz = + XGE_HAL_PCI_BUS_FREQUENCY_133MHZ; + } + } else if (card_id == XGE_HAL_CARD_TITAN) { + *bus_width = XGE_HAL_PCI_BUS_WIDTH_64BIT; + *bus_frequency = XGE_HAL_PCI_BUS_FREQUENCY_250MHZ; + if (hldev->config.pci_freq_mherz == + XGE_HAL_DEFAULT_USE_HARDCODE) { + hldev->config.pci_freq_mherz = *bus_frequency; + } + } else{ + rc_status = XGE_HAL_ERR_BAD_DEVICE_ID; + xge_debug_device(XGE_ERR, "invalid device id %d", card_id); + } +#endif + + return rc_status; +} + +/* + * __hal_device_handle_link_up_ind + * @hldev: HAL device handle. + * + * Link up indication handler. The function is invoked by HAL when + * Xframe indicates that the link is up for programmable amount of time. + */ +static int +__hal_device_handle_link_up_ind(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + /* + * If the previous link state is not down, return. + */ + if (hldev->link_state == XGE_HAL_LINK_UP) { +#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC){ + val64 = xge_os_pio_mem_read64( + hldev->pdev, hldev->regh0, + &bar0->misc_int_mask); + val64 |= XGE_HAL_MISC_INT_REG_LINK_UP_INT; + val64 &= ~XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->misc_int_mask); + } +#endif + xge_debug_device(XGE_TRACE, + "link up indication while link is up, ignoring.."); + return 0; + } + + /* Now re-enable it as due to noise, hardware turned it off */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + val64 |= XGE_HAL_ADAPTER_CNTL_EN; + val64 = val64 & (~XGE_HAL_ADAPTER_ECC_EN); /* ECC enable */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->adapter_control); + + /* Turn on the Laser */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + val64 = val64|(XGE_HAL_ADAPTER_EOI_TX_ON | + XGE_HAL_ADAPTER_LED_ON); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->adapter_control); + +#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_status); + if (val64 & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | + XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)) { + xge_debug_device(XGE_TRACE, "%s", + "fail to transition link to up..."); + return 0; + } + else { + /* + * Mask the Link Up interrupt and unmask the Link Down + * interrupt. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->misc_int_mask); + val64 |= XGE_HAL_MISC_INT_REG_LINK_UP_INT; + val64 &= ~XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->misc_int_mask); + xge_debug_device(XGE_TRACE, "calling link up.."); + hldev->link_state = XGE_HAL_LINK_UP; + + /* notify ULD */ + if (g_xge_hal_driver->uld_callbacks.link_up) { + g_xge_hal_driver->uld_callbacks.link_up( + hldev->upper_layer_info); + } + return 1; + } + } +#endif + xge_os_mdelay(1); + if (__hal_device_register_poll(hldev, &bar0->adapter_status, 0, + (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | + XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT), + XGE_HAL_DEVICE_FAULT_WAIT_MAX_MILLIS) == XGE_HAL_OK) { + + /* notify ULD */ + (void) xge_queue_produce_context(hldev->queueh, + XGE_HAL_EVENT_LINK_IS_UP, + hldev); + /* link is up after been enabled */ + return 1; + } else { + xge_debug_device(XGE_TRACE, "%s", + "fail to transition link to up..."); + return 0; + } +} + +/* + * __hal_device_handle_link_down_ind + * @hldev: HAL device handle. + * + * Link down indication handler. The function is invoked by HAL when + * Xframe indicates that the link is down. + */ +static int +__hal_device_handle_link_down_ind(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + /* + * If the previous link state is not up, return. + */ + if (hldev->link_state == XGE_HAL_LINK_DOWN) { +#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC){ + val64 = xge_os_pio_mem_read64( + hldev->pdev, hldev->regh0, + &bar0->misc_int_mask); + val64 |= XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; + val64 &= ~XGE_HAL_MISC_INT_REG_LINK_UP_INT; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->misc_int_mask); + } +#endif + xge_debug_device(XGE_TRACE, + "link down indication while link is down, ignoring.."); + return 0; + } + xge_os_mdelay(1); + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + + /* try to debounce the link only if the adapter is enabled. */ + if (val64 & XGE_HAL_ADAPTER_CNTL_EN) { + if (__hal_device_register_poll(hldev, &bar0->adapter_status, 0, + (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | + XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT), + XGE_HAL_DEVICE_FAULT_WAIT_MAX_MILLIS) == XGE_HAL_OK) { + xge_debug_device(XGE_TRACE, + "link is actually up (possible noisy link?), ignoring."); + return(0); + } + } + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + /* turn off LED */ + val64 = val64 & (~XGE_HAL_ADAPTER_LED_ON); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->adapter_control); + +#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + /* + * Mask the Link Down interrupt and unmask the Link up + * interrupt + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->misc_int_mask); + val64 |= XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; + val64 &= ~XGE_HAL_MISC_INT_REG_LINK_UP_INT; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->misc_int_mask); + + /* link is down */ + xge_debug_device(XGE_TRACE, "calling link down.."); + hldev->link_state = XGE_HAL_LINK_DOWN; + + /* notify ULD */ + if (g_xge_hal_driver->uld_callbacks.link_down) { + g_xge_hal_driver->uld_callbacks.link_down( + hldev->upper_layer_info); + } + return 1; + } +#endif + /* notify ULD */ + (void) xge_queue_produce_context(hldev->queueh, + XGE_HAL_EVENT_LINK_IS_DOWN, + hldev); + /* link is down */ + return 1; +} +/* + * __hal_device_handle_link_state_change + * @hldev: HAL device handle. + * + * Link state change handler. The function is invoked by HAL when + * Xframe indicates link state change condition. The code here makes sure to + * 1) ignore redundant state change indications; + * 2) execute link-up sequence, and handle the failure to bring the link up; + * 3) generate XGE_HAL_LINK_UP/DOWN event for the subsequent handling by + * upper-layer driver (ULD). + */ +static int +__hal_device_handle_link_state_change(xge_hal_device_t *hldev) +{ + u64 hw_status; + int hw_link_state; + int retcode; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + int i = 0; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + + /* If the adapter is not enabled but the hal thinks we are in the up + * state then transition to the down state. + */ + if ( !(val64 & XGE_HAL_ADAPTER_CNTL_EN) && + (hldev->link_state == XGE_HAL_LINK_UP) ) { + return(__hal_device_handle_link_down_ind(hldev)); + } + + do { + xge_os_mdelay(1); + (void) xge_hal_device_status(hldev, &hw_status); + hw_link_state = (hw_status & + (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | + XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)) ? + XGE_HAL_LINK_DOWN : XGE_HAL_LINK_UP; + + /* check if the current link state is still considered + * to be changed. This way we will make sure that this is + * not a noise which needs to be filtered out */ + if (hldev->link_state == hw_link_state) + break; + } while (i++ < hldev->config.link_valid_cnt); + + /* If the current link state is same as previous, just return */ + if (hldev->link_state == hw_link_state) + retcode = 0; + /* detected state change */ + else if (hw_link_state == XGE_HAL_LINK_UP) + retcode = __hal_device_handle_link_up_ind(hldev); + else + retcode = __hal_device_handle_link_down_ind(hldev); + return retcode; +} + +/* + * + */ +static void +__hal_device_handle_serr(xge_hal_device_t *hldev, char *reg, u64 value) +{ + hldev->stats.sw_dev_err_stats.serr_cnt++; + if (hldev->config.dump_on_serr) { +#ifdef XGE_HAL_USE_MGMT_AUX + (void) xge_hal_aux_device_dump(hldev); +#endif + } + + (void) xge_queue_produce(hldev->queueh, XGE_HAL_EVENT_SERR, hldev, + 1, sizeof(u64), (void *)&value); + + xge_debug_device(XGE_ERR, "%s: read "XGE_OS_LLXFMT, reg, + (unsigned long long) value); +} + +/* + * + */ +static void +__hal_device_handle_eccerr(xge_hal_device_t *hldev, char *reg, u64 value) +{ + if (hldev->config.dump_on_eccerr) { +#ifdef XGE_HAL_USE_MGMT_AUX + (void) xge_hal_aux_device_dump(hldev); +#endif + } + + /* Herc smart enough to recover on its own! */ + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { + (void) xge_queue_produce(hldev->queueh, + XGE_HAL_EVENT_ECCERR, hldev, + 1, sizeof(u64), (void *)&value); + } + + xge_debug_device(XGE_ERR, "%s: read "XGE_OS_LLXFMT, reg, + (unsigned long long) value); +} + +/* + * + */ +static void +__hal_device_handle_parityerr(xge_hal_device_t *hldev, char *reg, u64 value) +{ + if (hldev->config.dump_on_parityerr) { +#ifdef XGE_HAL_USE_MGMT_AUX + (void) xge_hal_aux_device_dump(hldev); +#endif + } + (void) xge_queue_produce_context(hldev->queueh, + XGE_HAL_EVENT_PARITYERR, hldev); + + xge_debug_device(XGE_ERR, "%s: read "XGE_OS_LLXFMT, reg, + (unsigned long long) value); +} + +/* + * + */ +static void +__hal_device_handle_targetabort(xge_hal_device_t *hldev) +{ + (void) xge_queue_produce_context(hldev->queueh, + XGE_HAL_EVENT_TARGETABORT, hldev); +} + + +/* + * __hal_device_hw_initialize + * @hldev: HAL device handle. + * + * Initialize Xframe hardware. + */ +static xge_hal_status_e +__hal_device_hw_initialize(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + xge_hal_status_e status; + u64 val64; + + /* Set proper endian settings and verify the same by reading the PIF + * Feed-back register. */ + status = __hal_device_set_swapper(hldev); + if (status != XGE_HAL_OK) { + return status; + } + + /* update the pci mode, frequency, and width */ + if (__hal_device_pci_info_get(hldev, &hldev->pci_mode, + &hldev->bus_frequency, &hldev->bus_width) != XGE_HAL_OK){ + hldev->pci_mode = XGE_HAL_PCI_INVALID_MODE; + hldev->bus_frequency = XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN; + hldev->bus_width = XGE_HAL_PCI_BUS_WIDTH_UNKNOWN; + /* + * FIXME: this cannot happen. + * But if it happens we cannot continue just like that + */ + xge_debug_device(XGE_ERR, "unable to get pci info"); + } + + if ((hldev->pci_mode == XGE_HAL_PCI_33MHZ_MODE) || + (hldev->pci_mode == XGE_HAL_PCI_66MHZ_MODE) || + (hldev->pci_mode == XGE_HAL_PCI_BASIC_MODE)) { + /* PCI optimization: set TxReqTimeOut + * register (0x800+0x120) to 0x1ff or + * something close to this. + * Note: not to be used for PCI-X! */ + + val64 = XGE_HAL_TXREQTO_VAL(0x1FF); + val64 |= XGE_HAL_TXREQTO_EN; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->txreqtimeout); + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0ULL, + &bar0->read_retry_delay); + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0ULL, + &bar0->write_retry_delay); + + xge_debug_device(XGE_TRACE, "%s", "optimizing for PCI mode"); + } + + if (hldev->bus_frequency == XGE_HAL_PCI_BUS_FREQUENCY_266MHZ || + hldev->bus_frequency == XGE_HAL_PCI_BUS_FREQUENCY_250MHZ) { + + /* Optimizing for PCI-X 266/250 */ + + val64 = XGE_HAL_TXREQTO_VAL(0x7F); + val64 |= XGE_HAL_TXREQTO_EN; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->txreqtimeout); + + xge_debug_device(XGE_TRACE, "%s", "optimizing for PCI-X 266/250 modes"); + } + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x4000000000000ULL, + &bar0->read_retry_delay); + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x4000000000000ULL, + &bar0->write_retry_delay); + } + + /* added this to set the no of bytes used to update lso_bytes_sent + returned TxD0 */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->pic_control_2); + val64 &= ~XGE_HAL_TXD_WRITE_BC(0x2); + val64 |= XGE_HAL_TXD_WRITE_BC(0x4); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->pic_control_2); + /* added this to clear the EOI_RESET field while leaving XGXS_RESET + * in reset, then a 1-second delay */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_SW_RESET_XGXS, &bar0->sw_reset); + xge_os_mdelay(1000); + + /* Clear the XGXS_RESET field of the SW_RESET register in order to + * release the XGXS from reset. Its reset value is 0xA5; write 0x00 + * to activate the XGXS. The core requires a minimum 500 us reset.*/ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0, &bar0->sw_reset); + (void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->sw_reset); + xge_os_mdelay(1); + + /* read registers in all blocks */ + (void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mac_int_mask); + (void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mc_int_mask); + (void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->xgxs_int_mask); + + /* set default MTU and steer based on length*/ + __hal_ring_mtu_set(hldev, hldev->config.mtu+22); // Alway set 22 bytes extra for steering to work + + if (hldev->config.mac.rmac_bcast_en) { + xge_hal_device_bcast_enable(hldev); + } else { + xge_hal_device_bcast_disable(hldev); + } + +#ifndef XGE_HAL_HERC_EMULATION + __hal_device_xaui_configure(hldev); +#endif + __hal_device_mac_link_util_set(hldev); + + __hal_device_mac_link_util_set(hldev); + + /* + * Keep its PCI REQ# line asserted during a write + * transaction up to the end of the transaction + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->misc_control); + + val64 |= XGE_HAL_MISC_CONTROL_EXT_REQ_EN; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->misc_control); + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->misc_control); + + val64 |= XGE_HAL_MISC_CONTROL_LINK_FAULT; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->misc_control); + } + + /* + * bimodal interrupts is when all Rx traffic interrupts + * will go to TTI, so we need to adjust RTI settings and + * use adaptive TTI timer. We need to make sure RTI is + * properly configured to sane value which will not + * distrupt bimodal behavior. + */ + if (hldev->config.bimodal_interrupts) { + int i; + + /* force polling_cnt to be "0", otherwise + * IRQ workload statistics will be screwed. This could + * be worked out in TXPIC handler later. */ + hldev->config.isr_polling_cnt = 0; + hldev->config.sched_timer_us = 10000; + + /* disable all TTI < 56 */ + for (i=0; i<XGE_HAL_MAX_FIFO_NUM; i++) { + int j; + if (!hldev->config.fifo.queue[i].configured) + continue; + for (j=0; j<XGE_HAL_MAX_FIFO_TTI_NUM; j++) { + if (hldev->config.fifo.queue[i].tti[j].enabled) + hldev->config.fifo.queue[i].tti[j].enabled = 0; + } + } + + /* now configure bimodal interrupts */ + __hal_device_bimodal_configure(hldev); + } + + status = __hal_device_tti_configure(hldev, 0); + if (status != XGE_HAL_OK) + return status; + + status = __hal_device_rti_configure(hldev, 0); + if (status != XGE_HAL_OK) + return status; + + status = __hal_device_rth_it_configure(hldev); + if (status != XGE_HAL_OK) + return status; + + status = __hal_device_rth_spdm_configure(hldev); + if (status != XGE_HAL_OK) + return status; + + status = __hal_device_rts_mac_configure(hldev); + if (status != XGE_HAL_OK) { + xge_debug_device(XGE_ERR, "__hal_device_rts_mac_configure Failed "); + return status; + } + + status = __hal_device_rts_port_configure(hldev); + if (status != XGE_HAL_OK) { + xge_debug_device(XGE_ERR, "__hal_device_rts_port_configure Failed "); + return status; + } + + status = __hal_device_rts_qos_configure(hldev); + if (status != XGE_HAL_OK) { + xge_debug_device(XGE_ERR, "__hal_device_rts_qos_configure Failed "); + return status; + } + + __hal_device_pause_frames_configure(hldev); + __hal_device_rmac_padding_configure(hldev); + __hal_device_shared_splits_configure(hldev); + + /* make sure all interrupts going to be disabled at the moment */ + __hal_device_intr_mgmt(hldev, XGE_HAL_ALL_INTRS, 0); + + /* SXE-008 Transmit DMA arbitration issue */ + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA && + hldev->revision < 4) { + xge_os_pio_mem_write64(hldev->pdev,hldev->regh0, + XGE_HAL_ADAPTER_PCC_ENABLE_FOUR, + &bar0->pcc_enable); + } + __hal_fifo_hw_initialize(hldev); + __hal_ring_hw_initialize(hldev); + + if (__hal_device_wait_quiescent(hldev, &val64)) { + return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; + } + + if (__hal_device_register_poll(hldev, &bar0->adapter_status, 1, + XGE_HAL_ADAPTER_STATUS_RC_PRC_QUIESCENT, + XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + xge_debug_device(XGE_TRACE, "%s", "PRC is not QUIESCENT!"); + return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; + } + + xge_debug_device(XGE_TRACE, "device 0x"XGE_OS_LLXFMT" is quiescent", + (unsigned long long)(ulong_t)hldev); + + if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX || + hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSI) { + /* + * If MSI is enabled, ensure that One Shot for MSI in PCI_CTRL + * is disabled. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->pic_control); + val64 &= ~(XGE_HAL_PIC_CNTL_ONE_SHOT_TINT); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->pic_control); + } + + hldev->hw_is_initialized = 1; + hldev->terminating = 0; + return XGE_HAL_OK; +} + +/* + * __hal_device_reset - Reset device only. + * @hldev: HAL device handle. + * + * Reset the device, and subsequently restore + * the previously saved PCI configuration space. + */ +#define XGE_HAL_MAX_PCI_CONFIG_SPACE_REINIT 50 +static xge_hal_status_e +__hal_device_reset(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + int i, j, swap_done, pcisize = 0; + u64 val64, rawval = 0ULL; + + if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + if ( hldev->bar2 ) { + u64 *msix_vetor_table = (u64 *)hldev->bar2; + + // 2 64bit words for each entry + for (i = 0; i < XGE_HAL_MAX_MSIX_MESSAGES * 2; + i++) { + hldev->msix_vector_table[i] = + xge_os_pio_mem_read64(hldev->pdev, + hldev->regh2, &msix_vetor_table[i]); + } + } + } + } + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->pif_rd_swapper_fb); + swap_done = (val64 == XGE_HAL_IF_RD_SWAPPER_FB); + + if (swap_done) { + __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, + (u32)(XGE_HAL_SW_RESET_ALL>>32), (char *)&bar0->sw_reset); + } else { + u32 val = (u32)(XGE_HAL_SW_RESET_ALL >> 32); +#if defined(XGE_OS_HOST_LITTLE_ENDIAN) || defined(XGE_OS_PIO_LITTLE_ENDIAN) + /* swap it */ + val = (((val & (u32)0x000000ffUL) << 24) | + ((val & (u32)0x0000ff00UL) << 8) | + ((val & (u32)0x00ff0000UL) >> 8) | + ((val & (u32)0xff000000UL) >> 24)); +#endif + xge_os_pio_mem_write32(hldev->pdev, hldev->regh0, val, + &bar0->sw_reset); + } + + pcisize = (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)? + XGE_HAL_PCISIZE_HERC : XGE_HAL_PCISIZE_XENA; + + xge_os_mdelay(20); /* Wait for 20 ms after reset */ + + { + /* Poll for no more than 1 second */ + for (i = 0; i < XGE_HAL_MAX_PCI_CONFIG_SPACE_REINIT; i++) + { + for (j = 0; j < pcisize; j++) { + xge_os_pci_write32(hldev->pdev, hldev->cfgh, j * 4, + *((u32*)&hldev->pci_config_space + j)); + } + + xge_os_pci_read16(hldev->pdev,hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, device_id), + &hldev->device_id); + + if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_UNKNOWN) + break; + xge_os_mdelay(20); + } + } + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_UNKNOWN) + { + xge_debug_device(XGE_ERR, "device reset failed"); + return XGE_HAL_ERR_RESET_FAILED; + } + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + int cnt = 0; + + rawval = XGE_HAL_SW_RESET_RAW_VAL_HERC; + pcisize = XGE_HAL_PCISIZE_HERC; + xge_os_mdelay(1); + do { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->sw_reset); + if (val64 != rawval) { + break; + } + cnt++; + xge_os_mdelay(1); /* Wait for 1ms before retry */ + } while(cnt < 20); + } else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { + rawval = XGE_HAL_SW_RESET_RAW_VAL_XENA; + pcisize = XGE_HAL_PCISIZE_XENA; + xge_os_mdelay(XGE_HAL_DEVICE_RESET_WAIT_MAX_MILLIS); + } + + /* Restore MSI-X vector table */ + if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + if ( hldev->bar2 ) { + /* + * 94: MSIXTable 00000004 ( BIR:4 Offset:0x0 ) + * 98: PBATable 00000404 ( BIR:4 Offset:0x400 ) + */ + u64 *msix_vetor_table = (u64 *)hldev->bar2; + + /* 2 64bit words for each entry */ + for (i = 0; i < XGE_HAL_MAX_MSIX_MESSAGES * 2; + i++) { + xge_os_pio_mem_write64(hldev->pdev, + hldev->regh2, + hldev->msix_vector_table[i], + &msix_vetor_table[i]); + } + } + } + } + + hldev->link_state = XGE_HAL_LINK_DOWN; + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->sw_reset); + + if (val64 != rawval) { + xge_debug_device(XGE_ERR, "device has not been reset " + "got 0x"XGE_OS_LLXFMT", expected 0x"XGE_OS_LLXFMT, + (unsigned long long)val64, (unsigned long long)rawval); + return XGE_HAL_ERR_RESET_FAILED; + } + + hldev->hw_is_initialized = 0; + return XGE_HAL_OK; +} + +/* + * __hal_device_poll - General private routine to poll the device. + * @hldev: HAL device handle. + * + * Returns: one of the xge_hal_status_e{} enumerated types. + * XGE_HAL_OK - for success. + * XGE_HAL_ERR_CRITICAL - when encounters critical error. + */ +static xge_hal_status_e +__hal_device_poll(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0; + u64 err_reg; + + bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + + /* Handling SERR errors by forcing a H/W reset. */ + err_reg = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->serr_source); + if (err_reg & XGE_HAL_SERR_SOURCE_ANY) { + __hal_device_handle_serr(hldev, "serr_source", err_reg); + return XGE_HAL_ERR_CRITICAL; + } + + err_reg = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->misc_int_reg); + + if (err_reg & XGE_HAL_MISC_INT_REG_DP_ERR_INT) { + hldev->stats.sw_dev_err_stats.parity_err_cnt++; + __hal_device_handle_parityerr(hldev, "misc_int_reg", err_reg); + return XGE_HAL_ERR_CRITICAL; + } + +#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) +#endif + { + + /* Handling link status change error Intr */ + err_reg = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mac_rmac_err_reg); + if (__hal_device_handle_link_state_change(hldev)) + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + err_reg, &bar0->mac_rmac_err_reg); + } + + if (hldev->inject_serr != 0) { + err_reg = hldev->inject_serr; + hldev->inject_serr = 0; + __hal_device_handle_serr(hldev, "inject_serr", err_reg); + return XGE_HAL_ERR_CRITICAL; + } + + if (hldev->inject_ecc != 0) { + err_reg = hldev->inject_ecc; + hldev->inject_ecc = 0; + hldev->stats.sw_dev_err_stats.ecc_err_cnt++; + __hal_device_handle_eccerr(hldev, "inject_ecc", err_reg); + return XGE_HAL_ERR_CRITICAL; + } + + if (hldev->inject_bad_tcode != 0) { + u8 t_code = hldev->inject_bad_tcode; + xge_hal_channel_t channel; + xge_hal_fifo_txd_t txd; + xge_hal_ring_rxd_1_t rxd; + + channel.devh = hldev; + + if (hldev->inject_bad_tcode_for_chan_type == + XGE_HAL_CHANNEL_TYPE_FIFO) { + channel.type = XGE_HAL_CHANNEL_TYPE_FIFO; + + } else { + channel.type = XGE_HAL_CHANNEL_TYPE_RING; + } + + hldev->inject_bad_tcode = 0; + + if (channel.type == XGE_HAL_CHANNEL_TYPE_FIFO) + return xge_hal_device_handle_tcode(&channel, &txd, + t_code); + else + return xge_hal_device_handle_tcode(&channel, &rxd, + t_code); + } + + return XGE_HAL_OK; +} + +/* + * __hal_verify_pcc_idle - Verify All Enbled PCC are IDLE or not + * @hldev: HAL device handle. + * @adp_status: Adapter Status value + * Usage: See xge_hal_device_enable{}. + */ +xge_hal_status_e +__hal_verify_pcc_idle(xge_hal_device_t *hldev, u64 adp_status) +{ + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA && + hldev->revision < 4) { + /* + * For Xena 1,2,3 we enable only 4 PCCs Due to + * SXE-008 (Transmit DMA arbitration issue) + */ + if ((adp_status & XGE_HAL_ADAPTER_STATUS_RMAC_PCC_4_IDLE) + != XGE_HAL_ADAPTER_STATUS_RMAC_PCC_4_IDLE) { + xge_debug_device(XGE_TRACE, "%s", + "PCC is not IDLE after adapter enabled!"); + return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; + } + } else { + if ((adp_status & XGE_HAL_ADAPTER_STATUS_RMAC_PCC_IDLE) != + XGE_HAL_ADAPTER_STATUS_RMAC_PCC_IDLE) { + xge_debug_device(XGE_TRACE, "%s", + "PCC is not IDLE after adapter enabled!"); + return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; + } + } + return XGE_HAL_OK; +} + +static void +__hal_update_bimodal(xge_hal_device_t *hldev, int ring_no) +{ + int tval, d, iwl_avg, len_avg, bytes_avg, bytes_hist, d_hist; + int iwl_rxcnt, iwl_txcnt, iwl_txavg, len_rxavg, iwl_rxavg, len_txavg; + int iwl_cnt, i; + +#define _HIST_SIZE 50 /* 0.5 sec history */ +#define _HIST_ADJ_TIMER 1 +#define _STEP 2 + + static int bytes_avg_history[_HIST_SIZE] = {0}; + static int d_avg_history[_HIST_SIZE] = {0}; + static int history_idx = 0; + static int pstep = 1; + static int hist_adj_timer = 0; + + /* + * tval - current value of this bimodal timer + */ + tval = hldev->bimodal_tti[ring_no].timer_val_us; + + /* + * d - how many interrupts we were getting since last + * bimodal timer tick. + */ + d = hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt - + hldev->bimodal_intr_cnt; + + /* advance bimodal interrupt counter */ + hldev->bimodal_intr_cnt = + hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt; + + /* + * iwl_cnt - how many interrupts we've got since last + * bimodal timer tick. + */ + iwl_rxcnt = (hldev->irq_workload_rxcnt[ring_no] ? + hldev->irq_workload_rxcnt[ring_no] : 1); + iwl_txcnt = (hldev->irq_workload_txcnt[ring_no] ? + hldev->irq_workload_txcnt[ring_no] : 1); + iwl_cnt = iwl_rxcnt + iwl_txcnt; + iwl_cnt = iwl_cnt; /* just to remove the lint warning */ + + /* + * we need to take hldev->config.isr_polling_cnt into account + * but for some reason this line causing GCC to produce wrong + * code on Solaris. As of now, if bimodal_interrupts is configured + * hldev->config.isr_polling_cnt is forced to be "0". + * + * iwl_cnt = iwl_cnt / (hldev->config.isr_polling_cnt + 1); */ + + /* + * iwl_avg - how many RXDs on avarage been processed since + * last bimodal timer tick. This indirectly includes + * CPU utilizations. + */ + iwl_rxavg = hldev->irq_workload_rxd[ring_no] / iwl_rxcnt; + iwl_txavg = hldev->irq_workload_txd[ring_no] / iwl_txcnt; + iwl_avg = iwl_rxavg + iwl_txavg; + iwl_avg = iwl_avg == 0 ? 1 : iwl_avg; + + /* + * len_avg - how many bytes on avarage been processed since + * last bimodal timer tick. i.e. avarage frame size. + */ + len_rxavg = 1 + hldev->irq_workload_rxlen[ring_no] / + (hldev->irq_workload_rxd[ring_no] ? + hldev->irq_workload_rxd[ring_no] : 1); + len_txavg = 1 + hldev->irq_workload_txlen[ring_no] / + (hldev->irq_workload_txd[ring_no] ? + hldev->irq_workload_txd[ring_no] : 1); + len_avg = len_rxavg + len_txavg; + if (len_avg < 60) + len_avg = 60; + + /* align on low boundary */ + if ((tval -_STEP) < hldev->config.bimodal_timer_lo_us) + tval = hldev->config.bimodal_timer_lo_us; + + /* reset faster */ + if (iwl_avg == 1) { + tval = hldev->config.bimodal_timer_lo_us; + /* reset history */ + for (i = 0; i < _HIST_SIZE; i++) + bytes_avg_history[i] = d_avg_history[i] = 0; + history_idx = 0; + pstep = 1; + hist_adj_timer = 0; + } + + /* always try to ajust timer to the best throughput value */ + bytes_avg = iwl_avg * len_avg; + history_idx %= _HIST_SIZE; + bytes_avg_history[history_idx] = bytes_avg; + d_avg_history[history_idx] = d; + history_idx++; + d_hist = bytes_hist = 0; + for (i = 0; i < _HIST_SIZE; i++) { + /* do not re-configure until history is gathered */ + if (!bytes_avg_history[i]) { + tval = hldev->config.bimodal_timer_lo_us; + goto _end; + } + bytes_hist += bytes_avg_history[i]; + d_hist += d_avg_history[i]; + } + bytes_hist /= _HIST_SIZE; + d_hist /= _HIST_SIZE; + +// xge_os_printf("d %d iwl_avg %d len_avg %d:%d:%d tval %d avg %d hist %d pstep %d", +// d, iwl_avg, len_txavg, len_rxavg, len_avg, tval, d*bytes_avg, +// d_hist*bytes_hist, pstep); + + /* make an adaptive step */ + if (d * bytes_avg < d_hist * bytes_hist && hist_adj_timer++ > _HIST_ADJ_TIMER) { + pstep = !pstep; + hist_adj_timer = 0; + } + + if (pstep && + (tval + _STEP) <= hldev->config.bimodal_timer_hi_us) { + tval += _STEP; + hldev->stats.sw_dev_info_stats.bimodal_hi_adjust_cnt++; + } else if ((tval - _STEP) >= hldev->config.bimodal_timer_lo_us) { + tval -= _STEP; + hldev->stats.sw_dev_info_stats.bimodal_lo_adjust_cnt++; + } + + /* enable TTI range A for better latencies */ + hldev->bimodal_urange_a_en = 0; + if (tval <= hldev->config.bimodal_timer_lo_us && iwl_avg > 2) + hldev->bimodal_urange_a_en = 1; + +_end: + /* reset workload statistics counters */ + hldev->irq_workload_rxcnt[ring_no] = 0; + hldev->irq_workload_rxd[ring_no] = 0; + hldev->irq_workload_rxlen[ring_no] = 0; + hldev->irq_workload_txcnt[ring_no] = 0; + hldev->irq_workload_txd[ring_no] = 0; + hldev->irq_workload_txlen[ring_no] = 0; + + /* reconfigure TTI56 + ring_no with new timer value */ + hldev->bimodal_timer_val_us = tval; + (void) __hal_device_rti_configure(hldev, 1); +} + +static void +__hal_update_rxufca(xge_hal_device_t *hldev, int ring_no) +{ + int ufc, ic, i; + + ufc = hldev->config.ring.queue[ring_no].rti.ufc_a; + ic = hldev->stats.sw_dev_info_stats.rx_traffic_intr_cnt; + + /* urange_a adaptive coalescing */ + if (hldev->rxufca_lbolt > hldev->rxufca_lbolt_time) { + if (ic > hldev->rxufca_intr_thres) { + if (ufc < hldev->config.rxufca_hi_lim) { + ufc += 1; + for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) + hldev->config.ring.queue[i].rti.ufc_a = ufc; + (void) __hal_device_rti_configure(hldev, 1); + hldev->stats.sw_dev_info_stats. + rxufca_hi_adjust_cnt++; + } + hldev->rxufca_intr_thres = ic + + hldev->config.rxufca_intr_thres; /* def: 30 */ + } else { + if (ufc > hldev->config.rxufca_lo_lim) { + ufc -= 1; + for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) + hldev->config.ring.queue[i].rti.ufc_a = ufc; + (void) __hal_device_rti_configure(hldev, 1); + hldev->stats.sw_dev_info_stats. + rxufca_lo_adjust_cnt++; + } + } + hldev->rxufca_lbolt_time = hldev->rxufca_lbolt + + hldev->config.rxufca_lbolt_period; + } + hldev->rxufca_lbolt++; +} + +/* + * __hal_device_handle_mc - Handle MC interrupt reason + * @hldev: HAL device handle. + * @reason: interrupt reason + */ +xge_hal_status_e +__hal_device_handle_mc(xge_hal_device_t *hldev, u64 reason) +{ + xge_hal_pci_bar0_t *isrbar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; + u64 val64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->mc_int_status); + if (!(val64 & XGE_HAL_MC_INT_STATUS_MC_INT)) + return XGE_HAL_OK; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->mc_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &isrbar0->mc_err_reg); + + if (val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_SG_ERR_L || + val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_SG_ERR_U || + val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_SG_ERR_0 || + val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_SG_ERR_1 || + (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_XENA && + (val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_SG_ERR_L || + val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_SG_ERR_U || + val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_SG_ERR_L || + val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_SG_ERR_U))) { + hldev->stats.sw_dev_err_stats.single_ecc_err_cnt++; + hldev->stats.sw_dev_err_stats.ecc_err_cnt++; + } + + if (val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_DB_ERR_L || + val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_DB_ERR_U || + val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_0 || + val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_1 || + (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_XENA && + (val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_DB_ERR_L || + val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_DB_ERR_U || + val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_DB_ERR_L || + val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_DB_ERR_U))) { + hldev->stats.sw_dev_err_stats.double_ecc_err_cnt++; + hldev->stats.sw_dev_err_stats.ecc_err_cnt++; + } + + if (val64 & XGE_HAL_MC_ERR_REG_SM_ERR) { + hldev->stats.sw_dev_err_stats.sm_err_cnt++; + } + + /* those two should result in device reset */ + if (val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_0 || + val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_1) { + __hal_device_handle_eccerr(hldev, "mc_err_reg", val64); + return XGE_HAL_ERR_CRITICAL; + } + + return XGE_HAL_OK; +} + +/* + * __hal_device_handle_pic - Handle non-traffic PIC interrupt reason + * @hldev: HAL device handle. + * @reason: interrupt reason + */ +xge_hal_status_e +__hal_device_handle_pic(xge_hal_device_t *hldev, u64 reason) +{ + xge_hal_pci_bar0_t *isrbar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; + u64 val64; + + if (reason & XGE_HAL_PIC_INT_FLSH) { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->flsh_int_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &isrbar0->flsh_int_reg); + /* FIXME: handle register */ + } + if (reason & XGE_HAL_PIC_INT_MDIO) { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->mdio_int_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &isrbar0->mdio_int_reg); + /* FIXME: handle register */ + } + if (reason & XGE_HAL_PIC_INT_IIC) { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->iic_int_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &isrbar0->iic_int_reg); + /* FIXME: handle register */ + } + if (reason & XGE_HAL_PIC_INT_MISC) { + val64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &isrbar0->misc_int_reg); +#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + /* Check for Link interrupts. If both Link Up/Down + * bits are set, clear both and check adapter status + */ + if ((val64 & XGE_HAL_MISC_INT_REG_LINK_UP_INT) && + (val64 & XGE_HAL_MISC_INT_REG_LINK_DOWN_INT)) { + u64 temp64; + + xge_debug_device(XGE_TRACE, + "both link up and link down detected "XGE_OS_LLXFMT, + (unsigned long long)val64); + + temp64 = (XGE_HAL_MISC_INT_REG_LINK_DOWN_INT | + XGE_HAL_MISC_INT_REG_LINK_UP_INT); + xge_os_pio_mem_write64(hldev->pdev, + hldev->regh0, temp64, + &isrbar0->misc_int_reg); + } + else if (val64 & XGE_HAL_MISC_INT_REG_LINK_UP_INT) { + xge_debug_device(XGE_TRACE, + "link up call request, misc_int "XGE_OS_LLXFMT, + (unsigned long long)val64); + __hal_device_handle_link_up_ind(hldev); + } + else if (val64 & XGE_HAL_MISC_INT_REG_LINK_DOWN_INT){ + xge_debug_device(XGE_TRACE, + "link down request, misc_int "XGE_OS_LLXFMT, + (unsigned long long)val64); + __hal_device_handle_link_down_ind(hldev); + } + } else +#endif + { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &isrbar0->misc_int_reg); + } + } + + return XGE_HAL_OK; +} + +/* + * __hal_device_handle_txpic - Handle TxPIC interrupt reason + * @hldev: HAL device handle. + * @reason: interrupt reason + */ +xge_hal_status_e +__hal_device_handle_txpic(xge_hal_device_t *hldev, u64 reason) +{ + xge_hal_status_e status = XGE_HAL_OK; + xge_hal_pci_bar0_t *isrbar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; + volatile u64 val64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->pic_int_status); + if ( val64 & (XGE_HAL_PIC_INT_FLSH | + XGE_HAL_PIC_INT_MDIO | + XGE_HAL_PIC_INT_IIC | + XGE_HAL_PIC_INT_MISC) ) { + status = __hal_device_handle_pic(hldev, val64); + xge_os_wmb(); + } + + if (!(val64 & XGE_HAL_PIC_INT_TX)) + return status; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->txpic_int_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &isrbar0->txpic_int_reg); + xge_os_wmb(); + + if (val64 & XGE_HAL_TXPIC_INT_SCHED_INTR) { + int i; + + if (g_xge_hal_driver->uld_callbacks.sched_timer != NULL) + g_xge_hal_driver->uld_callbacks.sched_timer( + hldev, hldev->upper_layer_info); + /* + * This feature implements adaptive receive interrupt + * coalecing. It is disabled by default. To enable it + * set hldev->config.rxufca_lo_lim to be not equal to + * hldev->config.rxufca_hi_lim. + * + * We are using HW timer for this feature, so + * use needs to configure hldev->config.rxufca_lbolt_period + * which is essentially a time slice of timer. + * + * For those who familiar with Linux, lbolt means jiffies + * of this timer. I.e. timer tick. + */ + if (hldev->config.rxufca_lo_lim != + hldev->config.rxufca_hi_lim && + hldev->config.rxufca_lo_lim != 0) { + for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { + if (!hldev->config.ring.queue[i].configured) + continue; + if (hldev->config.ring.queue[i].rti.urange_a) + __hal_update_rxufca(hldev, i); + } + } + + /* + * This feature implements adaptive TTI timer re-calculation + * based on host utilization, number of interrupt processed, + * number of RXD per tick and avarage length of packets per + * tick. + */ + if (hldev->config.bimodal_interrupts) { + for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { + if (!hldev->config.ring.queue[i].configured) + continue; + if (hldev->bimodal_tti[i].enabled) + __hal_update_bimodal(hldev, i); + } + } + } + + return XGE_HAL_OK; +} + +/* + * __hal_device_handle_txdma - Handle TxDMA interrupt reason + * @hldev: HAL device handle. + * @reason: interrupt reason + */ +xge_hal_status_e +__hal_device_handle_txdma(xge_hal_device_t *hldev, u64 reason) +{ + xge_hal_pci_bar0_t *isrbar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; + u64 val64, temp64, err; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->txdma_int_status); + if (val64 & XGE_HAL_TXDMA_PFC_INT) { + err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->pfc_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + err, &isrbar0->pfc_err_reg); + hldev->stats.sw_dev_info_stats.pfc_err_cnt++; + temp64 = XGE_HAL_PFC_ECC_DB_ERR|XGE_HAL_PFC_SM_ERR_ALARM + |XGE_HAL_PFC_MISC_0_ERR|XGE_HAL_PFC_MISC_1_ERR + |XGE_HAL_PFC_PCIX_ERR; + if (val64 & temp64) + goto reset; + } + if (val64 & XGE_HAL_TXDMA_TDA_INT) { + err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->tda_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + err, &isrbar0->tda_err_reg); + hldev->stats.sw_dev_info_stats.tda_err_cnt++; + temp64 = XGE_HAL_TDA_Fn_ECC_DB_ERR|XGE_HAL_TDA_SM0_ERR_ALARM + |XGE_HAL_TDA_SM1_ERR_ALARM; + if (val64 & temp64) + goto reset; + } + if (val64 & XGE_HAL_TXDMA_PCC_INT) { + err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->pcc_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + err, &isrbar0->pcc_err_reg); + hldev->stats.sw_dev_info_stats.pcc_err_cnt++; + temp64 = XGE_HAL_PCC_FB_ECC_DB_ERR|XGE_HAL_PCC_TXB_ECC_DB_ERR + |XGE_HAL_PCC_SM_ERR_ALARM|XGE_HAL_PCC_WR_ERR_ALARM + |XGE_HAL_PCC_N_SERR|XGE_HAL_PCC_6_COF_OV_ERR + |XGE_HAL_PCC_7_COF_OV_ERR|XGE_HAL_PCC_6_LSO_OV_ERR + |XGE_HAL_PCC_7_LSO_OV_ERR; + if (val64 & temp64) + goto reset; + } + if (val64 & XGE_HAL_TXDMA_TTI_INT) { + err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->tti_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + err, &isrbar0->tti_err_reg); + hldev->stats.sw_dev_info_stats.tti_err_cnt++; + temp64 = XGE_HAL_TTI_SM_ERR_ALARM; + if (val64 & temp64) + goto reset; + } + if (val64 & XGE_HAL_TXDMA_LSO_INT) { + err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->lso_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + err, &isrbar0->lso_err_reg); + hldev->stats.sw_dev_info_stats.lso_err_cnt++; + temp64 = XGE_HAL_LSO6_ABORT|XGE_HAL_LSO7_ABORT + |XGE_HAL_LSO6_SM_ERR_ALARM|XGE_HAL_LSO7_SM_ERR_ALARM; + if (val64 & temp64) + goto reset; + } + if (val64 & XGE_HAL_TXDMA_TPA_INT) { + err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->tpa_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + err, &isrbar0->tpa_err_reg); + hldev->stats.sw_dev_info_stats.tpa_err_cnt++; + temp64 = XGE_HAL_TPA_SM_ERR_ALARM; + if (val64 & temp64) + goto reset; + } + if (val64 & XGE_HAL_TXDMA_SM_INT) { + err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->sm_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + err, &isrbar0->sm_err_reg); + hldev->stats.sw_dev_info_stats.sm_err_cnt++; + temp64 = XGE_HAL_SM_SM_ERR_ALARM; + if (val64 & temp64) + goto reset; + } + + return XGE_HAL_OK; + +reset : xge_hal_device_reset(hldev); + xge_hal_device_enable(hldev); + xge_hal_device_intr_enable(hldev); + return XGE_HAL_OK; +} + +/* + * __hal_device_handle_txmac - Handle TxMAC interrupt reason + * @hldev: HAL device handle. + * @reason: interrupt reason + */ +xge_hal_status_e +__hal_device_handle_txmac(xge_hal_device_t *hldev, u64 reason) +{ + xge_hal_pci_bar0_t *isrbar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; + u64 val64, temp64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->mac_int_status); + if (!(val64 & XGE_HAL_MAC_INT_STATUS_TMAC_INT)) + return XGE_HAL_OK; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->mac_tmac_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &isrbar0->mac_tmac_err_reg); + hldev->stats.sw_dev_info_stats.mac_tmac_err_cnt++; + temp64 = XGE_HAL_TMAC_TX_BUF_OVRN|XGE_HAL_TMAC_TX_SM_ERR; + if (val64 & temp64) { + xge_hal_device_reset(hldev); + xge_hal_device_enable(hldev); + xge_hal_device_intr_enable(hldev); + } + + return XGE_HAL_OK; +} + +/* + * __hal_device_handle_txxgxs - Handle TxXGXS interrupt reason + * @hldev: HAL device handle. + * @reason: interrupt reason + */ +xge_hal_status_e +__hal_device_handle_txxgxs(xge_hal_device_t *hldev, u64 reason) +{ + xge_hal_pci_bar0_t *isrbar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; + u64 val64, temp64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->xgxs_int_status); + if (!(val64 & XGE_HAL_XGXS_INT_STATUS_TXGXS)) + return XGE_HAL_OK; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->xgxs_txgxs_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &isrbar0->xgxs_txgxs_err_reg); + hldev->stats.sw_dev_info_stats.xgxs_txgxs_err_cnt++; + temp64 = XGE_HAL_TXGXS_ESTORE_UFLOW|XGE_HAL_TXGXS_TX_SM_ERR; + if (val64 & temp64) { + xge_hal_device_reset(hldev); + xge_hal_device_enable(hldev); + xge_hal_device_intr_enable(hldev); + } + + return XGE_HAL_OK; +} + +/* + * __hal_device_handle_rxpic - Handle RxPIC interrupt reason + * @hldev: HAL device handle. + * @reason: interrupt reason + */ +xge_hal_status_e +__hal_device_handle_rxpic(xge_hal_device_t *hldev, u64 reason) +{ + /* FIXME: handle register */ + + return XGE_HAL_OK; +} + +/* + * __hal_device_handle_rxdma - Handle RxDMA interrupt reason + * @hldev: HAL device handle. + * @reason: interrupt reason + */ +xge_hal_status_e +__hal_device_handle_rxdma(xge_hal_device_t *hldev, u64 reason) +{ + xge_hal_pci_bar0_t *isrbar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; + u64 val64, err, temp64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->rxdma_int_status); + if (val64 & XGE_HAL_RXDMA_RC_INT) { + err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->rc_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + err, &isrbar0->rc_err_reg); + hldev->stats.sw_dev_info_stats.rc_err_cnt++; + temp64 = XGE_HAL_RC_PRCn_ECC_DB_ERR|XGE_HAL_RC_FTC_ECC_DB_ERR + |XGE_HAL_RC_PRCn_SM_ERR_ALARM + |XGE_HAL_RC_FTC_SM_ERR_ALARM; + if (val64 & temp64) + goto reset; + } + if (val64 & XGE_HAL_RXDMA_RPA_INT) { + err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->rpa_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + err, &isrbar0->rpa_err_reg); + hldev->stats.sw_dev_info_stats.rpa_err_cnt++; + temp64 = XGE_HAL_RPA_SM_ERR_ALARM|XGE_HAL_RPA_CREDIT_ERR; + if (val64 & temp64) + goto reset; + } + if (val64 & XGE_HAL_RXDMA_RDA_INT) { + err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->rda_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + err, &isrbar0->rda_err_reg); + hldev->stats.sw_dev_info_stats.rda_err_cnt++; + temp64 = XGE_HAL_RDA_RXDn_ECC_DB_ERR + |XGE_HAL_RDA_FRM_ECC_DB_N_AERR + |XGE_HAL_RDA_SM1_ERR_ALARM|XGE_HAL_RDA_SM0_ERR_ALARM + |XGE_HAL_RDA_RXD_ECC_DB_SERR; + if (val64 & temp64) + goto reset; + } + if (val64 & XGE_HAL_RXDMA_RTI_INT) { + err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->rti_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + err, &isrbar0->rti_err_reg); + hldev->stats.sw_dev_info_stats.rti_err_cnt++; + temp64 = XGE_HAL_RTI_SM_ERR_ALARM; + if (val64 & temp64) + goto reset; + } + + return XGE_HAL_OK; + +reset : xge_hal_device_reset(hldev); + xge_hal_device_enable(hldev); + xge_hal_device_intr_enable(hldev); + return XGE_HAL_OK; +} + +/* + * __hal_device_handle_rxmac - Handle RxMAC interrupt reason + * @hldev: HAL device handle. + * @reason: interrupt reason + */ +xge_hal_status_e +__hal_device_handle_rxmac(xge_hal_device_t *hldev, u64 reason) +{ + xge_hal_pci_bar0_t *isrbar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; + u64 val64, temp64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->mac_int_status); + if (!(val64 & XGE_HAL_MAC_INT_STATUS_RMAC_INT)) + return XGE_HAL_OK; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->mac_rmac_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &isrbar0->mac_rmac_err_reg); + hldev->stats.sw_dev_info_stats.mac_rmac_err_cnt++; + temp64 = XGE_HAL_RMAC_RX_BUFF_OVRN|XGE_HAL_RMAC_RX_SM_ERR; + if (val64 & temp64) { + xge_hal_device_reset(hldev); + xge_hal_device_enable(hldev); + xge_hal_device_intr_enable(hldev); + } + + return XGE_HAL_OK; +} + +/* + * __hal_device_handle_rxxgxs - Handle RxXGXS interrupt reason + * @hldev: HAL device handle. + * @reason: interrupt reason + */ +xge_hal_status_e +__hal_device_handle_rxxgxs(xge_hal_device_t *hldev, u64 reason) +{ + xge_hal_pci_bar0_t *isrbar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; + u64 val64, temp64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->xgxs_int_status); + if (!(val64 & XGE_HAL_XGXS_INT_STATUS_RXGXS)) + return XGE_HAL_OK; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &isrbar0->xgxs_rxgxs_err_reg); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &isrbar0->xgxs_rxgxs_err_reg); + hldev->stats.sw_dev_info_stats.xgxs_rxgxs_err_cnt++; + temp64 = XGE_HAL_RXGXS_ESTORE_OFLOW|XGE_HAL_RXGXS_RX_SM_ERR; + if (val64 & temp64) { + xge_hal_device_reset(hldev); + xge_hal_device_enable(hldev); + xge_hal_device_intr_enable(hldev); + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_enable - Enable device. + * @hldev: HAL device handle. + * + * Enable the specified device: bring up the link/interface. + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT - Failed to restore the device + * to a "quiescent" state. + * + * See also: xge_hal_status_e{}. + * + * Usage: See ex_open{}. + */ +xge_hal_status_e +xge_hal_device_enable(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + u64 adp_status; + int i, j; + + if (!hldev->hw_is_initialized) { + xge_hal_status_e status; + + status = __hal_device_hw_initialize(hldev); + if (status != XGE_HAL_OK) { + return status; + } + } + + /* + * Not needed in most cases, i.e. + * when device_disable() is followed by reset - + * the latter copies back PCI config space, along with + * the bus mastership - see __hal_device_reset(). + * However, there are/may-in-future be other cases, and + * does not hurt. + */ + __hal_device_bus_master_enable(hldev); + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + /* + * Configure the link stability period. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->misc_control); + if (hldev->config.link_stability_period != + XGE_HAL_DEFAULT_USE_HARDCODE) { + + val64 |= XGE_HAL_MISC_CONTROL_LINK_STABILITY_PERIOD( + hldev->config.link_stability_period); + } else { + /* + * Use the link stability period 1 ms as default + */ + val64 |= XGE_HAL_MISC_CONTROL_LINK_STABILITY_PERIOD( + XGE_HAL_DEFAULT_LINK_STABILITY_PERIOD); + } + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->misc_control); + + /* + * Clearing any possible Link up/down interrupts that + * could have popped up just before Enabling the card. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->misc_int_reg); + if (val64) { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->misc_int_reg); + xge_debug_device(XGE_TRACE, "%s","link state cleared"); + } + } else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { + /* + * Clearing any possible Link state change interrupts that + * could have popped up just before Enabling the card. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mac_rmac_err_reg); + if (val64) { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->mac_rmac_err_reg); + xge_debug_device(XGE_TRACE, "%s", "link state cleared"); + } + } + + if (__hal_device_wait_quiescent(hldev, &val64)) { + return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; + } + + /* Enabling Laser. */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + val64 |= XGE_HAL_ADAPTER_EOI_TX_ON; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->adapter_control); + + /* let link establish */ + xge_os_mdelay(1); + + /* set link down untill poll() routine will set it up (maybe) */ + hldev->link_state = XGE_HAL_LINK_DOWN; + + /* If link is UP (adpter is connected) then enable the adapter */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_status); + if( val64 & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | + XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT) ) { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + val64 = val64 & (~XGE_HAL_ADAPTER_LED_ON); + } else { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + val64 = val64 | ( XGE_HAL_ADAPTER_EOI_TX_ON | + XGE_HAL_ADAPTER_LED_ON ); + } + + val64 = val64 | XGE_HAL_ADAPTER_CNTL_EN; /* adapter enable */ + val64 = val64 & (~XGE_HAL_ADAPTER_ECC_EN); /* ECC enable */ + xge_os_pio_mem_write64 (hldev->pdev, hldev->regh0, val64, + &bar0->adapter_control); + + /* We spin here waiting for the Link to come up. + * This is the fix for the Link being unstable after the reset. */ + i = 0; + j = 0; + do + { + adp_status = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_status); + + /* Read the adapter control register for Adapter_enable bit */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + if (!(adp_status & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | + XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)) && + (val64 & XGE_HAL_ADAPTER_CNTL_EN)) { + j++; + if (j >= hldev->config.link_valid_cnt) { + if (xge_hal_device_status(hldev, &adp_status) == + XGE_HAL_OK) { + if (__hal_verify_pcc_idle(hldev, + adp_status) != XGE_HAL_OK) { + return + XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; + } + xge_debug_device(XGE_TRACE, + "adp_status: "XGE_OS_LLXFMT + ", link is up on " + "adapter enable!", + (unsigned long long)adp_status); + val64 = xge_os_pio_mem_read64( + hldev->pdev, + hldev->regh0, + &bar0->adapter_control); + val64 = val64| + (XGE_HAL_ADAPTER_EOI_TX_ON | + XGE_HAL_ADAPTER_LED_ON ); + xge_os_pio_mem_write64(hldev->pdev, + hldev->regh0, val64, + &bar0->adapter_control); + xge_os_mdelay(1); + + val64 = xge_os_pio_mem_read64( + hldev->pdev, + hldev->regh0, + &bar0->adapter_control); + break; /* out of for loop */ + } else { + return + XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; + } + } + } else { + j = 0; /* Reset the count */ + /* Turn on the Laser */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + val64 = val64 | XGE_HAL_ADAPTER_EOI_TX_ON; + xge_os_pio_mem_write64 (hldev->pdev, hldev->regh0, + val64, &bar0->adapter_control); + + xge_os_mdelay(1); + + /* Now re-enable it as due to noise, hardware + * turned it off */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + val64 |= XGE_HAL_ADAPTER_CNTL_EN; + val64 = val64 & (~XGE_HAL_ADAPTER_ECC_EN);/*ECC enable*/ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->adapter_control); + } + xge_os_mdelay(1); /* Sleep for 1 msec */ + i++; + } while (i < hldev->config.link_retry_cnt); + + __hal_device_led_actifity_fix(hldev); + +#ifndef XGE_HAL_PROCESS_LINK_INT_IN_ISR + /* Here we are performing soft reset on XGXS to force link down. + * Since link is already up, we will get link state change + * poll notificatoin after adapter is enabled */ + + __hal_serial_mem_write64(hldev, 0x80010515001E0000ULL, + &bar0->dtx_control); + (void) __hal_serial_mem_read64(hldev, &bar0->dtx_control); + + __hal_serial_mem_write64(hldev, 0x80010515001E00E0ULL, + &bar0->dtx_control); + (void) __hal_serial_mem_read64(hldev, &bar0->dtx_control); + + __hal_serial_mem_write64(hldev, 0x80070515001F00E4ULL, + &bar0->dtx_control); + (void) __hal_serial_mem_read64(hldev, &bar0->dtx_control); + + xge_os_mdelay(100); /* Sleep for 500 msec */ +#else + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) +#endif + { + /* + * With some switches the link state change interrupt does not + * occur even though the xgxs reset is done as per SPN-006. So, + * poll the adapter status register and check if the link state + * is ok. + */ + adp_status = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_status); + if (!(adp_status & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | + XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT))) + { + xge_debug_device(XGE_TRACE, "%s", + "enable device causing link state change ind.."); + (void) __hal_device_handle_link_state_change(hldev); + } + } + + if (hldev->config.stats_refresh_time_sec != + XGE_HAL_STATS_REFRESH_DISABLE) + __hal_stats_enable(&hldev->stats); + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_disable - Disable Xframe adapter. + * @hldev: Device handle. + * + * Disable this device. To gracefully reset the adapter, the host should: + * + * - call xge_hal_device_disable(); + * + * - call xge_hal_device_intr_disable(); + * + * - close all opened channels and clean up outstanding resources; + * + * - do some work (error recovery, change mtu, reset, etc); + * + * - call xge_hal_device_enable(); + * + * - open channels, replenish RxDs, etc. + * + * - call xge_hal_device_intr_enable(). + * + * Note: Disabling the device does _not_ include disabling of interrupts. + * After disabling the device stops receiving new frames but those frames + * that were already in the pipe will keep coming for some few milliseconds. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT - Failed to restore the device to + * a "quiescent" state. + * + * See also: xge_hal_status_e{}. + */ +xge_hal_status_e +xge_hal_device_disable(xge_hal_device_t *hldev) +{ + xge_hal_status_e status = XGE_HAL_OK; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + xge_debug_device(XGE_TRACE, "%s", "turn off laser, cleanup hardware"); + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + val64 = val64 & (~XGE_HAL_ADAPTER_CNTL_EN); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->adapter_control); + + if (__hal_device_wait_quiescent(hldev, &val64) != XGE_HAL_OK) { + status = XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; + } + + if (__hal_device_register_poll(hldev, &bar0->adapter_status, 1, + XGE_HAL_ADAPTER_STATUS_RC_PRC_QUIESCENT, + XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + xge_debug_device(XGE_TRACE, "%s", "PRC is not QUIESCENT!"); + status = XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; + } + + if (hldev->config.stats_refresh_time_sec != + XGE_HAL_STATS_REFRESH_DISABLE) + __hal_stats_disable(&hldev->stats); +#ifdef XGE_DEBUG_ASSERT + else + xge_assert(!hldev->stats.is_enabled); +#endif + +#ifndef XGE_HAL_DONT_DISABLE_BUS_MASTER_ON_STOP + __hal_device_bus_master_disable(hldev); +#endif + + return status; +} + +/** + * xge_hal_device_reset - Reset device. + * @hldev: HAL device handle. + * + * Soft-reset the device, reset the device stats except reset_cnt. + * + * After reset is done, will try to re-initialize HW. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_DEVICE_NOT_INITIALIZED - Device is not initialized. + * XGE_HAL_ERR_RESET_FAILED - Reset failed. + * + * See also: xge_hal_status_e{}. + */ +xge_hal_status_e +xge_hal_device_reset(xge_hal_device_t *hldev) +{ + xge_hal_status_e status; + + /* increment the soft reset counter */ + u32 reset_cnt = hldev->stats.sw_dev_info_stats.soft_reset_cnt; + + xge_debug_device(XGE_TRACE, "%s (%d)", "resetting the device", reset_cnt); + + if (!hldev->is_initialized) + return XGE_HAL_ERR_DEVICE_NOT_INITIALIZED; + + /* actual "soft" reset of the adapter */ + status = __hal_device_reset(hldev); + + /* reset all stats including saved */ + __hal_stats_soft_reset(hldev, 1); + + /* increment reset counter */ + hldev->stats.sw_dev_info_stats.soft_reset_cnt = reset_cnt + 1; + + /* re-initialize rxufca_intr_thres */ + hldev->rxufca_intr_thres = hldev->config.rxufca_intr_thres; + + hldev->reset_needed_after_close = 0; + + return status; +} + +/** + * xge_hal_device_status - Check whether Xframe hardware is ready for + * operation. + * @hldev: HAL device handle. + * @hw_status: Xframe status register. Returned by HAL. + * + * Check whether Xframe hardware is ready for operation. + * The checking includes TDMA, RDMA, PFC, PIC, MC_DRAM, and the rest + * hardware functional blocks. + * + * Returns: XGE_HAL_OK if the device is ready for operation. Otherwise + * returns XGE_HAL_FAIL. Also, fills in adapter status (in @hw_status). + * + * See also: xge_hal_status_e{}. + * Usage: See ex_open{}. + */ +xge_hal_status_e +xge_hal_device_status(xge_hal_device_t *hldev, u64 *hw_status) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 tmp64; + + tmp64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_status); + + *hw_status = tmp64; + + if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_TDMA_READY)) { + xge_debug_device(XGE_TRACE, "%s", "TDMA is not ready!"); + return XGE_HAL_FAIL; + } + if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_RDMA_READY)) { + xge_debug_device(XGE_TRACE, "%s", "RDMA is not ready!"); + return XGE_HAL_FAIL; + } + if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_PFC_READY)) { + xge_debug_device(XGE_TRACE, "%s", "PFC is not ready!"); + return XGE_HAL_FAIL; + } + if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_TMAC_BUF_EMPTY)) { + xge_debug_device(XGE_TRACE, "%s", "TMAC BUF is not empty!"); + return XGE_HAL_FAIL; + } + if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_PIC_QUIESCENT)) { + xge_debug_device(XGE_TRACE, "%s", "PIC is not QUIESCENT!"); + return XGE_HAL_FAIL; + } + if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_MC_DRAM_READY)) { + xge_debug_device(XGE_TRACE, "%s", "MC_DRAM is not ready!"); + return XGE_HAL_FAIL; + } + if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_MC_QUEUES_READY)) { + xge_debug_device(XGE_TRACE, "%s", "MC_QUEUES is not ready!"); + return XGE_HAL_FAIL; + } + if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_M_PLL_LOCK)) { + xge_debug_device(XGE_TRACE, "%s", "M_PLL is not locked!"); + return XGE_HAL_FAIL; + } +#ifndef XGE_HAL_HERC_EMULATION + /* + * Andrew: in PCI 33 mode, the P_PLL is not used, and therefore, + * the the P_PLL_LOCK bit in the adapter_status register will + * not be asserted. + */ + if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_P_PLL_LOCK) && + xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC && + hldev->pci_mode != XGE_HAL_PCI_33MHZ_MODE) { + xge_debug_device(XGE_TRACE, "%s", "P_PLL is not locked!"); + return XGE_HAL_FAIL; + } +#endif + + return XGE_HAL_OK; +} + +void +__hal_device_msi_intr_endis(xge_hal_device_t *hldev, int flag) +{ + u16 msi_control_reg; + + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, + msi_control), &msi_control_reg); + + if (flag) + msi_control_reg |= 0x1; + else + msi_control_reg &= ~0x1; + + xge_os_pci_write16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, + msi_control), msi_control_reg); +} + +void +__hal_device_msix_intr_endis(xge_hal_device_t *hldev, + xge_hal_channel_t *channel, int flag) +{ + u64 val64; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->xmsi_mask_reg); + + if (flag) + val64 &= ~(1LL << ( 63 - channel->msix_idx )); + else + val64 |= (1LL << ( 63 - channel->msix_idx )); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->xmsi_mask_reg); +} + +/** + * xge_hal_device_intr_enable - Enable Xframe interrupts. + * @hldev: HAL device handle. + * @op: One of the xge_hal_device_intr_e enumerated values specifying + * the type(s) of interrupts to enable. + * + * Enable Xframe interrupts. The function is to be executed the last in + * Xframe initialization sequence. + * + * See also: xge_hal_device_intr_disable() + */ +void +xge_hal_device_intr_enable(xge_hal_device_t *hldev) +{ + xge_list_t *item; + u64 val64; + + /* PRC initialization and configuration */ + xge_list_for_each(item, &hldev->ring_channels) { + xge_hal_channel_h channel; + channel = xge_container_of(item, xge_hal_channel_t, item); + __hal_ring_prc_enable(channel); + } + + /* enable traffic only interrupts */ + if (hldev->config.intr_mode != XGE_HAL_INTR_MODE_IRQLINE) { + /* + * make sure all interrupts going to be disabled if MSI + * is enabled. + */ + __hal_device_intr_mgmt(hldev, XGE_HAL_ALL_INTRS, 0); + } else { + /* + * Enable the Tx traffic interrupts only if the TTI feature is + * enabled. + */ + val64 = 0; + if (hldev->tti_enabled) + val64 = XGE_HAL_TX_TRAFFIC_INTR; + + if (!hldev->config.bimodal_interrupts) + val64 |= XGE_HAL_RX_TRAFFIC_INTR; + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) + val64 |= XGE_HAL_RX_TRAFFIC_INTR; + + val64 |=XGE_HAL_TX_PIC_INTR | + XGE_HAL_MC_INTR | + XGE_HAL_TX_DMA_INTR | + (hldev->config.sched_timer_us != + XGE_HAL_SCHED_TIMER_DISABLED ? XGE_HAL_SCHED_INTR : 0); + __hal_device_intr_mgmt(hldev, val64, 1); + } + + /* + * Enable MSI-X interrupts + */ + if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + /* + * To enable MSI-X, MSI also needs to be enabled, + * due to a bug in the herc NIC. + */ + __hal_device_msi_intr_endis(hldev, 1); + } + + + /* Enable the MSI-X interrupt for each configured channel */ + xge_list_for_each(item, &hldev->fifo_channels) { + xge_hal_channel_t *channel; + + channel = xge_container_of(item, + xge_hal_channel_t, item); + + /* 0 vector is reserved for alarms */ + if (!channel->msix_idx) + continue; + + __hal_device_msix_intr_endis(hldev, channel, 1); + } + + xge_list_for_each(item, &hldev->ring_channels) { + xge_hal_channel_t *channel; + + channel = xge_container_of(item, + xge_hal_channel_t, item); + + /* 0 vector is reserved for alarms */ + if (!channel->msix_idx) + continue; + + __hal_device_msix_intr_endis(hldev, channel, 1); + } + } + + xge_debug_device(XGE_TRACE, "%s", "interrupts are enabled"); +} + + +/** + * xge_hal_device_intr_disable - Disable Xframe interrupts. + * @hldev: HAL device handle. + * @op: One of the xge_hal_device_intr_e enumerated values specifying + * the type(s) of interrupts to disable. + * + * Disable Xframe interrupts. + * + * See also: xge_hal_device_intr_enable() + */ +void +xge_hal_device_intr_disable(xge_hal_device_t *hldev) +{ + xge_list_t *item; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + /* + * To disable MSI-X, MSI also needs to be disabled, + * due to a bug in the herc NIC. + */ + __hal_device_msi_intr_endis(hldev, 0); + } + + /* Disable the MSI-X interrupt for each configured channel */ + xge_list_for_each(item, &hldev->fifo_channels) { + xge_hal_channel_t *channel; + + channel = xge_container_of(item, + xge_hal_channel_t, item); + + /* 0 vector is reserved for alarms */ + if (!channel->msix_idx) + continue; + + __hal_device_msix_intr_endis(hldev, channel, 0); + + } + + xge_os_pio_mem_write64(hldev->pdev, + hldev->regh0, 0xFFFFFFFFFFFFFFFFULL, + &bar0->tx_traffic_mask); + + xge_list_for_each(item, &hldev->ring_channels) { + xge_hal_channel_t *channel; + + channel = xge_container_of(item, + xge_hal_channel_t, item); + + /* 0 vector is reserved for alarms */ + if (!channel->msix_idx) + continue; + + __hal_device_msix_intr_endis(hldev, channel, 0); + } + + xge_os_pio_mem_write64(hldev->pdev, + hldev->regh0, 0xFFFFFFFFFFFFFFFFULL, + &bar0->rx_traffic_mask); + } + + /* + * Disable traffic only interrupts. + * Tx traffic interrupts are used only if the TTI feature is + * enabled. + */ + val64 = 0; + if (hldev->tti_enabled) + val64 = XGE_HAL_TX_TRAFFIC_INTR; + + val64 |= XGE_HAL_RX_TRAFFIC_INTR | + XGE_HAL_TX_PIC_INTR | + XGE_HAL_MC_INTR | + (hldev->config.sched_timer_us != XGE_HAL_SCHED_TIMER_DISABLED ? + XGE_HAL_SCHED_INTR : 0); + __hal_device_intr_mgmt(hldev, val64, 0); + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + 0xFFFFFFFFFFFFFFFFULL, + &bar0->general_int_mask); + + + /* disable all configured PRCs */ + xge_list_for_each(item, &hldev->ring_channels) { + xge_hal_channel_h channel; + channel = xge_container_of(item, xge_hal_channel_t, item); + __hal_ring_prc_disable(channel); + } + + xge_debug_device(XGE_TRACE, "%s", "interrupts are disabled"); +} + + +/** + * xge_hal_device_mcast_enable - Enable Xframe multicast addresses. + * @hldev: HAL device handle. + * + * Enable Xframe multicast addresses. + * Returns: XGE_HAL_OK on success. + * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to enable mcast + * feature within the time(timeout). + * + * See also: xge_hal_device_mcast_disable(), xge_hal_status_e{}. + */ +xge_hal_status_e +xge_hal_device_mcast_enable(xge_hal_device_t *hldev) +{ + u64 val64; + xge_hal_pci_bar0_t *bar0; + int mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET; + + if (hldev == NULL) + return XGE_HAL_ERR_INVALID_DEVICE; + + if (hldev->mcast_refcnt) + return XGE_HAL_OK; + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) + mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET_HERC; + + hldev->mcast_refcnt = 1; + + bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + + /* Enable all Multicast addresses */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_RMAC_ADDR_DATA0_MEM_ADDR(0x010203040506ULL), + &bar0->rmac_addr_data0_mem); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_RMAC_ADDR_DATA1_MEM_MASK(0xfeffffffffffULL), + &bar0->rmac_addr_data1_mem); + val64 = XGE_HAL_RMAC_ADDR_CMD_MEM_WE | + XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | + XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET(mc_offset); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rmac_addr_cmd_mem); + + if (__hal_device_register_poll(hldev, + &bar0->rmac_addr_cmd_mem, 0, + XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + /* upper layer may require to repeat */ + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_mcast_disable - Disable Xframe multicast addresses. + * @hldev: HAL device handle. + * + * Disable Xframe multicast addresses. + * Returns: XGE_HAL_OK - success. + * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to disable mcast + * feature within the time(timeout). + * + * See also: xge_hal_device_mcast_enable(), xge_hal_status_e{}. + */ +xge_hal_status_e +xge_hal_device_mcast_disable(xge_hal_device_t *hldev) +{ + u64 val64; + xge_hal_pci_bar0_t *bar0; + int mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET; + + if (hldev == NULL) + return XGE_HAL_ERR_INVALID_DEVICE; + + if (hldev->mcast_refcnt == 0) + return XGE_HAL_OK; + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) + mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET_HERC; + + hldev->mcast_refcnt = 0; + + bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + + /* Disable all Multicast addresses */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_RMAC_ADDR_DATA0_MEM_ADDR(0xffffffffffffULL), + &bar0->rmac_addr_data0_mem); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_RMAC_ADDR_DATA1_MEM_MASK(0), + &bar0->rmac_addr_data1_mem); + + val64 = XGE_HAL_RMAC_ADDR_CMD_MEM_WE | + XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | + XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET(mc_offset); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rmac_addr_cmd_mem); + + if (__hal_device_register_poll(hldev, + &bar0->rmac_addr_cmd_mem, 0, + XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + /* upper layer may require to repeat */ + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_promisc_enable - Enable promiscuous mode. + * @hldev: HAL device handle. + * + * Enable promiscuous mode of Xframe operation. + * + * See also: xge_hal_device_promisc_disable(). + */ +void +xge_hal_device_promisc_enable(xge_hal_device_t *hldev) +{ + u64 val64; + xge_hal_pci_bar0_t *bar0; + + xge_assert(hldev); + + bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + + if (!hldev->is_promisc) { + /* Put the NIC into promiscuous mode */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mac_cfg); + val64 |= XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_RMAC_CFG_KEY(0x4C0D), + &bar0->rmac_cfg_key); + + __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, + (u32)(val64 >> 32), + &bar0->mac_cfg); + + hldev->is_promisc = 1; + xge_debug_device(XGE_TRACE, + "mac_cfg 0x"XGE_OS_LLXFMT": promisc enabled", + (unsigned long long)val64); + } +} + +/** + * xge_hal_device_promisc_disable - Disable promiscuous mode. + * @hldev: HAL device handle. + * + * Disable promiscuous mode of Xframe operation. + * + * See also: xge_hal_device_promisc_enable(). + */ +void +xge_hal_device_promisc_disable(xge_hal_device_t *hldev) +{ + u64 val64; + xge_hal_pci_bar0_t *bar0; + + xge_assert(hldev); + + bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + + if (hldev->is_promisc) { + /* Remove the NIC from promiscuous mode */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mac_cfg); + val64 &= ~XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_RMAC_CFG_KEY(0x4C0D), + &bar0->rmac_cfg_key); + + __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, + (u32)(val64 >> 32), + &bar0->mac_cfg); + + hldev->is_promisc = 0; + xge_debug_device(XGE_TRACE, + "mac_cfg 0x"XGE_OS_LLXFMT": promisc disabled", + (unsigned long long)val64); + } +} + +/** + * xge_hal_device_macaddr_get - Get MAC addresses. + * @hldev: HAL device handle. + * @index: MAC address index, in the range from 0 to + * XGE_HAL_MAX_MAC_ADDRESSES. + * @macaddr: MAC address. Returned by HAL. + * + * Retrieve one of the stored MAC addresses by reading non-volatile + * memory on the chip. + * + * Up to %XGE_HAL_MAX_MAC_ADDRESSES addresses is supported. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to retrieve the mac + * address within the time(timeout). + * XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES - Invalid MAC address index. + * + * See also: xge_hal_device_macaddr_set(), xge_hal_status_e{}. + */ +xge_hal_status_e +xge_hal_device_macaddr_get(xge_hal_device_t *hldev, int index, + macaddr_t *macaddr) +{ + xge_hal_pci_bar0_t *bar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + int i; + + if (hldev == NULL) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if ( index >= XGE_HAL_MAX_MAC_ADDRESSES ) { + return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; + } + +#ifdef XGE_HAL_HERC_EMULATION + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,0x0000010000000000, + &bar0->rmac_addr_data0_mem); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,0x0000000000000000, + &bar0->rmac_addr_data1_mem); + val64 = XGE_HAL_RMAC_ADDR_CMD_MEM_RD | + XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | + XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET((index)); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rmac_addr_cmd_mem); + + /* poll until done */ + __hal_device_register_poll(hldev, + &bar0->rmac_addr_cmd_mem, 0, + XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS); + +#endif + + val64 = ( XGE_HAL_RMAC_ADDR_CMD_MEM_RD | + XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | + XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET((index)) ); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rmac_addr_cmd_mem); + + if (__hal_device_register_poll(hldev, &bar0->rmac_addr_cmd_mem, 0, + XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + /* upper layer may require to repeat */ + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rmac_addr_data0_mem); + for (i=0; i < XGE_HAL_ETH_ALEN; i++) { + (*macaddr)[i] = (u8)(val64 >> ((64 - 8) - (i * 8))); + } + +#ifdef XGE_HAL_HERC_EMULATION + for (i=0; i < XGE_HAL_ETH_ALEN; i++) { + (*macaddr)[i] = (u8)0; + } + (*macaddr)[1] = (u8)1; + +#endif + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_macaddr_set - Set MAC address. + * @hldev: HAL device handle. + * @index: MAC address index, in the range from 0 to + * XGE_HAL_MAX_MAC_ADDRESSES. + * @macaddr: New MAC address to configure. + * + * Configure one of the available MAC address "slots". + * + * Up to %XGE_HAL_MAX_MAC_ADDRESSES addresses is supported. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to set the new mac + * address within the time(timeout). + * XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES - Invalid MAC address index. + * + * See also: xge_hal_device_macaddr_get(), xge_hal_status_e{}. + */ +xge_hal_status_e +xge_hal_device_macaddr_set(xge_hal_device_t *hldev, int index, + macaddr_t macaddr) +{ + xge_hal_pci_bar0_t *bar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64, temp64; + int i; + + if ( index >= XGE_HAL_MAX_MAC_ADDRESSES ) + return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; + + temp64 = 0; + for (i=0; i < XGE_HAL_ETH_ALEN; i++) { + temp64 |= macaddr[i]; + temp64 <<= 8; + } + temp64 >>= 8; + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_RMAC_ADDR_DATA0_MEM_ADDR(temp64), + &bar0->rmac_addr_data0_mem); + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_RMAC_ADDR_DATA1_MEM_MASK(0ULL), + &bar0->rmac_addr_data1_mem); + + val64 = ( XGE_HAL_RMAC_ADDR_CMD_MEM_WE | + XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | + XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET((index)) ); + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rmac_addr_cmd_mem); + + if (__hal_device_register_poll(hldev, &bar0->rmac_addr_cmd_mem, 0, + XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + /* upper layer may require to repeat */ + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_macaddr_clear - Set MAC address. + * @hldev: HAL device handle. + * @index: MAC address index, in the range from 0 to + * XGE_HAL_MAX_MAC_ADDRESSES. + * + * Clear one of the available MAC address "slots". + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to set the new mac + * address within the time(timeout). + * XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES - Invalid MAC address index. + * + * See also: xge_hal_device_macaddr_set(), xge_hal_status_e{}. + */ +xge_hal_status_e +xge_hal_device_macaddr_clear(xge_hal_device_t *hldev, int index) +{ + xge_hal_status_e status; + u8 macaddr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + status = xge_hal_device_macaddr_set(hldev, index, macaddr); + if (status != XGE_HAL_OK) { + xge_debug_device(XGE_ERR, "%s", + "Not able to set the mac addr"); + return status; + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_macaddr_find - Finds index in the rmac table. + * @hldev: HAL device handle. + * @wanted: Wanted MAC address. + * + * See also: xge_hal_device_macaddr_set(). + */ +int +xge_hal_device_macaddr_find(xge_hal_device_t *hldev, macaddr_t wanted) +{ + int i; + + if (hldev == NULL) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + for (i=1; i<XGE_HAL_MAX_MAC_ADDRESSES; i++) { + macaddr_t macaddr; + (void) xge_hal_device_macaddr_get(hldev, i, &macaddr); + if (!xge_os_memcmp(macaddr, wanted, sizeof(macaddr_t))) { + return i; + } + } + + return -1; +} + +/** + * xge_hal_device_mtu_set - Set MTU. + * @hldev: HAL device handle. + * @new_mtu: New MTU size to configure. + * + * Set new MTU value. Example, to use jumbo frames: + * xge_hal_device_mtu_set(my_device, my_channel, 9600); + * + * Returns: XGE_HAL_OK on success. + * XGE_HAL_ERR_SWAPPER_CTRL - Failed to configure swapper control + * register. + * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to initialize TTI/RTI + * schemes. + * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT - Failed to restore the device to + * a "quiescent" state. + */ +xge_hal_status_e +xge_hal_device_mtu_set(xge_hal_device_t *hldev, int new_mtu) +{ + xge_hal_status_e status; + + /* + * reset needed if 1) new MTU differs, and + * 2a) device was closed or + * 2b) device is being upped for first time. + */ + if (hldev->config.mtu != new_mtu) { + if (hldev->reset_needed_after_close || + !hldev->mtu_first_time_set) { + status = xge_hal_device_reset(hldev); + if (status != XGE_HAL_OK) { + xge_debug_device(XGE_TRACE, "%s", + "fatal: can not reset the device"); + return status; + } + } + /* store the new MTU in device, reset will use it */ + hldev->config.mtu = new_mtu; + xge_debug_device(XGE_TRACE, "new MTU %d applied", + new_mtu); + } + + if (!hldev->mtu_first_time_set) + hldev->mtu_first_time_set = 1; + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_initialize - Initialize Xframe device. + * @hldev: HAL device handle. + * @attr: pointer to xge_hal_device_attr_t structure + * @device_config: Configuration to be _applied_ to the device, + * For the Xframe configuration "knobs" please + * refer to xge_hal_device_config_t and Xframe + * User Guide. + * + * Initialize Xframe device. Note that all the arguments of this public API + * are 'IN', including @hldev. Upper-layer driver (ULD) cooperates with + * OS to find new Xframe device, locate its PCI and memory spaces. + * + * When done, the ULD allocates sizeof(xge_hal_device_t) bytes for HAL + * to enable the latter to perform Xframe hardware initialization. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_DRIVER_NOT_INITIALIZED - Driver is not initialized. + * XGE_HAL_ERR_BAD_DEVICE_CONFIG - Device configuration params are not + * valid. + * XGE_HAL_ERR_OUT_OF_MEMORY - Memory allocation failed. + * XGE_HAL_ERR_BAD_SUBSYSTEM_ID - Device subsystem id is invalid. + * XGE_HAL_ERR_INVALID_MAC_ADDRESS - Device mac address in not valid. + * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to retrieve the mac + * address within the time(timeout) or TTI/RTI initialization failed. + * XGE_HAL_ERR_SWAPPER_CTRL - Failed to configure swapper control. + * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT -Device is not queiscent. + * + * See also: xge_hal_device_terminate(), xge_hal_status_e{} + * xge_hal_device_attr_t{}. + */ +xge_hal_status_e +xge_hal_device_initialize(xge_hal_device_t *hldev, xge_hal_device_attr_t *attr, + xge_hal_device_config_t *device_config) +{ + int i; + xge_hal_status_e status; + xge_hal_channel_t *channel; + u16 subsys_device; + u16 subsys_vendor; + int total_dram_size, ring_auto_dram_cfg, left_dram_size; + int total_dram_size_max = 0; + + xge_debug_device(XGE_TRACE, "device 0x"XGE_OS_LLXFMT" is initializing", + (unsigned long long)(ulong_t)hldev); + + /* sanity check */ + if (g_xge_hal_driver == NULL || + !g_xge_hal_driver->is_initialized) { + return XGE_HAL_ERR_DRIVER_NOT_INITIALIZED; + } + + xge_os_memzero(hldev, sizeof(xge_hal_device_t)); + + /* + * validate a common part of Xframe-I/II configuration + * (and run check_card() later, once PCI inited - see below) + */ + status = __hal_device_config_check_common(device_config); + if (status != XGE_HAL_OK) + return status; + + /* apply config */ + xge_os_memcpy(&hldev->config, device_config, + sizeof(xge_hal_device_config_t)); + + /* save original attr */ + xge_os_memcpy(&hldev->orig_attr, attr, + sizeof(xge_hal_device_attr_t)); + + /* initialize rxufca_intr_thres */ + hldev->rxufca_intr_thres = hldev->config.rxufca_intr_thres; + + hldev->regh0 = attr->regh0; + hldev->regh1 = attr->regh1; + hldev->regh2 = attr->regh2; + hldev->isrbar0 = hldev->bar0 = attr->bar0; + hldev->bar1 = attr->bar1; + hldev->bar2 = attr->bar2; + hldev->pdev = attr->pdev; + hldev->irqh = attr->irqh; + hldev->cfgh = attr->cfgh; + + /* set initial bimodal timer for bimodal adaptive schema */ + hldev->bimodal_timer_val_us = hldev->config.bimodal_timer_lo_us; + + hldev->queueh = xge_queue_create(hldev->pdev, hldev->irqh, + g_xge_hal_driver->config.queue_size_initial, + g_xge_hal_driver->config.queue_size_max, + __hal_device_event_queued, hldev); + if (hldev->queueh == NULL) + return XGE_HAL_ERR_OUT_OF_MEMORY; + + hldev->magic = XGE_HAL_MAGIC; + + xge_assert(hldev->regh0); + xge_assert(hldev->regh1); + xge_assert(hldev->bar0); + xge_assert(hldev->bar1); + xge_assert(hldev->pdev); + xge_assert(hldev->irqh); + xge_assert(hldev->cfgh); + + /* initialize some PCI/PCI-X fields of this PCI device. */ + __hal_device_pci_init(hldev); + + /* + * initlialize lists to properly handling a potential + * terminate request + */ + xge_list_init(&hldev->free_channels); + xge_list_init(&hldev->fifo_channels); + xge_list_init(&hldev->ring_channels); + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { + /* fixups for xena */ + hldev->config.rth_en = 0; + hldev->config.rth_spdm_en = 0; + hldev->config.rts_mac_en = 0; + total_dram_size_max = XGE_HAL_MAX_RING_QUEUE_SIZE_XENA; + + status = __hal_device_config_check_xena(device_config); + if (status != XGE_HAL_OK) { + xge_hal_device_terminate(hldev); + return status; + } + if (hldev->config.bimodal_interrupts == 1) { + xge_hal_device_terminate(hldev); + return XGE_HAL_BADCFG_BIMODAL_XENA_NOT_ALLOWED; + } else if (hldev->config.bimodal_interrupts == + XGE_HAL_DEFAULT_USE_HARDCODE) + hldev->config.bimodal_interrupts = 0; + } else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + /* fixups for herc */ + total_dram_size_max = XGE_HAL_MAX_RING_QUEUE_SIZE_HERC; + status = __hal_device_config_check_herc(device_config); + if (status != XGE_HAL_OK) { + xge_hal_device_terminate(hldev); + return status; + } + if (hldev->config.bimodal_interrupts == + XGE_HAL_DEFAULT_USE_HARDCODE) + hldev->config.bimodal_interrupts = 1; + } else { + xge_debug_device(XGE_ERR, + "detected unknown device_id 0x%x", hldev->device_id); + xge_hal_device_terminate(hldev); + return XGE_HAL_ERR_BAD_DEVICE_ID; + } + +#ifdef XGEHAL_RNIC + + if(__hal_blockpool_create(hldev,&hldev->block_pool, + XGE_HAL_BLOCKPOOL_SIZE) != XGE_HAL_OK) { + xge_debug_device(XGE_ERR, + "block pool: __hal_blockpool_create failed"); + xge_hal_device_terminate(hldev); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + + if(__hal_regpool_create(hldev,&hldev->reg_pool, + XGE_HAL_REGPOOL_SIZE) != XGE_HAL_OK) { + xge_debug_device(XGE_ERR, + "reg pool: __hal_regpool_create failed"); + xge_hal_device_terminate(hldev); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + + for(i = 0; i < XGE_HAL_MAX_VIRTUAL_PATHS; i++) { + if(__hal_vp_initialize(hldev, i, &device_config->vp_config[i]) + != XGE_HAL_OK) { + xge_debug_device(XGE_ERR, + "virtual Paths: __hal_vp_initialize failed"); + xge_hal_device_terminate(hldev); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + } + +#endif + + /* allocate and initialize FIFO types of channels according to + * configuration */ + for (i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) { + if (!device_config->fifo.queue[i].configured) + continue; + + channel = __hal_channel_allocate(hldev, i, +#ifdef XGEHAL_RNIC + 0, +#endif + XGE_HAL_CHANNEL_TYPE_FIFO); + if (channel == NULL) { + xge_debug_device(XGE_ERR, + "fifo: __hal_channel_allocate failed"); + xge_hal_device_terminate(hldev); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + /* add new channel to the device */ + xge_list_insert(&channel->item, &hldev->free_channels); + } + + /* + * automatic DRAM adjustment + */ + total_dram_size = 0; + ring_auto_dram_cfg = 0; + for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { + if (!device_config->ring.queue[i].configured) + continue; + if (device_config->ring.queue[i].dram_size_mb == + XGE_HAL_DEFAULT_USE_HARDCODE) { + ring_auto_dram_cfg++; + continue; + } + total_dram_size += device_config->ring.queue[i].dram_size_mb; + } + left_dram_size = total_dram_size_max - total_dram_size; + if (left_dram_size < 0 || + (ring_auto_dram_cfg && left_dram_size / ring_auto_dram_cfg == 0)) { + xge_debug_device(XGE_ERR, + "ring config: exceeded DRAM size %d MB", + total_dram_size_max); + xge_hal_device_terminate(hldev); + return XGE_HAL_BADCFG_RING_QUEUE_SIZE; + } + + /* + * allocate and initialize RING types of channels according to + * configuration + */ + for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { + if (!device_config->ring.queue[i].configured) + continue; + + if (device_config->ring.queue[i].dram_size_mb == + XGE_HAL_DEFAULT_USE_HARDCODE) { + hldev->config.ring.queue[i].dram_size_mb = + device_config->ring.queue[i].dram_size_mb = + left_dram_size / ring_auto_dram_cfg; + } + + channel = __hal_channel_allocate(hldev, i, +#ifdef XGEHAL_RNIC + 0, +#endif + XGE_HAL_CHANNEL_TYPE_RING); + if (channel == NULL) { + xge_debug_device(XGE_ERR, + "ring: __hal_channel_allocate failed"); + xge_hal_device_terminate(hldev); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + /* add new channel to the device */ + xge_list_insert(&channel->item, &hldev->free_channels); + } + + /* get subsystem IDs */ + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, subsystem_id), + &subsys_device); + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, subsystem_vendor_id), + &subsys_vendor); + xge_debug_device(XGE_TRACE, + "subsystem_id %04x:%04x", + subsys_vendor, subsys_device); + + /* reset device initially */ + (void) __hal_device_reset(hldev); + + /* set host endian before, to assure proper action */ + status = __hal_device_set_swapper(hldev); + if (status != XGE_HAL_OK) { + xge_debug_device(XGE_ERR, + "__hal_device_set_swapper failed"); + xge_hal_device_terminate(hldev); + (void) __hal_device_reset(hldev); + return status; + } + +#ifndef XGE_HAL_HERC_EMULATION + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) + __hal_device_xena_fix_mac(hldev); +#endif + + /* MAC address initialization. + * For now only one mac address will be read and used. */ + status = xge_hal_device_macaddr_get(hldev, 0, &hldev->macaddr[0]); + if (status != XGE_HAL_OK) { + xge_debug_device(XGE_ERR, + "xge_hal_device_macaddr_get failed"); + xge_hal_device_terminate(hldev); + return status; + } + + if (hldev->macaddr[0][0] == 0xFF && + hldev->macaddr[0][1] == 0xFF && + hldev->macaddr[0][2] == 0xFF && + hldev->macaddr[0][3] == 0xFF && + hldev->macaddr[0][4] == 0xFF && + hldev->macaddr[0][5] == 0xFF) { + xge_debug_device(XGE_ERR, + "xge_hal_device_macaddr_get returns all FFs"); + xge_hal_device_terminate(hldev); + return XGE_HAL_ERR_INVALID_MAC_ADDRESS; + } + + xge_debug_device(XGE_TRACE, + "default macaddr: 0x%02x-%02x-%02x-%02x-%02x-%02x", + hldev->macaddr[0][0], hldev->macaddr[0][1], + hldev->macaddr[0][2], hldev->macaddr[0][3], + hldev->macaddr[0][4], hldev->macaddr[0][5]); + + status = __hal_stats_initialize(&hldev->stats, hldev); + if (status != XGE_HAL_OK) { + xge_debug_device(XGE_ERR, + "__hal_stats_initialize failed"); + xge_hal_device_terminate(hldev); + return status; + } + + status = __hal_device_hw_initialize(hldev); + if (status != XGE_HAL_OK) { + xge_debug_device(XGE_ERR, + "__hal_device_hw_initialize failed"); + xge_hal_device_terminate(hldev); + return status; + } + hldev->dump_buf=(char*)xge_os_malloc(hldev->pdev, XGE_HAL_DUMP_BUF_SIZE); + if (hldev->dump_buf == NULL) { + xge_debug_device(XGE_ERR, + "__hal_device_hw_initialize failed"); + xge_hal_device_terminate(hldev); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + + + /* Xena-only: need to serialize fifo posts across all device fifos */ +#if defined(XGE_HAL_TX_MULTI_POST) + xge_os_spin_lock_init(&hldev->xena_post_lock, hldev->pdev); +#elif defined(XGE_HAL_TX_MULTI_POST_IRQ) + xge_os_spin_lock_init_irq(&hldev->xena_post_lock, hldev->irqh); +#endif + /* Getting VPD data */ + __hal_device_get_vpd_data(hldev); + + hldev->is_initialized = 1; + + return XGE_HAL_OK; +} + +/** + * xge_hal_device_terminating - Mark the device as 'terminating'. + * @devh: HAL device handle. + * + * Mark the device as 'terminating', going to terminate. Can be used + * to serialize termination with other running processes/contexts. + * + * See also: xge_hal_device_terminate(). + */ +void +xge_hal_device_terminating(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + hldev->terminating = 1; +} + +/** + * xge_hal_device_terminate - Terminate Xframe device. + * @hldev: HAL device handle. + * + * Terminate HAL device. + * + * See also: xge_hal_device_initialize(). + */ +void +xge_hal_device_terminate(xge_hal_device_t *hldev) +{ +#ifdef XGEHAL_RNIC + int i; +#endif + xge_assert(g_xge_hal_driver != NULL); + xge_assert(hldev != NULL); + xge_assert(hldev->magic == XGE_HAL_MAGIC); + + xge_queue_flush(hldev->queueh); + + hldev->terminating = 1; + hldev->is_initialized = 0; + hldev->in_poll = 0; + hldev->magic = XGE_HAL_DEAD; + +#if defined(XGE_HAL_TX_MULTI_POST) + xge_os_spin_lock_destroy(&hldev->xena_post_lock, hldev->pdev); +#elif defined(XGE_HAL_TX_MULTI_POST_IRQ) + xge_os_spin_lock_destroy_irq(&hldev->xena_post_lock, hldev->pdev); +#endif + + xge_debug_device(XGE_TRACE, "device "XGE_OS_LLXFMT" is terminating", + (unsigned long long)(ulong_t)hldev); + + xge_assert(xge_list_is_empty(&hldev->fifo_channels)); + xge_assert(xge_list_is_empty(&hldev->ring_channels)); + + if (hldev->stats.is_initialized) { + __hal_stats_terminate(&hldev->stats); + } + + /* close if open and free all channels */ + while (!xge_list_is_empty(&hldev->free_channels)) { + xge_hal_channel_t *channel = (xge_hal_channel_t*) + hldev->free_channels.next; + + xge_assert(!channel->is_open); + xge_list_remove(&channel->item); + __hal_channel_free(channel); + } + + if (hldev->queueh) { + xge_queue_destroy(hldev->queueh); + } + + if (hldev->spdm_table) { + xge_os_free(hldev->pdev, + hldev->spdm_table[0], + (sizeof(xge_hal_spdm_entry_t) * + hldev->spdm_max_entries)); + xge_os_free(hldev->pdev, + hldev->spdm_table, + (sizeof(xge_hal_spdm_entry_t *) * + hldev->spdm_max_entries)); + xge_os_spin_lock_destroy(&hldev->spdm_lock, hldev->pdev); + hldev->spdm_table = NULL; + } + + if (hldev->dump_buf) { + xge_os_free(hldev->pdev, hldev->dump_buf, + XGE_HAL_DUMP_BUF_SIZE); + hldev->dump_buf = NULL; + } + + if (hldev->device_id != 0) { + int j, pcisize; + + pcisize = (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)? + XGE_HAL_PCISIZE_HERC : XGE_HAL_PCISIZE_XENA; + for (j = 0; j < pcisize; j++) { + xge_os_pci_write32(hldev->pdev, hldev->cfgh, j * 4, + *((u32*)&hldev->pci_config_space_bios + j)); + } + } +#ifdef XGEHAL_RNIC + + for(i = 0; i < XGE_HAL_MAX_VIRTUAL_PATHS; i++) { + __hal_vp_terminate(hldev, i); + } + + __hal_blockpool_destroy(&hldev->block_pool); + + __hal_regpool_destroy(&hldev->reg_pool); +#endif + +} +/** + * __hal_device_get_vpd_data - Getting vpd_data. + * + * @hldev: HAL device handle. + * + * Getting product name and serial number from vpd capabilites structure + * + */ +void +__hal_device_get_vpd_data(xge_hal_device_t *hldev) +{ + u8 * vpd_data; + u8 data; + int index = 0, count, fail = 0; + u8 vpd_addr = XGE_HAL_CARD_XENA_VPD_ADDR; + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) + vpd_addr = XGE_HAL_CARD_HERC_VPD_ADDR; + + xge_os_strcpy((char *) hldev->vpd_data.product_name, + "10 Gigabit Ethernet Adapter"); + xge_os_strcpy((char *) hldev->vpd_data.serial_num, "not available"); + + vpd_data = ( u8*) xge_os_malloc(hldev->pdev, XGE_HAL_VPD_BUFFER_SIZE); + if ( vpd_data == 0 ) + return; + + for (index = 0; index < XGE_HAL_VPD_BUFFER_SIZE; index +=4 ) { + xge_os_pci_write8(hldev->pdev, hldev->cfgh, (vpd_addr + 2), (u8)index); + xge_os_pci_read8(hldev->pdev, hldev->cfgh,(vpd_addr + 2), &data); + xge_os_pci_write8(hldev->pdev, hldev->cfgh, (vpd_addr + 3), 0); + for (count = 0; count < 5; count++ ) { + xge_os_mdelay(2); + xge_os_pci_read8(hldev->pdev, hldev->cfgh,(vpd_addr + 3), &data); + if (data == XGE_HAL_VPD_READ_COMPLETE) + break; + } + + if (count >= 5) { + xge_os_printf("ERR, Reading VPD data failed"); + fail = 1; + break; + } + + xge_os_pci_read32(hldev->pdev, hldev->cfgh,(vpd_addr + 4), + (u32 *)&vpd_data[index]); + } + + if(!fail) { + + /* read serial number of adapter */ + for (count = 0; count < XGE_HAL_VPD_BUFFER_SIZE; count++) { + if ((vpd_data[count] == 'S') && + (vpd_data[count + 1] == 'N') && + (vpd_data[count + 2] < XGE_HAL_VPD_LENGTH)) { + memset(hldev->vpd_data.serial_num, 0, XGE_HAL_VPD_LENGTH); + memcpy(hldev->vpd_data.serial_num, &vpd_data[count + 3], + vpd_data[count + 2]); + break; + } + } + + if (vpd_data[1] < XGE_HAL_VPD_LENGTH) { + memset(hldev->vpd_data.product_name, 0, vpd_data[1]); + memcpy(hldev->vpd_data.product_name, &vpd_data[3], vpd_data[1]); + } + + } + + xge_os_free(hldev->pdev, vpd_data, XGE_HAL_VPD_BUFFER_SIZE); +} + + +/** + * xge_hal_device_handle_tcode - Handle transfer code. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * @t_code: One of the enumerated (and documented in the Xframe user guide) + * "transfer codes". + * + * Handle descriptor's transfer code. The latter comes with each completed + * descriptor, see xge_hal_fifo_dtr_next_completed() and + * xge_hal_ring_dtr_next_completed(). + * Transfer codes are enumerated in xgehal-fifo.h and xgehal-ring.h. + * + * Returns: one of the xge_hal_status_e{} enumerated types. + * XGE_HAL_OK - for success. + * XGE_HAL_ERR_CRITICAL - when encounters critical error. + */ +xge_hal_status_e +xge_hal_device_handle_tcode (xge_hal_channel_h channelh, + xge_hal_dtr_h dtrh, u8 t_code) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + xge_hal_device_t *hldev = (xge_hal_device_t *)channel->devh; + + if (t_code > 15) { + xge_os_printf("invalid t_code %d", t_code); + return XGE_HAL_OK; + } + + if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { + hldev->stats.sw_dev_err_stats.txd_t_code_err_cnt[t_code]++; + +#if defined(XGE_HAL_DEBUG_BAD_TCODE) + xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh; + xge_os_printf(""XGE_OS_LLXFMT":"XGE_OS_LLXFMT":" + XGE_OS_LLXFMT":"XGE_OS_LLXFMT, + txdp->control_1, txdp->control_2, txdp->buffer_pointer, + txdp->host_control); +#endif + + /* handle link "down" immediately without going through + * xge_hal_device_poll() routine. */ + if (t_code == XGE_HAL_TXD_T_CODE_LOSS_OF_LINK) { + /* link is down */ + if (hldev->link_state != XGE_HAL_LINK_DOWN) { + xge_hal_pci_bar0_t *bar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + hldev->link_state = XGE_HAL_LINK_DOWN; + + val64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->adapter_control); + + /* turn off LED */ + val64 = val64 & (~XGE_HAL_ADAPTER_LED_ON); + xge_os_pio_mem_write64(hldev->pdev, + hldev->regh0, val64, + &bar0->adapter_control); + + g_xge_hal_driver->uld_callbacks.link_down( + hldev->upper_layer_info); + } + } else if (t_code == XGE_HAL_TXD_T_CODE_ABORT_BUFFER || + t_code == XGE_HAL_TXD_T_CODE_ABORT_DTOR) { + __hal_device_handle_targetabort(hldev); + return XGE_HAL_ERR_CRITICAL; + } + return XGE_HAL_ERR_PKT_DROP; + } else if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { + hldev->stats.sw_dev_err_stats.rxd_t_code_err_cnt[t_code]++; + +#if defined(XGE_HAL_DEBUG_BAD_TCODE) + xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh; + xge_os_printf(""XGE_OS_LLXFMT":"XGE_OS_LLXFMT":"XGE_OS_LLXFMT + ":"XGE_OS_LLXFMT, rxdp->control_1, + rxdp->control_2, rxdp->buffer0_ptr, + rxdp->host_control); +#endif + if (t_code == XGE_HAL_RXD_T_CODE_BAD_ECC) { + hldev->stats.sw_dev_err_stats.ecc_err_cnt++; + __hal_device_handle_eccerr(hldev, "rxd_t_code", + (u64)t_code); + return XGE_HAL_ERR_CRITICAL; + } else if (t_code == XGE_HAL_RXD_T_CODE_PARITY || + t_code == XGE_HAL_RXD_T_CODE_PARITY_ABORT) { + hldev->stats.sw_dev_err_stats.parity_err_cnt++; + __hal_device_handle_parityerr(hldev, "rxd_t_code", + (u64)t_code); + return XGE_HAL_ERR_CRITICAL; + /* do not drop if detected unknown IPv6 extension */ + } else if (t_code != XGE_HAL_RXD_T_CODE_UNKNOWN_PROTO) { + return XGE_HAL_ERR_PKT_DROP; + } + } + return XGE_HAL_OK; +} + +/** + * xge_hal_device_link_state - Get link state. + * @devh: HAL device handle. + * @ls: Link state, see xge_hal_device_link_state_e{}. + * + * Get link state. + * Returns: XGE_HAL_OK. + * See also: xge_hal_device_link_state_e{}. + */ +xge_hal_status_e xge_hal_device_link_state(xge_hal_device_h devh, + xge_hal_device_link_state_e *ls) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + + xge_assert(ls != NULL); + *ls = hldev->link_state; + return XGE_HAL_OK; +} + +/** + * xge_hal_device_sched_timer - Configure scheduled device interrupt. + * @devh: HAL device handle. + * @interval_us: Time interval, in miscoseconds. + * Unlike transmit and receive interrupts, + * the scheduled interrupt is generated independently of + * traffic, but purely based on time. + * @one_shot: 1 - generate scheduled interrupt only once. + * 0 - generate scheduled interrupt periodically at the specified + * @interval_us interval. + * + * (Re-)configure scheduled interrupt. Can be called at runtime to change + * the setting, generate one-shot interrupts based on the resource and/or + * traffic conditions, other purposes. + * See also: xge_hal_device_config_t{}. + */ +void xge_hal_device_sched_timer(xge_hal_device_h devh, int interval_us, + int one_shot) +{ + u64 val64; + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + xge_hal_pci_bar0_t *bar0 = + (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + unsigned int interval = hldev->config.pci_freq_mherz * interval_us; + + interval = __hal_fix_time_ival_herc(hldev, interval); + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->scheduled_int_ctrl); + if (interval) { + val64 &= XGE_HAL_SCHED_INT_PERIOD_MASK; + val64 |= XGE_HAL_SCHED_INT_PERIOD(interval); + if (one_shot) { + val64 |= XGE_HAL_SCHED_INT_CTRL_ONE_SHOT; + } + val64 |= XGE_HAL_SCHED_INT_CTRL_TIMER_EN; + } else { + val64 &= ~XGE_HAL_SCHED_INT_CTRL_TIMER_EN; + } + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->scheduled_int_ctrl); + + xge_debug_device(XGE_TRACE, "sched_timer 0x"XGE_OS_LLXFMT": %s", + (unsigned long long)val64, + interval ? "enabled" : "disabled"); +} + +/** + * xge_hal_device_check_id - Verify device ID. + * @devh: HAL device handle. + * + * Verify device ID. + * Returns: one of the xge_hal_card_e{} enumerated types. + * See also: xge_hal_card_e{}. + */ +xge_hal_card_e +xge_hal_device_check_id(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + switch (hldev->device_id) { + case XGE_PCI_DEVICE_ID_XENA_1: + case XGE_PCI_DEVICE_ID_XENA_2: + return XGE_HAL_CARD_XENA; + case XGE_PCI_DEVICE_ID_HERC_1: + case XGE_PCI_DEVICE_ID_HERC_2: + return XGE_HAL_CARD_HERC; + case XGE_PCI_DEVICE_ID_TITAN_1: + case XGE_PCI_DEVICE_ID_TITAN_2: + return XGE_HAL_CARD_TITAN; + default: + return XGE_HAL_CARD_UNKNOWN; + } +} + +/** + * xge_hal_device_pci_info_get - Get PCI bus informations such as width, + * frequency, and mode from previously stored values. + * @devh: HAL device handle. + * @pci_mode: pointer to a variable of enumerated type + * xge_hal_pci_mode_e{}. + * @bus_frequency: pointer to a variable of enumerated type + * xge_hal_pci_bus_frequency_e{}. + * @bus_width: pointer to a variable of enumerated type + * xge_hal_pci_bus_width_e{}. + * + * Get pci mode, frequency, and PCI bus width. + * Returns: one of the xge_hal_status_e{} enumerated types. + * XGE_HAL_OK - for success. + * XGE_HAL_ERR_INVALID_DEVICE - for invalid device handle. + * See Also: xge_hal_pci_mode_e, xge_hal_pci_mode_e, xge_hal_pci_width_e. + */ +xge_hal_status_e +xge_hal_device_pci_info_get(xge_hal_device_h devh, xge_hal_pci_mode_e *pci_mode, + xge_hal_pci_bus_frequency_e *bus_frequency, + xge_hal_pci_bus_width_e *bus_width) +{ + xge_hal_status_e rc_status; + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + + if (!hldev || !hldev->is_initialized || hldev->magic != XGE_HAL_MAGIC) { + rc_status = XGE_HAL_ERR_INVALID_DEVICE; + xge_debug_device(XGE_ERR, + "xge_hal_device_pci_info_get error, rc %d for device %p", + rc_status, hldev); + + return rc_status; + } + + *pci_mode = hldev->pci_mode; + *bus_frequency = hldev->bus_frequency; + *bus_width = hldev->bus_width; + rc_status = XGE_HAL_OK; + return rc_status; +} + +/** + * xge_hal_reinitialize_hw + * @hldev: private member of the device structure. + * + * This function will soft reset the NIC and re-initalize all the + * I/O registers to the values they had after it's inital initialization + * through the probe function. + */ +int xge_hal_reinitialize_hw(xge_hal_device_t * hldev) +{ + (void) xge_hal_device_reset(hldev); + if (__hal_device_hw_initialize(hldev) != XGE_HAL_OK) { + xge_hal_device_terminate(hldev); + (void) __hal_device_reset(hldev); + return 1; + } + return 0; +} + + +/* + * __hal_read_spdm_entry_line + * @hldev: pointer to xge_hal_device_t structure + * @spdm_line: spdm line in the spdm entry to be read. + * @spdm_entry: spdm entry of the spdm_line in the SPDM table. + * @spdm_line_val: Contains the value stored in the spdm line. + * + * SPDM table contains upto a maximum of 256 spdm entries. + * Each spdm entry contains 8 lines and each line stores 8 bytes. + * This function reads the spdm line(addressed by @spdm_line) + * of the spdm entry(addressed by @spdm_entry) in + * the SPDM table. + */ +xge_hal_status_e +__hal_read_spdm_entry_line(xge_hal_device_t *hldev, u8 spdm_line, + u16 spdm_entry, u64 *spdm_line_val) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + val64 = XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_STROBE | + XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_LINE_SEL(spdm_line) | + XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_OFFSET(spdm_entry); + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_rth_spdm_mem_ctrl); + + /* poll until done */ + if (__hal_device_register_poll(hldev, + &bar0->rts_rth_spdm_mem_ctrl, 0, + XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_STROBE, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + + *spdm_line_val = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->rts_rth_spdm_mem_data); + return XGE_HAL_OK; +} + + +/* + * __hal_get_free_spdm_entry + * @hldev: pointer to xge_hal_device_t structure + * @spdm_entry: Contains an index to the unused spdm entry in the SPDM table. + * + * This function returns an index of unused spdm entry in the SPDM + * table. + */ +static xge_hal_status_e +__hal_get_free_spdm_entry(xge_hal_device_t *hldev, u16 *spdm_entry) +{ + xge_hal_status_e status; + u64 spdm_line_val=0; + + /* + * Search in the local SPDM table for a free slot. + */ + *spdm_entry = 0; + for(; *spdm_entry < hldev->spdm_max_entries; (*spdm_entry)++) { + if (hldev->spdm_table[*spdm_entry]->in_use) { + break; + } + } + + if (*spdm_entry >= hldev->spdm_max_entries) { + return XGE_HAL_ERR_SPDM_TABLE_FULL; + } + + /* + * Make sure that the corresponding spdm entry in the SPDM + * table is free. + * Seventh line of the spdm entry contains information about + * whether the entry is free or not. + */ + if ((status = __hal_read_spdm_entry_line(hldev, 7, *spdm_entry, + &spdm_line_val)) != XGE_HAL_OK) { + return status; + } + + /* BIT(63) in spdm_line 7 corresponds to entry_enable bit */ + if ((spdm_line_val & BIT(63))) { + /* + * Log a warning + */ + xge_debug_device(XGE_ERR, "Local SPDM table is not " + "consistent with the actual one for the spdm " + "entry %d", *spdm_entry); + return XGE_HAL_ERR_SPDM_TABLE_DATA_INCONSISTENT; + } + + return XGE_HAL_OK; +} + + +/* + * __hal_calc_jhash - Calculate Jenkins hash. + * @msg: Jenkins hash algorithm key. + * @length: Length of the key. + * @golden_ratio: Jenkins hash golden ratio. + * @init_value: Jenkins hash initial value. + * + * This function implements the Jenkins based algorithm used for the + * calculation of the RTH hash. + * Returns: Jenkins hash value. + * + */ +static u32 +__hal_calc_jhash(u8 *msg, u32 length, u32 golden_ratio, u32 init_value) +{ + + register u32 a,b,c,len; + + /* + * Set up the internal state + */ + len = length; + a = b = golden_ratio; /* the golden ratio; an arbitrary value */ + c = init_value; /* the previous hash value */ + + /* handle most of the key */ + while (len >= 12) + { + a += (msg[0] + ((u32)msg[1]<<8) + ((u32)msg[2]<<16) + + ((u32)msg[3]<<24)); + b += (msg[4] + ((u32)msg[5]<<8) + ((u32)msg[6]<<16) + + ((u32)msg[7]<<24)); + c += (msg[8] + ((u32)msg[9]<<8) + ((u32)msg[10]<<16) + + ((u32)msg[11]<<24)); + mix(a,b,c); + msg += 12; len -= 12; + } + + /* handle the last 11 bytes */ + c += length; + switch(len) /* all the case statements fall through */ + { + case 11: c+= ((u32)msg[10]<<24); + break; + case 10: c+= ((u32)msg[9]<<16); + break; + case 9 : c+= ((u32)msg[8]<<8); + break; + /* the first byte of c is reserved for the length */ + case 8 : b+= ((u32)msg[7]<<24); + break; + case 7 : b+= ((u32)msg[6]<<16); + break; + case 6 : b+= ((u32)msg[5]<<8); + break; + case 5 : b+= msg[4]; + break; + case 4 : a+= ((u32)msg[3]<<24); + break; + case 3 : a+= ((u32)msg[2]<<16); + break; + case 2 : a+= ((u32)msg[1]<<8); + break; + case 1 : a+= msg[0]; + break; + /* case 0: nothing left to add */ + } + + mix(a,b,c); + + /* report the result */ + return c; +} + + +/** + * xge_hal_spdm_entry_add - Add a new entry to the SPDM table. + * @devh: HAL device handle. + * @src_ip: Source ip address(IPv4/IPv6). + * @dst_ip: Destination ip address(IPv4/IPv6). + * @l4_sp: L4 source port. + * @l4_dp: L4 destination port. + * @is_tcp: Set to 1, if the protocol is TCP. + * 0, if the protocol is UDP. + * @is_ipv4: Set to 1, if the protocol is IPv4. + * 0, if the protocol is IPv6. + * @tgt_queue: Target queue to route the receive packet. + * + * This function add a new entry to the SPDM table. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_SPDM_NOT_ENABLED - SPDM support is not enabled. + * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to add a new entry with in + * the time(timeout). + * XGE_HAL_ERR_SPDM_TABLE_FULL - SPDM table is full. + * XGE_HAL_ERR_SPDM_INVALID_ENTRY - Invalid SPDM entry. + * + * See also: xge_hal_spdm_entry_remove{}. + */ +xge_hal_status_e +xge_hal_spdm_entry_add(xge_hal_device_h devh, xge_hal_ipaddr_t *src_ip, + xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp, + u8 is_tcp, u8 is_ipv4, u8 tgt_queue) +{ + + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u32 jhash_value; + u32 jhash_init_val; + u32 jhash_golden_ratio; + u64 val64; + int off; + u16 spdm_entry; + u8 msg[XGE_HAL_JHASH_MSG_LEN]; + int ipaddr_len; + xge_hal_status_e status; + + + if (!hldev->config.rth_spdm_en) { + return XGE_HAL_ERR_SPDM_NOT_ENABLED; + } + + if ((tgt_queue < XGE_HAL_MIN_RING_NUM) || + (tgt_queue > XGE_HAL_MAX_RING_NUM)) { + return XGE_HAL_ERR_SPDM_INVALID_ENTRY; + } + + + /* + * Calculate the jenkins hash. + */ + /* + * Create the Jenkins hash algorithm key. + * key = {L3SA, L3DA, L4SP, L4DP}, if SPDM is configured to + * use L4 information. Otherwize key = {L3SA, L3DA}. + */ + + if (is_ipv4) { + ipaddr_len = 4; // In bytes + } else { + ipaddr_len = 16; + } + + /* + * Jenkins hash algorithm expects the key in the big endian + * format. Since key is the byte array, memcpy won't work in the + * case of little endian. So, the current code extracts each + * byte starting from MSB and store it in the key. + */ + if (is_ipv4) { + for (off = 0; off < ipaddr_len; off++) { + u32 mask = vBIT32(0xff,(off*8),8); + int shift = 32-(off+1)*8; + msg[off] = (u8)((src_ip->ipv4.addr & mask) >> shift); + msg[off+ipaddr_len] = + (u8)((dst_ip->ipv4.addr & mask) >> shift); + } + } else { + for (off = 0; off < ipaddr_len; off++) { + int loc = off % 8; + u64 mask = vBIT(0xff,(loc*8),8); + int shift = 64-(loc+1)*8; + + msg[off] = (u8)((src_ip->ipv6.addr[off/8] & mask) + >> shift); + msg[off+ipaddr_len] = (u8)((dst_ip->ipv6.addr[off/8] + & mask) >> shift); + } + } + + off = (2*ipaddr_len); + + if (hldev->config.rth_spdm_use_l4) { + msg[off] = (u8)((l4_sp & 0xff00) >> 8); + msg[off + 1] = (u8)(l4_sp & 0xff); + msg[off + 2] = (u8)((l4_dp & 0xff00) >> 8); + msg[off + 3] = (u8)(l4_dp & 0xff); + off += 4; + } + + /* + * Calculate jenkins hash for this configuration + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, + &bar0->rts_rth_jhash_cfg); + jhash_golden_ratio = (u32)(val64 >> 32); + jhash_init_val = (u32)(val64 & 0xffffffff); + + jhash_value = __hal_calc_jhash(msg, off, + jhash_golden_ratio, + jhash_init_val); + + xge_os_spin_lock(&hldev->spdm_lock); + + /* + * Locate a free slot in the SPDM table. To avoid a seach in the + * actual SPDM table, which is very expensive in terms of time, + * we are maintaining a local copy of the table and the search for + * the free entry is performed in the local table. + */ + if ((status = __hal_get_free_spdm_entry(hldev,&spdm_entry)) + != XGE_HAL_OK) { + xge_os_spin_unlock(&hldev->spdm_lock); + return status; + } + + /* + * Add this entry to the SPDM table + */ + status = __hal_spdm_entry_add(hldev, src_ip, dst_ip, l4_sp, l4_dp, + is_tcp, is_ipv4, tgt_queue, + jhash_value, /* calculated jhash */ + spdm_entry); + + xge_os_spin_unlock(&hldev->spdm_lock); + + return status; +} + +/** + * xge_hal_spdm_entry_remove - Remove an entry from the SPDM table. + * @devh: HAL device handle. + * @src_ip: Source ip address(IPv4/IPv6). + * @dst_ip: Destination ip address(IPv4/IPv6). + * @l4_sp: L4 source port. + * @l4_dp: L4 destination port. + * @is_tcp: Set to 1, if the protocol is TCP. + * 0, if the protocol os UDP. + * @is_ipv4: Set to 1, if the protocol is IPv4. + * 0, if the protocol is IPv6. + * + * This function remove an entry from the SPDM table. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_SPDM_NOT_ENABLED - SPDM support is not enabled. + * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to remove an entry with in + * the time(timeout). + * XGE_HAL_ERR_SPDM_ENTRY_NOT_FOUND - Unable to locate the entry in the SPDM + * table. + * + * See also: xge_hal_spdm_entry_add{}. + */ +xge_hal_status_e +xge_hal_spdm_entry_remove(xge_hal_device_h devh, xge_hal_ipaddr_t *src_ip, + xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp, + u8 is_tcp, u8 is_ipv4) +{ + + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + u16 spdm_entry; + xge_hal_status_e status; + u64 spdm_line_arr[8]; + u8 line_no; + u8 spdm_is_tcp; + u8 spdm_is_ipv4; + u16 spdm_l4_sp; + u16 spdm_l4_dp; + + if (!hldev->config.rth_spdm_en) { + return XGE_HAL_ERR_SPDM_NOT_ENABLED; + } + + xge_os_spin_lock(&hldev->spdm_lock); + + /* + * Poll the rxpic_int_reg register until spdm ready bit is set or + * timeout happens. + */ + if (__hal_device_register_poll(hldev, &bar0->rxpic_int_reg, 1, + XGE_HAL_RX_PIC_INT_REG_SPDM_READY, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + + /* upper layer may require to repeat */ + xge_os_spin_unlock(&hldev->spdm_lock); + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + + /* + * Clear the SPDM READY bit. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rxpic_int_reg); + val64 &= ~XGE_HAL_RX_PIC_INT_REG_SPDM_READY; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rxpic_int_reg); + + /* + * Search in the local SPDM table to get the index of the + * corresponding entry in the SPDM table. + */ + spdm_entry = 0; + for (;spdm_entry < hldev->spdm_max_entries; spdm_entry++) { + if ((!hldev->spdm_table[spdm_entry]->in_use) || + (hldev->spdm_table[spdm_entry]->is_tcp != is_tcp) || + (hldev->spdm_table[spdm_entry]->l4_sp != l4_sp) || + (hldev->spdm_table[spdm_entry]->l4_dp != l4_dp) || + (hldev->spdm_table[spdm_entry]->is_ipv4 != is_ipv4)) { + continue; + } + + /* + * Compare the src/dst IP addresses of source and target + */ + if (is_ipv4) { + if ((hldev->spdm_table[spdm_entry]->src_ip.ipv4.addr + != src_ip->ipv4.addr) || + (hldev->spdm_table[spdm_entry]->dst_ip.ipv4.addr + != dst_ip->ipv4.addr)) { + continue; + } + } else { + if ((hldev->spdm_table[spdm_entry]->src_ip.ipv6.addr[0] + != src_ip->ipv6.addr[0]) || + (hldev->spdm_table[spdm_entry]->src_ip.ipv6.addr[1] + != src_ip->ipv6.addr[1]) || + (hldev->spdm_table[spdm_entry]->dst_ip.ipv6.addr[0] + != dst_ip->ipv6.addr[0]) || + (hldev->spdm_table[spdm_entry]->dst_ip.ipv6.addr[1] + != dst_ip->ipv6.addr[1])) { + continue; + } + } + break; + } + + if (spdm_entry >= hldev->spdm_max_entries) { + xge_os_spin_unlock(&hldev->spdm_lock); + return XGE_HAL_ERR_SPDM_ENTRY_NOT_FOUND; + } + + /* + * Retrieve the corresponding entry from the SPDM table and + * make sure that the data is consistent. + */ + for(line_no = 0; line_no < 8; line_no++) { + + /* + * SPDM line 2,3,4 are valid only for IPv6 entry. + * SPDM line 5 & 6 are reserved. We don't have to + * read these entries in the above cases. + */ + if (((is_ipv4) && + ((line_no == 2)||(line_no == 3)||(line_no == 4))) || + (line_no == 5) || + (line_no == 6)) { + continue; + } + + if ((status = __hal_read_spdm_entry_line( + hldev, + line_no, + spdm_entry, + &spdm_line_arr[line_no])) + != XGE_HAL_OK) { + xge_os_spin_unlock(&hldev->spdm_lock); + return status; + } + } + + /* + * Seventh line of the spdm entry contains the entry_enable + * bit. Make sure that the entry_enable bit of this spdm entry + * is set. + * To remove an entry from the SPDM table, reset this + * bit. + */ + if (!(spdm_line_arr[7] & BIT(63))) { + /* + * Log a warning + */ + xge_debug_device(XGE_ERR, "Local SPDM table is not " + "consistent with the actual one for the spdm " + "entry %d ", spdm_entry); + goto err_exit; + } + + /* + * Retreive the L4 SP/DP, src/dst ip addresses from the SPDM + * table and do a comparision. + */ + spdm_is_tcp = (u8)((spdm_line_arr[0] & BIT(59)) >> 4); + spdm_is_ipv4 = (u8)(spdm_line_arr[0] & BIT(63)); + spdm_l4_sp = (u16)(spdm_line_arr[0] >> 48); + spdm_l4_dp = (u16)((spdm_line_arr[0] >> 32) & 0xffff); + + + if ((spdm_is_tcp != is_tcp) || + (spdm_is_ipv4 != is_ipv4) || + (spdm_l4_sp != l4_sp) || + (spdm_l4_dp != l4_dp)) { + /* + * Log a warning + */ + xge_debug_device(XGE_ERR, "Local SPDM table is not " + "consistent with the actual one for the spdm " + "entry %d ", spdm_entry); + goto err_exit; + } + + if (is_ipv4) { + /* Upper 32 bits of spdm_line(64 bit) contains the + * src IPv4 address. Lower 32 bits of spdm_line + * contains the destination IPv4 address. + */ + u32 temp_src_ip = (u32)(spdm_line_arr[1] >> 32); + u32 temp_dst_ip = (u32)(spdm_line_arr[1] & 0xffffffff); + + if ((temp_src_ip != src_ip->ipv4.addr) || + (temp_dst_ip != dst_ip->ipv4.addr)) { + xge_debug_device(XGE_ERR, "Local SPDM table is not " + "consistent with the actual one for the spdm " + "entry %d ", spdm_entry); + goto err_exit; + } + + } else { + /* + * SPDM line 1 & 2 contains the src IPv6 address. + * SPDM line 3 & 4 contains the dst IPv6 address. + */ + if ((spdm_line_arr[1] != src_ip->ipv6.addr[0]) || + (spdm_line_arr[2] != src_ip->ipv6.addr[1]) || + (spdm_line_arr[3] != dst_ip->ipv6.addr[0]) || + (spdm_line_arr[4] != dst_ip->ipv6.addr[1])) { + + /* + * Log a warning + */ + xge_debug_device(XGE_ERR, "Local SPDM table is not " + "consistent with the actual one for the spdm " + "entry %d ", spdm_entry); + goto err_exit; + } + } + + /* + * Reset the entry_enable bit to zero + */ + spdm_line_arr[7] &= ~BIT(63); + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + spdm_line_arr[7], + (void *)((char *)hldev->spdm_mem_base + + (spdm_entry * 64) + (7 * 8))); + + /* + * Wait for the operation to be completed. + */ + if (__hal_device_register_poll(hldev, + &bar0->rxpic_int_reg, 1, + XGE_HAL_RX_PIC_INT_REG_SPDM_READY, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + xge_os_spin_unlock(&hldev->spdm_lock); + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + + /* + * Make the corresponding spdm entry in the local SPDM table + * available for future use. + */ + hldev->spdm_table[spdm_entry]->in_use = 0; + xge_os_spin_unlock(&hldev->spdm_lock); + + return XGE_HAL_OK; + +err_exit: + xge_os_spin_unlock(&hldev->spdm_lock); + return XGE_HAL_ERR_SPDM_TABLE_DATA_INCONSISTENT; +} + +/* + * __hal_device_rti_set + * @ring: The post_qid of the ring. + * @channel: HAL channel of the ring. + * + * This function stores the RTI value associated for the MSI and + * also unmasks this particular RTI in the rti_mask register. + */ +static void __hal_device_rti_set(int ring_qid, xge_hal_channel_t *channel) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64; + + if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSI || + hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) + channel->rti = (u8)ring_qid; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rx_traffic_mask); + val64 &= ~BIT(ring_qid); + xge_os_pio_mem_write64(hldev->pdev, + hldev->regh0, val64, + &bar0->rx_traffic_mask); +} + +/* + * __hal_device_tti_set + * @ring: The post_qid of the FIFO. + * @channel: HAL channel the FIFO. + * + * This function stores the TTI value associated for the MSI and + * also unmasks this particular TTI in the tti_mask register. + */ +static void __hal_device_tti_set(int fifo_qid, xge_hal_channel_t *channel) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64; + + if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSI || + hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) + channel->tti = (u8)fifo_qid; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->tx_traffic_mask); + val64 &= ~BIT(fifo_qid); + xge_os_pio_mem_write64(hldev->pdev, + hldev->regh0, val64, + &bar0->tx_traffic_mask); +} + +/** + * xge_hal_channel_msi_set - Associate a RTI with a ring or TTI with a + * FIFO for a given MSI. + * @channelh: HAL channel handle. + * @msi: MSI Number associated with the channel. + * @msi_msg: The MSI message associated with the MSI number above. + * + * This API will associate a given channel (either Ring or FIFO) with the + * given MSI number. It will alo program the Tx_Mat/Rx_Mat tables in the + * hardware to indicate this association to the hardware. + */ +xge_hal_status_e +xge_hal_channel_msi_set(xge_hal_channel_h channelh, int msi, u32 msi_msg) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64; + + channel->msi_msg = msi_msg; + if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { + int ring = channel->post_qid; + xge_debug_osdep(XGE_TRACE, "MSI Data: 0x%4x, Ring: %d," + " MSI: %d", channel->msi_msg, ring, msi); + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rx_mat); + val64 |= XGE_HAL_SET_RX_MAT(ring, msi); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rx_mat); + __hal_device_rti_set(ring, channel); + } else { + int fifo = channel->post_qid; + xge_debug_osdep(XGE_TRACE, "MSI Data: 0x%4x, Fifo: %d," + " MSI: %d", channel->msi_msg, fifo, msi); + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->tx_mat[0]); + val64 |= XGE_HAL_SET_TX_MAT(fifo, msi); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->tx_mat[0]); + __hal_device_tti_set(fifo, channel); + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_mask_msix - Begin IRQ processing. + * @hldev: HAL device handle. + * @msi_id: MSI ID + * + * The function masks the msix interrupt for the given msi_id + * + * Note: + * + * Returns: 0, + * Otherwise, XGE_HAL_ERR_WRONG_IRQ if the msix index is out of range + * status. + * See also: + */ +xge_hal_status_e +xge_hal_mask_msix(xge_hal_device_h devh, int msi_id) +{ + xge_hal_status_e status = XGE_HAL_OK; + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + u32 *bar2 = (u32 *)hldev->bar2; + u32 val32; + + xge_assert(msi_id < XGE_HAL_MAX_MSIX_MESSAGES); + + val32 = xge_os_pio_mem_read32(hldev->pdev, hldev->regh2, &bar2[msi_id*4+3]); + val32 |= 1; + xge_os_pio_mem_write32(hldev->pdev, hldev->regh2, val32, &bar2[msi_id*4+3]); + return status; +} + +/** + * xge_hal_mask_msix - Begin IRQ processing. + * @hldev: HAL device handle. + * @msi_id: MSI ID + * + * The function masks the msix interrupt for the given msi_id + * + * Note: + * + * Returns: 0, + * Otherwise, XGE_HAL_ERR_WRONG_IRQ if the msix index is out of range + * status. + * See also: + */ +xge_hal_status_e +xge_hal_unmask_msix(xge_hal_device_h devh, int msi_id) +{ + xge_hal_status_e status = XGE_HAL_OK; + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + u32 *bar2 = (u32 *)hldev->bar2; + u32 val32; + + xge_assert(msi_id < XGE_HAL_MAX_MSIX_MESSAGES); + + val32 = xge_os_pio_mem_read32(hldev->pdev, hldev->regh2, &bar2[msi_id*4+3]); + val32 &= ~1; + xge_os_pio_mem_write32(hldev->pdev, hldev->regh2, val32, &bar2[msi_id*4+3]); + return status; +} + +/* + * __hal_set_msix_vals + * @devh: HAL device handle. + * @msix_value: 32bit MSI-X value transferred across PCI to @msix_address. + * Filled in by this function. + * @msix_address: 32bit MSI-X DMA address. + * Filled in by this function. + * @msix_idx: index that corresponds to the (@msix_value, @msix_address) + * entry in the table of MSI-X (value, address) pairs. + * + * This function will program the hardware associating the given + * address/value cobination to the specified msi number. + */ +static void __hal_set_msix_vals (xge_hal_device_h devh, + u32 *msix_value, + u64 *msix_addr, + int msix_idx) +{ + int cnt = 0; + + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64; + + val64 = XGE_HAL_XMSI_NO(msix_idx) | XGE_HAL_XMSI_STROBE; + __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, + (u32)(val64 >> 32), &bar0->xmsi_access); + __hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, + (u32)(val64), &bar0->xmsi_access); + do { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->xmsi_access); + if (val64 & XGE_HAL_XMSI_STROBE) + break; + cnt++; + xge_os_mdelay(20); + } while(cnt < 5); + *msix_value = (u32)(xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->xmsi_data)); + *msix_addr = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->xmsi_address); +} + +/** + * xge_hal_channel_msix_set - Associate MSI-X with a channel. + * @channelh: HAL channel handle. + * @msix_idx: index that corresponds to a particular (@msix_value, + * @msix_address) entry in the MSI-X table. + * + * This API associates a given channel (either Ring or FIFO) with the + * given MSI-X number. It programs the Xframe's Tx_Mat/Rx_Mat tables + * to indicate this association. + */ +xge_hal_status_e +xge_hal_channel_msix_set(xge_hal_channel_h channelh, int msix_idx) +{ + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64; + + if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { + /* Currently Ring and RTI is one on one. */ + int ring = channel->post_qid; + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rx_mat); + val64 |= XGE_HAL_SET_RX_MAT(ring, msix_idx); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rx_mat); + __hal_device_rti_set(ring, channel); + hldev->config.fifo.queue[channel->post_qid].intr_vector = + msix_idx; + } else if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { + int fifo = channel->post_qid; + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->tx_mat[0]); + val64 |= XGE_HAL_SET_TX_MAT(fifo, msix_idx); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->tx_mat[0]); + __hal_device_tti_set(fifo, channel); + hldev->config.ring.queue[channel->post_qid].intr_vector = + msix_idx; + } + channel->msix_idx = msix_idx; + __hal_set_msix_vals(hldev, &channel->msix_data, + &channel->msix_address, + channel->msix_idx); + + return XGE_HAL_OK; +} + +#if defined(XGE_HAL_CONFIG_LRO) +/** + * xge_hal_lro_terminate - Terminate lro resources. + * @lro_scale: Amount of lro memory. + * @hldev: Hal device structure. + * + */ +void +xge_hal_lro_terminate(u32 lro_scale, + xge_hal_device_t *hldev) +{ +} + +/** + * xge_hal_lro_init - Initiate lro resources. + * @lro_scale: Amount of lro memory. + * @hldev: Hal device structure. + * Note: For time being I am using only one LRO per device. Later on size + * will be increased. + */ + +xge_hal_status_e +xge_hal_lro_init(u32 lro_scale, + xge_hal_device_t *hldev) +{ + int i; + + if (hldev->config.lro_sg_size == XGE_HAL_DEFAULT_USE_HARDCODE) + hldev->config.lro_sg_size = XGE_HAL_LRO_DEFAULT_SG_SIZE; + + if (hldev->config.lro_frm_len == XGE_HAL_DEFAULT_USE_HARDCODE) + hldev->config.lro_frm_len = XGE_HAL_LRO_DEFAULT_FRM_LEN; + + for (i=0; i < XGE_HAL_MAX_RING_NUM; i++) + { + xge_os_memzero(hldev->lro_desc[i].lro_pool, + sizeof(lro_t) * XGE_HAL_LRO_MAX_BUCKETS); + + hldev->lro_desc[i].lro_next_idx = 0; + hldev->lro_desc[i].lro_recent = NULL; + } + + return XGE_HAL_OK; +} +#endif + + +/** + * xge_hal_device_poll - HAL device "polling" entry point. + * @devh: HAL device. + * + * HAL "polling" entry point. Note that this is part of HAL public API. + * Upper-Layer driver _must_ periodically poll HAL via + * xge_hal_device_poll(). + * + * HAL uses caller's execution context to serially process accumulated + * slow-path events, such as link state changes and hardware error + * indications. + * + * The rate of polling could be somewhere between 500us to 10ms, + * depending on requirements (e.g., the requirement to support fail-over + * could mean that 500us or even 100us polling interval need to be used). + * + * The need and motivation for external polling includes + * + * - remove the error-checking "burden" from the HAL interrupt handler + * (see xge_hal_device_handle_irq()); + * + * - remove the potential source of portability issues by _not_ + * implementing separate polling thread within HAL itself. + * + * See also: xge_hal_event_e{}, xge_hal_driver_config_t{}. + * Usage: See ex_slow_path{}. + */ +void +xge_hal_device_poll(xge_hal_device_h devh) +{ + unsigned char item_buf[sizeof(xge_queue_item_t) + + XGE_DEFAULT_EVENT_MAX_DATA_SIZE]; + xge_queue_item_t *item = (xge_queue_item_t *)(void *)item_buf; + xge_queue_status_e qstatus; + xge_hal_status_e hstatus; + int i = 0; + int queue_has_critical_event = 0; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + + xge_os_memzero(item_buf, (sizeof(xge_queue_item_t) + + XGE_DEFAULT_EVENT_MAX_DATA_SIZE)); + +_again: + if (!hldev->is_initialized || + hldev->terminating || + hldev->magic != XGE_HAL_MAGIC) + return; + + if(hldev->stats.sw_dev_err_stats.xpak_counter.tick_period < 72000) + { + /* + * Wait for an Hour + */ + hldev->stats.sw_dev_err_stats.xpak_counter.tick_period++; + } else { + /* + * Logging Error messages in the excess temperature, + * Bias current, laser ouput for three cycle + */ + __hal_updt_stats_xpak(hldev); + hldev->stats.sw_dev_err_stats.xpak_counter.tick_period = 0; + } + + if (!queue_has_critical_event) + queue_has_critical_event = + __queue_get_reset_critical(hldev->queueh); + + hldev->in_poll = 1; + while (i++ < XGE_HAL_DRIVER_QUEUE_CONSUME_MAX || queue_has_critical_event) { + + qstatus = xge_queue_consume(hldev->queueh, + XGE_DEFAULT_EVENT_MAX_DATA_SIZE, + item); + if (qstatus == XGE_QUEUE_IS_EMPTY) + break; + + xge_debug_queue(XGE_TRACE, + "queueh 0x"XGE_OS_LLXFMT" consumed event: %d ctxt 0x" + XGE_OS_LLXFMT, (u64)(ulong_t)hldev->queueh, item->event_type, + (u64)(ulong_t)item->context); + + if (!hldev->is_initialized || + hldev->magic != XGE_HAL_MAGIC) { + hldev->in_poll = 0; + return; + } + + switch (item->event_type) { + case XGE_HAL_EVENT_LINK_IS_UP: { + if (!queue_has_critical_event && + g_xge_hal_driver->uld_callbacks.link_up) { + g_xge_hal_driver->uld_callbacks.link_up( + hldev->upper_layer_info); + hldev->link_state = XGE_HAL_LINK_UP; + } + } break; + case XGE_HAL_EVENT_LINK_IS_DOWN: { + if (!queue_has_critical_event && + g_xge_hal_driver->uld_callbacks.link_down) { + g_xge_hal_driver->uld_callbacks.link_down( + hldev->upper_layer_info); + hldev->link_state = XGE_HAL_LINK_DOWN; + } + } break; + case XGE_HAL_EVENT_SERR: + case XGE_HAL_EVENT_ECCERR: + case XGE_HAL_EVENT_PARITYERR: + case XGE_HAL_EVENT_TARGETABORT: + case XGE_HAL_EVENT_SLOT_FREEZE: { + void *item_data = xge_queue_item_data(item); + xge_hal_event_e event_type = item->event_type; + u64 val64 = *((u64*)item_data); + + if (event_type != XGE_HAL_EVENT_SLOT_FREEZE) + if (xge_hal_device_is_slot_freeze(hldev)) + event_type = XGE_HAL_EVENT_SLOT_FREEZE; + if (g_xge_hal_driver->uld_callbacks.crit_err) { + g_xge_hal_driver->uld_callbacks.crit_err( + hldev->upper_layer_info, + event_type, + val64); + /* handle one critical event per poll cycle */ + hldev->in_poll = 0; + return; + } + } break; + default: { + xge_debug_queue(XGE_TRACE, + "got non-HAL event %d", + item->event_type); + } break; + } + + /* broadcast this event */ + if (g_xge_hal_driver->uld_callbacks.event) + g_xge_hal_driver->uld_callbacks.event(item); + } + + if (g_xge_hal_driver->uld_callbacks.before_device_poll) { + if (g_xge_hal_driver->uld_callbacks.before_device_poll( + hldev) != 0) { + hldev->in_poll = 0; + return; + } + } + + hstatus = __hal_device_poll(hldev); + if (g_xge_hal_driver->uld_callbacks.after_device_poll) + g_xge_hal_driver->uld_callbacks.after_device_poll(hldev); + + /* + * handle critical error right away: + * - walk the device queue again + * - drop non-critical events, if any + * - look for the 1st critical + */ + if (hstatus == XGE_HAL_ERR_CRITICAL) { + queue_has_critical_event = 1; + goto _again; + } + + hldev->in_poll = 0; +} + +/** + * xge_hal_rts_rth_init - Set enhanced mode for RTS hashing. + * @hldev: HAL device handle. + * + * This function is used to set the adapter to enhanced mode. + * + * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_set(). + */ +void +xge_hal_rts_rth_init(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + /* + * Set the receive traffic steering mode from default(classic) + * to enhanced. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rts_ctrl); + val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->rts_ctrl); +} + +/** + * xge_hal_rts_rth_clr - Clear RTS hashing. + * @hldev: HAL device handle. + * + * This function is used to clear all RTS hashing related stuff. + * It brings the adapter out from enhanced mode to classic mode. + * It also clears RTS_RTH_CFG register i.e clears hash type, function etc. + * + * See also: xge_hal_rts_rth_set(), xge_hal_rts_rth_itable_set(). + */ +void +xge_hal_rts_rth_clr(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + /* + * Set the receive traffic steering mode from default(classic) + * to enhanced. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rts_ctrl); + val64 &= ~XGE_HAL_RTS_CTRL_ENHANCED_MODE; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->rts_ctrl); + val64 = 0; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_rth_cfg); +} + +/** + * xge_hal_rts_rth_set - Set/configure RTS hashing. + * @hldev: HAL device handle. + * @def_q: default queue + * @hash_type: hash type i.e TcpIpV4, TcpIpV6 etc. + * @bucket_size: no of least significant bits to be used for hashing. + * + * Used to set/configure all RTS hashing related stuff. + * - set the steering mode to enhanced. + * - set hash function i.e algo selection. + * - set the default queue. + * + * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_itable_set(). + */ +void +xge_hal_rts_rth_set(xge_hal_device_t *hldev, u8 def_q, u64 hash_type, + u16 bucket_size) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + val64 = XGE_HAL_RTS_DEFAULT_Q(def_q); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_default_q); + + val64 = hash_type; + val64 |= XGE_HAL_RTS_RTH_EN; + val64 |= XGE_HAL_RTS_RTH_BUCKET_SIZE(bucket_size); + val64 |= XGE_HAL_RTS_RTH_ALG_SEL_MS; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_rth_cfg); +} + +/** + * xge_hal_rts_rth_start - Start RTS hashing. + * @hldev: HAL device handle. + * + * Used to Start RTS hashing . + * + * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_itable_set(), xge_hal_rts_rth_start. + */ +void +xge_hal_rts_rth_start(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rts_rth_cfg); + val64 |= XGE_HAL_RTS_RTH_EN; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_rth_cfg); +} + +/** + * xge_hal_rts_rth_stop - Stop the RTS hashing. + * @hldev: HAL device handle. + * + * Used to Staop RTS hashing . + * + * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_itable_set(), xge_hal_rts_rth_start. + */ +void +xge_hal_rts_rth_stop(xge_hal_device_t *hldev) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rts_rth_cfg); + val64 &= ~XGE_HAL_RTS_RTH_EN; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_rth_cfg); +} + +/** + * xge_hal_rts_rth_itable_set - Set/configure indirection table (IT). + * @hldev: HAL device handle. + * @itable: Pointer to the indirection table + * @itable_size: no of least significant bits to be used for hashing + * + * Used to set/configure indirection table. + * It enables the required no of entries in the IT. + * It adds entries to the IT. + * + * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_set(). + */ +xge_hal_status_e +xge_hal_rts_rth_itable_set(xge_hal_device_t *hldev, u8 *itable, u32 itable_size) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + u32 idx; + + for (idx = 0; idx < itable_size; idx++) { + val64 = XGE_HAL_RTS_RTH_MAP_MEM_DATA_ENTRY_EN | + XGE_HAL_RTS_RTH_MAP_MEM_DATA(itable[idx]); + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_rth_map_mem_data); + + /* execute */ + val64 = (XGE_HAL_RTS_RTH_MAP_MEM_CTRL_WE | + XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE | + XGE_HAL_RTS_RTH_MAP_MEM_CTRL_OFFSET(idx)); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_rth_map_mem_ctrl); + + /* poll until done */ + if (__hal_device_register_poll(hldev, + &bar0->rts_rth_map_mem_ctrl, 0, + XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE, + XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { + /* upper layer may require to repeat */ + return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; + } + } + + return XGE_HAL_OK; +} + + +/** + * xge_hal_device_rts_rth_key_set - Configure 40byte secret for hash calc. + * + * @hldev: HAL device handle. + * @KeySize: Number of 64-bit words + * @Key: upto 40-byte array of 8-bit values + * This function configures the 40-byte secret which is used for hash + * calculation. + * + * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_set(). + */ +void +xge_hal_device_rts_rth_key_set(xge_hal_device_t *hldev, u8 KeySize, u8 *Key) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *) hldev->bar0; + u64 val64; + u32 entry, nreg, i; + + entry = 0; + nreg = 0; + + while( KeySize ) { + val64 = 0; + for ( i = 0; i < 8 ; i++) { + /* Prepare 64-bit word for 'nreg' containing 8 keys. */ + if (i) + val64 <<= 8; + val64 |= Key[entry++]; + } + + KeySize--; + + /* temp64 = XGE_HAL_RTH_HASH_MASK_n(val64, (n<<3), (n<<3)+7);*/ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_rth_hash_mask[nreg++]); + } + + while( nreg < 5 ) { + /* Clear the rest if key is less than 40 bytes */ + val64 = 0; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_rth_hash_mask[nreg++]); + } +} + + +/** + * xge_hal_device_is_closed - Device is closed + * + * @devh: HAL device handle. + */ +int +xge_hal_device_is_closed(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + + if (xge_list_is_empty(&hldev->fifo_channels) && + xge_list_is_empty(&hldev->ring_channels)) + return 1; + + return 0; +} + +xge_hal_status_e +xge_hal_device_rts_section_enable(xge_hal_device_h devh, int index) +{ + u64 val64; + int section; + int max_addr = XGE_HAL_MAX_MAC_ADDRESSES; + + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) + max_addr = XGE_HAL_MAX_MAC_ADDRESSES_HERC; + + if ( index >= max_addr ) + return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; + + /* + * Calculate the section value + */ + section = index / 32; + + xge_debug_device(XGE_TRACE, "the Section value is %d ", section); + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rts_mac_cfg); + switch(section) + { + case 0: + val64 |= XGE_HAL_RTS_MAC_SECT0_EN; + break; + case 1: + val64 |= XGE_HAL_RTS_MAC_SECT1_EN; + break; + case 2: + val64 |= XGE_HAL_RTS_MAC_SECT2_EN; + break; + case 3: + val64 |= XGE_HAL_RTS_MAC_SECT3_EN; + break; + case 4: + val64 |= XGE_HAL_RTS_MAC_SECT4_EN; + break; + case 5: + val64 |= XGE_HAL_RTS_MAC_SECT5_EN; + break; + case 6: + val64 |= XGE_HAL_RTS_MAC_SECT6_EN; + break; + case 7: + val64 |= XGE_HAL_RTS_MAC_SECT7_EN; + break; + default: + xge_debug_device(XGE_ERR, "Invalid Section value %d " + , section); + } + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->rts_mac_cfg); + return XGE_HAL_OK; +} + + diff --git a/sys/dev/nxge/xgehal/xgehal-driver.c b/sys/dev/nxge/xgehal/xgehal-driver.c new file mode 100644 index 0000000..c8d1989 --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-driver.c @@ -0,0 +1,300 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-driver.c + * + * Description: HAL driver object functionality + * + * Created: 10 May 2004 + */ + +#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 +} diff --git a/sys/dev/nxge/xgehal/xgehal-fifo-fp.c b/sys/dev/nxge/xgehal/xgehal-fifo-fp.c new file mode 100644 index 0000000..4f59674 --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-fifo-fp.c @@ -0,0 +1,1175 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-fifo-fp.c + * + * Description: Tx fifo object functionality (fast path) + * + * Created: 10 June 2004 + */ + +#ifdef XGE_DEBUG_FP +#include <dev/nxge/include/xgehal-fifo.h> +#endif + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_fifo_txdl_priv_t* +__hal_fifo_txdl_priv(xge_hal_dtr_h dtrh) +{ + xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t*)dtrh; + xge_hal_fifo_txdl_priv_t *txdl_priv; + + xge_assert(txdp); + txdl_priv = (xge_hal_fifo_txdl_priv_t *) + (ulong_t)txdp->host_control; + + xge_assert(txdl_priv); + xge_assert(txdl_priv->dma_object); + xge_assert(txdl_priv->dma_addr); + + xge_assert(txdl_priv->dma_object->handle == txdl_priv->dma_handle); + + return txdl_priv; +} + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +__hal_fifo_dtr_post_single(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + u64 ctrl_1) +{ + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + xge_hal_fifo_hw_pair_t *hw_pair = fifo->hw_pair; + xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh; + xge_hal_fifo_txdl_priv_t *txdl_priv; + u64 ctrl; + + txdp->control_1 |= XGE_HAL_TXD_LIST_OWN_XENA; + +#ifdef XGE_DEBUG_ASSERT + /* make sure Xena overwrites the (illegal) t_code value on completion */ + XGE_HAL_SET_TXD_T_CODE(txdp->control_1, XGE_HAL_TXD_T_CODE_UNUSED_5); +#endif + + txdl_priv = __hal_fifo_txdl_priv(dtrh); + +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING) + /* sync the TxDL to device */ + xge_os_dma_sync(fifo->channel.pdev, + txdl_priv->dma_handle, + txdl_priv->dma_addr, + txdl_priv->dma_offset, + txdl_priv->frags << 5 /* sizeof(xge_hal_fifo_txd_t) */, + XGE_OS_DMA_DIR_TODEVICE); +#endif + /* write the pointer first */ + xge_os_pio_mem_write64(fifo->channel.pdev, + fifo->channel.regh1, + txdl_priv->dma_addr, + &hw_pair->txdl_pointer); + + /* spec: 0x00 = 1 TxD in the list */ + ctrl = XGE_HAL_TX_FIFO_LAST_TXD_NUM(txdl_priv->frags - 1); + ctrl |= ctrl_1; + ctrl |= fifo->no_snoop_bits; + + if (txdp->control_1 & XGE_HAL_TXD_LSO_COF_CTRL(XGE_HAL_TXD_TCP_LSO)) { + ctrl |= XGE_HAL_TX_FIFO_SPECIAL_FUNC; + } + + /* + * according to the XENA spec: + * + * It is important to note that pointers and list control words are + * always written in pairs: in the first write, the host must write a + * pointer, and in the second write, it must write the list control + * word. Any other access will result in an error. Also, all 16 bytes + * of the pointer/control structure must be written, including any + * reserved bytes. + */ + xge_os_wmb(); + + /* + * we want touch work_arr in order with ownership bit set to HW + */ + __hal_channel_dtr_post(channelh, dtrh); + + xge_os_pio_mem_write64(fifo->channel.pdev, fifo->channel.regh1, + ctrl, &hw_pair->list_control); + + xge_debug_fifo(XGE_TRACE, "posted txdl 0x"XGE_OS_LLXFMT" ctrl 0x"XGE_OS_LLXFMT" " + "into 0x"XGE_OS_LLXFMT"", (unsigned long long)txdl_priv->dma_addr, + (unsigned long long)ctrl, + (unsigned long long)(ulong_t)&hw_pair->txdl_pointer); + +#ifdef XGE_HAL_FIFO_DUMP_TXD + xge_os_printf(""XGE_OS_LLXFMT":"XGE_OS_LLXFMT":"XGE_OS_LLXFMT":" + XGE_OS_LLXFMT" dma "XGE_OS_LLXFMT, + txdp->control_1, txdp->control_2, txdp->buffer_pointer, + txdp->host_control, txdl_priv->dma_addr); +#endif + + fifo->channel.stats.total_posts++; + fifo->channel.usage_cnt++; + if (fifo->channel.stats.usage_max < fifo->channel.usage_cnt) + fifo->channel.stats.usage_max = fifo->channel.usage_cnt; +} + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +__hal_fifo_txdl_free_many(xge_hal_channel_h channelh, + xge_hal_fifo_txd_t *txdp, int list_size, int frags) +{ + xge_hal_fifo_txdl_priv_t *current_txdl_priv; + xge_hal_fifo_txdl_priv_t *next_txdl_priv; + int invalid_frags = frags % list_size; + if (invalid_frags){ + xge_debug_fifo(XGE_ERR, + "freeing corrupt dtrh %p, fragments %d list size %d", + txdp, frags, list_size); + xge_assert(invalid_frags == 0); + } + while(txdp){ + xge_debug_fifo(XGE_TRACE, + "freeing linked dtrh %p, fragments %d list size %d", + txdp, frags, list_size); + current_txdl_priv = __hal_fifo_txdl_priv(txdp); +#if defined(XGE_DEBUG_ASSERT) && defined(XGE_OS_MEMORY_CHECK) + current_txdl_priv->allocated = 0; +#endif + __hal_channel_dtr_free(channelh, txdp); + next_txdl_priv = current_txdl_priv->next_txdl_priv; + xge_assert(frags); + frags -= list_size; + if (next_txdl_priv) { + current_txdl_priv->next_txdl_priv = NULL; + txdp = next_txdl_priv->first_txdp; + } + else { + xge_debug_fifo(XGE_TRACE, + "freed linked dtrh fragments %d list size %d", + frags, list_size); + break; + } + } + xge_assert(frags == 0) +} + +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +__hal_fifo_txdl_restore_many(xge_hal_channel_h channelh, + xge_hal_fifo_txd_t *txdp, int txdl_count) +{ + xge_hal_fifo_txdl_priv_t *current_txdl_priv; + xge_hal_fifo_txdl_priv_t *next_txdl_priv; + int i = txdl_count; + + xge_assert(((xge_hal_channel_t *)channelh)->reserve_length + + txdl_count <= ((xge_hal_channel_t *)channelh)->reserve_initial); + + current_txdl_priv = __hal_fifo_txdl_priv(txdp); + do{ + xge_assert(i); +#if defined(XGE_DEBUG_ASSERT) && defined(XGE_OS_MEMORY_CHECK) + current_txdl_priv->allocated = 0; +#endif + next_txdl_priv = current_txdl_priv->next_txdl_priv; + txdp = current_txdl_priv->first_txdp; + current_txdl_priv->next_txdl_priv = NULL; + __hal_channel_dtr_restore(channelh, (xge_hal_dtr_h )txdp, --i); + xge_debug_fifo(XGE_TRACE, + "dtrh %p restored at offset %d", txdp, i); + current_txdl_priv = next_txdl_priv; + } while(current_txdl_priv); + __hal_channel_dtr_restore(channelh, NULL, txdl_count); +} +/** + * xge_hal_fifo_dtr_private - Retrieve per-descriptor private data. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * + * Retrieve per-descriptor private data. + * Note that ULD requests per-descriptor space via + * xge_hal_channel_open(). + * + * Returns: private ULD data associated with the descriptor. + * Usage: See ex_xmit{} and ex_tx_compl{}. + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void* +xge_hal_fifo_dtr_private(xge_hal_dtr_h dtrh) +{ + xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh; + + return ((char *)(ulong_t)txdp->host_control) + + sizeof(xge_hal_fifo_txdl_priv_t); +} + +/** + * xge_hal_fifo_dtr_buffer_cnt - Get number of buffers carried by the + * descriptor. + * @dtrh: Descriptor handle. + * + * Returns: Number of buffers stored in the given descriptor. Can be used + * _after_ the descriptor is set up for posting (see + * xge_hal_fifo_dtr_post()) and _before_ it is deallocated (see + * xge_hal_fifo_dtr_free()). + * + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO int +xge_hal_fifo_dtr_buffer_cnt(xge_hal_dtr_h dtrh) +{ + xge_hal_fifo_txdl_priv_t *txdl_priv; + + txdl_priv = __hal_fifo_txdl_priv(dtrh); + + return txdl_priv->frags; +} +/** + * xge_hal_fifo_dtr_reserve_many- Reserve fifo descriptors which span more + * than single txdl. + * @channelh: Channel handle. + * @dtrh: Reserved descriptor. On success HAL fills this "out" parameter + * with a valid handle. + * @frags: minimum number of fragments to be reserved. + * + * Reserve TxDL(s) (that is, fifo descriptor) + * for the subsequent filling-in by upper layerdriver (ULD)) + * and posting on the corresponding channel (@channelh) + * via xge_hal_fifo_dtr_post(). + * + * Returns: XGE_HAL_OK - success; + * XGE_HAL_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available + * + * See also: xge_hal_fifo_dtr_reserve_sp(), xge_hal_fifo_dtr_free(), + * xge_hal_ring_dtr_reserve(), xge_hal_status_e{}. + * Usage: See ex_xmit{}. + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e +xge_hal_fifo_dtr_reserve_many(xge_hal_channel_h channelh, + xge_hal_dtr_h *dtrh, const int frags) +{ + xge_hal_status_e status = XGE_HAL_OK; + int alloc_frags = 0, dang_frags = 0; + xge_hal_fifo_txd_t *curr_txdp = NULL; + xge_hal_fifo_txd_t *next_txdp; + xge_hal_fifo_txdl_priv_t *next_txdl_priv, *curr_txdl_priv = NULL; + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + int max_frags = fifo->config->max_frags; + xge_hal_dtr_h dang_dtrh = NULL; +#if defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) + unsigned long flags=0; +#endif + xge_debug_fifo(XGE_TRACE, "dtr_reserve_many called for frags %d", + frags); + xge_assert(frags < (fifo->txdl_per_memblock * max_frags)); +#if defined(XGE_HAL_TX_MULTI_RESERVE) + xge_os_spin_lock(&fifo->channel.reserve_lock); +#elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) + xge_os_spin_lock_irq(&fifo->channel.reserve_lock, flags); +#endif + while(alloc_frags < frags) { + status = __hal_channel_dtr_alloc(channelh, + (xge_hal_dtr_h *)(void*)&next_txdp); + if (status != XGE_HAL_OK){ + xge_debug_fifo(XGE_ERR, + "failed to allocate linked fragments rc %d", + status); + xge_assert(status == XGE_HAL_INF_OUT_OF_DESCRIPTORS); + if (*dtrh) { + xge_assert(alloc_frags/max_frags); + __hal_fifo_txdl_restore_many(channelh, + (xge_hal_fifo_txd_t *) *dtrh, alloc_frags/max_frags); + } + if (dang_dtrh) { + xge_assert(dang_frags/max_frags); + __hal_fifo_txdl_restore_many(channelh, + (xge_hal_fifo_txd_t *) dang_dtrh, dang_frags/max_frags); + } + break; + } + xge_debug_fifo(XGE_TRACE, "allocated linked dtrh %p" + " for frags %d", next_txdp, frags); + next_txdl_priv = __hal_fifo_txdl_priv(next_txdp); + xge_assert(next_txdl_priv); + xge_assert(next_txdl_priv->first_txdp == next_txdp); + next_txdl_priv->dang_txdl = NULL; + next_txdl_priv->dang_frags = 0; + next_txdl_priv->next_txdl_priv = NULL; +#if defined(XGE_OS_MEMORY_CHECK) + next_txdl_priv->allocated = 1; +#endif + if (!curr_txdp || !curr_txdl_priv) { + curr_txdp = next_txdp; + curr_txdl_priv = next_txdl_priv; + *dtrh = (xge_hal_dtr_h)next_txdp; + alloc_frags = max_frags; + continue; + } + if (curr_txdl_priv->memblock == + next_txdl_priv->memblock) { + xge_debug_fifo(XGE_TRACE, + "linking dtrh %p, with %p", + *dtrh, next_txdp); + xge_assert (next_txdp == + curr_txdp + max_frags); + alloc_frags += max_frags; + curr_txdl_priv->next_txdl_priv = next_txdl_priv; + } + else { + xge_assert(*dtrh); + xge_assert(dang_dtrh == NULL); + dang_dtrh = *dtrh; + dang_frags = alloc_frags; + xge_debug_fifo(XGE_TRACE, + "dangling dtrh %p, linked with dtrh %p", + *dtrh, next_txdp); + next_txdl_priv->dang_txdl = (xge_hal_fifo_txd_t *) *dtrh; + next_txdl_priv->dang_frags = alloc_frags; + alloc_frags = max_frags; + *dtrh = next_txdp; + } + curr_txdp = next_txdp; + curr_txdl_priv = next_txdl_priv; + } + +#if defined(XGE_HAL_TX_MULTI_RESERVE) + xge_os_spin_unlock(&fifo->channel.reserve_lock); +#elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) + xge_os_spin_unlock_irq(&fifo->channel.reserve_lock, flags); +#endif + + if (status == XGE_HAL_OK) { + xge_hal_fifo_txdl_priv_t * txdl_priv; + xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)*dtrh; + xge_hal_stats_channel_info_t *statsp = &fifo->channel.stats; + txdl_priv = __hal_fifo_txdl_priv(txdp); + /* reset the TxDL's private */ + txdl_priv->align_dma_offset = 0; + txdl_priv->align_vaddr_start = txdl_priv->align_vaddr; + txdl_priv->align_used_frags = 0; + txdl_priv->frags = 0; + txdl_priv->bytes_sent = 0; + txdl_priv->alloc_frags = alloc_frags; + /* reset TxD0 */ + txdp->control_1 = txdp->control_2 = 0; + +#if defined(XGE_OS_MEMORY_CHECK) + txdl_priv->allocated = 1; +#endif + /* update statistics */ + statsp->total_posts_dtrs_many++; + statsp->total_posts_frags_many += txdl_priv->alloc_frags; + if (txdl_priv->dang_frags){ + statsp->total_posts_dang_dtrs++; + statsp->total_posts_dang_frags += txdl_priv->dang_frags; + } + } + + return status; +} + +/** + * xge_hal_fifo_dtr_reserve - Reserve fifo descriptor. + * @channelh: Channel handle. + * @dtrh: Reserved descriptor. On success HAL fills this "out" parameter + * with a valid handle. + * + * Reserve a single TxDL (that is, fifo descriptor) + * for the subsequent filling-in by upper layerdriver (ULD)) + * and posting on the corresponding channel (@channelh) + * via xge_hal_fifo_dtr_post(). + * + * Note: it is the responsibility of ULD to reserve multiple descriptors + * for lengthy (e.g., LSO) transmit operation. A single fifo descriptor + * carries up to configured number (fifo.max_frags) of contiguous buffers. + * + * Returns: XGE_HAL_OK - success; + * XGE_HAL_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available + * + * See also: xge_hal_fifo_dtr_reserve_sp(), xge_hal_fifo_dtr_free(), + * xge_hal_ring_dtr_reserve(), xge_hal_status_e{}. + * Usage: See ex_xmit{}. + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e +xge_hal_fifo_dtr_reserve(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh) +{ + xge_hal_status_e status; +#if defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) + unsigned long flags=0; +#endif + +#if defined(XGE_HAL_TX_MULTI_RESERVE) + xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->reserve_lock); +#elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) + xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->reserve_lock, + flags); +#endif + + status = __hal_channel_dtr_alloc(channelh, dtrh); + +#if defined(XGE_HAL_TX_MULTI_RESERVE) + xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->reserve_lock); +#elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) + xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->reserve_lock, + flags); +#endif + + if (status == XGE_HAL_OK) { + xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)*dtrh; + xge_hal_fifo_txdl_priv_t *txdl_priv; + + txdl_priv = __hal_fifo_txdl_priv(txdp); + + /* reset the TxDL's private */ + txdl_priv->align_dma_offset = 0; + txdl_priv->align_vaddr_start = txdl_priv->align_vaddr; + txdl_priv->align_used_frags = 0; + txdl_priv->frags = 0; + txdl_priv->alloc_frags = + ((xge_hal_fifo_t *)channelh)->config->max_frags; + txdl_priv->dang_txdl = NULL; + txdl_priv->dang_frags = 0; + txdl_priv->next_txdl_priv = NULL; + txdl_priv->bytes_sent = 0; + + /* reset TxD0 */ + txdp->control_1 = txdp->control_2 = 0; + +#if defined(XGE_OS_MEMORY_CHECK) + txdl_priv->allocated = 1; +#endif + } + + return status; +} + +/** + * xge_hal_fifo_dtr_reserve_sp - Reserve fifo descriptor and store it in + * the ULD-provided "scratch" memory. + * @channelh: Channel handle. + * @dtr_sp_size: Size of the %dtr_sp "scratch pad" that HAL can use for TxDL. + * @dtr_sp: "Scratch pad" supplied by upper-layer driver (ULD). + * + * Reserve TxDL and fill-in ULD supplied "scratch pad". The difference + * between this API and xge_hal_fifo_dtr_reserve() is (possibly) - + * performance. + * + * If upper-layer uses ULP-defined commands, and if those commands have enough + * space for HAL/Xframe descriptors - tnan it is better (read: faster) to fit + * all the per-command information into one command, which is typically + * one contiguous block. + * + * Note: Unlike xge_hal_fifo_dtr_reserve(), this function can be used to + * allocate a single descriptor for transmit operation. + * + * See also: xge_hal_fifo_dtr_reserve(), xge_hal_fifo_dtr_free(), + * xge_hal_ring_dtr_reserve(), xge_hal_status_e{}. + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e +xge_hal_fifo_dtr_reserve_sp(xge_hal_channel_h channelh, int dtr_sp_size, + xge_hal_dtr_h dtr_sp) +{ + /* FIXME: implement */ + return XGE_HAL_OK; +} + +/** + * xge_hal_fifo_dtr_post - Post descriptor on the fifo channel. + * @channelh: Channel handle. + * @dtrh: Descriptor obtained via xge_hal_fifo_dtr_reserve() or + * xge_hal_fifo_dtr_reserve_sp() + * @frags: Number of contiguous buffers that are part of a single + * transmit operation. + * + * Post descriptor on the 'fifo' type channel for transmission. + * Prior to posting the descriptor should be filled in accordance with + * Host/Xframe interface specification for a given service (LL, etc.). + * + * See also: xge_hal_fifo_dtr_post_many(), xge_hal_ring_dtr_post(). + * Usage: See ex_xmit{}. + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh) +{ + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + xge_hal_fifo_txdl_priv_t *txdl_priv; + xge_hal_fifo_txd_t *txdp_last; + xge_hal_fifo_txd_t *txdp_first; +#if defined(XGE_HAL_TX_MULTI_POST_IRQ) + unsigned long flags = 0; +#endif + + txdl_priv = __hal_fifo_txdl_priv(dtrh); + + txdp_first = (xge_hal_fifo_txd_t *)dtrh; + txdp_first->control_1 |= XGE_HAL_TXD_GATHER_CODE_FIRST; + txdp_first->control_2 |= fifo->interrupt_type; + + txdp_last = (xge_hal_fifo_txd_t *)dtrh + (txdl_priv->frags - 1); + txdp_last->control_1 |= XGE_HAL_TXD_GATHER_CODE_LAST; + +#if defined(XGE_HAL_TX_MULTI_POST) + xge_os_spin_lock(fifo->post_lock_ptr); +#elif defined(XGE_HAL_TX_MULTI_POST_IRQ) + xge_os_spin_lock_irq(fifo->post_lock_ptr, flags); +#endif + + __hal_fifo_dtr_post_single(channelh, dtrh, + (u64)(XGE_HAL_TX_FIFO_FIRST_LIST | XGE_HAL_TX_FIFO_LAST_LIST)); + +#if defined(XGE_HAL_TX_MULTI_POST) + xge_os_spin_unlock(fifo->post_lock_ptr); +#elif defined(XGE_HAL_TX_MULTI_POST_IRQ) + xge_os_spin_unlock_irq(fifo->post_lock_ptr, flags); +#endif +} + +/** + * xge_hal_fifo_dtr_post_many - Post multiple descriptors on fifo + * channel. + * @channelh: Channel to post descriptor. + * @num: Number of descriptors (i.e., fifo TxDLs) in the %dtrs[]. + * @dtrs: Descriptors obtained via xge_hal_fifo_dtr_reserve(). + * @frags_arr: Number of fragments carried @dtrs descriptors. + * Note that frag_arr[i] corresponds to descriptor dtrs[i]. + * + * Post multi-descriptor on the fifo channel. The operation is atomic: + * all descriptrs are posted on the channel "back-to-back' without + * letting other posts (possibly driven by multiple transmitting threads) + * to interleave. + * + * See also: xge_hal_fifo_dtr_post(), xge_hal_ring_dtr_post(). + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_post_many(xge_hal_channel_h channelh, int num, + xge_hal_dtr_h dtrs[]) +{ + int i; + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + xge_hal_fifo_txd_t *txdp_last; + xge_hal_fifo_txd_t *txdp_first; + xge_hal_fifo_txdl_priv_t *txdl_priv_last; +#if defined(XGE_HAL_TX_MULTI_POST_IRQ) + unsigned long flags = 0; +#endif + + xge_assert(num > 1); + + txdp_first = (xge_hal_fifo_txd_t *)dtrs[0]; + txdp_first->control_1 |= XGE_HAL_TXD_GATHER_CODE_FIRST; + txdp_first->control_2 |= fifo->interrupt_type; + + txdl_priv_last = __hal_fifo_txdl_priv(dtrs[num-1]); + txdp_last = (xge_hal_fifo_txd_t *)dtrs[num-1] + + (txdl_priv_last->frags - 1); + txdp_last->control_1 |= XGE_HAL_TXD_GATHER_CODE_LAST; + +#if defined(XGE_HAL_TX_MULTI_POST) + xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->post_lock); +#elif defined(XGE_HAL_TX_MULTI_POST_IRQ) + xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->post_lock, + flags); +#endif + + for (i=0; i<num; i++) { + xge_hal_fifo_txdl_priv_t *txdl_priv; + u64 val64; + xge_hal_dtr_h dtrh = dtrs[i]; + + txdl_priv = __hal_fifo_txdl_priv(dtrh); + txdl_priv = txdl_priv; /* Cheat lint */ + + val64 = 0; + if (i == 0) { + val64 |= XGE_HAL_TX_FIFO_FIRST_LIST; + } else if (i == num -1) { + val64 |= XGE_HAL_TX_FIFO_LAST_LIST; + } + + val64 |= XGE_HAL_TX_FIFO_SPECIAL_FUNC; + __hal_fifo_dtr_post_single(channelh, dtrh, val64); + } + +#if defined(XGE_HAL_TX_MULTI_POST) + xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->post_lock); +#elif defined(XGE_HAL_TX_MULTI_POST_IRQ) + xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->post_lock, + flags); +#endif + + fifo->channel.stats.total_posts_many++; +} + +/** + * xge_hal_fifo_dtr_next_completed - Retrieve next completed descriptor. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. Returned by HAL. + * @t_code: Transfer code, as per Xframe User Guide, + * Transmit Descriptor Format. + * Returned by HAL. + * + * Retrieve the _next_ completed descriptor. + * HAL uses channel callback (*xge_hal_channel_callback_f) to notifiy + * upper-layer driver (ULD) of new completed descriptors. After that + * the ULD can use xge_hal_fifo_dtr_next_completed to retrieve the rest + * completions (the very first completion is passed by HAL via + * xge_hal_channel_callback_f). + * + * Implementation-wise, the upper-layer driver is free to call + * xge_hal_fifo_dtr_next_completed either immediately from inside the + * channel callback, or in a deferred fashion and separate (from HAL) + * context. + * + * Non-zero @t_code means failure to process the descriptor. + * The failure could happen, for instance, when the link is + * down, in which case Xframe completes the descriptor because it + * is not able to send the data out. + * + * For details please refer to Xframe User Guide. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed descriptors + * are currently available for processing. + * + * See also: xge_hal_channel_callback_f{}, + * xge_hal_ring_dtr_next_completed(). + * Usage: See ex_tx_compl{}. + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e +xge_hal_fifo_dtr_next_completed(xge_hal_channel_h channelh, + xge_hal_dtr_h *dtrh, u8 *t_code) +{ + xge_hal_fifo_txd_t *txdp; + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING) + xge_hal_fifo_txdl_priv_t *txdl_priv; +#endif + + __hal_channel_dtr_try_complete(channelh, dtrh); + txdp = (xge_hal_fifo_txd_t *)*dtrh; + if (txdp == NULL) { + return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS; + } + +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING) + txdl_priv = __hal_fifo_txdl_priv(txdp); + + /* sync TxDL to read the ownership + * + * Note: 16bytes means Control_1 & Control_2 */ + xge_os_dma_sync(fifo->channel.pdev, + txdl_priv->dma_handle, + txdl_priv->dma_addr, + txdl_priv->dma_offset, + 16, + XGE_OS_DMA_DIR_FROMDEVICE); +#endif + + /* check whether host owns it */ + if ( !(txdp->control_1 & XGE_HAL_TXD_LIST_OWN_XENA) ) { + + xge_assert(txdp->host_control!=0); + + __hal_channel_dtr_complete(channelh); + + *t_code = (u8)XGE_HAL_GET_TXD_T_CODE(txdp->control_1); + + /* see XGE_HAL_SET_TXD_T_CODE() above.. */ + xge_assert(*t_code != XGE_HAL_TXD_T_CODE_UNUSED_5); + + if (fifo->channel.usage_cnt > 0) + fifo->channel.usage_cnt--; + + return XGE_HAL_OK; + } + + /* no more completions */ + *dtrh = 0; + return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS; +} + +/** + * xge_hal_fifo_dtr_free - Free descriptor. + * @channelh: Channel handle. + * @dtr: Descriptor handle. + * + * Free the reserved descriptor. This operation is "symmetrical" to + * xge_hal_fifo_dtr_reserve or xge_hal_fifo_dtr_reserve_sp. + * The "free-ing" completes the descriptor's lifecycle. + * + * After free-ing (see xge_hal_fifo_dtr_free()) the descriptor again can + * be: + * + * - reserved (xge_hal_fifo_dtr_reserve); + * + * - posted (xge_hal_fifo_dtr_post); + * + * - completed (xge_hal_fifo_dtr_next_completed); + * + * - and recycled again (xge_hal_fifo_dtr_free). + * + * For alternative state transitions and more details please refer to + * the design doc. + * + * See also: xge_hal_ring_dtr_free(), xge_hal_fifo_dtr_reserve(). + * Usage: See ex_tx_compl{}. + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_free(xge_hal_channel_h channelh, xge_hal_dtr_h dtr) +{ +#if defined(XGE_HAL_TX_MULTI_FREE_IRQ) + unsigned long flags = 0; +#endif + xge_hal_fifo_txdl_priv_t *txdl_priv = __hal_fifo_txdl_priv( + (xge_hal_fifo_txd_t *)dtr); + int max_frags = ((xge_hal_fifo_t *)channelh)->config->max_frags; +#if defined(XGE_HAL_TX_MULTI_FREE) + xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->free_lock); +#elif defined(XGE_HAL_TX_MULTI_FREE_IRQ) + xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->free_lock, + flags); +#endif + + if (txdl_priv->alloc_frags > max_frags) { + xge_hal_fifo_txd_t *dang_txdp = (xge_hal_fifo_txd_t *) + txdl_priv->dang_txdl; + int dang_frags = txdl_priv->dang_frags; + int alloc_frags = txdl_priv->alloc_frags; + txdl_priv->dang_txdl = NULL; + txdl_priv->dang_frags = 0; + txdl_priv->alloc_frags = 0; + /* dtrh must have a linked list of dtrh */ + xge_assert(txdl_priv->next_txdl_priv); + + /* free any dangling dtrh first */ + if (dang_txdp) { + xge_debug_fifo(XGE_TRACE, + "freeing dangled dtrh %p for %d fragments", + dang_txdp, dang_frags); + __hal_fifo_txdl_free_many(channelh, dang_txdp, + max_frags, dang_frags); + } + + /* now free the reserved dtrh list */ + xge_debug_fifo(XGE_TRACE, + "freeing dtrh %p list of %d fragments", dtr, + alloc_frags); + __hal_fifo_txdl_free_many(channelh, + (xge_hal_fifo_txd_t *)dtr, max_frags, + alloc_frags); + } + else + __hal_channel_dtr_free(channelh, dtr); + + ((xge_hal_channel_t *)channelh)->poll_bytes += txdl_priv->bytes_sent; + +#if defined(XGE_DEBUG_ASSERT) && defined(XGE_OS_MEMORY_CHECK) + __hal_fifo_txdl_priv(dtr)->allocated = 0; +#endif + +#if defined(XGE_HAL_TX_MULTI_FREE) + xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->free_lock); +#elif defined(XGE_HAL_TX_MULTI_FREE_IRQ) + xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->free_lock, + flags); +#endif +} + + +/** + * xge_hal_fifo_dtr_buffer_set_aligned - Align transmit buffer and fill + * in fifo descriptor. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * @frag_idx: Index of the data buffer in the caller's scatter-gather listá + * (of buffers). + * @vaddr: Virtual address of the data buffer. + * @dma_pointer: DMA address of the data buffer referenced by @frag_idx. + * @size: Size of the data buffer (in bytes). + * @misaligned_size: Size (in bytes) of the misaligned portion of the + * data buffer. Calculated by the caller, based on the platform/OS/other + * specific criteria, which is outside of HAL's domain. See notes below. + * + * This API is part of the transmit descriptor preparation for posting + * (via xge_hal_fifo_dtr_post()). The related "preparation" APIs include + * xge_hal_fifo_dtr_mss_set() and xge_hal_fifo_dtr_cksum_set_bits(). + * All three APIs fill in the fields of the fifo descriptor, + * in accordance with the Xframe specification. + * On the PCI-X based systems aligning transmit data typically provides better + * transmit performance. The typical alignment granularity: L2 cacheline size. + * However, HAL does not make assumptions in terms of the alignment granularity; + * this is specified via additional @misaligned_size parameter described above. + * Prior to calling xge_hal_fifo_dtr_buffer_set_aligned(), + * ULD is supposed to check alignment of a given fragment/buffer. For this HAL + * provides a separate xge_hal_check_alignment() API sufficient to cover + * most (but not all) possible alignment criteria. + * If the buffer appears to be aligned, the ULD calls + * xge_hal_fifo_dtr_buffer_set(). + * Otherwise, ULD calls xge_hal_fifo_dtr_buffer_set_aligned(). + * + * Note; This API is a "superset" of xge_hal_fifo_dtr_buffer_set(). In + * addition to filling in the specified descriptor it aligns transmit data on + * the specified boundary. + * Note: Decision on whether to align or not to align a given contiguous + * transmit buffer is outside of HAL's domain. To this end ULD can use any + * programmable criteria, which can help to 1) boost transmit performance, + * and/or 2) provide a workaround for PCI bridge bugs, if any. + * + * See also: xge_hal_fifo_dtr_buffer_set(), + * xge_hal_check_alignment(). + * + * See also: xge_hal_fifo_dtr_reserve(), xge_hal_fifo_dtr_post(), + * xge_hal_fifo_dtr_mss_set(), xge_hal_fifo_dtr_cksum_set_bits() + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e +xge_hal_fifo_dtr_buffer_set_aligned(xge_hal_channel_h channelh, + xge_hal_dtr_h dtrh, int frag_idx, void *vaddr, + dma_addr_t dma_pointer, int size, int misaligned_size) +{ + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + xge_hal_fifo_txdl_priv_t *txdl_priv; + xge_hal_fifo_txd_t *txdp; + int remaining_size; + ptrdiff_t prev_boff; + + txdl_priv = __hal_fifo_txdl_priv(dtrh); + txdp = (xge_hal_fifo_txd_t *)dtrh + txdl_priv->frags; + + if (frag_idx != 0) { + txdp->control_1 = txdp->control_2 = 0; + } + + /* On some systems buffer size could be zero. + * It is the responsibility of ULD and *not HAL* to + * detect it and skip it. */ + xge_assert(size > 0); + xge_assert(frag_idx < txdl_priv->alloc_frags); + xge_assert(misaligned_size != 0 && + misaligned_size <= fifo->config->alignment_size); + + remaining_size = size - misaligned_size; + xge_assert(remaining_size >= 0); + + xge_os_memcpy((char*)txdl_priv->align_vaddr_start, + vaddr, misaligned_size); + + if (txdl_priv->align_used_frags >= fifo->config->max_aligned_frags) { + return XGE_HAL_ERR_OUT_ALIGNED_FRAGS; + } + + /* setup new buffer */ + prev_boff = txdl_priv->align_vaddr_start - txdl_priv->align_vaddr; + txdp->buffer_pointer = (u64)txdl_priv->align_dma_addr + prev_boff; + txdp->control_1 |= XGE_HAL_TXD_BUFFER0_SIZE(misaligned_size); + txdl_priv->bytes_sent += misaligned_size; + fifo->channel.stats.total_buffers++; + txdl_priv->frags++; + txdl_priv->align_used_frags++; + txdl_priv->align_vaddr_start += fifo->config->alignment_size; + txdl_priv->align_dma_offset = 0; + +#if defined(XGE_OS_DMA_REQUIRES_SYNC) + /* sync new buffer */ + xge_os_dma_sync(fifo->channel.pdev, + txdl_priv->align_dma_handle, + txdp->buffer_pointer, + 0, + misaligned_size, + XGE_OS_DMA_DIR_TODEVICE); +#endif + + if (remaining_size) { + xge_assert(frag_idx < txdl_priv->alloc_frags); + txdp++; + txdp->buffer_pointer = (u64)dma_pointer + + misaligned_size; + txdp->control_1 = + XGE_HAL_TXD_BUFFER0_SIZE(remaining_size); + txdl_priv->bytes_sent += remaining_size; + txdp->control_2 = 0; + fifo->channel.stats.total_buffers++; + txdl_priv->frags++; + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_fifo_dtr_buffer_append - Append the contents of virtually + * contiguous data buffer to a single physically contiguous buffer. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * @vaddr: Virtual address of the data buffer. + * @size: Size of the data buffer (in bytes). + * + * This API is part of the transmit descriptor preparation for posting + * (via xge_hal_fifo_dtr_post()). + * The main difference of this API wrt to the APIs + * xge_hal_fifo_dtr_buffer_set_aligned() is that this API appends the + * contents of virtually contiguous data buffers received from + * upper layer into a single physically contiguous data buffer and the + * device will do a DMA from this buffer. + * + * See Also: xge_hal_fifo_dtr_buffer_finalize(), xge_hal_fifo_dtr_buffer_set(), + * xge_hal_fifo_dtr_buffer_set_aligned(). + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e +xge_hal_fifo_dtr_buffer_append(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + void *vaddr, int size) +{ + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + xge_hal_fifo_txdl_priv_t *txdl_priv; + ptrdiff_t used; + + xge_assert(size > 0); + + txdl_priv = __hal_fifo_txdl_priv(dtrh); + + used = txdl_priv->align_vaddr_start - txdl_priv->align_vaddr; + used += txdl_priv->align_dma_offset; + if (used + (unsigned int)size > (unsigned int)fifo->align_size) + return XGE_HAL_ERR_OUT_ALIGNED_FRAGS; + + xge_os_memcpy((char*)txdl_priv->align_vaddr_start + + txdl_priv->align_dma_offset, vaddr, size); + + fifo->channel.stats.copied_frags++; + + txdl_priv->align_dma_offset += size; + return XGE_HAL_OK; +} + +/** + * xge_hal_fifo_dtr_buffer_finalize - Prepares a descriptor that contains the + * single physically contiguous buffer. + * + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * @frag_idx: Index of the data buffer in the Txdl list. + * + * This API in conjuction with xge_hal_fifo_dtr_buffer_append() prepares + * a descriptor that consists of a single physically contiguous buffer + * which inturn contains the contents of one or more virtually contiguous + * buffers received from the upper layer. + * + * See Also: xge_hal_fifo_dtr_buffer_append(). +*/ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_buffer_finalize(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + int frag_idx) +{ + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + xge_hal_fifo_txdl_priv_t *txdl_priv; + xge_hal_fifo_txd_t *txdp; + ptrdiff_t prev_boff; + + xge_assert(frag_idx < fifo->config->max_frags); + + txdl_priv = __hal_fifo_txdl_priv(dtrh); + txdp = (xge_hal_fifo_txd_t *)dtrh + txdl_priv->frags; + + if (frag_idx != 0) { + txdp->control_1 = txdp->control_2 = 0; + } + + prev_boff = txdl_priv->align_vaddr_start - txdl_priv->align_vaddr; + txdp->buffer_pointer = (u64)txdl_priv->align_dma_addr + prev_boff; + txdp->control_1 |= + XGE_HAL_TXD_BUFFER0_SIZE(txdl_priv->align_dma_offset); + txdl_priv->bytes_sent += (unsigned int)txdl_priv->align_dma_offset; + fifo->channel.stats.total_buffers++; + fifo->channel.stats.copied_buffers++; + txdl_priv->frags++; + txdl_priv->align_used_frags++; + +#if defined(XGE_OS_DMA_REQUIRES_SYNC) + /* sync pre-mapped buffer */ + xge_os_dma_sync(fifo->channel.pdev, + txdl_priv->align_dma_handle, + txdp->buffer_pointer, + 0, + txdl_priv->align_dma_offset, + XGE_OS_DMA_DIR_TODEVICE); +#endif + + /* increment vaddr_start for the next buffer_append() iteration */ + txdl_priv->align_vaddr_start += txdl_priv->align_dma_offset; + txdl_priv->align_dma_offset = 0; +} + +/** + * xge_hal_fifo_dtr_buffer_set - Set transmit buffer pointer in the + * descriptor. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * @frag_idx: Index of the data buffer in the caller's scatter-gather listá + * (of buffers). + * @dma_pointer: DMA address of the data buffer referenced by @frag_idx. + * @size: Size of the data buffer (in bytes). + * + * This API is part of the preparation of the transmit descriptor for posting + * (via xge_hal_fifo_dtr_post()). The related "preparation" APIs include + * xge_hal_fifo_dtr_mss_set() and xge_hal_fifo_dtr_cksum_set_bits(). + * All three APIs fill in the fields of the fifo descriptor, + * in accordance with the Xframe specification. + * + * See also: xge_hal_fifo_dtr_buffer_set_aligned(), + * xge_hal_check_alignment(). + * + * See also: xge_hal_fifo_dtr_reserve(), xge_hal_fifo_dtr_post(), + * xge_hal_fifo_dtr_mss_set(), xge_hal_fifo_dtr_cksum_set_bits() + * Prepare transmit descriptor for transmission (via + * xge_hal_fifo_dtr_post()). + * See also: xge_hal_fifo_dtr_vlan_set(). + * Note: Compare with xge_hal_fifo_dtr_buffer_set_aligned(). + * + * Usage: See ex_xmit{}. + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_buffer_set(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + int frag_idx, dma_addr_t dma_pointer, int size) +{ + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + xge_hal_fifo_txdl_priv_t *txdl_priv; + xge_hal_fifo_txd_t *txdp; + + txdl_priv = __hal_fifo_txdl_priv(dtrh); + txdp = (xge_hal_fifo_txd_t *)dtrh + txdl_priv->frags; + + if (frag_idx != 0) { + txdp->control_1 = txdp->control_2 = 0; + } + + /* Note: + * it is the responsibility of upper layers and not HAL + * detect it and skip zero-size fragment + */ + xge_assert(size > 0); + xge_assert(frag_idx < txdl_priv->alloc_frags); + + txdp->buffer_pointer = (u64)dma_pointer; + txdp->control_1 |= XGE_HAL_TXD_BUFFER0_SIZE(size); + txdl_priv->bytes_sent += size; + fifo->channel.stats.total_buffers++; + txdl_priv->frags++; +} + +/** + * xge_hal_fifo_dtr_mss_set - Set MSS. + * @dtrh: Descriptor handle. + * @mss: MSS size for _this_ TCP connection. Passed by TCP stack down to the + * ULD, which in turn inserts the MSS into the @dtrh. + * + * This API is part of the preparation of the transmit descriptor for posting + * (via xge_hal_fifo_dtr_post()). The related "preparation" APIs include + * xge_hal_fifo_dtr_buffer_set(), xge_hal_fifo_dtr_buffer_set_aligned(), + * and xge_hal_fifo_dtr_cksum_set_bits(). + * All these APIs fill in the fields of the fifo descriptor, + * in accordance with the Xframe specification. + * + * See also: xge_hal_fifo_dtr_reserve(), + * xge_hal_fifo_dtr_post(), xge_hal_fifo_dtr_vlan_set(). + * Usage: See ex_xmit{}. + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_mss_set(xge_hal_dtr_h dtrh, int mss) +{ + xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh; + + txdp->control_1 |= XGE_HAL_TXD_LSO_COF_CTRL(XGE_HAL_TXD_TCP_LSO); + txdp->control_1 |= XGE_HAL_TXD_TCP_LSO_MSS(mss); +} + +/** + * xge_hal_fifo_dtr_cksum_set_bits - Offload checksum. + * @dtrh: Descriptor handle. + * @cksum_bits: Specifies which checksums are to be offloaded: IPv4, + * and/or TCP and/or UDP. + * + * Ask Xframe to calculate IPv4 & transport checksums for _this_ transmit + * descriptor. + * This API is part of the preparation of the transmit descriptor for posting + * (via xge_hal_fifo_dtr_post()). The related "preparation" APIs include + * xge_hal_fifo_dtr_mss_set(), xge_hal_fifo_dtr_buffer_set_aligned(), + * and xge_hal_fifo_dtr_buffer_set(). + * All these APIs fill in the fields of the fifo descriptor, + * in accordance with the Xframe specification. + * + * See also: xge_hal_fifo_dtr_reserve(), + * xge_hal_fifo_dtr_post(), XGE_HAL_TXD_TX_CKO_IPV4_EN, + * XGE_HAL_TXD_TX_CKO_TCP_EN. + * Usage: See ex_xmit{}. + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_cksum_set_bits(xge_hal_dtr_h dtrh, u64 cksum_bits) +{ + xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh; + + txdp->control_2 |= cksum_bits; +} + + +/** + * xge_hal_fifo_dtr_vlan_set - Set VLAN tag. + * @dtrh: Descriptor handle. + * @vlan_tag: 16bit VLAN tag. + * + * Insert VLAN tag into specified transmit descriptor. + * The actual insertion of the tag into outgoing frame is done by the hardware. + * See also: xge_hal_fifo_dtr_buffer_set(), xge_hal_fifo_dtr_mss_set(). + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO void +xge_hal_fifo_dtr_vlan_set(xge_hal_dtr_h dtrh, u16 vlan_tag) +{ + xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh; + + txdp->control_2 |= XGE_HAL_TXD_VLAN_ENABLE; + txdp->control_2 |= XGE_HAL_TXD_VLAN_TAG(vlan_tag); +} + +/** + * xge_hal_fifo_is_next_dtr_completed - Checks if the next dtr is completed + * @channelh: Channel handle. + */ +__HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e +xge_hal_fifo_is_next_dtr_completed(xge_hal_channel_h channelh) +{ + xge_hal_fifo_txd_t *txdp; + xge_hal_dtr_h dtrh; + + __hal_channel_dtr_try_complete(channelh, &dtrh); + txdp = (xge_hal_fifo_txd_t *)dtrh; + if (txdp == NULL) { + return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS; + } + + /* check whether host owns it */ + if ( !(txdp->control_1 & XGE_HAL_TXD_LIST_OWN_XENA) ) { + xge_assert(txdp->host_control!=0); + return XGE_HAL_OK; + } + + /* no more completions */ + return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS; +} diff --git a/sys/dev/nxge/xgehal/xgehal-fifo.c b/sys/dev/nxge/xgehal/xgehal-fifo.c new file mode 100644 index 0000000..de6befd --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-fifo.c @@ -0,0 +1,568 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-fifo.c + * + * Description: fifo object implementation + * + * Created: 10 May 2004 + */ + +#include <dev/nxge/include/xgehal-fifo.h> +#include <dev/nxge/include/xgehal-device.h> + +static xge_hal_status_e +__hal_fifo_mempool_item_alloc(xge_hal_mempool_h mempoolh, + void *memblock, + int memblock_index, + xge_hal_mempool_dma_t *dma_object, + void *item, + int index, + int is_last, + void *userdata) +{ + int memblock_item_idx; + xge_hal_fifo_txdl_priv_t *txdl_priv; + xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)item; + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)userdata; + + xge_assert(item); + txdl_priv = (xge_hal_fifo_txdl_priv_t *) \ + __hal_mempool_item_priv((xge_hal_mempool_t *) mempoolh, + memblock_index, + item, + &memblock_item_idx); + xge_assert(txdl_priv); + + /* pre-format HAL's TxDL's private */ + txdl_priv->dma_offset = (char*)item - (char*)memblock; + txdl_priv->dma_addr = dma_object->addr + txdl_priv->dma_offset; + txdl_priv->dma_handle = dma_object->handle; + txdl_priv->memblock = memblock; + txdl_priv->first_txdp = (xge_hal_fifo_txd_t *)item; + txdl_priv->next_txdl_priv = NULL; + txdl_priv->dang_txdl = NULL; + txdl_priv->dang_frags = 0; + txdl_priv->alloc_frags = 0; + +#ifdef XGE_DEBUG_ASSERT + txdl_priv->dma_object = dma_object; +#endif + txdp->host_control = (u64)(ulong_t)txdl_priv; + +#ifdef XGE_HAL_ALIGN_XMIT + txdl_priv->align_vaddr = NULL; + txdl_priv->align_dma_addr = (dma_addr_t)0; + +#ifndef XGE_HAL_ALIGN_XMIT_ALLOC_RT + { + xge_hal_status_e status; + if (fifo->config->alignment_size) { + status =__hal_fifo_dtr_align_alloc_map(fifo, txdp); + if (status != XGE_HAL_OK) { + xge_debug_mm(XGE_ERR, + "align buffer[%d] %d bytes, status %d", + index, + fifo->align_size, + status); + return status; + } + } + } +#endif +#endif + + if (fifo->channel.dtr_init) { + fifo->channel.dtr_init(fifo, (xge_hal_dtr_h)txdp, index, + fifo->channel.userdata, XGE_HAL_CHANNEL_OC_NORMAL); + } + + return XGE_HAL_OK; +} + + +static xge_hal_status_e +__hal_fifo_mempool_item_free(xge_hal_mempool_h mempoolh, + void *memblock, + int memblock_index, + xge_hal_mempool_dma_t *dma_object, + void *item, + int index, + int is_last, + void *userdata) +{ + int memblock_item_idx; + xge_hal_fifo_txdl_priv_t *txdl_priv; +#ifdef XGE_HAL_ALIGN_XMIT + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)userdata; +#endif + + xge_assert(item); + + txdl_priv = (xge_hal_fifo_txdl_priv_t *) \ + __hal_mempool_item_priv((xge_hal_mempool_t *) mempoolh, + memblock_index, + item, + &memblock_item_idx); + xge_assert(txdl_priv); + +#ifdef XGE_HAL_ALIGN_XMIT + if (fifo->config->alignment_size) { + if (txdl_priv->align_dma_addr != 0) { + xge_os_dma_unmap(fifo->channel.pdev, + txdl_priv->align_dma_handle, + txdl_priv->align_dma_addr, + fifo->align_size, + XGE_OS_DMA_DIR_TODEVICE); + + txdl_priv->align_dma_addr = 0; + } + + if (txdl_priv->align_vaddr != NULL) { + xge_os_dma_free(fifo->channel.pdev, + txdl_priv->align_vaddr, + fifo->align_size, + &txdl_priv->align_dma_acch, + &txdl_priv->align_dma_handle); + + txdl_priv->align_vaddr = NULL; + } + } +#endif + + return XGE_HAL_OK; +} + +xge_hal_status_e +__hal_fifo_open(xge_hal_channel_h channelh, xge_hal_channel_attr_t *attr) +{ + xge_hal_device_t *hldev; + xge_hal_status_e status; + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + xge_hal_fifo_queue_t *queue; + int i, txdl_size, max_arr_index, mid_point; + xge_hal_dtr_h dtrh; + + hldev = (xge_hal_device_t *)fifo->channel.devh; + fifo->config = &hldev->config.fifo; + queue = &fifo->config->queue[attr->post_qid]; + +#if defined(XGE_HAL_TX_MULTI_RESERVE) + xge_os_spin_lock_init(&fifo->channel.reserve_lock, hldev->pdev); +#elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) + xge_os_spin_lock_init_irq(&fifo->channel.reserve_lock, hldev->irqh); +#endif +#if defined(XGE_HAL_TX_MULTI_POST) + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { + fifo->post_lock_ptr = &hldev->xena_post_lock; + } else { + xge_os_spin_lock_init(&fifo->channel.post_lock, hldev->pdev); + fifo->post_lock_ptr = &fifo->channel.post_lock; + } +#elif defined(XGE_HAL_TX_MULTI_POST_IRQ) + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { + fifo->post_lock_ptr = &hldev->xena_post_lock; + } else { + xge_os_spin_lock_init_irq(&fifo->channel.post_lock, + hldev->irqh); + fifo->post_lock_ptr = &fifo->channel.post_lock; + } +#endif + + fifo->align_size = + fifo->config->alignment_size * fifo->config->max_aligned_frags; + + /* Initializing the BAR1 address as the start of + * the FIFO queue pointer and as a location of FIFO control + * word. */ + fifo->hw_pair = + (xge_hal_fifo_hw_pair_t *) (void *)(hldev->bar1 + + (attr->post_qid * XGE_HAL_FIFO_HW_PAIR_OFFSET)); + + /* apply "interrupts per txdl" attribute */ + fifo->interrupt_type = XGE_HAL_TXD_INT_TYPE_UTILZ; + if (queue->intr) { + fifo->interrupt_type = XGE_HAL_TXD_INT_TYPE_PER_LIST; + } + fifo->no_snoop_bits = + (int)(XGE_HAL_TX_FIFO_NO_SNOOP(queue->no_snoop_bits)); + + /* + * FIFO memory management strategy: + * + * TxDL splitted into three independent parts: + * - set of TxD's + * - TxD HAL private part + * - upper layer private part + * + * Adaptative memory allocation used. i.e. Memory allocated on + * demand with the size which will fit into one memory block. + * One memory block may contain more than one TxDL. In simple case + * memory block size can be equal to CPU page size. On more + * sophisticated OS's memory block can be contigious across + * several pages. + * + * During "reserve" operations more memory can be allocated on demand + * for example due to FIFO full condition. + * + * Pool of memory memblocks never shrinks except __hal_fifo_close + * routine which will essentially stop channel and free the resources. + */ + + /* TxDL common private size == TxDL private + ULD private */ + fifo->priv_size = sizeof(xge_hal_fifo_txdl_priv_t) + + attr->per_dtr_space; + fifo->priv_size = ((fifo->priv_size + __xge_os_cacheline_size -1) / + __xge_os_cacheline_size) * + __xge_os_cacheline_size; + + /* recompute txdl size to be cacheline aligned */ + fifo->txdl_size = fifo->config->max_frags * sizeof(xge_hal_fifo_txd_t); + txdl_size = ((fifo->txdl_size + __xge_os_cacheline_size - 1) / + __xge_os_cacheline_size) * __xge_os_cacheline_size; + + if (fifo->txdl_size != txdl_size) + xge_debug_fifo(XGE_ERR, "cacheline > 128 ( ?? ): %d, %d, %d, %d", + fifo->config->max_frags, fifo->txdl_size, txdl_size, + __xge_os_cacheline_size); + + fifo->txdl_size = txdl_size; + + /* since dtr_init() callback will be called from item_alloc(), + * the same way channels userdata might be used prior to + * channel_initialize() */ + fifo->channel.dtr_init = attr->dtr_init; + fifo->channel.userdata = attr->userdata; + fifo->txdl_per_memblock = fifo->config->memblock_size / + fifo->txdl_size; + + fifo->mempool = __hal_mempool_create(hldev->pdev, + fifo->config->memblock_size, + fifo->txdl_size, + fifo->priv_size, + queue->initial, + queue->max, + __hal_fifo_mempool_item_alloc, + __hal_fifo_mempool_item_free, + fifo); + if (fifo->mempool == NULL) { + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + + status = __hal_channel_initialize(channelh, attr, + (void **) __hal_mempool_items_arr(fifo->mempool), + queue->initial, queue->max, + fifo->config->reserve_threshold); + if (status != XGE_HAL_OK) { + __hal_fifo_close(channelh); + return status; + } + xge_debug_fifo(XGE_TRACE, + "DTR reserve_length:%d reserve_top:%d\n" + "max_frags:%d reserve_threshold:%d\n" + "memblock_size:%d alignment_size:%d max_aligned_frags:%d", + fifo->channel.reserve_length, fifo->channel.reserve_top, + fifo->config->max_frags, fifo->config->reserve_threshold, + fifo->config->memblock_size, fifo->config->alignment_size, + fifo->config->max_aligned_frags); + +#ifdef XGE_DEBUG_ASSERT + for ( i = 0; i < fifo->channel.reserve_length; i++) { + xge_debug_fifo(XGE_TRACE, "DTR before reversing index:%d" + " handle:%p", i, fifo->channel.reserve_arr[i]); + } +#endif + + xge_assert(fifo->channel.reserve_length); + /* reverse the FIFO dtr array */ + max_arr_index = fifo->channel.reserve_length - 1; + max_arr_index -=fifo->channel.reserve_top; + xge_assert(max_arr_index); + mid_point = (fifo->channel.reserve_length - fifo->channel.reserve_top)/2; + for (i = 0; i < mid_point; i++) { + dtrh = fifo->channel.reserve_arr[i]; + fifo->channel.reserve_arr[i] = + fifo->channel.reserve_arr[max_arr_index - i]; + fifo->channel.reserve_arr[max_arr_index - i] = dtrh; + } + +#ifdef XGE_DEBUG_ASSERT + for ( i = 0; i < fifo->channel.reserve_length; i++) { + xge_debug_fifo(XGE_TRACE, "DTR after reversing index:%d" + " handle:%p", i, fifo->channel.reserve_arr[i]); + } +#endif + + return XGE_HAL_OK; +} + +void +__hal_fifo_close(xge_hal_channel_h channelh) +{ + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + xge_hal_device_t *hldev = (xge_hal_device_t *)fifo->channel.devh; + + if (fifo->mempool) { + __hal_mempool_destroy(fifo->mempool); + } + + __hal_channel_terminate(channelh); + +#if defined(XGE_HAL_TX_MULTI_RESERVE) + xge_os_spin_lock_destroy(&fifo->channel.reserve_lock, hldev->pdev); +#elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) + xge_os_spin_lock_destroy_irq(&fifo->channel.reserve_lock, hldev->pdev); +#endif + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { +#if defined(XGE_HAL_TX_MULTI_POST) + xge_os_spin_lock_destroy(&fifo->channel.post_lock, hldev->pdev); +#elif defined(XGE_HAL_TX_MULTI_POST_IRQ) + xge_os_spin_lock_destroy_irq(&fifo->channel.post_lock, + hldev->pdev); +#endif + } +} + +void +__hal_fifo_hw_initialize(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64* tx_fifo_partitions[4]; + u64* tx_fifo_wrr[5]; + u64 tx_fifo_wrr_value[5]; + u64 val64, part0; + int i; + + /* Tx DMA Initialization */ + + tx_fifo_partitions[0] = &bar0->tx_fifo_partition_0; + tx_fifo_partitions[1] = &bar0->tx_fifo_partition_1; + tx_fifo_partitions[2] = &bar0->tx_fifo_partition_2; + tx_fifo_partitions[3] = &bar0->tx_fifo_partition_3; + + tx_fifo_wrr[0] = &bar0->tx_w_round_robin_0; + tx_fifo_wrr[1] = &bar0->tx_w_round_robin_1; + tx_fifo_wrr[2] = &bar0->tx_w_round_robin_2; + tx_fifo_wrr[3] = &bar0->tx_w_round_robin_3; + tx_fifo_wrr[4] = &bar0->tx_w_round_robin_4; + + tx_fifo_wrr_value[0] = XGE_HAL_FIFO_WRR_0; + tx_fifo_wrr_value[1] = XGE_HAL_FIFO_WRR_1; + tx_fifo_wrr_value[2] = XGE_HAL_FIFO_WRR_2; + tx_fifo_wrr_value[3] = XGE_HAL_FIFO_WRR_3; + tx_fifo_wrr_value[4] = XGE_HAL_FIFO_WRR_4; + + /* Note: WRR calendar must be configured before the transmit + * FIFOs are enabled! page 6-77 user guide */ + + if (!hldev->config.rts_qos_en) { + /* all zeroes for Round-Robin */ + for (i = 0; i < XGE_HAL_FIFO_MAX_WRR; i++) { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0, + tx_fifo_wrr[i]); + } + + /* reset all of them but '0' */ + for (i=1; i < XGE_HAL_FIFO_MAX_PARTITION; i++) { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0ULL, + tx_fifo_partitions[i]); + } + } else { /* Change the default settings */ + + for (i = 0; i < XGE_HAL_FIFO_MAX_WRR; i++) { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + tx_fifo_wrr_value[i], tx_fifo_wrr[i]); + } + } + + /* configure only configured FIFOs */ + val64 = 0; part0 = 0; + for (i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) { + int reg_half = i % 2; + int reg_num = i / 2; + + if (hldev->config.fifo.queue[i].configured) { + int priority = hldev->config.fifo.queue[i].priority; + val64 |= + vBIT((hldev->config.fifo.queue[i].max-1), + (((reg_half) * 32) + 19), + 13) | vBIT(priority, (((reg_half)*32) + 5), 3); + } + + /* NOTE: do write operation for each second u64 half + * or force for first one if configured number + * is even */ + if (reg_half) { + if (reg_num == 0) { + /* skip partition '0', must write it once at + * the end */ + part0 = val64; + } else { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, tx_fifo_partitions[reg_num]); + xge_debug_fifo(XGE_TRACE, + "fifo partition_%d at: " + "0x"XGE_OS_LLXFMT" is: 0x"XGE_OS_LLXFMT, + reg_num, (unsigned long long)(ulong_t) + tx_fifo_partitions[reg_num], + (unsigned long long)val64); + } + val64 = 0; + } + } + + part0 |= BIT(0); /* to enable the FIFO partition. */ + __hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, (u32)part0, + tx_fifo_partitions[0]); + xge_os_wmb(); + __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, (u32)(part0>>32), + tx_fifo_partitions[0]); + xge_debug_fifo(XGE_TRACE, "fifo partition_0 at: " + "0x"XGE_OS_LLXFMT" is: 0x"XGE_OS_LLXFMT, + (unsigned long long)(ulong_t) + tx_fifo_partitions[0], + (unsigned long long) part0); + + /* + * Initialization of Tx_PA_CONFIG register to ignore packet + * integrity checking. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->tx_pa_cfg); + val64 |= XGE_HAL_TX_PA_CFG_IGNORE_FRM_ERR | + XGE_HAL_TX_PA_CFG_IGNORE_SNAP_OUI | + XGE_HAL_TX_PA_CFG_IGNORE_LLC_CTRL | + XGE_HAL_TX_PA_CFG_IGNORE_L2_ERR; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->tx_pa_cfg); + + /* + * Assign MSI-X vectors + */ + for (i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) { + xge_list_t *item; + xge_hal_channel_t *channel = NULL; + + if (!hldev->config.fifo.queue[i].configured || + !hldev->config.fifo.queue[i].intr_vector || + !hldev->config.intr_mode != XGE_HAL_INTR_MODE_MSIX) + continue; + + /* find channel */ + xge_list_for_each(item, &hldev->free_channels) { + xge_hal_channel_t *tmp; + tmp = xge_container_of(item, xge_hal_channel_t, + item); + if (tmp->type == XGE_HAL_CHANNEL_TYPE_FIFO && + tmp->post_qid == i) { + channel = tmp; + break; + } + } + + if (channel) { + xge_hal_channel_msix_set(channel, + hldev->config.fifo.queue[i].intr_vector); + } + } + + xge_debug_fifo(XGE_TRACE, "%s", "fifo channels initialized"); +} + +#ifdef XGE_HAL_ALIGN_XMIT +void +__hal_fifo_dtr_align_free_unmap(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh) +{ + xge_hal_fifo_txdl_priv_t *txdl_priv; + xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh; + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + + txdl_priv = __hal_fifo_txdl_priv(txdp); + + if (txdl_priv->align_dma_addr != 0) { + xge_os_dma_unmap(fifo->channel.pdev, + txdl_priv->align_dma_handle, + txdl_priv->align_dma_addr, + fifo->align_size, + XGE_OS_DMA_DIR_TODEVICE); + + txdl_priv->align_dma_addr = 0; + } + + if (txdl_priv->align_vaddr != NULL) { + xge_os_dma_free(fifo->channel.pdev, + txdl_priv->align_vaddr, + fifo->align_size, + &txdl_priv->align_dma_acch, + &txdl_priv->align_dma_handle); + + + txdl_priv->align_vaddr = NULL; + } + } + +xge_hal_status_e +__hal_fifo_dtr_align_alloc_map(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh) +{ + xge_hal_fifo_txdl_priv_t *txdl_priv; + xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh; + xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh; + + xge_assert(txdp); + + txdl_priv = __hal_fifo_txdl_priv(txdp); + + /* allocate alignment DMA-buffer */ + txdl_priv->align_vaddr = xge_os_dma_malloc(fifo->channel.pdev, + fifo->align_size, + XGE_OS_DMA_CACHELINE_ALIGNED | + XGE_OS_DMA_STREAMING, + &txdl_priv->align_dma_handle, + &txdl_priv->align_dma_acch); + if (txdl_priv->align_vaddr == NULL) { + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + + /* map it */ + txdl_priv->align_dma_addr = xge_os_dma_map(fifo->channel.pdev, + txdl_priv->align_dma_handle, txdl_priv->align_vaddr, + fifo->align_size, + XGE_OS_DMA_DIR_TODEVICE, XGE_OS_DMA_STREAMING); + + if (txdl_priv->align_dma_addr == XGE_OS_INVALID_DMA_ADDR) { + __hal_fifo_dtr_align_free_unmap(channelh, dtrh); + return XGE_HAL_ERR_OUT_OF_MAPPING; + } + + return XGE_HAL_OK; +} +#endif + + diff --git a/sys/dev/nxge/xgehal/xgehal-mgmt.c b/sys/dev/nxge/xgehal/xgehal-mgmt.c new file mode 100644 index 0000000..3e30e25 --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-mgmt.c @@ -0,0 +1,1772 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-mgmt.c + * + * Description: Xframe-family management facility implementation + * + * Created: 1 September 2004 + */ + +#include <dev/nxge/include/xgehal-mgmt.h> +#include <dev/nxge/include/xgehal-driver.h> +#include <dev/nxge/include/xgehal-device.h> + +/** + * xge_hal_mgmt_about - Retrieve about info. + * @devh: HAL device handle. + * @about_info: Filled in by HAL. See xge_hal_mgmt_about_info_t{}. + * @size: Size of the @about_info buffer. HAL will return error if the + * size is smaller than sizeof(xge_hal_mgmt_about_info_t). + * + * Retrieve information such as PCI device and vendor IDs, board + * revision number, HAL version number, etc. + * + * Returns: XGE_HAL_OK - success; + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * XGE_HAL_FAIL - Failed to retrieve the information. + * + * See also: xge_hal_mgmt_about_info_t{}. + */ +xge_hal_status_e +xge_hal_mgmt_about(xge_hal_device_h devh, xge_hal_mgmt_about_info_t *about_info, + int size) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + + if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if (size != sizeof(xge_hal_mgmt_about_info_t)) { + return XGE_HAL_ERR_VERSION_CONFLICT; + } + + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, vendor_id), + &about_info->vendor); + + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, device_id), + &about_info->device); + + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, subsystem_vendor_id), + &about_info->subsys_vendor); + + xge_os_pci_read16(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, subsystem_id), + &about_info->subsys_device); + + xge_os_pci_read8(hldev->pdev, hldev->cfgh, + xge_offsetof(xge_hal_pci_config_le_t, revision), + &about_info->board_rev); + + xge_os_strcpy(about_info->vendor_name, XGE_DRIVER_VENDOR); + xge_os_strcpy(about_info->chip_name, XGE_CHIP_FAMILY); + xge_os_strcpy(about_info->media, XGE_SUPPORTED_MEDIA_0); + + xge_os_strcpy(about_info->hal_major, XGE_HAL_VERSION_MAJOR); + xge_os_strcpy(about_info->hal_minor, XGE_HAL_VERSION_MINOR); + xge_os_strcpy(about_info->hal_fix, XGE_HAL_VERSION_FIX); + xge_os_strcpy(about_info->hal_build, XGE_HAL_VERSION_BUILD); + + xge_os_strcpy(about_info->ll_major, XGELL_VERSION_MAJOR); + xge_os_strcpy(about_info->ll_minor, XGELL_VERSION_MINOR); + xge_os_strcpy(about_info->ll_fix, XGELL_VERSION_FIX); + xge_os_strcpy(about_info->ll_build, XGELL_VERSION_BUILD); + + about_info->transponder_temperature = + xge_hal_read_xfp_current_temp(devh); + + return XGE_HAL_OK; +} + +/** + * xge_hal_mgmt_reg_read - Read Xframe register. + * @devh: HAL device handle. + * @bar_id: 0 - for BAR0, 1- for BAR1. + * @offset: Register offset in the Base Address Register (BAR) space. + * @value: Register value. Returned by HAL. + * Read Xframe register. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_INVALID_OFFSET - Register offset in the BAR space is not + * valid. + * XGE_HAL_ERR_INVALID_BAR_ID - BAR id is not valid. + * + * See also: xge_hal_aux_bar0_read(), xge_hal_aux_bar1_read(). + */ +xge_hal_status_e +xge_hal_mgmt_reg_read(xge_hal_device_h devh, int bar_id, unsigned int offset, + u64 *value) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + + if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if (bar_id == 0) { + if (offset > sizeof(xge_hal_pci_bar0_t)-8) { + return XGE_HAL_ERR_INVALID_OFFSET; + } + *value = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + (void *)(hldev->bar0 + offset)); + } else if (bar_id == 1 && + (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA || + xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)) { + int i; + for (i=0; i<XGE_HAL_MAX_FIFO_NUM_HERC; i++) { + if (offset == i*0x2000 || offset == i*0x2000+0x18) { + break; + } + } + if (i == XGE_HAL_MAX_FIFO_NUM_HERC) { + return XGE_HAL_ERR_INVALID_OFFSET; + } + *value = xge_os_pio_mem_read64(hldev->pdev, hldev->regh1, + (void *)(hldev->bar1 + offset)); + } else if (bar_id == 1) { + /* FIXME: check TITAN BAR1 offsets */ + } else { + return XGE_HAL_ERR_INVALID_BAR_ID; + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_mgmt_reg_write - Write Xframe register. + * @devh: HAL device handle. + * @bar_id: 0 - for BAR0, 1- for BAR1. + * @offset: Register offset in the Base Address Register (BAR) space. + * @value: Register value. + * + * Write Xframe register. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_INVALID_OFFSET - Register offset in the BAR space is not + * valid. + * XGE_HAL_ERR_INVALID_BAR_ID - BAR id is not valid. + * + * See also: xge_hal_aux_bar0_write(). + */ +xge_hal_status_e +xge_hal_mgmt_reg_write(xge_hal_device_h devh, int bar_id, unsigned int offset, + u64 value) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + + if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if (bar_id == 0) { + if (offset > sizeof(xge_hal_pci_bar0_t)-8) { + return XGE_HAL_ERR_INVALID_OFFSET; + } + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, value, + (void *)(hldev->bar0 + offset)); + } else if (bar_id == 1 && + (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA || + xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)) { + int i; + for (i=0; i<XGE_HAL_MAX_FIFO_NUM_HERC; i++) { + if (offset == i*0x2000 || offset == i*0x2000+0x18) { + break; + } + } + if (i == XGE_HAL_MAX_FIFO_NUM_HERC) { + return XGE_HAL_ERR_INVALID_OFFSET; + } + xge_os_pio_mem_write64(hldev->pdev, hldev->regh1, value, + (void *)(hldev->bar1 + offset)); + } else if (bar_id == 1) { + /* FIXME: check TITAN BAR1 offsets */ + } else { + return XGE_HAL_ERR_INVALID_BAR_ID; + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_mgmt_hw_stats - Get Xframe hardware statistics. + * @devh: HAL device handle. + * @hw_stats: Hardware statistics. Returned by HAL. + * See xge_hal_stats_hw_info_t{}. + * @size: Size of the @hw_stats buffer. HAL will return an error + * if the size is smaller than sizeof(xge_hal_stats_hw_info_t). + * Get Xframe hardware statistics. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + * See also: xge_hal_mgmt_sw_stats(). + */ +xge_hal_status_e +xge_hal_mgmt_hw_stats(xge_hal_device_h devh, xge_hal_mgmt_hw_stats_t *hw_stats, + int size) +{ + xge_hal_status_e status; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_stats_hw_info_t *hw_info; + + xge_assert(xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN); + + if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if (size != sizeof(xge_hal_stats_hw_info_t)) { + return XGE_HAL_ERR_VERSION_CONFLICT; + } + + if ((status = xge_hal_stats_hw (devh, &hw_info)) != XGE_HAL_OK) { + return status; + } + + xge_os_memcpy(hw_stats, hw_info, sizeof(xge_hal_stats_hw_info_t)); + + return XGE_HAL_OK; +} + +/** + * xge_hal_mgmt_hw_stats_off - TBD. + * @devh: HAL device handle. + * @off: TBD + * @size: TBD + * @out: TBD + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + * See also: xge_hal_mgmt_sw_stats(). + */ +xge_hal_status_e +xge_hal_mgmt_hw_stats_off(xge_hal_device_h devh, int off, int size, char *out) +{ + xge_hal_status_e status; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_stats_hw_info_t *hw_info; + + xge_assert(xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN); + + if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if (off > sizeof(xge_hal_stats_hw_info_t)-4 || + size > 8) { + return XGE_HAL_ERR_INVALID_OFFSET; + } + + if ((status = xge_hal_stats_hw (devh, &hw_info)) != XGE_HAL_OK) { + return status; + } + + xge_os_memcpy(out, (char*)hw_info + off, size); + + return XGE_HAL_OK; +} + +/** + * xge_hal_mgmt_pcim_stats - Get Titan hardware statistics. + * @devh: HAL device handle. + * @pcim_stats: PCIM statistics. Returned by HAL. + * See xge_hal_stats_hw_info_t{}. + * @size: Size of the @hw_stats buffer. HAL will return an error + * if the size is smaller than sizeof(xge_hal_stats_hw_info_t). + * Get Xframe hardware statistics. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + * See also: xge_hal_mgmt_sw_stats(). + */ +xge_hal_status_e +xge_hal_mgmt_pcim_stats(xge_hal_device_h devh, + xge_hal_mgmt_pcim_stats_t *pcim_stats, int size) +{ + xge_hal_status_e status; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_stats_pcim_info_t *pcim_info; + + xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN); + + if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if (size != sizeof(xge_hal_stats_pcim_info_t)) { + return XGE_HAL_ERR_VERSION_CONFLICT; + } + + if ((status = xge_hal_stats_pcim (devh, &pcim_info)) != XGE_HAL_OK) { + return status; + } + + xge_os_memcpy(pcim_stats, pcim_info, + sizeof(xge_hal_stats_pcim_info_t)); + + return XGE_HAL_OK; +} + +/** + * xge_hal_mgmt_pcim_stats_off - TBD. + * @devh: HAL device handle. + * @off: TBD + * @size: TBD + * @out: TBD + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + * See also: xge_hal_mgmt_sw_stats(). + */ +xge_hal_status_e +xge_hal_mgmt_pcim_stats_off(xge_hal_device_h devh, int off, int size, + char *out) +{ + xge_hal_status_e status; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_stats_pcim_info_t *pcim_info; + + xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN); + + if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if (off > sizeof(xge_hal_stats_pcim_info_t)-8 || + size > 8) { + return XGE_HAL_ERR_INVALID_OFFSET; + } + + if ((status = xge_hal_stats_pcim (devh, &pcim_info)) != XGE_HAL_OK) { + return status; + } + + xge_os_memcpy(out, (char*)pcim_info + off, size); + + return XGE_HAL_OK; +} + +/** + * xge_hal_mgmt_sw_stats - Get per-device software statistics. + * @devh: HAL device handle. + * @sw_stats: Hardware statistics. Returned by HAL. + * See xge_hal_stats_sw_err_t{}. + * @size: Size of the @sw_stats buffer. HAL will return an error + * if the size is smaller than sizeof(xge_hal_stats_sw_err_t). + * Get device software statistics, including ECC and Parity error + * counters, etc. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + * See also: xge_hal_stats_sw_err_t{}, xge_hal_mgmt_hw_stats(). + */ +xge_hal_status_e +xge_hal_mgmt_sw_stats(xge_hal_device_h devh, xge_hal_mgmt_sw_stats_t *sw_stats, + int size) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + + if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if (size != sizeof(xge_hal_stats_sw_err_t)) { + return XGE_HAL_ERR_VERSION_CONFLICT; + } + + if (!hldev->stats.is_initialized || + !hldev->stats.is_enabled) { + return XGE_HAL_INF_STATS_IS_NOT_READY; + } + + /* Updating xpak stats value */ + __hal_updt_stats_xpak(hldev); + + xge_os_memcpy(sw_stats, &hldev->stats.sw_dev_err_stats, + sizeof(xge_hal_stats_sw_err_t)); + + return XGE_HAL_OK; +} + +/** + * xge_hal_mgmt_device_stats - Get HAL device statistics. + * @devh: HAL device handle. + * @device_stats: HAL device "soft" statistics. Maintained by HAL itself. + * (as opposed to xge_hal_mgmt_hw_stats() - those are + * maintained by the Xframe hardware). + * Returned by HAL. + * See xge_hal_stats_device_info_t{}. + * @size: Size of the @device_stats buffer. HAL will return an error + * if the size is smaller than sizeof(xge_hal_stats_device_info_t). + * + * Get HAL (layer) statistic counters. + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not + * currently available. + * + */ +xge_hal_status_e +xge_hal_mgmt_device_stats(xge_hal_device_h devh, + xge_hal_mgmt_device_stats_t *device_stats, int size) +{ + xge_hal_status_e status; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_stats_device_info_t *device_info; + + if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if (size != sizeof(xge_hal_stats_device_info_t)) { + return XGE_HAL_ERR_VERSION_CONFLICT; + } + + if ((status = xge_hal_stats_device (devh, &device_info)) != + XGE_HAL_OK) { + return status; + } + + xge_os_memcpy(device_stats, device_info, + sizeof(xge_hal_stats_device_info_t)); + + return XGE_HAL_OK; +} + +/* + * __hal_update_ring_bump - Update the ring bump counter for the + * particular channel. + * @hldev: HAL device handle. + * @queue: the queue who's data is to be collected. + * @chinfo: pointer to the statistics structure of the given channel. + * Usage: See xge_hal_aux_stats_hal_read{} + */ + +static void +__hal_update_ring_bump(xge_hal_device_t *hldev, int queue, + xge_hal_stats_channel_info_t *chinfo) +{ + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 rbc = 0; + int reg = (queue / 4); + void * addr; + + addr = (reg == 1)? (&bar0->ring_bump_counter2) : + (&bar0->ring_bump_counter1); + rbc = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, addr); + chinfo->ring_bump_cnt = XGE_HAL_RING_BUMP_CNT(queue, rbc); +} + +/** + * xge_hal_mgmt_channel_stats - Get HAL channel statistics. + * @channelh: HAL channel handle. + * @channel_stats: HAL channel statistics. Maintained by HAL itself + * (as opposed to xge_hal_mgmt_hw_stats() - those are + * maintained by the Xframe hardware). + * Returned by HAL. + * See xge_hal_stats_channel_info_t{}. + * @size: Size of the @channel_stats buffer. HAL will return an error + * if the size is smaller than sizeof(xge_hal_mgmt_channel_stats_t). + * + * Get HAL per-channel statistic counters. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not + * currently available. + * + */ +xge_hal_status_e +xge_hal_mgmt_channel_stats(xge_hal_channel_h channelh, + xge_hal_mgmt_channel_stats_t *channel_stats, int size) +{ + xge_hal_status_e status; + xge_hal_stats_channel_info_t *channel_info; + xge_hal_channel_t *channel = (xge_hal_channel_t* ) channelh; + + if (size != sizeof(xge_hal_stats_channel_info_t)) { + return XGE_HAL_ERR_VERSION_CONFLICT; + } + + if ((status = xge_hal_stats_channel (channelh, &channel_info)) != + XGE_HAL_OK) { + return status; + } + + if (xge_hal_device_check_id(channel->devh) == XGE_HAL_CARD_HERC) { + __hal_update_ring_bump( (xge_hal_device_t *) channel->devh, channel->post_qid, channel_info); + } + + xge_os_memcpy(channel_stats, channel_info, + sizeof(xge_hal_stats_channel_info_t)); + + return XGE_HAL_OK; +} + +/** + * xge_hal_mgmt_pcireg_read - Read PCI configuration at a specified + * offset. + * @devh: HAL device handle. + * @offset: Offset in the 256 byte PCI configuration space. + * @value_bits: 8, 16, or 32 (bits) to read. + * @value: Value returned by HAL. + * + * Read PCI configuration, given device and offset in the PCI space. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_INVALID_OFFSET - Register offset in the BAR space is not + * valid. + * XGE_HAL_ERR_INVALID_VALUE_BIT_SIZE - Invalid bits size. Valid + * values(8/16/32). + * + */ +xge_hal_status_e +xge_hal_mgmt_pcireg_read(xge_hal_device_h devh, unsigned int offset, + int value_bits, u32 *value) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + + if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if (offset > sizeof(xge_hal_pci_config_t)-value_bits/8) { + return XGE_HAL_ERR_INVALID_OFFSET; + } + + if (value_bits == 8) { + xge_os_pci_read8(hldev->pdev, hldev->cfgh, offset, (u8*)value); + } else if (value_bits == 16) { + xge_os_pci_read16(hldev->pdev, hldev->cfgh, offset, + (u16*)value); + } else if (value_bits == 32) { + xge_os_pci_read32(hldev->pdev, hldev->cfgh, offset, value); + } else { + return XGE_HAL_ERR_INVALID_VALUE_BIT_SIZE; + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_mgmt_device_config - Retrieve device configuration. + * @devh: HAL device handle. + * @dev_config: Device configuration, see xge_hal_device_config_t{}. + * @size: Size of the @dev_config buffer. HAL will return an error + * if the size is smaller than sizeof(xge_hal_mgmt_device_config_t). + * + * Get device configuration. Permits to retrieve at run-time configuration + * values that were used to initialize and configure the device. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + * See also: xge_hal_device_config_t{}, xge_hal_mgmt_driver_config(). + */ +xge_hal_status_e +xge_hal_mgmt_device_config(xge_hal_device_h devh, + xge_hal_mgmt_device_config_t *dev_config, int size) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + + if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if (size != sizeof(xge_hal_mgmt_device_config_t)) { + return XGE_HAL_ERR_VERSION_CONFLICT; + } + + xge_os_memcpy(dev_config, &hldev->config, + sizeof(xge_hal_device_config_t)); + + return XGE_HAL_OK; +} + +/** + * xge_hal_mgmt_driver_config - Retrieve driver configuration. + * @drv_config: Device configuration, see xge_hal_driver_config_t{}. + * @size: Size of the @dev_config buffer. HAL will return an error + * if the size is smaller than sizeof(xge_hal_mgmt_driver_config_t). + * + * Get driver configuration. Permits to retrieve at run-time configuration + * values that were used to configure the device at load-time. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_DRIVER_NOT_INITIALIZED - HAL is not initialized. + * XGE_HAL_ERR_VERSION_CONFLICT - Version is not maching. + * + * See also: xge_hal_driver_config_t{}, xge_hal_mgmt_device_config(). + */ +xge_hal_status_e +xge_hal_mgmt_driver_config(xge_hal_mgmt_driver_config_t *drv_config, int size) +{ + + if (g_xge_hal_driver == NULL) { + return XGE_HAL_ERR_DRIVER_NOT_INITIALIZED; + } + + if (size != sizeof(xge_hal_mgmt_driver_config_t)) { + return XGE_HAL_ERR_VERSION_CONFLICT; + } + + xge_os_memcpy(drv_config, &g_xge_hal_driver->config, + sizeof(xge_hal_mgmt_driver_config_t)); + + return XGE_HAL_OK; +} + +/** + * xge_hal_mgmt_pci_config - Retrieve PCI configuration. + * @devh: HAL device handle. + * @pci_config: 256 byte long buffer for PCI configuration space. + * @size: Size of the @ buffer. HAL will return an error + * if the size is smaller than sizeof(xge_hal_mgmt_pci_config_t). + * + * Get PCI configuration. Permits to retrieve at run-time configuration + * values that were used to configure the device at load-time. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + */ +xge_hal_status_e +xge_hal_mgmt_pci_config(xge_hal_device_h devh, + xge_hal_mgmt_pci_config_t *pci_config, int size) +{ + int i; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + + if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if (size != sizeof(xge_hal_mgmt_pci_config_t)) { + return XGE_HAL_ERR_VERSION_CONFLICT; + } + + /* refresh PCI config space */ + for (i = 0; i < 0x68/4+1; i++) { + xge_os_pci_read32(hldev->pdev, hldev->cfgh, i*4, + (u32*)&hldev->pci_config_space + i); + } + + xge_os_memcpy(pci_config, &hldev->pci_config_space, + sizeof(xge_hal_mgmt_pci_config_t)); + + return XGE_HAL_OK; +} + +#ifdef XGE_TRACE_INTO_CIRCULAR_ARR +/** + * xge_hal_mgmt_trace_read - Read trace buffer contents. + * @buffer: Buffer to store the trace buffer contents. + * @buf_size: Size of the buffer. + * @offset: Offset in the internal trace buffer to read data. + * @read_length: Size of the valid data in the buffer. + * + * Read HAL trace buffer contents starting from the offset + * upto the size of the buffer or till EOF is reached. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_EOF_TRACE_BUF - No more data in the trace buffer. + * + */ +xge_hal_status_e +xge_hal_mgmt_trace_read (char *buffer, + unsigned buf_size, + unsigned *offset, + unsigned *read_length) +{ + int data_offset; + int start_offset; + + if ((g_xge_os_tracebuf == NULL) || + (g_xge_os_tracebuf->offset == g_xge_os_tracebuf->size - 2)) { + return XGE_HAL_EOF_TRACE_BUF; + } + + data_offset = g_xge_os_tracebuf->offset + 1; + + if (*offset >= (unsigned)xge_os_strlen(g_xge_os_tracebuf->data + + data_offset)) { + + return XGE_HAL_EOF_TRACE_BUF; + } + + xge_os_memzero(buffer, buf_size); + + start_offset = data_offset + *offset; + *read_length = xge_os_strlen(g_xge_os_tracebuf->data + + start_offset); + + if (*read_length >= buf_size) { + *read_length = buf_size - 1; + } + + xge_os_memcpy(buffer, g_xge_os_tracebuf->data + start_offset, + *read_length); + + *offset += *read_length; + (*read_length) ++; + + return XGE_HAL_OK; +} + +#endif + +/** + * xge_hal_restore_link_led - Restore link LED to its original state. + * @devh: HAL device handle. + */ +void +xge_hal_restore_link_led(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64; + + /* + * If the current link state is UP, switch on LED else make it + * off. + */ + + /* + * For Xena 3 and lower revision cards, adapter control needs to be + * used for making LED ON/OFF. + */ + if ((xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) && + (xge_hal_device_rev(hldev) <= 3)) { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + if (hldev->link_state == XGE_HAL_LINK_UP) { + val64 |= XGE_HAL_ADAPTER_LED_ON; + } else { + val64 &= ~XGE_HAL_ADAPTER_LED_ON; + } + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->adapter_control); + return; + } + + /* + * Use beacon control register to control the LED. + * LED link output corresponds to bit 8 of the beacon control + * register. Note that, in the case of Xena, beacon control register + * represents the gpio control register. In the case of Herc, LED + * handling is done by beacon control register as opposed to gpio + * control register in Xena. Beacon control is used only to toggle + * and the value written into it does not depend on the link state. + * It is upto the ULD to toggle the LED even number of times which + * brings the LED to it's original state. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->beacon_control); + val64 |= 0x0000800000000000ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->beacon_control); +} + +/** + * xge_hal_flick_link_led - Flick (blink) link LED. + * @devh: HAL device handle. + * + * Depending on the card revision flicker the link LED by using the + * beacon control or the adapter_control register. + */ +void +xge_hal_flick_link_led(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64 = 0; + + /* + * For Xena 3 and lower revision cards, adapter control needs to be + * used for making LED ON/OFF. + */ + if ((xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) && + (xge_hal_device_rev(hldev) <= 3)) { + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + val64 ^= XGE_HAL_ADAPTER_LED_ON; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->adapter_control); + return; + } + + /* + * Use beacon control register to control the Link LED. + * Note that, in the case of Xena, beacon control register represents + * the gpio control register. In the case of Herc, LED handling is + * done by beacon control register as opposed to gpio control register + * in Xena. + */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->beacon_control); + val64 ^= XGE_HAL_GPIO_CTRL_GPIO_0; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->beacon_control); +} + +/** + * xge_hal_read_eeprom - Read 4 bytes of data from user given offset. + * @devh: HAL device handle. + * @off: offset at which the data must be written + * @data: output parameter where the data is stored. + * + * Read 4 bytes of data from the user given offset and return the + * read data. + * Note: will allow to read only part of the EEPROM visible through the + * I2C bus. + * Returns: -1 on failure, 0 on success. + */ +xge_hal_status_e +xge_hal_read_eeprom(xge_hal_device_h devh, int off, u32* data) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_status_e ret = XGE_HAL_FAIL; + u32 exit_cnt = 0; + u64 val64; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + + val64 = XGE_HAL_I2C_CONTROL_DEV_ID(XGE_DEV_ID) | + XGE_HAL_I2C_CONTROL_ADDR(off) | + XGE_HAL_I2C_CONTROL_BYTE_CNT(0x3) | + XGE_HAL_I2C_CONTROL_READ | XGE_HAL_I2C_CONTROL_CNTL_START; + + __hal_serial_mem_write64(hldev, val64, &bar0->i2c_control); + + while (exit_cnt < 5) { + val64 = __hal_serial_mem_read64(hldev, &bar0->i2c_control); + if (XGE_HAL_I2C_CONTROL_CNTL_END(val64)) { + *data = XGE_HAL_I2C_CONTROL_GET_DATA(val64); + ret = XGE_HAL_OK; + break; + } + exit_cnt++; + } + + return ret; +} + +/* + * xge_hal_write_eeprom - actually writes the relevant part of the data + value. + * @devh: HAL device handle. + * @off: offset at which the data must be written + * @data : The data that is to be written + * @cnt : Number of bytes of the data that are actually to be written into + * the Eeprom. (max of 3) + * + * Actually writes the relevant part of the data value into the Eeprom + * through the I2C bus. + * Return value: + * 0 on success, -1 on failure. + */ + +xge_hal_status_e +xge_hal_write_eeprom(xge_hal_device_h devh, int off, u32 data, int cnt) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_status_e ret = XGE_HAL_FAIL; + u32 exit_cnt = 0; + u64 val64; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + + val64 = XGE_HAL_I2C_CONTROL_DEV_ID(XGE_DEV_ID) | + XGE_HAL_I2C_CONTROL_ADDR(off) | + XGE_HAL_I2C_CONTROL_BYTE_CNT(cnt) | + XGE_HAL_I2C_CONTROL_SET_DATA(data) | + XGE_HAL_I2C_CONTROL_CNTL_START; + __hal_serial_mem_write64(hldev, val64, &bar0->i2c_control); + + while (exit_cnt < 5) { + val64 = __hal_serial_mem_read64(hldev, &bar0->i2c_control); + if (XGE_HAL_I2C_CONTROL_CNTL_END(val64)) { + if (!(val64 & XGE_HAL_I2C_CONTROL_NACK)) + ret = XGE_HAL_OK; + break; + } + exit_cnt++; + } + + return ret; +} + +/* + * xge_hal_register_test - reads and writes into all clock domains. + * @hldev : private member of the device structure. + * xge_nic structure. + * @data : variable that returns the result of each of the test conducted b + * by the driver. + * + * Read and write into all clock domains. The NIC has 3 clock domains, + * see that registers in all the three regions are accessible. + * Return value: + * 0 on success. + */ +xge_hal_status_e +xge_hal_register_test(xge_hal_device_h devh, u64 *data) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64 = 0; + int fail = 0; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->pif_rd_swapper_fb); + if (val64 != 0x123456789abcdefULL) { + fail = 1; + xge_debug_osdep(XGE_TRACE, "Read Test level 1 fails"); + } + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rmac_pause_cfg); + if (val64 != 0xc000ffff00000000ULL) { + fail = 1; + xge_debug_osdep(XGE_TRACE, "Read Test level 2 fails"); + } + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rx_queue_cfg); + if (val64 != 0x0808080808080808ULL) { + fail = 1; + xge_debug_osdep(XGE_TRACE, "Read Test level 3 fails"); + } + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->xgxs_efifo_cfg); + if (val64 != 0x000000001923141EULL) { + fail = 1; + xge_debug_osdep(XGE_TRACE, "Read Test level 4 fails"); + } + + val64 = 0x5A5A5A5A5A5A5A5AULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->xmsi_data); + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->xmsi_data); + if (val64 != 0x5A5A5A5A5A5A5A5AULL) { + fail = 1; + xge_debug_osdep(XGE_ERR, "Write Test level 1 fails"); + } + + val64 = 0xA5A5A5A5A5A5A5A5ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->xmsi_data); + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->xmsi_data); + if (val64 != 0xA5A5A5A5A5A5A5A5ULL) { + fail = 1; + xge_debug_osdep(XGE_ERR, "Write Test level 2 fails"); + } + + *data = fail; + return XGE_HAL_OK; +} + +/* + * xge_hal_rldram_test - offline test for access to the RldRam chip on + the NIC + * @devh: HAL device handle. + * @data: variable that returns the result of each of the test + * conducted by the driver. + * + * This is one of the offline test that tests the read and write + * access to the RldRam chip on the NIC. + * Return value: + * 0 on success. + */ +xge_hal_status_e +xge_hal_rldram_test(xge_hal_device_h devh, u64 *data) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64; + int cnt, iteration = 0, test_pass = 0; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_control); + val64 &= ~XGE_HAL_ADAPTER_ECC_EN; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->adapter_control); + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mc_rldram_test_ctrl); + val64 |= XGE_HAL_MC_RLDRAM_TEST_MODE; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mc_rldram_test_ctrl); + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mc_rldram_mrs); + val64 |= XGE_HAL_MC_RLDRAM_QUEUE_SIZE_ENABLE; + __hal_serial_mem_write64(hldev, val64, &bar0->i2c_control); + + val64 |= XGE_HAL_MC_RLDRAM_MRS_ENABLE; + __hal_serial_mem_write64(hldev, val64, &bar0->i2c_control); + + while (iteration < 2) { + val64 = 0x55555555aaaa0000ULL; + if (iteration == 1) { + val64 ^= 0xFFFFFFFFFFFF0000ULL; + } + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mc_rldram_test_d0); + + val64 = 0xaaaa5a5555550000ULL; + if (iteration == 1) { + val64 ^= 0xFFFFFFFFFFFF0000ULL; + } + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mc_rldram_test_d1); + + val64 = 0x55aaaaaaaa5a0000ULL; + if (iteration == 1) { + val64 ^= 0xFFFFFFFFFFFF0000ULL; + } + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mc_rldram_test_d2); + + val64 = (u64) (0x0000003fffff0000ULL); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mc_rldram_test_add); + + + val64 = XGE_HAL_MC_RLDRAM_TEST_MODE; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mc_rldram_test_ctrl); + + val64 |= + XGE_HAL_MC_RLDRAM_TEST_MODE | XGE_HAL_MC_RLDRAM_TEST_WRITE | + XGE_HAL_MC_RLDRAM_TEST_GO; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mc_rldram_test_ctrl); + + for (cnt = 0; cnt < 5; cnt++) { + val64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->mc_rldram_test_ctrl); + if (val64 & XGE_HAL_MC_RLDRAM_TEST_DONE) + break; + xge_os_mdelay(200); + } + + if (cnt == 5) + break; + + val64 = XGE_HAL_MC_RLDRAM_TEST_MODE; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mc_rldram_test_ctrl); + + val64 |= XGE_HAL_MC_RLDRAM_TEST_MODE | + XGE_HAL_MC_RLDRAM_TEST_GO; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mc_rldram_test_ctrl); + + for (cnt = 0; cnt < 5; cnt++) { + val64 = xge_os_pio_mem_read64(hldev->pdev, + hldev->regh0, &bar0->mc_rldram_test_ctrl); + if (val64 & XGE_HAL_MC_RLDRAM_TEST_DONE) + break; + xge_os_mdelay(500); + } + + if (cnt == 5) + break; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mc_rldram_test_ctrl); + if (val64 & XGE_HAL_MC_RLDRAM_TEST_PASS) + test_pass = 1; + + iteration++; + } + + if (!test_pass) + *data = 1; + else + *data = 0; + + return XGE_HAL_OK; +} + +/* + * xge_hal_pma_loopback - Enable or disable PMA loopback + * @devh: HAL device handle. + * @enable:Boolean set to 1 to enable and 0 to disable. + * + * Enable or disable PMA loopback. + * Return value: + * 0 on success. + */ +xge_hal_status_e +xge_hal_pma_loopback( xge_hal_device_h devh, int enable ) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64; + u16 data; + + /* + * This code if for MAC loopbak + * Should be enabled through another parameter + */ +#if 0 + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mac_cfg); + if ( enable ) + { + val64 |= ( XGE_HAL_MAC_CFG_TMAC_LOOPBACK | XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE ); + } + __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, + (u32)(val64 >> 32), (char*)&bar0->mac_cfg); + xge_os_mdelay(1); +#endif + + val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1) | + XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_CTRL(0) | + XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_ADDRESS); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1) | + XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_CTRL(0) | + XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_READ); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control); + + data = (u16)XGE_HAL_MDIO_CONTROL_MMD_DATA_GET(val64); + +#define _HAL_LOOPBK_PMA 1 + + if( enable ) + data |= 1; + else + data &= 0xfe; + + val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1) | + XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_CTRL(0) | + XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_ADDRESS); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1) | + XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_DATA(data) | + XGE_HAL_MDIO_CONTROL_MMD_CTRL(0x0) | + XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_WRITE); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1) | + XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_CTRL(0x0) | + XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_READ); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + return XGE_HAL_OK; +} + +u16 +xge_hal_mdio_read( xge_hal_device_h devh, u32 mmd_type, u64 addr ) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64 = 0x0; + u16 rval16 = 0x0; + u8 i = 0; + + /* address transaction */ + val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(addr) | + XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(mmd_type) | + XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_ADDRESS); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + do + { + val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control); + if (i++ > 10) + { + break; + } + }while((val64 & XGE_HAL_MDIO_CONTROL_MMD_CTRL(0xF)) != XGE_HAL_MDIO_CONTROL_MMD_CTRL(1)); + + /* Data transaction */ + val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(addr) | + XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(mmd_type) | + XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_READ); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + i = 0; + + do + { + val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control); + if (i++ > 10) + { + break; + } + }while((val64 & XGE_HAL_MDIO_CONTROL_MMD_CTRL(0xF)) != XGE_HAL_MDIO_CONTROL_MMD_CTRL(1)); + + rval16 = (u16)XGE_HAL_MDIO_CONTROL_MMD_DATA_GET(val64); + + return rval16; +} + +xge_hal_status_e +xge_hal_mdio_write( xge_hal_device_h devh, u32 mmd_type, u64 addr, u32 value ) +{ + u64 val64 = 0x0; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u8 i = 0; + /* address transaction */ + + val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(addr) | + XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(mmd_type) | + XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_ADDRESS); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + do + { + val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control); + if (i++ > 10) + { + break; + } + } while((val64 & XGE_HAL_MDIO_CONTROL_MMD_CTRL(0xF)) != + XGE_HAL_MDIO_CONTROL_MMD_CTRL(1)); + + /* Data transaction */ + + val64 = 0x0; + + val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(addr) | + XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(mmd_type) | + XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | + XGE_HAL_MDIO_CONTROL_MMD_DATA(value) | + XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_WRITE); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); + __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); + + i = 0; + + do + { + val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control); + if (i++ > 10) + { + break; + } + }while((val64 & XGE_HAL_MDIO_CONTROL_MMD_CTRL(0xF)) != XGE_HAL_MDIO_CONTROL_MMD_CTRL(1)); + + return XGE_HAL_OK; +} + +/* + * xge_hal_eeprom_test - to verify that EEprom in the xena can be + programmed. + * @devh: HAL device handle. + * @data:variable that returns the result of each of the test conducted by + * the driver. + * + * Verify that EEPROM in the xena can be programmed using I2C_CONTROL + * register. + * Return value: + * 0 on success. + */ +xge_hal_status_e +xge_hal_eeprom_test(xge_hal_device_h devh, u64 *data) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + int fail = 0; + u32 ret_data = 0; + + /* Test Write Error at offset 0 */ + if (!xge_hal_write_eeprom(hldev, 0, 0, 3)) + fail = 1; + + /* Test Write at offset 4f0 */ + if (xge_hal_write_eeprom(hldev, 0x4F0, 0x01234567, 3)) + fail = 1; + if (xge_hal_read_eeprom(hldev, 0x4F0, &ret_data)) + fail = 1; + + if (ret_data != 0x01234567) + fail = 1; + + /* Reset the EEPROM data go FFFF */ + (void) xge_hal_write_eeprom(hldev, 0x4F0, 0xFFFFFFFF, 3); + + /* Test Write Request Error at offset 0x7c */ + if (!xge_hal_write_eeprom(hldev, 0x07C, 0, 3)) + fail = 1; + + /* Test Write Request at offset 0x7fc */ + if (xge_hal_write_eeprom(hldev, 0x7FC, 0x01234567, 3)) + fail = 1; + if (xge_hal_read_eeprom(hldev, 0x7FC, &ret_data)) + fail = 1; + + if (ret_data != 0x01234567) + fail = 1; + + /* Reset the EEPROM data go FFFF */ + (void) xge_hal_write_eeprom(hldev, 0x7FC, 0xFFFFFFFF, 3); + + /* Test Write Error at offset 0x80 */ + if (!xge_hal_write_eeprom(hldev, 0x080, 0, 3)) + fail = 1; + + /* Test Write Error at offset 0xfc */ + if (!xge_hal_write_eeprom(hldev, 0x0FC, 0, 3)) + fail = 1; + + /* Test Write Error at offset 0x100 */ + if (!xge_hal_write_eeprom(hldev, 0x100, 0, 3)) + fail = 1; + + /* Test Write Error at offset 4ec */ + if (!xge_hal_write_eeprom(hldev, 0x4EC, 0, 3)) + fail = 1; + + *data = fail; + return XGE_HAL_OK; +} + +/* + * xge_hal_bist_test - invokes the MemBist test of the card . + * @devh: HAL device handle. + * xge_nic structure. + * @data:variable that returns the result of each of the test conducted by + * the driver. + * + * This invokes the MemBist test of the card. We give around + * 2 secs time for the Test to complete. If it's still not complete + * within this peiod, we consider that the test failed. + * Return value: + * 0 on success and -1 on failure. + */ +xge_hal_status_e +xge_hal_bist_test(xge_hal_device_h devh, u64 *data) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + u8 bist = 0; + int cnt = 0; + xge_hal_status_e ret = XGE_HAL_FAIL; + + xge_os_pci_read8(hldev->pdev, hldev->cfgh, 0x0f, &bist); + bist |= 0x40; + xge_os_pci_write8(hldev->pdev, hldev->cfgh, 0x0f, bist); + + while (cnt < 20) { + xge_os_pci_read8(hldev->pdev, hldev->cfgh, 0x0f, &bist); + if (!(bist & 0x40)) { + *data = (bist & 0x0f); + ret = XGE_HAL_OK; + break; + } + xge_os_mdelay(100); + cnt++; + } + + return ret; +} + +/* + * xge_hal_link_test - verifies the link state of the nic + * @devh: HAL device handle. + * @data: variable that returns the result of each of the test conducted by + * the driver. + * + * Verify the link state of the NIC and updates the input + * argument 'data' appropriately. + * Return value: + * 0 on success. + */ +xge_hal_status_e +xge_hal_link_test(xge_hal_device_h devh, u64 *data) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->adapter_status); + if (val64 & XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT) + *data = 1; + + return XGE_HAL_OK; +} + + +/** + * xge_hal_getpause_data -Pause frame frame generation and reception. + * @devh: HAL device handle. + * @tx : A field to return the pause generation capability of the NIC. + * @rx : A field to return the pause reception capability of the NIC. + * + * Returns the Pause frame generation and reception capability of the NIC. + * Return value: + * void + */ +void xge_hal_getpause_data(xge_hal_device_h devh, int *tx, int *rx) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rmac_pause_cfg); + if (val64 & XGE_HAL_RMAC_PAUSE_GEN_EN) + *tx = 1; + if (val64 & XGE_HAL_RMAC_PAUSE_RCV_EN) + *rx = 1; +} + +/** + * xge_hal_setpause_data - set/reset pause frame generation. + * @devh: HAL device handle. + * @tx: A field that indicates the pause generation capability to be + * set on the NIC. + * @rx: A field that indicates the pause reception capability to be + * set on the NIC. + * + * It can be used to set or reset Pause frame generation or reception + * support of the NIC. + * Return value: + * int, returns 0 on Success + */ + +int xge_hal_setpause_data(xge_hal_device_h devh, int tx, int rx) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; + u64 val64; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rmac_pause_cfg); + if (tx) + val64 |= XGE_HAL_RMAC_PAUSE_GEN_EN; + else + val64 &= ~XGE_HAL_RMAC_PAUSE_GEN_EN; + if (rx) + val64 |= XGE_HAL_RMAC_PAUSE_RCV_EN; + else + val64 &= ~XGE_HAL_RMAC_PAUSE_RCV_EN; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->rmac_pause_cfg); + return 0; +} + +/** + * xge_hal_read_xfp_current_temp - + * @hldev: HAL device handle. + * + * This routine only gets the temperature for XFP modules. Also, updating of the + * NVRAM can sometimes fail and so the reading we might get may not be uptodate. + */ +u32 xge_hal_read_xfp_current_temp(xge_hal_device_h hldev) +{ + u16 val_1, val_2, i = 0; + u32 actual; + + /* First update the NVRAM table of XFP. */ + + (void) xge_hal_mdio_write(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, 0x8000, 0x3); + + + /* Now wait for the transfer to complete */ + do + { + xge_os_mdelay( 50 ); // wait 50 milliseonds + + val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, 0x8000); + + if ( i++ > 10 ) + { + // waited 500 ms which should be plenty of time. + break; + } + }while (( val_1 & 0x000C ) != 0x0004); + + /* Now NVRAM table of XFP should be updated, so read the temp */ + val_1 = (u8) xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, 0x8067); + val_2 = (u8) xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, 0x8068); + + actual = ((val_1 << 8) | val_2); + + if (actual >= 32768) + actual = actual- 65536; + actual = actual/256; + + return actual; +} + +/** + * __hal_chk_xpak_counter - check the Xpak error count and log the msg. + * @hldev: pointer to xge_hal_device_t structure + * @type: xpak stats error type + * @value: xpak stats value + * + * It is used to log the error message based on the xpak stats value + * Return value: + * None + */ + +void __hal_chk_xpak_counter(xge_hal_device_t *hldev, int type, u32 value) +{ + /* + * If the value is high for three consecutive cylce, + * log a error message + */ + if(value == 3) + { + switch(type) + { + case 1: + hldev->stats.sw_dev_err_stats.xpak_counter. + excess_temp = 0; + + /* + * Notify the ULD on Excess Xpak temperature alarm msg + */ + if (g_xge_hal_driver->uld_callbacks.xpak_alarm_log) { + g_xge_hal_driver->uld_callbacks.xpak_alarm_log( + hldev->upper_layer_info, + XGE_HAL_XPAK_ALARM_EXCESS_TEMP); + } + break; + case 2: + hldev->stats.sw_dev_err_stats.xpak_counter. + excess_bias_current = 0; + + /* + * Notify the ULD on Excess xpak bias current alarm msg + */ + if (g_xge_hal_driver->uld_callbacks.xpak_alarm_log) { + g_xge_hal_driver->uld_callbacks.xpak_alarm_log( + hldev->upper_layer_info, + XGE_HAL_XPAK_ALARM_EXCESS_BIAS_CURRENT); + } + break; + case 3: + hldev->stats.sw_dev_err_stats.xpak_counter. + excess_laser_output = 0; + + /* + * Notify the ULD on Excess Xpak Laser o/p power + * alarm msg + */ + if (g_xge_hal_driver->uld_callbacks.xpak_alarm_log) { + g_xge_hal_driver->uld_callbacks.xpak_alarm_log( + hldev->upper_layer_info, + XGE_HAL_XPAK_ALARM_EXCESS_LASER_OUTPUT); + } + break; + default: + xge_debug_osdep(XGE_TRACE, "Incorrect XPAK Alarm " + "type "); + } + } + +} + +/** + * __hal_updt_stats_xpak - update the Xpak error count. + * @hldev: pointer to xge_hal_device_t structure + * + * It is used to update the xpak stats value + * Return value: + * None + */ +void __hal_updt_stats_xpak(xge_hal_device_t *hldev) +{ + u16 val_1; + u64 addr; + + /* Check the communication with the MDIO slave */ + addr = 0x0000; + val_1 = 0x0; + val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr); + if((val_1 == 0xFFFF) || (val_1 == 0x0000)) + { + xge_debug_osdep(XGE_TRACE, "ERR: MDIO slave access failed - " + "Returned %x", val_1); + return; + } + + /* Check for the expected value of 2040 at PMA address 0x0000 */ + if(val_1 != 0x2040) + { + xge_debug_osdep(XGE_TRACE, "Incorrect value at PMA address 0x0000 - "); + xge_debug_osdep(XGE_TRACE, "Returned: %llx- Expected: 0x2040", + (unsigned long long)(unsigned long)val_1); + return; + } + + /* Loading the DOM register to MDIO register */ + addr = 0xA100; + (void) xge_hal_mdio_write(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr, 0x0); + val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr); + + /* + * Reading the Alarm flags + */ + addr = 0xA070; + val_1 = 0x0; + val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr); + if(CHECKBIT(val_1, 0x7)) + { + hldev->stats.sw_dev_err_stats.stats_xpak. + alarm_transceiver_temp_high++; + hldev->stats.sw_dev_err_stats.xpak_counter.excess_temp++; + __hal_chk_xpak_counter(hldev, 0x1, + hldev->stats.sw_dev_err_stats.xpak_counter.excess_temp); + } else { + hldev->stats.sw_dev_err_stats.xpak_counter.excess_temp = 0; + } + if(CHECKBIT(val_1, 0x6)) + hldev->stats.sw_dev_err_stats.stats_xpak. + alarm_transceiver_temp_low++; + + if(CHECKBIT(val_1, 0x3)) + { + hldev->stats.sw_dev_err_stats.stats_xpak. + alarm_laser_bias_current_high++; + hldev->stats.sw_dev_err_stats.xpak_counter. + excess_bias_current++; + __hal_chk_xpak_counter(hldev, 0x2, + hldev->stats.sw_dev_err_stats.xpak_counter. + excess_bias_current); + } else { + hldev->stats.sw_dev_err_stats.xpak_counter. + excess_bias_current = 0; + } + if(CHECKBIT(val_1, 0x2)) + hldev->stats.sw_dev_err_stats.stats_xpak. + alarm_laser_bias_current_low++; + + if(CHECKBIT(val_1, 0x1)) + { + hldev->stats.sw_dev_err_stats.stats_xpak. + alarm_laser_output_power_high++; + hldev->stats.sw_dev_err_stats.xpak_counter. + excess_laser_output++; + __hal_chk_xpak_counter(hldev, 0x3, + hldev->stats.sw_dev_err_stats.xpak_counter. + excess_laser_output); + } else { + hldev->stats.sw_dev_err_stats.xpak_counter. + excess_laser_output = 0; + } + if(CHECKBIT(val_1, 0x0)) + hldev->stats.sw_dev_err_stats.stats_xpak. + alarm_laser_output_power_low++; + + /* + * Reading the warning flags + */ + addr = 0xA074; + val_1 = 0x0; + val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr); + if(CHECKBIT(val_1, 0x7)) + hldev->stats.sw_dev_err_stats.stats_xpak. + warn_transceiver_temp_high++; + if(CHECKBIT(val_1, 0x6)) + hldev->stats.sw_dev_err_stats.stats_xpak. + warn_transceiver_temp_low++; + if(CHECKBIT(val_1, 0x3)) + hldev->stats.sw_dev_err_stats.stats_xpak. + warn_laser_bias_current_high++; + if(CHECKBIT(val_1, 0x2)) + hldev->stats.sw_dev_err_stats.stats_xpak. + warn_laser_bias_current_low++; + if(CHECKBIT(val_1, 0x1)) + hldev->stats.sw_dev_err_stats.stats_xpak. + warn_laser_output_power_high++; + if(CHECKBIT(val_1, 0x0)) + hldev->stats.sw_dev_err_stats.stats_xpak. + warn_laser_output_power_low++; +} diff --git a/sys/dev/nxge/xgehal/xgehal-mgmtaux.c b/sys/dev/nxge/xgehal/xgehal-mgmtaux.c new file mode 100644 index 0000000..e2f0046 --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-mgmtaux.c @@ -0,0 +1,1731 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-mgmtaux.c + * + * Description: Xframe-family management auxiliary API implementation + * + * Created: 1 September 2004 + */ + +#include <dev/nxge/include/xgehal-mgmt.h> +#include <dev/nxge/include/xgehal-driver.h> +#include <dev/nxge/include/xgehal-device.h> + +#ifdef XGE_OS_HAS_SNPRINTF +#define __hal_aux_snprintf(retbuf, bufsize, fmt, key, value, retsize) \ + if (bufsize <= 0) return XGE_HAL_ERR_OUT_OF_SPACE; \ + retsize = xge_os_snprintf(retbuf, bufsize, fmt, key, \ + XGE_HAL_AUX_SEPA, value); \ + if (retsize < 0 || retsize >= bufsize) return XGE_HAL_ERR_OUT_OF_SPACE; +#else +#define __hal_aux_snprintf(retbuf, bufsize, fmt, key, value, retsize) \ + if (bufsize <= 0) return XGE_HAL_ERR_OUT_OF_SPACE; \ + retsize = xge_os_sprintf(retbuf, fmt, key, XGE_HAL_AUX_SEPA, value); \ + xge_assert(retsize < bufsize); \ + if (retsize < 0 || retsize >= bufsize) \ + return XGE_HAL_ERR_OUT_OF_SPACE; +#endif + +#define __HAL_AUX_ENTRY_DECLARE(size, buf) \ + int entrysize = 0, leftsize = size; \ + char *ptr = buf; + +#define __HAL_AUX_ENTRY(key, value, fmt) \ + ptr += entrysize; leftsize -= entrysize; \ + __hal_aux_snprintf(ptr, leftsize, "%s%c"fmt"\n", key, value, entrysize) + +#define __HAL_AUX_ENTRY_END(bufsize, retsize) \ + leftsize -= entrysize; \ + *retsize = bufsize - leftsize; + +#define __hal_aux_pci_link_info(name, index, var) { \ + __HAL_AUX_ENTRY(name, \ + (unsigned long long)pcim.link_info[index].var, "%llu") \ + } + +#define __hal_aux_pci_aggr_info(name, index, var) { \ + __HAL_AUX_ENTRY(name, \ + (unsigned long long)pcim.aggr_info[index].var, "%llu") \ + } + +/** + * xge_hal_aux_bar0_read - Read and format Xframe BAR0 register. + * @devh: HAL device handle. + * @offset: Register offset in the BAR0 space. + * @bufsize: Buffer size. + * @retbuf: Buffer pointer. + * @retsize: Size of the result. Cannot be greater than @bufsize. + * + * Read Xframe register from BAR0 space. The result is formatted as an ascii string. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_OUT_OF_SPACE - Buffer size is very small. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_INVALID_OFFSET - Register offset in the BAR space is not + * valid. + * XGE_HAL_ERR_INVALID_BAR_ID - BAR id is not valid. + * + * See also: xge_hal_mgmt_reg_read(). + */ +xge_hal_status_e xge_hal_aux_bar0_read(xge_hal_device_h devh, + unsigned int offset, int bufsize, char *retbuf, + int *retsize) +{ + xge_hal_status_e status; + u64 retval; + + status = xge_hal_mgmt_reg_read(devh, 0, offset, &retval); + if (status != XGE_HAL_OK) { + return status; + } + + if (bufsize < XGE_OS_SPRINTF_STRLEN) { + return XGE_HAL_ERR_OUT_OF_SPACE; + } + + *retsize = xge_os_sprintf(retbuf, "0x%04X%c0x%08X%08X\n", offset, + XGE_HAL_AUX_SEPA, (u32)(retval>>32), (u32)retval); + + return XGE_HAL_OK; +} + +/** + * xge_hal_aux_bar1_read - Read and format Xframe BAR1 register. + * @devh: HAL device handle. + * @offset: Register offset in the BAR1 space. + * @bufsize: Buffer size. + * @retbuf: Buffer pointer. + * @retsize: Size of the result. Cannot be greater than @bufsize. + * + * Read Xframe register from BAR1 space. The result is formatted as ascii string. + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_OUT_OF_SPACE - Buffer size is very small. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_INVALID_OFFSET - Register offset in the BAR space is not + * valid. + * XGE_HAL_ERR_INVALID_BAR_ID - BAR id is not valid. + * + * See also: xge_hal_mgmt_reg_read(). + */ +xge_hal_status_e xge_hal_aux_bar1_read(xge_hal_device_h devh, + unsigned int offset, int bufsize, char *retbuf, + int *retsize) +{ + xge_hal_status_e status; + u64 retval; + + status = xge_hal_mgmt_reg_read(devh, 1, offset, &retval); + if (status != XGE_HAL_OK) { + return status; + } + + if (bufsize < XGE_OS_SPRINTF_STRLEN) { + return XGE_HAL_ERR_OUT_OF_SPACE; + } + + *retsize = xge_os_sprintf(retbuf, "0x%04X%c0x%08X%08X\n", + offset, + XGE_HAL_AUX_SEPA, (u32)(retval>>32), (u32)retval); + + return XGE_HAL_OK; +} + +/** + * xge_hal_aux_bar0_write - Write BAR0 register. + * @devh: HAL device handle. + * @offset: Register offset in the BAR0 space. + * @value: Regsister value (to write). + * + * Write BAR0 register. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_INVALID_OFFSET - Register offset in the BAR space is not + * valid. + * XGE_HAL_ERR_INVALID_BAR_ID - BAR id is not valid. + * + * See also: xge_hal_mgmt_reg_write(). + */ +xge_hal_status_e xge_hal_aux_bar0_write(xge_hal_device_h devh, + unsigned int offset, u64 value) +{ + xge_hal_status_e status; + + status = xge_hal_mgmt_reg_write(devh, 0, offset, value); + if (status != XGE_HAL_OK) { + return status; + } + + return XGE_HAL_OK; +} + +/** + * xge_hal_aux_about_read - Retrieve and format about info. + * @devh: HAL device handle. + * @bufsize: Buffer size. + * @retbuf: Buffer pointer. + * @retsize: Size of the result. Cannot be greater than @bufsize. + * + * Retrieve about info (using xge_hal_mgmt_about()) and sprintf it + * into the provided @retbuf. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * XGE_HAL_FAIL - Failed to retrieve the information. + * + * See also: xge_hal_mgmt_about(), xge_hal_aux_device_dump(). + */ +xge_hal_status_e xge_hal_aux_about_read(xge_hal_device_h devh, int bufsize, + char *retbuf, int *retsize) +{ + xge_hal_status_e status; + xge_hal_mgmt_about_info_t about_info; + __HAL_AUX_ENTRY_DECLARE(bufsize, retbuf); + + status = xge_hal_mgmt_about(devh, &about_info, + sizeof(xge_hal_mgmt_about_info_t)); + if (status != XGE_HAL_OK) { + return status; + } + + __HAL_AUX_ENTRY("vendor", about_info.vendor, "0x%x"); + __HAL_AUX_ENTRY("device", about_info.device, "0x%x"); + __HAL_AUX_ENTRY("subsys_vendor", about_info.subsys_vendor, "0x%x"); + __HAL_AUX_ENTRY("subsys_device", about_info.subsys_device, "0x%x"); + __HAL_AUX_ENTRY("board_rev", about_info.board_rev, "0x%x"); + __HAL_AUX_ENTRY("vendor_name", about_info.vendor_name, "%s"); + __HAL_AUX_ENTRY("chip_name", about_info.chip_name, "%s"); + __HAL_AUX_ENTRY("media", about_info.media, "%s"); + __HAL_AUX_ENTRY("hal_major", about_info.hal_major, "%s"); + __HAL_AUX_ENTRY("hal_minor", about_info.hal_minor, "%s"); + __HAL_AUX_ENTRY("hal_fix", about_info.hal_fix, "%s"); + __HAL_AUX_ENTRY("hal_build", about_info.hal_build, "%s"); + __HAL_AUX_ENTRY("ll_major", about_info.ll_major, "%s"); + __HAL_AUX_ENTRY("ll_minor", about_info.ll_minor, "%s"); + __HAL_AUX_ENTRY("ll_fix", about_info.ll_fix, "%s"); + __HAL_AUX_ENTRY("ll_build", about_info.ll_build, "%s"); + + __HAL_AUX_ENTRY("transponder_temperature", + about_info.transponder_temperature, "%d C"); + + __HAL_AUX_ENTRY_END(bufsize, retsize); + + return XGE_HAL_OK; +} + +/** + * xge_hal_aux_stats_tmac_read - Read TMAC hardware statistics. + * @devh: HAL device handle. + * @bufsize: Buffer size. + * @retbuf: Buffer pointer. + * @retsize: Size of the result. Cannot be greater than @bufsize. + * + * Read TMAC hardware statistics. This is a subset of stats counters + * from xge_hal_stats_hw_info_t{}. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + * See also: xge_hal_mgmt_hw_stats{}, xge_hal_stats_hw_info_t{}, + * xge_hal_aux_stats_pci_read(), + * xge_hal_aux_device_dump(). + */ +xge_hal_status_e xge_hal_aux_stats_tmac_read(xge_hal_device_h devh, int bufsize, + char *retbuf, int *retsize) +{ + xge_hal_status_e status; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + + __HAL_AUX_ENTRY_DECLARE(bufsize, retbuf); + + if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) { + xge_hal_mgmt_hw_stats_t hw; + + status = xge_hal_mgmt_hw_stats(devh, &hw, + sizeof(xge_hal_mgmt_hw_stats_t)); + if (status != XGE_HAL_OK) { + return status; + } + + __HAL_AUX_ENTRY("tmac_data_octets", hw.tmac_data_octets, "%u"); + __HAL_AUX_ENTRY("tmac_frms", hw.tmac_frms, "%u"); + __HAL_AUX_ENTRY("tmac_drop_frms", (unsigned long long) + hw.tmac_drop_frms, "%llu"); + __HAL_AUX_ENTRY("tmac_bcst_frms", hw.tmac_bcst_frms, "%u"); + __HAL_AUX_ENTRY("tmac_mcst_frms", hw.tmac_mcst_frms, "%u"); + __HAL_AUX_ENTRY("tmac_pause_ctrl_frms", (unsigned long long) + hw.tmac_pause_ctrl_frms, "%llu"); + __HAL_AUX_ENTRY("tmac_ucst_frms", hw.tmac_ucst_frms, "%u"); + __HAL_AUX_ENTRY("tmac_ttl_octets", hw.tmac_ttl_octets, "%u"); + __HAL_AUX_ENTRY("tmac_any_err_frms", hw.tmac_any_err_frms, "%u"); + __HAL_AUX_ENTRY("tmac_nucst_frms", hw.tmac_nucst_frms, "%u"); + __HAL_AUX_ENTRY("tmac_ttl_less_fb_octets", (unsigned long long) + hw.tmac_ttl_less_fb_octets, "%llu"); + __HAL_AUX_ENTRY("tmac_vld_ip_octets", (unsigned long long) + hw.tmac_vld_ip_octets, "%llu"); + __HAL_AUX_ENTRY("tmac_drop_ip", hw.tmac_drop_ip, "%u"); + __HAL_AUX_ENTRY("tmac_vld_ip", hw.tmac_vld_ip, "%u"); + __HAL_AUX_ENTRY("tmac_rst_tcp", hw.tmac_rst_tcp, "%u"); + __HAL_AUX_ENTRY("tmac_icmp", hw.tmac_icmp, "%u"); + __HAL_AUX_ENTRY("tmac_tcp", (unsigned long long) + hw.tmac_tcp, "%llu"); + __HAL_AUX_ENTRY("reserved_0", hw.reserved_0, "%u"); + __HAL_AUX_ENTRY("tmac_udp", hw.tmac_udp, "%u"); + } else { + int i; + xge_hal_mgmt_pcim_stats_t pcim; + status = xge_hal_mgmt_pcim_stats(devh, &pcim, + sizeof(xge_hal_mgmt_pcim_stats_t)); + if (status != XGE_HAL_OK) { + return status; + } + + for (i = 0; i < XGE_HAL_MAC_LINKS; i++) { + __hal_aux_pci_link_info("tx_frms", i, + tx_frms); + __hal_aux_pci_link_info("tx_ttl_eth_octets", + i, tx_ttl_eth_octets ); + __hal_aux_pci_link_info("tx_data_octets", i, + tx_data_octets); + __hal_aux_pci_link_info("tx_mcst_frms", i, + tx_mcst_frms); + __hal_aux_pci_link_info("tx_bcst_frms", i, + tx_bcst_frms); + __hal_aux_pci_link_info("tx_ucst_frms", i, + tx_ucst_frms); + __hal_aux_pci_link_info("tx_tagged_frms", i, + tx_tagged_frms); + __hal_aux_pci_link_info("tx_vld_ip", i, + tx_vld_ip); + __hal_aux_pci_link_info("tx_vld_ip_octets", i, + tx_vld_ip_octets); + __hal_aux_pci_link_info("tx_icmp", i, + tx_icmp); + __hal_aux_pci_link_info("tx_tcp", i, + tx_tcp); + __hal_aux_pci_link_info("tx_rst_tcp", i, + tx_rst_tcp); + __hal_aux_pci_link_info("tx_udp", i, + tx_udp); + __hal_aux_pci_link_info("tx_unknown_protocol", i, + tx_unknown_protocol); + __hal_aux_pci_link_info("tx_parse_error", i, + tx_parse_error); + __hal_aux_pci_link_info("tx_pause_ctrl_frms", i, + tx_pause_ctrl_frms); + __hal_aux_pci_link_info("tx_lacpdu_frms", i, + tx_lacpdu_frms); + __hal_aux_pci_link_info("tx_marker_pdu_frms", i, + tx_marker_pdu_frms); + __hal_aux_pci_link_info("tx_marker_resp_pdu_frms", i, + tx_marker_resp_pdu_frms); + __hal_aux_pci_link_info("tx_drop_ip", i, + tx_drop_ip); + __hal_aux_pci_link_info("tx_xgmii_char1_match", i, + tx_xgmii_char1_match); + __hal_aux_pci_link_info("tx_xgmii_char2_match", i, + tx_xgmii_char2_match); + __hal_aux_pci_link_info("tx_xgmii_column1_match", i, + tx_xgmii_column1_match); + __hal_aux_pci_link_info("tx_xgmii_column2_match", i, + tx_xgmii_column2_match); + __hal_aux_pci_link_info("tx_drop_frms", i, + tx_drop_frms); + __hal_aux_pci_link_info("tx_any_err_frms", i, + tx_any_err_frms); + } + + for (i = 0; i < XGE_HAL_MAC_AGGREGATORS; i++) { + __hal_aux_pci_aggr_info("tx_frms", i, tx_frms); + __hal_aux_pci_aggr_info("tx_mcst_frms", i, + tx_mcst_frms); + __hal_aux_pci_aggr_info("tx_bcst_frms", i, + tx_bcst_frms); + __hal_aux_pci_aggr_info("tx_discarded_frms", i, + tx_discarded_frms); + __hal_aux_pci_aggr_info("tx_errored_frms", i, + tx_errored_frms); + } + } + + __HAL_AUX_ENTRY_END(bufsize, retsize); + + return XGE_HAL_OK; +} + +/** + * xge_hal_aux_stats_rmac_read - Read RMAC hardware statistics. + * @devh: HAL device handle. + * @bufsize: Buffer size. + * @retbuf: Buffer pointer. + * @retsize: Size of the result. Cannot be greater than @bufsize. + * + * Read RMAC hardware statistics. This is a subset of stats counters + * from xge_hal_stats_hw_info_t{}. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + * See also: xge_hal_mgmt_hw_stats{}, xge_hal_stats_hw_info_t{}, + * xge_hal_aux_stats_pci_read(), xge_hal_aux_stats_tmac_read(), + * xge_hal_aux_device_dump(). + */ +xge_hal_status_e xge_hal_aux_stats_rmac_read(xge_hal_device_h devh, int bufsize, + char *retbuf, int *retsize) +{ + xge_hal_status_e status; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + + __HAL_AUX_ENTRY_DECLARE(bufsize, retbuf); + + if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) { + xge_hal_mgmt_hw_stats_t hw; + + status = xge_hal_mgmt_hw_stats(devh, &hw, + sizeof(xge_hal_mgmt_hw_stats_t)); + if (status != XGE_HAL_OK) { + return status; + } + + __HAL_AUX_ENTRY("rmac_data_octets", hw.rmac_data_octets, "%u"); + __HAL_AUX_ENTRY("rmac_vld_frms", hw.rmac_vld_frms, "%u"); + __HAL_AUX_ENTRY("rmac_fcs_err_frms", (unsigned long long) + hw.rmac_fcs_err_frms, "%llu"); + __HAL_AUX_ENTRY("mac_drop_frms", (unsigned long long) + hw.rmac_drop_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_vld_bcst_frms", hw.rmac_vld_bcst_frms, + "%u"); + __HAL_AUX_ENTRY("rmac_vld_mcst_frms", hw.rmac_vld_mcst_frms, + "%u"); + __HAL_AUX_ENTRY("rmac_out_rng_len_err_frms", + hw.rmac_out_rng_len_err_frms, "%u"); + __HAL_AUX_ENTRY("rmac_in_rng_len_err_frms", + hw.rmac_in_rng_len_err_frms, "%u"); + __HAL_AUX_ENTRY("rmac_long_frms", (unsigned long long) + hw.rmac_long_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_pause_ctrl_frms", (unsigned long long) + hw.rmac_pause_ctrl_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_unsup_ctrl_frms", (unsigned long long) + hw.rmac_unsup_ctrl_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_accepted_ucst_frms", + hw.rmac_accepted_ucst_frms, "%u"); + __HAL_AUX_ENTRY("rmac_ttl_octets", hw.rmac_ttl_octets, "%u"); + __HAL_AUX_ENTRY("rmac_discarded_frms", hw.rmac_discarded_frms, + "%u"); + __HAL_AUX_ENTRY("rmac_accepted_nucst_frms", + hw.rmac_accepted_nucst_frms, "%u"); + __HAL_AUX_ENTRY("reserved_1", hw.reserved_1, "%u"); + __HAL_AUX_ENTRY("rmac_drop_events", hw.rmac_drop_events, "%u"); + __HAL_AUX_ENTRY("rmac_ttl_less_fb_octets", (unsigned long long) + hw.rmac_ttl_less_fb_octets, "%llu"); + __HAL_AUX_ENTRY("rmac_ttl_frms", (unsigned long long) + hw.rmac_ttl_frms, "%llu"); + __HAL_AUX_ENTRY("reserved_2", (unsigned long long) + hw.reserved_2, "%llu"); + __HAL_AUX_ENTRY("rmac_usized_frms", hw.rmac_usized_frms, "%u"); + __HAL_AUX_ENTRY("reserved_3", hw.reserved_3, "%u"); + __HAL_AUX_ENTRY("rmac_frag_frms", hw.rmac_frag_frms, "%u"); + __HAL_AUX_ENTRY("rmac_osized_frms", hw.rmac_osized_frms, "%u"); + __HAL_AUX_ENTRY("reserved_4", hw.reserved_4, "%u"); + __HAL_AUX_ENTRY("rmac_jabber_frms", hw.rmac_jabber_frms, "%u"); + __HAL_AUX_ENTRY("rmac_ttl_64_frms", (unsigned long long) + hw.rmac_ttl_64_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_ttl_65_127_frms", (unsigned long long) + hw.rmac_ttl_65_127_frms, "%llu"); + __HAL_AUX_ENTRY("reserved_5", (unsigned long long) + hw.reserved_5, "%llu"); + __HAL_AUX_ENTRY("rmac_ttl_128_255_frms", (unsigned long long) + hw.rmac_ttl_128_255_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_ttl_256_511_frms", (unsigned long long) + hw.rmac_ttl_256_511_frms, "%llu"); + __HAL_AUX_ENTRY("reserved_6", (unsigned long long) + hw.reserved_6, "%llu"); + __HAL_AUX_ENTRY("rmac_ttl_512_1023_frms", (unsigned long long) + hw.rmac_ttl_512_1023_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_ttl_1024_1518_frms", (unsigned long long) + hw.rmac_ttl_1024_1518_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_ip", hw.rmac_ip, "%u"); + __HAL_AUX_ENTRY("reserved_7", hw.reserved_7, "%u"); + __HAL_AUX_ENTRY("rmac_ip_octets", (unsigned long long) + hw.rmac_ip_octets, "%llu"); + __HAL_AUX_ENTRY("rmac_drop_ip", hw.rmac_drop_ip, "%u"); + __HAL_AUX_ENTRY("rmac_hdr_err_ip", hw.rmac_hdr_err_ip, "%u"); + __HAL_AUX_ENTRY("reserved_8", hw.reserved_8, "%u"); + __HAL_AUX_ENTRY("rmac_icmp", hw.rmac_icmp, "%u"); + __HAL_AUX_ENTRY("rmac_tcp", (unsigned long long) + hw.rmac_tcp, "%llu"); + __HAL_AUX_ENTRY("rmac_err_drp_udp", hw.rmac_err_drp_udp, "%u"); + __HAL_AUX_ENTRY("rmac_udp", hw.rmac_udp, "%u"); + __HAL_AUX_ENTRY("rmac_xgmii_err_sym", (unsigned long long) + hw.rmac_xgmii_err_sym, "%llu"); + __HAL_AUX_ENTRY("rmac_frms_q0", (unsigned long long) + hw.rmac_frms_q0, "%llu"); + __HAL_AUX_ENTRY("rmac_frms_q1", (unsigned long long) + hw.rmac_frms_q1, "%llu"); + __HAL_AUX_ENTRY("rmac_frms_q2", (unsigned long long) + hw.rmac_frms_q2, "%llu"); + __HAL_AUX_ENTRY("rmac_frms_q3", (unsigned long long) + hw.rmac_frms_q3, "%llu"); + __HAL_AUX_ENTRY("rmac_frms_q4", (unsigned long long) + hw.rmac_frms_q4, "%llu"); + __HAL_AUX_ENTRY("rmac_frms_q5", (unsigned long long) + hw.rmac_frms_q5, "%llu"); + __HAL_AUX_ENTRY("rmac_frms_q6", (unsigned long long) + hw.rmac_frms_q6, "%llu"); + __HAL_AUX_ENTRY("rmac_frms_q7", (unsigned long long) + hw.rmac_frms_q7, "%llu"); + __HAL_AUX_ENTRY("rmac_full_q3", hw.rmac_full_q3, "%d"); + __HAL_AUX_ENTRY("rmac_full_q2", hw.rmac_full_q2, "%d"); + __HAL_AUX_ENTRY("rmac_full_q1", hw.rmac_full_q1, "%d"); + __HAL_AUX_ENTRY("rmac_full_q0", hw.rmac_full_q0, "%d"); + __HAL_AUX_ENTRY("rmac_full_q7", hw.rmac_full_q7, "%d"); + __HAL_AUX_ENTRY("rmac_full_q6", hw.rmac_full_q6, "%d"); + __HAL_AUX_ENTRY("rmac_full_q5", hw.rmac_full_q5, "%d"); + __HAL_AUX_ENTRY("rmac_full_q4", hw.rmac_full_q4, "%d"); + __HAL_AUX_ENTRY("reserved_9", hw.reserved_9, "%u"); + __HAL_AUX_ENTRY("rmac_pause_cnt", hw.rmac_pause_cnt, "%u"); + __HAL_AUX_ENTRY("rmac_xgmii_data_err_cnt", (unsigned long long) + hw.rmac_xgmii_data_err_cnt, "%llu"); + __HAL_AUX_ENTRY("rmac_xgmii_ctrl_err_cnt", (unsigned long long) + hw.rmac_xgmii_ctrl_err_cnt, "%llu"); + __HAL_AUX_ENTRY("rmac_err_tcp", hw.rmac_err_tcp, "%u"); + __HAL_AUX_ENTRY("rmac_accepted_ip", hw.rmac_accepted_ip, "%u"); + } else { + int i; + xge_hal_mgmt_pcim_stats_t pcim; + status = xge_hal_mgmt_pcim_stats(devh, &pcim, + sizeof(xge_hal_mgmt_pcim_stats_t)); + if (status != XGE_HAL_OK) { + return status; + } + for (i = 0; i < XGE_HAL_MAC_LINKS; i++) { + __hal_aux_pci_link_info("rx_ttl_frms", i, + rx_ttl_frms); + __hal_aux_pci_link_info("rx_vld_frms", i, + rx_vld_frms); + __hal_aux_pci_link_info("rx_offld_frms", i, + rx_offld_frms); + __hal_aux_pci_link_info("rx_ttl_eth_octets", i, + rx_ttl_eth_octets); + __hal_aux_pci_link_info("rx_data_octets", i, + rx_data_octets); + __hal_aux_pci_link_info("rx_offld_octets", i, + rx_offld_octets); + __hal_aux_pci_link_info("rx_vld_mcst_frms", i, + rx_vld_mcst_frms); + __hal_aux_pci_link_info("rx_vld_bcst_frms", i, + rx_vld_bcst_frms); + __hal_aux_pci_link_info("rx_accepted_ucst_frms", i, + rx_accepted_ucst_frms); + __hal_aux_pci_link_info("rx_accepted_nucst_frms", i, + rx_accepted_nucst_frms); + __hal_aux_pci_link_info("rx_tagged_frms", i, + rx_tagged_frms); + __hal_aux_pci_link_info("rx_long_frms", i, + rx_long_frms); + __hal_aux_pci_link_info("rx_usized_frms", i, + rx_usized_frms); + __hal_aux_pci_link_info("rx_osized_frms", i, + rx_osized_frms); + __hal_aux_pci_link_info("rx_frag_frms", i, + rx_frag_frms); + __hal_aux_pci_link_info("rx_jabber_frms", i, + rx_jabber_frms); + __hal_aux_pci_link_info("rx_ttl_64_frms", i, + rx_ttl_64_frms); + __hal_aux_pci_link_info("rx_ttl_65_127_frms", i, + rx_ttl_65_127_frms); + __hal_aux_pci_link_info("rx_ttl_128_255_frms", i, + rx_ttl_128_255_frms); + __hal_aux_pci_link_info("rx_ttl_256_511_frms", i, + rx_ttl_256_511_frms); + __hal_aux_pci_link_info("rx_ttl_512_1023_frms", i, + rx_ttl_512_1023_frms); + __hal_aux_pci_link_info("rx_ttl_1024_1518_frms", i, + rx_ttl_1024_1518_frms); + __hal_aux_pci_link_info("rx_ttl_1519_4095_frms", i, + rx_ttl_1519_4095_frms); + __hal_aux_pci_link_info("rx_ttl_40956_8191_frms", i, + rx_ttl_40956_8191_frms); + __hal_aux_pci_link_info("rx_ttl_8192_max_frms", i, + rx_ttl_8192_max_frms); + __hal_aux_pci_link_info("rx_ttl_gt_max_frms", i, + rx_ttl_gt_max_frms); + __hal_aux_pci_link_info("rx_ip", i, + rx_ip); + __hal_aux_pci_link_info("rx_ip_octets", i, + rx_ip_octets); + + __hal_aux_pci_link_info("rx_hdr_err_ip", i, + rx_hdr_err_ip); + + __hal_aux_pci_link_info("rx_icmp", i, + rx_icmp); + __hal_aux_pci_link_info("rx_tcp", i, + rx_tcp); + __hal_aux_pci_link_info("rx_udp", i, + rx_udp); + __hal_aux_pci_link_info("rx_err_tcp", i, + rx_err_tcp); + __hal_aux_pci_link_info("rx_pause_cnt", i, + rx_pause_cnt); + __hal_aux_pci_link_info("rx_pause_ctrl_frms", i, + rx_pause_ctrl_frms); + __hal_aux_pci_link_info("rx_unsup_ctrl_frms", i, + rx_pause_cnt); + __hal_aux_pci_link_info("rx_in_rng_len_err_frms", i, + rx_in_rng_len_err_frms); + __hal_aux_pci_link_info("rx_out_rng_len_err_frms", i, + rx_out_rng_len_err_frms); + __hal_aux_pci_link_info("rx_drop_frms", i, + rx_drop_frms); + __hal_aux_pci_link_info("rx_discarded_frms", i, + rx_discarded_frms); + __hal_aux_pci_link_info("rx_drop_ip", i, + rx_drop_ip); + __hal_aux_pci_link_info("rx_err_drp_udp", i, + rx_err_drp_udp); + __hal_aux_pci_link_info("rx_lacpdu_frms", i, + rx_lacpdu_frms); + __hal_aux_pci_link_info("rx_marker_pdu_frms", i, + rx_marker_pdu_frms); + __hal_aux_pci_link_info("rx_marker_resp_pdu_frms", i, + rx_marker_resp_pdu_frms); + __hal_aux_pci_link_info("rx_unknown_pdu_frms", i, + rx_unknown_pdu_frms); + __hal_aux_pci_link_info("rx_illegal_pdu_frms", i, + rx_illegal_pdu_frms); + __hal_aux_pci_link_info("rx_fcs_discard", i, + rx_fcs_discard); + __hal_aux_pci_link_info("rx_len_discard", i, + rx_len_discard); + __hal_aux_pci_link_info("rx_pf_discard", i, + rx_pf_discard); + __hal_aux_pci_link_info("rx_trash_discard", i, + rx_trash_discard); + __hal_aux_pci_link_info("rx_rts_discard", i, + rx_trash_discard); + __hal_aux_pci_link_info("rx_wol_discard", i, + rx_wol_discard); + __hal_aux_pci_link_info("rx_red_discard", i, + rx_red_discard); + __hal_aux_pci_link_info("rx_ingm_full_discard", i, + rx_ingm_full_discard); + __hal_aux_pci_link_info("rx_xgmii_data_err_cnt", i, + rx_xgmii_data_err_cnt); + __hal_aux_pci_link_info("rx_xgmii_ctrl_err_cnt", i, + rx_xgmii_ctrl_err_cnt); + __hal_aux_pci_link_info("rx_xgmii_err_sym", i, + rx_xgmii_err_sym); + __hal_aux_pci_link_info("rx_xgmii_char1_match", i, + rx_xgmii_char1_match); + __hal_aux_pci_link_info("rx_xgmii_char2_match", i, + rx_xgmii_char2_match); + __hal_aux_pci_link_info("rx_xgmii_column1_match", i, + rx_xgmii_column1_match); + __hal_aux_pci_link_info("rx_xgmii_column2_match", i, + rx_xgmii_column2_match); + __hal_aux_pci_link_info("rx_local_fault", i, + rx_local_fault); + __hal_aux_pci_link_info("rx_remote_fault", i, + rx_remote_fault); + __hal_aux_pci_link_info("rx_queue_full", i, + rx_queue_full); + } + for (i = 0; i < XGE_HAL_MAC_AGGREGATORS; i++) { + __hal_aux_pci_aggr_info("rx_frms", i, rx_frms); + __hal_aux_pci_link_info("rx_data_octets", i, + rx_data_octets); + __hal_aux_pci_aggr_info("rx_mcst_frms", i, + rx_mcst_frms); + __hal_aux_pci_aggr_info("rx_bcst_frms", i, + rx_bcst_frms); + __hal_aux_pci_aggr_info("rx_discarded_frms", i, + rx_discarded_frms); + __hal_aux_pci_aggr_info("rx_errored_frms", i, + rx_errored_frms); + __hal_aux_pci_aggr_info("rx_unknown_protocol_frms", i, + rx_unknown_protocol_frms); + } + + } + __HAL_AUX_ENTRY_END(bufsize, retsize); + + return XGE_HAL_OK; +} + +/** + * xge_hal_aux_stats_herc_enchanced - Get Hercules hardware statistics. + * @devh: HAL device handle. + * @bufsize: Buffer size. + * @retbuf: Buffer pointer. + * @retsize: Size of the result. Cannot be greater than @bufsize. + * + * Read Hercules device hardware statistics. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + * See also: xge_hal_mgmt_hw_stats{}, xge_hal_stats_hw_info_t{}, + * xge_hal_aux_stats_tmac_read(), xge_hal_aux_stats_rmac_read(), + * xge_hal_aux_device_dump(). +*/ +xge_hal_status_e xge_hal_aux_stats_herc_enchanced(xge_hal_device_h devh, + int bufsize, char *retbuf, int *retsize) +{ + xge_hal_status_e status; + xge_hal_mgmt_hw_stats_t hw; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + + __HAL_AUX_ENTRY_DECLARE(bufsize, retbuf); + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN) { + + __HAL_AUX_ENTRY_END(bufsize, retsize); + + return XGE_HAL_OK; + } + + + status = xge_hal_mgmt_hw_stats(devh, &hw, + sizeof(xge_hal_mgmt_hw_stats_t)); + if (status != XGE_HAL_OK) { + return status; + } + __HAL_AUX_ENTRY("tmac_frms_oflow", hw.tmac_frms_oflow, "%u"); + __HAL_AUX_ENTRY("tmac_data_octets_oflow", hw.tmac_data_octets_oflow, + "%u"); + __HAL_AUX_ENTRY("tmac_mcst_frms_oflow", hw.tmac_mcst_frms_oflow, "%u"); + __HAL_AUX_ENTRY("tmac_bcst_frms_oflow", hw.tmac_bcst_frms_oflow, "%u"); + __HAL_AUX_ENTRY("tmac_ttl_octets_oflow", hw.tmac_ttl_octets_oflow, + "%u"); + __HAL_AUX_ENTRY("tmac_ucst_frms_oflow", hw.tmac_ucst_frms_oflow, "%u"); + __HAL_AUX_ENTRY("tmac_nucst_frms_oflow", hw.tmac_nucst_frms_oflow, + "%u"); + __HAL_AUX_ENTRY("tmac_any_err_frms_oflow", hw.tmac_any_err_frms_oflow, + "%u"); + __HAL_AUX_ENTRY("tmac_vlan_frms", (unsigned long long)hw.tmac_vlan_frms, + "%llu"); + __HAL_AUX_ENTRY("tmac_vld_ip_oflow", hw.tmac_vld_ip_oflow, "%u"); + __HAL_AUX_ENTRY("tmac_drop_ip_oflow", hw.tmac_drop_ip_oflow, "%u"); + __HAL_AUX_ENTRY("tmac_icmp_oflow", hw.tmac_icmp_oflow, "%u"); + __HAL_AUX_ENTRY("tmac_rst_tcp_oflow", hw.tmac_rst_tcp_oflow, "%u"); + __HAL_AUX_ENTRY("tmac_udp_oflow", hw.tmac_udp_oflow, "%u"); + __HAL_AUX_ENTRY("tpa_unknown_protocol", hw.tpa_unknown_protocol, "%u"); + __HAL_AUX_ENTRY("tpa_parse_failure", hw.tpa_parse_failure, "%u"); + __HAL_AUX_ENTRY("rmac_vld_frms_oflow", hw.rmac_vld_frms_oflow, "%u"); + __HAL_AUX_ENTRY("rmac_data_octets_oflow", hw.rmac_data_octets_oflow, + "%u"); + __HAL_AUX_ENTRY("rmac_vld_mcst_frms_oflow", hw.rmac_vld_mcst_frms_oflow, + "%u"); + __HAL_AUX_ENTRY("rmac_vld_bcst_frms_oflow", hw.rmac_vld_bcst_frms_oflow, + "%u"); + __HAL_AUX_ENTRY("rmac_ttl_octets_oflow", hw.rmac_ttl_octets_oflow, + "%u"); + __HAL_AUX_ENTRY("rmac_accepted_ucst_frms_oflow", + hw.rmac_accepted_ucst_frms_oflow, "%u"); + __HAL_AUX_ENTRY("rmac_accepted_nucst_frms_oflow", + hw.rmac_accepted_nucst_frms_oflow, "%u"); + __HAL_AUX_ENTRY("rmac_discarded_frms_oflow", + hw.rmac_discarded_frms_oflow, "%u"); + __HAL_AUX_ENTRY("rmac_drop_events_oflow", hw.rmac_drop_events_oflow, + "%u"); + __HAL_AUX_ENTRY("rmac_usized_frms_oflow", hw.rmac_usized_frms_oflow, + "%u"); + __HAL_AUX_ENTRY("rmac_osized_frms_oflow", hw.rmac_osized_frms_oflow, + "%u"); + __HAL_AUX_ENTRY("rmac_frag_frms_oflow", hw.rmac_frag_frms_oflow, "%u"); + __HAL_AUX_ENTRY("rmac_jabber_frms_oflow", hw.rmac_jabber_frms_oflow, + "%u"); + __HAL_AUX_ENTRY("rmac_ip_oflow", hw.rmac_ip_oflow, "%u"); + __HAL_AUX_ENTRY("rmac_drop_ip_oflow", hw.rmac_drop_ip_oflow, "%u"); + __HAL_AUX_ENTRY("rmac_icmp_oflow", hw.rmac_icmp_oflow, "%u"); + __HAL_AUX_ENTRY("rmac_udp_oflow", hw.rmac_udp_oflow, "%u"); + __HAL_AUX_ENTRY("rmac_err_drp_udp_oflow", hw.rmac_err_drp_udp_oflow, + "%u"); + __HAL_AUX_ENTRY("rmac_pause_cnt_oflow", hw.rmac_pause_cnt_oflow, "%u"); + __HAL_AUX_ENTRY("rmac_ttl_1519_4095_frms", + (unsigned long long)hw.rmac_ttl_1519_4095_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_ttl_4096_8191_frms", + (unsigned long long)hw.rmac_ttl_4096_8191_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_ttl_8192_max_frms", + (unsigned long long)hw.rmac_ttl_8192_max_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_ttl_gt_max_frms", + (unsigned long long)hw.rmac_ttl_gt_max_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_osized_alt_frms", + (unsigned long long)hw.rmac_osized_alt_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_jabber_alt_frms", + (unsigned long long)hw.rmac_jabber_alt_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_gt_max_alt_frms", + (unsigned long long)hw.rmac_gt_max_alt_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_vlan_frms", + (unsigned long long)hw.rmac_vlan_frms, "%llu"); + __HAL_AUX_ENTRY("rmac_fcs_discard", hw.rmac_fcs_discard, "%u"); + __HAL_AUX_ENTRY("rmac_len_discard", hw.rmac_len_discard, "%u"); + __HAL_AUX_ENTRY("rmac_da_discard", hw.rmac_da_discard, "%u"); + __HAL_AUX_ENTRY("rmac_pf_discard", hw.rmac_pf_discard, "%u"); + __HAL_AUX_ENTRY("rmac_rts_discard", hw.rmac_rts_discard, "%u"); + __HAL_AUX_ENTRY("rmac_red_discard", hw.rmac_red_discard, "%u"); + __HAL_AUX_ENTRY("rmac_ingm_full_discard", hw.rmac_ingm_full_discard, + "%u"); + __HAL_AUX_ENTRY("rmac_accepted_ip_oflow", hw.rmac_accepted_ip_oflow, + "%u"); + __HAL_AUX_ENTRY("link_fault_cnt", hw.link_fault_cnt, "%u"); + + __HAL_AUX_ENTRY_END(bufsize, retsize); + + return XGE_HAL_OK; +} + +/** + * xge_hal_aux_stats_rmac_read - Read PCI hardware statistics. + * @devh: HAL device handle. + * @bufsize: Buffer size. + * @retbuf: Buffer pointer. + * @retsize: Size of the result. Cannot be greater than @bufsize. + * + * Read PCI statistics counters, including number of PCI read and + * write transactions, PCI retries, discards, etc. + * This is a subset of stats counters from xge_hal_stats_hw_info_t{}. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + * See also: xge_hal_mgmt_hw_stats{}, xge_hal_stats_hw_info_t{}, + * xge_hal_aux_stats_tmac_read(), xge_hal_aux_stats_rmac_read(), + * xge_hal_aux_device_dump(). + */ +xge_hal_status_e xge_hal_aux_stats_pci_read(xge_hal_device_h devh, int bufsize, + char *retbuf, int *retsize) +{ + xge_hal_status_e status; + xge_hal_mgmt_hw_stats_t hw; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + + __HAL_AUX_ENTRY_DECLARE(bufsize, retbuf); + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN) { + + __HAL_AUX_ENTRY_END(bufsize, retsize); + + return XGE_HAL_OK; + } + + + status = xge_hal_mgmt_hw_stats(devh, &hw, + sizeof(xge_hal_mgmt_hw_stats_t)); + if (status != XGE_HAL_OK) { + return status; + } + + __HAL_AUX_ENTRY("new_rd_req_cnt", hw.new_rd_req_cnt, "%u"); + __HAL_AUX_ENTRY("rd_req_cnt", hw.rd_req_cnt, "%u"); + __HAL_AUX_ENTRY("rd_rtry_cnt", hw.rd_rtry_cnt, "%u"); + __HAL_AUX_ENTRY("new_rd_req_rtry_cnt", hw.new_rd_req_rtry_cnt, "%u"); + __HAL_AUX_ENTRY("wr_req_cnt", hw.wr_req_cnt, "%u"); + __HAL_AUX_ENTRY("wr_rtry_rd_ack_cnt", hw.wr_rtry_rd_ack_cnt, "%u"); + __HAL_AUX_ENTRY("new_wr_req_rtry_cnt", hw.new_wr_req_rtry_cnt, "%u"); + __HAL_AUX_ENTRY("new_wr_req_cnt", hw.new_wr_req_cnt, "%u"); + __HAL_AUX_ENTRY("wr_disc_cnt", hw.wr_disc_cnt, "%u"); + __HAL_AUX_ENTRY("wr_rtry_cnt", hw.wr_rtry_cnt, "%u"); + __HAL_AUX_ENTRY("txp_wr_cnt", hw.txp_wr_cnt, "%u"); + __HAL_AUX_ENTRY("rd_rtry_wr_ack_cnt", hw.rd_rtry_wr_ack_cnt, "%u"); + __HAL_AUX_ENTRY("txd_wr_cnt", hw.txd_wr_cnt, "%u"); + __HAL_AUX_ENTRY("txd_rd_cnt", hw.txd_rd_cnt, "%u"); + __HAL_AUX_ENTRY("rxd_wr_cnt", hw.rxd_wr_cnt, "%u"); + __HAL_AUX_ENTRY("rxd_rd_cnt", hw.rxd_rd_cnt, "%u"); + __HAL_AUX_ENTRY("rxf_wr_cnt", hw.rxf_wr_cnt, "%u"); + __HAL_AUX_ENTRY("txf_rd_cnt", hw.txf_rd_cnt, "%u"); + + __HAL_AUX_ENTRY_END(bufsize, retsize); + + return XGE_HAL_OK; +} + +/** + * xge_hal_aux_stats_hal_read - Read HAL (layer) statistics. + * @devh: HAL device handle. + * @bufsize: Buffer size. + * @retbuf: Buffer pointer. + * @retsize: Size of the result. Cannot be greater than @bufsize. + * + * Read HAL statistics. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not + * currently available. + * + * See also: xge_hal_aux_device_dump(). + */ +xge_hal_status_e xge_hal_aux_stats_hal_read(xge_hal_device_h devh, + int bufsize, char *retbuf, int *retsize) +{ + xge_list_t *item; + xge_hal_channel_t *channel; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_status_e status; + xge_hal_mgmt_device_stats_t devstat; + xge_hal_mgmt_channel_stats_t chstat; + __HAL_AUX_ENTRY_DECLARE(bufsize, retbuf); + + status = xge_hal_mgmt_device_stats(hldev, &devstat, + sizeof(xge_hal_mgmt_device_stats_t)); + if (status != XGE_HAL_OK) { + return status; + } + + if (!hldev->config.bimodal_interrupts) { + __HAL_AUX_ENTRY("rx_traffic_intr_cnt", + devstat.rx_traffic_intr_cnt, "%u"); + } + __HAL_AUX_ENTRY("tx_traffic_intr_cnt", devstat.tx_traffic_intr_cnt, "%u"); + __HAL_AUX_ENTRY("txpic_intr_cnt", devstat.txpic_intr_cnt, "%u"); + __HAL_AUX_ENTRY("txdma_intr_cnt", devstat.txdma_intr_cnt, "%u"); + __HAL_AUX_ENTRY("txmac_intr_cnt", devstat.txmac_intr_cnt, "%u"); + __HAL_AUX_ENTRY("txxgxs_intr_cnt", devstat.txxgxs_intr_cnt, "%u"); + __HAL_AUX_ENTRY("rxpic_intr_cnt", devstat.rxpic_intr_cnt, "%u"); + __HAL_AUX_ENTRY("rxdma_intr_cnt", devstat.rxdma_intr_cnt, "%u"); + __HAL_AUX_ENTRY("rxmac_intr_cnt", devstat.rxmac_intr_cnt, "%u"); + __HAL_AUX_ENTRY("rxxgxs_intr_cnt", devstat.rxxgxs_intr_cnt, "%u"); + __HAL_AUX_ENTRY("mc_intr_cnt", devstat.mc_intr_cnt, "%u"); + __HAL_AUX_ENTRY("not_xge_intr_cnt", devstat.not_xge_intr_cnt, "%u"); + __HAL_AUX_ENTRY("not_traffic_intr_cnt", + devstat.not_traffic_intr_cnt, "%u"); + __HAL_AUX_ENTRY("traffic_intr_cnt", devstat.traffic_intr_cnt, "%u"); + __HAL_AUX_ENTRY("total_intr_cnt", devstat.total_intr_cnt, "%u"); + __HAL_AUX_ENTRY("soft_reset_cnt", devstat.soft_reset_cnt, "%u"); + + if (hldev->config.rxufca_hi_lim != hldev->config.rxufca_lo_lim && + hldev->config.rxufca_lo_lim != 0) { + __HAL_AUX_ENTRY("rxufca_lo_adjust_cnt", + devstat.rxufca_lo_adjust_cnt, "%u"); + __HAL_AUX_ENTRY("rxufca_hi_adjust_cnt", + devstat.rxufca_hi_adjust_cnt, "%u"); + } + + if (hldev->config.bimodal_interrupts) { + __HAL_AUX_ENTRY("bimodal_lo_adjust_cnt", + devstat.bimodal_lo_adjust_cnt, "%u"); + __HAL_AUX_ENTRY("bimodal_hi_adjust_cnt", + devstat.bimodal_hi_adjust_cnt, "%u"); + } + +#if defined(XGE_HAL_CONFIG_LRO) + __HAL_AUX_ENTRY("tot_frms_lroised", + devstat.tot_frms_lroised, "%u"); + __HAL_AUX_ENTRY("tot_lro_sessions", + devstat.tot_lro_sessions, "%u"); + __HAL_AUX_ENTRY("lro_frm_len_exceed_cnt", + devstat.lro_frm_len_exceed_cnt, "%u"); + __HAL_AUX_ENTRY("lro_sg_exceed_cnt", + devstat.lro_sg_exceed_cnt, "%u"); + __HAL_AUX_ENTRY("lro_out_of_seq_pkt_cnt", + devstat.lro_out_of_seq_pkt_cnt, "%u"); + __HAL_AUX_ENTRY("lro_dup_pkt_cnt", + devstat.lro_dup_pkt_cnt, "%u"); +#endif + + /* for each opened rx channel */ + xge_list_for_each(item, &hldev->ring_channels) { + char key[XGE_OS_SPRINTF_STRLEN]; + channel = xge_container_of(item, xge_hal_channel_t, item); + + status = xge_hal_mgmt_channel_stats(channel, &chstat, + sizeof(xge_hal_mgmt_channel_stats_t)); + if (status != XGE_HAL_OK) { + return status; + } + + (void) xge_os_sprintf(key, "ring%d_", channel->post_qid); + + xge_os_strcpy(key+6, "full_cnt"); + __HAL_AUX_ENTRY(key, chstat.full_cnt, "%u"); + xge_os_strcpy(key+6, "usage_max"); + __HAL_AUX_ENTRY(key, chstat.usage_max, "%u"); + xge_os_strcpy(key+6, "usage_cnt"); + __HAL_AUX_ENTRY(key, channel->usage_cnt, "%u"); + xge_os_strcpy(key+6, "reserve_free_swaps_cnt"); + __HAL_AUX_ENTRY(key, chstat.reserve_free_swaps_cnt, "%u"); + if (!hldev->config.bimodal_interrupts) { + xge_os_strcpy(key+6, "avg_compl_per_intr_cnt"); + __HAL_AUX_ENTRY(key, chstat.avg_compl_per_intr_cnt, "%u"); + } + xge_os_strcpy(key+6, "total_compl_cnt"); + __HAL_AUX_ENTRY(key, chstat.total_compl_cnt, "%u"); + xge_os_strcpy(key+6, "bump_cnt"); + __HAL_AUX_ENTRY(key, chstat.ring_bump_cnt, "%u"); + } + + /* for each opened tx channel */ + xge_list_for_each(item, &hldev->fifo_channels) { + char key[XGE_OS_SPRINTF_STRLEN]; + channel = xge_container_of(item, xge_hal_channel_t, item); + + status = xge_hal_mgmt_channel_stats(channel, &chstat, + sizeof(xge_hal_mgmt_channel_stats_t)); + if (status != XGE_HAL_OK) { + return status; + } + + (void) xge_os_sprintf(key, "fifo%d_", channel->post_qid); + + xge_os_strcpy(key+6, "full_cnt"); + __HAL_AUX_ENTRY(key, chstat.full_cnt, "%u"); + xge_os_strcpy(key+6, "usage_max"); + __HAL_AUX_ENTRY(key, chstat.usage_max, "%u"); + xge_os_strcpy(key+6, "usage_cnt"); + __HAL_AUX_ENTRY(key, channel->usage_cnt, "%u"); + xge_os_strcpy(key+6, "reserve_free_swaps_cnt"); + __HAL_AUX_ENTRY(key, chstat.reserve_free_swaps_cnt, "%u"); + xge_os_strcpy(key+6, "avg_compl_per_intr_cnt"); + __HAL_AUX_ENTRY(key, chstat.avg_compl_per_intr_cnt, "%u"); + xge_os_strcpy(key+6, "total_compl_cnt"); + __HAL_AUX_ENTRY(key, chstat.total_compl_cnt, "%u"); + xge_os_strcpy(key+6, "total_posts"); + __HAL_AUX_ENTRY(key, chstat.total_posts, "%u"); + xge_os_strcpy(key+6, "total_posts_many"); + __HAL_AUX_ENTRY(key, chstat.total_posts_many, "%u"); + xge_os_strcpy(key+6, "copied_frags"); + __HAL_AUX_ENTRY(key, chstat.copied_frags, "%u"); + xge_os_strcpy(key+6, "copied_buffers"); + __HAL_AUX_ENTRY(key, chstat.copied_buffers, "%u"); + xge_os_strcpy(key+6, "total_buffers"); + __HAL_AUX_ENTRY(key, chstat.total_buffers, "%u"); + xge_os_strcpy(key+6, "avg_buffers_per_post"); + __HAL_AUX_ENTRY(key, chstat.avg_buffers_per_post, "%u"); + xge_os_strcpy(key+6, "avg_buffer_size"); + __HAL_AUX_ENTRY(key, chstat.avg_buffer_size, "%u"); + xge_os_strcpy(key+6, "avg_post_size"); + __HAL_AUX_ENTRY(key, chstat.avg_post_size, "%u"); + xge_os_strcpy(key+6, "total_posts_dtrs_many"); + __HAL_AUX_ENTRY(key, chstat.total_posts_dtrs_many, "%u"); + xge_os_strcpy(key+6, "total_posts_frags_many"); + __HAL_AUX_ENTRY(key, chstat.total_posts_frags_many, "%u"); + xge_os_strcpy(key+6, "total_posts_dang_dtrs"); + __HAL_AUX_ENTRY(key, chstat.total_posts_dang_dtrs, "%u"); + xge_os_strcpy(key+6, "total_posts_dang_frags"); + __HAL_AUX_ENTRY(key, chstat.total_posts_dang_frags, "%u"); + } + + __HAL_AUX_ENTRY_END(bufsize, retsize); + + return XGE_HAL_OK; +} + + + +/** + * xge_hal_aux_stats_sw_dev_read - Read software device statistics. + * @devh: HAL device handle. + * @bufsize: Buffer size. + * @retbuf: Buffer pointer. + * @retsize: Size of the result. Cannot be greater than @bufsize. + * + * Read software-maintained device statistics. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not + * currently available. + * + * See also: xge_hal_aux_device_dump(). + */ +xge_hal_status_e xge_hal_aux_stats_sw_dev_read(xge_hal_device_h devh, + int bufsize, char *retbuf, int *retsize) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_status_e status; + xge_hal_mgmt_sw_stats_t sw_dev_err_stats; + int t_code; + char buf[XGE_OS_SPRINTF_STRLEN]; + + __HAL_AUX_ENTRY_DECLARE(bufsize, retbuf); + + status = xge_hal_mgmt_sw_stats(hldev, &sw_dev_err_stats, + sizeof(xge_hal_mgmt_sw_stats_t)); + if (status != XGE_HAL_OK) { + return status; + } + + __HAL_AUX_ENTRY("sm_err_cnt",sw_dev_err_stats.sm_err_cnt, "%u"); + __HAL_AUX_ENTRY("single_ecc_err_cnt",sw_dev_err_stats.single_ecc_err_cnt, "%u"); + __HAL_AUX_ENTRY("double_ecc_err_cnt",sw_dev_err_stats.double_ecc_err_cnt, "%u"); + __HAL_AUX_ENTRY("ecc_err_cnt", sw_dev_err_stats.ecc_err_cnt, "%u"); + __HAL_AUX_ENTRY("parity_err_cnt",sw_dev_err_stats.parity_err_cnt, "%u"); + __HAL_AUX_ENTRY("serr_cnt",sw_dev_err_stats.serr_cnt, "%u"); + + for (t_code = 1; t_code < 16; t_code++) { + int t_code_cnt = sw_dev_err_stats.rxd_t_code_err_cnt[t_code]; + if (t_code_cnt) { + (void) xge_os_sprintf(buf, "rxd_t_code_%d", t_code); + __HAL_AUX_ENTRY(buf, t_code_cnt, "%u"); + } + t_code_cnt = sw_dev_err_stats.txd_t_code_err_cnt[t_code]; + if (t_code_cnt) { + (void) xge_os_sprintf(buf, "txd_t_code_%d", t_code); + __HAL_AUX_ENTRY(buf, t_code_cnt, "%u"); + } + } + __HAL_AUX_ENTRY("alarm_transceiver_temp_high",sw_dev_err_stats. + stats_xpak.alarm_transceiver_temp_high, "%u"); + __HAL_AUX_ENTRY("alarm_transceiver_temp_low",sw_dev_err_stats. + stats_xpak.alarm_transceiver_temp_low, "%u"); + __HAL_AUX_ENTRY("alarm_laser_bias_current_high",sw_dev_err_stats. + stats_xpak.alarm_laser_bias_current_high, "%u"); + __HAL_AUX_ENTRY("alarm_laser_bias_current_low",sw_dev_err_stats. + stats_xpak.alarm_laser_bias_current_low, "%u"); + __HAL_AUX_ENTRY("alarm_laser_output_power_high",sw_dev_err_stats. + stats_xpak.alarm_laser_output_power_high, "%u"); + __HAL_AUX_ENTRY("alarm_laser_output_power_low",sw_dev_err_stats. + stats_xpak.alarm_laser_output_power_low, "%u"); + __HAL_AUX_ENTRY("warn_transceiver_temp_high",sw_dev_err_stats. + stats_xpak.warn_transceiver_temp_high, "%u"); + __HAL_AUX_ENTRY("warn_transceiver_temp_low",sw_dev_err_stats. + stats_xpak.warn_transceiver_temp_low, "%u"); + __HAL_AUX_ENTRY("warn_laser_bias_current_high",sw_dev_err_stats. + stats_xpak.warn_laser_bias_current_high, "%u"); + __HAL_AUX_ENTRY("warn_laser_bias_current_low",sw_dev_err_stats. + stats_xpak.warn_laser_bias_current_low, "%u"); + __HAL_AUX_ENTRY("warn_laser_output_power_high",sw_dev_err_stats. + stats_xpak.warn_laser_output_power_high, "%u"); + __HAL_AUX_ENTRY("warn_laser_output_power_low",sw_dev_err_stats. + stats_xpak.warn_laser_output_power_low, "%u"); + + __HAL_AUX_ENTRY_END(bufsize, retsize); + + return XGE_HAL_OK; +} + +/** + * xge_hal_aux_pci_config_read - Retrieve and format PCI Configuration + * info. + * @devh: HAL device handle. + * @bufsize: Buffer size. + * @retbuf: Buffer pointer. + * @retsize: Size of the result. Cannot be greater than @bufsize. + * + * Retrieve about info (using xge_hal_mgmt_pci_config()) and sprintf it + * into the provided @retbuf. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + * See also: xge_hal_mgmt_pci_config(), xge_hal_aux_device_dump(). + */ +xge_hal_status_e xge_hal_aux_pci_config_read(xge_hal_device_h devh, int bufsize, + char *retbuf, int *retsize) +{ + xge_hal_status_e status; + xge_hal_mgmt_pci_config_t pci_config; + __HAL_AUX_ENTRY_DECLARE(bufsize, retbuf); + + status = xge_hal_mgmt_pci_config(devh, &pci_config, + sizeof(xge_hal_mgmt_pci_config_t)); + if (status != XGE_HAL_OK) { + return status; + } + + __HAL_AUX_ENTRY("vendor_id", pci_config.vendor_id, "0x%04X"); + __HAL_AUX_ENTRY("device_id", pci_config.device_id, "0x%04X"); + __HAL_AUX_ENTRY("command", pci_config.command, "0x%04X"); + __HAL_AUX_ENTRY("status", pci_config.status, "0x%04X"); + __HAL_AUX_ENTRY("revision", pci_config.revision, "0x%02X"); + __HAL_AUX_ENTRY("pciClass1", pci_config.pciClass[0], "0x%02X"); + __HAL_AUX_ENTRY("pciClass2", pci_config.pciClass[1], "0x%02X"); + __HAL_AUX_ENTRY("pciClass3", pci_config.pciClass[2], "0x%02X"); + __HAL_AUX_ENTRY("cache_line_size", + pci_config.cache_line_size, "0x%02X"); + __HAL_AUX_ENTRY("latency_timer", pci_config.latency_timer, "0x%02X"); + __HAL_AUX_ENTRY("header_type", pci_config.header_type, "0x%02X"); + __HAL_AUX_ENTRY("bist", pci_config.bist, "0x%02X"); + __HAL_AUX_ENTRY("base_addr0_lo", pci_config.base_addr0_lo, "0x%08X"); + __HAL_AUX_ENTRY("base_addr0_hi", pci_config.base_addr0_hi, "0x%08X"); + __HAL_AUX_ENTRY("base_addr1_lo", pci_config.base_addr1_lo, "0x%08X"); + __HAL_AUX_ENTRY("base_addr1_hi", pci_config.base_addr1_hi, "0x%08X"); + __HAL_AUX_ENTRY("not_Implemented1", + pci_config.not_Implemented1, "0x%08X"); + __HAL_AUX_ENTRY("not_Implemented2", pci_config.not_Implemented2, + "0x%08X"); + __HAL_AUX_ENTRY("cardbus_cis_pointer", pci_config.cardbus_cis_pointer, + "0x%08X"); + __HAL_AUX_ENTRY("subsystem_vendor_id", pci_config.subsystem_vendor_id, + "0x%04X"); + __HAL_AUX_ENTRY("subsystem_id", pci_config.subsystem_id, "0x%04X"); + __HAL_AUX_ENTRY("rom_base", pci_config.rom_base, "0x%08X"); + __HAL_AUX_ENTRY("capabilities_pointer", + pci_config.capabilities_pointer, "0x%02X"); + __HAL_AUX_ENTRY("interrupt_line", pci_config.interrupt_line, "0x%02X"); + __HAL_AUX_ENTRY("interrupt_pin", pci_config.interrupt_pin, "0x%02X"); + __HAL_AUX_ENTRY("min_grant", pci_config.min_grant, "0x%02X"); + __HAL_AUX_ENTRY("max_latency", pci_config.max_latency, "0x%02X"); + __HAL_AUX_ENTRY("msi_cap_id", pci_config.msi_cap_id, "0x%02X"); + __HAL_AUX_ENTRY("msi_next_ptr", pci_config.msi_next_ptr, "0x%02X"); + __HAL_AUX_ENTRY("msi_control", pci_config.msi_control, "0x%04X"); + __HAL_AUX_ENTRY("msi_lower_address", pci_config.msi_lower_address, + "0x%08X"); + __HAL_AUX_ENTRY("msi_higher_address", pci_config.msi_higher_address, + "0x%08X"); + __HAL_AUX_ENTRY("msi_data", pci_config.msi_data, "0x%04X"); + __HAL_AUX_ENTRY("msi_unused", pci_config.msi_unused, "0x%04X"); + __HAL_AUX_ENTRY("vpd_cap_id", pci_config.vpd_cap_id, "0x%02X"); + __HAL_AUX_ENTRY("vpd_next_cap", pci_config.vpd_next_cap, "0x%02X"); + __HAL_AUX_ENTRY("vpd_addr", pci_config.vpd_addr, "0x%04X"); + __HAL_AUX_ENTRY("vpd_data", pci_config.vpd_data, "0x%08X"); + __HAL_AUX_ENTRY("pcix_cap", pci_config.pcix_cap, "0x%02X"); + __HAL_AUX_ENTRY("pcix_next_cap", pci_config.pcix_next_cap, "0x%02X"); + __HAL_AUX_ENTRY("pcix_command", pci_config.pcix_command, "0x%04X"); + __HAL_AUX_ENTRY("pcix_status", pci_config.pcix_status, "0x%08X"); + + if (xge_hal_device_check_id(devh) == XGE_HAL_CARD_HERC) { + char key[XGE_OS_SPRINTF_STRLEN]; + int i; + + for (i = 0; + i < (XGE_HAL_PCI_XFRAME_CONFIG_SPACE_SIZE - 0x68)/4; + i++) { + (void) xge_os_sprintf(key, "%03x:", 4*i + 0x68); + __HAL_AUX_ENTRY(key, *((int *)pci_config.rsvd_b1 + i), + "0x%08X"); + } + } + + __HAL_AUX_ENTRY_END(bufsize, retsize); + + return XGE_HAL_OK; +} + + +/** + * xge_hal_aux_channel_read - Read channels information. + * @devh: HAL device handle. + * @bufsize: Buffer size. + * @retbuf: Buffer pointer. + * @retsize: Size of the result. Cannot be greater than @bufsize. + * + * Read HAL statistics. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_OUT_OF_SPACE - Buffer size is very small. + * See also: xge_hal_aux_device_dump(). + */ +xge_hal_status_e xge_hal_aux_channel_read(xge_hal_device_h devh, + int bufsize, char *retbuf, int *retsize) +{ + xge_list_t *item; + xge_hal_channel_t *channel; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + __HAL_AUX_ENTRY_DECLARE(bufsize, retbuf); + + if (hldev->magic != XGE_HAL_MAGIC) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + /* for each opened rx channel */ + xge_list_for_each(item, &hldev->ring_channels) { + char key[XGE_OS_SPRINTF_STRLEN]; + channel = xge_container_of(item, xge_hal_channel_t, item); + + if (channel->is_open != 1) + continue; + + (void) xge_os_sprintf(key, "ring%d_", channel->post_qid); + xge_os_strcpy(key+6, "type"); + __HAL_AUX_ENTRY(key, channel->type, "%u"); + xge_os_strcpy(key+6, "length"); + __HAL_AUX_ENTRY(key, channel->length, "%u"); + xge_os_strcpy(key+6, "is_open"); + __HAL_AUX_ENTRY(key, channel->is_open, "%u"); + xge_os_strcpy(key+6, "reserve_initial"); + __HAL_AUX_ENTRY(key, channel->reserve_initial, "%u"); + xge_os_strcpy(key+6, "reserve_max"); + __HAL_AUX_ENTRY(key, channel->reserve_max, "%u"); + xge_os_strcpy(key+6, "reserve_length"); + __HAL_AUX_ENTRY(key, channel->reserve_length, "%u"); + xge_os_strcpy(key+6, "reserve_top"); + __HAL_AUX_ENTRY(key, channel->reserve_top, "%u"); + xge_os_strcpy(key+6, "reserve_threshold"); + __HAL_AUX_ENTRY(key, channel->reserve_threshold, "%u"); + xge_os_strcpy(key+6, "free_length"); + __HAL_AUX_ENTRY(key, channel->free_length, "%u"); + xge_os_strcpy(key+6, "post_index"); + __HAL_AUX_ENTRY(key, channel->post_index, "%u"); + xge_os_strcpy(key+6, "compl_index"); + __HAL_AUX_ENTRY(key, channel->compl_index, "%u"); + xge_os_strcpy(key+6, "per_dtr_space"); + __HAL_AUX_ENTRY(key, channel->per_dtr_space, "%u"); + xge_os_strcpy(key+6, "usage_cnt"); + __HAL_AUX_ENTRY(key, channel->usage_cnt, "%u"); + } + + /* for each opened tx channel */ + xge_list_for_each(item, &hldev->fifo_channels) { + char key[XGE_OS_SPRINTF_STRLEN]; + channel = xge_container_of(item, xge_hal_channel_t, item); + + if (channel->is_open != 1) + continue; + + (void) xge_os_sprintf(key, "fifo%d_", channel->post_qid); + xge_os_strcpy(key+6, "type"); + __HAL_AUX_ENTRY(key, channel->type, "%u"); + xge_os_strcpy(key+6, "length"); + __HAL_AUX_ENTRY(key, channel->length, "%u"); + xge_os_strcpy(key+6, "is_open"); + __HAL_AUX_ENTRY(key, channel->is_open, "%u"); + xge_os_strcpy(key+6, "reserve_initial"); + __HAL_AUX_ENTRY(key, channel->reserve_initial, "%u"); + xge_os_strcpy(key+6, "reserve_max"); + __HAL_AUX_ENTRY(key, channel->reserve_max, "%u"); + xge_os_strcpy(key+6, "reserve_length"); + __HAL_AUX_ENTRY(key, channel->reserve_length, "%u"); + xge_os_strcpy(key+6, "reserve_top"); + __HAL_AUX_ENTRY(key, channel->reserve_top, "%u"); + xge_os_strcpy(key+6, "reserve_threshold"); + __HAL_AUX_ENTRY(key, channel->reserve_threshold, "%u"); + xge_os_strcpy(key+6, "free_length"); + __HAL_AUX_ENTRY(key, channel->free_length, "%u"); + xge_os_strcpy(key+6, "post_index"); + __HAL_AUX_ENTRY(key, channel->post_index, "%u"); + xge_os_strcpy(key+6, "compl_index"); + __HAL_AUX_ENTRY(key, channel->compl_index, "%u"); + xge_os_strcpy(key+6, "per_dtr_space"); + __HAL_AUX_ENTRY(key, channel->per_dtr_space, "%u"); + xge_os_strcpy(key+6, "usage_cnt"); + __HAL_AUX_ENTRY(key, channel->usage_cnt, "%u"); + } + + __HAL_AUX_ENTRY_END(bufsize, retsize); + + return XGE_HAL_OK; +} + +/** + * xge_hal_aux_device_dump - Dump driver "about" info and device state. + * @devh: HAL device handle. + * + * Dump driver & device "about" info and device state, + * including all BAR0 registers, hardware and software statistics, PCI + * configuration space. + * See also: xge_hal_aux_about_read(), xge_hal_mgmt_reg_read(), + * xge_hal_aux_pci_config_read(), xge_hal_aux_stats_sw_dev_read(), + * xge_hal_aux_stats_tmac_read(), xge_hal_aux_stats_rmac_read(), + * xge_hal_aux_channel_read(), xge_hal_aux_stats_hal_read(). + * Returns: + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_OUT_OF_SPACE - Buffer size is very small. + */ +xge_hal_status_e +xge_hal_aux_device_dump(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + xge_hal_status_e status; + int retsize; + int offset; + u64 retval; + + xge_assert(hldev->dump_buf != NULL); + + xge_os_println("********* xge DEVICE DUMP BEGIN **********"); + + status = xge_hal_aux_about_read(hldev, XGE_HAL_DUMP_BUF_SIZE, + hldev->dump_buf, + &retsize); + if (status != XGE_HAL_OK) { + goto error; + } + xge_os_println(hldev->dump_buf); + + + for (offset = 0; offset < 1574; offset++) { + + status = xge_hal_mgmt_reg_read(hldev, 0, offset*8, &retval); + if (status != XGE_HAL_OK) { + goto error; + } + + if (!retval) continue; + + xge_os_printf("0x%04x 0x%08x%08x", offset*8, + (u32)(retval>>32), (u32)retval); + } + xge_os_println("\n"); + + status = xge_hal_aux_pci_config_read(hldev, XGE_HAL_DUMP_BUF_SIZE, + hldev->dump_buf, + &retsize); + if (status != XGE_HAL_OK) { + goto error; + } + xge_os_println(hldev->dump_buf); + + status = xge_hal_aux_stats_tmac_read(hldev, XGE_HAL_DUMP_BUF_SIZE, + hldev->dump_buf, + &retsize); + if (status != XGE_HAL_OK) { + goto error; + } + xge_os_println(hldev->dump_buf); + + status = xge_hal_aux_stats_rmac_read(hldev, XGE_HAL_DUMP_BUF_SIZE, + hldev->dump_buf, + &retsize); + if (status != XGE_HAL_OK) { + goto error; + } + xge_os_println(hldev->dump_buf); + + status = xge_hal_aux_stats_pci_read(hldev, XGE_HAL_DUMP_BUF_SIZE, + hldev->dump_buf, + &retsize); + if (status != XGE_HAL_OK) { + goto error; + } + xge_os_println(hldev->dump_buf); + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + status = xge_hal_aux_stats_herc_enchanced(hldev, + XGE_HAL_DUMP_BUF_SIZE, hldev->dump_buf, &retsize); + if (status != XGE_HAL_OK) { + goto error; + } + xge_os_println(hldev->dump_buf); + } + + status = xge_hal_aux_stats_sw_dev_read(hldev, XGE_HAL_DUMP_BUF_SIZE, + hldev->dump_buf, &retsize); + if (status != XGE_HAL_OK) { + goto error; + } + xge_os_println(hldev->dump_buf); + + status = xge_hal_aux_channel_read(hldev, XGE_HAL_DUMP_BUF_SIZE, + hldev->dump_buf, + &retsize); + if (status != XGE_HAL_OK) { + goto error; + } + xge_os_println(hldev->dump_buf); + + status = xge_hal_aux_stats_hal_read(hldev, XGE_HAL_DUMP_BUF_SIZE, + hldev->dump_buf, + &retsize); + if (status != XGE_HAL_OK) { + goto error; + } + xge_os_println(hldev->dump_buf); + + xge_os_println("********* XFRAME DEVICE DUMP END **********"); + +error: + return status; +} + + +/** + * xge_hal_aux_driver_config_read - Read Driver configuration. + * @bufsize: Buffer size. + * @retbuf: Buffer pointer. + * @retsize: Size of the result. Cannot be greater than @bufsize. + * + * Read driver configuration, + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + * See also: xge_hal_aux_device_config_read(). + */ +xge_hal_status_e +xge_hal_aux_driver_config_read(int bufsize, char *retbuf, int *retsize) +{ + xge_hal_status_e status; + xge_hal_driver_config_t drv_config; + __HAL_AUX_ENTRY_DECLARE(bufsize, retbuf); + + status = xge_hal_mgmt_driver_config(&drv_config, + sizeof(xge_hal_driver_config_t)); + if (status != XGE_HAL_OK) { + return status; + } + + __HAL_AUX_ENTRY("queue size initial", + drv_config.queue_size_initial, "%u"); + __HAL_AUX_ENTRY("queue size max", drv_config.queue_size_max, "%u"); + __HAL_AUX_ENTRY_END(bufsize, retsize); + + return XGE_HAL_OK; +} + + +/** + * xge_hal_aux_device_config_read - Read device configuration. + * @devh: HAL device handle. + * @bufsize: Buffer size. + * @retbuf: Buffer pointer. + * @retsize: Size of the result. Cannot be greater than @bufsize. + * + * Read device configuration, + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. + * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. + * + * See also: xge_hal_aux_driver_config_read(). + */ +xge_hal_status_e xge_hal_aux_device_config_read(xge_hal_device_h devh, + int bufsize, char *retbuf, int *retsize) +{ + int i; + xge_hal_status_e status; + xge_hal_device_config_t *dev_config; + xge_hal_device_t *hldev = (xge_hal_device_t *) devh; + char key[XGE_OS_SPRINTF_STRLEN]; + __HAL_AUX_ENTRY_DECLARE(bufsize, retbuf); + + dev_config = (xge_hal_device_config_t *) xge_os_malloc(hldev->pdev, + sizeof(xge_hal_device_config_t)); + if (dev_config == NULL) { + return XGE_HAL_FAIL; + } + + status = xge_hal_mgmt_device_config(devh, dev_config, + sizeof(xge_hal_device_config_t)); + if (status != XGE_HAL_OK) { + xge_os_free(hldev->pdev, dev_config, + sizeof(xge_hal_device_config_t)); + return status; + } + + __HAL_AUX_ENTRY("mtu", dev_config->mtu, "%u"); + __HAL_AUX_ENTRY("isr_polling_count", dev_config->isr_polling_cnt, "%u"); + __HAL_AUX_ENTRY("latency_timer", dev_config->latency_timer, "%u"); + __HAL_AUX_ENTRY("max_splits_trans", + dev_config->max_splits_trans, "%u"); + __HAL_AUX_ENTRY("mmrb_count", dev_config->mmrb_count, "%d"); + __HAL_AUX_ENTRY("shared_splits", dev_config->shared_splits, "%u"); + __HAL_AUX_ENTRY("stats_refresh_time_sec", + dev_config->stats_refresh_time_sec, "%u"); + __HAL_AUX_ENTRY("pci_freq_mherz", dev_config->pci_freq_mherz, "%u"); + __HAL_AUX_ENTRY("intr_mode", dev_config->intr_mode, "%u"); + __HAL_AUX_ENTRY("ring_memblock_size", + dev_config->ring.memblock_size, "%u"); + + __HAL_AUX_ENTRY("sched_timer_us", dev_config->sched_timer_us, "%u"); + __HAL_AUX_ENTRY("sched_timer_one_shot", + dev_config->sched_timer_one_shot, "%u"); + __HAL_AUX_ENTRY("rxufca_intr_thres", dev_config->rxufca_intr_thres, "%u"); + __HAL_AUX_ENTRY("rxufca_lo_lim", dev_config->rxufca_lo_lim, "%u"); + __HAL_AUX_ENTRY("rxufca_hi_lim", dev_config->rxufca_hi_lim, "%u"); + __HAL_AUX_ENTRY("rxufca_lbolt_period", dev_config->rxufca_lbolt_period, "%u"); + + for(i = 0; i < XGE_HAL_MAX_RING_NUM; i++) + { + xge_hal_ring_queue_t *ring = &dev_config->ring.queue[i]; + xge_hal_rti_config_t *rti = &ring->rti; + + if (!ring->configured) + continue; + + (void) xge_os_sprintf(key, "ring%d_", i); + xge_os_strcpy(key+6, "inital"); + __HAL_AUX_ENTRY(key, ring->initial, "%u"); + xge_os_strcpy(key+6, "max"); + __HAL_AUX_ENTRY(key, ring->max, "%u"); + xge_os_strcpy(key+6, "buffer_mode"); + __HAL_AUX_ENTRY(key, ring->buffer_mode, "%u"); + xge_os_strcpy(key+6, "dram_size_mb"); + __HAL_AUX_ENTRY(key, ring->dram_size_mb, "%u"); + xge_os_strcpy(key+6, "backoff_interval_us"); + __HAL_AUX_ENTRY(key, ring->backoff_interval_us, "%u"); + xge_os_strcpy(key+6, "max_frame_len"); + __HAL_AUX_ENTRY(key, ring->max_frm_len, "%d"); + xge_os_strcpy(key+6, "priority"); + __HAL_AUX_ENTRY(key, ring->priority, "%u"); + xge_os_strcpy(key+6, "rth_en"); + __HAL_AUX_ENTRY(key, ring->rth_en, "%u"); + xge_os_strcpy(key+6, "no_snoop_bits"); + __HAL_AUX_ENTRY(key, ring->no_snoop_bits, "%u"); + xge_os_strcpy(key+6, "indicate_max_pkts"); + __HAL_AUX_ENTRY(key, ring->indicate_max_pkts, "%u"); + + xge_os_strcpy(key+6, "urange_a"); + __HAL_AUX_ENTRY(key, rti->urange_a, "%u"); + xge_os_strcpy(key+6, "ufc_a"); + __HAL_AUX_ENTRY(key, rti->ufc_a, "%u"); + xge_os_strcpy(key+6, "urange_b"); + __HAL_AUX_ENTRY(key, rti->urange_b, "%u"); + xge_os_strcpy(key+6, "ufc_b"); + __HAL_AUX_ENTRY(key, rti->ufc_b, "%u"); + xge_os_strcpy(key+6, "urange_c"); + __HAL_AUX_ENTRY(key, rti->urange_c, "%u"); + xge_os_strcpy(key+6, "ufc_c"); + __HAL_AUX_ENTRY(key, rti->ufc_c, "%u"); + xge_os_strcpy(key+6, "ufc_d"); + __HAL_AUX_ENTRY(key, rti->ufc_d, "%u"); + xge_os_strcpy(key+6, "timer_val_us"); + __HAL_AUX_ENTRY(key, rti->timer_val_us, "%u"); + } + + + { + xge_hal_mac_config_t *mac= &dev_config->mac; + + __HAL_AUX_ENTRY("tmac_util_period", + mac->tmac_util_period, "%u"); + __HAL_AUX_ENTRY("rmac_util_period", + mac->rmac_util_period, "%u"); + __HAL_AUX_ENTRY("rmac_bcast_en", + mac->rmac_bcast_en, "%u"); + __HAL_AUX_ENTRY("rmac_pause_gen_en", + mac->rmac_pause_gen_en, "%d"); + __HAL_AUX_ENTRY("rmac_pause_rcv_en", + mac->rmac_pause_rcv_en, "%d"); + __HAL_AUX_ENTRY("rmac_pause_time", + mac->rmac_pause_time, "%u"); + __HAL_AUX_ENTRY("mc_pause_threshold_q0q3", + mac->mc_pause_threshold_q0q3, "%u"); + __HAL_AUX_ENTRY("mc_pause_threshold_q4q7", + mac->mc_pause_threshold_q4q7, "%u"); + } + + + __HAL_AUX_ENTRY("fifo_max_frags", dev_config->fifo.max_frags, "%u"); + __HAL_AUX_ENTRY("fifo_reserve_threshold", + dev_config->fifo.reserve_threshold, "%u"); + __HAL_AUX_ENTRY("fifo_memblock_size", + dev_config->fifo.memblock_size, "%u"); +#ifdef XGE_HAL_ALIGN_XMIT + __HAL_AUX_ENTRY("fifo_alignment_size", + dev_config->fifo.alignment_size, "%u"); +#endif + + for (i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) { + int j; + xge_hal_fifo_queue_t *fifo = &dev_config->fifo.queue[i]; + + if (!fifo->configured) + continue; + + (void) xge_os_sprintf(key, "fifo%d_", i); + xge_os_strcpy(key+6, "initial"); + __HAL_AUX_ENTRY(key, fifo->initial, "%u"); + xge_os_strcpy(key+6, "max"); + __HAL_AUX_ENTRY(key, fifo->max, "%u"); + xge_os_strcpy(key+6, "intr"); + __HAL_AUX_ENTRY(key, fifo->intr, "%u"); + xge_os_strcpy(key+6, "no_snoop_bits"); + __HAL_AUX_ENTRY(key, fifo->no_snoop_bits, "%u"); + + for (j = 0; j < XGE_HAL_MAX_FIFO_TTI_NUM; j++) { + xge_hal_tti_config_t *tti = + &dev_config->fifo.queue[i].tti[j]; + + if (!tti->enabled) + continue; + + (void) xge_os_sprintf(key, "fifo%d_tti%02d_", i, + i * XGE_HAL_MAX_FIFO_TTI_NUM + j); + xge_os_strcpy(key+12, "urange_a"); + __HAL_AUX_ENTRY(key, tti->urange_a, "%u"); + xge_os_strcpy(key+12, "ufc_a"); + __HAL_AUX_ENTRY(key, tti->ufc_a, "%u"); + xge_os_strcpy(key+12, "urange_b"); + __HAL_AUX_ENTRY(key, tti->urange_b, "%u"); + xge_os_strcpy(key+12, "ufc_b"); + __HAL_AUX_ENTRY(key, tti->ufc_b, "%u"); + xge_os_strcpy(key+12, "urange_c"); + __HAL_AUX_ENTRY(key, tti->urange_c, "%u"); + xge_os_strcpy(key+12, "ufc_c"); + __HAL_AUX_ENTRY(key, tti->ufc_c, "%u"); + xge_os_strcpy(key+12, "ufc_d"); + __HAL_AUX_ENTRY(key, tti->ufc_d, "%u"); + xge_os_strcpy(key+12, "timer_val_us"); + __HAL_AUX_ENTRY(key, tti->timer_val_us, "%u"); + xge_os_strcpy(key+12, "timer_ci_en"); + __HAL_AUX_ENTRY(key, tti->timer_ci_en, "%u"); + } + } + + /* and bimodal TTIs */ + for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) { + xge_hal_tti_config_t *tti = &hldev->bimodal_tti[i]; + + if (!tti->enabled) + continue; + + (void) xge_os_sprintf(key, "tti%02d_", + XGE_HAL_MAX_FIFO_TTI_RING_0 + i); + + xge_os_strcpy(key+6, "urange_a"); + __HAL_AUX_ENTRY(key, tti->urange_a, "%u"); + xge_os_strcpy(key+6, "ufc_a"); + __HAL_AUX_ENTRY(key, tti->ufc_a, "%u"); + xge_os_strcpy(key+6, "urange_b"); + __HAL_AUX_ENTRY(key, tti->urange_b, "%u"); + xge_os_strcpy(key+6, "ufc_b"); + __HAL_AUX_ENTRY(key, tti->ufc_b, "%u"); + xge_os_strcpy(key+6, "urange_c"); + __HAL_AUX_ENTRY(key, tti->urange_c, "%u"); + xge_os_strcpy(key+6, "ufc_c"); + __HAL_AUX_ENTRY(key, tti->ufc_c, "%u"); + xge_os_strcpy(key+6, "ufc_d"); + __HAL_AUX_ENTRY(key, tti->ufc_d, "%u"); + xge_os_strcpy(key+6, "timer_val_us"); + __HAL_AUX_ENTRY(key, tti->timer_val_us, "%u"); + xge_os_strcpy(key+6, "timer_ac_en"); + __HAL_AUX_ENTRY(key, tti->timer_ac_en, "%u"); + xge_os_strcpy(key+6, "timer_ci_en"); + __HAL_AUX_ENTRY(key, tti->timer_ci_en, "%u"); + } + __HAL_AUX_ENTRY("dump_on_serr", dev_config->dump_on_serr, "%u"); + __HAL_AUX_ENTRY("dump_on_eccerr", + dev_config->dump_on_eccerr, "%u"); + __HAL_AUX_ENTRY("dump_on_parityerr", + dev_config->dump_on_parityerr, "%u"); + __HAL_AUX_ENTRY("rth_en", dev_config->rth_en, "%u"); + __HAL_AUX_ENTRY("rth_bucket_size", dev_config->rth_bucket_size, "%u"); + + __HAL_AUX_ENTRY_END(bufsize, retsize); + + xge_os_free(hldev->pdev, dev_config, + sizeof(xge_hal_device_config_t)); + + return XGE_HAL_OK; +} + diff --git a/sys/dev/nxge/xgehal/xgehal-mm.c b/sys/dev/nxge/xgehal/xgehal-mm.c new file mode 100644 index 0000000..d23f88a --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-mm.c @@ -0,0 +1,436 @@ +/*- + * 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$ + */ + +/* + * FileName : hal-mm.c + * + * Description: chipset memory pool object implementation + * + * Created: 10 May 2004 + */ + +#include <dev/nxge/include/xge-os-pal.h> +#include <dev/nxge/include/xgehal-mm.h> +#include <dev/nxge/include/xge-debug.h> + +/* + * __hal_mempool_grow + * + * Will resize mempool up to %num_allocate value. + */ +xge_hal_status_e +__hal_mempool_grow(xge_hal_mempool_t *mempool, int num_allocate, + int *num_allocated) +{ + int i, first_time = mempool->memblocks_allocated == 0 ? 1 : 0; + int n_items = mempool->items_per_memblock; + + *num_allocated = 0; + + if ((mempool->memblocks_allocated + num_allocate) > + mempool->memblocks_max) { + xge_debug_mm(XGE_ERR, "%s", + "__hal_mempool_grow: can grow anymore"); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + + for (i = mempool->memblocks_allocated; + i < mempool->memblocks_allocated + num_allocate; i++) { + int j; + int is_last = + ((mempool->memblocks_allocated+num_allocate-1) == i); + xge_hal_mempool_dma_t *dma_object = + mempool->memblocks_dma_arr + i; + void *the_memblock; + int dma_flags; + + dma_flags = XGE_OS_DMA_CACHELINE_ALIGNED; +#ifdef XGE_HAL_DMA_DTR_CONSISTENT + dma_flags |= XGE_OS_DMA_CONSISTENT; +#else + dma_flags |= XGE_OS_DMA_STREAMING; +#endif + + /* allocate DMA-capable memblock */ + mempool->memblocks_arr[i] = xge_os_dma_malloc(mempool->pdev, + mempool->memblock_size, + dma_flags, + &dma_object->handle, + &dma_object->acc_handle); + if (mempool->memblocks_arr[i] == NULL) { + xge_debug_mm(XGE_ERR, + "memblock[%d]: out of DMA memory", i); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + xge_os_memzero(mempool->memblocks_arr[i], + mempool->memblock_size); + the_memblock = mempool->memblocks_arr[i]; + + /* allocate memblock's private part. Each DMA memblock + * has a space allocated for item's private usage upon + * mempool's user request. Each time mempool grows, it will + * allocate new memblock and its private part at once. + * This helps to minimize memory usage a lot. */ + mempool->memblocks_priv_arr[i] = xge_os_malloc(mempool->pdev, + mempool->items_priv_size * n_items); + if (mempool->memblocks_priv_arr[i] == NULL) { + xge_os_dma_free(mempool->pdev, + the_memblock, + mempool->memblock_size, + &dma_object->acc_handle, + &dma_object->handle); + xge_debug_mm(XGE_ERR, + "memblock_priv[%d]: out of virtual memory, " + "requested %d(%d:%d) bytes", i, + mempool->items_priv_size * n_items, + mempool->items_priv_size, n_items); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + xge_os_memzero(mempool->memblocks_priv_arr[i], + mempool->items_priv_size * n_items); + + /* map memblock to physical memory */ + dma_object->addr = xge_os_dma_map(mempool->pdev, + dma_object->handle, + the_memblock, + mempool->memblock_size, + XGE_OS_DMA_DIR_BIDIRECTIONAL, +#ifdef XGE_HAL_DMA_DTR_CONSISTENT + XGE_OS_DMA_CONSISTENT +#else + XGE_OS_DMA_STREAMING +#endif + ); + if (dma_object->addr == XGE_OS_INVALID_DMA_ADDR) { + xge_os_free(mempool->pdev, mempool->memblocks_priv_arr[i], + mempool->items_priv_size * + n_items); + xge_os_dma_free(mempool->pdev, + the_memblock, + mempool->memblock_size, + &dma_object->acc_handle, + &dma_object->handle); + return XGE_HAL_ERR_OUT_OF_MAPPING; + } + + /* fill the items hash array */ + for (j=0; j<n_items; j++) { + int index = i*n_items + j; + + if (first_time && index >= mempool->items_initial) { + break; + } + + mempool->items_arr[index] = + ((char *)the_memblock + j*mempool->item_size); + + /* let caller to do more job on each item */ + if (mempool->item_func_alloc != NULL) { + xge_hal_status_e status; + + if ((status = mempool->item_func_alloc( + mempool, + the_memblock, + i, + dma_object, + mempool->items_arr[index], + index, + is_last, + mempool->userdata)) != XGE_HAL_OK) { + + if (mempool->item_func_free != NULL) { + int k; + + for (k=0; k<j; k++) { + + index =i*n_items + k; + + (void)mempool->item_func_free( + mempool, the_memblock, + i, dma_object, + mempool->items_arr[index], + index, is_last, + mempool->userdata); + } + } + + xge_os_free(mempool->pdev, + mempool->memblocks_priv_arr[i], + mempool->items_priv_size * + n_items); + xge_os_dma_unmap(mempool->pdev, + dma_object->handle, + dma_object->addr, + mempool->memblock_size, + XGE_OS_DMA_DIR_BIDIRECTIONAL); + xge_os_dma_free(mempool->pdev, + the_memblock, + mempool->memblock_size, + &dma_object->acc_handle, + &dma_object->handle); + return status; + } + } + + mempool->items_current = index + 1; + } + + xge_debug_mm(XGE_TRACE, + "memblock%d: allocated %dk, vaddr 0x"XGE_OS_LLXFMT", " + "dma_addr 0x"XGE_OS_LLXFMT, i, mempool->memblock_size / 1024, + (unsigned long long)(ulong_t)mempool->memblocks_arr[i], + (unsigned long long)dma_object->addr); + + (*num_allocated)++; + + if (first_time && mempool->items_current == + mempool->items_initial) { + break; + } + } + + /* increment actual number of allocated memblocks */ + mempool->memblocks_allocated += *num_allocated; + + return XGE_HAL_OK; +} + +/* + * xge_hal_mempool_create + * @memblock_size: + * @items_initial: + * @items_max: + * @item_size: + * @item_func: + * + * This function will create memory pool object. Pool may grow but will + * never shrink. Pool consists of number of dynamically allocated blocks + * with size enough to hold %items_initial number of items. Memory is + * DMA-able but client must map/unmap before interoperating with the device. + * See also: xge_os_dma_map(), xge_hal_dma_unmap(), xge_hal_status_e{}. + */ +xge_hal_mempool_t* +__hal_mempool_create(pci_dev_h pdev, int memblock_size, int item_size, + int items_priv_size, int items_initial, int items_max, + xge_hal_mempool_item_f item_func_alloc, + xge_hal_mempool_item_f item_func_free, void *userdata) +{ + xge_hal_status_e status; + int memblocks_to_allocate; + xge_hal_mempool_t *mempool; + int allocated; + + if (memblock_size < item_size) { + xge_debug_mm(XGE_ERR, + "memblock_size %d < item_size %d: misconfiguration", + memblock_size, item_size); + return NULL; + } + + mempool = (xge_hal_mempool_t *) \ + xge_os_malloc(pdev, sizeof(xge_hal_mempool_t)); + if (mempool == NULL) { + xge_debug_mm(XGE_ERR, "mempool allocation failure"); + return NULL; + } + xge_os_memzero(mempool, sizeof(xge_hal_mempool_t)); + + mempool->pdev = pdev; + mempool->memblock_size = memblock_size; + mempool->items_max = items_max; + mempool->items_initial = items_initial; + mempool->item_size = item_size; + mempool->items_priv_size = items_priv_size; + mempool->item_func_alloc = item_func_alloc; + mempool->item_func_free = item_func_free; + mempool->userdata = userdata; + + mempool->memblocks_allocated = 0; + + mempool->items_per_memblock = memblock_size / item_size; + + mempool->memblocks_max = (items_max + mempool->items_per_memblock - 1) / + mempool->items_per_memblock; + + /* allocate array of memblocks */ + mempool->memblocks_arr = (void ** ) xge_os_malloc(mempool->pdev, + sizeof(void*) * mempool->memblocks_max); + if (mempool->memblocks_arr == NULL) { + xge_debug_mm(XGE_ERR, "memblocks_arr allocation failure"); + __hal_mempool_destroy(mempool); + return NULL; + } + xge_os_memzero(mempool->memblocks_arr, + sizeof(void*) * mempool->memblocks_max); + + /* allocate array of private parts of items per memblocks */ + mempool->memblocks_priv_arr = (void **) xge_os_malloc(mempool->pdev, + sizeof(void*) * mempool->memblocks_max); + if (mempool->memblocks_priv_arr == NULL) { + xge_debug_mm(XGE_ERR, "memblocks_priv_arr allocation failure"); + __hal_mempool_destroy(mempool); + return NULL; + } + xge_os_memzero(mempool->memblocks_priv_arr, + sizeof(void*) * mempool->memblocks_max); + + /* allocate array of memblocks DMA objects */ + mempool->memblocks_dma_arr = + (xge_hal_mempool_dma_t *) xge_os_malloc(mempool->pdev, + sizeof(xge_hal_mempool_dma_t) * mempool->memblocks_max); + + if (mempool->memblocks_dma_arr == NULL) { + xge_debug_mm(XGE_ERR, "memblocks_dma_arr allocation failure"); + __hal_mempool_destroy(mempool); + return NULL; + } + xge_os_memzero(mempool->memblocks_dma_arr, + sizeof(xge_hal_mempool_dma_t) * mempool->memblocks_max); + + /* allocate hash array of items */ + mempool->items_arr = (void **) xge_os_malloc(mempool->pdev, + sizeof(void*) * mempool->items_max); + if (mempool->items_arr == NULL) { + xge_debug_mm(XGE_ERR, "items_arr allocation failure"); + __hal_mempool_destroy(mempool); + return NULL; + } + xge_os_memzero(mempool->items_arr, sizeof(void *) * mempool->items_max); + + mempool->shadow_items_arr = (void **) xge_os_malloc(mempool->pdev, + sizeof(void*) * mempool->items_max); + if (mempool->shadow_items_arr == NULL) { + xge_debug_mm(XGE_ERR, "shadow_items_arr allocation failure"); + __hal_mempool_destroy(mempool); + return NULL; + } + xge_os_memzero(mempool->shadow_items_arr, + sizeof(void *) * mempool->items_max); + + /* calculate initial number of memblocks */ + memblocks_to_allocate = (mempool->items_initial + + mempool->items_per_memblock - 1) / + mempool->items_per_memblock; + + xge_debug_mm(XGE_TRACE, "allocating %d memblocks, " + "%d items per memblock", memblocks_to_allocate, + mempool->items_per_memblock); + + /* pre-allocate the mempool */ + status = __hal_mempool_grow(mempool, memblocks_to_allocate, &allocated); + xge_os_memcpy(mempool->shadow_items_arr, mempool->items_arr, + sizeof(void*) * mempool->items_max); + if (status != XGE_HAL_OK) { + xge_debug_mm(XGE_ERR, "mempool_grow failure"); + __hal_mempool_destroy(mempool); + return NULL; + } + + xge_debug_mm(XGE_TRACE, + "total: allocated %dk of DMA-capable memory", + mempool->memblock_size * allocated / 1024); + + return mempool; +} + +/* + * xge_hal_mempool_destroy + */ +void +__hal_mempool_destroy(xge_hal_mempool_t *mempool) +{ + int i, j; + + for (i=0; i<mempool->memblocks_allocated; i++) { + xge_hal_mempool_dma_t *dma_object; + + xge_assert(mempool->memblocks_arr[i]); + xge_assert(mempool->memblocks_dma_arr + i); + + dma_object = mempool->memblocks_dma_arr + i; + + for (j=0; j<mempool->items_per_memblock; j++) { + int index = i*mempool->items_per_memblock + j; + + /* to skip last partially filled(if any) memblock */ + if (index >= mempool->items_current) { + break; + } + + /* let caller to do more job on each item */ + if (mempool->item_func_free != NULL) { + + mempool->item_func_free(mempool, + mempool->memblocks_arr[i], + i, dma_object, + mempool->shadow_items_arr[index], + index, /* unused */ -1, + mempool->userdata); + } + } + + xge_os_dma_unmap(mempool->pdev, + dma_object->handle, dma_object->addr, + mempool->memblock_size, XGE_OS_DMA_DIR_BIDIRECTIONAL); + + xge_os_free(mempool->pdev, mempool->memblocks_priv_arr[i], + mempool->items_priv_size * mempool->items_per_memblock); + + xge_os_dma_free(mempool->pdev, mempool->memblocks_arr[i], + mempool->memblock_size, &dma_object->acc_handle, + &dma_object->handle); + } + + if (mempool->items_arr) { + xge_os_free(mempool->pdev, mempool->items_arr, sizeof(void*) * + mempool->items_max); + } + + if (mempool->shadow_items_arr) { + xge_os_free(mempool->pdev, mempool->shadow_items_arr, + sizeof(void*) * mempool->items_max); + } + + if (mempool->memblocks_dma_arr) { + xge_os_free(mempool->pdev, mempool->memblocks_dma_arr, + sizeof(xge_hal_mempool_dma_t) * + mempool->memblocks_max); + } + + if (mempool->memblocks_priv_arr) { + xge_os_free(mempool->pdev, mempool->memblocks_priv_arr, + sizeof(void*) * mempool->memblocks_max); + } + + if (mempool->memblocks_arr) { + xge_os_free(mempool->pdev, mempool->memblocks_arr, + sizeof(void*) * mempool->memblocks_max); + } + + xge_os_free(mempool->pdev, mempool, sizeof(xge_hal_mempool_t)); +} diff --git a/sys/dev/nxge/xgehal/xgehal-ring-fp.c b/sys/dev/nxge/xgehal/xgehal-ring-fp.c new file mode 100644 index 0000000..9d5a09e --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-ring-fp.c @@ -0,0 +1,852 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-ring-fp.c + * + * Description: HAL Rx ring object functionality (fast path) + * + * Created: 10 June 2004 + */ + +#ifdef XGE_DEBUG_FP +#include <dev/nxge/include/xgehal-ring.h> +#endif + +__HAL_STATIC_RING __HAL_INLINE_RING xge_hal_ring_rxd_priv_t* +__hal_ring_rxd_priv(xge_hal_ring_t *ring, xge_hal_dtr_h dtrh) +{ + + xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh; + xge_hal_ring_rxd_priv_t *rxd_priv; + + xge_assert(rxdp); + +#if defined(XGE_HAL_USE_5B_MODE) + xge_assert(ring); + if (ring->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_5) { + xge_hal_ring_rxd_5_t *rxdp_5 = (xge_hal_ring_rxd_5_t *)dtrh; +#if defined (XGE_OS_PLATFORM_64BIT) + int memblock_idx = rxdp_5->host_control >> 16; + int i = rxdp_5->host_control & 0xFFFF; + rxd_priv = (xge_hal_ring_rxd_priv_t *) + ((char*)ring->mempool->memblocks_priv_arr[memblock_idx] + ring->rxd_priv_size * i); +#else + /* 32-bit case */ + rxd_priv = (xge_hal_ring_rxd_priv_t *)rxdp_5->host_control; +#endif + } else +#endif + { + rxd_priv = (xge_hal_ring_rxd_priv_t *) + (ulong_t)rxdp->host_control; + } + + xge_assert(rxd_priv); + xge_assert(rxd_priv->dma_object); + + xge_assert(rxd_priv->dma_object->handle == rxd_priv->dma_handle); + + xge_assert(rxd_priv->dma_object->addr + rxd_priv->dma_offset == + rxd_priv->dma_addr); + + return rxd_priv; +} + +__HAL_STATIC_RING __HAL_INLINE_RING int +__hal_ring_block_memblock_idx(xge_hal_ring_block_t *block) +{ + return (int)*((u64 *)(void *)((char *)block + + XGE_HAL_RING_MEMBLOCK_IDX_OFFSET)); +} + +__HAL_STATIC_RING __HAL_INLINE_RING void +__hal_ring_block_memblock_idx_set(xge_hal_ring_block_t*block, int memblock_idx) +{ + *((u64 *)(void *)((char *)block + + XGE_HAL_RING_MEMBLOCK_IDX_OFFSET)) = + memblock_idx; +} + + +__HAL_STATIC_RING __HAL_INLINE_RING dma_addr_t +__hal_ring_block_next_pointer(xge_hal_ring_block_t *block) +{ + return (dma_addr_t)*((u64 *)(void *)((char *)block + + XGE_HAL_RING_NEXT_BLOCK_POINTER_OFFSET)); +} + +__HAL_STATIC_RING __HAL_INLINE_RING void +__hal_ring_block_next_pointer_set(xge_hal_ring_block_t *block, + dma_addr_t dma_next) +{ + *((u64 *)(void *)((char *)block + + XGE_HAL_RING_NEXT_BLOCK_POINTER_OFFSET)) = dma_next; +} + +/** + * xge_hal_ring_dtr_private - Get ULD private per-descriptor data. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * + * Returns: private ULD info associated with the descriptor. + * ULD requests per-descriptor space via xge_hal_channel_open(). + * + * See also: xge_hal_fifo_dtr_private(). + * Usage: See ex_rx_compl{}. + */ +__HAL_STATIC_RING __HAL_INLINE_RING void* +xge_hal_ring_dtr_private(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh) +{ + return (char *)__hal_ring_rxd_priv((xge_hal_ring_t *) channelh, dtrh) + + sizeof(xge_hal_ring_rxd_priv_t); +} + +/** + * xge_hal_ring_dtr_reserve - Reserve ring descriptor. + * @channelh: Channel handle. + * @dtrh: Reserved descriptor. On success HAL fills this "out" parameter + * with a valid handle. + * + * Reserve Rx descriptor for the subsequent filling-in (by upper layer + * driver (ULD)) and posting on the corresponding channel (@channelh) + * via xge_hal_ring_dtr_post(). + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available. + * + * See also: xge_hal_fifo_dtr_reserve(), xge_hal_ring_dtr_free(), + * xge_hal_fifo_dtr_reserve_sp(), xge_hal_status_e{}. + * Usage: See ex_post_all_rx{}. + */ +__HAL_STATIC_RING __HAL_INLINE_RING xge_hal_status_e +xge_hal_ring_dtr_reserve(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh) +{ + xge_hal_status_e status; +#if defined(XGE_HAL_RX_MULTI_RESERVE_IRQ) + unsigned long flags; +#endif + +#if defined(XGE_HAL_RX_MULTI_RESERVE) + xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->reserve_lock); +#elif defined(XGE_HAL_RX_MULTI_RESERVE_IRQ) + xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->reserve_lock, + flags); +#endif + + status = __hal_channel_dtr_alloc(channelh, dtrh); + +#if defined(XGE_HAL_RX_MULTI_RESERVE) + xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->reserve_lock); +#elif defined(XGE_HAL_RX_MULTI_RESERVE_IRQ) + xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->reserve_lock, + flags); +#endif + + if (status == XGE_HAL_OK) { + xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)*dtrh; + + /* instead of memset: reset this RxD */ + rxdp->control_1 = rxdp->control_2 = 0; + +#if defined(XGE_OS_MEMORY_CHECK) + __hal_ring_rxd_priv((xge_hal_ring_t *) channelh, rxdp)->allocated = 1; +#endif + } + + return status; +} + +/** + * xge_hal_ring_dtr_info_get - Get extended information associated with + * a completed receive descriptor for 1b mode. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * @ext_info: See xge_hal_dtr_info_t{}. Returned by HAL. + * + * Retrieve extended information associated with a completed receive descriptor. + * + * See also: xge_hal_dtr_info_t{}, xge_hal_ring_dtr_1b_get(), + * xge_hal_ring_dtr_5b_get(). + */ +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_info_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + xge_hal_dtr_info_t *ext_info) +{ + /* cast to 1-buffer mode RxD: the code below relies on the fact + * that control_1 and control_2 are formatted the same way.. */ + xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh; + + ext_info->l3_cksum = XGE_HAL_RXD_GET_L3_CKSUM(rxdp->control_1); + ext_info->l4_cksum = XGE_HAL_RXD_GET_L4_CKSUM(rxdp->control_1); + ext_info->frame = XGE_HAL_RXD_GET_FRAME_TYPE(rxdp->control_1); + ext_info->proto = XGE_HAL_RXD_GET_FRAME_PROTO(rxdp->control_1); + ext_info->vlan = XGE_HAL_RXD_GET_VLAN_TAG(rxdp->control_2); + + /* Herc only, a few extra cycles imposed on Xena and/or + * when RTH is not enabled. + * Alternatively, could check + * xge_hal_device_check_id(), hldev->config.rth_en, queue->rth_en */ + ext_info->rth_it_hit = XGE_HAL_RXD_GET_RTH_IT_HIT(rxdp->control_1); + ext_info->rth_spdm_hit = + XGE_HAL_RXD_GET_RTH_SPDM_HIT(rxdp->control_1); + ext_info->rth_hash_type = + XGE_HAL_RXD_GET_RTH_HASH_TYPE(rxdp->control_1); + ext_info->rth_value = XGE_HAL_RXD_1_GET_RTH_VALUE(rxdp->control_2); +} + +/** + * xge_hal_ring_dtr_info_nb_get - Get extended information associated + * with a completed receive descriptor for 3b or 5b + * modes. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * @ext_info: See xge_hal_dtr_info_t{}. Returned by HAL. + * + * Retrieve extended information associated with a completed receive descriptor. + * + * See also: xge_hal_dtr_info_t{}, xge_hal_ring_dtr_1b_get(), + * xge_hal_ring_dtr_5b_get(). + */ +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_info_nb_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + xge_hal_dtr_info_t *ext_info) +{ + /* cast to 1-buffer mode RxD: the code below relies on the fact + * that control_1 and control_2 are formatted the same way.. */ + xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh; + + ext_info->l3_cksum = XGE_HAL_RXD_GET_L3_CKSUM(rxdp->control_1); + ext_info->l4_cksum = XGE_HAL_RXD_GET_L4_CKSUM(rxdp->control_1); + ext_info->frame = XGE_HAL_RXD_GET_FRAME_TYPE(rxdp->control_1); + ext_info->proto = XGE_HAL_RXD_GET_FRAME_PROTO(rxdp->control_1); + ext_info->vlan = XGE_HAL_RXD_GET_VLAN_TAG(rxdp->control_2); + /* Herc only, a few extra cycles imposed on Xena and/or + * when RTH is not enabled. Same comment as above. */ + ext_info->rth_it_hit = XGE_HAL_RXD_GET_RTH_IT_HIT(rxdp->control_1); + ext_info->rth_spdm_hit = + XGE_HAL_RXD_GET_RTH_SPDM_HIT(rxdp->control_1); + ext_info->rth_hash_type = + XGE_HAL_RXD_GET_RTH_HASH_TYPE(rxdp->control_1); + ext_info->rth_value = (u32)rxdp->buffer0_ptr; +} + +/** + * xge_hal_ring_dtr_1b_set - Prepare 1-buffer-mode descriptor. + * @dtrh: Descriptor handle. + * @dma_pointer: DMA address of a single receive buffer this descriptor + * should carry. Note that by the time + * xge_hal_ring_dtr_1b_set + * is called, the receive buffer should be already mapped + * to the corresponding Xframe device. + * @size: Size of the receive @dma_pointer buffer. + * + * Prepare 1-buffer-mode Rx descriptor for posting + * (via xge_hal_ring_dtr_post()). + * + * This inline helper-function does not return any parameters and always + * succeeds. + * + * See also: xge_hal_ring_dtr_3b_set(), xge_hal_ring_dtr_5b_set(). + * Usage: See ex_post_all_rx{}. + */ +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_1b_set(xge_hal_dtr_h dtrh, dma_addr_t dma_pointer, int size) +{ + xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh; + rxdp->buffer0_ptr = dma_pointer; + rxdp->control_2 &= (~XGE_HAL_RXD_1_MASK_BUFFER0_SIZE); + rxdp->control_2 |= XGE_HAL_RXD_1_SET_BUFFER0_SIZE(size); + + xge_debug_ring(XGE_TRACE, "xge_hal_ring_dtr_1b_set: rxdp %p control_2 %p buffer0_ptr %p", + (xge_hal_ring_rxd_1_t *)dtrh, + rxdp->control_2, + rxdp->buffer0_ptr); +} + +/** + * xge_hal_ring_dtr_1b_get - Get data from the completed 1-buf + * descriptor. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * @dma_pointer: DMA address of a single receive buffer _this_ descriptor + * carries. Returned by HAL. + * @pkt_length: Length (in bytes) of the data in the buffer pointed by + * @dma_pointer. Returned by HAL. + * + * Retrieve protocol data from the completed 1-buffer-mode Rx descriptor. + * This inline helper-function uses completed descriptor to populate receive + * buffer pointer and other "out" parameters. The function always succeeds. + * + * See also: xge_hal_ring_dtr_3b_get(), xge_hal_ring_dtr_5b_get(). + * Usage: See ex_rx_compl{}. + */ +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_1b_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + dma_addr_t *dma_pointer, int *pkt_length) +{ + xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh; + + *pkt_length = XGE_HAL_RXD_1_GET_BUFFER0_SIZE(rxdp->control_2); + *dma_pointer = rxdp->buffer0_ptr; + + ((xge_hal_channel_t *)channelh)->poll_bytes += *pkt_length; +} + +/** + * xge_hal_ring_dtr_3b_set - Prepare 3-buffer-mode descriptor. + * @dtrh: Descriptor handle. + * @dma_pointers: Array of DMA addresses. Contains exactly 3 receive buffers + * _this_ descriptor should carry. + * Note that by the time xge_hal_ring_dtr_3b_set + * is called, the receive buffers should be mapped + * to the corresponding Xframe device. + * @sizes: Array of receive buffer sizes. Contains 3 sizes: one size per + * buffer from @dma_pointers. + * + * Prepare 3-buffer-mode Rx descriptor for posting (via + * xge_hal_ring_dtr_post()). + * This inline helper-function does not return any parameters and always + * succeeds. + * + * See also: xge_hal_ring_dtr_1b_set(), xge_hal_ring_dtr_5b_set(). + */ +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_3b_set(xge_hal_dtr_h dtrh, dma_addr_t dma_pointers[], + int sizes[]) +{ + xge_hal_ring_rxd_3_t *rxdp = (xge_hal_ring_rxd_3_t *)dtrh; + rxdp->buffer0_ptr = dma_pointers[0]; + rxdp->control_2 &= (~XGE_HAL_RXD_3_MASK_BUFFER0_SIZE); + rxdp->control_2 |= XGE_HAL_RXD_3_SET_BUFFER0_SIZE(sizes[0]); + rxdp->buffer1_ptr = dma_pointers[1]; + rxdp->control_2 &= (~XGE_HAL_RXD_3_MASK_BUFFER1_SIZE); + rxdp->control_2 |= XGE_HAL_RXD_3_SET_BUFFER1_SIZE(sizes[1]); + rxdp->buffer2_ptr = dma_pointers[2]; + rxdp->control_2 &= (~XGE_HAL_RXD_3_MASK_BUFFER2_SIZE); + rxdp->control_2 |= XGE_HAL_RXD_3_SET_BUFFER2_SIZE(sizes[2]); +} + +/** + * xge_hal_ring_dtr_3b_get - Get data from the completed 3-buf + * descriptor. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * @dma_pointers: DMA addresses of the 3 receive buffers _this_ descriptor + * carries. The first two buffers contain ethernet and + * (IP + transport) headers. The 3rd buffer contains packet + * data. + * Returned by HAL. + * @sizes: Array of receive buffer sizes. Contains 3 sizes: one size per + * buffer from @dma_pointers. Returned by HAL. + * + * Retrieve protocol data from the completed 3-buffer-mode Rx descriptor. + * This inline helper-function uses completed descriptor to populate receive + * buffer pointer and other "out" parameters. The function always succeeds. + * + * See also: xge_hal_ring_dtr_3b_get(), xge_hal_ring_dtr_5b_get(). + */ +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_3b_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + dma_addr_t dma_pointers[], int sizes[]) +{ + xge_hal_ring_rxd_3_t *rxdp = (xge_hal_ring_rxd_3_t *)dtrh; + + dma_pointers[0] = rxdp->buffer0_ptr; + sizes[0] = XGE_HAL_RXD_3_GET_BUFFER0_SIZE(rxdp->control_2); + + dma_pointers[1] = rxdp->buffer1_ptr; + sizes[1] = XGE_HAL_RXD_3_GET_BUFFER1_SIZE(rxdp->control_2); + + dma_pointers[2] = rxdp->buffer2_ptr; + sizes[2] = XGE_HAL_RXD_3_GET_BUFFER2_SIZE(rxdp->control_2); + + ((xge_hal_channel_t *)channelh)->poll_bytes += sizes[0] + sizes[1] + + sizes[2]; +} + +/** + * xge_hal_ring_dtr_5b_set - Prepare 5-buffer-mode descriptor. + * @dtrh: Descriptor handle. + * @dma_pointers: Array of DMA addresses. Contains exactly 5 receive buffers + * _this_ descriptor should carry. + * Note that by the time xge_hal_ring_dtr_5b_set + * is called, the receive buffers should be mapped + * to the corresponding Xframe device. + * @sizes: Array of receive buffer sizes. Contains 5 sizes: one size per + * buffer from @dma_pointers. + * + * Prepare 3-buffer-mode Rx descriptor for posting (via + * xge_hal_ring_dtr_post()). + * This inline helper-function does not return any parameters and always + * succeeds. + * + * See also: xge_hal_ring_dtr_1b_set(), xge_hal_ring_dtr_3b_set(). + */ +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_5b_set(xge_hal_dtr_h dtrh, dma_addr_t dma_pointers[], + int sizes[]) +{ + xge_hal_ring_rxd_5_t *rxdp = (xge_hal_ring_rxd_5_t *)dtrh; + rxdp->buffer0_ptr = dma_pointers[0]; + rxdp->control_2 &= (~XGE_HAL_RXD_5_MASK_BUFFER0_SIZE); + rxdp->control_2 |= XGE_HAL_RXD_5_SET_BUFFER0_SIZE(sizes[0]); + rxdp->buffer1_ptr = dma_pointers[1]; + rxdp->control_2 &= (~XGE_HAL_RXD_5_MASK_BUFFER1_SIZE); + rxdp->control_2 |= XGE_HAL_RXD_5_SET_BUFFER1_SIZE(sizes[1]); + rxdp->buffer2_ptr = dma_pointers[2]; + rxdp->control_2 &= (~XGE_HAL_RXD_5_MASK_BUFFER2_SIZE); + rxdp->control_2 |= XGE_HAL_RXD_5_SET_BUFFER2_SIZE(sizes[2]); + rxdp->buffer3_ptr = dma_pointers[3]; + rxdp->control_3 &= (~XGE_HAL_RXD_5_MASK_BUFFER3_SIZE); + rxdp->control_3 |= XGE_HAL_RXD_5_SET_BUFFER3_SIZE(sizes[3]); + rxdp->buffer4_ptr = dma_pointers[4]; + rxdp->control_3 &= (~XGE_HAL_RXD_5_MASK_BUFFER4_SIZE); + rxdp->control_3 |= XGE_HAL_RXD_5_SET_BUFFER4_SIZE(sizes[4]); +} + +/** + * xge_hal_ring_dtr_5b_get - Get data from the completed 5-buf + * descriptor. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * @dma_pointers: DMA addresses of the 5 receive buffers _this_ descriptor + * carries. The first 4 buffers contains L2 (ethernet) through + * L5 headers. The 5th buffer contain received (applicaion) + * data. Returned by HAL. + * @sizes: Array of receive buffer sizes. Contains 5 sizes: one size per + * buffer from @dma_pointers. Returned by HAL. + * + * Retrieve protocol data from the completed 5-buffer-mode Rx descriptor. + * This inline helper-function uses completed descriptor to populate receive + * buffer pointer and other "out" parameters. The function always succeeds. + * + * See also: xge_hal_ring_dtr_3b_get(), xge_hal_ring_dtr_5b_get(). + */ +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_5b_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, + dma_addr_t dma_pointers[], int sizes[]) +{ + xge_hal_ring_rxd_5_t *rxdp = (xge_hal_ring_rxd_5_t *)dtrh; + + dma_pointers[0] = rxdp->buffer0_ptr; + sizes[0] = XGE_HAL_RXD_5_GET_BUFFER0_SIZE(rxdp->control_2); + + dma_pointers[1] = rxdp->buffer1_ptr; + sizes[1] = XGE_HAL_RXD_5_GET_BUFFER1_SIZE(rxdp->control_2); + + dma_pointers[2] = rxdp->buffer2_ptr; + sizes[2] = XGE_HAL_RXD_5_GET_BUFFER2_SIZE(rxdp->control_2); + + dma_pointers[3] = rxdp->buffer3_ptr; + sizes[3] = XGE_HAL_RXD_5_GET_BUFFER3_SIZE(rxdp->control_3); + + dma_pointers[4] = rxdp->buffer4_ptr; + sizes[4] = XGE_HAL_RXD_5_GET_BUFFER4_SIZE(rxdp->control_3); + + ((xge_hal_channel_t *)channelh)->poll_bytes += sizes[0] + sizes[1] + + sizes[2] + sizes[3] + sizes[4]; +} + + +/** + * xge_hal_ring_dtr_pre_post - FIXME. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * + * TBD + */ +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_pre_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh) +{ + xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh; +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING) + xge_hal_ring_rxd_priv_t *priv; + xge_hal_ring_t *ring = (xge_hal_ring_t *)channelh; +#endif +#if defined(XGE_HAL_RX_MULTI_POST_IRQ) + unsigned long flags; +#endif + + rxdp->control_2 |= XGE_HAL_RXD_NOT_COMPLETED; + +#ifdef XGE_DEBUG_ASSERT + /* make sure Xena overwrites the (illegal) t_code on completion */ + XGE_HAL_RXD_SET_T_CODE(rxdp->control_1, XGE_HAL_RXD_T_CODE_UNUSED_C); +#endif + + xge_debug_ring(XGE_TRACE, "xge_hal_ring_dtr_pre_post: rxd 0x"XGE_OS_LLXFMT" posted %d post_qid %d", + (unsigned long long)(ulong_t)dtrh, + ((xge_hal_ring_t *)channelh)->channel.post_index, + ((xge_hal_ring_t *)channelh)->channel.post_qid); + +#if defined(XGE_HAL_RX_MULTI_POST) + xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->post_lock); +#elif defined(XGE_HAL_RX_MULTI_POST_IRQ) + xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->post_lock, + flags); +#endif + +#if defined(XGE_DEBUG_ASSERT) && defined(XGE_HAL_RING_ENFORCE_ORDER) + { + xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; + + if (channel->post_index != 0) { + xge_hal_dtr_h prev_dtrh; + xge_hal_ring_rxd_priv_t *rxdp_priv; + + rxdp_priv = __hal_ring_rxd_priv(channelh, rxdp); + prev_dtrh = channel->work_arr[channel->post_index - 1]; + + if (prev_dtrh != NULL && + (rxdp_priv->dma_offset & (~0xFFF)) != + rxdp_priv->dma_offset) { + xge_assert((char *)prev_dtrh + + ((xge_hal_ring_t*)channel)->rxd_size == dtrh); + } + } + } +#endif + + __hal_channel_dtr_post(channelh, dtrh); + +#if defined(XGE_HAL_RX_MULTI_POST) + xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->post_lock); +#elif defined(XGE_HAL_RX_MULTI_POST_IRQ) + xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->post_lock, + flags); +#endif +} + + +/** + * xge_hal_ring_dtr_post_post - FIXME. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * + * TBD + */ +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_post_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh) +{ + xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh; + xge_hal_ring_t *ring = (xge_hal_ring_t *)channelh; +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING) + xge_hal_ring_rxd_priv_t *priv; +#endif + /* do POST */ + rxdp->control_1 |= XGE_HAL_RXD_POSTED_4_XFRAME; + +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING) + priv = __hal_ring_rxd_priv(ring, rxdp); + xge_os_dma_sync(ring->channel.pdev, + priv->dma_handle, priv->dma_addr, + priv->dma_offset, ring->rxd_size, + XGE_OS_DMA_DIR_TODEVICE); +#endif + + xge_debug_ring(XGE_TRACE, "xge_hal_ring_dtr_post_post: rxdp %p control_1 %p", + (xge_hal_ring_rxd_1_t *)dtrh, + rxdp->control_1); + + if (ring->channel.usage_cnt > 0) + ring->channel.usage_cnt--; +} + +/** + * xge_hal_ring_dtr_post_post_wmb. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * + * Similar as xge_hal_ring_dtr_post_post, but in addition it does memory barrier. + */ +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_post_post_wmb(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh) +{ + xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh; + xge_hal_ring_t *ring = (xge_hal_ring_t *)channelh; +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING) + xge_hal_ring_rxd_priv_t *priv; +#endif + /* Do memory barrier before changing the ownership */ + xge_os_wmb(); + + /* do POST */ + rxdp->control_1 |= XGE_HAL_RXD_POSTED_4_XFRAME; + +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING) + priv = __hal_ring_rxd_priv(ring, rxdp); + xge_os_dma_sync(ring->channel.pdev, + priv->dma_handle, priv->dma_addr, + priv->dma_offset, ring->rxd_size, + XGE_OS_DMA_DIR_TODEVICE); +#endif + + if (ring->channel.usage_cnt > 0) + ring->channel.usage_cnt--; + + xge_debug_ring(XGE_TRACE, "xge_hal_ring_dtr_post_post_wmb: rxdp %p control_1 %p rxds_with_host %d", + (xge_hal_ring_rxd_1_t *)dtrh, + rxdp->control_1, ring->channel.usage_cnt); + +} + +/** + * xge_hal_ring_dtr_post - Post descriptor on the ring channel. + * @channelh: Channel handle. + * @dtrh: Descriptor obtained via xge_hal_ring_dtr_reserve(). + * + * Post descriptor on the 'ring' type channel. + * Prior to posting the descriptor should be filled in accordance with + * Host/Xframe interface specification for a given service (LL, etc.). + * + * See also: xge_hal_fifo_dtr_post_many(), xge_hal_fifo_dtr_post(). + * Usage: See ex_post_all_rx{}. + */ +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh) +{ + xge_hal_ring_dtr_pre_post(channelh, dtrh); + xge_hal_ring_dtr_post_post(channelh, dtrh); +} + +/** + * xge_hal_ring_dtr_next_completed - Get the _next_ completed + * descriptor. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. Returned by HAL. + * @t_code: Transfer code, as per Xframe User Guide, + * Receive Descriptor Format. Returned by HAL. + * + * Retrieve the _next_ completed descriptor. + * HAL uses channel callback (*xge_hal_channel_callback_f) to notifiy + * upper-layer driver (ULD) of new completed descriptors. After that + * the ULD can use xge_hal_ring_dtr_next_completed to retrieve the rest + * completions (the very first completion is passed by HAL via + * xge_hal_channel_callback_f). + * + * Implementation-wise, the upper-layer driver is free to call + * xge_hal_ring_dtr_next_completed either immediately from inside the + * channel callback, or in a deferred fashion and separate (from HAL) + * context. + * + * Non-zero @t_code means failure to fill-in receive buffer(s) + * of the descriptor. + * For instance, parity error detected during the data transfer. + * In this case Xframe will complete the descriptor and indicate + * for the host that the received data is not to be used. + * For details please refer to Xframe User Guide. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed descriptors + * are currently available for processing. + * + * See also: xge_hal_channel_callback_f{}, + * xge_hal_fifo_dtr_next_completed(), xge_hal_status_e{}. + * Usage: See ex_rx_compl{}. + */ +__HAL_STATIC_RING __HAL_INLINE_RING xge_hal_status_e +xge_hal_ring_dtr_next_completed(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh, + u8 *t_code) +{ + xge_hal_ring_rxd_1_t *rxdp; /* doesn't matter 1, 3 or 5... */ + xge_hal_ring_t *ring = (xge_hal_ring_t *)channelh; +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING) + xge_hal_ring_rxd_priv_t *priv; +#endif + + __hal_channel_dtr_try_complete(ring, dtrh); + rxdp = (xge_hal_ring_rxd_1_t *)*dtrh; + if (rxdp == NULL) { + return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS; + } + +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING) + /* Note: 24 bytes at most means: + * - Control_3 in case of 5-buffer mode + * - Control_1 and Control_2 + * + * This is the only length needs to be invalidated + * type of channels.*/ + priv = __hal_ring_rxd_priv(ring, rxdp); + xge_os_dma_sync(ring->channel.pdev, + priv->dma_handle, priv->dma_addr, + priv->dma_offset, 24, + XGE_OS_DMA_DIR_FROMDEVICE); +#endif + + /* check whether it is not the end */ + if (!(rxdp->control_2 & XGE_HAL_RXD_NOT_COMPLETED) && + !(rxdp->control_1 & XGE_HAL_RXD_POSTED_4_XFRAME)) { +#ifndef XGE_HAL_IRQ_POLLING + if (++ring->cmpl_cnt > ring->indicate_max_pkts) { + /* reset it. since we don't want to return + * garbage to the ULD */ + *dtrh = 0; + return XGE_HAL_COMPLETIONS_REMAIN; + } +#endif + +#ifdef XGE_DEBUG_ASSERT +#if defined(XGE_HAL_USE_5B_MODE) +#if !defined(XGE_OS_PLATFORM_64BIT) + if (ring->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_5) { + xge_assert(((xge_hal_ring_rxd_5_t *) + rxdp)->host_control!=0); + } +#endif + +#else + xge_assert(rxdp->host_control!=0); +#endif +#endif + + __hal_channel_dtr_complete(ring); + + *t_code = (u8)XGE_HAL_RXD_GET_T_CODE(rxdp->control_1); + + /* see XGE_HAL_SET_RXD_T_CODE() above.. */ + xge_assert(*t_code != XGE_HAL_RXD_T_CODE_UNUSED_C); + + xge_debug_ring(XGE_TRACE, + "compl_index %d post_qid %d t_code %d rxd 0x"XGE_OS_LLXFMT, + ((xge_hal_channel_t*)ring)->compl_index, + ((xge_hal_channel_t*)ring)->post_qid, *t_code, + (unsigned long long)(ulong_t)rxdp); + + ring->channel.usage_cnt++; + if (ring->channel.stats.usage_max < ring->channel.usage_cnt) + ring->channel.stats.usage_max = ring->channel.usage_cnt; + + return XGE_HAL_OK; + } + + /* reset it. since we don't want to return + * garbage to the ULD */ + *dtrh = 0; + return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS; +} + +/** + * xge_hal_ring_dtr_free - Free descriptor. + * @channelh: Channel handle. + * @dtrh: Descriptor handle. + * + * Free the reserved descriptor. This operation is "symmetrical" to + * xge_hal_ring_dtr_reserve. The "free-ing" completes the descriptor's + * lifecycle. + * + * After free-ing (see xge_hal_ring_dtr_free()) the descriptor again can + * be: + * + * - reserved (xge_hal_ring_dtr_reserve); + * + * - posted (xge_hal_ring_dtr_post); + * + * - completed (xge_hal_ring_dtr_next_completed); + * + * - and recycled again (xge_hal_ring_dtr_free). + * + * For alternative state transitions and more details please refer to + * the design doc. + * + * See also: xge_hal_ring_dtr_reserve(), xge_hal_fifo_dtr_free(). + * Usage: See ex_rx_compl{}. + */ +__HAL_STATIC_RING __HAL_INLINE_RING void +xge_hal_ring_dtr_free(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh) +{ +#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) + unsigned long flags; +#endif + +#if defined(XGE_HAL_RX_MULTI_FREE) + xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->free_lock); +#elif defined(XGE_HAL_RX_MULTI_FREE_IRQ) + xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->free_lock, + flags); +#endif + + __hal_channel_dtr_free(channelh, dtrh); +#if defined(XGE_OS_MEMORY_CHECK) + __hal_ring_rxd_priv((xge_hal_ring_t * ) channelh, dtrh)->allocated = 0; +#endif + +#if defined(XGE_HAL_RX_MULTI_FREE) + xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->free_lock); +#elif defined(XGE_HAL_RX_MULTI_FREE_IRQ) + xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->free_lock, + flags); +#endif +} + +/** + * xge_hal_ring_is_next_dtr_completed - Check if the next dtr is completed + * @channelh: Channel handle. + * + * Checks if the the _next_ completed descriptor is in host memory + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed descriptors + * are currently available for processing. + */ +__HAL_STATIC_RING __HAL_INLINE_RING xge_hal_status_e +xge_hal_ring_is_next_dtr_completed(xge_hal_channel_h channelh) +{ + xge_hal_ring_rxd_1_t *rxdp; /* doesn't matter 1, 3 or 5... */ + xge_hal_ring_t *ring = (xge_hal_ring_t *)channelh; + xge_hal_dtr_h dtrh; + + __hal_channel_dtr_try_complete(ring, &dtrh); + rxdp = (xge_hal_ring_rxd_1_t *)dtrh; + if (rxdp == NULL) { + return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS; + } + + /* check whether it is not the end */ + if (!(rxdp->control_2 & XGE_HAL_RXD_NOT_COMPLETED) && + !(rxdp->control_1 & XGE_HAL_RXD_POSTED_4_XFRAME)) { + +#ifdef XGE_DEBUG_ASSERT +#if defined(XGE_HAL_USE_5B_MODE) +#if !defined(XGE_OS_PLATFORM_64BIT) + if (ring->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_5) { + xge_assert(((xge_hal_ring_rxd_5_t *) + rxdp)->host_control!=0); + } +#endif + +#else + xge_assert(rxdp->host_control!=0); +#endif +#endif + return XGE_HAL_OK; + } + + return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS; +} diff --git a/sys/dev/nxge/xgehal/xgehal-ring.c b/sys/dev/nxge/xgehal/xgehal-ring.c new file mode 100644 index 0000000..84e8f9b --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-ring.c @@ -0,0 +1,669 @@ +/*- + * 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$ + */ + +/* + * FileName : hal-ring.c + * + * Description: Rx ring object implementation + * + * Created: 10 May 2004 + */ + +#include <dev/nxge/include/xgehal-ring.h> +#include <dev/nxge/include/xgehal-device.h> + +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING) +static ptrdiff_t +__hal_ring_item_dma_offset(xge_hal_mempool_h mempoolh, + void *item) +{ + int memblock_idx; + void *memblock; + + /* get owner memblock index */ + memblock_idx = __hal_ring_block_memblock_idx(item); + + /* get owner memblock by memblock index */ + memblock = __hal_mempool_memblock(mempoolh, memblock_idx); + + return (char*)item - (char*)memblock; +} +#endif + +static dma_addr_t +__hal_ring_item_dma_addr(xge_hal_mempool_h mempoolh, void *item, + pci_dma_h *dma_handle) +{ + int memblock_idx; + void *memblock; + xge_hal_mempool_dma_t *memblock_dma_object; + ptrdiff_t dma_item_offset; + + /* get owner memblock index */ + memblock_idx = __hal_ring_block_memblock_idx((xge_hal_ring_block_t *) item); + + /* get owner memblock by memblock index */ + memblock = __hal_mempool_memblock((xge_hal_mempool_t *) mempoolh, + memblock_idx); + + /* get memblock DMA object by memblock index */ + memblock_dma_object = + __hal_mempool_memblock_dma((xge_hal_mempool_t *) mempoolh, + memblock_idx); + + /* calculate offset in the memblock of this item */ + dma_item_offset = (char*)item - (char*)memblock; + + *dma_handle = memblock_dma_object->handle; + + return memblock_dma_object->addr + dma_item_offset; +} + +static void +__hal_ring_rxdblock_link(xge_hal_mempool_h mempoolh, + xge_hal_ring_t *ring, int from, int to) +{ + xge_hal_ring_block_t *to_item, *from_item; + dma_addr_t to_dma, from_dma; + pci_dma_h to_dma_handle, from_dma_handle; + + /* get "from" RxD block */ + from_item = (xge_hal_ring_block_t *) + __hal_mempool_item((xge_hal_mempool_t *) mempoolh, from); + xge_assert(from_item); + + /* get "to" RxD block */ + to_item = (xge_hal_ring_block_t *) + __hal_mempool_item((xge_hal_mempool_t *) mempoolh, to); + xge_assert(to_item); + + /* return address of the beginning of previous RxD block */ + to_dma = __hal_ring_item_dma_addr(mempoolh, to_item, &to_dma_handle); + + /* set next pointer for this RxD block to point on + * previous item's DMA start address */ + __hal_ring_block_next_pointer_set(from_item, to_dma); + + /* return "from" RxD block's DMA start address */ + from_dma = + __hal_ring_item_dma_addr(mempoolh, from_item, &from_dma_handle); + +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING) + /* we must sync "from" RxD block, so hardware will see it */ + xge_os_dma_sync(ring->channel.pdev, + from_dma_handle, + from_dma + XGE_HAL_RING_NEXT_BLOCK_POINTER_OFFSET, + __hal_ring_item_dma_offset(mempoolh, from_item) + + XGE_HAL_RING_NEXT_BLOCK_POINTER_OFFSET, + sizeof(u64), + XGE_OS_DMA_DIR_TODEVICE); +#endif + + xge_debug_ring(XGE_TRACE, "block%d:0x"XGE_OS_LLXFMT" => block%d:0x"XGE_OS_LLXFMT, + from, (unsigned long long)from_dma, to, + (unsigned long long)to_dma); +} + +static xge_hal_status_e +__hal_ring_mempool_item_alloc(xge_hal_mempool_h mempoolh, + void *memblock, + int memblock_index, + xge_hal_mempool_dma_t *dma_object, + void *item, + int index, + int is_last, + void *userdata) +{ + int i; + xge_hal_ring_t *ring = (xge_hal_ring_t *)userdata; + + xge_assert(item); + xge_assert(ring); + + + /* format rxds array */ + for (i=ring->rxds_per_block-1; i>=0; i--) { + void *rxdblock_priv; + xge_hal_ring_rxd_priv_t *rxd_priv; + xge_hal_ring_rxd_1_t *rxdp; + int reserve_index = index * ring->rxds_per_block + i; + int memblock_item_idx; + + ring->reserved_rxds_arr[reserve_index] = (char *)item + + (ring->rxds_per_block - 1 - i) * ring->rxd_size; + + /* Note: memblock_item_idx is index of the item within + * the memblock. For instance, in case of three RxD-blocks + * per memblock this value can be 0,1 or 2. */ + rxdblock_priv = + __hal_mempool_item_priv((xge_hal_mempool_t *) mempoolh, + memblock_index, item, + &memblock_item_idx); + rxdp = (xge_hal_ring_rxd_1_t *) + ring->reserved_rxds_arr[reserve_index]; + rxd_priv = (xge_hal_ring_rxd_priv_t *) (void *) + ((char*)rxdblock_priv + ring->rxd_priv_size * i); + + /* pre-format per-RxD Ring's private */ + rxd_priv->dma_offset = (char*)rxdp - (char*)memblock; + rxd_priv->dma_addr = dma_object->addr + rxd_priv->dma_offset; + rxd_priv->dma_handle = dma_object->handle; +#ifdef XGE_DEBUG_ASSERT + rxd_priv->dma_object = dma_object; +#endif + + /* pre-format Host_Control */ +#if defined(XGE_HAL_USE_5B_MODE) + if (ring->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_5) { + xge_hal_ring_rxd_5_t *rxdp_5 = (xge_hal_ring_rxd_5_t *)rxdp; +#if defined(XGE_OS_PLATFORM_64BIT) + xge_assert(memblock_index <= 0xFFFF); + xge_assert(i <= 0xFFFF); + /* store memblock's index */ + rxdp_5->host_control = (u32)memblock_index << 16; + /* store index of memblock's private */ + rxdp_5->host_control |= (u32)(memblock_item_idx * + ring->rxds_per_block + i); +#else + /* 32-bit case */ + rxdp_5->host_control = (u32)rxd_priv; +#endif + } else { + /* 1b and 3b modes */ + rxdp->host_control = (u64)(ulong_t)rxd_priv; + } +#else + /* 1b and 3b modes */ + rxdp->host_control = (u64)(ulong_t)rxd_priv; +#endif + } + + __hal_ring_block_memblock_idx_set((xge_hal_ring_block_t *) item, memblock_index); + + if (is_last) { + /* link last one with first one */ + __hal_ring_rxdblock_link(mempoolh, ring, 0, index); + } + + if (index > 0 ) { + /* link this RxD block with previous one */ + __hal_ring_rxdblock_link(mempoolh, ring, index, index-1); + } + + return XGE_HAL_OK; +} + + xge_hal_status_e +__hal_ring_initial_replenish(xge_hal_channel_t *channel, + xge_hal_channel_reopen_e reopen) +{ + xge_hal_dtr_h dtr; + + while (xge_hal_channel_dtr_count(channel) > 0) { + xge_hal_status_e status; + + status = xge_hal_ring_dtr_reserve(channel, &dtr); + xge_assert(status == XGE_HAL_OK); + + if (channel->dtr_init) { + status = channel->dtr_init(channel, + dtr, channel->reserve_length, + channel->userdata, + reopen); + if (status != XGE_HAL_OK) { + xge_hal_ring_dtr_free(channel, dtr); + xge_hal_channel_abort(channel, + XGE_HAL_CHANNEL_OC_NORMAL); + return status; + } + } + + xge_hal_ring_dtr_post(channel, dtr); + } + + return XGE_HAL_OK; +} + +xge_hal_status_e +__hal_ring_open(xge_hal_channel_h channelh, xge_hal_channel_attr_t *attr) +{ + xge_hal_status_e status; + xge_hal_device_t *hldev; + xge_hal_ring_t *ring = (xge_hal_ring_t *)channelh; + xge_hal_ring_queue_t *queue; + + + /* Note: at this point we have channel.devh and channel.pdev + * pre-set only! */ + + hldev = (xge_hal_device_t *)ring->channel.devh; + ring->config = &hldev->config.ring; + queue = &ring->config->queue[attr->post_qid]; + ring->indicate_max_pkts = queue->indicate_max_pkts; + ring->buffer_mode = queue->buffer_mode; + + xge_assert(queue->configured); + +#if defined(XGE_HAL_RX_MULTI_RESERVE) + xge_os_spin_lock_init(&ring->channel.reserve_lock, hldev->pdev); +#elif defined(XGE_HAL_RX_MULTI_RESERVE_IRQ) + xge_os_spin_lock_init_irq(&ring->channel.reserve_lock, hldev->irqh); +#endif +#if defined(XGE_HAL_RX_MULTI_POST) + xge_os_spin_lock_init(&ring->channel.post_lock, hldev->pdev); +#elif defined(XGE_HAL_RX_MULTI_POST_IRQ) + xge_os_spin_lock_init_irq(&ring->channel.post_lock, hldev->irqh); +#endif + + ring->rxd_size = XGE_HAL_RING_RXD_SIZEOF(queue->buffer_mode); + ring->rxd_priv_size = + sizeof(xge_hal_ring_rxd_priv_t) + attr->per_dtr_space; + + /* how many RxDs can fit into one block. Depends on configured + * buffer_mode. */ + ring->rxds_per_block = XGE_HAL_RING_RXDS_PER_BLOCK(queue->buffer_mode); + + /* calculate actual RxD block private size */ + ring->rxdblock_priv_size = ring->rxd_priv_size * ring->rxds_per_block; + + ring->reserved_rxds_arr = (void **) xge_os_malloc(ring->channel.pdev, + sizeof(void*) * queue->max * ring->rxds_per_block); + + if (ring->reserved_rxds_arr == NULL) { + __hal_ring_close(channelh); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + + ring->mempool = __hal_mempool_create( + hldev->pdev, + ring->config->memblock_size, + XGE_HAL_RING_RXDBLOCK_SIZE, + ring->rxdblock_priv_size, + queue->initial, queue->max, + __hal_ring_mempool_item_alloc, + NULL, /* nothing to free */ + ring); + if (ring->mempool == NULL) { + __hal_ring_close(channelh); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + + status = __hal_channel_initialize(channelh, + attr, + ring->reserved_rxds_arr, + queue->initial * ring->rxds_per_block, + queue->max * ring->rxds_per_block, + 0 /* no threshold for ring! */); + if (status != XGE_HAL_OK) { + __hal_ring_close(channelh); + return status; + } + + /* sanity check that everything formatted ok */ + xge_assert(ring->reserved_rxds_arr[0] == + (char *)ring->mempool->items_arr[0] + + (ring->rxds_per_block * ring->rxd_size - ring->rxd_size)); + + /* Note: + * Specifying dtr_init callback means two things: + * 1) dtrs need to be initialized by ULD at channel-open time; + * 2) dtrs need to be posted at channel-open time + * (that's what the initial_replenish() below does) + * Currently we don't have a case when the 1) is done without the 2). + */ + if (ring->channel.dtr_init) { + if ((status = __hal_ring_initial_replenish ( + (xge_hal_channel_t *) channelh, + XGE_HAL_CHANNEL_OC_NORMAL) ) + != XGE_HAL_OK) { + __hal_ring_close(channelh); + return status; + } + } + + /* initial replenish will increment the counter in its post() routine, + * we have to reset it */ + ring->channel.usage_cnt = 0; + + return XGE_HAL_OK; +} + +void +__hal_ring_close(xge_hal_channel_h channelh) +{ + xge_hal_ring_t *ring = (xge_hal_ring_t *)channelh; + xge_hal_ring_queue_t *queue; +#if defined(XGE_HAL_RX_MULTI_RESERVE)||defined(XGE_HAL_RX_MULTI_RESERVE_IRQ)||\ + defined(XGE_HAL_RX_MULTI_POST) || defined(XGE_HAL_RX_MULTI_POST_IRQ) + xge_hal_device_t *hldev = (xge_hal_device_t *)ring->channel.devh; +#endif + + xge_assert(ring->channel.pdev); + + queue = &ring->config->queue[ring->channel.post_qid]; + + if (ring->mempool) { + __hal_mempool_destroy(ring->mempool); + } + + if (ring->reserved_rxds_arr) { + xge_os_free(ring->channel.pdev, + ring->reserved_rxds_arr, + sizeof(void*) * queue->max * ring->rxds_per_block); + } + + __hal_channel_terminate(channelh); + +#if defined(XGE_HAL_RX_MULTI_RESERVE) + xge_os_spin_lock_destroy(&ring->channel.reserve_lock, hldev->pdev); +#elif defined(XGE_HAL_RX_MULTI_RESERVE_IRQ) + xge_os_spin_lock_destroy_irq(&ring->channel.reserve_lock, hldev->pdev); +#endif +#if defined(XGE_HAL_RX_MULTI_POST) + xge_os_spin_lock_destroy(&ring->channel.post_lock, hldev->pdev); +#elif defined(XGE_HAL_RX_MULTI_POST_IRQ) + xge_os_spin_lock_destroy_irq(&ring->channel.post_lock, hldev->pdev); +#endif +} + +void +__hal_ring_prc_enable(xge_hal_channel_h channelh) +{ + xge_hal_ring_t *ring = (xge_hal_ring_t *)channelh; + xge_hal_device_t *hldev = (xge_hal_device_t *)ring->channel.devh; + xge_hal_pci_bar0_t *bar0; + u64 val64; + void *first_block; + int block_num; + xge_hal_ring_queue_t *queue; + pci_dma_h dma_handle; + + xge_assert(ring); + xge_assert(ring->channel.pdev); + bar0 = (xge_hal_pci_bar0_t *) (void *) + ((xge_hal_device_t *)ring->channel.devh)->bar0; + + queue = &ring->config->queue[ring->channel.post_qid]; + xge_assert(queue->buffer_mode == 1 || + queue->buffer_mode == 3 || + queue->buffer_mode == 5); + + /* last block in fact becomes first. This is just the way it + * is filled up and linked by item_alloc() */ + + block_num = queue->initial; + first_block = __hal_mempool_item(ring->mempool, block_num - 1); + val64 = __hal_ring_item_dma_addr(ring->mempool, + first_block, &dma_handle); + xge_os_pio_mem_write64(ring->channel.pdev, ring->channel.regh0, + val64, &bar0->prc_rxd0_n[ring->channel.post_qid]); + + xge_debug_ring(XGE_TRACE, "ring%d PRC DMA addr 0x"XGE_OS_LLXFMT" initialized", + ring->channel.post_qid, (unsigned long long)val64); + + val64 = xge_os_pio_mem_read64(ring->channel.pdev, + ring->channel.regh0, &bar0->prc_ctrl_n[ring->channel.post_qid]); + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC && + !queue->rth_en) { + val64 |= XGE_HAL_PRC_CTRL_RTH_DISABLE; + } + val64 |= XGE_HAL_PRC_CTRL_RC_ENABLED; + + val64 |= vBIT((queue->buffer_mode >> 1),14,2);/* 1,3 or 5 => 0,1 or 2 */ + val64 &= ~XGE_HAL_PRC_CTRL_RXD_BACKOFF_INTERVAL(0xFFFFFF); + val64 |= XGE_HAL_PRC_CTRL_RXD_BACKOFF_INTERVAL( + (hldev->config.pci_freq_mherz * queue->backoff_interval_us)); + + /* Beware: no snoop by the bridge if (no_snoop_bits) */ + val64 |= XGE_HAL_PRC_CTRL_NO_SNOOP(queue->no_snoop_bits); + + /* Herc: always use group_reads */ + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) + val64 |= XGE_HAL_PRC_CTRL_GROUP_READS; + + if (hldev->config.bimodal_interrupts) + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) + val64 |= XGE_HAL_PRC_CTRL_BIMODAL_INTERRUPT; + + xge_os_pio_mem_write64(ring->channel.pdev, ring->channel.regh0, + val64, &bar0->prc_ctrl_n[ring->channel.post_qid]); + + /* Configure Receive Protocol Assist */ + val64 = xge_os_pio_mem_read64(ring->channel.pdev, + ring->channel.regh0, &bar0->rx_pa_cfg); + val64 |= XGE_HAL_RX_PA_CFG_SCATTER_MODE(ring->config->scatter_mode); + val64 |= (XGE_HAL_RX_PA_CFG_IGNORE_SNAP_OUI | XGE_HAL_RX_PA_CFG_IGNORE_LLC_CTRL); + /* Clean STRIP_VLAN_TAG bit and set as config from upper layer */ + val64 &= ~XGE_HAL_RX_PA_CFG_STRIP_VLAN_TAG_MODE(1); + val64 |= XGE_HAL_RX_PA_CFG_STRIP_VLAN_TAG_MODE(ring->config->strip_vlan_tag); + + xge_os_pio_mem_write64(ring->channel.pdev, ring->channel.regh0, + val64, &bar0->rx_pa_cfg); + + xge_debug_ring(XGE_TRACE, "ring%d enabled in buffer_mode %d", + ring->channel.post_qid, queue->buffer_mode); +} + +void +__hal_ring_prc_disable(xge_hal_channel_h channelh) +{ + xge_hal_ring_t *ring = (xge_hal_ring_t *)channelh; + xge_hal_pci_bar0_t *bar0; + u64 val64; + + xge_assert(ring); + xge_assert(ring->channel.pdev); + bar0 = (xge_hal_pci_bar0_t *) (void *) + ((xge_hal_device_t *)ring->channel.devh)->bar0; + + val64 = xge_os_pio_mem_read64(ring->channel.pdev, + ring->channel.regh0, + &bar0->prc_ctrl_n[ring->channel.post_qid]); + val64 &= ~((u64) XGE_HAL_PRC_CTRL_RC_ENABLED); + xge_os_pio_mem_write64(ring->channel.pdev, ring->channel.regh0, + val64, &bar0->prc_ctrl_n[ring->channel.post_qid]); +} + +void +__hal_ring_hw_initialize(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + u64 val64; + int i, j; + + /* Rx DMA intialization. */ + + val64 = 0; + for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { + if (!hldev->config.ring.queue[i].configured) + continue; + val64 |= vBIT(hldev->config.ring.queue[i].priority, + (5 + (i * 8)), 3); + } + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rx_queue_priority); + xge_debug_ring(XGE_TRACE, "Rings priority configured to 0x"XGE_OS_LLXFMT, + (unsigned long long)val64); + + /* Configuring ring queues according to per-ring configuration */ + val64 = 0; + for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { + if (!hldev->config.ring.queue[i].configured) + continue; + val64 |= vBIT(hldev->config.ring.queue[i].dram_size_mb,(i*8),8); + } + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rx_queue_cfg); + xge_debug_ring(XGE_TRACE, "DRAM configured to 0x"XGE_OS_LLXFMT, + (unsigned long long)val64); + + if (!hldev->config.rts_qos_en && + !hldev->config.rts_port_en && + !hldev->config.rts_mac_en) { + + /* + * Activate default (QoS-based) Rx steering + */ + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->rts_qos_steering); + for (j = 0; j < 8 /* QoS max */; j++) + { + for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) + { + if (!hldev->config.ring.queue[i].configured) + continue; + if (!hldev->config.ring.queue[i].rth_en) + val64 |= (BIT(i) >> (j*8)); + } + } + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->rts_qos_steering); + xge_debug_ring(XGE_TRACE, "QoS steering configured to 0x"XGE_OS_LLXFMT, + (unsigned long long)val64); + + } + + /* Note: If a queue does not exist, it should be assigned a maximum + * length of zero. Otherwise, packet loss could occur. + * P. 4-4 User guide. + * + * All configured rings will be properly set at device open time + * by utilizing device_mtu_set() API call. */ + for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { + if (hldev->config.ring.queue[i].configured) + continue; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0ULL, + &bar0->rts_frm_len_n[i]); + } + +#ifdef XGE_HAL_HERC_EMULATION + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + ((u8 *)bar0 + 0x2e60)); /* mc_rldram_mrs_herc */ + val64 |= 0x0000000000010000; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + ((u8 *)bar0 + 0x2e60)); + + val64 |= 0x003a000000000000; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + ((u8 *)bar0 + 0x2e40)); /* mc_rldram_ref_herc */ + xge_os_mdelay(2000); +#endif + + /* now enabling MC-RLDRAM after setting MC_QUEUE sizes */ + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mc_rldram_mrs); + val64 |= XGE_HAL_MC_RLDRAM_QUEUE_SIZE_ENABLE | + XGE_HAL_MC_RLDRAM_MRS_ENABLE; + __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, (u32)(val64>>32), + &bar0->mc_rldram_mrs); + xge_os_wmb(); + __hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, (u32)val64, + &bar0->mc_rldram_mrs); + + /* RLDRAM initialization procedure require 500us to complete */ + xge_os_mdelay(1); + + /* Temporary fixes for Herc RLDRAM */ + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + val64 = XGE_HAL_MC_RLDRAM_SET_REF_PERIOD(0x0279); + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mc_rldram_ref_per_herc); + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->mc_rldram_mrs_herc); + xge_debug_ring(XGE_TRACE, "default mc_rldram_mrs_herc 0x"XGE_OS_LLXFMT, + (unsigned long long)val64); + + val64 = 0x0003570003010300ULL; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->mc_rldram_mrs_herc); + + xge_os_mdelay(1); + } + + /* + * Assign MSI-X vectors + */ + for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { + xge_list_t *item; + xge_hal_channel_t *channel = NULL; + + if (!hldev->config.ring.queue[i].configured || + !hldev->config.ring.queue[i].intr_vector || + !hldev->config.intr_mode != XGE_HAL_INTR_MODE_MSIX) + continue; + + /* find channel */ + xge_list_for_each(item, &hldev->free_channels) { + xge_hal_channel_t *tmp; + tmp = xge_container_of(item, xge_hal_channel_t, + item); + if (tmp->type == XGE_HAL_CHANNEL_TYPE_RING && + tmp->post_qid == i) { + channel = tmp; + break; + } + } + + if (channel) { + xge_hal_channel_msix_set(channel, + hldev->config.ring.queue[i].intr_vector); + } + } + + xge_debug_ring(XGE_TRACE, "%s", "ring channels initialized"); +} + +void +__hal_ring_mtu_set(xge_hal_device_h devh, int new_frmlen) +{ + int i; + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + + for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { + if (!hldev->config.ring.queue[i].configured) + continue; + if (hldev->config.ring.queue[i].max_frm_len != + XGE_HAL_RING_USE_MTU) { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_MAC_RTS_FRM_LEN_SET( + hldev->config.ring.queue[i].max_frm_len), + &bar0->rts_frm_len_n[i]); + } else { + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_MAC_RTS_FRM_LEN_SET(new_frmlen), + &bar0->rts_frm_len_n[i]); + } + } + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + XGE_HAL_RMAC_MAX_PYLD_LEN(new_frmlen), + &bar0->rmac_max_pyld_len); +} diff --git a/sys/dev/nxge/xgehal/xgehal-stats.c b/sys/dev/nxge/xgehal/xgehal-stats.c new file mode 100644 index 0000000..2755ebb --- /dev/null +++ b/sys/dev/nxge/xgehal/xgehal-stats.c @@ -0,0 +1,1019 @@ +/*- + * 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$ + */ + +/* + * FileName : xgehal-stats.c + * + * Description: statistics object implementation + * + * Created: 2 June 2004 + */ + +#include <dev/nxge/include/xgehal-stats.h> +#include <dev/nxge/include/xgehal-device.h> + +/* + * __hal_stats_initialize + * @stats: xge_hal_stats_t structure that contains, in particular, + * Xframe hw stat counters. + * @devh: HAL device handle. + * + * Initialize per-device statistics object. + * See also: xge_hal_stats_getinfo(), xge_hal_status_e{}. + */ +xge_hal_status_e +__hal_stats_initialize (xge_hal_stats_t *stats, xge_hal_device_h devh) +{ + int dma_flags; + xge_hal_device_t *hldev = (xge_hal_device_t*)devh; + + xge_assert(!stats->is_initialized); + + dma_flags = XGE_OS_DMA_CACHELINE_ALIGNED; +#ifdef XGE_HAL_DMA_STATS_CONSISTENT + dma_flags |= XGE_OS_DMA_CONSISTENT; +#else + dma_flags |= XGE_OS_DMA_STREAMING; +#endif + if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) { + stats->hw_info = + (xge_hal_stats_hw_info_t *) xge_os_dma_malloc( + hldev->pdev, + sizeof(xge_hal_stats_hw_info_t), + dma_flags, + &stats->hw_info_dmah, + &stats->hw_info_dma_acch); + + if (stats->hw_info == NULL) { + xge_debug_stats(XGE_ERR, "%s", "can not DMA alloc"); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + xge_os_memzero(stats->hw_info, + sizeof(xge_hal_stats_hw_info_t)); + xge_os_memzero(&stats->hw_info_saved, + sizeof(xge_hal_stats_hw_info_t)); + xge_os_memzero(&stats->hw_info_latest, + sizeof(xge_hal_stats_hw_info_t)); + + + + stats->dma_addr = xge_os_dma_map(hldev->pdev, + stats->hw_info_dmah, + stats->hw_info, + sizeof(xge_hal_stats_hw_info_t), + XGE_OS_DMA_DIR_FROMDEVICE, + XGE_OS_DMA_CACHELINE_ALIGNED | +#ifdef XGE_HAL_DMA_STATS_CONSISTENT + XGE_OS_DMA_CONSISTENT +#else + XGE_OS_DMA_STREAMING +#endif + ); + if (stats->dma_addr == XGE_OS_INVALID_DMA_ADDR) { + xge_debug_stats(XGE_ERR, + "can not map vaddr 0x"XGE_OS_LLXFMT" to DMA", + (unsigned long long)(ulong_t)stats->hw_info); + xge_os_dma_free(hldev->pdev, + stats->hw_info, + sizeof(xge_hal_stats_hw_info_t), + &stats->hw_info_dma_acch, + &stats->hw_info_dmah); + return XGE_HAL_ERR_OUT_OF_MAPPING; + } + } + else { + stats->pcim_info_saved = + (xge_hal_stats_pcim_info_t *)xge_os_malloc( + hldev->pdev, sizeof(xge_hal_stats_pcim_info_t)); + if (stats->pcim_info_saved == NULL) { + xge_debug_stats(XGE_ERR, "%s", "can not alloc"); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + + stats->pcim_info_latest = + (xge_hal_stats_pcim_info_t *)xge_os_malloc( + hldev->pdev, sizeof(xge_hal_stats_pcim_info_t)); + if (stats->pcim_info_latest == NULL) { + xge_os_free(hldev->pdev, stats->pcim_info_saved, + sizeof(xge_hal_stats_pcim_info_t)); + xge_debug_stats(XGE_ERR, "%s", "can not alloc"); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + + stats->pcim_info = + (xge_hal_stats_pcim_info_t *) xge_os_dma_malloc( + hldev->pdev, + sizeof(xge_hal_stats_pcim_info_t), + dma_flags, + &stats->hw_info_dmah, + &stats->hw_info_dma_acch); + + if (stats->pcim_info == NULL) { + xge_os_free(hldev->pdev, stats->pcim_info_saved, + sizeof(xge_hal_stats_pcim_info_t)); + xge_os_free(hldev->pdev, stats->pcim_info_latest, + sizeof(xge_hal_stats_pcim_info_t)); + xge_debug_stats(XGE_ERR, "%s", "can not DMA alloc"); + return XGE_HAL_ERR_OUT_OF_MEMORY; + } + + + xge_os_memzero(stats->pcim_info, + sizeof(xge_hal_stats_pcim_info_t)); + xge_os_memzero(stats->pcim_info_saved, + sizeof(xge_hal_stats_pcim_info_t)); + xge_os_memzero(stats->pcim_info_latest, + sizeof(xge_hal_stats_pcim_info_t)); + + + + stats->dma_addr = xge_os_dma_map(hldev->pdev, + stats->hw_info_dmah, + stats->pcim_info, + sizeof(xge_hal_stats_pcim_info_t), + XGE_OS_DMA_DIR_FROMDEVICE, + XGE_OS_DMA_CACHELINE_ALIGNED | +#ifdef XGE_HAL_DMA_STATS_CONSISTENT + XGE_OS_DMA_CONSISTENT +#else + XGE_OS_DMA_STREAMING +#endif + ); + if (stats->dma_addr == XGE_OS_INVALID_DMA_ADDR) { + xge_debug_stats(XGE_ERR, + "can not map vaddr 0x"XGE_OS_LLXFMT" to DMA", + (unsigned long long)(ulong_t)stats->hw_info); + + xge_os_dma_free(hldev->pdev, + stats->pcim_info, + sizeof(xge_hal_stats_pcim_info_t), + &stats->hw_info_dma_acch, + &stats->hw_info_dmah); + + xge_os_free(hldev->pdev, stats->pcim_info_saved, + sizeof(xge_hal_stats_pcim_info_t)); + + xge_os_free(hldev->pdev, stats->pcim_info_latest, + sizeof(xge_hal_stats_pcim_info_t)); + + return XGE_HAL_ERR_OUT_OF_MAPPING; + } + } + stats->devh = devh; + xge_os_memzero(&stats->sw_dev_info_stats, + sizeof(xge_hal_stats_device_info_t)); + + stats->is_initialized = 1; + + return XGE_HAL_OK; +} + +static void +__hal_stats_save (xge_hal_stats_t *stats) +{ + xge_hal_device_t *hldev = (xge_hal_device_t*)stats->devh; + + if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) { + xge_hal_stats_hw_info_t *latest; + + (void) xge_hal_stats_hw(stats->devh, &latest); + + xge_os_memcpy(&stats->hw_info_saved, stats->hw_info, + sizeof(xge_hal_stats_hw_info_t)); + } else { + xge_hal_stats_pcim_info_t *latest; + + (void) xge_hal_stats_pcim(stats->devh, &latest); + + xge_os_memcpy(stats->pcim_info_saved, stats->pcim_info, + sizeof(xge_hal_stats_pcim_info_t)); + } +} + +/* + * __hal_stats_disable + * @stats: xge_hal_stats_t structure that contains, in particular, + * Xframe hw stat counters. + * + * Ask device to stop collecting stats. + * See also: xge_hal_stats_getinfo(). + */ +void +__hal_stats_disable (xge_hal_stats_t *stats) +{ + xge_hal_device_t *hldev; + xge_hal_pci_bar0_t *bar0; + u64 val64; + + xge_assert(stats->hw_info); + + hldev = (xge_hal_device_t*)stats->devh; + xge_assert(hldev); + bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + + val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->stat_cfg); + val64 &= ~XGE_HAL_STAT_CFG_STAT_EN; + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, + &bar0->stat_cfg); + /* flush the write */ + (void)xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, + &bar0->stat_cfg); + + xge_debug_stats(XGE_TRACE, "stats disabled at 0x"XGE_OS_LLXFMT, + (unsigned long long)stats->dma_addr); + + stats->is_enabled = 0; +} + +/* + * __hal_stats_terminate + * @stats: xge_hal_stats_t structure that contains, in particular, + * Xframe hw stat counters. + * Terminate per-device statistics object. + */ +void +__hal_stats_terminate (xge_hal_stats_t *stats) +{ + xge_hal_device_t *hldev; + + xge_assert(stats->hw_info); + + hldev = (xge_hal_device_t*)stats->devh; + xge_assert(hldev); + xge_assert(stats->is_initialized); + if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) { + xge_os_dma_unmap(hldev->pdev, + stats->hw_info_dmah, + stats->dma_addr, + sizeof(xge_hal_stats_hw_info_t), + XGE_OS_DMA_DIR_FROMDEVICE); + + xge_os_dma_free(hldev->pdev, + stats->hw_info, + sizeof(xge_hal_stats_hw_info_t), + &stats->hw_info_dma_acch, + &stats->hw_info_dmah); + } else { + xge_os_dma_unmap(hldev->pdev, + stats->hw_info_dmah, + stats->dma_addr, + sizeof(xge_hal_stats_pcim_info_t), + XGE_OS_DMA_DIR_FROMDEVICE); + + xge_os_dma_free(hldev->pdev, + stats->pcim_info, + sizeof(xge_hal_stats_pcim_info_t), + &stats->hw_info_dma_acch, + &stats->hw_info_dmah); + + xge_os_free(hldev->pdev, stats->pcim_info_saved, + sizeof(xge_hal_stats_pcim_info_t)); + + xge_os_free(hldev->pdev, stats->pcim_info_latest, + sizeof(xge_hal_stats_pcim_info_t)); + + } + + stats->is_initialized = 0; + stats->is_enabled = 0; +} + + + +/* + * __hal_stats_enable + * @stats: xge_hal_stats_t structure that contains, in particular, + * Xframe hw stat counters. + * + * Ask device to start collecting stats. + * See also: xge_hal_stats_getinfo(). + */ +void +__hal_stats_enable (xge_hal_stats_t *stats) +{ + xge_hal_device_t *hldev; + xge_hal_pci_bar0_t *bar0; + u64 val64; + unsigned int refresh_time_pci_clocks; + + xge_assert(stats->hw_info); + + hldev = (xge_hal_device_t*)stats->devh; + xge_assert(hldev); + + bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; + + /* enable statistics + * For Titan stat_addr offset == 0x09d8, and stat_cfg offset == 0x09d0 + */ + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + stats->dma_addr, &bar0->stat_addr); + + refresh_time_pci_clocks = XGE_HAL_XENA_PER_SEC * + hldev->config.stats_refresh_time_sec; + refresh_time_pci_clocks = + __hal_fix_time_ival_herc(hldev, + refresh_time_pci_clocks); + +#ifdef XGE_HAL_HERC_EMULATION + /* + * The clocks in the emulator are running ~1000 times slower + * than real world, so the stats transfer will occur ~1000 + * times less frequent. STAT_CFG.STAT_TRSF_PERIOD should be + * set to 0x20C for Hercules emulation (stats transferred + * every 0.5 sec). + */ + + val64 = (0x20C | XGE_HAL_STAT_CFG_STAT_RO | + XGE_HAL_STAT_CFG_STAT_EN); +#else + val64 = XGE_HAL_SET_UPDT_PERIOD(refresh_time_pci_clocks) | + XGE_HAL_STAT_CFG_STAT_RO | + XGE_HAL_STAT_CFG_STAT_EN; +#endif + + xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, + val64, &bar0->stat_cfg); + + xge_debug_stats(XGE_TRACE, "stats enabled at 0x"XGE_OS_LLXFMT, + (unsigned long long)stats->dma_addr); + + stats->is_enabled = 1; +} + +/* + * __hal_stats_pcim_update_latest - Update hw ER stats counters, based on the + * real hardware maintained counters and the stored "reset" values. + */ +static void +__hal_stats_pcim_update_latest(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + int i; + +#define set_latest_stat_link_cnt(_link, _p) \ + hldev->stats.pcim_info_latest->link_info[_link]._p = \ + ((hldev->stats.pcim_info->link_info[_link]._p >= \ + hldev->stats.pcim_info_saved->link_info[_link]._p) ? \ + hldev->stats.pcim_info->link_info[_link]._p - \ + hldev->stats.pcim_info_saved->link_info[_link]._p : \ + ((-1) - hldev->stats.pcim_info_saved->link_info[_link]._p) + \ + hldev->stats.pcim_info->link_info[_link]._p) + + +#define set_latest_stat_aggr_cnt(_aggr, _p) \ + hldev->stats.pcim_info_latest->aggr_info[_aggr]._p = \ + ((hldev->stats.pcim_info->aggr_info[_aggr]._p >= \ + hldev->stats.pcim_info_saved->aggr_info[_aggr]._p) ? \ + hldev->stats.pcim_info->aggr_info[_aggr]._p - \ + hldev->stats.pcim_info_saved->aggr_info[_aggr]._p : \ + ((-1) - hldev->stats.pcim_info_saved->aggr_info[_aggr]._p) + \ + hldev->stats.pcim_info->aggr_info[_aggr]._p) + + + for (i = 0; i < XGE_HAL_MAC_LINKS; i++) { + set_latest_stat_link_cnt(i, tx_frms); + set_latest_stat_link_cnt(i, tx_ttl_eth_octets); + set_latest_stat_link_cnt(i, tx_data_octets); + set_latest_stat_link_cnt(i, tx_mcst_frms); + set_latest_stat_link_cnt(i, tx_bcst_frms); + set_latest_stat_link_cnt(i, tx_ucst_frms); + set_latest_stat_link_cnt(i, tx_tagged_frms); + set_latest_stat_link_cnt(i, tx_vld_ip); + set_latest_stat_link_cnt(i, tx_vld_ip_octets); + set_latest_stat_link_cnt(i, tx_icmp); + set_latest_stat_link_cnt(i, tx_tcp); + set_latest_stat_link_cnt(i, tx_rst_tcp); + set_latest_stat_link_cnt(i, tx_udp); + set_latest_stat_link_cnt(i, tx_unknown_protocol); + set_latest_stat_link_cnt(i, tx_parse_error); + set_latest_stat_link_cnt(i, tx_pause_ctrl_frms); + set_latest_stat_link_cnt(i, tx_lacpdu_frms); + set_latest_stat_link_cnt(i, tx_marker_pdu_frms); + set_latest_stat_link_cnt(i, tx_marker_resp_pdu_frms); + set_latest_stat_link_cnt(i, tx_drop_ip); + set_latest_stat_link_cnt(i, tx_xgmii_char1_match); + set_latest_stat_link_cnt(i, tx_xgmii_char2_match); + set_latest_stat_link_cnt(i, tx_xgmii_column1_match); + set_latest_stat_link_cnt(i, tx_xgmii_column2_match); + set_latest_stat_link_cnt(i, tx_drop_frms); + set_latest_stat_link_cnt(i, tx_any_err_frms); + set_latest_stat_link_cnt(i, rx_ttl_frms); + set_latest_stat_link_cnt(i, rx_vld_frms); + set_latest_stat_link_cnt(i, rx_offld_frms); + set_latest_stat_link_cnt(i, rx_ttl_eth_octets); + set_latest_stat_link_cnt(i, rx_data_octets); + set_latest_stat_link_cnt(i, rx_offld_octets); + set_latest_stat_link_cnt(i, rx_vld_mcst_frms); + set_latest_stat_link_cnt(i, rx_vld_bcst_frms); + set_latest_stat_link_cnt(i, rx_accepted_ucst_frms); + set_latest_stat_link_cnt(i, rx_accepted_nucst_frms); + set_latest_stat_link_cnt(i, rx_tagged_frms); + set_latest_stat_link_cnt(i, rx_long_frms); + set_latest_stat_link_cnt(i, rx_usized_frms); + set_latest_stat_link_cnt(i, rx_osized_frms); + set_latest_stat_link_cnt(i, rx_frag_frms); + set_latest_stat_link_cnt(i, rx_jabber_frms); + set_latest_stat_link_cnt(i, rx_ttl_64_frms); + set_latest_stat_link_cnt(i, rx_ttl_65_127_frms); + set_latest_stat_link_cnt(i, rx_ttl_128_255_frms); + set_latest_stat_link_cnt(i, rx_ttl_256_511_frms); + set_latest_stat_link_cnt(i, rx_ttl_512_1023_frms); + set_latest_stat_link_cnt(i, rx_ttl_1024_1518_frms); + set_latest_stat_link_cnt(i, rx_ttl_1519_4095_frms); + set_latest_stat_link_cnt(i, rx_ttl_40956_8191_frms); + set_latest_stat_link_cnt(i, rx_ttl_8192_max_frms); + set_latest_stat_link_cnt(i, rx_ttl_gt_max_frms); + set_latest_stat_link_cnt(i, rx_ip); + set_latest_stat_link_cnt(i, rx_ip_octets); + set_latest_stat_link_cnt(i, rx_hdr_err_ip); + set_latest_stat_link_cnt(i, rx_icmp); + set_latest_stat_link_cnt(i, rx_tcp); + set_latest_stat_link_cnt(i, rx_udp); + set_latest_stat_link_cnt(i, rx_err_tcp); + set_latest_stat_link_cnt(i, rx_pause_cnt); + set_latest_stat_link_cnt(i, rx_pause_ctrl_frms); + set_latest_stat_link_cnt(i, rx_unsup_ctrl_frms); + set_latest_stat_link_cnt(i, rx_in_rng_len_err_frms); + set_latest_stat_link_cnt(i, rx_out_rng_len_err_frms); + set_latest_stat_link_cnt(i, rx_drop_frms); + set_latest_stat_link_cnt(i, rx_discarded_frms); + set_latest_stat_link_cnt(i, rx_drop_ip); + set_latest_stat_link_cnt(i, rx_err_drp_udp); + set_latest_stat_link_cnt(i, rx_lacpdu_frms); + set_latest_stat_link_cnt(i, rx_marker_pdu_frms); + set_latest_stat_link_cnt(i, rx_marker_resp_pdu_frms); + set_latest_stat_link_cnt(i, rx_unknown_pdu_frms); + set_latest_stat_link_cnt(i, rx_illegal_pdu_frms); + set_latest_stat_link_cnt(i, rx_fcs_discard); + set_latest_stat_link_cnt(i, rx_len_discard); + set_latest_stat_link_cnt(i, rx_pf_discard); + set_latest_stat_link_cnt(i, rx_trash_discard); + set_latest_stat_link_cnt(i, rx_rts_discard); + set_latest_stat_link_cnt(i, rx_wol_discard); + set_latest_stat_link_cnt(i, rx_red_discard); + set_latest_stat_link_cnt(i, rx_ingm_full_discard); + set_latest_stat_link_cnt(i, rx_xgmii_data_err_cnt); + set_latest_stat_link_cnt(i, rx_xgmii_ctrl_err_cnt); + set_latest_stat_link_cnt(i, rx_xgmii_err_sym); + set_latest_stat_link_cnt(i, rx_xgmii_char1_match); + set_latest_stat_link_cnt(i, rx_xgmii_char2_match); + set_latest_stat_link_cnt(i, rx_xgmii_column1_match); + set_latest_stat_link_cnt(i, rx_xgmii_column2_match); + set_latest_stat_link_cnt(i, rx_local_fault); + set_latest_stat_link_cnt(i, rx_remote_fault); + set_latest_stat_link_cnt(i, rx_queue_full); + } + + for (i = 0; i < XGE_HAL_MAC_AGGREGATORS; i++) { + set_latest_stat_aggr_cnt(i, tx_frms); + set_latest_stat_aggr_cnt(i, tx_mcst_frms); + set_latest_stat_aggr_cnt(i, tx_bcst_frms); + set_latest_stat_aggr_cnt(i, tx_discarded_frms); + set_latest_stat_aggr_cnt(i, tx_errored_frms); + set_latest_stat_aggr_cnt(i, rx_frms); + set_latest_stat_aggr_cnt(i, rx_data_octets); + set_latest_stat_aggr_cnt(i, rx_mcst_frms); + set_latest_stat_aggr_cnt(i, rx_bcst_frms); + set_latest_stat_aggr_cnt(i, rx_discarded_frms); + set_latest_stat_aggr_cnt(i, rx_errored_frms); + set_latest_stat_aggr_cnt(i, rx_unknown_protocol_frms); + } + return; +} + +/* + * __hal_stats_update_latest - Update hw stats counters, based on the real + * hardware maintained counters and the stored "reset" values. + */ +static void +__hal_stats_update_latest(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + +#define set_latest_stat_cnt(_dev, _p) \ + hldev->stats.hw_info_latest._p = \ + ((hldev->stats.hw_info->_p >= hldev->stats.hw_info_saved._p) ? \ + hldev->stats.hw_info->_p - hldev->stats.hw_info_saved._p : \ + ((-1) - hldev->stats.hw_info_saved._p) + hldev->stats.hw_info->_p) + + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN) { + __hal_stats_pcim_update_latest(devh); + return; + } + + /* Tx MAC statistics counters. */ + set_latest_stat_cnt(hldev, tmac_frms); + set_latest_stat_cnt(hldev, tmac_data_octets); + set_latest_stat_cnt(hldev, tmac_drop_frms); + set_latest_stat_cnt(hldev, tmac_mcst_frms); + set_latest_stat_cnt(hldev, tmac_bcst_frms); + set_latest_stat_cnt(hldev, tmac_pause_ctrl_frms); + set_latest_stat_cnt(hldev, tmac_ttl_octets); + set_latest_stat_cnt(hldev, tmac_ucst_frms); + set_latest_stat_cnt(hldev, tmac_nucst_frms); + set_latest_stat_cnt(hldev, tmac_any_err_frms); + set_latest_stat_cnt(hldev, tmac_ttl_less_fb_octets); + set_latest_stat_cnt(hldev, tmac_vld_ip_octets); + set_latest_stat_cnt(hldev, tmac_vld_ip); + set_latest_stat_cnt(hldev, tmac_drop_ip); + set_latest_stat_cnt(hldev, tmac_icmp); + set_latest_stat_cnt(hldev, tmac_rst_tcp); + set_latest_stat_cnt(hldev, tmac_tcp); + set_latest_stat_cnt(hldev, tmac_udp); + set_latest_stat_cnt(hldev, reserved_0); + + /* Rx MAC Statistics counters. */ + set_latest_stat_cnt(hldev, rmac_vld_frms); + set_latest_stat_cnt(hldev, rmac_data_octets); + set_latest_stat_cnt(hldev, rmac_fcs_err_frms); + set_latest_stat_cnt(hldev, rmac_drop_frms); + set_latest_stat_cnt(hldev, rmac_vld_mcst_frms); + set_latest_stat_cnt(hldev, rmac_vld_bcst_frms); + set_latest_stat_cnt(hldev, rmac_in_rng_len_err_frms); + set_latest_stat_cnt(hldev, rmac_out_rng_len_err_frms); + set_latest_stat_cnt(hldev, rmac_long_frms); + set_latest_stat_cnt(hldev, rmac_pause_ctrl_frms); + set_latest_stat_cnt(hldev, rmac_unsup_ctrl_frms); + set_latest_stat_cnt(hldev, rmac_ttl_octets); + set_latest_stat_cnt(hldev, rmac_accepted_ucst_frms); + set_latest_stat_cnt(hldev, rmac_accepted_nucst_frms); + set_latest_stat_cnt(hldev, rmac_discarded_frms); + set_latest_stat_cnt(hldev, rmac_drop_events); + set_latest_stat_cnt(hldev, reserved_1); + set_latest_stat_cnt(hldev, rmac_ttl_less_fb_octets); + set_latest_stat_cnt(hldev, rmac_ttl_frms); + set_latest_stat_cnt(hldev, reserved_2); + set_latest_stat_cnt(hldev, reserved_3); + set_latest_stat_cnt(hldev, rmac_usized_frms); + set_latest_stat_cnt(hldev, rmac_osized_frms); + set_latest_stat_cnt(hldev, rmac_frag_frms); + set_latest_stat_cnt(hldev, rmac_jabber_frms); + set_latest_stat_cnt(hldev, reserved_4); + set_latest_stat_cnt(hldev, rmac_ttl_64_frms); + set_latest_stat_cnt(hldev, rmac_ttl_65_127_frms); + set_latest_stat_cnt(hldev, reserved_5); + set_latest_stat_cnt(hldev, rmac_ttl_128_255_frms); + set_latest_stat_cnt(hldev, rmac_ttl_256_511_frms); + set_latest_stat_cnt(hldev, reserved_6); + set_latest_stat_cnt(hldev, rmac_ttl_512_1023_frms); + set_latest_stat_cnt(hldev, rmac_ttl_1024_1518_frms); + set_latest_stat_cnt(hldev, reserved_7); + set_latest_stat_cnt(hldev, rmac_ip); + set_latest_stat_cnt(hldev, rmac_ip_octets); + set_latest_stat_cnt(hldev, rmac_hdr_err_ip); + set_latest_stat_cnt(hldev, rmac_drop_ip); + set_latest_stat_cnt(hldev, rmac_icmp); + set_latest_stat_cnt(hldev, reserved_8); + set_latest_stat_cnt(hldev, rmac_tcp); + set_latest_stat_cnt(hldev, rmac_udp); + set_latest_stat_cnt(hldev, rmac_err_drp_udp); + set_latest_stat_cnt(hldev, rmac_xgmii_err_sym); + set_latest_stat_cnt(hldev, rmac_frms_q0); + set_latest_stat_cnt(hldev, rmac_frms_q1); + set_latest_stat_cnt(hldev, rmac_frms_q2); + set_latest_stat_cnt(hldev, rmac_frms_q3); + set_latest_stat_cnt(hldev, rmac_frms_q4); + set_latest_stat_cnt(hldev, rmac_frms_q5); + set_latest_stat_cnt(hldev, rmac_frms_q6); + set_latest_stat_cnt(hldev, rmac_frms_q7); + set_latest_stat_cnt(hldev, rmac_full_q0); + set_latest_stat_cnt(hldev, rmac_full_q1); + set_latest_stat_cnt(hldev, rmac_full_q2); + set_latest_stat_cnt(hldev, rmac_full_q3); + set_latest_stat_cnt(hldev, rmac_full_q4); + set_latest_stat_cnt(hldev, rmac_full_q5); + set_latest_stat_cnt(hldev, rmac_full_q6); + set_latest_stat_cnt(hldev, rmac_full_q7); + set_latest_stat_cnt(hldev, rmac_pause_cnt); + set_latest_stat_cnt(hldev, reserved_9); + set_latest_stat_cnt(hldev, rmac_xgmii_data_err_cnt); + set_latest_stat_cnt(hldev, rmac_xgmii_ctrl_err_cnt); + set_latest_stat_cnt(hldev, rmac_accepted_ip); + set_latest_stat_cnt(hldev, rmac_err_tcp); + + /* PCI/PCI-X Read transaction statistics. */ + set_latest_stat_cnt(hldev, rd_req_cnt); + set_latest_stat_cnt(hldev, new_rd_req_cnt); + set_latest_stat_cnt(hldev, new_rd_req_rtry_cnt); + set_latest_stat_cnt(hldev, rd_rtry_cnt); + set_latest_stat_cnt(hldev, wr_rtry_rd_ack_cnt); + + /* PCI/PCI-X write transaction statistics. */ + set_latest_stat_cnt(hldev, wr_req_cnt); + set_latest_stat_cnt(hldev, new_wr_req_cnt); + set_latest_stat_cnt(hldev, new_wr_req_rtry_cnt); + set_latest_stat_cnt(hldev, wr_rtry_cnt); + set_latest_stat_cnt(hldev, wr_disc_cnt); + set_latest_stat_cnt(hldev, rd_rtry_wr_ack_cnt); + + /* DMA Transaction statistics. */ + set_latest_stat_cnt(hldev, txp_wr_cnt); + set_latest_stat_cnt(hldev, txd_rd_cnt); + set_latest_stat_cnt(hldev, txd_wr_cnt); + set_latest_stat_cnt(hldev, rxd_rd_cnt); + set_latest_stat_cnt(hldev, rxd_wr_cnt); + set_latest_stat_cnt(hldev, txf_rd_cnt); + set_latest_stat_cnt(hldev, rxf_wr_cnt); + + /* Enhanced Herc statistics */ + set_latest_stat_cnt(hldev, tmac_frms_oflow); + set_latest_stat_cnt(hldev, tmac_data_octets_oflow); + set_latest_stat_cnt(hldev, tmac_mcst_frms_oflow); + set_latest_stat_cnt(hldev, tmac_bcst_frms_oflow); + set_latest_stat_cnt(hldev, tmac_ttl_octets_oflow); + set_latest_stat_cnt(hldev, tmac_ucst_frms_oflow); + set_latest_stat_cnt(hldev, tmac_nucst_frms_oflow); + set_latest_stat_cnt(hldev, tmac_any_err_frms_oflow); + set_latest_stat_cnt(hldev, tmac_vlan_frms); + set_latest_stat_cnt(hldev, tmac_vld_ip_oflow); + set_latest_stat_cnt(hldev, tmac_drop_ip_oflow); + set_latest_stat_cnt(hldev, tmac_icmp_oflow); + set_latest_stat_cnt(hldev, tmac_rst_tcp_oflow); + set_latest_stat_cnt(hldev, tmac_udp_oflow); + set_latest_stat_cnt(hldev, tpa_unknown_protocol); + set_latest_stat_cnt(hldev, tpa_parse_failure); + set_latest_stat_cnt(hldev, rmac_vld_frms_oflow); + set_latest_stat_cnt(hldev, rmac_data_octets_oflow); + set_latest_stat_cnt(hldev, rmac_vld_mcst_frms_oflow); + set_latest_stat_cnt(hldev, rmac_vld_bcst_frms_oflow); + set_latest_stat_cnt(hldev, rmac_ttl_octets_oflow); + set_latest_stat_cnt(hldev, rmac_accepted_ucst_frms_oflow); + set_latest_stat_cnt(hldev, rmac_accepted_nucst_frms_oflow); + set_latest_stat_cnt(hldev, rmac_discarded_frms_oflow); + set_latest_stat_cnt(hldev, rmac_drop_events_oflow); + set_latest_stat_cnt(hldev, rmac_usized_frms_oflow); + set_latest_stat_cnt(hldev, rmac_osized_frms_oflow); + set_latest_stat_cnt(hldev, rmac_frag_frms_oflow); + set_latest_stat_cnt(hldev, rmac_jabber_frms_oflow); + set_latest_stat_cnt(hldev, rmac_ip_oflow); + set_latest_stat_cnt(hldev, rmac_drop_ip_oflow); + set_latest_stat_cnt(hldev, rmac_icmp_oflow); + set_latest_stat_cnt(hldev, rmac_udp_oflow); + set_latest_stat_cnt(hldev, rmac_err_drp_udp_oflow); + set_latest_stat_cnt(hldev, rmac_pause_cnt_oflow); + set_latest_stat_cnt(hldev, rmac_ttl_1519_4095_frms); + set_latest_stat_cnt(hldev, rmac_ttl_4096_8191_frms); + set_latest_stat_cnt(hldev, rmac_ttl_8192_max_frms); + set_latest_stat_cnt(hldev, rmac_ttl_gt_max_frms); + set_latest_stat_cnt(hldev, rmac_osized_alt_frms); + set_latest_stat_cnt(hldev, rmac_jabber_alt_frms); + set_latest_stat_cnt(hldev, rmac_gt_max_alt_frms); + set_latest_stat_cnt(hldev, rmac_vlan_frms); + set_latest_stat_cnt(hldev, rmac_fcs_discard); + set_latest_stat_cnt(hldev, rmac_len_discard); + set_latest_stat_cnt(hldev, rmac_da_discard); + set_latest_stat_cnt(hldev, rmac_pf_discard); + set_latest_stat_cnt(hldev, rmac_rts_discard); + set_latest_stat_cnt(hldev, rmac_red_discard); + set_latest_stat_cnt(hldev, rmac_ingm_full_discard); + set_latest_stat_cnt(hldev, rmac_accepted_ip_oflow); + set_latest_stat_cnt(hldev, link_fault_cnt); +} + +/** + * xge_hal_stats_hw - Get HW device statistics. + * @devh: HAL device handle. + * @hw_info: Xframe statistic counters. See xge_hal_stats_hw_info_t. + * Returned by HAL. + * + * Get device and HAL statistics. The latter is part of the in-host statistics + * that HAL maintains for _that_ device. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not + * currently available. + * + * See also: xge_hal_status_e{}. + */ +xge_hal_status_e +xge_hal_stats_hw(xge_hal_device_h devh, xge_hal_stats_hw_info_t **hw_info) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + + xge_assert(xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) + + if (!hldev->stats.is_initialized || + !hldev->stats.is_enabled) { + *hw_info = NULL; + return XGE_HAL_INF_STATS_IS_NOT_READY; + } + +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_STATS_STREAMING) + xge_os_dma_sync(hldev->pdev, + hldev->stats.hw_info_dmah, + hldev->stats.dma_addr, + 0, + sizeof(xge_hal_stats_hw_info_t), + XGE_OS_DMA_DIR_FROMDEVICE); +#endif + + /* + * update hw counters, taking into account + * the "reset" or "saved" + * values + */ + __hal_stats_update_latest(devh); + + /* + * statistics HW bug fixups for Xena and Herc + */ + if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA || + xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { + u64 mcst, bcst; + xge_hal_stats_hw_info_t *hwsta = &hldev->stats.hw_info_latest; + + mcst = ((u64)hwsta->rmac_vld_mcst_frms_oflow << 32) | + hwsta->rmac_vld_mcst_frms; + + bcst = ((u64)hwsta->rmac_vld_bcst_frms_oflow << 32) | + hwsta->rmac_vld_bcst_frms; + + mcst -= bcst; + + hwsta->rmac_vld_mcst_frms_oflow = (u32)(mcst >> 32); + hwsta->rmac_vld_mcst_frms = (u32)mcst; + } + + *hw_info = &hldev->stats.hw_info_latest; + + return XGE_HAL_OK; +} + +/** + * xge_hal_stats_pcim - Get HW device statistics. + * @devh: HAL device handle. + * @hw_info: Xframe statistic counters. See xge_hal_stats_pcim_info_t. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not + * currently available. + * + * See also: xge_hal_status_e{}. + */ +xge_hal_status_e +xge_hal_stats_pcim(xge_hal_device_h devh, xge_hal_stats_pcim_info_t **hw_info) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + + xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN) + + if (!hldev->stats.is_initialized || + !hldev->stats.is_enabled) { + *hw_info = NULL; + return XGE_HAL_INF_STATS_IS_NOT_READY; + } + +#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_STATS_STREAMING) + xge_os_dma_sync(hldev->pdev, + hldev->stats.hw_info_dmah, + hldev->stats.dma_addr, + 0, + sizeof(xge_hal_stats_pcim_info_t), + XGE_OS_DMA_DIR_FROMDEVICE); +#endif + + /* + * update hw counters, taking into account + * the "reset" or "saved" + * values + */ + __hal_stats_pcim_update_latest(devh); + + *hw_info = hldev->stats.pcim_info_latest; + + return XGE_HAL_OK; +} + +/** + * xge_hal_stats_device - Get HAL statistics. + * @devh: HAL device handle. + * @hw_info: Xframe statistic counters. See xge_hal_stats_hw_info_t. + * Returned by HAL. + * @device_info: HAL statistics. See xge_hal_stats_device_info_t. + * Returned by HAL. + * + * Get device and HAL statistics. The latter is part of the in-host statistics + * that HAL maintains for _that_ device. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not + * currently available. + * + * See also: xge_hal_status_e{}. + */ +xge_hal_status_e +xge_hal_stats_device(xge_hal_device_h devh, + xge_hal_stats_device_info_t **device_info) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + + if (!hldev->stats.is_initialized || + !hldev->stats.is_enabled) { + *device_info = NULL; + return XGE_HAL_INF_STATS_IS_NOT_READY; + } + + hldev->stats.sw_dev_info_stats.traffic_intr_cnt = + hldev->stats.sw_dev_info_stats.total_intr_cnt - + hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt; + + *device_info = &hldev->stats.sw_dev_info_stats; + + return XGE_HAL_OK; +} + +/** + * xge_hal_stats_channel - Get channel statistics. + * @channelh: Channel handle. + * @channel_info: HAL channel statistic counters. + * See xge_hal_stats_channel_info_t{}. Returned by HAL. + * + * Retrieve statistics of a particular HAL channel. This includes, for instance, + * number of completions per interrupt, number of traffic interrupts, etc. + * + * Returns: XGE_HAL_OK - success. + * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not + * currently available. + * + * See also: xge_hal_status_e{}. + */ +xge_hal_status_e +xge_hal_stats_channel(xge_hal_channel_h channelh, + xge_hal_stats_channel_info_t **channel_info) +{ + xge_hal_stats_hw_info_t *latest; + xge_hal_channel_t *channel; + xge_hal_device_t *hldev; + + channel = (xge_hal_channel_t *)channelh; + hldev = (xge_hal_device_t *)channel->devh; + if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + if ((channel == NULL) || (channel->magic != XGE_HAL_MAGIC)) { + return XGE_HAL_ERR_INVALID_DEVICE; + } + + if (!hldev->stats.is_initialized || + !hldev->stats.is_enabled || + !channel->is_open) { + *channel_info = NULL; + return XGE_HAL_INF_STATS_IS_NOT_READY; + } + + hldev->stats.sw_dev_info_stats.traffic_intr_cnt = + hldev->stats.sw_dev_info_stats.total_intr_cnt - + hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt; + + if (hldev->stats.sw_dev_info_stats.traffic_intr_cnt) { + int rxcnt = hldev->stats.sw_dev_info_stats.rx_traffic_intr_cnt; + int txcnt = hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt; + if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { + if (!txcnt) + txcnt = 1; + channel->stats.avg_compl_per_intr_cnt = + channel->stats.total_compl_cnt / txcnt; + } else if (channel->type == XGE_HAL_CHANNEL_TYPE_RING && + !hldev->config.bimodal_interrupts) { + if (!rxcnt) + rxcnt = 1; + channel->stats.avg_compl_per_intr_cnt = + channel->stats.total_compl_cnt / rxcnt; + } + if (channel->stats.avg_compl_per_intr_cnt == 0) { + /* to not confuse user */ + channel->stats.avg_compl_per_intr_cnt = 1; + } + } + + (void) xge_hal_stats_hw(hldev, &latest); + + if (channel->stats.total_posts) { + channel->stats.avg_buffers_per_post = + channel->stats.total_buffers / + channel->stats.total_posts; +#ifdef XGE_OS_PLATFORM_64BIT + if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { + channel->stats.avg_post_size = + (u32)(latest->tmac_ttl_less_fb_octets / + channel->stats.total_posts); + } +#endif + } + +#ifdef XGE_OS_PLATFORM_64BIT + if (channel->stats.total_buffers && + channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { + channel->stats.avg_buffer_size = + (u32)(latest->tmac_ttl_less_fb_octets / + channel->stats.total_buffers); + } +#endif + + *channel_info = &channel->stats; + return XGE_HAL_OK; +} + +/** + * xge_hal_stats_reset - Reset (zero-out) device statistics + * @devh: HAL device handle. + * + * Reset all device statistics. + * Returns: XGE_HAL_OK - success. + * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not + * currently available. + * + * See also: xge_hal_status_e{}, xge_hal_stats_channel_info_t{}, + * xge_hal_stats_sw_err_t{}, xge_hal_stats_device_info_t{}. + */ +xge_hal_status_e +xge_hal_stats_reset(xge_hal_device_h devh) +{ + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + + if (!hldev->stats.is_initialized || + !hldev->stats.is_enabled) { + return XGE_HAL_INF_STATS_IS_NOT_READY; + } + + /* save hw stats to calculate the after-reset values */ + __hal_stats_save(&hldev->stats); + + /* zero-out driver-maintained stats, don't reset the saved */ + __hal_stats_soft_reset(hldev, 0); + + return XGE_HAL_OK; +} + +/* + * __hal_stats_soft_reset - Reset software-maintained statistics. + */ +void +__hal_stats_soft_reset (xge_hal_device_h devh, int reset_all) +{ + xge_list_t *item; + xge_hal_channel_t *channel; + xge_hal_device_t *hldev = (xge_hal_device_t *)devh; + + if (reset_all) { + if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) { + xge_os_memzero(&hldev->stats.hw_info_saved, + sizeof(xge_hal_stats_hw_info_t)); + xge_os_memzero(&hldev->stats.hw_info_latest, + sizeof(xge_hal_stats_hw_info_t)); + } else { + xge_os_memzero(&hldev->stats.pcim_info_saved, + sizeof(xge_hal_stats_pcim_info_t)); + xge_os_memzero(&hldev->stats.pcim_info_latest, + sizeof(xge_hal_stats_pcim_info_t)); + } + } + + /* Reset the "soft" error and informational statistics */ + xge_os_memzero(&hldev->stats.sw_dev_err_stats, + sizeof(xge_hal_stats_sw_err_t)); + xge_os_memzero(&hldev->stats.sw_dev_info_stats, + sizeof(xge_hal_stats_device_info_t)); + + /* for each Rx channel */ + xge_list_for_each(item, &hldev->ring_channels) { + channel = xge_container_of(item, xge_hal_channel_t, item); + xge_os_memzero(&channel->stats, + sizeof(xge_hal_stats_channel_info_t)); + } + + /* for each Tx channel */ + xge_list_for_each(item, &hldev->fifo_channels) { + channel = xge_container_of(item, xge_hal_channel_t, item); + xge_os_memzero(&channel->stats, + sizeof(xge_hal_stats_channel_info_t)); + } +} + diff --git a/sys/dev/nxge/xgell-version.h b/sys/dev/nxge/xgell-version.h new file mode 100644 index 0000000..f694833 --- /dev/null +++ b/sys/dev/nxge/xgell-version.h @@ -0,0 +1,48 @@ +/*- + * 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$ + */ + +/* + * FileName : version.h + * + * Description: versioning file + * + * Created: 3 September 2004 + */ + +#ifndef XGELL_VERSION_H +#define XGELL_VERSION_H + +#define XGELL_VERSION_MAJOR "2" +#define XGELL_VERSION_MINOR "0" +#define XGELL_VERSION_FIX "7" +#define XGELL_VERSION_BUILD GENERATED_BUILD_VERSION +#define XGELL_VERSION XGELL_VERSION_MAJOR"."XGELL_VERSION_MINOR"." \ + GENERATED_BUILD_VERSION +#define XGELL_DESC XGE_DRIVER_NAME" v."XGELL_VERSION + +#endif /* XGELL_VERSION_H */ |