/*******************************************************************************
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2014 QLogic Corporation
* The contents of this file are subject to the terms of the
* QLogic End User License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the License at
* See the License for the specific language governing permissions
* and limitations under the License.
*
*
* Module Description:
* This file contains functions that handle direct HW access
*
******************************************************************************/
#include "lm5710.h"
#include "hw_dump.h"
#include "577xx_int_offsets.h"
/* not in hsi */
struct rate_shaping_vars_per_vn *ram_data);
In this mode, we assume that the driver in the host OS loads
first, and allocates offset 0 in the NIG for it's own MAC address,
so we don't use it. Also, iSCSI has a reserved entry in the NIG, so
we don't use that either.
*/
#define IS_VALID_NIG_IDX(_idx) ((_idx != ECORE_LLH_CAM_ETH_LINE) && (_idx != ECORE_LLH_CAM_ISCSI_ETH_LINE))
// initialize congestion managmet params
{
u32_t i = 0;
const u8_t port_id = PORT_ID(pdev); // TBD: E1H - cmng params are currently per port, may change to be per function
static const u8_t DEF_MIN_RATE = 1 ; /* default MIN rate in case VNIC min rate is configured to zero- 100Mbps */
{
{
vnic);
{
{
}
else
{
}
}
}
// IS_DCB_ENABLED isn't updated when this function is called from lm_init_intmem_port
// but it is called each time the link is up.
{
}
if( b_afex_and_non_pmf )
{
}
else
{
}
}
// store per vnic struct to internal memory rs. we store data for all 4 vnics even if there are only 2 vnics, just to
// make sure there are known values.
{
{
// If AFEX && non pmf we want to write only for the current VNIC
continue;
}
{
buf[i], BAR_XSTRORM_INTMEM);
}
}
if( b_afex_and_non_pmf )
{
// If AFEX && non pmf we want to write only for the current VNIC
// All other writes below are for PMF so we exit in this case.
return;
}
// Store per port struct to internal memory
{
LM_INTMEM_WRITE32(pdev,(XSTORM_CMNG_PER_PORT_VARS_OFFSET(port_id) + OFFSETOF(struct cmng_struct_per_port, rs_vars) + i*4),
buf[i], BAR_XSTRORM_INTMEM);
}
{
LM_INTMEM_WRITE32(pdev,(XSTORM_CMNG_PER_PORT_VARS_OFFSET(port_id) + OFFSETOF(struct cmng_struct_per_port, fair_vars) + i*4),
buf[i], BAR_XSTRORM_INTMEM);
}
{
LM_INTMEM_WRITE32(pdev,(XSTORM_CMNG_PER_PORT_VARS_OFFSET(port_id) + OFFSETOF(struct cmng_struct_per_port, flags) + i*4),
buf[i], BAR_XSTRORM_INTMEM);
}
// store per vnic struct to internal memory fair. we store data for all 4 vnics even if there are only 2 vnics, just to
//make sure there are known values.
{
{
buf[i], BAR_XSTRORM_INTMEM);
}
}
} /* lm_cmng_init */
/**initialize_nig_entry
* Initialize a NIG mirror entry to a given MAC address. Note -
* the entrie's reference count remains 0.
*
* @param pdev
* @param offset the index of the NIG entry
* @param addr the MAC address to use
*
* @return lm_status_t LM_STATUS_SUCCESS on success, some other
* failure code on failure.
*/
{
return LM_STATUS_SUCCESS;
}
/**get_available_nig_entry
* Find a NIG entry that's not in use. Entry 0 and 15 are never
* considered available, since they are used by iSCSI and by the
* L2 client.
*
* @param pdev
*
* @return an index to a usable NIG entry, or INVALID_NIG_OFFSET
* if there aren't any available entries.
*/
{
u8_t i;
{
if (IS_VALID_NIG_IDX(i) &&
{
return i;
}
}
return INVALID_NIG_OFFSET;
}
/**find_nig_entry_for_addr
* Find the entry for a given MAC address in the nig.
*
* @param pdev
* @param addr the MAC address to look for
*
* @return u8_t the index of the NIG entry that contains the
* given MAC address, or INVALID_NIG_OFFSET if no such
* entry exists.
*/
{
u8_t i;
{
{
return i;
}
}
return INVALID_NIG_OFFSET;
}
{
if (offset == INVALID_NIG_OFFSET)
{
/*If there was no entry for this MAC, insert it to an available slot and call lm_set_mac_in_nig.*/
if (offset == INVALID_NIG_OFFSET)
{
return LM_STATUS_RESOURCE; //no available NIG entry.
}
if (lm_status != LM_STATUS_SUCCESS)
{
return lm_status;
}
}
return lm_status;
}
/**remove_nig_entry
* Dereference the entry for a given MAC address. If this was
* the last reference the MAC address is removed from the NIG.
*
* @param pdev
* @param addr the MAC address
*
* @return lm_status_t LM_STATUS_SUCCESS on success,
* LM_STATUS_FAILURE if the given MAC is not in the NIG,
* other failure codes on other errors.
*/
{
if (offset == INVALID_NIG_OFFSET)
{
return LM_STATUS_FAILURE;
}
{
if (lm_status != LM_STATUS_SUCCESS)
{
return lm_status;
}
}
return lm_status;
}
{
switch(val)
{
{
/*
* The fan failure mechanism is usually related to the PHY type since
* the power consumption of the board is effected by the PHY. Currently,
* fan is required for most designs with SFX7101, BCM8727 and BCM8481.
*/
{
is_required |= elink_fan_failure_det_req(pdev, pdev->hw_info.shmem_base, pdev->hw_info.shmem_base2, port);
}
}
break;
is_required = TRUE;
break;
default:
break;
}
DbgMessage(pdev, WARN, "lm_setup_fan_failure_detection: cfg=0x%x is_required=%d\n", val, is_required );
if (!is_required)
{
return;
}
// read spio5 in order to make it input collaterally - we don't care of the returned value
// MCP does the same
if( LM_STATUS_SUCCESS != lm_status )
{
DbgBreakIf(1) ;
}
// We write here since value changes from 1 to 0
// enable the SPIO_INT 5 to signal the IGU
}
/*
*------------------------------------------------------------------------
* lm_gpio_read -
*
* Read the value of the requested GPIO pin (with pin_num)
*
*------------------------------------------------------------------------
*/
{
{
DbgBreakIf(!pdev);
return LM_STATUS_INVALID_PARAMETER ;
}
if (pin_num > MISC_REGISTERS_GPIO_3)
{
return LM_STATUS_INVALID_PARAMETER;
}
/* The GPIO should be swapped if the swap register is set and active */
// define port upon swap
// Get the current port number (0 or 1)
if (gpio_port > 1)
{
return LM_STATUS_FAILURE;
}
// Calculate the value with relevent OE set to 1 (for input).
// Calulate the mask for the read value.
if (gpio_port == 0)
{
switch (pin_num)
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
default:
break;
}
}
// Calculate the value with relevent OE set to 1 (for input).
// Calulate the mask for the read value.
if (gpio_port == 1)
{
switch (pin_num)
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
default:
break;
}
}
// Read from MISC block the GPIO register
// Get the requested pin value by masking the val with mask
{
*value_ptr = 1;
}
else
{
*value_ptr = 0;
}
return LM_STATUS_SUCCESS;
}
/*
*------------------------------------------------------------------------
* lm_gpio_write -
*
* Write a value to the requested GPIO pin (with pin_num)
*
*------------------------------------------------------------------------
*/
{
{
DbgBreakIf(!pdev);
return LM_STATUS_INVALID_PARAMETER ;
}
if (pin_num > MISC_REGISTERS_GPIO_3)
{
return LM_STATUS_INVALID_PARAMETER;
}
/* The GPIO should be swapped if the swap register is set and active */
// define port upon swap
// Get the current port number (0 or 1)
if (gpio_port > 1) {
return LM_STATUS_FAILURE;
}
gpio_shift = pin_num +
(gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0);
// lock before read
/* read GPIO and mask except the float bits */
switch (mode) {
/* clear FLOAT and set CLR */
break;
/* clear FLOAT and set SET */
break;
/* set FLOAT */
break;
default:
break;
}
return LM_STATUS_SUCCESS;
}
/*
*------------------------------------------------------------------------
* lm_gpio_mult_write -
*
* Write a value to the requested GPIO pins (bits defined)
* User is expected to handle any port swapping and know exactly
* which pin(s) to drive.
*
*------------------------------------------------------------------------
*/
{
{
DbgBreakIf(!pdev);
return LM_STATUS_INVALID_PARAMETER ;
}
// lock before read
/* read GPIO and mask except the float bits */
switch (mode) {
/* clear FLOAT and set CLR */
break;
/* clear FLOAT and set SET */
break;
/* set FLOAT */
break;
default:
break;
}
if (rc == LM_STATUS_SUCCESS)
{
}
return rc;
}
/*
*------------------------------------------------------------------------
* lm_gpio_int_write -
*
* Set or clear the requested GPIO pin (with pin_num)
*
*------------------------------------------------------------------------
*/
{
/* The GPIO should be swapped if swap register is set and active */
if (pin_num > MISC_REGISTERS_GPIO_3)
{
return LM_STATUS_INVALID_PARAMETER;
}
// lock before read
/* read GPIO int */
switch (mode)
{
// clear SET and set CLR
break;
// clear CLR and set SET
break;
default:
break;
}
// unlock after write
return 0;
}
/*
*------------------------------------------------------------------------
* lm_spio_read -
*
* Read the value of the requested SPIO pin (with pin_num)
*
*------------------------------------------------------------------------
*/
{
// Read from MISC block the SPIO register
// Calculate the value with relevent OE set to 1 (for input).
// Calulate the mask for the read value.
switch (pin_num) {
case 0: // SPIO pins 0-2 do not have OE pins
break;
case 1:
break;
case 2:
break;
case 3: // SPIO pin 3 is not connected
return LM_STATUS_FAILURE;
case 4: // SPIO pins 4-7 have OE pins
break;
case 5:
break;
case 6:
break;
case 7:
break;
default:
return LM_STATUS_FAILURE;
}
// Write to SPIO register the value with the relevant OE set to 1
// Read from MISC block the SPIO register
// Get the requested pin value by masking the val with mask
{
*value_ptr = 1;
}
else
{
*value_ptr = 0;
}
return LM_STATUS_SUCCESS;
}
/*
*------------------------------------------------------------------------
* lm_spio_write -
*
* Write a value to the requested SPIO pin (with pin_num)
*
*------------------------------------------------------------------------
*/
{
{
DbgBreakIf(!pdev);
return LM_STATUS_INVALID_PARAMETER ;
}
// lock before read
// Read from MISC block the SPIO register
// Turn the requested SPIO pin to output by setting its OE bit to 0 and
// If value is 1 set the relevant SET bit to 1, otherwise set the CLR bit to 1.
// SPIO pin 3 is not connected
} else {
// Set pin as OUTPUT
// Clear the pins CLR and SET bits
// If value is 1 set the SET bit of this pin, otherwise set the CLR bit.
}
if( LM_STATUS_SUCCESS == lm_status )
{
// Write to SPIO register the value with the relevant OE set to 1 and
// If value is 1, set the relevant SET bit to 1, otherwise set the CLR bit to 1.
}
// unlock
return lm_status ;
}
/*
*------------------------------------------------------------------------
* lm_set_led_mode -
*
* Set the led mode of the requested port
*
*------------------------------------------------------------------------
*/
{
DbgBreakIf(!pdev);
// Write to relevant NIG register LED_MODE (P0 or P1) the mode index (0-15)
switch (port_idx) {
case 0:
break;
case 1:
break;
default:
return LM_STATUS_FAILURE;
}
DbgMessage(NULL, INFORM, "lm_set_led_mode() wrote to NIG_REG_LED_MODE (port %d) 0x%x\n", port_idx, mode_idx);
return LM_STATUS_SUCCESS;
}
/*
*------------------------------------------------------------------------
* lm_get_led_mode -
*
* Get the led mode of the requested port
*
*------------------------------------------------------------------------
*/
{
DbgBreakIf(!pdev);
// Read from the relevant NIG register LED_MODE (P0 or P1) the mode index (0-15)
switch (port_idx) {
case 0:
break;
case 1:
break;
default:
return LM_STATUS_FAILURE;
}
DbgMessage(NULL, INFORM, "lm_get_led_mode() read from NIG_REG_LED_MODE (port %d) 0x%x\n", port_idx, *mode_idx_ptr);
return LM_STATUS_SUCCESS;
}
/*
*------------------------------------------------------------------------
* lm_override_led_value -
*
* Override the led value of the requsted led
*
*------------------------------------------------------------------------
*/
lm_status_t lm_override_led_value(struct _lm_device_t *pdev, u32_t port_idx, u32_t led_idx, u32_t value)
{
// If port 0 then use EMAC0, else use EMAC1
DbgBreakIf(!pdev);
DbgMessage(NULL, INFORM, "lm_override_led_value() port %d led_idx %d value %d\n", port_idx, led_idx, value);
switch (led_idx) {
case 0: //10MB led
// Read the current value of the LED register in the EMAC block
// Set the OVERRIDE bit to 1
// If value is 1, set the 10M_OVERRIDE bit, otherwise reset it.
break;
case 1: //100MB led
// Read the current value of the LED register in the EMAC block
// Set the OVERRIDE bit to 1
// If value is 1, set the 100M_OVERRIDE bit, otherwise reset it.
break;
case 2: //1000MB led
// Read the current value of the LED register in the EMAC block
// Set the OVERRIDE bit to 1
// If value is 1, set the 1000M_OVERRIDE bit, otherwise reset it.
reg_val = (value==1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) : (reg_val & ~EMAC_LED_1000MB_OVERRIDE);
break;
case 3: //2500MB led
// Read the current value of the LED register in the EMAC block
// Set the OVERRIDE bit to 1
// If value is 1, set the 2500M_OVERRIDE bit, otherwise reset it.
reg_val = (value==1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) : (reg_val & ~EMAC_LED_2500MB_OVERRIDE);
break;
case 4: //10G led
if (port_idx == 0) {
} else {
}
break;
case 5: //TRAFFIC led
// Find if the traffic control is via BMAC or EMAC
if (port_idx == 0) {
} else {
}
// Override the traffic led in the EMAC:
if (reg_val == 1) {
// Read the current value of the LED register in the EMAC block
// Set the TRAFFIC_OVERRIDE bit to 1
// If value is 1, set the TRAFFIC bit, otherwise reset it.
} else { // Override the traffic led in the BMAC:
if (port_idx == 0) {
} else {
}
}
break;
default:
return LM_STATUS_FAILURE;
}
return LM_STATUS_SUCCESS;
}
/*
*------------------------------------------------------------------------
* lm_blink_traffic_led -
*
* Blink the traffic led with the requsted rate
*
*------------------------------------------------------------------------
*/
{
// If port 0 then use EMAC0, else use EMAC1
DbgBreakIf(!pdev);
// Find if the traffic control is via BMAC or EMAC
if (port_idx == 0) {
} else {
}
// Blink the traffic led using EMAC control:
if (reg_val == 1) {
// Read the current value of the LED register in the EMAC block
// Set the TRAFFIC_OVERRIDE, TRAFFIC and BLNK_TRAFFIC to 1
// If rate field was entered then set the BLNK_RATE_ENA bit and the BLNK_RATE field,
// Otherwise the blink rate will be about 16Hz
if (rate != 0) {
}
DbgMessage(NULL, INFORM, "lm_blink_traffic_led() port %d write to EMAC_REG_EMAC_LED the value 0x%x\n", port_idx, reg_val);
} else { // Blink the traffic led in the BMAC:
// Set the CONTROL_OVERRIDE_TRAFFIC and the CONTROL_BLINK_TRAFFIC to 1.
if (port_idx == 0) {
// If the rate field was entered, update the BLINK_RATE register accordingly
if (rate != 0) {
DbgMessage(NULL, INFORM, "lm_blink_traffic_led() port %d write to NIG_REG_LED_CONTROL_BLINK_RATE_P0 %x\n", port_idx, rate);
}
} else {
// If the rate field was entered, update the BLINK_RATE register accordingly
if (rate != 0) {
DbgMessage(NULL, INFORM, "lm_blink_traffic_led() port %d write to NIG_REG_LED_CONTROL_BLINK_RATE_P1 0x%x\n", port_idx, rate);
}
}
}
return LM_STATUS_SUCCESS;
}
/*
*------------------------------------------------------------------------
* lm_get_led_status -
*
* Get the led status of the requsted led, on the requested port
*
*------------------------------------------------------------------------
*/
lm_status_t lm_get_led_status(struct _lm_device_t *pdev, u32_t port_idx, u32_t led_idx, u32_t* value_ptr)
{
// If port 0 then use EMAC0, else use EMAC1
DbgBreakIf(!pdev);
switch (led_idx) {
case 0: //10MB LED
// Read the current value of the LED register in the EMAC block
// Check the 10MB bit status
break;
case 1: //100MB LED
// Read the current value of the LED register in the EMAC block
// Check the 100MB bit status
break;
case 2: //1000MB LED
// Read the current value of the LED register in the EMAC block
// Check the 1000MB bit status
break;
case 3: //2500MB LED
// Read the current value of the LED register in the EMAC block
// Check the 2500MB bit status
break;
case 4: //10G LED
if (port_idx == 0) {
} else {
}
break;
case 5: //TRAFFIC LED
// Read the traffic led from the EMAC block
// Check the TRAFFIC_STAT bit status
// Read the traffic led from the BMAC block
if (port_idx == 0) {
} else {
}
break;
default:
return LM_STATUS_FAILURE;
}
DbgMessage(NULL, INFORM, "lm_get_led_status() port %d led_idx %d value %d\n", port_idx, led_idx, *value_ptr);
return LM_STATUS_SUCCESS;
}
/*
*------------------------------------------------------------------------
* lm_reset_led -
*
* Sets the LEDs to operational mode after establishing link
*
*------------------------------------------------------------------------
*/
void
{
//u32_t val;
DbgBreakIf(!pdev);
return;
}
}
{
{
return 0;
}
/* read status from PCIE core */
/* if interrupt line value from PCIE core is not asserted then take no action (different problem) */
#define PCIE_CORE_INT_PENDING_BIT 0X00080000 /* when this bit is set, interrupt is asserted (pending) */
{
return 0;
}
/* if interrupt line from PCIE core is not enabled then take no action (different problem) */
{
return 0;
}
/* read interrupt mask from IGU */
/* if not 1FFFF then write warning to log (suspected as different problem) and continue to following step */
if(val != 0x0001ffff)
{
DbgMessage(pdev, WARN, "IGU int mask != 0x1ffff - might not be related to debugging INTA/B issue\n");
}
/* verify that int_line_en_0/1 is 1. If bit is clear then no action write warning to log and return. */
// We skip this check.
return 1;
}
/** lm_57710A0_dbg_intr
*
* Description:
* 1. some sanity checks that the case we have is indeed the
* interrupt debugging mode.
* 2. Apply special handling, that is to disable and enable
* INTA/B in IGU
*/
{
{
}
}
/*******************************************************************************
* Description: turn led on/off/operational mode
* Must be called under PHY_LOCK
* Return:
******************************************************************************/
{
elink_res = elink_set_led( &pdev->params.link, &pdev->vars.link, led_mode, pdev->vars.link.line_speed );
switch(elink_res)
{
case ELINK_STATUS_OK:
break;
case ELINK_STATUS_ERROR:
default:
break;
}// switch elink_res
return lm_status;
} /* lm_set_led */
/*******************************************************************************
* Description: Reads the parametrs using elink interface
* Must be called under PHY_LOCK
* Return:
******************************************************************************/
{
// we use local variables (vendor_name, model_num etc...) to protect flows in IA64
// that upper layer might send us non-aligned to u16_t pointer, in this case a BSOD might occur.
// using local variables and than memcpy prevent such situation.
if CHK_NULL( b10_transceiver_data )
{
return LM_STATUS_INVALID_PARAMETER;
}
ptr_arr[0] = &vendor_name[0];
{
DbgBreakIf(1);
return LM_STATUS_FAILURE;
}
// query from elink all ext_phy types (currently 1 and 2)
{
{
// only in case not SFP+ - the elink query is supported
{
elink_res = elink_read_sfp_module_eeprom( &pdev->params.link.phy[ext_phy_type], // ELINK_INT_PHY, ELINK_EXT_PHY1, ELINK_EXT_PHY2
eeprom_data[idx][0],
if( ELINK_STATUS_OK != elink_res )
{
// We assume that if one of the queries failed - there is an error so we break this loop
break;
}
} // for "eeprom_data" size
// only one sfp+ module is expected on board so we exit the ext_phy_type loop
break;
} // ELINK_ETH_PHY_SFP_FIBER == media_type
} // for "ext_phy_type"
switch(elink_res)
{
case ELINK_STATUS_OK:
{
}
break;
case ELINK_STATUS_TIMEOUT:
break;
case ELINK_STATUS_ERROR:
default:
break;
}// switch elink_res
return lm_status;
} /* lm_get_transceiver_data */
lm_status_t lm_set_mac_in_nig(lm_device_t * pdev, u8_t * mac_addr, lm_cli_idx_t lm_cli_idx, u8_t offset)
{
if (lm_cli_idx == LM_CLI_IDX_ISCSI)
{
}
else if (offset == ECORE_LLH_CAM_ISCSI_ETH_LINE)
{
}
if (CHIP_IS_E1x(pdev) || !IS_MULTI_VNIC(pdev) || IS_MF_SD_MODE(pdev) || offset >= MAX_MAC_OFFSET_IN_NIG)
{
return LM_STATUS_SUCCESS;
}
/* in switch-independt mode we need to configure the NIG LLH with the appropriate mac addresses, we use the
* cam mapping 1--1 for all indices smaller than 16 */
if (mac_addr)
{
DbgMessage(pdev, WARN, "Setting mac in nig to offset: %d mac_addr[%02x]:[%02x]:[%02x]:[%02x]:[%02x]:[%02x]\n", offset,
if (offset < MAX_OFFSET_IN_MEM_1)
{
}
else
{
reg_offset = (PORT_ID(pdev)? NIG_REG_P1_LLH_FUNC_MEM2: NIG_REG_P0_LLH_FUNC_MEM2) + 8*(offset - MAX_OFFSET_IN_MEM_1);
}
enable_mac = 1;
}
if (offset < MAX_OFFSET_IN_MEM_1)
{
reg_offset = (PORT_ID(pdev)? NIG_REG_LLH1_FUNC_MEM_ENABLE : NIG_REG_LLH0_FUNC_MEM_ENABLE) + 4*offset;
}
else
{
reg_offset = (PORT_ID(pdev)? NIG_REG_P1_LLH_FUNC_MEM2_ENABLE : NIG_REG_P0_LLH_FUNC_MEM2_ENABLE) + 4*(offset - MAX_OFFSET_IN_MEM_1);
}
return LM_STATUS_SUCCESS;
}
/**
* Table to lookup appropriate lock register for function.
*
* Indexed with func ID (0-7).
*
* Note registers are *not* consecutive, thus table.
*/
MISC_REG_DRIVER_CONTROL_1, /* 0 */
MISC_REG_DRIVER_CONTROL_2, /* 1 */
MISC_REG_DRIVER_CONTROL_3, /* 2 */
MISC_REG_DRIVER_CONTROL_4, /* 3 */
MISC_REG_DRIVER_CONTROL_5, /* 4 */
MISC_REG_DRIVER_CONTROL_6, /* 5 */
MISC_REG_DRIVER_CONTROL_7, /* 6 */
MISC_REG_DRIVER_CONTROL_8, /* 7 */
};
/*******************************************************************************
* Description:
* Acquiring the HW lock for a specific resource.
* The assumption is that only 1 bit is set in the resource parameter
* There is a HW attention in case the same function attempts to
* acquire the same lock more than once
*
* Params:
* resource: the HW LOCK Register name
* b_block: Try to get lock until succesful, or backout immediately on failure.
* Return:
* Success - got the lock
* Fail - Invalid parameter or could not obtain the lock for our 1 sec in block mode
* or couldn't obtain lock one-shot in non block mode
******************************************************************************/
{
// Validating the resource in within range
{
DbgBreakMsg("lm_hw_lock: LM_STATUS_INVALID_PARAMETER\n");
return LM_STATUS_INVALID_PARAMETER;
}
// Validating that the resource is not already taken
if (lock_status & resource_bit)
{
DbgMessage(pdev, FATAL , "lm_hw_lock: LM_STATUS_EXISTING_OBJECT lock_status=0x%x resource_bit=0x%x\n", lock_status, resource_bit);
DbgBreakMsg("lm_hw_lock: LM_STATUS_EXISTING_OBJECT\n");
return LM_STATUS_EXISTING_OBJECT;
}
// Try for 16 second every 50us
{
// Try to acquire the lock
if (lock_status & resource_bit)
{
return LM_STATUS_SUCCESS;
}
if (!b_block)
{
return LM_STATUS_FAILURE;
}
}
DbgBreakMsg("lm_hw_lock: FAILED LM_STATUS_TIMEOUT\n");
return LM_STATUS_TIMEOUT;
}
/*******************************************************************************
* Description:
* Releasing the HW lock for a specific resource.
* There is a HW attention in case the a function attempts to release
* a lock that it did not acquire (if b_verify_locked is TRUE, default)
* Return:
* Success - if the parameter is valid, the assumption is that it
* will succeed
* Fail - Invalid parameter
******************************************************************************/
const u8_t b_verify_locked )
{
// Validating the resource in within range
{
DbgBreakMsg("lm_hw_unlock: LM_STATUS_INVALID_PARAMETER\n");
return LM_STATUS_INVALID_PARAMETER;
}
// Validating that the resource is currently taken
if (!(lock_status & resource_bit))
{
// This comment is explicitly outside the IF since we still want to be aware it happened.
DbgMessage(pdev, FATAL, "lm_hw_unlock: LM_STATUS_OBJECT_NOT_FOUND lock_status=0x%x resource_bit=0x%x\n", lock_status, resource_bit);
if( b_verify_locked )
{
DbgBreakMsg("lm_hw_unlock: LM_STATUS_OBJECT_NOT_FOUND\n");
return LM_STATUS_OBJECT_NOT_FOUND;
}
}
return LM_STATUS_SUCCESS;
}
/*******************************************************************************
* Description:
* Releasing the HW lock for a specific resource.
* There is a HW attention in case the a function attempts to release
* a lock that it did not acquire
THIS function is a wrapper function now for lm_hw_unlock_ex.
* Return:
* Success - if the parameter is valid, the assumption is that it
* will succeed
* Fail - Invalid parameter
******************************************************************************/
{
}
/**
* @Desription
* This function is used to recover from a state where the
* locks stayed in "taken" state during a reboot. We want
* to clear all the locks before proceeding.
*
* @param pdev
*/
{
/* We clear locks due to error recover possible failure leaving locking traces...
* we do this only for E2 and above */
if (CHIP_IS_E1x(pdev))
{
return;
}
{
if (lock_status != 0)
{
}
}
}
u32_t reg_wait_verify_val(struct _lm_device_t * pdev, u32_t reg_offset, u32_t excpected_val, u32_t total_wait_time_ms )
{
if( wait_cnt_limit == 0 )
{
wait_cnt_limit = 1;
}
{
}
if (val != excpected_val) {
}
return wait_cnt;
}
/*******************************************************************************
* Description:
* after this function is called, no write to chip is availalbe anymore.
* Return:
* void
******************************************************************************/
{
{
if (CHIP_IS_E1x(pdev))
{
/* Disable bus_master. */
}
else
{
/* In E2, there is a cleaner way to disable pci-dma, no need for a pci-configuration
* transaction */
}
/* wait until there is no pending transaction. */
if (b_wait_for_done)
{
{
{
break;
}
}
}
}
}
/*******************************************************************************
* Description:
* enable Bus Master Enable
* Return:
* void
******************************************************************************/
{
{
if (CHIP_IS_E1x(pdev))
{
/* Enable bus_master. */
{
}
}
else
{
/* In E2, there is a cleaner way to disable pci-dma, no need for a pci-configuration
* transaction */
}
}
}
/*******************************************************************************
* Description:
* disable non fatal error pcie reporting
* Return:
* void
******************************************************************************/
{
{
}
}
// These lm_reg_xx_ind_imp() are for blk reading when lock is acquired only once (for the whole block reading)
void
{
} /* lm_reg_rd_ind_imp */
void
{
} /* lm_reg_wr_ind_imp */
/*******************************************************************************
* Description:
*
* Return:
* None.
*
* Note:
* The caller is responsible for synchronizing calls to lm_reg_rd_ind and
* lm_reg_wr_ind.
******************************************************************************/
void
{
} /* lm_reg_rd_ind */
/*******************************************************************************
* Description:
*
* Return:
* None.
*
* Note:
* The caller is responsible for synchronizing calls to lm_reg_rd_ind and
* lm_reg_wr_ind.
******************************************************************************/
void
{
} /* lm_reg_wr_ind */
/*******************************************************************************
* Description:
*
* Return:
******************************************************************************/
void
{
while(u32t_cnt)
{
buf_ptr++;
u32t_cnt--;
current_offset += 4;
}
} /* lm_reg_rd_blk */
/*******************************************************************************
* Description:
*
* Return:
******************************************************************************/
void
{
{
}
while(u32t_cnt)
{
buf_ptr++;
u32t_cnt--;
current_offset += 4;
}
{
}
} /* lm_reg_rd_blk_ind */
/*******************************************************************************
* Description:
*
* Return:
******************************************************************************/
void
{
while(u32t_cnt)
{
data_ptr++;
u32t_cnt--;
current_offset += 4;
}
} /* lm_reg_wr_blk */
/*******************************************************************************
* Description:
*
* Return:
******************************************************************************/
void
{
while(u32t_cnt)
{
data_ptr++;
u32t_cnt--;
current_offset += 4;
}
} /* lm_reg_wr_blk_ind */
{
}
const u8_t b_idle_chk,
const u8_t b_storms_asserts,
const u8_t b_dorrbell_info )
{
if( b_idle_chk )
{
}
if( b_dorrbell_info )
{
}
if( b_storms_asserts )
{
}
#endif
}