aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuresh R <sureshr@serverengines.com>2009-12-03 19:15:52 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-03 19:15:52 -0500
commitff33a6e2ab97f4cde484cdf1a41778af6d6b7cff (patch)
tree655e8cc5a61e6ed5245b182217fbca9632d17499
parent49d09007879ce7bee36ab453c73e97c00adce884 (diff)
be2net: Add support for ethtool self test
This patch adds support for ethtool selftest. From: Suresh R <sureshr@serverengines.com> Signed-off-by: Ajit Khaparde <ajitk@serverengines.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/benet/be_cmds.c93
-rw-r--r--drivers/net/benet/be_cmds.h48
-rw-r--r--drivers/net/benet/be_ethtool.c82
3 files changed, 223 insertions, 0 deletions
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index bee7b822d120..1b68bd98dc0c 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -1478,3 +1478,96 @@ err:
1478 spin_unlock_bh(&adapter->mcc_lock); 1478 spin_unlock_bh(&adapter->mcc_lock);
1479 return status; 1479 return status;
1480} 1480}
1481
1482int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
1483 u32 loopback_type, u32 pkt_size, u32 num_pkts, u64 pattern)
1484{
1485 struct be_mcc_wrb *wrb;
1486 struct be_cmd_req_loopback_test *req;
1487 int status;
1488
1489 spin_lock_bh(&adapter->mcc_lock);
1490
1491 wrb = wrb_from_mccq(adapter);
1492 if (!wrb) {
1493 status = -EBUSY;
1494 goto err;
1495 }
1496
1497 req = embedded_payload(wrb);
1498
1499 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
1500 OPCODE_LOWLEVEL_LOOPBACK_TEST);
1501
1502 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
1503 OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req));
1504
1505 req->pattern = cpu_to_le64(pattern);
1506 req->src_port = cpu_to_le32(port_num);
1507 req->dest_port = cpu_to_le32(port_num);
1508 req->pkt_size = cpu_to_le32(pkt_size);
1509 req->num_pkts = cpu_to_le32(num_pkts);
1510 req->loopback_type = cpu_to_le32(loopback_type);
1511
1512 status = be_mcc_notify_wait(adapter);
1513 if (!status) {
1514 struct be_cmd_resp_loopback_test *resp = embedded_payload(wrb);
1515 status = le32_to_cpu(resp->status);
1516 }
1517
1518err:
1519 spin_unlock_bh(&adapter->mcc_lock);
1520 return status;
1521}
1522
1523int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
1524 u32 byte_cnt, struct be_dma_mem *cmd)
1525{
1526 struct be_mcc_wrb *wrb;
1527 struct be_cmd_req_ddrdma_test *req;
1528 struct be_sge *sge;
1529 int status;
1530 int i, j = 0;
1531
1532 spin_lock_bh(&adapter->mcc_lock);
1533
1534 wrb = wrb_from_mccq(adapter);
1535 if (!wrb) {
1536 status = -EBUSY;
1537 goto err;
1538 }
1539 req = cmd->va;
1540 sge = nonembedded_sgl(wrb);
1541 be_wrb_hdr_prepare(wrb, cmd->size, false, 1,
1542 OPCODE_LOWLEVEL_HOST_DDR_DMA);
1543 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
1544 OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size);
1545
1546 sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma));
1547 sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF);
1548 sge->len = cpu_to_le32(cmd->size);
1549
1550 req->pattern = cpu_to_le64(pattern);
1551 req->byte_count = cpu_to_le32(byte_cnt);
1552 for (i = 0; i < byte_cnt; i++) {
1553 req->snd_buff[i] = (u8)(pattern >> (j*8));
1554 j++;
1555 if (j > 7)
1556 j = 0;
1557 }
1558
1559 status = be_mcc_notify_wait(adapter);
1560
1561 if (!status) {
1562 struct be_cmd_resp_ddrdma_test *resp;
1563 resp = cmd->va;
1564 if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) ||
1565 resp->snd_err) {
1566 status = -1;
1567 }
1568 }
1569
1570err:
1571 spin_unlock_bh(&adapter->mcc_lock);
1572 return status;
1573}
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index e8512a144f5e..e7323be507d0 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -112,6 +112,7 @@ struct be_mcc_mailbox {
112 112
113#define CMD_SUBSYSTEM_COMMON 0x1 113#define CMD_SUBSYSTEM_COMMON 0x1
114#define CMD_SUBSYSTEM_ETH 0x3 114#define CMD_SUBSYSTEM_ETH 0x3
115#define CMD_SUBSYSTEM_LOWLEVEL 0xb
115 116
116#define OPCODE_COMMON_NTWK_MAC_QUERY 1 117#define OPCODE_COMMON_NTWK_MAC_QUERY 1
117#define OPCODE_COMMON_NTWK_MAC_SET 2 118#define OPCODE_COMMON_NTWK_MAC_SET 2
@@ -152,6 +153,9 @@ struct be_mcc_mailbox {
152#define OPCODE_ETH_RX_DESTROY 10 153#define OPCODE_ETH_RX_DESTROY 10
153#define OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG 12 154#define OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG 12
154 155
156#define OPCODE_LOWLEVEL_HOST_DDR_DMA 17
157#define OPCODE_LOWLEVEL_LOOPBACK_TEST 18
158
155struct be_cmd_req_hdr { 159struct be_cmd_req_hdr {
156 u8 opcode; /* dword 0 */ 160 u8 opcode; /* dword 0 */
157 u8 subsystem; /* dword 0 */ 161 u8 subsystem; /* dword 0 */
@@ -797,6 +801,45 @@ struct be_cmd_req_acpi_wol_magic_config{
797 u8 rsvd2[2]; 801 u8 rsvd2[2];
798} __packed; 802} __packed;
799 803
804/********************** LoopBack test *********************/
805struct be_cmd_req_loopback_test {
806 struct be_cmd_req_hdr hdr;
807 u32 loopback_type;
808 u32 num_pkts;
809 u64 pattern;
810 u32 src_port;
811 u32 dest_port;
812 u32 pkt_size;
813};
814
815struct be_cmd_resp_loopback_test {
816 struct be_cmd_resp_hdr resp_hdr;
817 u32 status;
818 u32 num_txfer;
819 u32 num_rx;
820 u32 miscomp_off;
821 u32 ticks_compl;
822};
823
824/********************** DDR DMA test *********************/
825struct be_cmd_req_ddrdma_test {
826 struct be_cmd_req_hdr hdr;
827 u64 pattern;
828 u32 byte_count;
829 u32 rsvd0;
830 u8 snd_buff[4096];
831 u8 rsvd1[4096];
832};
833
834struct be_cmd_resp_ddrdma_test {
835 struct be_cmd_resp_hdr hdr;
836 u64 pattern;
837 u32 byte_cnt;
838 u32 snd_err;
839 u8 rsvd0[4096];
840 u8 rcv_buff[4096];
841};
842
800extern int be_pci_fnum_get(struct be_adapter *adapter); 843extern int be_pci_fnum_get(struct be_adapter *adapter);
801extern int be_cmd_POST(struct be_adapter *adapter); 844extern int be_cmd_POST(struct be_adapter *adapter);
802extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, 845extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
@@ -864,3 +907,8 @@ extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
864 struct be_dma_mem *nonemb_cmd); 907 struct be_dma_mem *nonemb_cmd);
865extern int be_cmd_fw_init(struct be_adapter *adapter); 908extern int be_cmd_fw_init(struct be_adapter *adapter);
866extern int be_cmd_fw_clean(struct be_adapter *adapter); 909extern int be_cmd_fw_clean(struct be_adapter *adapter);
910extern int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
911 u32 loopback_type, u32 pkt_size,
912 u32 num_pkts, u64 pattern);
913extern int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
914 u32 byte_cnt, struct be_dma_mem *cmd);
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index 83a2fc703995..298b92cbd689 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -107,6 +107,18 @@ static const struct be_ethtool_stat et_stats[] = {
107}; 107};
108#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats) 108#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats)
109 109
110static const char et_self_tests[][ETH_GSTRING_LEN] = {
111 "MAC Loopback test",
112 "PHY Loopback test",
113 "External Loopback test",
114 "DDR DMA test"
115};
116
117#define ETHTOOL_TESTS_NUM ARRAY_SIZE(et_self_tests)
118#define BE_MAC_LOOPBACK 0x0
119#define BE_PHY_LOOPBACK 0x1
120#define BE_ONE_PORT_EXT_LOOPBACK 0x2
121
110static void 122static void
111be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) 123be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
112{ 124{
@@ -278,12 +290,20 @@ be_get_stat_strings(struct net_device *netdev, uint32_t stringset,
278 data += ETH_GSTRING_LEN; 290 data += ETH_GSTRING_LEN;
279 } 291 }
280 break; 292 break;
293 case ETH_SS_TEST:
294 for (i = 0; i < ETHTOOL_TESTS_NUM; i++) {
295 memcpy(data, et_self_tests[i], ETH_GSTRING_LEN);
296 data += ETH_GSTRING_LEN;
297 }
298 break;
281 } 299 }
282} 300}
283 301
284static int be_get_sset_count(struct net_device *netdev, int stringset) 302static int be_get_sset_count(struct net_device *netdev, int stringset)
285{ 303{
286 switch (stringset) { 304 switch (stringset) {
305 case ETH_SS_TEST:
306 return ETHTOOL_TESTS_NUM;
287 case ETH_SS_STATS: 307 case ETH_SS_STATS:
288 return ETHTOOL_STATS_NUM; 308 return ETHTOOL_STATS_NUM;
289 default: 309 default:
@@ -442,6 +462,67 @@ be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
442} 462}
443 463
444static int 464static int
465be_test_ddr_dma(struct be_adapter *adapter)
466{
467 int ret, i;
468 struct be_dma_mem ddrdma_cmd;
469 u64 pattern[2] = {0x5a5a5a5a5a5a5a5a, 0xa5a5a5a5a5a5a5a5};
470
471 ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);
472 ddrdma_cmd.va = pci_alloc_consistent(adapter->pdev, ddrdma_cmd.size,
473 &ddrdma_cmd.dma);
474 if (!ddrdma_cmd.va) {
475 dev_err(&adapter->pdev->dev, "Memory allocation failure \n");
476 return -ENOMEM;
477 }
478
479 for (i = 0; i < 2; i++) {
480 ret = be_cmd_ddr_dma_test(adapter, pattern[i],
481 4096, &ddrdma_cmd);
482 if (ret != 0)
483 goto err;
484 }
485
486err:
487 pci_free_consistent(adapter->pdev, ddrdma_cmd.size,
488 ddrdma_cmd.va, ddrdma_cmd.dma);
489 return ret;
490}
491
492static void
493be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
494{
495 struct be_adapter *adapter = netdev_priv(netdev);
496
497 memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM);
498
499 if (test->flags & ETH_TEST_FL_OFFLINE) {
500 data[0] = be_cmd_loopback_test(adapter, adapter->port_num,
501 BE_MAC_LOOPBACK, 1500,
502 2, 0xabc);
503 if (data[0] != 0)
504 test->flags |= ETH_TEST_FL_FAILED;
505
506 data[1] = be_cmd_loopback_test(adapter, adapter->port_num,
507 BE_PHY_LOOPBACK, 1500,
508 2, 0xabc);
509 if (data[1] != 0)
510 test->flags |= ETH_TEST_FL_FAILED;
511
512 data[2] = be_cmd_loopback_test(adapter, adapter->port_num,
513 BE_ONE_PORT_EXT_LOOPBACK,
514 1500, 2, 0xabc);
515 if (data[2] != 0)
516 test->flags |= ETH_TEST_FL_FAILED;
517
518 data[3] = be_test_ddr_dma(adapter);
519 if (data[3] != 0)
520 test->flags |= ETH_TEST_FL_FAILED;
521 }
522
523}
524
525static int
445be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) 526be_do_flash(struct net_device *netdev, struct ethtool_flash *efl)
446{ 527{
447 struct be_adapter *adapter = netdev_priv(netdev); 528 struct be_adapter *adapter = netdev_priv(netdev);
@@ -479,4 +560,5 @@ const struct ethtool_ops be_ethtool_ops = {
479 .get_sset_count = be_get_sset_count, 560 .get_sset_count = be_get_sset_count,
480 .get_ethtool_stats = be_get_ethtool_stats, 561 .get_ethtool_stats = be_get_ethtool_stats,
481 .flash_device = be_do_flash, 562 .flash_device = be_do_flash,
563 .self_test = be_self_test,
482}; 564};