aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic/qlcnic_init.c
diff options
context:
space:
mode:
authorAmit Kumar Salecha <amit.salecha@qlogic.com>2010-02-01 00:25:00 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-02 18:55:46 -0500
commitcdaff1854f32ac9ddb4733530f617d32188665ed (patch)
tree5d1e7b5bcf656d0071840431f1f3cbc94b828e21 /drivers/net/qlcnic/qlcnic_init.c
parent7eb9855d68faabe0004ed18c2af1f0974d3c2c63 (diff)
qlcnic: add loopback diagnostic test
Loopback test (offline) added in ethtool self test. o Set device in loopback mode o Send packets o Process receive packets in qlcnic_process_rcv_ring_diag() o Compare packets o Reset device in normal mode. Signed-off-by: Amit Kumar Salecha <amit.salecha@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.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 7ae8bcc1e439..ea00ab4d4feb 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -1464,3 +1464,78 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
1464 spin_unlock(&rds_ring->lock); 1464 spin_unlock(&rds_ring->lock);
1465} 1465}
1466 1466
1467static struct qlcnic_rx_buffer *
1468qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
1469 struct qlcnic_host_sds_ring *sds_ring,
1470 int ring, u64 sts_data0)
1471{
1472 struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
1473 struct qlcnic_rx_buffer *buffer;
1474 struct sk_buff *skb;
1475 struct qlcnic_host_rds_ring *rds_ring;
1476 int index, length, cksum, pkt_offset;
1477
1478 if (unlikely(ring >= adapter->max_rds_rings))
1479 return NULL;
1480
1481 rds_ring = &recv_ctx->rds_rings[ring];
1482
1483 index = qlcnic_get_sts_refhandle(sts_data0);
1484 if (unlikely(index >= rds_ring->num_desc))
1485 return NULL;
1486
1487 buffer = &rds_ring->rx_buf_arr[index];
1488
1489 length = qlcnic_get_sts_totallength(sts_data0);
1490 cksum = qlcnic_get_sts_status(sts_data0);
1491 pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
1492
1493 skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
1494 if (!skb)
1495 return buffer;
1496
1497 skb_put(skb, rds_ring->skb_size);
1498
1499 if (pkt_offset)
1500 skb_pull(skb, pkt_offset);
1501
1502 skb->truesize = skb->len + sizeof(struct sk_buff);
1503
1504 if (!qlcnic_check_loopback_buff(skb->data))
1505 adapter->diag_cnt++;
1506
1507 dev_kfree_skb_any(skb);
1508
1509 return buffer;
1510}
1511
1512void
1513qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
1514{
1515 struct qlcnic_adapter *adapter = sds_ring->adapter;
1516 struct status_desc *desc;
1517 struct qlcnic_rx_buffer *rxbuf;
1518 u64 sts_data0;
1519
1520 int opcode, ring, desc_cnt;
1521 u32 consumer = sds_ring->consumer;
1522
1523 desc = &sds_ring->desc_head[consumer];
1524 sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
1525
1526 if (!(sts_data0 & STATUS_OWNER_HOST))
1527 return;
1528
1529 desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
1530 opcode = qlcnic_get_sts_opcode(sts_data0);
1531
1532 ring = qlcnic_get_sts_type(sts_data0);
1533 rxbuf = qlcnic_process_rcv_diag(adapter, sds_ring,
1534 ring, sts_data0);
1535
1536 desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
1537 consumer = get_next_index(consumer, sds_ring->num_desc);
1538
1539 sds_ring->consumer = consumer;
1540 writel(consumer, sds_ring->crb_sts_consumer);
1541}