Neterion: New driver: Traffic & alarm handler
Subsystems (2)
PATCH 7/10 Neterion: New driver: Traffic & alarm handler
This patch takes care of trafic handling related APIS.
- Interrupt Enable and disable
- Mask / Unmask Interrupt
- Traffic Interrupt handling.
- Alarm Interrupt handling.
Signed-off-by Sivakumar Subramani <[email protected]>
Signed-off-by Rastapur Santosh <[email protected]>
Signed-off-by Ramkrishna Vepa <[email protected]>
---
drivers/net/vxge/vxge-traffic.c +2969 -0
@@ -0,0 +1,2969 @@ +/****************************************************************************** +* This software may be used and distributed according to the terms of +* the GNU General Public License (GPL), incorporated herein by reference. +* Drivers based on or derived from this code fall under the GPL and must +* retain the authorship, copyright and license notice. This file is not +* a complete program and may only be used when the entire operating +* system is licensed under the GPL. +* See the file COPYING in this distribution for more information. +******************************************************************************/ +/******************************************************************************* +* vxge-traffic.c: Driver for Neterion Inc's X3100 Series 10GbE PCIe I/O +* Virtualized Server Adapter. +* Copyright(c) 2002-2009 Neterion Inc. +******************************************************************************/ +#include <linux/version.h> +#include <linux/pci.h> +#include <linux/vmalloc.h> +#include <linux/netdevice.h> +#include <linux/inetdevice.h> +#include <linux/if_vlan.h> +#include <linux/etherdevice.h> + +#include "vxge-traffic.h" +#include "vxge-config.h" +#include "vxge-main.h" + +/* +* vxge_hw_vpath_intr_enable - Enable vpath interrupts. +* @vp: Virtual Path handle. +* +* Enable vpath interrupts. The function is to be executed the last in +* vpath initialization sequence. +* +* See also: vxge_hw_vpath_intr_disable() +*/ +enum vxge_hw_status vxge_hw_vpath_intr_enable ( +struct __hw_vpath_handle *vp) +{ +u64 val64; + +struct __hw_virtualpath *vpath; +enum vxge_hw_status status =VXGE_HW_OK ; +vxge_assert (vp !=NULL ); + +if (vp ==NULL ) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + vpath = (struct __hw_virtualpath *)vp->vpath; +vxge_assert (vpath !=NULL ); + +if (vpath->vp_open ==VXGE_HW_VP_NOT_OPEN ) { + status =VXGE_HW_ERR_VPATH_NOT_OPEN ; + goto exit; + } + +writeq (VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->kdfcctl_errors_reg); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->general_errors_reg); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->pci_config_errors_reg); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->mrpcim_to_vpath_alarm_reg); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->srpcim_to_vpath_alarm_reg); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->vpath_ppif_int_status); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->srpcim_msg_to_vpath_reg); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->vpath_pcipif_int_status); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->prc_alarm_reg); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->wrdma_alarm_status); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->asic_ntwk_vp_err_reg); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->xgmac_vp_int_status); + + val64 =readq (&vpath->vp_reg->vpath_general_int_status); + +/* Mask unwanted interrupts */ + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->vpath_pcipif_int_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->srpcim_msg_to_vpath_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->srpcim_to_vpath_alarm_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->mrpcim_to_vpath_alarm_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->pci_config_errors_mask); + +/* Unmask the individual interrupts */ + +writeq ((u32 )bVAL32 ((VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO1_OVRFLOW | +VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO2_OVRFLOW | +VXGE_HW_GENERAL_ERRORS_REG_STATSB_DROP_TIMEOUT_REQ | +VXGE_HW_GENERAL_ERRORS_REG_STATSB_PIF_CHAIN_ERR ),0 ), + &vpath->vp_reg->general_errors_mask); + +__hw_pio_mem_write32_upper ( + (u32 )bVAL32 ((VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_OVRWR | +VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_OVRWR | +VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_POISON | +VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_POISON | +VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_DMA_ERR | +VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_DMA_ERR ),0 ), + &vpath->vp_reg->kdfcctl_errors_mask); + +__hw_pio_mem_write32_upper (0 , + &vpath->vp_reg->vpath_ppif_int_mask); + +__hw_pio_mem_write32_upper ( + (u32 )bVAL32 (VXGE_HW_PRC_ALARM_REG_PRC_RING_BUMP ,0 ), + &vpath->vp_reg->prc_alarm_mask); + +__hw_pio_mem_write32_upper (0 , + &vpath->vp_reg->wrdma_alarm_mask); + +__hw_pio_mem_write32_upper (0 , + &vpath->vp_reg->xgmac_vp_int_mask); + +if (vpath->hldev->first_vp_id != vpath->vp_id) +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->asic_ntwk_vp_err_mask); +else +__hw_pio_mem_write32_upper ((u32 )bVAL32 (( +VXGE_HW_ASIC_NTWK_VP_ERR_REG_XMACJ_NTWK_REAFFIRMED_FAULT | +VXGE_HW_ASIC_NTWK_VP_ERR_REG_XMACJ_NTWK_REAFFIRMED_OK ),0 ), + &vpath->vp_reg->asic_ntwk_vp_err_mask); + +__hw_pio_mem_write32_upper (0 , + &vpath->vp_reg->vpath_general_int_mask); +exit: + +return status; + +} + +/* +* vxge_hw_vpath_intr_disable - Disable vpath interrupts. +* @vp: Virtual Path handle. +* +* Disable vpath interrupts. The function is to be executed the last in +* vpath initialization sequence. +* +* See also: vxge_hw_vpath_intr_enable() +*/ +enum vxge_hw_status vxge_hw_vpath_intr_disable ( +struct __hw_vpath_handle *vp) +{ +u64 val64; + +struct __hw_virtualpath *vpath; +enum vxge_hw_status status =VXGE_HW_OK ; +vxge_assert (vp !=NULL ); + +if (vp ==NULL ) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + vpath = (struct __hw_virtualpath *)vp->vpath; +vxge_assert (vpath !=NULL ); + +if (vpath->vp_open ==VXGE_HW_VP_NOT_OPEN ) { + status =VXGE_HW_ERR_VPATH_NOT_OPEN ; + goto exit; + } + +__hw_pio_mem_write32_upper ( + (u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->vpath_general_int_mask); + + val64 =VXGE_HW_TIM_CLR_INT_EN_VP (1 << (16 - vpath->vp_id)); + +writeq (VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->kdfcctl_errors_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->general_errors_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->pci_config_errors_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->mrpcim_to_vpath_alarm_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->srpcim_to_vpath_alarm_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->vpath_ppif_int_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->srpcim_msg_to_vpath_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->vpath_pcipif_int_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->wrdma_alarm_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->prc_alarm_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->xgmac_vp_int_mask); + +__hw_pio_mem_write32_upper ((u32 )VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->asic_ntwk_vp_err_mask); + +exit: + +return status; + +} + +/** +* vxge_hw_channel_msix_mask - Mask MSIX Vector. +* @channeh: Channel for rx or tx handle +* @msix_id: MSIX ID +* +* The function masks the msix interrupt for the given msix_id +* +* Note: +* +* Returns: 0 +*/ +void +vxge_hw_channel_msix_mask (struct __hw_channel *channel,int msix_id) +{ + +__hw_pio_mem_write32_upper ( + (u32 )bVAL32 (vxge_mBIT (channel->first_vp_id+(msix_id/4 )),0 ), + &channel->common_reg->set_msix_mask_vect[msix_id%4 ]); + +return ; +} + +/** +* vxge_hw_channel_msix_unmask - Unmask the MSIX Vector. +* @channeh: Channel for rx or tx handle +* @msix_id: MSI ID +* +* The function unmasks the msix interrupt for the given msix_id +* +* Note: +* +* Returns: 0 +*/ +void +vxge_hw_channel_msix_unmask (struct __hw_channel *channel,int msix_id) +{ + +__hw_pio_mem_write32_upper ( + (u32 )bVAL32 (vxge_mBIT (channel->first_vp_id+(msix_id/4 )),0 ), + &channel->common_reg->clear_msix_mask_vect[msix_id%4 ]); + +return ; +} + +/** +* vxge_hw_device_set_intr_type - Updates the configuration +* with new interrupt type. +* @hldev: HW device handle. +* @intr_mode: New interrupt type +*/ +u32 vxge_hw_device_set_intr_type (struct __hw_device *hldev,u32 intr_mode) +{ + +if ((intr_mode !=VXGE_HW_INTR_MODE_IRQLINE ) && + (intr_mode !=VXGE_HW_INTR_MODE_MSIX ) && + (intr_mode !=VXGE_HW_INTR_MODE_MSIX_ONE_SHOT ) && + (intr_mode !=VXGE_HW_INTR_MODE_DEF )) + intr_mode =VXGE_HW_INTR_MODE_IRQLINE ; + + hldev->config.intr_mode = intr_mode; +return intr_mode; +} + +/** +* vxge_hw_device_intr_enable - Enable interrupts. +* @hldev: HW device handle. +* @op: One of the enum vxge_hw_device_intr enumerated values specifying +* the type(s) of interrupts to enable. +* +* Enable Titan interrupts. The function is to be executed the last in +* Titan initialization sequence. +* +* See also: vxge_hw_device_intr_disable() +*/ +void vxge_hw_device_intr_enable (struct __hw_device *hldev) +{ +u32 i; +u64 val64; +u32 val32; + +vxge_assert (hldev); + +for (i =0 ; i <VXGE_HW_MAX_VIRTUAL_PATHS ; i++) { + +if (!(hldev->vpaths_deployed &vxge_mBIT (i))) +continue ; + +vxge_hw_vpath_intr_enable ( +VXGE_HW_VIRTUAL_PATH_HANDLE (&hldev->virtual_paths[i])); + } + +if (hldev->config.intr_mode ==VXGE_HW_INTR_MODE_IRQLINE ) { + val64 = hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_TX ] | + hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_RX ]; + +if (val64 !=0 ) { +writeq (val64, &hldev->common_reg->tim_int_status0); + +writeq (~val64, &hldev->common_reg->tim_int_mask0); + } + + val32 = hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_TX ] | + hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_RX ]; + +if (val32 !=0 ) { +__hw_pio_mem_write32_upper (val32, + &hldev->common_reg->tim_int_status1); + +__hw_pio_mem_write32_upper (~val32, + &hldev->common_reg->tim_int_mask1); + } + } + + val64 =readq (&hldev->common_reg->titan_general_int_status); + +vxge_hw_device_unmask_all (hldev); + +return ; +} + +/** +* vxge_hw_device_intr_disable - Disable Titan interrupts. +* @hldev: HW device handle. +* @op: One of the enum vxge_hw_device_intr enumerated values specifying +* the type(s) of interrupts to disable. +* +* Disable Titan interrupts. +* +* See also: vxge_hw_device_intr_enable() +*/ +void vxge_hw_device_intr_disable (struct __hw_device *hldev) +{ +u32 i; + +vxge_assert (hldev); + +vxge_hw_device_mask_all (hldev); + +/* mask all the tim interrupts */ +writeq (VXGE_HW_INTR_MASK_ALL , &hldev->common_reg->tim_int_mask0); +__hw_pio_mem_write32_upper (VXGE_HW_DEFAULT_32 , + &hldev->common_reg->tim_int_mask1); + +for (i =0 ; i <VXGE_HW_MAX_VIRTUAL_PATHS ; i++) { + +if (!(hldev->vpaths_deployed &vxge_mBIT (i))) +continue ; + +vxge_hw_vpath_intr_disable ( +VXGE_HW_VIRTUAL_PATH_HANDLE (&hldev->virtual_paths[i])); + } + +return ; +} + +/** +* vxge_hw_device_mask_all - Mask all device interrupts. +* @hldev: HW device handle. +* +* Mask all device interrupts. +* +* See also: vxge_hw_device_unmask_all() +*/ +void vxge_hw_device_mask_all (struct __hw_device *hldev) +{ +u64 val64; + +vxge_assert (hldev); + + val64 =VXGE_HW_TITAN_MASK_ALL_INT_ALARM | +VXGE_HW_TITAN_MASK_ALL_INT_TRAFFIC ; + +__hw_pio_mem_write32_upper ((u32 )bVAL32 (val64,0 ), + &hldev->common_reg->titan_mask_all_int); + +return ; +} + +/** +* vxge_hw_device_unmask_all - Unmask all device interrupts. +* @hldev: HW device handle. +* +* Unmask all device interrupts. +* +* See also: vxge_hw_device_mask_all() +*/ +void vxge_hw_device_unmask_all (struct __hw_device *hldev) +{ +u64 val64 =0 ; + +vxge_assert (hldev); + +if (hldev->config.intr_mode ==VXGE_HW_INTR_MODE_IRQLINE ) + val64 =VXGE_HW_TITAN_MASK_ALL_INT_TRAFFIC ; + +__hw_pio_mem_write32_upper ((u32 )bVAL32 (val64,0 ), + &hldev->common_reg->titan_mask_all_int); + +return ; +} + +/** +* vxge_hw_device_flush_io - Flush io writes. +* @hldev: HW device handle. +* +* The function performs a read operation to flush io writes. +* +* Note: +* +* Returns: void +*/ +void vxge_hw_device_flush_io (struct __hw_device *hldev) +{ +u32 val32; + +vxge_assert (hldev !=NULL ); + + val32 =readl (&hldev->common_reg->titan_general_int_status); +} + +/** +* vxge_hw_device_begin_irq - Begin IRQ processing. +* @hldev: HW device handle. +* @skip_alarms: Do not clear the alarms +* @reason: "Reason" for the interrupt, the value of Titan'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: +* vxge_hw_device_begin_irq() does not flush MMIO writes through the +* bridge. Therefore, two back-to-back interrupts are potentially possible. +* +* Returns: 0, if the interrupt is not "ours" (note that in this case the +* device remain enabled). +* Otherwise, vxge_hw_device_begin_irq() returns 64bit general adapter +* status. +*/ +enum vxge_hw_status vxge_hw_device_begin_irq ( +struct __hw_device *hldev, +u32 skip_alarms, +u64 *reason) +{ +u32 i; +u64 val64; +u64 adapter_status; +u64 vpath_mask; +enum vxge_hw_status ret =VXGE_HW_OK ; + +vxge_assert ((hldev !=NULL ) && (reason !=NULL )); + + val64 =readq (&hldev->common_reg->titan_general_int_status); + +if (unlikely (!val64)) { +/* not Titan interrupt */ + *reason =0 ; + ret =VXGE_HW_ERR_WRONG_IRQ ; + goto exit; + } + +if (unlikely (val64 ==VXGE_HW_ALL_FOXES )) { + + adapter_status =readq (&hldev->common_reg->adapter_status); + +if (adapter_status ==VXGE_HW_ALL_FOXES ) { + +__hw_device_handle_error (hldev, +NULL_VPID ,VXGE_HW_EVENT_SLOT_FREEZE ); + *reason =0 ; + ret =VXGE_HW_ERR_SLOT_FREEZE ; + goto exit; + } + } + + hldev->stats.sw_dev_info_stats.total_intr_cnt++; + + *reason = val64; + + vpath_mask = hldev->vpaths_deployed >> + (64 -VXGE_HW_MAX_VIRTUAL_PATHS ); + +if (val64 & +VXGE_HW_TITAN_GENERAL_INT_STATUS_VPATH_TRAFFIC_INT (vpath_mask)) { + hldev->stats.sw_dev_info_stats.traffic_intr_cnt++; + +return VXGE_HW_OK ; + } + + hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt++; + +if (unlikely (val64 & +VXGE_HW_TITAN_GENERAL_INT_STATUS_VPATH_ALARM_INT )) { + +enum vxge_hw_status error_level =VXGE_HW_OK ; + + hldev->stats.sw_dev_err_stats.vpath_alarms++; + +for (i =0 ; i <VXGE_HW_MAX_VIRTUAL_PATHS ; i++) { + +if (!(hldev->vpaths_deployed &vxge_mBIT (i))) +continue ; + + ret =__hw_vpath_alarm_process ( + &hldev->virtual_paths[i], + skip_alarms); + + error_level =VXGE_HW_SET_LEVEL (ret, error_level); + +if (unlikely ((ret ==VXGE_HW_ERR_CRITICAL ) || + (ret ==VXGE_HW_ERR_SLOT_FREEZE ))) +break ; + } + + ret = error_level; + } +exit: + +return ret; +} + +/* +* __hw_device_handle_link_up_ind +* @hldev: HW device handle. +* +* Link up indication handler. The function is invoked by HW when +* Titan indicates that the link is up for programmable amount of time. +*/ +enum vxge_hw_status +__hw_device_handle_link_up_ind (struct __hw_device *hldev) +{ +vxge_assert (hldev); + +/* +* If the previous link state is not down, return. +*/ +if (hldev->link_state ==VXGE_HW_LINK_UP ) + goto exit; + + hldev->link_state =VXGE_HW_LINK_UP ; + +/* notify driver */ +if (hldev->uld_callbacks.link_up) + hldev->uld_callbacks.link_up (hldev, hldev->upper_layer_data); +exit: + +return VXGE_HW_OK ; +} + +/* +* __hw_device_handle_link_down_ind +* @hldev: HW device handle. +* +* Link down indication handler. The function is invoked by HW when +* Titan indicates that the link is down. +*/ +enum vxge_hw_status +__hw_device_handle_link_down_ind (struct __hw_device *hldev) +{ +vxge_assert (hldev); + +/* +* If the previous link state is not down, return. +*/ +if (hldev->link_state ==VXGE_HW_LINK_DOWN ) + goto exit; + + hldev->link_state =VXGE_HW_LINK_DOWN ; + +/* notify driver */ +if (hldev->uld_callbacks.link_down) + hldev->uld_callbacks.link_down (hldev, hldev->upper_layer_data); +exit: + +return VXGE_HW_OK ; +} + +/** +* __hw_device_handle_error - Handle error +* @hldev: HW device +* @vp_id: Vpath Id +* @type: Error type. Please see enum vxge_hw_event{} +* +* Handle error. +*/ +enum vxge_hw_status +__hw_device_handle_error ( +struct __hw_device *hldev, +u32 vp_id, +enum vxge_hw_event type) +{ +vxge_assert (hldev); + +switch (type) { +case VXGE_HW_EVENT_UNKNOWN : +break ; +case VXGE_HW_EVENT_RESET_START : +case VXGE_HW_EVENT_RESET_COMPLETE : +case VXGE_HW_EVENT_LINK_DOWN : +case VXGE_HW_EVENT_LINK_UP : + goto out; +case VXGE_HW_EVENT_ALARM_CLEARED : + goto out; +case VXGE_HW_EVENT_ECCERR : +case VXGE_HW_EVENT_MRPCIM_ECCERR : + goto out; +case VXGE_HW_EVENT_FIFO_ERR : +case VXGE_HW_EVENT_VPATH_ERR : +case VXGE_HW_EVENT_CRITICAL_ERR : +case VXGE_HW_EVENT_SERR : +break ; +case VXGE_HW_EVENT_SRPCIM_SERR : +case VXGE_HW_EVENT_MRPCIM_SERR : + goto out; +case VXGE_HW_EVENT_SLOT_FREEZE : +break ; +default : +vxge_assert (0 ); + goto out; +break ; + } + +/* notify driver */ +if (hldev->uld_callbacks.crit_err) + hldev->uld_callbacks.crit_err ( + (struct __hw_device *)hldev, + hldev->upper_layer_data, + type, + vp_id); +out: + +return VXGE_HW_OK ; +} + +/** +* vxge_hw_device_clear_tx_rx - Acknowledge (that is, clear) the +* condition that has caused the Tx and RX interrupt. +* @hldev: HW device. +* +* Acknowledge (that is, clear) the condition that has caused +* the Tx and Rx interrupt. +* See also: vxge_hw_device_begin_irq(), +* vxge_hw_device_mask_tx_rx(), vxge_hw_device_unmask_tx_rx(). +*/ +void vxge_hw_device_clear_tx_rx (struct __hw_device *hldev) +{ + +vxge_assert (hldev); + +if ((hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_TX ] !=0 ) || + (hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_RX ] !=0 )) { +writeq ((hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_TX ] | + hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_RX ]), + &hldev->common_reg->tim_int_status0); + } + +if ((hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_TX ] !=0 ) || + (hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_RX ] !=0 )) { +__hw_pio_mem_write32_upper ( + (hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_TX ] | + hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_RX ]), + &hldev->common_reg->tim_int_status1); + } + +return ; +} + +/** +* vxge_hw_device_restore_link_led - Restore link LED to its original state. +* @hldev: HW device handle. +* @port : Port number 0, 1, or 2 +* +* Restore link LED to its original state +*/ +enum vxge_hw_status +vxge_hw_device_restore_link_led ( +struct __hw_device *hldev, +u32 port) +{ +enum vxge_hw_status status =VXGE_HW_OK ; +return status; +} + +/** +* vxge_hw_device_flick_link_led - Flick (blink) link LED. +* @hldev: HW device handle. +* @port : Port number 0, 1, or 2 +* +* Flicker the link LED by using the beacon control register. +*/ +enum vxge_hw_status +vxge_hw_device_flick_link_led ( +struct __hw_device *hldev, +u32 port) +{ +enum vxge_hw_status status =VXGE_HW_OK ; +return status; +} + +/* +* vxge_hw_channel_dtr_alloc - Allocate a dtr from the channel +* @channelh: Channel +* @dtr: Buffer to return the DTR pointer +* +* Allocates a dtr from the reserve array. If the reserve array is empty, +* it swaps the reserve and free arrays. +* +*/ +enum vxge_hw_status +vxge_hw_channel_dtr_alloc (struct __hw_channel *channel,void **dtrh) +{ +void **tmp_arr; + +if (channel->reserve_ptr - channel->reserve_top >0 ) { +_alloc_after_swap: + *dtrh = channel->reserve_arr[--channel->reserve_ptr]; + +return VXGE_HW_OK ; + } + +/* 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->length - channel->free_ptr >0 ) { + + tmp_arr = channel->reserve_arr; + channel->reserve_arr = channel->free_arr; + channel->free_arr = tmp_arr; + channel->reserve_ptr = channel->length; + channel->reserve_top = channel->free_ptr; + channel->free_ptr = channel->length; + + channel->stats->reserve_free_swaps_cnt++; + + goto _alloc_after_swap; + } + + channel->stats->full_cnt++; + + *dtrh =NULL ; +return VXGE_HW_INF_OUT_OF_DESCRIPTORS ; +} + +/* +* vxge_hw_channel_dtr_post - Post a dtr to the channel +* @channelh: Channel +* @dtr: DTR pointer +* +* Posts a dtr to work array. +* +*/ +void +vxge_hw_channel_dtr_post (struct __hw_channel *channel,void *dtrh) +{ +vxge_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 ; +} + +/* +* vxge_hw_channel_dtr_try_complete - Returns next completed dtr +* @channelh: Channel +* @dtr: Buffer to return the next completed DTR pointer +* +* Returns the next completed dtr with out removing it from work array +* +*/ +void +vxge_hw_channel_dtr_try_complete (struct __hw_channel *channel,void **dtrh) +{ +vxge_assert (channel->work_arr); +vxge_assert (channel->compl_index < channel->length); + + *dtrh = channel->work_arr[channel->compl_index]; +} + +/* +* vxge_hw_channel_dtr_complete - Removes next completed dtr from the work array +* @channelh: Channel +* +* Removes the next completed dtr from work array +* +*/ +void +vxge_hw_channel_dtr_complete (struct __hw_channel *channel) +{ + channel->work_arr[channel->compl_index] =NULL ; + +/* wrap-around */ +if (++channel->compl_index == channel->length) + channel->compl_index =0 ; + + channel->stats->total_compl_cnt++; +} + +/* +* vxge_hw_channel_dtr_free - Frees a dtr +* @channelh: Channel +* @dtr: DTR pointer +* +* Returns the dtr to free array +* +*/ +void +vxge_hw_channel_dtr_free (struct __hw_channel *channel,void *dtrh) +{ + channel->free_arr[--channel->free_ptr] = dtrh; + +} + +/* +* vxge_hw_channel_dtr_count +* @channelh: Channel handle. Obtained via vxge_hw_channel_open(). +* +* Retreive number of DTRs available. This function can not be called +* from data path. ring_initial_replenishi() is the only user. +*/ +int +vxge_hw_channel_dtr_count (struct __hw_channel *channel) +{ +return (channel->reserve_ptr - channel->reserve_top) + + (channel->length - channel->free_ptr); +} + +/** +* vxge_hw_ring_rxd_reserve - Reserve ring descriptor. +* @ringh: Handle to the ring object used for receive +* @rxdh: Reserved descriptor. On success HW fills this "out" parameter +* with a valid handle. +* +* Reserve Rx descriptor for the subsequent filling-in driver +* and posting on the corresponding channel (@channelh) +* via vxge_hw_ring_rxd_post(). +* +* Returns: VXGE_HW_OK - success. +* VXGE_HW_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available. +* +*/ +enum vxge_hw_status vxge_hw_ring_rxd_reserve ( +struct __hw_ring *ring_handle, +void **rxdh) +{ +enum vxge_hw_status status; +struct __hw_ring *ring = (struct __hw_ring *)ring_handle; +struct __hw_channel *channel; + +vxge_assert ((ring !=NULL )); + + channel = &ring->channel; + + status =vxge_hw_channel_dtr_alloc (channel, rxdh); + +if (status ==VXGE_HW_OK ) { +struct vxge_hw_ring_rxd_1 *rxdp = + (struct vxge_hw_ring_rxd_1 *)*rxdh; + +/* instead of memset: reset this RxD */ + rxdp->control_0 = rxdp->control_1 =0 ; + } + +return status; +} + +/** +* vxge_hw_ring_rxd_free - Free descriptor. +* @ringh: Handle to the ring object used for receive +* @rxdh: Descriptor handle. +* +* Free the reserved descriptor. This operation is "symmetrical" to +* vxge_hw_ring_rxd_reserve. The "free-ing" completes the descriptor's +* lifecycle. +* +* After free-ing (see vxge_hw_ring_rxd_free()) the descriptor again can +* be: +* +* - reserved (vxge_hw_ring_rxd_reserve); +* +* - posted (vxge_hw_ring_rxd_post); +* +* - completed (vxge_hw_ring_rxd_next_completed); +* +* - and recycled again (vxge_hw_ring_rxd_free). +* +* For alternative state transitions and more details please refer to +* the design doc. +* +*/ +void vxge_hw_ring_rxd_free ( +struct __hw_ring *ringh, +void *rxdh) +{ +struct __hw_ring *ring = (struct __hw_ring *)ringh; +struct __hw_channel *channel; + +vxge_assert ((ringh !=NULL ) && (rxdh !=NULL )); + + channel = &ring->channel; + +vxge_hw_channel_dtr_free (channel, rxdh); + +} + +/** +* vxge_hw_ring_rxd_pre_post - Prepare rxd and post +* @ringh: Handle to the ring object used for receive +* @rxdh: Descriptor handle. +* +* This routine prepares a rxd and posts +*/ +void +vxge_hw_ring_rxd_pre_post ( +struct __hw_ring *ringh, +void *rxdh) +{ +#ifdef VXGE_DEBUG_ASSERT +struct vxge_hw_ring_rxd_1 *rxdp = (struct vxge_hw_ring_rxd_1 *)rxdh; +#endif + +struct __hw_ring *ring = (struct __hw_ring *)ringh; +struct __hw_channel *channel; + +vxge_assert ((ringh !=NULL ) && (rxdh !=NULL )); + + channel = &ring->channel; + +#ifdef VXGE_DEBUG_ASSERT +/* make sure device overwrites the (illegal) t_code on completion */ + rxdp->control_0 |=VXGE_HW_RING_RXD_T_CODE ( +VXGE_HW_RING_RXD_T_CODE_UNUSED ); +#endif + +vxge_hw_channel_dtr_post (channel, rxdh); + +} + +/** +* vxge_hw_ring_rxd_post_post - Process rxd after post. +* @ringh: Handle to the ring object used for receive +* @rxdh: Descriptor handle. +* +* Processes rxd after post +*/ +void +vxge_hw_ring_rxd_post_post ( +struct __hw_ring *ringh, +void *rxdh) +{ +struct vxge_hw_ring_rxd_1 *rxdp = (struct vxge_hw_ring_rxd_1 *)rxdh; +struct __hw_ring *ring = (struct __hw_ring *)ringh; +struct __hw_channel *channel; + +vxge_assert ((ringh !=NULL ) && (rxdh !=NULL )); + + channel = &ring->channel; + +/* do POST */ + rxdp->control_0 |=VXGE_HW_RING_RXD_LIST_OWN_ADAPTER ; + +if (ring->buffer_mode ==VXGE_HW_RING_RXD_BUFFER_MODE_3 ) + rxdp->control_1 |=VXGE_HW_RING_RXD_LIST_TAIL_OWN_ADAPTER ; + +if (ring->stats->common_stats.usage_cnt >0 ) + ring->stats->common_stats.usage_cnt--; + +} + +/** +* vxge_hw_ring_rxd_post - Post descriptor on the ring. +* @ringh: Handle to the ring object used for receive +* @rxdh: Descriptor obtained via vxge_hw_ring_rxd_reserve(). +* +* Post descriptor on the ring. +* Prior to posting the descriptor should be filled in accordance with +* Host/Titan interface specification for a given service (LL, etc.). +* +*/ +void +vxge_hw_ring_rxd_post ( +struct __hw_ring *ringh, +void *rxdh) +{ +struct vxge_hw_ring_rxd_1 *rxdp = (struct vxge_hw_ring_rxd_1 *)rxdh; +struct __hw_ring *ring = (struct __hw_ring *)ringh; +struct __hw_channel *channel; + +vxge_assert ((ringh !=NULL ) && (rxdh !=NULL )); + + channel = &ring->channel; + +#ifdef VXGE_DEBUG_ASSERT +/* make sure device overwrites the (illegal) t_code on completion */ + rxdp->control_0 |=VXGE_HW_RING_RXD_T_CODE ( +VXGE_HW_RING_RXD_T_CODE_UNUSED ); +#endif + +/* Do memory barrier before changing the ownership */ +wmb (); + +if (ring->buffer_mode ==VXGE_HW_RING_RXD_BUFFER_MODE_3 ) + rxdp->control_1 |=VXGE_HW_RING_RXD_LIST_TAIL_OWN_ADAPTER ; + + rxdp->control_0 |=VXGE_HW_RING_RXD_LIST_OWN_ADAPTER ; + +vxge_hw_channel_dtr_post (channel, rxdh); + +if (ring->stats->common_stats.usage_cnt >0 ) + ring->stats->common_stats.usage_cnt--; + +} + +/** +* vxge_hw_ring_rxd_post_post_wmb - Process rxd after post with memory barrier. +* @ringh: Handle to the ring object used for receive +* @rxdh: Descriptor handle. +* +* Processes rxd after post with memory barrier. +*/ +void +vxge_hw_ring_rxd_post_post_wmb ( +struct __hw_ring *ringh, +void *rxdh) +{ +struct __hw_ring *ring = (struct __hw_ring *)ringh; +struct __hw_channel *channel; + +vxge_assert ((ringh !=NULL ) && (rxdh !=NULL )); + + channel = &ring->channel; + +/* Do memory barrier before changing the ownership */ +wmb (); + +vxge_hw_ring_rxd_post_post (ringh, rxdh); + +} + +/** +* vxge_hw_ring_rxd_next_completed - Get the _next_ completed descriptor. +* @ringh: Handle to the ring object used for receive +* @rxdh: Descriptor handle. Returned by HW. +* @t_code: Transfer code, as per Titan User Guide, +* Receive Descriptor Format. Returned by HW. +* +* Retrieve the _next_ completed descriptor. +* HW uses ring callback (*vxge_hw_ring_callback_f) to notifiy +* driver of new completed descriptors. After that +* the driver can use vxge_hw_ring_rxd_next_completed to retrieve the rest +* completions (the very first completion is passed by HW via +* vxge_hw_ring_callback_f). +* +* Implementation-wise, the driver is free to call +* vxge_hw_ring_rxd_next_completed either immediately from inside the +* ring callback, or in a deferred fashion and separate (from HW) +* 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 Titan will complete the descriptor and indicate +* for the host that the received data is not to be used. +* For details please refer to Titan User Guide. +* +* Returns: VXGE_HW_OK - success. +* VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed descriptors +* are currently available for processing. +* +* See also: vxge_hw_ring_callback_f{}, +* vxge_hw_fifo_rxd_next_completed(), enum vxge_hw_status{}. +*/ +enum vxge_hw_status vxge_hw_ring_rxd_next_completed ( +struct __hw_ring *ringh, +void **rxdh, +u8 *t_code) +{ +struct __hw_ring *ring = (struct __hw_ring *)ringh; +struct __hw_channel *channel; +struct vxge_hw_ring_rxd_1 *rxdp; +enum vxge_hw_status status =VXGE_HW_OK ; +vxge_assert ((ringh !=NULL ) && (rxdh !=NULL ) && + (t_code !=NULL )); + + channel = &ring->channel; + +vxge_hw_channel_dtr_try_complete (channel, rxdh); + + rxdp = (struct vxge_hw_ring_rxd_1 *)*rxdh; +if (rxdp ==NULL ) { + status =VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS ; + goto exit; + } + +/* check whether it is not the end */ +if (!(rxdp->control_0 &VXGE_HW_RING_RXD_LIST_OWN_ADAPTER )) { +if (++ring->cmpl_cnt > ring->indicate_max_pkts) { +/* reset it. since we don't want to return +* garbage to the driver */ + *rxdh =0 ; + status =VXGE_HW_COMPLETIONS_REMAIN ; + goto exit; + } + +vxge_assert (((struct vxge_hw_ring_rxd_1 *)rxdp)->host_control != +0 ); + +vxge_hw_channel_dtr_complete (channel); + + *t_code = (u8 )VXGE_HW_RING_RXD_T_CODE_GET (rxdp->control_0); + +/* see VXGE_HW_SET_RXD_T_CODE() above.. */ +vxge_assert (*t_code !=VXGE_HW_RING_RXD_T_CODE_UNUSED ); + + ring->stats->common_stats.usage_cnt++; +if (ring->stats->common_stats.usage_max < + ring->stats->common_stats.usage_cnt) + ring->stats->common_stats.usage_max = + ring->stats->common_stats.usage_cnt; + + channel->poll_bytes += (u32 )VXGE_HW_RING_RXD_1_BUFFER0_SIZE_GET ( + rxdp->control_1); + + status =VXGE_HW_OK ; + goto exit; + } + +/* reset it. since we don't want to return +* garbage to the driver */ + *rxdh =0 ; + status =VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS ; +exit: + +return status; +} + +/** +* vxge_hw_ring_handle_tcode - Handle transfer code. +* @ringh: Handle to the ring object used for receive +* @rxdh: Descriptor handle. +* @t_code: One of the enumerated (and documented in the Titan user guide) +* "transfer codes". +* +* Handle descriptor's transfer code. The latter comes with each completed +* descriptor. +* +* Returns: one of the enum vxge_hw_status{} enumerated types. +* VXGE_HW_OK - for success. +* VXGE_HW_ERR_CRITICAL - when encounters critical error. +*/ +enum vxge_hw_status vxge_hw_ring_handle_tcode ( +struct __hw_ring *ringh, +void *rxdh, +u8 t_code) +{ +struct __hw_ring *ring = (struct __hw_ring *)ringh; +struct __hw_channel *channel; +enum vxge_hw_status status =VXGE_HW_OK ; +vxge_assert ((ringh !=NULL ) && (rxdh !=NULL )); + + channel = &ring->channel; + +/* If the t_code is not supported and if the +* t_code is other than 0x5 (unparseable packet +* such as unknown UPV6 header), Drop it !!! +*/ + +if (t_code ==0 || t_code ==5 ) { + status =VXGE_HW_OK ; + goto exit; + } + +if (t_code >0xF ) { + status =VXGE_HW_ERR_INVALID_TCODE ; + goto exit; + } + + ring->stats->rxd_t_code_err_cnt[t_code]++; +exit: + +return status; +} + +/** +* __hw_non_offload_db_post - Post non offload doorbell +* +* @fifo: fifohandle +* @txdl_ptr: The starting location of the TxDL in host memory +* @num_txds: The highest TxD in this TxDL (0 to 255 means 1 to 256) +* @no_snoop: No snoop flags +* +* This function posts a non-offload doorbell to doorbell FIFO +* +*/ +void +__hw_non_offload_db_post ( +struct __hw_fifo *fifo, +u64 txdl_ptr, +u32 num_txds, +u32 no_snoop) +{ +struct __hw_channel *channel; + +vxge_assert ((fifo !=NULL ) && (txdl_ptr !=0 )); + + channel = &fifo->channel; + +writeq (VXGE_HW_NODBW_TYPE (VXGE_HW_NODBW_TYPE_NODBW ) | +VXGE_HW_NODBW_LAST_TXD_NUMBER (num_txds) | +VXGE_HW_NODBW_GET_NO_SNOOP (no_snoop), + &fifo->nofl_db->control_0); + +wmb (); + +writeq (txdl_ptr, &fifo->nofl_db->txdl_ptr); +wmb (); + +} + +/** +* vxge_hw_fifo_free_txdl_count_get - returns the number of txdls available in +* the fifo +* @fifoh: Handle to the fifo object used for non offload send +*/ +u32 vxge_hw_fifo_free_txdl_count_get ( +struct __hw_fifo *fifoh) +{ + +return vxge_hw_channel_dtr_count (&((struct __hw_fifo *)fifoh)->channel); + +} + +/** +* vxge_hw_fifo_txdl_reserve - Reserve fifo descriptor. +* @fifoh: Handle to the fifo object used for non offload send +* @txdlh: Reserved descriptor. On success HW fills this "out" parameter +* with a valid handle. +* @txdl_priv: Buffer to return the pointer to per txdl space +* +* Reserve a single TxDL (that is, fifo descriptor) +* for the subsequent filling-in by driver) +* and posting on the corresponding channel (@channelh) +* via vxge_hw_fifo_txdl_post(). +* +* Note: it is the responsibility of driver 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: VXGE_HW_OK - success; +* VXGE_HW_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available +* +*/ +enum vxge_hw_status vxge_hw_fifo_txdl_reserve ( +struct __hw_fifo *fifoh, +void **txdlh,void **txdl_priv) +{ +struct __hw_fifo *fifo = (struct __hw_fifo *)fifoh; +struct __hw_channel *channel; +enum vxge_hw_status status; +int i; + +vxge_assert ((fifoh !=NULL ) && (txdlh !=NULL )); + + channel = &fifo->channel; + + status =vxge_hw_channel_dtr_alloc (channel, txdlh); + +if (status ==VXGE_HW_OK ) { +struct vxge_hw_fifo_txd *txdp = + (struct vxge_hw_fifo_txd *)*txdlh; +struct __hw_fifo_txdl_priv *priv; + + priv =__hw_fifo_txdl_priv (fifo, txdp); + +/* reset the TxDL's private */ + priv->align_dma_offset =0 ; + priv->align_vaddr_start = priv->align_vaddr; + priv->align_used_frags =0 ; + priv->frags =0 ; + priv->alloc_frags = fifo->config->max_frags; + priv->dang_txdl =NULL ; + priv->dang_frags =0 ; + priv->next_txdl_priv =NULL ; + priv->bytes_sent =0 ; + + *txdl_priv = (void *)(ptr_t )txdp->host_control; + +for (i =0 ; i < fifo->config->max_frags; i++) { + txdp = ((struct vxge_hw_fifo_txd *)*txdlh) + i; + txdp->control_0 = txdp->control_1 =0 ; + } + } + +return status; +} + +/** +* vxge_hw_fifo_txdl_buffer_set - Set transmit buffer pointer in the +* descriptor. +* @fifoh: Handle to the fifo object used for non offload send +* @txdlh: 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 vxge_hw_fifo_txdl_post()). The related "preparation" APIs include +* vxge_hw_fifo_txdl_mss_set() and vxge_hw_fifo_txdl_cksum_set_bits(). +* All three APIs fill in the fields of the fifo descriptor, +* in accordance with the Titan specification. +* +*/ +void vxge_hw_fifo_txdl_buffer_set ( +struct __hw_fifo *fifoh, +void *txdlh, +u32 frag_idx, +dma_addr_t dma_pointer, +u32 size) +{ +struct __hw_fifo *fifo = (struct __hw_fifo *)fifoh; +struct __hw_fifo_txdl_priv *txdl_priv; +struct vxge_hw_fifo_txd *txdp, *txdp_last; +struct __hw_channel *channel; + +vxge_assert ((fifoh !=NULL ) && (txdlh !=NULL ) && + (dma_pointer !=0 ) && (size !=0 )); + + channel = &fifo->channel; + + txdl_priv =__hw_fifo_txdl_priv (fifo, txdlh); + + txdp = (struct vxge_hw_fifo_txd *)txdlh + txdl_priv->frags; + +if (frag_idx !=0 ) + txdp->control_0 = txdp->control_1 =0 ; +else { + txdp->control_0 |=VXGE_HW_FIFO_TXD_GATHER_CODE ( +VXGE_HW_FIFO_TXD_GATHER_CODE_FIRST ); + txdp->control_1 |= fifo->interrupt_type; + txdp->control_1 |=VXGE_HW_FIFO_TXD_INT_NUMBER ( + fifo->tx_intr_num); +if (txdl_priv->frags) { + txdp_last = (struct vxge_hw_fifo_txd *)txdlh + + (txdl_priv->frags -1 ); + txdp_last->control_0 |=VXGE_HW_FIFO_TXD_GATHER_CODE ( +VXGE_HW_FIFO_TXD_GATHER_CODE_LAST ); + } + } + +/* Note: +* it is the responsibility of upper layers and not HW +* detect it and skip zero-size fragment +*/ +vxge_assert (size >0 ); +vxge_assert (frag_idx < txdl_priv->alloc_frags); + + txdp->buffer_pointer = (u64 )dma_pointer; + txdp->control_0 |=VXGE_HW_FIFO_TXD_BUFFER_SIZE (size); + txdl_priv->bytes_sent += size; + fifo->stats->total_buffers++; + txdl_priv->frags++; + +} + +/** +* vxge_hw_fifo_txdl_post - Post descriptor on the fifo channel. +* @fifoh: Handle to the fifo object used for non offload send +* @txdlh: Descriptor obtained via vxge_hw_fifo_txdl_reserve() +* @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/Titan interface specification for a given service (LL, etc.). +* +*/ +void vxge_hw_fifo_txdl_post ( +struct __hw_fifo *fifoh, +void *txdlh) +{ +struct __hw_fifo *fifo = (struct __hw_fifo *)fifoh; +struct __hw_fifo_txdl_priv *txdl_priv; +struct vxge_hw_fifo_txd *txdp_last; +struct vxge_hw_fifo_txd *txdp_first; +struct __hw_channel *channel; + +vxge_assert ((fifoh !=NULL ) && (txdlh !=NULL )); + + channel = &fifo->channel; + + txdl_priv =__hw_fifo_txdl_priv (fifo, txdlh); + + txdp_first = (struct vxge_hw_fifo_txd *)txdlh; + + txdp_last = (struct vxge_hw_fifo_txd *)txdlh + (txdl_priv->frags -1 ); + txdp_last->control_0 |= +VXGE_HW_FIFO_TXD_GATHER_CODE (VXGE_HW_FIFO_TXD_GATHER_CODE_LAST ); + txdp_first->control_0 |=VXGE_HW_FIFO_TXD_LIST_OWN_ADAPTER ; + +#ifdef VXGE_DEBUG_ASSERT +/* make sure device overwrites the (illegal) +* t_code value on completion */ + txdp_first->control_0 |= +VXGE_HW_FIFO_TXD_T_CODE (VXGE_HW_FIFO_TXD_T_CODE_UNUSED ); +#endif + +/* +* we want touch work_arr in order with ownership bit set to HW +*/ +vxge_hw_channel_dtr_post (&fifo->channel, txdlh); + +__hw_non_offload_db_post (fifo, + (u64 )(ptr_t )txdl_priv->dma_addr, + txdl_priv->frags -1 , + fifo->no_snoop_bits); + +#ifdef VXGE_HW_FIFO_DUMP_TXD + +#endif + + fifo->stats->total_posts++; + fifo->stats->common_stats.usage_cnt++; +if (fifo->stats->common_stats.usage_max < + fifo->stats->common_stats.usage_cnt) + fifo->stats->common_stats.usage_max = + fifo->stats->common_stats.usage_cnt; + +} + +/** +* vxge_hw_fifo_txdl_next_completed - Retrieve next completed descriptor. +* @fifoh: Handle to the fifo object used for non offload send +* @txdlh: Descriptor handle. Returned by HW. +* @txdl_priv: Buffer to return the pointer to per txdl space +* @t_code: Transfer code, as per Titan User Guide, +* Transmit Descriptor Format. +* Returned by HW. +* +* Retrieve the _next_ completed descriptor. +* HW uses channel callback (*vxge_hw_channel_callback_f) to notifiy +* driver of new completed descriptors. After that +* the driver can use vxge_hw_fifo_txdl_next_completed to retrieve the rest +* completions (the very first completion is passed by HW via +* vxge_hw_channel_callback_f). +* +* Implementation-wise, the driver is free to call +* vxge_hw_fifo_txdl_next_completed either immediately from inside the +* channel callback, or in a deferred fashion and separate (from HW) +* 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 Titan completes the descriptor because it +* is not able to send the data out. +* +* For details please refer to Titan User Guide. +* +* Returns: VXGE_HW_OK - success. +* VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed descriptors +* are currently available for processing. +* +*/ +enum vxge_hw_status vxge_hw_fifo_txdl_next_completed ( +struct __hw_fifo *fifoh, +void **txdlh, +void **txdl_priv, +enum vxge_hw_fifo_tcode *t_code) +{ +struct __hw_fifo *fifo = (struct __hw_fifo *)fifoh; +struct __hw_channel *channel; +struct vxge_hw_fifo_txd *txdp; +enum vxge_hw_status status =VXGE_HW_OK ; + +vxge_assert ((fifoh !=NULL ) && (txdlh !=NULL ) && + (t_code !=NULL )); + + channel = &fifo->channel; + +vxge_hw_channel_dtr_try_complete (channel, txdlh); + + txdp = (struct vxge_hw_fifo_txd *)*txdlh; +if (txdp ==NULL ) { + status =VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS ; + goto exit; + } + +/* check whether host owns it */ +if (!(txdp->control_0 &VXGE_HW_FIFO_TXD_LIST_OWN_ADAPTER )) { + +vxge_assert (txdp->host_control !=0 ); + +vxge_hw_channel_dtr_complete (channel); + + *txdl_priv = (void *)(ptr_t )txdp->host_control; + + *t_code = (u8 )VXGE_HW_FIFO_TXD_T_CODE_GET (txdp->control_0); + +/* see VXGE_HW_SET_TXD_T_CODE() above.. */ +vxge_assert (*t_code !=VXGE_HW_FIFO_TXD_T_CODE_UNUSED ); + +if (fifo->stats->common_stats.usage_cnt >0 ) + fifo->stats->common_stats.usage_cnt--; + + status =VXGE_HW_OK ; + goto exit; + } + +/* no more completions */ + *txdlh =0 ; + status =VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS ; +exit: + +return status; +} + +/** +* vxge_hw_fifo_handle_tcode - Handle transfer code. +* @fifoh: Handle to the fifo object used for non offload send +* @txdlh: Descriptor handle. +* @t_code: One of the enumerated (and documented in the Titan user guide) +* "transfer codes". +* +* Handle descriptor's transfer code. The latter comes with each completed +* descriptor. +* +* Returns: one of the enum vxge_hw_status{} enumerated types. +* VXGE_HW_OK - for success. +* VXGE_HW_ERR_CRITICAL - when encounters critical error. +*/ +enum vxge_hw_status vxge_hw_fifo_handle_tcode ( +struct __hw_fifo *fifoh, +void *txdlh, +enum vxge_hw_fifo_tcode t_code) +{ +struct __hw_fifo *fifo = (struct __hw_fifo *)fifoh; +struct __hw_channel *channel; + +enum vxge_hw_status status =VXGE_HW_OK ; +vxge_assert ((fifoh !=NULL ) && (txdlh !=NULL )); + + channel = &fifo->channel; + +if (((t_code &0x7 ) <0 ) || ((t_code &0x7 ) >0x4 )) { + status =VXGE_HW_ERR_INVALID_TCODE ; + goto exit; + } + + fifo->stats->txd_t_code_err_cnt[t_code]++; +exit: + +return status; +} + +/** +* vxge_hw_fifo_txdl_free - Free descriptor. +* @fifoh: Handle to the fifo object used for non offload send +* @txdlh: Descriptor handle. +* +* Free the reserved descriptor. This operation is "symmetrical" to +* vxge_hw_fifo_txdl_reserve. The "free-ing" completes the descriptor's +* lifecycle. +* +* After free-ing (see vxge_hw_fifo_txdl_free()) the descriptor again can +* be: +* +* - reserved (vxge_hw_fifo_txdl_reserve); +* +* - posted (vxge_hw_fifo_txdl_post); +* +* - completed (vxge_hw_fifo_txdl_next_completed); +* +* - and recycled again (vxge_hw_fifo_txdl_free). +* +* For alternative state transitions and more details please refer to +* the design doc. +* +*/ +void vxge_hw_fifo_txdl_free ( +struct __hw_fifo *fifoh, +void *txdlh) +{ +struct __hw_fifo *fifo = (struct __hw_fifo *)fifoh; +struct __hw_fifo_txdl_priv *txdl_priv; +u32 max_frags; +struct __hw_channel *channel; + +vxge_assert ((fifoh !=NULL ) && (txdlh !=NULL )); + + channel = &fifo->channel; + + txdl_priv =__hw_fifo_txdl_priv (fifo, (struct vxge_hw_fifo_txd *)txdlh); + + max_frags = fifo->config->max_frags; + +vxge_hw_channel_dtr_free (channel, txdlh); + channel->poll_bytes += txdl_priv->bytes_sent; + +} + +/** +* vxge_hw_vpath_mac_addr_add - Add the mac address entry for this vpath +* to MAC address table. +* @vp: Vpath handle. +* @macaddr: MAC address to be added for this vpath into the list +* @macaddr_mask: MAC address mask for macaddr +* @duplicate_mode: Duplicate MAC address add mode. Please see +* enum vxge_hw_vpath_mac_addr_add_mode{} +* +* Adds the given mac address and mac address mask into the list for this +* vpath. +* see also: vxge_hw_vpath_mac_addr_delete, vxge_hw_vpath_mac_addr_get and +* vxge_hw_vpath_mac_addr_get_next +* +*/ +enum vxge_hw_status +vxge_hw_vpath_mac_addr_add ( +struct __hw_vpath_handle *vp, +u8 (macaddr )[ETH_ALEN ], +u8 (macaddr_mask )[ETH_ALEN ], +enum vxge_hw_vpath_mac_addr_add_mode duplicate_mode) +{ +u32 i; +u64 data1 =0ULL ; +u64 data2 =0ULL ; +enum vxge_hw_status status =VXGE_HW_OK ; + +vxge_assert (vp !=NULL ); + +if (vp ==NULL ) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + +for (i =0 ; i <ETH_ALEN ; i++) { + data1 <<=8 ; + data1 |= (u8 )macaddr[i]; + + data2 <<=8 ; + data2 |= (u8 )macaddr_mask[i]; + } + +switch (duplicate_mode) { +case VXGE_HW_VPATH_MAC_ADDR_ADD_DUPLICATE : + i =0 ; +break ; +case VXGE_HW_VPATH_MAC_ADDR_DISCARD_DUPLICATE : + i =1 ; +break ; +case VXGE_HW_VPATH_MAC_ADDR_REPLACE_DUPLICATE : + i =2 ; +break ; +default : + i =0 ; +break ; + } + + status =__hw_vpath_rts_table_set (vp, +VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_ADD_ENTRY , +VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA , +0 , +VXGE_HW_RTS_ACCESS_STEER_DATA0_DA_MAC_ADDR (data1), +VXGE_HW_RTS_ACCESS_STEER_DATA1_DA_MAC_ADDR_MASK (data2)| +VXGE_HW_RTS_ACCESS_STEER_DATA1_DA_MAC_ADDR_MODE (i)); +exit: + +return status; +} + +/** +* vxge_hw_vpath_mac_addr_get - Get the first mac address entry for this vpath +* from MAC address table. +* @vp: Vpath handle. +* @macaddr: First MAC address entry for this vpath in the list +* @macaddr_mask: MAC address mask for macaddr +* +* Returns the first mac address and mac address mask in the list for this +* vpath. +* see also: vxge_hw_vpath_mac_addr_get_next +* +*/ +enum vxge_hw_status +vxge_hw_vpath_mac_addr_get ( +struct __hw_vpath_handle *vp, +u8 (macaddr )[ETH_ALEN ], +u8 (macaddr_mask )[ETH_ALEN ]) +{ +u32 i; +u64 data1 =0ULL ; +u64 data2 =0ULL ; +enum vxge_hw_status status =VXGE_HW_OK ; + +vxge_assert (vp !=NULL ); + +if (vp ==NULL ) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + status =__hw_vpath_rts_table_get (vp, +VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_FIRST_ENTRY , +VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA , +0 , + &data1, + &data2); + +if (status !=VXGE_HW_OK ) + goto exit; + + data1 =VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR (data1); + + data2 =VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK (data2); + +for (i =ETH_ALEN ; i >0 ; i--) { + macaddr[i-1 ] = (u8)(data1 &0xFF ); + data1 >>=8 ; + + macaddr_mask[i-1 ] = (u8)(data2 &0xFF ); + data2 >>=8 ; + } +exit: + +return status; +} + +/** +* vxge_hw_vpath_mac_addr_get_next - Get the next mac address entry for this +* vpath +* from MAC address table. +* @vp: Vpath handle. +* @macaddr: Next MAC address entry for this vpath in the list +* @macaddr_mask: MAC address mask for macaddr +* +* Returns the next mac address and mac address mask in the list for this +* vpath. +* see also: vxge_hw_vpath_mac_addr_get +* +*/ +enum vxge_hw_status +vxge_hw_vpath_mac_addr_get_next ( +struct __hw_vpath_handle *vp, +u8 (macaddr )[ETH_ALEN ], +u8 (macaddr_mask )[ETH_ALEN ]) +{ +u32 i; +u64 data1 =0ULL ; +u64 data2 =0ULL ; +enum vxge_hw_status status =VXGE_HW_OK ; + +vxge_assert (vp !=NULL ); + +if (vp ==NULL ) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + status =__hw_vpath_rts_table_get (vp, +VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_NEXT_ENTRY , +VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA , +0 , + &data1, + &data2); + +if (status !=VXGE_HW_OK ) + goto exit; + + data1 =VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR (data1); + + data2 =VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK (data2); + +for (i =ETH_ALEN ; i >0 ; i--) { + macaddr[i-1 ] = (u8)(data1 &0xFF ); + data1 >>=8 ; + + macaddr_mask[i-1 ] = (u8)(data2 &0xFF ); + data2 >>=8 ; + } + +exit: + +return status; +} + +/** +* vxge_hw_vpath_mac_addr_delete - Delete the mac address entry for this vpath +* to MAC address table. +* @vp: Vpath handle. +* @macaddr: MAC address to be added for this vpath into the list +* @macaddr_mask: MAC address mask for macaddr +* +* Delete the given mac address and mac address mask into the list for this +* vpath. +* see also: vxge_hw_vpath_mac_addr_add, vxge_hw_vpath_mac_addr_get and +* vxge_hw_vpath_mac_addr_get_next +* +*/ +enum vxge_hw_status +vxge_hw_vpath_mac_addr_delete ( +struct __hw_vpath_handle *vp, +u8 (macaddr )[ETH_ALEN ], +u8 (macaddr_mask )[ETH_ALEN ]) +{ +u32 i; +u64 data1 =0ULL ; +u64 data2 =0ULL ; +enum vxge_hw_status status =VXGE_HW_OK ; + +vxge_assert (vp !=NULL ); + +if (vp ==NULL ) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + +for (i =0 ; i <ETH_ALEN ; i++) { + data1 <<=8 ; + data1 |= (u8 )macaddr[i]; + + data2 <<=8 ; + data2 |= (u8 )macaddr_mask[i]; + } + + status =__hw_vpath_rts_table_set (vp, +VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_DELETE_ENTRY , +VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA , +0 , +VXGE_HW_RTS_ACCESS_STEER_DATA0_DA_MAC_ADDR (data1), +VXGE_HW_RTS_ACCESS_STEER_DATA1_DA_MAC_ADDR_MASK ( + data2)); +exit: + +return status; +} + +/** +* vxge_hw_vpath_vid_add - Add the vlan id entry for this vpath +* to vlan id table. +* @vp: Vpath handle. +* @vid: vlan id to be added for this vpath into the list +* +* Adds the given vlan id into the list for this vpath. +* see also: vxge_hw_vpath_vid_delete, vxge_hw_vpath_vid_get and +* vxge_hw_vpath_vid_get_next +* +*/ +enum vxge_hw_status +vxge_hw_vpath_vid_add ( +struct __hw_vpath_handle *vp, +u64 vid) +{ +enum vxge_hw_status status =VXGE_HW_OK ; + +vxge_assert (vp !=NULL ); + +if (vp ==NULL ) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + status =__hw_vpath_rts_table_set (vp, +VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_ADD_ENTRY , +VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_VID , +0 , +VXGE_HW_RTS_ACCESS_STEER_DATA0_VLAN_ID (vid), +0 ); +exit: + +return status; +} + +/** +* vxge_hw_vpath_vid_get - Get the first vid entry for this vpath +* from vlan id table. +* @vp: Vpath handle. +* @vid: Buffer to return vlan id +* +* Returns the first vlan id in the list for this vpath. +* see also: vxge_hw_vpath_vid_get_next +* +*/ +enum vxge_hw_status +vxge_hw_vpath_vid_get ( +struct __hw_vpath_handle *vp, +u64 *vid) +{ +enum vxge_hw_status status =VXGE_HW_OK ; + +vxge_assert ((vp !=NULL ) && (vid !=NULL )); + +if (vp ==NULL ) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + status =__hw_vpath_rts_table_get (vp, +VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_FIRST_ENTRY , +VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_VID , +0 , + vid, +NULL ); + + *vid =VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_VLAN_ID (*vid); +exit: + +return status; +} + +/** +* vxge_hw_vpath_vid_get_next - Get the next vid entry for this vpath +* from vlan id table. +* @vp: Vpath handle. +* @vid: Buffer to return vlan id +* +* Returns the next vlan id in the list for this vpath. +* see also: vxge_hw_vpath_vid_get +* +*/ +enum vxge_hw_status +vxge_hw_vpath_vid_get_next ( +struct __hw_vpath_handle *vp, +u64 *vid) +{ +enum vxge_hw_status status =VXGE_HW_OK ; + +vxge_assert ((vp !=NULL ) && (vid !=NULL )); + +if (vp ==NULL ) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + status =__hw_vpath_rts_table_get (vp, +VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_NEXT_ENTRY , +VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_VID , +0 , + vid, +NULL ); + + *vid =VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_VLAN_ID (*vid); +exit: + +return status; +} + +/** +* vxge_hw_vpath_vid_delete - Delete the vlan id entry for this vpath +* to vlan id table. +* @vp: Vpath handle. +* @vid: vlan id to be added for this vpath into the list +* +* Adds the given vlan id into the list for this vpath. +* see also: vxge_hw_vpath_vid_add, vxge_hw_vpath_vid_get and +* vxge_hw_vpath_vid_get_next +* +*/ +enum vxge_hw_status +vxge_hw_vpath_vid_delete ( +struct __hw_vpath_handle *vp, +u64 vid) +{ +enum vxge_hw_status status =VXGE_HW_OK ; + +vxge_assert (vp !=NULL ); + +if (vp ==NULL ) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + status =__hw_vpath_rts_table_set (vp, +VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_DELETE_ENTRY , +VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_VID , +0 , +VXGE_HW_RTS_ACCESS_STEER_DATA0_VLAN_ID (vid), +0 ); +exit: + +return status; +} + +/** +* vxge_hw_vpath_all_vid_enable - Enable all Vlan Ids. +* @vp: Vpath handle. +* +* Enable all vlan ids. +* Returns: VXGE_HAL_OK on success. +* +*/ +enum vxge_hw_status vxge_hw_vpath_all_vid_enable ( +struct __hw_vpath_handle *vp) +{u64 val64; +struct __hw_virtualpath *vpath; +enum vxge_hw_status status =VXGE_HW_OK ; +vxge_assert (vp !=NULL ); + +if ((vp ==NULL ) || (vp->vpath->ringh ==NULL )) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + vpath = (struct __hw_virtualpath *)vp->vpath; + + val64 =readq (&vpath->vp_reg->rxmac_vcfg0); + +if (!(val64 &VXGE_HW_RXMAC_VCFG0_ALL_VID_EN )) { + + val64 |=VXGE_HW_RXMAC_VCFG0_ALL_VID_EN ; + +writeq (val64, &vpath->vp_reg->rxmac_vcfg0); + } +exit: + +return status; +} + +/** +* vxge_hw_vpath_promisc_enable - Enable promiscuous mode. +* @vp: Vpath handle. +* +* Enable promiscuous mode of Titan-e operation. +* +* See also: vxge_hw_vpath_promisc_disable(). +*/ +enum vxge_hw_status vxge_hw_vpath_promisc_enable ( +struct __hw_vpath_handle *vp) +{ +u64 val64; +struct __hw_virtualpath *vpath; +enum vxge_hw_status status =VXGE_HW_OK ; +vxge_assert (vp !=NULL ); + +if ((vp ==NULL ) || (vp->vpath->ringh ==NULL )) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + vpath = (struct __hw_virtualpath *)vp->vpath; + +/* Enable promiscous mode for function 0 only */ +if (!(vp->vpath->hldev->access_rights & +VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM )) +return VXGE_HW_OK ; + + val64 =readq (&vpath->vp_reg->rxmac_vcfg0); + +if (!(val64 &VXGE_HW_RXMAC_VCFG0_UCAST_ALL_ADDR_EN )) { + + val64 |=VXGE_HW_RXMAC_VCFG0_UCAST_ALL_ADDR_EN | +VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN | +VXGE_HW_RXMAC_VCFG0_BCAST_EN | +VXGE_HW_RXMAC_VCFG0_ALL_VID_EN ; + +writeq (val64, &vpath->vp_reg->rxmac_vcfg0); + } +exit: + +return status; +} + +/** +* vxge_hw_vpath_promisc_disable - Disable promiscuous mode. +* @vp: Vpath handle. +* +* Disable promiscuous mode of Titan-e operation. +* +* See also: vxge_hw_vpath_promisc_enable(). +*/ +enum vxge_hw_status vxge_hw_vpath_promisc_disable ( +struct __hw_vpath_handle *vp) +{ +u64 val64; +struct __hw_virtualpath *vpath; +enum vxge_hw_status status =VXGE_HW_OK ; +vxge_assert (vp !=NULL ); + +if ((vp ==NULL ) || (vp->vpath->ringh ==NULL )) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + vpath = (struct __hw_virtualpath *)vp->vpath; + + val64 =readq (&vpath->vp_reg->rxmac_vcfg0); + +if (val64 &VXGE_HW_RXMAC_VCFG0_UCAST_ALL_ADDR_EN ) { + + val64 &= ~(VXGE_HW_RXMAC_VCFG0_UCAST_ALL_ADDR_EN | +VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN | +VXGE_HW_RXMAC_VCFG0_ALL_VID_EN ); + +writeq (val64, &vpath->vp_reg->rxmac_vcfg0); + } +exit: + +return status; +} + +/* +* vxge_hw_vpath_bcast_enable - Enable broadcast +* @vp: Vpath handle. +* +* Enable receiving broadcasts. +*/ +enum vxge_hw_status vxge_hw_vpath_bcast_enable ( +struct __hw_vpath_handle *vp) +{ +u64 val64; +struct __hw_virtualpath *vpath; +enum vxge_hw_status status =VXGE_HW_OK ; +vxge_assert (vp !=NULL ); + +if ((vp ==NULL ) || (vp->vpath->ringh ==NULL )) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + vpath = (struct __hw_virtualpath *)vp->vpath; + + val64 =readq (&vpath->vp_reg->rxmac_vcfg0); + +if (!(val64 &VXGE_HW_RXMAC_VCFG0_BCAST_EN )) { + val64 |=VXGE_HW_RXMAC_VCFG0_BCAST_EN ; +writeq (val64, &vpath->vp_reg->rxmac_vcfg0); + } +exit: + +return status; +} + +/* +* vxge_hw_vpath_bcast_disable - Disable broadcast +* @vp: Vpath handle. +* +* Disable receiving broadcasts. +*/ +enum vxge_hw_status vxge_hw_vpath_bcast_disable ( +struct __hw_vpath_handle *vp) +{ +u64 val64; +struct __hw_virtualpath *vpath; +enum vxge_hw_status status =VXGE_HW_OK ; +vxge_assert (vp !=NULL ); + +if ((vp ==NULL ) || (vp->vpath->ringh ==NULL )) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + vpath = (struct __hw_virtualpath *)vp->vpath; + + val64 =readq (&vpath->vp_reg->rxmac_vcfg0); + +if (val64 &VXGE_HW_RXMAC_VCFG0_BCAST_EN ) { + val64 &= ~VXGE_HW_RXMAC_VCFG0_BCAST_EN ; +writeq (val64, &vpath->vp_reg->rxmac_vcfg0); + } +exit: + +return status; +} + +/** +* vxge_hw_vpath_mcast_enable - Enable multicast addresses. +* @vp: Vpath handle. +* +* Enable Titan-e multicast addresses. +* Returns: VXGE_HW_OK on success. +* +*/ +enum vxge_hw_status vxge_hw_vpath_mcast_enable ( +struct __hw_vpath_handle *vp) +{ +u64 val64; +struct __hw_virtualpath *vpath; +enum vxge_hw_status status =VXGE_HW_OK ; +vxge_assert (vp !=NULL ); + +if ((vp ==NULL ) || (vp->vpath->ringh ==NULL )) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + vpath = (struct __hw_virtualpath *)vp->vpath; + + val64 =readq (&vpath->vp_reg->rxmac_vcfg0); + +if (!(val64 &VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN )) { + + val64 |=VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN ; +writeq (val64, &vpath->vp_reg->rxmac_vcfg0); + } +exit: + +return status; +} + +/** +* vxge_hw_vpath_mcast_disable - Disable multicast addresses. +* @vp: Vpath handle. +* +* Disable Titan-e multicast addresses. +* Returns: VXGE_HW_OK - success. +* VXGE_HW_INF_MEM_STROBE_CMD_EXECUTING - Failed to disable mcast +* feature within the time(timeout). +* +*/ +enum vxge_hw_status vxge_hw_vpath_mcast_disable (struct __hw_vpath_handle *vp) +{ +u64 val64; +struct __hw_virtualpath *vpath; +enum vxge_hw_status status =VXGE_HW_OK ; +vxge_assert (vp !=NULL ); + +if ((vp ==NULL ) || (vp->vpath->ringh ==NULL )) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + vpath = (struct __hw_virtualpath *)vp->vpath; + + val64 =readq (&vpath->vp_reg->rxmac_vcfg0); + +if (val64 &VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN ) { + val64 &= ~VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN ; +writeq (val64, &vpath->vp_reg->rxmac_vcfg0); + } +exit: + +return status; +} + +/* +* __hw_vpath_alarm_process - Process Alarms. +* @vpath: Virtual Path. +* @skip_alarms: Do not clear the alarms +* +* Process vpath alarms. +* +*/ +enum vxge_hw_status __hw_vpath_alarm_process ( +struct __hw_virtualpath *vpath, +u32 skip_alarms) +{ +u64 val64; +u64 alarm_status; +u64 pic_status; +struct __hw_device *hldev =NULL ; +enum vxge_hw_event alarm_event =VXGE_HW_EVENT_UNKNOWN ; +u64 mask64; + +vxge_assert (vpath !=NULL ); + +if (vpath ==NULL ) { + alarm_event =VXGE_HW_SET_LEVEL (VXGE_HW_EVENT_UNKNOWN , + alarm_event); + goto out; + } + + hldev = vpath->hldev; + + alarm_status =readq (&vpath->vp_reg->vpath_general_int_status); + +if (alarm_status ==VXGE_HW_ALL_FOXES ) { + alarm_event =VXGE_HW_SET_LEVEL (VXGE_HW_EVENT_SLOT_FREEZE , + alarm_event); + goto out; + } + +if (alarm_status & ~( +VXGE_HW_VPATH_GENERAL_INT_STATUS_PIC_INT | +VXGE_HW_VPATH_GENERAL_INT_STATUS_PCI_INT | +VXGE_HW_VPATH_GENERAL_INT_STATUS_WRDMA_INT | +VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT )) { + vpath->sw_stats->error_stats.unknown_alarms++; + + alarm_event =VXGE_HW_SET_LEVEL (VXGE_HW_EVENT_UNKNOWN , + alarm_event); + goto out; + } + +if (alarm_status &VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT ) { + + val64 =readq (&vpath->vp_reg->xgmac_vp_int_status); + +if (val64 & +VXGE_HW_XGMAC_VP_INT_STATUS_ASIC_NTWK_VP_ERR_ASIC_NTWK_VP_INT ) { + + val64 =readq (&vpath->vp_reg->asic_ntwk_vp_err_reg); + +if (((val64 & +VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT ) && + (!(val64 & +VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK ))) || + ((val64 & +VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT_OCCURR ) + && (!(val64 & +VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK_OCCURR ) + ))) { + vpath->sw_stats->error_stats. + network_sustained_fault++; + +writeq ( +VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT , + &vpath->vp_reg->asic_ntwk_vp_err_mask); + +__hw_device_handle_link_down_ind (hldev); + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_LINK_DOWN , alarm_event); + } + +if (((val64 & +VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK ) && + (!(val64 & +VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT ))) || + ((val64 & +VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK_OCCURR ) + && (!(val64 & +VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT_OCCURR ) + ))) { + + vpath->sw_stats->error_stats. + network_sustained_ok++; + +writeq ( +VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK , + &vpath->vp_reg->asic_ntwk_vp_err_mask); + +__hw_device_handle_link_up_ind (hldev); + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_LINK_UP , alarm_event); + } + +writeq (VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->asic_ntwk_vp_err_reg); + + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_ALARM_CLEARED , + alarm_event); + +if (skip_alarms) +return VXGE_HW_OK ; + } + } + +if (alarm_status &VXGE_HW_VPATH_GENERAL_INT_STATUS_PIC_INT ) { + + pic_status =readq (&vpath->vp_reg->vpath_ppif_int_status); + +if (pic_status & +VXGE_HW_VPATH_PPIF_INT_STATUS_GENERAL_ERRORS_GENERAL_INT ) { + + val64 =readq (&vpath->vp_reg->general_errors_reg); + + mask64 =readq (&vpath->vp_reg->general_errors_mask); + +if ((val64 & +VXGE_HW_GENERAL_ERRORS_REG_INI_SERR_DET ) & + ~mask64) { + vpath->sw_stats->error_stats.ini_serr_det++; + + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_SERR , alarm_event); + } + +if ((val64 & +VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO0_OVRFLOW ) & + ~mask64) { + vpath->sw_stats->error_stats. + dblgen_fifo0_overflow++; + + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_FIFO_ERR , alarm_event); + } + +if ((val64 & +VXGE_HW_GENERAL_ERRORS_REG_STATSB_PIF_CHAIN_ERR ) & + ~mask64) { + vpath->sw_stats->error_stats. + statsb_pif_chain_error++; + + } + +if ((val64 & +VXGE_HW_GENERAL_ERRORS_REG_STATSB_DROP_TIMEOUT_REQ ) & + ~mask64) { + vpath->sw_stats->error_stats. + statsb_drop_timeout++; + + } + +if ((val64 & +VXGE_HW_GENERAL_ERRORS_REG_TGT_ILLEGAL_ACCESS ) & + ~mask64) { + vpath->sw_stats->error_stats. + target_illegal_access++; + + } + +if (!skip_alarms) { +writeq (VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->general_errors_reg); + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_ALARM_CLEARED , + alarm_event); + } + } + +if (pic_status & +VXGE_HW_VPATH_PPIF_INT_STATUS_KDFCCTL_ERRORS_KDFCCTL_INT ) { + + val64 =readq (&vpath->vp_reg->kdfcctl_errors_reg); + + mask64 =readq (&vpath->vp_reg->kdfcctl_errors_mask); + +if ((val64 & +VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_OVRWR ) & + ~mask64) { + vpath->sw_stats->error_stats. + kdfcctl_fifo0_overwrite++; + + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_FIFO_ERR , + alarm_event); + } + +if ((val64 & +VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_POISON ) & + ~mask64) { + vpath->sw_stats->error_stats. + kdfcctl_fifo0_poison++; + + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_FIFO_ERR , + alarm_event); + } + +if ((val64 & +VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_DMA_ERR ) & + ~mask64) { + vpath->sw_stats->error_stats. + kdfcctl_fifo0_dma_error++; + + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_FIFO_ERR , + alarm_event); + } + +if (!skip_alarms) { +writeq (VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->kdfcctl_errors_reg); + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_ALARM_CLEARED , + alarm_event); + } + } + + } + +if (alarm_status &VXGE_HW_VPATH_GENERAL_INT_STATUS_WRDMA_INT ) { + + val64 =readq (&vpath->vp_reg->wrdma_alarm_status); + +if (val64 &VXGE_HW_WRDMA_ALARM_STATUS_PRC_ALARM_PRC_INT ) { + + val64 =readq (&vpath->vp_reg->prc_alarm_reg); + + mask64 =readq (&vpath->vp_reg->prc_alarm_mask); + +if ((val64 &VXGE_HW_PRC_ALARM_REG_PRC_RING_BUMP )& + ~mask64) { + vpath->sw_stats->error_stats.prc_ring_bumps++; + + } + +if ((val64 &VXGE_HW_PRC_ALARM_REG_PRC_RXDCM_SC_ERR ) & + ~mask64) { + vpath->sw_stats->error_stats.prc_rxdcm_sc_err++; + + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_VPATH_ERR , + alarm_event); + } + +if ((val64 &VXGE_HW_PRC_ALARM_REG_PRC_RXDCM_SC_ABORT ) + & ~mask64) { + vpath->sw_stats->error_stats. + prc_rxdcm_sc_abort++; + + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_VPATH_ERR , + alarm_event); + } + +if ((val64 &VXGE_HW_PRC_ALARM_REG_PRC_QUANTA_SIZE_ERR ) + & ~mask64) { + vpath->sw_stats->error_stats. + prc_quanta_size_err++; + + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_VPATH_ERR , + alarm_event); + } + +if (!skip_alarms) { +writeq (VXGE_HW_INTR_MASK_ALL , + &vpath->vp_reg->prc_alarm_reg); + alarm_event =VXGE_HW_SET_LEVEL ( +VXGE_HW_EVENT_ALARM_CLEARED , + alarm_event); + } + } + } +out: + hldev->stats.sw_dev_err_stats.vpath_alarms++; + +if ((alarm_event ==VXGE_HW_EVENT_ALARM_CLEARED ) || + (alarm_event ==VXGE_HW_EVENT_UNKNOWN )) +return VXGE_HW_OK ; + +vxge_assert (0 ); + +__hw_device_handle_error (hldev, + vpath->vp_id, + alarm_event); + +if (alarm_event ==VXGE_HW_EVENT_SERR ) +return VXGE_HW_ERR_CRITICAL ; + +return (alarm_event ==VXGE_HW_EVENT_SLOT_FREEZE ) ? +VXGE_HW_ERR_SLOT_FREEZE : + (alarm_event ==VXGE_HW_EVENT_FIFO_ERR ) ?VXGE_HW_ERR_FIFO : +VXGE_HW_ERR_VPATH ; +} + +/* +* vxge_hw_vpath_alarm_process - Process Alarms. +* @vpath: Virtual Path. +* @skip_alarms: Do not clear the alarms +* +* Process vpath alarms. +* +*/ +enum vxge_hw_status vxge_hw_vpath_alarm_process ( +struct __hw_vpath_handle *vp, +u32 skip_alarms) +{ +enum vxge_hw_status status =VXGE_HW_OK ; + +vxge_assert (vp !=NULL ); + +if (vp ==NULL ) { + status =VXGE_HW_ERR_INVALID_HANDLE ; + goto exit; + } + + status =__hw_vpath_alarm_process ( + vp->vpath, + skip_alarms); +exit: + +return status; +} + +/** +* vxge_hw_vpath_msix_set - Associate MSIX vectors with TIM interrupts and +* alrms +* @vp: Virtual Path handle. +* @tim_msix_id: MSIX vectors associated with VXGE_HW_VPATH_MSIX_MAX number of +* interrupts(Can be repeated). If fifo or ring are not enabled +* the MSIX vector for that should be set to 0 +* @alarm_msix_id: MSIX vector for alarm. +* +* This API will associate a given MSIX vector numbers with the four TIM +* interrupts and alarm interrupt. +*/ +enum vxge_hw_status +vxge_hw_vpath_msix_set (struct __hw_vpath_handle *vp,int *tim_msix_id, +int alarm_msix_id) +{ +u64 val64; + +vxge_assert (vp !=NULL ); + + val64 =VXGE_HW_INTERRUPT_CFG0_GROUP0_MSIX_FOR_TXTI ( + (vp->vpath->hldev->first_vp_id *4 ) + tim_msix_id[0 ]) | +VXGE_HW_INTERRUPT_CFG0_GROUP1_MSIX_FOR_TXTI ( + (vp->vpath->hldev->first_vp_id *4 ) + tim_msix_id[1 ]) | +VXGE_HW_INTERRUPT_CFG0_GROUP2_MSIX_FOR_TXTI ( + (vp->vpath->hldev->first_vp_id *4 ) + tim_msix_id[2 ]); + + val64 |=VXGE_HW_INTERRUPT_CFG0_GROUP3_MSIX_FOR_TXTI ( + (vp->vpath->hldev->first_vp_id *4 ) + tim_msix_id[3 ]); + +writeq (val64, &vp->vpath->vp_reg->interrupt_cfg0); + +writeq (VXGE_HW_INTERRUPT_CFG2_ALARM_MAP_TO_MSG ( + (vp->vpath->hldev->first_vp_id *4 ) + alarm_msix_id), + &vp->vpath->vp_reg->interrupt_cfg2); + +if ( + + (vp->vpath->hldev->config.intr_mode == +VXGE_HW_INTR_MODE_MSIX_ONE_SHOT )) { +__hw_pio_mem_write32_upper ((u32 )bVAL32 ( +VXGE_HW_ONE_SHOT_VECT1_EN_ONE_SHOT_VECT1_EN , +0 ), + &vp->vpath->vp_reg->one_shot_vect1_en); + } + +if (vp->vpath->hldev->config.intr_mode == +VXGE_HW_INTR_MODE_MSIX_ONE_SHOT ) { +__hw_pio_mem_write32_upper ((u32 )bVAL32 ( +VXGE_HW_ONE_SHOT_VECT2_EN_ONE_SHOT_VECT2_EN , +0 ), + &vp->vpath->vp_reg->one_shot_vect2_en); + +__hw_pio_mem_write32_upper ((u32 )bVAL32 ( +VXGE_HW_ONE_SHOT_VECT3_EN_ONE_SHOT_VECT3_EN , +0 ), + &vp->vpath->vp_reg->one_shot_vect3_en); + } + +return VXGE_HW_OK ; +} + +/** +* vxge_hw_vpath_msix_mask - Mask MSIX Vector. +* @vp: Virtual Path handle. +* @msix_id: MSIX ID +* +* The function masks the msix interrupt for the given msix_id +* +* Note: +* +* Returns: 0, +* Otherwise, VXGE_HW_ERR_WRONG_IRQ if the msix index is out of range +* status. +* See also: +*/ +void +vxge_hw_vpath_msix_mask (struct __hw_vpath_handle *vp,int msix_id) +{ + +vxge_assert (vp !=NULL ); + +__hw_pio_mem_write32_upper ( + (u32 )bVAL32 (vxge_mBIT (vp->vpath->hldev->first_vp_id + + (msix_id /4 )),0 ), + &vp->vpath->hldev->common_reg->set_msix_mask_vect[msix_id%4 ]); + +return ; +} + +/** +* vxge_hw_vpath_msix_clear - Clear MSIX Vector. +* @vp: Virtual Path handle. +* @msix_id: MSI ID +* +* The function clears the msix interrupt for the given msix_id +* +* Note: +* +* Returns: 0, +* Otherwise, VXGE_HW_ERR_WRONG_IRQ if the msix index is out of range +* status. +* See also: +*/ +void +vxge_hw_vpath_msix_clear (struct __hw_vpath_handle *vp,int msix_id) +{ + +vxge_assert (vp !=NULL ); + +if ( + + (vp->vpath->hldev->config.intr_mode == +VXGE_HW_INTR_MODE_MSIX_ONE_SHOT )) { +__hw_pio_mem_write32_upper ( + (u32 )bVAL32 (vxge_mBIT (vp->vpath->hldev-> + first_vp_id+(msix_id/4 )),0 ), + &vp->vpath->hldev->common_reg-> + clr_msix_one_shot_vec[msix_id%4 ]); + }else { +__hw_pio_mem_write32_upper ( + (u32 )bVAL32 (vxge_mBIT (vp->vpath->hldev->first_vp_id+ + (msix_id/4 )),0 ), + &vp->vpath->hldev->common_reg-> + clear_msix_mask_vect[msix_id%4 ]); + } + +return ; +} + +/** +* vxge_hw_vpath_msix_unmask - Unmask the MSIX Vector. +* @vp: Virtual Path handle. +* @msix_id: MSI ID +* +* The function unmasks the msix interrupt for the given msix_id +* +* Note: +* +* Returns: 0, +* Otherwise, VXGE_HW_ERR_WRONG_IRQ if the msix index is out of range +* status. +* See also: +*/ +void +vxge_hw_vpath_msix_unmask (struct __hw_vpath_handle *vp,int msix_id) +{ + +vxge_assert (vp !=NULL ); + +__hw_pio_mem_write32_upper ( + (u32 )bVAL32 (vxge_mBIT (vp->vpath->hldev->first_vp_id+ + (msix_id/4 )),0 ), + &vp->vpath->hldev->common_reg-> + clear_msix_mask_vect[msix_id%4 ]); + +return ; +} + +/** +* vxge_hw_vpath_msix_mask_all - Mask all MSIX vectors for the vpath. +* @vp: Virtual Path handle. +* +* The function masks all msix interrupt for the given vpath +* +*/ +void +vxge_hw_vpath_msix_mask_all (struct __hw_vpath_handle *vp) +{ + +vxge_assert (vp !=NULL ); + +__hw_pio_mem_write32_upper ( + (u32 )bVAL32 (vxge_mBIT (vp->vpath->vp_id),0 ), + &vp->vpath->hldev->common_reg->set_msix_mask_all_vect); + +return ; +} + +/** +* vxge_hw_vpath_inta_mask_tx_rx - Mask Tx and Rx interrupts. +* @vp: Virtual Path handle. +* +* Mask Tx and Rx vpath interrupts. +* +* See also: vxge_hw_vpath_inta_mask_tx_rx() +*/ +void vxge_hw_vpath_inta_mask_tx_rx (struct __hw_vpath_handle *vp) +{ +u64 tim_int_mask0[4 ] = {[0 ...3 ] =0 }; +u32 tim_int_mask1[4 ] = {[0 ...3 ] =0 }; +u64 val64; + +vxge_assert (vp !=NULL ); + +VXGE_HW_DEVICE_TIM_INT_MASK_SET (tim_int_mask0, + tim_int_mask1, + vp->vpath->vp_id); + + val64 =readq (&vp->vpath->hldev->common_reg->tim_int_mask0); + +if ((tim_int_mask0[VXGE_HW_VPATH_INTR_TX ] !=0 ) || + (tim_int_mask0[VXGE_HW_VPATH_INTR_RX ] !=0 )) { +writeq ((tim_int_mask0[VXGE_HW_VPATH_INTR_TX ] | + tim_int_mask0[VXGE_HW_VPATH_INTR_RX ] | val64), + &vp->vpath->hldev->common_reg->tim_int_mask0); + } + + val64 =readl (&vp->vpath->hldev->common_reg->tim_int_mask1); + +if ((tim_int_mask1[VXGE_HW_VPATH_INTR_TX ] !=0 ) || + (tim_int_mask1[VXGE_HW_VPATH_INTR_RX ] !=0 )) { +__hw_pio_mem_write32_upper ( + (tim_int_mask1[VXGE_HW_VPATH_INTR_TX ] | + tim_int_mask1[VXGE_HW_VPATH_INTR_RX ] | val64), + &vp->vpath->hldev->common_reg->tim_int_mask1); + } + +return ; +} + +/** +* vxge_hw_vpath_inta_unmask_tx_rx - Unmask Tx and Rx interrupts. +* @vp: Virtual Path handle. +* +* Unmask Tx and Rx vpath interrupts. +* +* See also: vxge_hw_vpath_inta_mask_tx_rx() +*/ +void vxge_hw_vpath_inta_unmask_tx_rx (struct __hw_vpath_handle *vp) +{ +u64 tim_int_mask0[4 ] = {[0 ...3 ] =0 }; +u32 tim_int_mask1[4 ] = {[0 ...3 ] =0 }; +u64 val64; + +vxge_assert (vp !=NULL ); + +VXGE_HW_DEVICE_TIM_INT_MASK_SET (tim_int_mask0, + tim_int_mask1, + vp->vpath->vp_id); + + val64 =readq (&vp->vpath->hldev->common_reg->tim_int_mask0); + +if ((tim_int_mask0[VXGE_HW_VPATH_INTR_TX ] !=0 ) || + (tim_int_mask0[VXGE_HW_VPATH_INTR_RX ] !=0 )) { +writeq ((~(tim_int_mask0[VXGE_HW_VPATH_INTR_TX ] | + tim_int_mask0[VXGE_HW_VPATH_INTR_RX ])) & val64, + &vp->vpath->hldev->common_reg->tim_int_mask0); + } + +if ((tim_int_mask1[VXGE_HW_VPATH_INTR_TX ] !=0 ) || + (tim_int_mask1[VXGE_HW_VPATH_INTR_RX ] !=0 )) { +__hw_pio_mem_write32_upper ( + (~(tim_int_mask1[VXGE_HW_VPATH_INTR_TX ] | + tim_int_mask1[VXGE_HW_VPATH_INTR_RX ])) & val64, + &vp->vpath->hldev->common_reg->tim_int_mask1); + } + +return ; +} + +/** +* vxge_hw_vpath_poll_rx - Poll Rx Virtual Path for completed +* descriptors and process the same. +* @ringh: Handle to the ring object used for receive +* @got_rx: Buffer to return the flag set if receive interrupt is occured +* +* The function polls the Rx for the completed descriptors and calls +* the driver via supplied completion callback. +* +* Returns: VXGE_HW_OK, if the polling is completed successful. +* VXGE_HW_COMPLETIONS_REMAIN: There are still more completed +* descriptors available which are yet to be processed. +* +* See also: vxge_hw_vpath_poll_rx() +*/ +enum vxge_hw_status vxge_hw_vpath_poll_rx ( +struct __hw_ring *ringh, +u32 *got_rx) +{ +u8 t_code; +int got_bytes; +enum vxge_hw_status status =VXGE_HW_OK ; +void *first_rxdh; +struct __hw_ring *ring = (struct __hw_ring *)ringh; + +vxge_assert ((ringh !=NULL ) && (got_rx !=NULL )); + +if (ring ==NULL ) +return status; + + got_bytes = *got_rx =0 ; + + ring->cmpl_cnt =0 ; + + ring->channel.poll_bytes =0 ; + + status =vxge_hw_ring_rxd_next_completed (ringh, + &first_rxdh, + &t_code); +if (status ==VXGE_HW_OK ) { +if (ring->callback (ringh, first_rxdh, + t_code, ring->channel.userdata) !=VXGE_HW_OK ) + status =VXGE_HW_COMPLETIONS_REMAIN ; + + (*got_rx) += ring->cmpl_cnt +1 ; + got_bytes += ring->channel.poll_bytes +1 ; + } + +return status; +} + +/** +* vxge_hw_vpath_poll_tx - Poll Tx for completed descriptors and process +* the same. +* @fifoh: Handle to the fifo object used for non offload send +* @got_tx: Buffer to return the flag set if transmit interrupt is occured +* +* The function polls the Tx for the completed descriptors and calls +* the driver via supplied completion callback. +* +* Returns: VXGE_HW_OK, if the polling is completed successful. +* VXGE_HW_COMPLETIONS_REMAIN: There are still more completed +* descriptors available which are yet to be processed. +* +* See also: vxge_hw_vpath_poll_tx(). +*/ +enum vxge_hw_status vxge_hw_vpath_poll_tx ( +struct __hw_fifo *fifoh, +u32 *got_tx,void **skb_ptr) +{ +enum vxge_hw_fifo_tcode t_code; +int got_bytes; +void *first_txdlh; +void *txdl_priv; +struct __hw_fifo *fifo = (struct __hw_fifo *)fifoh; +enum vxge_hw_status status =VXGE_HW_OK ; +struct __hw_channel *channel; + +vxge_assert ((fifoh !=NULL ) && (got_tx !=NULL )); + +if (fifo ==NULL ) +return status; + + channel = &fifo->channel; + + channel->poll_bytes =0 ; + + got_bytes = *got_tx =0 ; + + status =vxge_hw_fifo_txdl_next_completed (fifoh, + &first_txdlh, &txdl_priv, &t_code); +if (status ==VXGE_HW_OK ) { +if (fifo->callback (fifoh, first_txdlh, + txdl_priv, t_code, channel->userdata, skb_ptr) != +VXGE_HW_OK ) + status =VXGE_HW_COMPLETIONS_REMAIN ; + + (*got_tx)++; + got_bytes += channel->poll_bytes +1 ; + } + +return status; +}
drivers/net/vxge/vxge-traffic.h +2808 -0
31 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.