mirror of https://gitee.com/openkylin/linux.git
qlcnic: refactor 83xx diagnostic loopback test
Cleanly separate 83xx diagnostic loopback test routines from 82xx Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
483202d590
commit
ba4468dbf3
|
@ -1442,7 +1442,9 @@ int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
|
|||
void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *);
|
||||
|
||||
/* Functions from qlcnic_ethtool.c */
|
||||
int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]);
|
||||
int qlcnic_check_loopback_buff(unsigned char *, u8 []);
|
||||
int qlcnic_do_lb_test(struct qlcnic_adapter *, u8);
|
||||
int qlcnic_loopback_test(struct net_device *, u8);
|
||||
|
||||
/* Functions from qlcnic_main.c */
|
||||
int qlcnic_reset_context(struct qlcnic_adapter *);
|
||||
|
|
|
@ -257,8 +257,6 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
|
|||
.config_intr_coal = qlcnic_83xx_config_intr_coal,
|
||||
.config_rss = qlcnic_83xx_config_rss,
|
||||
.config_hw_lro = qlcnic_83xx_config_hw_lro,
|
||||
.config_loopback = qlcnic_83xx_set_lb_mode,
|
||||
.clear_loopback = qlcnic_83xx_clear_lb_mode,
|
||||
.config_promisc_mode = qlcnic_83xx_nic_set_promisc,
|
||||
.change_l2_filter = qlcnic_83xx_change_l2_filter,
|
||||
.get_board_info = qlcnic_83xx_get_port_info,
|
||||
|
@ -1118,6 +1116,100 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test)
|
||||
{
|
||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||
struct qlcnic_host_sds_ring *sds_ring;
|
||||
struct qlcnic_host_rds_ring *rds_ring;
|
||||
u8 ring;
|
||||
int ret;
|
||||
|
||||
netif_device_detach(netdev);
|
||||
|
||||
if (netif_running(netdev))
|
||||
__qlcnic_down(adapter, netdev);
|
||||
|
||||
qlcnic_detach(adapter);
|
||||
|
||||
adapter->max_sds_rings = 1;
|
||||
adapter->ahw->diag_test = test;
|
||||
adapter->ahw->linkup = 0;
|
||||
|
||||
ret = qlcnic_attach(adapter);
|
||||
if (ret) {
|
||||
netif_device_attach(netdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = qlcnic_fw_create_ctx(adapter);
|
||||
if (ret) {
|
||||
qlcnic_detach(adapter);
|
||||
netif_device_attach(netdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
|
||||
rds_ring = &adapter->recv_ctx->rds_rings[ring];
|
||||
qlcnic_post_rx_buffers(adapter, rds_ring, ring);
|
||||
}
|
||||
|
||||
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
|
||||
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
|
||||
sds_ring = &adapter->recv_ctx->sds_rings[ring];
|
||||
qlcnic_83xx_enable_intr(adapter, sds_ring);
|
||||
}
|
||||
}
|
||||
|
||||
if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
|
||||
/* disable and free mailbox interrupt */
|
||||
qlcnic_83xx_free_mbx_intr(adapter);
|
||||
adapter->ahw->loopback_state = 0;
|
||||
adapter->ahw->hw_ops->setup_link_event(adapter, 1);
|
||||
}
|
||||
|
||||
set_bit(__QLCNIC_DEV_UP, &adapter->state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
|
||||
int max_sds_rings)
|
||||
{
|
||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||
struct qlcnic_host_sds_ring *sds_ring;
|
||||
int ring, err;
|
||||
|
||||
clear_bit(__QLCNIC_DEV_UP, &adapter->state);
|
||||
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
|
||||
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
|
||||
sds_ring = &adapter->recv_ctx->sds_rings[ring];
|
||||
writel(1, sds_ring->crb_intr_mask);
|
||||
}
|
||||
}
|
||||
|
||||
qlcnic_fw_destroy_ctx(adapter);
|
||||
qlcnic_detach(adapter);
|
||||
|
||||
if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
|
||||
err = qlcnic_83xx_setup_mbx_intr(adapter);
|
||||
if (err) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"%s: failed to setup mbx interrupt\n",
|
||||
__func__);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
adapter->ahw->diag_test = 0;
|
||||
adapter->max_sds_rings = max_sds_rings;
|
||||
|
||||
if (qlcnic_attach(adapter))
|
||||
goto out;
|
||||
|
||||
if (netif_running(netdev))
|
||||
__qlcnic_up(adapter, netdev);
|
||||
out:
|
||||
netif_device_attach(netdev);
|
||||
}
|
||||
|
||||
int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state,
|
||||
u32 beacon)
|
||||
{
|
||||
|
@ -1265,6 +1357,57 @@ int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
|
|||
return err;
|
||||
}
|
||||
|
||||
int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
|
||||
{
|
||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||
int ret = 0, loop = 0, max_sds_rings = adapter->max_sds_rings;
|
||||
|
||||
QLCDB(adapter, DRV, "%s loopback test in progress\n",
|
||||
mode == QLCNIC_ILB_MODE ? "internal" : "external");
|
||||
if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
|
||||
dev_warn(&adapter->pdev->dev,
|
||||
"Loopback test not supported for non privilege function\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
|
||||
return -EBUSY;
|
||||
|
||||
ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
|
||||
if (ret)
|
||||
goto fail_diag_alloc;
|
||||
|
||||
ret = qlcnic_83xx_set_lb_mode(adapter, mode);
|
||||
if (ret)
|
||||
goto free_diag_res;
|
||||
|
||||
/* Poll for link up event before running traffic */
|
||||
do {
|
||||
msleep(500);
|
||||
qlcnic_83xx_process_aen(adapter);
|
||||
if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"Firmware didn't sent link up event to loopback request\n");
|
||||
ret = -QLCNIC_FW_NOT_RESPOND;
|
||||
qlcnic_83xx_clear_lb_mode(adapter, mode);
|
||||
goto free_diag_res;
|
||||
}
|
||||
} while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
|
||||
|
||||
ret = qlcnic_do_lb_test(adapter, mode);
|
||||
|
||||
qlcnic_83xx_clear_lb_mode(adapter, mode);
|
||||
|
||||
free_diag_res:
|
||||
qlcnic_83xx_diag_free_res(netdev, max_sds_rings);
|
||||
|
||||
fail_diag_alloc:
|
||||
adapter->max_sds_rings = max_sds_rings;
|
||||
clear_bit(__QLCNIC_RESETTING, &adapter->state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
|
||||
{
|
||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||
|
|
|
@ -428,6 +428,7 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *);
|
|||
int qlcnic_83xx_reg_test(struct qlcnic_adapter *);
|
||||
int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *);
|
||||
int qlcnic_83xx_get_registers(struct qlcnic_adapter *, u32 *);
|
||||
int qlcnic_83xx_loopback_test(struct net_device *, u8);
|
||||
int qlcnic_83xx_interrupt_test(struct qlcnic_adapter *,
|
||||
struct qlcnic_cmd_args *);
|
||||
int qlcnic_83xx_flash_test(struct qlcnic_adapter *);
|
||||
|
|
|
@ -883,7 +883,7 @@ int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
|
|||
return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
|
||||
}
|
||||
|
||||
static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
|
||||
int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
|
||||
{
|
||||
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
||||
struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
|
||||
|
@ -925,7 +925,7 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
|
||||
int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
|
||||
{
|
||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||
int max_sds_rings = adapter->max_sds_rings;
|
||||
|
@ -935,13 +935,14 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
|
|||
int ret;
|
||||
|
||||
if (qlcnic_83xx_check(adapter))
|
||||
goto skip_cap;
|
||||
return qlcnic_83xx_loopback_test(netdev, mode);
|
||||
|
||||
if (!(ahw->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"Firmware do not support loopback test\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
skip_cap:
|
||||
|
||||
dev_warn(&adapter->pdev->dev, "%s loopback test in progress\n",
|
||||
mode == QLCNIC_ILB_MODE ? "internal" : "external");
|
||||
if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
|
||||
|
@ -962,9 +963,6 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
|
|||
if (ret)
|
||||
goto free_res;
|
||||
|
||||
if (qlcnic_83xx_check(adapter))
|
||||
goto skip_fw_msg;
|
||||
|
||||
ahw->diag_cnt = 0;
|
||||
do {
|
||||
msleep(500);
|
||||
|
@ -979,21 +977,9 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
|
|||
goto free_res;
|
||||
}
|
||||
} while (!QLCNIC_IS_LB_CONFIGURED(ahw->loopback_state));
|
||||
skip_fw_msg:
|
||||
if (qlcnic_83xx_check(adapter)) {
|
||||
/* wait until firmware report link up before running traffic */
|
||||
loop = 0;
|
||||
do {
|
||||
msleep(500);
|
||||
if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"No linkup event after LB req\n");
|
||||
ret = -QLCNIC_FW_NOT_RESPOND;
|
||||
goto free_res;
|
||||
}
|
||||
} while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
|
||||
}
|
||||
|
||||
ret = qlcnic_do_lb_test(adapter, mode);
|
||||
|
||||
qlcnic_clear_lb_mode(adapter, mode);
|
||||
|
||||
free_res:
|
||||
|
|
|
@ -1503,10 +1503,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
|
|||
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
|
||||
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
|
||||
sds_ring = &adapter->recv_ctx->sds_rings[ring];
|
||||
if (qlcnic_83xx_check(adapter))
|
||||
writel(1, sds_ring->crb_intr_mask);
|
||||
else
|
||||
qlcnic_disable_int(sds_ring);
|
||||
qlcnic_disable_int(sds_ring);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1599,10 +1596,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
|
|||
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
|
||||
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
|
||||
sds_ring = &adapter->recv_ctx->sds_rings[ring];
|
||||
if (qlcnic_82xx_check(adapter))
|
||||
qlcnic_enable_int(sds_ring);
|
||||
else
|
||||
qlcnic_83xx_enable_intr(adapter, sds_ring);
|
||||
qlcnic_enable_int(sds_ring);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue