Skip to content

Commit 582a1db

Browse files
committed
Merge branch 'qed-selftests'
Sudarsana Reddy Kalluru says: ==================== qed/qede: ethtool selftests support. This series adds the driver support for following selftests: 1. Register test 2. Memory test 3. Clock test 4. Interrupt test 5. Internal loopback test Patch (1) adds the qed driver infrastructure for selftests. Patches (2) and (3) add qede driver support for ethtool selftests. Please consider applying this series to "net-next". ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 158bc06 + 16f46bf commit 582a1db

File tree

13 files changed

+598
-6
lines changed

13 files changed

+598
-6
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
obj-$(CONFIG_QED) := qed.o
22

33
qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o qed_init_ops.o \
4-
qed_int.o qed_main.o qed_mcp.o qed_sp_commands.o qed_spq.o qed_l2.o
4+
qed_int.o qed_main.o qed_mcp.o qed_sp_commands.o qed_spq.o qed_l2.o \
5+
qed_selftest.o

drivers/net/ethernet/qlogic/qed/qed_hsi.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3857,6 +3857,7 @@ struct public_drv_mb {
38573857
#define DRV_MSG_CODE_PHY_CORE_WRITE 0x000e0000
38583858
#define DRV_MSG_CODE_SET_VERSION 0x000f0000
38593859

3860+
#define DRV_MSG_CODE_BIST_TEST 0x001e0000
38603861
#define DRV_MSG_CODE_SET_LED_MODE 0x00200000
38613862

38623863
#define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff
@@ -3914,6 +3915,18 @@ struct public_drv_mb {
39143915
#define DRV_MB_PARAM_SET_LED_MODE_ON 0x1
39153916
#define DRV_MB_PARAM_SET_LED_MODE_OFF 0x2
39163917

3918+
#define DRV_MB_PARAM_BIST_UNKNOWN_TEST 0
3919+
#define DRV_MB_PARAM_BIST_REGISTER_TEST 1
3920+
#define DRV_MB_PARAM_BIST_CLOCK_TEST 2
3921+
3922+
#define DRV_MB_PARAM_BIST_RC_UNKNOWN 0
3923+
#define DRV_MB_PARAM_BIST_RC_PASSED 1
3924+
#define DRV_MB_PARAM_BIST_RC_FAILED 2
3925+
#define DRV_MB_PARAM_BIST_RC_INVALID_PARAMETER 3
3926+
3927+
#define DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT 0
3928+
#define DRV_MB_PARAM_BIST_TEST_INDEX_MASK 0x000000FF
3929+
39173930
u32 fw_mb_header;
39183931
#define FW_MSG_CODE_MASK 0xffff0000
39193932
#define FW_MSG_CODE_DRV_LOAD_ENGINE 0x10100000

drivers/net/ethernet/qlogic/qed/qed_main.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "qed_dev_api.h"
2929
#include "qed_mcp.h"
3030
#include "qed_hw.h"
31+
#include "qed_selftest.h"
3132

3233
static char version[] =
3334
"QLogic FastLinQ 4xxxx Core Module qed " DRV_MODULE_VERSION "\n";
@@ -976,6 +977,25 @@ static int qed_set_link(struct qed_dev *cdev,
976977
else
977978
link_params->pause.forced_tx = false;
978979
}
980+
if (params->override_flags & QED_LINK_OVERRIDE_LOOPBACK_MODE) {
981+
switch (params->loopback_mode) {
982+
case QED_LINK_LOOPBACK_INT_PHY:
983+
link_params->loopback_mode = PMM_LOOPBACK_INT_PHY;
984+
break;
985+
case QED_LINK_LOOPBACK_EXT_PHY:
986+
link_params->loopback_mode = PMM_LOOPBACK_EXT_PHY;
987+
break;
988+
case QED_LINK_LOOPBACK_EXT:
989+
link_params->loopback_mode = PMM_LOOPBACK_EXT;
990+
break;
991+
case QED_LINK_LOOPBACK_MAC:
992+
link_params->loopback_mode = PMM_LOOPBACK_MAC;
993+
break;
994+
default:
995+
link_params->loopback_mode = PMM_LOOPBACK_NONE;
996+
break;
997+
}
998+
}
979999

9801000
rc = qed_mcp_set_link(hwfn, ptt, params->link_up);
9811001

@@ -1182,7 +1202,15 @@ static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode)
11821202
return status;
11831203
}
11841204

1205+
struct qed_selftest_ops qed_selftest_ops_pass = {
1206+
.selftest_memory = &qed_selftest_memory,
1207+
.selftest_interrupt = &qed_selftest_interrupt,
1208+
.selftest_register = &qed_selftest_register,
1209+
.selftest_clock = &qed_selftest_clock,
1210+
};
1211+
11851212
const struct qed_common_ops qed_common_ops_pass = {
1213+
.selftest = &qed_selftest_ops_pass,
11861214
.probe = &qed_probe,
11871215
.remove = &qed_remove,
11881216
.set_power_state = &qed_set_power_state,

drivers/net/ethernet/qlogic/qed/qed_mcp.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,3 +1017,45 @@ int qed_mcp_set_led(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
10171017

10181018
return rc;
10191019
}
1020+
1021+
int qed_mcp_bist_register_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
1022+
{
1023+
u32 drv_mb_param = 0, rsp, param;
1024+
int rc = 0;
1025+
1026+
drv_mb_param = (DRV_MB_PARAM_BIST_REGISTER_TEST <<
1027+
DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT);
1028+
1029+
rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
1030+
drv_mb_param, &rsp, &param);
1031+
1032+
if (rc)
1033+
return rc;
1034+
1035+
if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) ||
1036+
(param != DRV_MB_PARAM_BIST_RC_PASSED))
1037+
rc = -EAGAIN;
1038+
1039+
return rc;
1040+
}
1041+
1042+
int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
1043+
{
1044+
u32 drv_mb_param, rsp, param;
1045+
int rc = 0;
1046+
1047+
drv_mb_param = (DRV_MB_PARAM_BIST_CLOCK_TEST <<
1048+
DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT);
1049+
1050+
rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BIST_TEST,
1051+
drv_mb_param, &rsp, &param);
1052+
1053+
if (rc)
1054+
return rc;
1055+
1056+
if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK) ||
1057+
(param != DRV_MB_PARAM_BIST_RC_PASSED))
1058+
rc = -EAGAIN;
1059+
1060+
return rc;
1061+
}

drivers/net/ethernet/qlogic/qed/qed_mcp.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,28 @@ int qed_mcp_set_led(struct qed_hwfn *p_hwfn,
245245
struct qed_ptt *p_ptt,
246246
enum qed_led_mode mode);
247247

