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

qlcnic: Fix loopback test for SR-IOV PF.

o Do not disable mailbox interrupts while running
  loopback test through SR-IOV PF.
Signed-off-by: default avatarManish Chopra <manish.chopra@qlogic.com>
Signed-off-by: default avatarRajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 91b7282b
...@@ -1868,6 +1868,7 @@ static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring) ...@@ -1868,6 +1868,7 @@ static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
writel(0xfbff, adapter->tgt_mask_reg); writel(0xfbff, adapter->tgt_mask_reg);
} }
extern const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops;
extern const struct ethtool_ops qlcnic_ethtool_ops; extern const struct ethtool_ops qlcnic_ethtool_ops;
extern const struct ethtool_ops qlcnic_ethtool_failed_ops; extern const struct ethtool_ops qlcnic_ethtool_failed_ops;
......
...@@ -402,7 +402,8 @@ static void qlcnic_83xx_poll_process_aen(struct qlcnic_adapter *adapter) ...@@ -402,7 +402,8 @@ static void qlcnic_83xx_poll_process_aen(struct qlcnic_adapter *adapter)
event = readl(QLCNIC_MBX_FW(adapter->ahw, 0)); event = readl(QLCNIC_MBX_FW(adapter->ahw, 0));
if (event & QLCNIC_MBX_ASYNC_EVENT) if (event & QLCNIC_MBX_ASYNC_EVENT)
qlcnic_83xx_process_aen(adapter); __qlcnic_83xx_process_aen(adapter);
out: out:
qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter); qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags); spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
...@@ -758,7 +759,7 @@ int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter, ...@@ -758,7 +759,7 @@ int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter,
/* Get the FW response data */ /* Get the FW response data */
fw_data = readl(QLCNIC_MBX_FW(ahw, 0)); fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
if (fw_data & QLCNIC_MBX_ASYNC_EVENT) { if (fw_data & QLCNIC_MBX_ASYNC_EVENT) {
qlcnic_83xx_process_aen(adapter); __qlcnic_83xx_process_aen(adapter);
mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL); mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
if (mbx_val) if (mbx_val)
goto poll; goto poll;
...@@ -862,7 +863,7 @@ static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter, ...@@ -862,7 +863,7 @@ static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter,
return; return;
} }
void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter) void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
{ {
u32 event[QLC_83XX_MBX_AEN_CNT]; u32 event[QLC_83XX_MBX_AEN_CNT];
int i; int i;
...@@ -907,6 +908,24 @@ void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter) ...@@ -907,6 +908,24 @@ void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
} }
static void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
{
struct qlcnic_hardware_context *ahw = adapter->ahw;
u32 resp, event;
unsigned long flags;
spin_lock_irqsave(&ahw->mbx_lock, flags);
resp = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
if (resp & QLCNIC_SET_OWNER) {
event = readl(QLCNIC_MBX_FW(ahw, 0));
if (event & QLCNIC_MBX_ASYNC_EVENT)
__qlcnic_83xx_process_aen(adapter);
}
spin_unlock_irqrestore(&ahw->mbx_lock, flags);
}
static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter) static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter)
{ {
int index, i, err, sds_mbx_size; int index, i, err, sds_mbx_size;
...@@ -1274,7 +1293,8 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test) ...@@ -1274,7 +1293,8 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test)
if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) { if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
/* disable and free mailbox interrupt */ /* disable and free mailbox interrupt */
qlcnic_83xx_free_mbx_intr(adapter); if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
qlcnic_83xx_free_mbx_intr(adapter);
adapter->ahw->loopback_state = 0; adapter->ahw->loopback_state = 0;
adapter->ahw->hw_ops->setup_link_event(adapter, 1); adapter->ahw->hw_ops->setup_link_event(adapter, 1);
} }
...@@ -1302,12 +1322,14 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev, ...@@ -1302,12 +1322,14 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
qlcnic_detach(adapter); qlcnic_detach(adapter);
if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) { if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
err = qlcnic_83xx_setup_mbx_intr(adapter); if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
if (err) { err = qlcnic_83xx_setup_mbx_intr(adapter);
dev_err(&adapter->pdev->dev, if (err) {
"%s: failed to setup mbx interrupt\n", dev_err(&adapter->pdev->dev,
__func__); "%s: failed to setup mbx interrupt\n",
goto out; __func__);
goto out;
}
} }
} }
adapter->ahw->diag_test = 0; adapter->ahw->diag_test = 0;
...@@ -1556,7 +1578,9 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode) ...@@ -1556,7 +1578,9 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
/* Poll for link up event before running traffic */ /* Poll for link up event before running traffic */
do { do {
msleep(500); msleep(500);
qlcnic_83xx_process_aen(adapter); if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
qlcnic_83xx_process_aen(adapter);
if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) { if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
dev_info(&adapter->pdev->dev, dev_info(&adapter->pdev->dev,
"Firmware didn't sent link up event to loopback request\n"); "Firmware didn't sent link up event to loopback request\n");
...@@ -1610,7 +1634,9 @@ int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) ...@@ -1610,7 +1634,9 @@ int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
/* Wait for Link and IDC Completion AEN */ /* Wait for Link and IDC Completion AEN */
do { do {
msleep(300); msleep(300);
qlcnic_83xx_process_aen(adapter); if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
qlcnic_83xx_process_aen(adapter);
if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) { if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"FW did not generate IDC completion AEN\n"); "FW did not generate IDC completion AEN\n");
...@@ -1650,7 +1676,9 @@ int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode) ...@@ -1650,7 +1676,9 @@ int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
/* Wait for Link and IDC Completion AEN */ /* Wait for Link and IDC Completion AEN */
do { do {
msleep(300); msleep(300);
qlcnic_83xx_process_aen(adapter); if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
qlcnic_83xx_process_aen(adapter);
if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) { if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Firmware didn't sent IDC completion AEN\n"); "Firmware didn't sent IDC completion AEN\n");
...@@ -1924,7 +1952,7 @@ irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data) ...@@ -1924,7 +1952,7 @@ irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data)
event = readl(QLCNIC_MBX_FW(adapter->ahw, 0)); event = readl(QLCNIC_MBX_FW(adapter->ahw, 0));
if (event & QLCNIC_MBX_ASYNC_EVENT) if (event & QLCNIC_MBX_ASYNC_EVENT)
qlcnic_83xx_process_aen(adapter); __qlcnic_83xx_process_aen(adapter);
out: out:
mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK); mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
writel(0, adapter->ahw->pci_base0 + mask); writel(0, adapter->ahw->pci_base0 + mask);
......
...@@ -558,7 +558,7 @@ void qlcnic_83xx_disable_intr(struct qlcnic_adapter *, ...@@ -558,7 +558,7 @@ void qlcnic_83xx_disable_intr(struct qlcnic_adapter *,
struct qlcnic_host_sds_ring *); struct qlcnic_host_sds_ring *);
void qlcnic_83xx_check_vf(struct qlcnic_adapter *, void qlcnic_83xx_check_vf(struct qlcnic_adapter *,
const struct pci_device_id *); const struct pci_device_id *);
void qlcnic_83xx_process_aen(struct qlcnic_adapter *); void __qlcnic_83xx_process_aen(struct qlcnic_adapter *);
int qlcnic_83xx_get_port_config(struct qlcnic_adapter *); int qlcnic_83xx_get_port_config(struct qlcnic_adapter *);
int qlcnic_83xx_set_port_config(struct qlcnic_adapter *); int qlcnic_83xx_set_port_config(struct qlcnic_adapter *);
int qlcnic_enable_eswitch(struct qlcnic_adapter *, u8, u8); int qlcnic_enable_eswitch(struct qlcnic_adapter *, u8, u8);
......
...@@ -859,9 +859,11 @@ static int qlcnic_irq_test(struct net_device *netdev) ...@@ -859,9 +859,11 @@ static int qlcnic_irq_test(struct net_device *netdev)
return ret; return ret;
} }
#define QLCNIC_ILB_PKT_SIZE 64 #define QLCNIC_ILB_PKT_SIZE 64
#define QLCNIC_NUM_ILB_PKT 16 #define QLCNIC_NUM_ILB_PKT 16
#define QLCNIC_ILB_MAX_RCV_LOOP 10 #define QLCNIC_ILB_MAX_RCV_LOOP 10
#define QLCNIC_LB_PKT_POLL_DELAY_MSEC 1
#define QLCNIC_LB_PKT_POLL_COUNT 20
static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[]) static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[])
{ {
...@@ -898,9 +900,9 @@ int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) ...@@ -898,9 +900,9 @@ int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
loop = 0; loop = 0;
do { do {
msleep(1); msleep(QLCNIC_LB_PKT_POLL_DELAY_MSEC);
qlcnic_process_rcv_ring_diag(sds_ring); qlcnic_process_rcv_ring_diag(sds_ring);
if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) if (loop++ > QLCNIC_LB_PKT_POLL_COUNT)
break; break;
} while (!adapter->ahw->diag_cnt); } while (!adapter->ahw->diag_cnt);
...@@ -1539,3 +1541,25 @@ const struct ethtool_ops qlcnic_ethtool_ops = { ...@@ -1539,3 +1541,25 @@ const struct ethtool_ops qlcnic_ethtool_ops = {
.get_dump_data = qlcnic_get_dump_data, .get_dump_data = qlcnic_get_dump_data,
.set_dump = qlcnic_set_dump, .set_dump = qlcnic_set_dump,
}; };
const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops = {
.get_settings = qlcnic_get_settings,
.get_drvinfo = qlcnic_get_drvinfo,
.get_regs_len = qlcnic_get_regs_len,
.get_regs = qlcnic_get_regs,
.get_link = ethtool_op_get_link,
.get_eeprom_len = qlcnic_get_eeprom_len,
.get_eeprom = qlcnic_get_eeprom,
.get_ringparam = qlcnic_get_ringparam,
.set_ringparam = qlcnic_set_ringparam,
.get_channels = qlcnic_get_channels,
.get_pauseparam = qlcnic_get_pauseparam,
.get_wol = qlcnic_get_wol,
.get_strings = qlcnic_get_strings,
.get_ethtool_stats = qlcnic_get_ethtool_stats,
.get_sset_count = qlcnic_get_sset_count,
.get_coalesce = qlcnic_get_intr_coalesce,
.set_coalesce = qlcnic_set_intr_coalesce,
.set_msglevel = qlcnic_set_msglevel,
.get_msglevel = qlcnic_get_msglevel,
};
...@@ -1743,7 +1743,10 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, ...@@ -1743,7 +1743,10 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
qlcnic_change_mtu(netdev, netdev->mtu); qlcnic_change_mtu(netdev, netdev->mtu);
SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops); if (qlcnic_sriov_vf_check(adapter))
SET_ETHTOOL_OPS(netdev, &qlcnic_sriov_vf_ethtool_ops);
else
SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM | netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
NETIF_F_IPV6_CSUM | NETIF_F_GRO | NETIF_F_IPV6_CSUM | NETIF_F_GRO |
......
...@@ -335,7 +335,7 @@ static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr, ...@@ -335,7 +335,7 @@ static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr,
/* Get the FW response data */ /* Get the FW response data */
fw_data = readl(QLCNIC_MBX_FW(ahw, 0)); fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
if (fw_data & QLCNIC_MBX_ASYNC_EVENT) { if (fw_data & QLCNIC_MBX_ASYNC_EVENT) {
qlcnic_83xx_process_aen(adapter); __qlcnic_83xx_process_aen(adapter);
mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL); mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
if (mbx_val) if (mbx_val)
goto poll; goto poll;
......
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