Commit 4d2a5b40 authored by Jon Mason's avatar Jon Mason Committed by David S. Miller

vxge: Wait for Rx to become idle before reseting or closing

Wait for the receive traffic to become idle before attempting to close
or reset the adapter.  To enable the processing of packets while Receive
Idle, move the clearing of __VXGE_STATE_CARD_UP bit in vxge_close to
after it.  Also, modify the return value of the ISR when the adapter is
down to IRQ_HANDLED.  Otherwise there are unhandled interrupts for the
device.
Signed-off-by: default avatarJon Mason <jon.mason@exar.com>
Signed-off-by: default avatarRam Vepa <ram.vepa@exar.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 47f01db4
......@@ -193,6 +193,88 @@ static enum vxge_hw_status
__vxge_hw_vpath_xmac_rx_stats_get(struct __vxge_hw_virtualpath *vpath,
struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats);
static void
vxge_hw_vpath_set_zero_rx_frm_len(struct vxge_hw_vpath_reg __iomem *vp_reg)
{
u64 val64;
val64 = readq(&vp_reg->rxmac_vcfg0);
val64 &= ~VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(0x3fff);
writeq(val64, &vp_reg->rxmac_vcfg0);
val64 = readq(&vp_reg->rxmac_vcfg0);
return;
}
/*
* vxge_hw_vpath_wait_receive_idle - Wait for Rx to become idle
*/
int vxge_hw_vpath_wait_receive_idle(struct __vxge_hw_device *hldev, u32 vp_id)
{
struct vxge_hw_vpath_reg __iomem *vp_reg;
struct __vxge_hw_virtualpath *vpath;
u64 val64, rxd_count, rxd_spat;
int count = 0, total_count = 0;
vpath = &hldev->virtual_paths[vp_id];
vp_reg = vpath->vp_reg;
vxge_hw_vpath_set_zero_rx_frm_len(vp_reg);
/* Check that the ring controller for this vpath has enough free RxDs
* to send frames to the host. This is done by reading the
* PRC_RXD_DOORBELL_VPn register and comparing the read value to the
* RXD_SPAT value for the vpath.
*/
val64 = readq(&vp_reg->prc_cfg6);
rxd_spat = VXGE_HW_PRC_CFG6_GET_RXD_SPAT(val64) + 1;
/* Use a factor of 2 when comparing rxd_count against rxd_spat for some
* leg room.
*/
rxd_spat *= 2;
do {
mdelay(1);
rxd_count = readq(&vp_reg->prc_rxd_doorbell);
/* Check that the ring controller for this vpath does
* not have any frame in its pipeline.
*/
val64 = readq(&vp_reg->frm_in_progress_cnt);
if ((rxd_count <= rxd_spat) || (val64 > 0))
count = 0;
else
count++;
total_count++;
} while ((count < VXGE_HW_MIN_SUCCESSIVE_IDLE_COUNT) &&
(total_count < VXGE_HW_MAX_POLLING_COUNT));
if (total_count >= VXGE_HW_MAX_POLLING_COUNT)
printk(KERN_ALERT "%s: Still Receiving traffic. Abort wait\n",
__func__);
return total_count;
}
/* vxge_hw_device_wait_receive_idle - This function waits until all frames
* stored in the frame buffer for each vpath assigned to the given
* function (hldev) have been sent to the host.
*/
void vxge_hw_device_wait_receive_idle(struct __vxge_hw_device *hldev)
{
int i, total_count = 0;
for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
continue;
total_count += vxge_hw_vpath_wait_receive_idle(hldev, i);
if (total_count >= VXGE_HW_MAX_POLLING_COUNT)
break;
}
}
/*
* __vxge_hw_channel_allocate - Allocate memory for channel
* This function allocates required memory for the channel and various arrays
......@@ -390,7 +472,7 @@ __vxge_hw_device_register_poll(void __iomem *reg, u64 mask, u32 max_millis)
return ret;
}
/* __vxge_hw_device_vpath_reset_in_prog_check - Check if vpath reset
/* __vxge_hw_device_vpath_reset_in_prog_check - Check if vpath reset
* in progress
* This routine checks the vpath reset in progress register is turned zero
*/
......@@ -1165,7 +1247,6 @@ enum vxge_hw_status vxge_hw_device_getpause_data(struct __vxge_hw_device *hldev,
* It can be used to set or reset Pause frame generation or reception
* support of the NIC.
*/
enum vxge_hw_status vxge_hw_device_setpause_data(struct __vxge_hw_device *hldev,
u32 port, u32 tx, u32 rx)
{
......@@ -1409,7 +1490,6 @@ vxge_hw_ring_replenish(struct __vxge_hw_ring *ring)
/*
* __vxge_hw_ring_create - Create a Ring
* This function creates Ring and initializes it.
*
*/
static enum vxge_hw_status
__vxge_hw_ring_create(struct __vxge_hw_vpath_handle *vp,
......
......@@ -2051,4 +2051,11 @@ enum vxge_hw_status vxge_hw_vpath_rts_rth_set(
enum vxge_hw_status
__vxge_hw_device_is_privilaged(u32 host_type, u32 func_id);
#define VXGE_HW_MIN_SUCCESSIVE_IDLE_COUNT 5
#define VXGE_HW_MAX_POLLING_COUNT 100
int vxge_hw_vpath_wait_receive_idle(struct __vxge_hw_device *hldev, u32 vp_id);
void vxge_hw_device_wait_receive_idle(struct __vxge_hw_device *hldev);
#endif
......@@ -90,7 +90,6 @@ static int vxge_mac_list_add(struct vxge_vpath *vpath, struct macInfo *mac);
static int vxge_mac_list_del(struct vxge_vpath *vpath, struct macInfo *mac);
static enum vxge_hw_status vxge_restore_vpath_vid_table(struct vxge_vpath *vpath);
static enum vxge_hw_status vxge_restore_vpath_mac_addr(struct vxge_vpath *vpath);
static enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev);
static inline int is_vxge_card_up(struct vxgedev *vdev)
{
......@@ -1299,8 +1298,13 @@ static void vxge_vpath_intr_enable(struct vxgedev *vdev, int vp_id)
static void vxge_vpath_intr_disable(struct vxgedev *vdev, int vp_id)
{
struct vxge_vpath *vpath = &vdev->vpaths[vp_id];
struct __vxge_hw_device *hldev;
int msix_id;
hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
vxge_hw_vpath_wait_receive_idle(hldev, vpath->device_id);
vxge_hw_vpath_intr_disable(vpath->handle);
if (vdev->config.intr_type == INTA)
......@@ -1430,6 +1434,7 @@ static int do_vxge_reset(struct vxgedev *vdev, int event)
}
if (event == VXGE_LL_FULL_RESET) {
vxge_hw_device_wait_receive_idle(vdev->devh);
vxge_hw_device_intr_disable(vdev->devh);
switch (vdev->cric_err_event) {
......@@ -1935,7 +1940,7 @@ static enum vxge_hw_status vxge_restore_vpath_mac_addr(struct vxge_vpath *vpath)
}
/* reset vpaths */
static enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev)
enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev)
{
enum vxge_hw_status status = VXGE_HW_OK;
struct vxge_vpath *vpath;
......@@ -2080,7 +2085,7 @@ static irqreturn_t vxge_isr_napi(int irq, void *dev_id)
return IRQ_NONE;
if (unlikely(!is_vxge_card_up(vdev)))
return IRQ_NONE;
return IRQ_HANDLED;
status = vxge_hw_device_begin_irq(hldev, vdev->exec_mode,
&reason);
......@@ -2787,7 +2792,6 @@ static int do_vxge_close(struct net_device *dev, int do_io)
while (test_and_set_bit(__VXGE_STATE_RESET_CARD, &vdev->state))
msleep(50);
clear_bit(__VXGE_STATE_CARD_UP, &vdev->state);
if (do_io) {
/* Put the vpath back in normal mode */
vpath_vector = vxge_mBIT(vdev->vpaths[0].device_id);
......@@ -2831,6 +2835,11 @@ static int do_vxge_close(struct net_device *dev, int do_io)
del_timer_sync(&vdev->vp_reset_timer);
if (do_io)
vxge_hw_device_wait_receive_idle(hldev);
clear_bit(__VXGE_STATE_CARD_UP, &vdev->state);
/* Disable napi */
if (vdev->config.intr_type != MSI_X)
napi_disable(&vdev->napi);
......@@ -2847,8 +2856,6 @@ static int do_vxge_close(struct net_device *dev, int do_io)
if (do_io)
vxge_hw_device_intr_disable(vdev->devh);
mdelay(1000);
vxge_rem_isr(vdev);
vxge_napi_del_all(vdev);
......
......@@ -397,6 +397,8 @@ struct vxge_tx_priv {
} while (0);
extern void vxge_initialize_ethtool_ops(struct net_device *ndev);
enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev);
/**
* #define VXGE_DEBUG_INIT: debug for initialization functions
* #define VXGE_DEBUG_TX : debug transmit related functions
......
......@@ -3998,6 +3998,7 @@ struct vxge_hw_vpath_reg {
#define VXGE_HW_PRC_CFG6_L4_CPC_TRSFR_CODE_EN vxge_mBIT(9)
#define VXGE_HW_PRC_CFG6_RXD_CRXDT(val) vxge_vBIT(val, 23, 9)
#define VXGE_HW_PRC_CFG6_RXD_SPAT(val) vxge_vBIT(val, 36, 9)
#define VXGE_HW_PRC_CFG6_GET_RXD_SPAT(val) vxge_bVALn(val, 36, 9)
/*0x00a78*/ u64 prc_cfg7;
#define VXGE_HW_PRC_CFG7_SCATTER_MODE(val) vxge_vBIT(val, 6, 2)
#define VXGE_HW_PRC_CFG7_SMART_SCAT_EN vxge_mBIT(11)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment