aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic/qlcnic_init.c
diff options
context:
space:
mode:
authorSucheta Chakraborty <sucheta.chakraborty@qlogic.com>2011-06-21 22:52:23 -0400
committerDavid S. Miller <davem@davemloft.net>2011-06-24 04:17:07 -0400
commit22c8c9343258feda9ea9ebb9e5f8cbb727b69454 (patch)
treefac14dcf287c032ff83c832a253178b90a2228b3 /drivers/net/qlcnic/qlcnic_init.c
parent9d6a6440fe30132e4d1f1aadd099345ced9178fb (diff)
qlcnic: multi protocol internal loopback support added.
Driver will generate loopback traffic pattern and do the test. And returns result of the test to application. Updated driver version to 5.0.19. Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com> Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_init.c')
-rw-r--r--drivers/net/qlcnic/qlcnic_init.c126
1 files changed, 124 insertions, 2 deletions
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 5b8bbcf904d5..9d5bee03a587 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)