Commit f036e4f4 authored by Rajesh Borundia's avatar Rajesh Borundia Committed by David S. Miller

qlcnic: VF reset recovery implementation.

o Implement recovery mechanism for VF to recover from
  adapter resets.
Signed-off-by: default avatarManish Chopra <manish.chopra@qlogic.com>
Signed-off-by: default avatarSucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: default avatarRajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 97d8105c
......@@ -976,6 +976,7 @@ struct qlcnic_adapter {
u8 fw_fail_cnt;
u8 tx_timeo_cnt;
u8 need_fw_reset;
u8 reset_ctx_cnt;
u16 is_up;
u16 pvid;
......
......@@ -339,12 +339,13 @@ inline void qlcnic_83xx_enable_legacy_msix_mbx_intr(struct qlcnic_adapter
writel(0, adapter->ahw->pci_base0 + mask);
}
inline void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *adapter)
void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *adapter)
{
u32 mask;
mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
writel(1, adapter->ahw->pci_base0 + mask);
QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, 0);
}
static inline void qlcnic_83xx_get_mbx_data(struct qlcnic_adapter *adapter,
......@@ -453,17 +454,15 @@ irqreturn_t qlcnic_83xx_tmp_intr(int irq, void *data)
void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter)
{
u32 val = 0, num_msix = adapter->ahw->num_msix - 1;
u32 num_msix;
qlcnic_83xx_disable_mbx_intr(adapter);
if (adapter->flags & QLCNIC_MSIX_ENABLED)
num_msix = adapter->ahw->num_msix - 1;
else
num_msix = 0;
QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val);
qlcnic_83xx_disable_mbx_intr(adapter);
msleep(20);
synchronize_irq(adapter->msix_entries[num_msix].vector);
free_irq(adapter->msix_entries[num_msix].vector, adapter);
......
......@@ -317,6 +317,18 @@ struct qlc_83xx_idc {
char **name;
};
/* Device States */
enum qlcnic_83xx_states {
QLC_83XX_IDC_DEV_UNKNOWN,
QLC_83XX_IDC_DEV_COLD,
QLC_83XX_IDC_DEV_INIT,
QLC_83XX_IDC_DEV_READY,
QLC_83XX_IDC_DEV_NEED_RESET,
QLC_83XX_IDC_DEV_NEED_QUISCENT,
QLC_83XX_IDC_DEV_FAILED,
QLC_83XX_IDC_DEV_QUISCENT
};
#define QLCNIC_MBX_RSP(reg) LSW(reg)
#define QLCNIC_MBX_NUM_REGS(reg) (MSW(reg) & 0x1FF)
#define QLCNIC_MBX_STATUS(reg) (((reg) >> 25) & 0x7F)
......@@ -536,6 +548,7 @@ void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *);
irqreturn_t qlcnic_83xx_handle_aen(int, void *);
int qlcnic_83xx_get_port_info(struct qlcnic_adapter *);
void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *);
void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *);
irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *);
irqreturn_t qlcnic_83xx_intr(int, void *);
irqreturn_t qlcnic_83xx_tmp_intr(int, void *);
......
......@@ -115,18 +115,6 @@ static const char *const qlc_83xx_idc_states[] = {
"Quiesce"
};
/* Device States */
enum qlcnic_83xx_states {
QLC_83XX_IDC_DEV_UNKNOWN,
QLC_83XX_IDC_DEV_COLD,
QLC_83XX_IDC_DEV_INIT,
QLC_83XX_IDC_DEV_READY,
QLC_83XX_IDC_DEV_NEED_RESET,
QLC_83XX_IDC_DEV_NEED_QUISCENT,
QLC_83XX_IDC_DEV_FAILED,
QLC_83XX_IDC_DEV_QUISCENT
};
static int
qlcnic_83xx_idc_check_driver_presence_reg(struct qlcnic_adapter *adapter)
{
......@@ -162,7 +150,8 @@ static int qlcnic_83xx_idc_update_audit_reg(struct qlcnic_adapter *adapter,
return -EBUSY;
}
val = adapter->portnum & 0xf;
val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT);
val |= (adapter->portnum & 0xf);
val |= mode << 7;
if (mode)
seconds = jiffies / HZ - adapter->ahw->idc.sec_counter;
......@@ -401,14 +390,18 @@ static void qlcnic_83xx_idc_detach_driver(struct qlcnic_adapter *adapter)
struct net_device *netdev = adapter->netdev;
netif_device_detach(netdev);
/* Disable mailbox interrupt */
QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, 0);
qlcnic_83xx_disable_mbx_intr(adapter);
qlcnic_down(adapter, netdev);
for (i = 0; i < adapter->ahw->num_msix; i++) {
adapter->ahw->intr_tbl[i].id = i;
adapter->ahw->intr_tbl[i].enabled = 0;
adapter->ahw->intr_tbl[i].src = 0;
}
if (qlcnic_sriov_pf_check(adapter))
qlcnic_sriov_pf_reset(adapter);
}
/**
......@@ -610,9 +603,15 @@ static int qlcnic_83xx_idc_check_fan_failure(struct qlcnic_adapter *adapter)
static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
{
int err;
/* register for NIC IDC AEN Events */
qlcnic_83xx_register_nic_idc_func(adapter, 1);
err = qlcnic_sriov_pf_reinit(adapter);
if (err)
return err;
qlcnic_83xx_enable_mbx_intrpt(adapter);
if (qlcnic_83xx_configure_opmode(adapter)) {
......
......@@ -669,7 +669,7 @@ enum {
#define QLCNIC_CMDPEG_CHECK_RETRY_COUNT 60
#define QLCNIC_CMDPEG_CHECK_DELAY 500
#define QLCNIC_HEARTBEAT_PERIOD_MSECS 200
#define QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT 45
#define QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT 10
#define QLCNIC_MAX_MC_COUNT 38
#define QLCNIC_WATCHDOG_TIMEOUTVALUE 5
......
......@@ -197,6 +197,8 @@ void qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov *, struct qlcnic_vf_info *);
bool qlcnic_sriov_soft_flr_check(struct qlcnic_adapter *,
struct qlcnic_bc_trans *,
struct qlcnic_vf_info *);
void qlcnic_sriov_pf_reset(struct qlcnic_adapter *);
int qlcnic_sriov_pf_reinit(struct qlcnic_adapter *);
#else
static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {}
static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {}
......@@ -227,6 +229,9 @@ static inline bool qlcnic_sriov_soft_flr_check(struct qlcnic_adapter *adapter,
struct qlcnic_bc_trans *trans,
struct qlcnic_vf_info *vf)
{ return false; }
static inline void qlcnic_sriov_pf_reset(struct qlcnic_adapter *adapter) {}
static inline int qlcnic_sriov_pf_reinit(struct qlcnic_adapter *adapter)
{ return 0; }
#endif
#endif
......@@ -1376,3 +1376,43 @@ void qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov *sriov,
qlcnic_sriov_schedule_flr(sriov, vf, qlcnic_sriov_pf_process_flr);
netdev_info(dev, "FLR received for PCI func %d\n", vf->pci_func);
}
void qlcnic_sriov_pf_reset(struct qlcnic_adapter *adapter)
{
struct qlcnic_hardware_context *ahw = adapter->ahw;
struct qlcnic_sriov *sriov = ahw->sriov;
struct qlcnic_vf_info *vf;
u16 num_vfs = sriov->num_vfs;
int i;
for (i = 0; i < num_vfs; i++) {
vf = &sriov->vf_info[i];
vf->rx_ctx_id = 0;
vf->tx_ctx_id = 0;
cancel_work_sync(&vf->flr_work);
__qlcnic_sriov_process_flr(vf);
clear_bit(QLC_BC_VF_STATE, &vf->state);
}
qlcnic_sriov_pf_reset_vport_handle(adapter, ahw->pci_func);
QLCWRX(ahw, QLCNIC_MBX_INTR_ENBL, (ahw->num_msix - 1) << 8);
}
int qlcnic_sriov_pf_reinit(struct qlcnic_adapter *adapter)
{
struct qlcnic_hardware_context *ahw = adapter->ahw;
int err;
if (!qlcnic_sriov_enable_check(adapter))
return 0;
ahw->op_mode = QLCNIC_SRIOV_PF_FUNC;
err = qlcnic_sriov_pf_init(adapter);
if (err)
return err;
dev_info(&adapter->pdev->dev, "%s: op_mode %d\n",
__func__, ahw->op_mode);
return err;
}
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