aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/qlcnic/qlcnic.h22
-rw-r--r--drivers/net/qlcnic/qlcnic_ethtool.c123
-rw-r--r--drivers/net/qlcnic/qlcnic_hw.c50
-rw-r--r--drivers/net/qlcnic/qlcnic_init.c126
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c6
5 files changed, 322 insertions, 5 deletions
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 0be84bdb55b..e5454502df6 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -36,8 +36,8 @@
36 36
37#define _QLCNIC_LINUX_MAJOR 5 37#define _QLCNIC_LINUX_MAJOR 5
38#define _QLCNIC_LINUX_MINOR 0 38#define _QLCNIC_LINUX_MINOR 0
39#define _QLCNIC_LINUX_SUBVERSION 18 39#define _QLCNIC_LINUX_SUBVERSION 19
40#define QLCNIC_LINUX_VERSIONID "5.0.18" 40#define QLCNIC_LINUX_VERSIONID "5.0.19"
41#define QLCNIC_DRV_IDC_VER 0x01 41#define QLCNIC_DRV_IDC_VER 0x01
42#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ 42#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
43 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) 43 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -451,6 +451,7 @@ struct qlcnic_hardware_context {
451 u8 revision_id; 451 u8 revision_id;
452 u8 pci_func; 452 u8 pci_func;
453 u8 linkup; 453 u8 linkup;
454 u8 loopback_state;
454 u16 port_type; 455 u16 port_type;
455 u16 board_type; 456 u16 board_type;
456 457
@@ -780,6 +781,13 @@ struct qlcnic_mac_list_s {
780#define QLCNIC_IP_UP 2 781#define QLCNIC_IP_UP 2
781#define QLCNIC_IP_DOWN 3 782#define QLCNIC_IP_DOWN 3
782 783
784#define QLCNIC_ILB_MODE 0x1
785
786#define QLCNIC_LINKEVENT 0x1
787#define QLCNIC_LB_RESPONSE 0x2
788#define QLCNIC_IS_LB_CONFIGURED(VAL) \
789 (VAL == (QLCNIC_LINKEVENT | QLCNIC_LB_RESPONSE))
790
783/* 791/*
784 * Driver --> Firmware 792 * Driver --> Firmware
785 */ 793 */
@@ -789,13 +797,17 @@ struct qlcnic_mac_list_s {
789#define QLCNIC_H2C_OPCODE_LRO_REQUEST 0x7 797#define QLCNIC_H2C_OPCODE_LRO_REQUEST 0x7
790#define QLCNIC_H2C_OPCODE_SET_MAC_RECEIVE_MODE 0xc 798#define QLCNIC_H2C_OPCODE_SET_MAC_RECEIVE_MODE 0xc
791#define QLCNIC_H2C_OPCODE_CONFIG_IPADDR 0x12 799#define QLCNIC_H2C_OPCODE_CONFIG_IPADDR 0x12
800
792#define QLCNIC_H2C_OPCODE_GET_LINKEVENT 0x15 801#define QLCNIC_H2C_OPCODE_GET_LINKEVENT 0x15
793#define QLCNIC_H2C_OPCODE_CONFIG_BRIDGING 0x17 802#define QLCNIC_H2C_OPCODE_CONFIG_BRIDGING 0x17
794#define QLCNIC_H2C_OPCODE_CONFIG_HW_LRO 0x18 803#define QLCNIC_H2C_OPCODE_CONFIG_HW_LRO 0x18
804#define QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK 0x13
805
795/* 806/*
796 * Firmware --> Driver 807 * Firmware --> Driver
797 */ 808 */
798 809
810#define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK 0x8f
799#define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 141 811#define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 141
800 812
801#define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */ 813#define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */
@@ -1430,6 +1442,12 @@ int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
1430void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter, 1442void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
1431 struct qlcnic_host_tx_ring *tx_ring); 1443 struct qlcnic_host_tx_ring *tx_ring);
1432void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *); 1444void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
1445void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
1446void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter);
1447int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode);
1448
1449/* Functions from qlcnic_ethtool.c */
1450int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]);
1433 1451
1434/* Functions from qlcnic_main.c */ 1452/* Functions from qlcnic_main.c */
1435int qlcnic_reset_context(struct qlcnic_adapter *); 1453int qlcnic_reset_context(struct qlcnic_adapter *);
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 31f5cba6222..743035e4538 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -84,7 +84,8 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
84static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = { 84static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
85 "Register_Test_on_offline", 85 "Register_Test_on_offline",
86 "Link_Test_on_offline", 86 "Link_Test_on_offline",
87 "Interrupt_Test_offline" 87 "Interrupt_Test_offline",
88 "Loopback_Test_offline"
88}; 89};
89 90
90#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test) 91#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test)
@@ -685,6 +686,123 @@ clear_it:
685 return ret; 686 return ret;
686} 687}
687 688
689#define QLCNIC_ILB_PKT_SIZE 64
690#define QLCNIC_NUM_ILB_PKT 16
691#define QLCNIC_ILB_MAX_RCV_LOOP 10
692
693static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[])
694{
695 unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
696
697 memset(data, 0x4e, QLCNIC_ILB_PKT_SIZE);
698
699 memcpy(data, mac, ETH_ALEN);
700 memcpy(data + ETH_ALEN, mac, ETH_ALEN);
701
702 memcpy(data + 2 * ETH_ALEN, random_data, sizeof(random_data));
703}
704
705int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
706{
707 unsigned char buff[QLCNIC_ILB_PKT_SIZE];
708 qlcnic_create_loopback_buff(buff, mac);
709 return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
710}
711
712static int qlcnic_do_ilb_test(struct qlcnic_adapter *adapter)
713{
714 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
715 struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
716 struct sk_buff *skb;
717 int i, loop, cnt = 0;
718
719 for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
720 skb = dev_alloc_skb(QLCNIC_ILB_PKT_SIZE);
721 qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
722 skb_put(skb, QLCNIC_ILB_PKT_SIZE);
723
724 adapter->diag_cnt = 0;
725 qlcnic_xmit_frame(skb, adapter->netdev);
726
727 loop = 0;
728 do {
729 msleep(1);
730 qlcnic_process_rcv_ring_diag(sds_ring);
731 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
732 break;
733 } while (!adapter->diag_cnt);
734
735 dev_kfree_skb_any(skb);
736
737 if (!adapter->diag_cnt)
738 dev_warn(&adapter->pdev->dev, "ILB Test: %dth packet"
739 " not recevied\n", i + 1);
740 else
741 cnt++;
742 }
743 if (cnt != i) {
744 dev_warn(&adapter->pdev->dev, "ILB Test failed\n");
745 return -1;
746 }
747 return 0;
748}
749
750static int qlcnic_iloopback_test(struct net_device *netdev)
751{
752 struct qlcnic_adapter *adapter = netdev_priv(netdev);
753 int max_sds_rings = adapter->max_sds_rings;
754 struct qlcnic_host_sds_ring *sds_ring;
755 int loop = 0;
756 int ret;
757
758 netdev_info(netdev, "%s: in progress\n", __func__);
759 if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
760 netdev_warn(netdev, "Loopback test not supported for non "
761 "privilege function\n");
762 return 0;
763 }
764
765 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
766 return -EIO;
767
768
769 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
770 if (ret)
771 goto clear_it;
772
773 sds_ring = &adapter->recv_ctx->sds_rings[0];
774
775 ret = qlcnic_set_lb_mode(adapter, QLCNIC_ILB_MODE);
776 if (ret)
777 goto free_res;
778
779 do {
780 msleep(500);
781 qlcnic_process_rcv_ring_diag(sds_ring);
782 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
783 break;
784 } while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state));
785
786 if (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state)) {
787 netdev_info(netdev, "firmware didnt respond to loopback "
788 "configure request\n");
789 ret = adapter->ahw->loopback_state;
790 goto free_res;
791 }
792
793 ret = qlcnic_do_ilb_test(adapter);
794
795 qlcnic_clear_lb_mode(adapter);
796
797 free_res:
798 qlcnic_diag_free_res(netdev, max_sds_rings);
799
800 clear_it:
801 adapter->max_sds_rings = max_sds_rings;
802 clear_bit(__QLCNIC_RESETTING, &adapter->state);
803 return ret;
804}
805
688static void 806static void
689qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, 807qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
690 u64 *data) 808 u64 *data)
@@ -704,6 +822,9 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
704 if (data[2]) 822 if (data[2])
705 eth_test->flags |= ETH_TEST_FL_FAILED; 823 eth_test->flags |= ETH_TEST_FL_FAILED;
706 824
825 data[3] = qlcnic_iloopback_test(dev);
826 if (data[3])
827 eth_test->flags |= ETH_TEST_FL_FAILED;
707 828
708 } 829 }
709} 830}
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index 81de563ee96..0391a04695d 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -533,6 +533,56 @@ void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
533 } 533 }
534} 534}
535 535
536int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag)
537{
538 struct qlcnic_nic_req req;
539 int rv;
540
541 memset(&req, 0, sizeof(struct qlcnic_nic_req));
542
543 req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
544 req.req_hdr = cpu_to_le64(QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK |
545 ((u64) adapter->portnum << 16) | ((u64) 0x1 << 32));
546
547 req.words[0] = cpu_to_le64(flag);
548
549 rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
550 if (rv != 0)
551 dev_err(&adapter->pdev->dev, "%sting loopback mode failed\n",
552 flag ? "Set" : "Reset");
553 return rv;
554}
555
556int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
557{
558 if (qlcnic_set_fw_loopback(adapter, mode))
559 return -EIO;
560
561 if (qlcnic_nic_set_promisc(adapter, VPORT_MISS_MODE_ACCEPT_ALL)) {
562 qlcnic_set_fw_loopback(adapter, mode);
563 return -EIO;
564 }
565
566 msleep(1000);
567 return 0;
568}
569
570void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter)
571{
572 int mode = VPORT_MISS_MODE_DROP;
573 struct net_device *netdev = adapter->netdev;
574
575 qlcnic_set_fw_loopback(adapter, 0);
576
577 if (netdev->flags & IFF_PROMISC)
578 mode = VPORT_MISS_MODE_ACCEPT_ALL;
579 else if (netdev->flags & IFF_ALLMULTI)
580 mode = VPORT_MISS_MODE_ACCEPT_MULTI;
581
582 qlcnic_nic_set_promisc(adapter, mode);
583 msleep(1000);
584}
585
536/* 586/*
537 * Send the interrupt coalescing parameter set by ethtool to the card. 587 * Send the interrupt coalescing parameter set by ethtool to the card.
538 */ 588 */
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 5b8bbcf904d..9d5bee03a58 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -1281,6 +1281,7 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
1281 u16 cable_len; 1281 u16 cable_len;
1282 u16 link_speed; 1282 u16 link_speed;
1283 u8 link_status, module, duplex, autoneg; 1283 u8 link_status, module, duplex, autoneg;
1284 u8 lb_status = 0;
1284 struct net_device *netdev = adapter->netdev; 1285 struct net_device *netdev = adapter->netdev;
1285 1286
1286 adapter->has_link_events = 1; 1287 adapter->has_link_events = 1;
@@ -1292,6 +1293,7 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
1292 link_status = msg->body[2] & 0xff; 1293 link_status = msg->body[2] & 0xff;
1293 duplex = (msg->body[2] >> 16) & 0xff; 1294 duplex = (msg->body[2] >> 16) & 0xff;
1294 autoneg = (msg->body[2] >> 24) & 0xff; 1295 autoneg = (msg->body[2] >> 24) & 0xff;
1296 lb_status = (msg->body[2] >> 32) & 0x3;
1295 1297
1296 module = (msg->body[2] >> 8) & 0xff; 1298 module = (msg->body[2] >> 8) & 0xff;
1297 if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) 1299 if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
@@ -1301,6 +1303,9 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
1301 dev_info(&netdev->dev, "unsupported cable length %d\n", 1303 dev_info(&netdev->dev, "unsupported cable length %d\n",
1302 cable_len); 1304 cable_len);
1303 1305
1306 if (!link_status && (lb_status == 1))
1307 adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
1308
1304 qlcnic_advert_link_change(adapter, link_status); 1309 qlcnic_advert_link_change(adapter, link_status);
1305 1310
1306 if (duplex == LINKEVENT_FULL_DUPLEX) 1311 if (duplex == LINKEVENT_FULL_DUPLEX)
@@ -1319,7 +1324,9 @@ qlcnic_handle_fw_message(int desc_cnt, int index,
1319{ 1324{
1320 struct qlcnic_fw_msg msg; 1325 struct qlcnic_fw_msg msg;
1321 struct status_desc *desc; 1326 struct status_desc *desc;
1322 int i = 0, opcode; 1327 struct qlcnic_adapter *adapter;
1328 struct device *dev;
1329 int i = 0, opcode, ret;
1323 1330
1324 while (desc_cnt > 0 && i < 8) { 1331 while (desc_cnt > 0 && i < 8) {
1325 desc = &sds_ring->desc_head[index]; 1332 desc = &sds_ring->desc_head[index];
@@ -1330,10 +1337,28 @@ qlcnic_handle_fw_message(int desc_cnt, int index,
1330 desc_cnt--; 1337 desc_cnt--;
1331 } 1338 }
1332 1339
1340 adapter = sds_ring->adapter;
1341 dev = &adapter->pdev->dev;
1333 opcode = qlcnic_get_nic_msg_opcode(msg.body[0]); 1342 opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
1343
1334 switch (opcode) { 1344 switch (opcode) {
1335 case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE: 1345 case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
1336 qlcnic_handle_linkevent(sds_ring->adapter, &msg); 1346 qlcnic_handle_linkevent(adapter, &msg);
1347 break;
1348 case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
1349 ret = (u32)(msg.body[1]);
1350 switch (ret) {
1351 case 0:
1352 adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
1353 break;
1354 case 1:
1355 dev_info(dev, "loopback already in progress\n");
1356 break;
1357 default:
1358 dev_info(dev, "loopback configure request failed,"
1359 " ret %x\n", ret);
1360 break;
1361 }
1337 break; 1362 break;
1338 default: 1363 default:
1339 break; 1364 break;
@@ -1746,6 +1771,103 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
1746 spin_unlock(&rds_ring->lock); 1771 spin_unlock(&rds_ring->lock);
1747} 1772}
1748 1773
1774static void dump_skb(struct sk_buff *skb)
1775{
1776 int i;
1777 unsigned char *data = skb->data;
1778
1779 printk(KERN_INFO "\n");
1780 for (i = 0; i < skb->len; i++) {
1781 printk(KERN_INFO "%02x ", data[i]);
1782 if ((i & 0x0f) == 8)
1783 printk(KERN_INFO "\n");
1784 }
1785}
1786
1787void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
1788 struct qlcnic_host_sds_ring *sds_ring,
1789 int ring, u64 sts_data0)
1790{
1791 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1792 struct sk_buff *skb;
1793 struct qlcnic_host_rds_ring *rds_ring;
1794 int index, length, cksum, pkt_offset;
1795
1796 if (unlikely(ring >= adapter->max_rds_rings))
1797 return;
1798
1799 rds_ring = &recv_ctx->rds_rings[ring];
1800
1801 index = qlcnic_get_sts_refhandle(sts_data0);
1802 length = qlcnic_get_sts_totallength(sts_data0);
1803 if (unlikely(index >= rds_ring->num_desc))
1804 return;
1805
1806 cksum = qlcnic_get_sts_status(sts_data0);
1807 pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
1808
1809 skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
1810 if (!skb)
1811 return;
1812
1813 if (length > rds_ring->skb_size)
1814 skb_put(skb, rds_ring->skb_size);
1815 else
1816 skb_put(skb, length);
1817
1818 if (pkt_offset)
1819 skb_pull(skb, pkt_offset);
1820
1821 if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
1822 adapter->diag_cnt++;
1823 else
1824 dump_skb(skb);
1825
1826 dev_kfree_skb_any(skb);
1827 adapter->stats.rx_pkts++;
1828 adapter->stats.rxbytes += length;
1829
1830 return;
1831}
1832
1833void
1834qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
1835{
1836 struct qlcnic_adapter *adapter = sds_ring->adapter;
1837 struct status_desc *desc;
1838 u64 sts_data0;
1839 int ring, opcode, desc_cnt;
1840
1841 u32 consumer = sds_ring->consumer;
1842
1843 desc = &sds_ring->desc_head[consumer];
1844 sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
1845
1846 if (!(sts_data0 & STATUS_OWNER_HOST))
1847 return;
1848
1849 desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
1850 opcode = qlcnic_get_sts_opcode(sts_data0);
1851 switch (opcode) {
1852 case QLCNIC_RESPONSE_DESC:
1853 qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
1854 break;
1855 default:
1856 ring = qlcnic_get_sts_type(sts_data0);
1857 qlcnic_process_rcv_diag(adapter, sds_ring, ring, sts_data0);
1858 break;
1859 }
1860
1861 for (; desc_cnt > 0; desc_cnt--) {
1862 desc = &sds_ring->desc_head[consumer];
1863 desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
1864 consumer = get_next_index(consumer, sds_ring->num_desc);
1865 }
1866
1867 sds_ring->consumer = consumer;
1868 writel(consumer, sds_ring->crb_sts_consumer);
1869}
1870
1749void 1871void
1750qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2, 1872qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2,
1751 u8 alt_mac, u8 *mac) 1873 u8 alt_mac, u8 *mac)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index ac7f8a2f7d9..357436be801 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -1391,6 +1391,12 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
1391 qlcnic_enable_int(sds_ring); 1391 qlcnic_enable_int(sds_ring);
1392 } 1392 }
1393 } 1393 }
1394
1395 if (adapter->diag_test == QLCNIC_LOOPBACK_TEST) {
1396 adapter->ahw->loopback_state = 0;
1397 qlcnic_linkevent_request(adapter, 1);
1398 }
1399
1394 set_bit(__QLCNIC_DEV_UP, &adapter->state); 1400 set_bit(__QLCNIC_DEV_UP, &adapter->state);
1395 1401
1396 return 0; 1402 return 0;