248+
/**
249+
* @brief Bist register test
250+
*
251+
* @param p_hwfn - hw function
252+
* @param p_ptt - PTT required for register access
253+
*
254+
* @return int - 0 - operation was successful.
255+
*/
256+
int qed_mcp_bist_register_test(struct qed_hwfn *p_hwfn,
257+
struct qed_ptt *p_ptt);
258+
259+
/**
260+
* @brief Bist clock test
261+
*
262+
* @param p_hwfn - hw function
263+
* @param p_ptt - PTT required for register access
264+
*
265+
* @return int - 0 - operation was successful.
266+
*/
267+
int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn,
268+
struct qed_ptt *p_ptt);
269+
248270
/* Using hwfn number (and not pf_num) is required since in CMT mode,
249271
* same pf_num may be used by two different hwfn
250272
* TODO - this shouldn't really be in .h file, but until all fields
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include "qed.h"
2+
#include "qed_dev_api.h"
3+
#include "qed_mcp.h"
4+
#include "qed_sp.h"
5+
6+
int qed_selftest_memory(struct qed_dev *cdev)
7+
{
8+
int rc = 0, i;
9+
10+
for_each_hwfn(cdev, i) {
11+
rc = qed_sp_heartbeat_ramrod(&cdev->hwfns[i]);
12+
if (rc)
13+
return rc;
14+
}
15+
16+
return rc;
17+
}
18+
19+
int qed_selftest_interrupt(struct qed_dev *cdev)
20+
{
21+
int rc = 0, i;
22+
23+
for_each_hwfn(cdev, i) {
24+
rc = qed_sp_heartbeat_ramrod(&cdev->hwfns[i]);
25+
if (rc)
26+
return rc;
27+
}
28+
29+
return rc;
30+
}
31+
32+
int qed_selftest_register(struct qed_dev *cdev)
33+
{
34+
struct qed_hwfn *p_hwfn;
35+
struct qed_ptt *p_ptt;
36+
int rc = 0, i;
37+
38+
/* although performed by MCP, this test is per engine */
39+
for_each_hwfn(cdev, i) {
40+
p_hwfn = &cdev->hwfns[i];
41+
p_ptt = qed_ptt_acquire(p_hwfn);
42+
if (!p_ptt) {
43+
DP_ERR(p_hwfn, "failed to acquire ptt\n");
44+
return -EBUSY;
45+
}
46+
rc = qed_mcp_bist_register_test(p_hwfn, p_ptt);
47+
qed_ptt_release(p_hwfn, p_ptt);
48+
if (rc)
49+
break;
50+
}
51+
52+
return rc;
53+
}
54+
55+
int qed_selftest_clock(struct qed_dev *cdev)
56+
{
57+
struct qed_hwfn *p_hwfn;
58+
struct qed_ptt *p_ptt;
59+
int rc = 0, i;
60+
61+
/* although performed by MCP, this test is per engine */
62+
for_each_hwfn(cdev, i) {
63+
p_hwfn = &cdev->hwfns[i];
64+
p_ptt = qed_ptt_acquire(p_hwfn);
65+
if (!p_ptt) {
66+
DP_ERR(p_hwfn, "failed to acquire ptt\n");
67+
return -EBUSY;
68+
}
69+
rc = qed_mcp_bist_clock_test(p_hwfn, p_ptt);
70+
qed_ptt_release(p_hwfn, p_ptt);
71+
if (rc)
72+
break;
73+
}
74+
75+
return rc;
76+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#ifndef _QED_SELFTEST_API_H
2+
#define _QED_SELFTEST_API_H
3+
#include <linux/types.h>
4+
5+
/**
6+
* @brief qed_selftest_memory - Perform memory test
7+
*
8+
* @param cdev
9+
*
10+
* @return int
11+
*/
12+
int qed_selftest_memory(struct qed_dev *cdev);
13+
14+
/**
15+
* @brief qed_selftest_interrupt - Perform interrupt test
16+
*
17+
* @param cdev
18+
*
19+
* @return int
20+
*/
21+
int qed_selftest_interrupt(struct qed_dev *cdev);
22+
23+
/**
24+
* @brief qed_selftest_register - Perform register test
25+
*
26+
* @param cdev
27+
*
28+
* @return int
29+
*/
30+
int qed_selftest_register(struct qed_dev *cdev);
31+
32+
/**
33+
* @brief qed_selftest_clock - Perform clock test
34+
*
35+
* @param cdev
36+
*
37+
* @return int
38+
*/
39+
int qed_selftest_clock(struct qed_dev *cdev);
40+
#endif

drivers/net/ethernet/qlogic/qed/qed_sp.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,4 +369,14 @@ int qed_sp_pf_update_tunn_cfg(struct qed_hwfn *p_hwfn,
369369
struct qed_tunn_update_params *p_tunn,
370370
enum spq_mode comp_mode,
371371
struct qed_spq_comp_cb *p_comp_data);
372+
/**
373+
* @brief qed_sp_heartbeat_ramrod - Send empty Ramrod
374+
*
375+
* @param p_hwfn
376+
*
377+
* @return int
378+
*/
379+
380+
int qed_sp_heartbeat_ramrod(struct qed_hwfn *p_hwfn);
381+
372382
#endif

drivers/net/ethernet/qlogic/qed/qed_sp_commands.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,3 +428,24 @@ int qed_sp_pf_stop(struct qed_hwfn *p_hwfn)
428428

429429
return qed_spq_post(p_hwfn, p_ent, NULL);
430430
}
431+
432+
int qed_sp_heartbeat_ramrod(struct qed_hwfn *p_hwfn)
433+
{
434+
struct qed_spq_entry *p_ent = NULL;
435+
struct qed_sp_init_data init_data;
436+
int rc;
437+
438+
/* Get SPQ entry */
439+
memset(&init_data, 0, sizeof(init_data));
440+
init_data.cid = qed_spq_get_cid(p_hwfn);
441+
init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
442+
init_data.comp_mode = QED_SPQ_MODE_EBLOCK;
443+
444+
rc = qed_sp_init_request(p_hwfn, &p_ent,
445+
COMMON_RAMROD_EMPTY, PROTOCOLID_COMMON,
446+
&init_data);
447+
if (rc)
448+
return rc;
449+
450+
return qed_spq_post(p_hwfn, p_ent, NULL);
451+
}

drivers/net/ethernet/qlogic/qede/qede.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,10 @@ void qede_reload(struct qede_dev *edev,
308308
union qede_reload_args *args);
309309
int qede_change_mtu(struct net_device *dev, int new_mtu);
310310
void qede_fill_by_demand_stats(struct qede_dev *edev);
311+
bool qede_has_rx_work(struct qede_rx_queue *rxq);
312+
int qede_txq_has_work(struct qede_tx_queue *txq);
313+
void qede_recycle_rx_bd_ring(struct qede_rx_queue *rxq, struct qede_dev *edev,
314+
u8 count);
311315

312316
#define RX_RING_SIZE_POW 13
313317
#define RX_RING_SIZE ((u16)BIT(RX_RING_SIZE_POW))

0 commit comments

Comments
 (0)