aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJitendra Kalsaria <jitendra.kalsaria@qlogic.com>2013-02-09 04:29:51 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-11 02:04:13 -0500
commitba4468dbf3364c35652dda14e2ef90c5cf09ab16 (patch)
treec4c17ea14da629b8762c471ca6368458cf42267c /drivers
parent483202d590cd76fc794f3aa11a342b718a804a28 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h4
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c147
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h1
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c28
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c10
5 files changed, 158 insertions, 32 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 3a840e741982..61b594c6d9d7 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1442,7 +1442,9 @@ int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
1442void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *); 1442void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *);
1443 1443
1444/* Functions from qlcnic_ethtool.c */ 1444/* Functions from qlcnic_ethtool.c */
1445int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]); 1445int qlcnic_check_loopback_buff(unsigned char *, u8 []);
1446int qlcnic_do_lb_test(struct qlcnic_adapter *, u8);
1447int qlcnic_loopback_test(struct net_device *, u8);
1446 1448
1447/* Functions from qlcnic_main.c */ 1449/* Functions from qlcnic_main.c */
1448int qlcnic_reset_context(struct qlcnic_adapter *); 1450int qlcnic_reset_context(struct qlcnic_adapter *);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 3d628c638247..3d4813121d2e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -257,8 +257,6 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
257 .config_intr_coal = qlcnic_83xx_config_intr_coal, 257 .config_intr_coal = qlcnic_83xx_config_intr_coal,
258 .config_rss = qlcnic_83xx_config_rss, 258 .config_rss = qlcnic_83xx_config_rss,
259 .config_hw_lro = qlcnic_83xx_config_hw_lro, 259 .config_hw_lro = qlcnic_83xx_config_hw_lro,
260 .config_loopback = qlcnic_83xx_set_lb_mode,
261 .clear_loopback = qlcnic_83xx_clear_lb_mode,
262 .config_promisc_mode = qlcnic_83xx_nic_set_promisc, 260 .config_promisc_mode = qlcnic_83xx_nic_set_promisc,
263 .change_l2_filter = qlcnic_83xx_change_l2_filter, 261 .change_l2_filter = qlcnic_83xx_change_l2_filter,
264 .get_board_info = qlcnic_83xx_get_port_info, 262 .get_board_info = qlcnic_83xx_get_port_info,
@@ -1118,6 +1116,100 @@ out:
1118 return err; 1116 return err;
1119} 1117}
1120 1118
1119static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test)
1120{
1121 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1122 struct qlcnic_host_sds_ring *sds_ring;
1123 struct qlcnic_host_rds_ring *rds_ring;
1124 u8 ring;
1125 int ret;
1126
1127 netif_device_detach(netdev);
1128
1129 if (netif_running(netdev))
1130 __qlcnic_down(adapter, netdev);
1131
1132 qlcnic_detach(adapter);
1133
1134 adapter->max_sds_rings = 1;
1135 adapter->ahw->diag_test = test;
1136 adapter->ahw->linkup = 0;
1137
1138 ret = qlcnic_attach(adapter);
1139 if (ret) {
1140 netif_device_attach(netdev);
1141 return ret;
1142 }
1143
1144 ret = qlcnic_fw_create_ctx(adapter);
1145 if (ret) {
1146 qlcnic_detach(adapter);
1147 netif_device_attach(netdev);
1148 return ret;
1149 }
1150
1151 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
1152 rds_ring = &adapter->recv_ctx->rds_rings[ring];
1153 qlcnic_post_rx_buffers(adapter, rds_ring, ring);
1154 }
1155
1156 if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
1157 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
1158 sds_ring = &adapter->recv_ctx->sds_rings[ring];
1159 qlcnic_83xx_enable_intr(adapter, sds_ring);
1160 }
1161 }
1162
1163 if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
1164 /* disable and free mailbox interrupt */
1165 qlcnic_83xx_free_mbx_intr(adapter);
1166 adapter->ahw->loopback_state = 0;
1167 adapter->ahw->hw_ops->setup_link_event(adapter, 1);
1168 }
1169
1170 set_bit(__QLCNIC_DEV_UP, &adapter->state);
1171 return 0;
1172}
1173
1174static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
1175 int max_sds_rings)
1176{
1177 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1178 struct qlcnic_host_sds_ring *sds_ring;
1179 int ring, err;
1180
1181 clear_bit(__QLCNIC_DEV_UP, &adapter->state);
1182 if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
1183 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
1184 sds_ring = &adapter->recv_ctx->sds_rings[ring];
1185 writel(1, sds_ring->crb_intr_mask);
1186 }
1187 }
1188
1189 qlcnic_fw_destroy_ctx(adapter);
1190 qlcnic_detach(adapter);
1191
1192 if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
1193 err = qlcnic_83xx_setup_mbx_intr(adapter);
1194 if (err) {
1195 dev_err(&adapter->pdev->dev,
1196 "%s: failed to setup mbx interrupt\n",
1197 __func__);
1198 goto out;
1199 }
1200 }
1201 adapter->ahw->diag_test = 0;
1202 adapter->max_sds_rings = max_sds_rings;
1203
1204 if (qlcnic_attach(adapter))
1205 goto out;
1206
1207 if (netif_running(netdev))
1208 __qlcnic_up(adapter, netdev);
1209out:
1210 netif_device_attach(netdev);
1211}
1212
1121int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state, 1213int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state,
1122 u32 beacon) 1214 u32 beacon)
1123{ 1215{
@@ -1265,6 +1357,57 @@ int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
1265 return err; 1357 return err;
1266} 1358}
1267 1359
1360int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
1361{
1362 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1363 struct qlcnic_hardware_context *ahw = adapter->ahw;
1364 int ret = 0, loop = 0, max_sds_rings = adapter->max_sds_rings;
1365
1366 QLCDB(adapter, DRV, "%s loopback test in progress\n",
1367 mode == QLCNIC_ILB_MODE ? "internal" : "external");
1368 if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
1369 dev_warn(&adapter->pdev->dev,
1370 "Loopback test not supported for non privilege function\n");
1371 return ret;
1372 }
1373
1374 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
1375 return -EBUSY;
1376
1377 ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
1378 if (ret)
1379 goto fail_diag_alloc;
1380
1381 ret = qlcnic_83xx_set_lb_mode(adapter, mode);
1382 if (ret)
1383 goto free_diag_res;
1384
1385 /* Poll for link up event before running traffic */
1386 do {
1387 msleep(500);
1388 qlcnic_83xx_process_aen(adapter);
1389 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
1390 dev_info(&adapter->pdev->dev,
1391 "Firmware didn't sent link up event to loopback request\n");
1392 ret = -QLCNIC_FW_NOT_RESPOND;
1393 qlcnic_83xx_clear_lb_mode(adapter, mode);
1394 goto free_diag_res;
1395 }
1396 } while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
1397
1398 ret = qlcnic_do_lb_test(adapter, mode);
1399
1400 qlcnic_83xx_clear_lb_mode(adapter, mode);
1401
1402free_diag_res:
1403 qlcnic_83xx_diag_free_res(netdev, max_sds_rings);
1404
1405fail_diag_alloc:
1406 adapter->max_sds_rings = max_sds_rings;
1407 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1408 return ret;
1409}
1410
1268int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) 1411int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
1269{ 1412{
1270 struct qlcnic_hardware_context *ahw = adapter->ahw; 1413 struct qlcnic_hardware_context *ahw = adapter->ahw;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index 16c5df626616..87f2e08c31f4 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -428,6 +428,7 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *);
428int qlcnic_83xx_reg_test(struct qlcnic_adapter *); 428int qlcnic_83xx_reg_test(struct qlcnic_adapter *);
429int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *); 429int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *);
430int qlcnic_83xx_get_registers(struct qlcnic_adapter *, u32 *); 430int qlcnic_83xx_get_registers(struct qlcnic_adapter *, u32 *);
431int qlcnic_83xx_loopback_test(struct net_device *, u8);
431int qlcnic_83xx_interrupt_test(struct qlcnic_adapter *, 432int qlcnic_83xx_interrupt_test(struct qlcnic_adapter *,
432 struct qlcnic_cmd_args *); 433 struct qlcnic_cmd_args *);
433int qlcnic_83xx_flash_test(struct qlcnic_adapter *); 434int qlcnic_83xx_flash_test(struct qlcnic_adapter *);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 6320d551c63d..58e255437d5a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -883,7 +883,7 @@ int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
883 return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE); 883 return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
884} 884}
885 885
886static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) 886int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
887{ 887{
888 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; 888 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
889 struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0]; 889 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)
925 return 0; 925 return 0;
926} 926}
927 927
928static int qlcnic_loopback_test(struct net_device *netdev, u8 mode) 928int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
929{ 929{
930 struct qlcnic_adapter *adapter = netdev_priv(netdev); 930 struct qlcnic_adapter *adapter = netdev_priv(netdev);
931 int max_sds_rings = adapter->max_sds_rings; 931 int max_sds_rings = adapter->max_sds_rings;
@@ -935,13 +935,14 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
935 int ret; 935 int ret;
936 936
937 if (qlcnic_83xx_check(adapter)) 937 if (qlcnic_83xx_check(adapter))
938 goto skip_cap; 938 return qlcnic_83xx_loopback_test(netdev, mode);
939
939 if (!(ahw->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) { 940 if (!(ahw->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
940 dev_info(&adapter->pdev->dev, 941 dev_info(&adapter->pdev->dev,
941 "Firmware do not support loopback test\n"); 942 "Firmware do not support loopback test\n");
942 return -EOPNOTSUPP; 943 return -EOPNOTSUPP;
943 } 944 }
944skip_cap: 945
945 dev_warn(&adapter->pdev->dev, "%s loopback test in progress\n", 946 dev_warn(&adapter->pdev->dev, "%s loopback test in progress\n",
946 mode == QLCNIC_ILB_MODE ? "internal" : "external"); 947 mode == QLCNIC_ILB_MODE ? "internal" : "external");
947 if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { 948 if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
@@ -962,9 +963,6 @@ skip_cap:
962 if (ret) 963 if (ret)
963 goto free_res; 964 goto free_res;
964 965
965 if (qlcnic_83xx_check(adapter))
966 goto skip_fw_msg;
967
968 ahw->diag_cnt = 0; 966 ahw->diag_cnt = 0;
969 do { 967 do {
970 msleep(500); 968 msleep(500);
@@ -979,21 +977,9 @@ skip_cap:
979 goto free_res; 977 goto free_res;
980 } 978 }
981 } while (!QLCNIC_IS_LB_CONFIGURED(ahw->loopback_state)); 979 } while (!QLCNIC_IS_LB_CONFIGURED(ahw->loopback_state));
982skip_fw_msg: 980
983 if (qlcnic_83xx_check(adapter)) {
984 /* wait until firmware report link up before running traffic */
985 loop = 0;
986 do {
987 msleep(500);
988 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
989 dev_info(&adapter->pdev->dev,
990 "No linkup event after LB req\n");
991 ret = -QLCNIC_FW_NOT_RESPOND;
992 goto free_res;
993 }
994 } while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
995 }
996 ret = qlcnic_do_lb_test(adapter, mode); 981 ret = qlcnic_do_lb_test(adapter, mode);
982
997 qlcnic_clear_lb_mode(adapter, mode); 983 qlcnic_clear_lb_mode(adapter, mode);
998 984
999 free_res: 985 free_res:
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index dcb990d3d559..30aa1f295224 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -1503,10 +1503,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
1503 if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { 1503 if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
1504 for (ring = 0; ring < adapter->max_sds_rings; ring++) { 1504 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
1505 sds_ring = &adapter->recv_ctx->sds_rings[ring]; 1505 sds_ring = &adapter->recv_ctx->sds_rings[ring];
1506 if (qlcnic_83xx_check(adapter)) 1506 qlcnic_disable_int(sds_ring);
1507 writel(1, sds_ring->crb_intr_mask);
1508 else
1509 qlcnic_disable_int(sds_ring);
1510 } 1507 }
1511 } 1508 }
1512 1509
@@ -1599,10 +1596,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
1599 if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { 1596 if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
1600 for (ring = 0; ring < adapter->max_sds_rings; ring++) { 1597 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
1601 sds_ring = &adapter->recv_ctx->sds_rings[ring]; 1598 sds_ring = &adapter->recv_ctx->sds_rings[ring];
1602 if (qlcnic_82xx_check(adapter)) 1599 qlcnic_enable_int(sds_ring);
1603 qlcnic_enable_int(sds_ring);
1604 else
1605 qlcnic_83xx_enable_intr(adapter, sds_ring);
1606 } 1600 }
1607 } 1601 }
1608 1602