diff mbox series

[v4] igc: add support to interrupt, eeprom, registers and link self-tests

Message ID 20200405121604.36654-1-vitaly.lifshits@intel.com
State Superseded
Delegated to: Jeff Kirsher
Headers show
Series [v4] igc: add support to interrupt, eeprom, registers and link self-tests | expand

Commit Message

Vitaly Lifshits April 5, 2020, 12:16 p.m. UTC
Introduced igc_diag.c and igc_diag.h, these files have the
diagnostics functionality of igc driver. For the time being
these files are being used by ethtool self-test callbacks.
Which mean that interrupt, eeprom, registers and link self-tests for
ethtool were implemented.

Signed-off-by: Vitaly Lifshits <vitaly.lifshits@intel.com>
Reported-by: kbuild test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
---
v2: Fix return 0/1 to boolean value in igc_reg_test function
v3: Address community comments
v4: Fix interrupt test and address community comments
---
 drivers/net/ethernet/intel/igc/Makefile      |   2 +-
 drivers/net/ethernet/intel/igc/igc.h         |   4 +
 drivers/net/ethernet/intel/igc/igc_diag.c    | 336 +++++++++++++++++++++++++++
 drivers/net/ethernet/intel/igc/igc_diag.h    |  37 +++
 drivers/net/ethernet/intel/igc/igc_ethtool.c |  63 +++++
 drivers/net/ethernet/intel/igc/igc_main.c    |   4 +-
 drivers/net/ethernet/intel/igc/igc_regs.h    |   2 +
 7 files changed, 445 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/ethernet/intel/igc/igc_diag.c
 create mode 100644 drivers/net/ethernet/intel/igc/igc_diag.h

Comments

Andre Guedes April 9, 2020, 5:51 p.m. UTC | #1
> Introduced igc_diag.c and igc_diag.h, these files have the
> diagnostics functionality of igc driver. For the time being
> these files are being used by ethtool self-test callbacks.
> Which mean that interrupt, eeprom, registers and link self-tests for
> ethtool were implemented.
> 
> Signed-off-by: Vitaly Lifshits <vitaly.lifshits@intel.com>
> Reported-by: kbuild test robot <lkp@intel.com>
> Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

Acked-by: Andre Guedes <andre.guedes@intel.com>
Brown, Aaron F May 1, 2020, 7:18 p.m. UTC | #2
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of Vitaly
> Lifshits
> Sent: Sunday, April 5, 2020 5:16 AM
> To: intel-wired-lan@osuosl.org
> Subject: [Intel-wired-lan] [PATCH v4] igc: add support to interrupt, eeprom,
> registers and link self-tests
> 
> Introduced igc_diag.c and igc_diag.h, these files have the
> diagnostics functionality of igc driver. For the time being
> these files are being used by ethtool self-test callbacks.
> Which mean that interrupt, eeprom, registers and link self-tests for
> ethtool were implemented.
> 
> Signed-off-by: Vitaly Lifshits <vitaly.lifshits@intel.com>
> Reported-by: kbuild test robot <lkp@intel.com>
> Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> ---
> v2: Fix return 0/1 to boolean value in igc_reg_test function
> v3: Address community comments
> v4: Fix interrupt test and address community comments
> ---
>  drivers/net/ethernet/intel/igc/Makefile      |   2 +-
>  drivers/net/ethernet/intel/igc/igc.h         |   4 +
>  drivers/net/ethernet/intel/igc/igc_diag.c    | 336
> +++++++++++++++++++++++++++
>  drivers/net/ethernet/intel/igc/igc_diag.h    |  37 +++
>  drivers/net/ethernet/intel/igc/igc_ethtool.c |  63 +++++
>  drivers/net/ethernet/intel/igc/igc_main.c    |   4 +-
>  drivers/net/ethernet/intel/igc/igc_regs.h    |   2 +
>  7 files changed, 445 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/net/ethernet/intel/igc/igc_diag.c
>  create mode 100644 drivers/net/ethernet/intel/igc/igc_diag.h
> 

This does enable ethtool diags tests to run and at first it looks fine and I was about to give my Tested-by: to when a "watchdog: BUG: soft lockup  - CPU#7 stuck" leading to a call trace popped up on one of my systems that had been running other tests for several days before running a last round of diags...  And then on it showed up on the other system I had been doing most the diags on...  

When it appears the system is still up and the trace gets dumped to /var/log/messages but the system is not responsive to the console or network connections.  The trace repeats every 30 seconds or so.

It's repeatable but generally takes hundreds of iterations to show up.  The soonest I've seen it appear (after creating an ethtool diag / print iteration / repeat script) was around 50 iterations.  The second soonest I counted was 730 iterations and an my last try int took 1713.  It can take hours to appear with nothing more than an endless `ethtool -t $iface` loop, but not days. 

Here's a trace capture (this shows igb and e1000e drivers loaded, but the issue triggers with just igc loaded as well.)
-----------------------------------------------------------------------
May  1 06:36:27 u1322 kernel: igc 0000:01:00.0 eth1: Offline testing starting
May  1 06:36:32 u1322 kernel: igc 0000:01:00.0 eth1: Register testing starting
May  1 06:36:32 u1322 kernel: igc 0000:01:00.0 eth1: EEPROM testing starting
May  1 06:36:32 u1322 kernel: igc 0000:01:00.0 eth1: interrupt testing starting
May  1 06:36:32 u1322 kernel: igc 0000:01:00.0 eth1: testing shared interrupt
May  1 06:37:00 u1322 kernel: watchdog: BUG: soft lockup - CPU#7 stuck for 23s! [ethtool:9111]
May  1 06:37:00 u1322 kernel: Modules linked in: igb igc e1000e rfcomm xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defra
g_ipv4 ipt_REJECT nf_reject_ipv4 nft_counter nft_compat nf_tables nfnetlink tun stp llc cmac bnep iTCO_wdt iTCO_vendor_s
upport wmi_bmof intel_wmi_thunderbolt mxm_wmi x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm snd_hda_codec
_hdmi snd_hda_codec_realtek snd_hda_codec_generic ledtrig_audio btusb irqbypass btrtl snd_hda_intel btbcm snd_intel_dspc
fg btintel snd_hda_codec bluetooth snd_hwdep snd_hda_core snd_seq crct10dif_pclmul snd_seq_device crc32_pclmul snd_pcm g
hash_clmulni_intel joydev pl2303 intel_cstate snd_timer intel_uncore snd ecdh_generic mei_me ecc soundcore pcspkr mei i2
c_i801 intel_rapl_perf rfkill sg wmi intel_pmc_core acpi_pad nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables xfs l
ibcrc32c sr_mod sd_mod cdrom t10_pi i915 intel_gtt drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops cec drm
ahci libahci libata crc32c_intel dca i2c_algo_bit video
May  1 06:37:00 u1322 kernel: [last unloaded: bridge]
May  1 06:37:00 u1322 kernel: CPU: 7 PID: 9111 Comm: ethtool Not tainted 5.7.0-rc2_next-queue_dev-queue_c097661-00758-gc
097661edb2b #31
May  1 06:37:00 u1322 kernel: Hardware name: Gigabyte Technology Co., Ltd. Z370 AORUS Gaming 5/Z370 AORUS Gaming 5-CF, B
IOS F6 04/03/2018
May  1 06:37:00 u1322 kernel: RIP: 0010:__do_softirq+0x76/0x2ec
May  1 06:37:00 u1322 kernel: Code: 81 05 b2 7e e1 5d 00 01 00 00 c7 44 24 20 0a 00 00 00 44 89 74 24 04 48 c7 c0 40 b5
02 00 65 66 c7 00 00 00 fb b8 ff ff ff ff <48> c7 c6 00 51 a0 a2 0f bc 44 24 04 83 c0 01 49 89 f7 89 44 24 08
May  1 06:37:00 u1322 kernel: RSP: 0018:ffffaed900254f70 EFLAGS: 00000286 ORIG_RAX: ffffffffffffff13
May  1 06:37:00 u1322 kernel: RAX: 00000000ffffffff RBX: ffff96bb7e3d8640 RCX: 000000000000001f
May  1 06:37:00 u1322 kernel: RDX: 0000000000000043 RSI: 000000002819aad9 RDI: fffffffa31c219af
May  1 06:37:00 u1322 kernel: RBP: 0000000000000000 R08: 0000000000000002 R09: 000000000002b5c0
May  1 06:37:00 u1322 kernel: R10: 000167b91c1d8b72 R11: 000070ac2bd6bc76 R12: 0000000000000000
May  1 06:37:00 u1322 kernel: R13: 0000000000000000 R14: 0000000000000282 R15: 0000000000000000
May  1 06:37:00 u1322 kernel: FS:  00007ff4033ab740(0000) GS:ffff96bb7e3c0000(0000) knlGS:0000000000000000
May  1 06:37:00 u1322 kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
May  1 06:37:00 u1322 kernel: CR2: 00007fde63363000 CR3: 0000000fe1f1c004 CR4: 00000000003606e0
May  1 06:37:00 u1322 kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
May  1 06:37:00 u1322 kernel: DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
May  1 06:37:00 u1322 kernel: Call Trace:
May  1 06:37:00 u1322 kernel: <IRQ>
May  1 06:37:00 u1322 kernel: ? hrtimer_interrupt+0x12e/0x220
May  1 06:37:00 u1322 kernel: ? hrtimer_interrupt+0x12e/0x220
May  1 06:37:00 u1322 kernel: irq_exit+0xe3/0xf0
May  1 06:37:00 u1322 kernel: smp_apic_timer_interrupt+0x74/0x130
May  1 06:37:00 u1322 kernel: apic_timer_interrupt+0xf/0x20
May  1 06:37:00 u1322 kernel: </IRQ>
May  1 06:37:00 u1322 kernel: RIP: 0010:igc_rd32+0x16/0x80 [igc]
May  1 06:37:00 u1322 kernel: Code: e1 31 c0 c3 b8 fd ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 41 55 89
f0 41 54 55 53 48 8b 57 08 48 01 d0 8b 18 <83> fb ff 74 09 89 d8 5b 5d 41 5c 41 5d c3 85 f6 74 07 8b 02 83 f8
May  1 06:37:00 u1322 kernel: RSP: 0018:ffffaed906a57c48 EFLAGS: 00000282 ORIG_RAX: ffffffffffffff13
May  1 06:37:00 u1322 kernel: RAX: ffffaed901d00008 RBX: 0000000040380681 RCX: 0000000000000000
May  1 06:37:00 u1322 kernel: RDX: ffffaed901d00000 RSI: 0000000000000008 RDI: ffff96ac87278ae0
May  1 06:37:00 u1322 kernel: RBP: 0000000000000001 R08: 0000000000000010 R09: 000000000000fe6d
May  1 06:37:00 u1322 kernel: R10: 000000000000fe6d R11: 000070ac2bc77a36 R12: ffff96ac87278ae0
May  1 06:37:00 u1322 kernel: R13: ffff96bb71f30410 R14: 0000000000000001 R15: ffff96ac87278880
May  1 06:37:00 u1322 kernel: ? usleep_range+0x5c/0x80
May  1 06:37:00 u1322 kernel: igc_intr_test.cold.2+0x11d/0x279 [igc]
May  1 06:37:00 u1322 kernel: igc_ethtool_diag_test+0xe4/0x166 [igc]
May  1 06:37:00 u1322 kernel: dev_ethtool+0x1049/0x2a30
May  1 06:37:00 u1322 kernel: ? inet_ioctl+0x187/0x1d0
May  1 06:37:00 u1322 kernel: ? netdev_run_todo+0x5e/0x290
May  1 06:37:00 u1322 kernel: dev_ioctl+0xb5/0x550
May  1 06:37:00 u1322 kernel: sock_do_ioctl+0xa0/0x140
May  1 06:37:00 u1322 kernel: sock_ioctl+0x22a/0x380
May  1 06:37:00 u1322 kernel: ksys_ioctl+0x86/0xc0
May  1 06:37:00 u1322 kernel: __x64_sys_ioctl+0x16/0x20
May  1 06:37:00 u1322 kernel: do_syscall_64+0x55/0x1d0
May  1 06:37:00 u1322 kernel: entry_SYSCALL_64_after_hwframe+0x44/0xa9
May  1 06:37:00 u1322 kernel: RIP: 0033:0x7ff402b4bb2b
May  1 06:37:00 u1322 kernel: Code: 0f 1e fa 48 8b 05 5d a3 2c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 0f 1f
44 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 2d a3 2c 00 f7 d8 64 89 01 48
May  1 06:37:00 u1322 kernel: RSP: 002b:00007ffd006b7ef8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010May  1 06:37:00 u1322 kernel: ? hrtimer_interrupt+0x12e/0x220
May  1 06:37:00 u1322 kernel: irq_exit+0xe3/0xf0
May  1 06:37:00 u1322 kernel: smp_apic_timer_interrupt+0x74/0x130
May  1 06:37:00 u1322 kernel: apic_timer_interrupt+0xf/0x20
May  1 06:37:00 u1322 kernel: </IRQ>
May  1 06:37:00 u1322 kernel: RIP: 0010:igc_rd32+0x16/0x80 [igc]
May  1 06:37:00 u1322 kernel: Code: e1 31 c0 c3 b8 fd ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 41 55 89
f0 41 54 55 53 48 8b 57 08 48 01 d0 8b 18 <83> fb ff 74 09 89 d8 5b 5d 41 5c 41 5d c3 85 f6 74 07 8b 02 83 f8
May  1 06:37:00 u1322 kernel: RSP: 0018:ffffaed906a57c48 EFLAGS: 00000282 ORIG_RAX: ffffffffffffff13
May  1 06:37:00 u1322 kernel: RAX: ffffaed901d00008 RBX: 0000000040380681 RCX: 0000000000000000
May  1 06:37:00 u1322 kernel: RDX: ffffaed901d00000 RSI: 0000000000000008 RDI: ffff96ac87278ae0
May  1 06:37:00 u1322 kernel: RBP: 0000000000000001 R08: 0000000000000010 R09: 000000000000fe6d
May  1 06:37:00 u1322 kernel: R10: 000000000000fe6d R11: 000070ac2bc77a36 R12: ffff96ac87278ae0
May  1 06:37:00 u1322 kernel: R13: ffff96bb71f30410 R14: 0000000000000001 R15: ffff96ac87278880
May  1 06:37:00 u1322 kernel: ? usleep_range+0x5c/0x80
May  1 06:37:00 u1322 kernel: igc_intr_test.cold.2+0x11d/0x279 [igc]
May  1 06:37:00 u1322 kernel: igc_ethtool_diag_test+0xe4/0x166 [igc]
May  1 06:37:00 u1322 kernel: dev_ethtool+0x1049/0x2a30
May  1 06:37:00 u1322 kernel: ? inet_ioctl+0x187/0x1d0
May  1 06:37:00 u1322 kernel: ? netdev_run_todo+0x5e/0x290
May  1 06:37:00 u1322 kernel: dev_ioctl+0xb5/0x550
May  1 06:37:00 u1322 kernel: sock_do_ioctl+0xa0/0x140
May  1 06:37:00 u1322 kernel: sock_ioctl+0x22a/0x380
May  1 06:37:00 u1322 kernel: ksys_ioctl+0x86/0xc0
May  1 06:37:00 u1322 kernel: __x64_sys_ioctl+0x16/0x20
May  1 06:37:00 u1322 kernel: do_syscall_64+0x55/0x1d0
May  1 06:37:00 u1322 kernel: entry_SYSCALL_64_after_hwframe+0x44/0xa9
May  1 06:37:00 u1322 kernel: RIP: 0033:0x7ff402b4bb2b
May  1 06:37:00 u1322 kernel: Code: 0f 1e fa 48 8b 05 5d a3 2c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 0f 1f
44 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 2d a3 2c 00 f7 d8 64 89 01 48
May  1 06:37:00 u1322 kernel: RSP: 002b:00007ffd006b7ef8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
May  1 06:37:00 u1322 kernel: RAX: ffffffffffffffda RBX: 0000000000a92320 RCX: 00007ff402b4bb2b
May  1 06:37:00 u1322 kernel: RDX: 00007ffd006b7f40 RSI: 0000000000008946 RDI: 0000000000000003
May  1 06:37:00 u1322 kernel: RBP: 0000000000a92260 R08: 0000000000a92320 R09: 0000000000000003
May  1 06:37:00 u1322 kernel: R10: fffffffffffff6e6 R11: 0000000000000246 R12: 00007ffd006b7f30
May  1 06:37:00 u1322 kernel: R13: 0000000000000038 R14: 0000000000000001 R15: 0000000000000000
May  1 06:37:28 u1322 kernel: watchdog: BUG: soft lockup - CPU#7 stuck for 23s! [ethtool:9111]
May  1 06:37:28 u1322 kernel: Modules linked in: igb igc e1000e rfcomm xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ipt_REJECT nf_reject_ipv4 nft_counter nft_compat nf_tables nfnetlink tun stp llc cmac bnep iTCO_wdt iTCO_vendor_support wmi_bmof intel_wmi_thunderbolt mxm_wmi x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic ledtrig_audio btusb irqbypass btrtl snd_hda_intel btbcm snd_intel_dspcfg btintel snd_hda_codec bluetooth snd_hwdep snd_hda_core snd_seq crct10dif_pclmul snd_seq_device crc32_pclmul snd_pcm ghash_clmulni_intel joydev pl2303 intel_cstate snd_timer intel_uncore snd ecdh_generic mei_me ecc soundcore pcspkr mei i2c_i801 intel_rapl_perf rfkill sg wmi intel_pmc_core acpi_pad nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables xfs libcrc32c sr_mod sd_mod cdrom t10_pi i915 intel_gtt drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops cec drm ahci libahci libata crc32c_int
 el dca i2c_algo_bit video
May  1 06:37:28 u1322 kernel: [last unloaded: bridge]
May  1 06:37:28 u1322 kernel: CPU: 7 PID: 9111 Comm: ethtool Tainted: G             L    5.7.0-rc2_next-queue_dev-queue_c097661-00758-gc097661edb2b #31
May  1 06:37:28 u1322 kernel: Hardware name: Gigabyte Technology Co., Ltd. Z370 AORUS Gaming 5/Z370 AORUS Gaming 5-CF, BIOS F6 04/03/2018
May  1 06:37:28 u1322 kernel: RIP: 0010:__do_softirq+0x76/0x2ec
May  1 06:37:28 u1322 kernel: Code: 81 05 b2 7e e1 5d 00 01 00 00 c7 44 24 20 0a 00 00 00 44 89 74 24 04 48 c7 c0 40 b5 02 00 65 66 c7 00 00 00 fb b8 ff ff ff ff <48> c7 c6 00 51 a0 a2 0f bc 44 24 04 83 c0 01 49 89 f7 89 44 24 08
May  1 06:37:28 u1322 kernel: RSP: 0018:ffffaed900254f70 EFLAGS: 00000286 ORIG_RAX: ffffffffffffff13
May  1 06:37:28 u1322 kernel: RAX: 00000000ffffffff RBX: ffff96bb7e3d8640 RCX: 000000000000001f
May  1 06:37:28 u1322 kernel: RDX: 0000000000000043 RSI: 000000002819aad9 RDI: fffffffa31c219af
May  1 06:37:28 u1322 kernel: RBP: 0000000000000000 R08: 0000000000000002 R09: 000000000002b5c0
May  1 06:37:28 u1322 kernel: R10: 000167b91c1d8b72 R11: 000070ac2bd6bc76 R12: 0000000000000000
May  1 06:37:28 u1322 kernel: R13: 0000000000000000 R14: 0000000000000282 R15: 0000000000000000
May  1 06:37:28 u1322 kernel: FS:  00007ff4033ab740(0000) GS:ffff96bb7e3c0000(0000) knlGS:0000000000000000
May  1 06:37:28 u1322 kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
May  1 06:37:28 u1322 kernel: CR2: 00007fde63363000 CR3: 0000000fe1f1c004 CR4: 00000000003606e0
May  1 06:37:28 u1322 kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
May  1 06:37:28 u1322 kernel: DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
May  1 06:37:28 u1322 kernel: Call Trace:
May  1 06:37:28 u1322 kernel: <IRQ>
May  1 06:37:28 u1322 kernel: ? hrtimer_interrupt+0x12e/0x220
May  1 06:37:28 u1322 kernel: irq_exit+0xe3/0xf0
May  1 06:37:28 u1322 kernel: smp_apic_timer_interrupt+0x74/0x130
May  1 06:37:28 u1322 kernel: apic_timer_interrupt+0xf/0x20
May  1 06:37:28 u1322 kernel: </IRQ>
May  1 06:37:28 u1322 kernel: RIP: 0010:igc_rd32+0x16/0x80 [igc]
May  1 06:37:28 u1322 kernel: Code: e1 31 c0 c3 b8 fd ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 41 55 89 f0 41 54 55 53 48 8b 57 08 48 01 d0 8b 18 <83> fb ff 74 09 89 d8 5b 5d 41 5c 41 5d c3 85 f6 74 07 8b 02 83 f8
May  1 06:37:28 u1322 kernel: RSP: 0018:ffffaed906a57c48 EFLAGS: 00000282 ORIG_RAX: ffffffffffffff13
May  1 06:37:28 u1322 kernel: RAX: ffffaed901d00008 RBX: 0000000040380681 RCX: 0000000000000000
May  1 06:37:28 u1322 kernel: RDX: ffffaed901d00000 RSI: 0000000000000008 RDI: ffff96ac87278ae0
May  1 06:37:28 u1322 kernel: RBP: 0000000000000001 R08: 0000000000000010 R09: 000000000000fe6d
May  1 06:37:28 u1322 kernel: R10: 000000000000fe6d R11: 000070ac2bc77a36 R12: ffff96ac87278ae0
May  1 06:37:28 u1322 kernel: R13: ffff96bb71f30410 R14: 0000000000000001 R15: ffff96ac87278880
May  1 06:37:28 u1322 kernel: ? usleep_range+0x5c/0x80
May  1 06:37:28 u1322 kernel: igc_intr_test.cold.2+0x11d/0x279 [igc]
May  1 06:37:28 u1322 kernel: igc_ethtool_diag_test+0xe4/0x166 [igc]
May  1 06:37:28 u1322 kernel: dev_ethtool+0x1049/0x2a30
May  1 06:37:28 u1322 kernel: ? inet_ioctl+0x187/0x1d0
May  1 06:37:28 u1322 kernel: ? netdev_run_todo+0x5e/0x290
May  1 06:37:28 u1322 kernel: dev_ioctl+0xb5/0x550
May  1 06:37:28 u1322 kernel: sock_do_ioctl+0xa0/0x140
May  1 06:37:28 u1322 kernel: sock_ioctl+0x22a/0x380
May  1 06:37:28 u1322 kernel: ksys_ioctl+0x86/0xc0
May  1 06:37:28 u1322 kernel: __x64_sys_ioctl+0x16/0x20
May  1 06:37:28 u1322 kernel: do_syscall_64+0x55/0x1d0
May  1 06:37:28 u1322 kernel: entry_SYSCALL_64_after_hwframe+0x44/0xa9
May  1 06:37:28 u1322 kernel: RIP: 0033:0x7ff402b4bb2b
May  1 06:37:28 u1322 kernel: Code: 0f 1e fa 48 8b 05 5d a3 2c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 2d a3 2c 00 f7 d8 64 89 01 48
May  1 06:37:28 u1322 kernel: RSP: 002b:00007ffd006b7ef8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
May  1 06:37:28 u1322 kernel: RAX: ffffffffffffffda RBX: 0000000000a92320 RCX: 00007ff402b4bb2b
May  1 06:37:28 u1322 kernel: RDX: 00007ffd006b7f40 RSI: 0000000000008946 RDI: 0000000000000003
May  1 06:37:28 u1322 kernel: RBP: 0000000000a92260 R08: 0000000000a92320 R09: 0000000000000003
May  1 06:37:28 u1322 kernel: R10: fffffffffffff6e6 R11: 0000000000000246 R12: 00007ffd006b7f30
May  1 06:37:28 u1322 kernel: R13: 0000000000000038 R14: 0000000000000001 R15: 0000000000000000
May  1 06:37:33 u1322 kernel: rcu: INFO: rcu_sched self-detected stall on CPU
May  1 06:37:33 u1322 kernel: rcu: #0117-....: (2 GPs behind) idle=4be/1/0x4000000000000004 softirq=180999/181000 fqs=14982
May  1 06:37:33 u1322 kernel: #011(t=60000 jiffies g=2095585 q=2857)
May  1 06:37:33 u1322 kernel: NMI backtrace for cpu 7
May  1 06:37:33 u1322 kernel: CPU: 7 PID: 9111 Comm: ethtool Tainted: G             L    5.7.0-rc2_next-queue_dev-queue_c097661-00758-gc097661edb2b #31
May  1 06:37:33 u1322 kernel: Hardware name: Gigabyte Technology Co., Ltd. Z370 AORUS Gaming 5/Z370 AORUS Gaming 5-CF, BIOS F6 04/03/2018
May  1 06:37:33 u1322 kernel: Call Trace:
May  1 06:37:33 u1322 kernel: <IRQ>
May  1 06:37:33 u1322 kernel: dump_stack+0x50/0x70
May  1 06:37:33 u1322 kernel: nmi_cpu_backtrace.cold.8+0x13/0x4f
May  1 06:37:33 u1322 kernel: ? lapic_can_unplug_cpu.cold.30+0x37/0x37
May  1 06:37:33 u1322 kernel: nmi_trigger_cpumask_backtrace+0xde/0xe0
May  1 06:37:33 u1322 kernel: rcu_dump_cpu_stacks+0xae/0xdc
May  1 06:37:33 u1322 kernel: rcu_sched_clock_irq.cold.87+0x10a/0x380
May  1 06:37:33 u1322 kernel: ? timekeeping_advance+0x371/0x5a0
May  1 06:37:33 u1322 kernel: ? tick_sched_do_timer+0x70/0x70
May  1 06:37:33 u1322 kernel: ? tick_sched_do_timer+0x70/0x70
May  1 06:37:33 u1322 kernel: update_process_times+0x24/0x50
May  1 06:37:33 u1322 kernel: tick_sched_handle+0x22/0x60
May  1 06:37:33 u1322 kernel: tick_sched_timer+0x37/0x70
May  1 06:37:33 u1322 kernel: __hrtimer_run_queues+0x100/0x280
May  1 06:37:33 u1322 kernel: hrtimer_interrupt+0x100/0x220
May  1 06:37:33 u1322 kernel: smp_apic_timer_interrupt+0x6a/0x130
May  1 06:37:33 u1322 kernel: apic_timer_interrupt+0xf/0x20
May  1 06:37:33 u1322 kernel: RIP: 0010:__do_softirq+0x76/0x2ec
May  1 06:37:33 u1322 kernel: Code: 81 05 b2 7e e1 5d 00 01 00 00 c7 44 24 20 0a 00 00 00 44 89 74 24 04 48 c7 c0 40 b5 02 00 65 66 c7 00 00 00 fb b8 ff ff ff ff <48> c7 c6 00 51 a0 a2 0f bc 44 24 04 83 c0 01 49 89 f7 89 44 24 08
May  1 06:37:33 u1322 kernel: RSP: 0018:ffffaed900254f70 EFLAGS: 00000286 ORIG_RAX: ffffffffffffff13
May  1 06:37:33 u1322 kernel: RAX: 00000000ffffffff RBX: ffff96bb7e3d8640 RCX: 000000000000001f
May  1 06:37:33 u1322 kernel: RDX: 0000000000000043 RSI: 000000002819aad9 RDI: fffffffa31c219af
May  1 06:37:33 u1322 kernel: RBP: 0000000000000000 R08: 0000000000000002 R09: 000000000002b5c0
May  1 06:37:33 u1322 kernel: R10: 000167b91c1d8b72 R11: 000070ac2bd6bc76 R12: 0000000000000000
May  1 06:37:33 u1322 kernel: R13: 0000000000000000 R14: 0000000000000282 R15: 0000000000000000
May  1 06:37:33 u1322 kernel: ? apic_timer_interrupt+0xa/0x20
May  1 06:37:33 u1322 kernel: ? hrtimer_interrupt+0x12e/0x220
May  1 06:37:33 u1322 kernel: irq_exit+0xe3/0xf0
May  1 06:37:33 u1322 kernel: smp_apic_timer_interrupt+0x74/0x130
May  1 06:37:33 u1322 kernel: apic_timer_interrupt+0xf/0x20
May  1 06:37:33 u1322 kernel: </IRQ>
May  1 06:37:33 u1322 kernel: RIP: 0010:igc_rd32+0x16/0x80 [igc]
May  1 06:37:33 u1322 kernel: Code: e1 31 c0 c3 b8 fd ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 41 55 89 f0 41 54 55 53 48 8b 57 08 48 01 d0 8b 18 <83> fb ff 74 09 89 d8 5b 5d 41 5c 41 5d c3 85 f6 74 07 8b 02 83 f8
May  1 06:37:33 u1322 kernel: RSP: 0018:ffffaed906a57c48 EFLAGS: 00000282 ORIG_RAX: ffffffffffffff13
May  1 06:37:33 u1322 kernel: RAX: ffffaed901d00008 RBX: 0000000040380681 RCX: 0000000000000000
May  1 06:37:33 u1322 kernel: RDX: ffffaed901d00000 RSI: 0000000000000008 RDI: ffff96ac87278ae0
May  1 06:37:33 u1322 kernel: RBP: 0000000000000001 R08: 0000000000000010 R09: 000000000000fe6d
May  1 06:37:33 u1322 kernel: R10: 000000000000fe6d R11: 000070ac2bc77a36 R12: ffff96ac87278ae0
May  1 06:37:33 u1322 kernel: R13: ffff96bb71f30410 R14: 0000000000000001 R15: ffff96ac87278880
May  1 06:37:33 u1322 kernel: ? usleep_range+0x5c/0x80
May  1 06:37:33 u1322 kernel: igc_intr_test.cold.2+0x11d/0x279 [igc]
May  1 06:37:33 u1322 kernel: igc_ethtool_diag_test+0xe4/0x166 [igc]
May  1 06:37:33 u1322 kernel: dev_ethtool+0x1049/0x2a30
May  1 06:37:33 u1322 kernel: ? inet_ioctl+0x187/0x1d0
May  1 06:37:33 u1322 kernel: ? netdev_run_todo+0x5e/0x290
May  1 06:37:33 u1322 kernel: dev_ioctl+0xb5/0x550
May  1 06:37:33 u1322 kernel: sock_do_ioctl+0xa0/0x140
May  1 06:37:33 u1322 kernel: sock_ioctl+0x22a/0x380
May  1 06:37:33 u1322 kernel: ksys_ioctl+0x86/0xc0
May  1 06:37:33 u1322 kernel: __x64_sys_ioctl+0x16/0x20
May  1 06:37:33 u1322 kernel: do_syscall_64+0x55/0x1d0
May  1 06:37:33 u1322 kernel: entry_SYSCALL_64_after_hwframe+0x44/0xa9
May  1 06:37:33 u1322 kernel: RIP: 0033:0x7ff402b4bb2b
May  1 06:37:33 u1322 kernel: Code: 0f 1e fa 48 8b 05 5d a3 2c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 2d a3 2c 00 f7 d8 64 89 01 48
May  1 06:37:33 u1322 kernel: RSP: 002b:00007ffd006b7ef8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
May  1 06:37:33 u1322 kernel: RAX: ffffffffffffffda RBX: 0000000000a92320 RCX: 00007ff402b4bb2b
May  1 06:37:33 u1322 kernel: RDX: 00007ffd006b7f40 RSI: 0000000000008946 RDI: 0000000000000003
May  1 06:37:33 u1322 kernel: RBP: 0000000000a92260 R08: 0000000000a92320 R09: 0000000000000003
May  1 06:37:33 u1322 kernel: R10: fffffffffffff6e6 R11: 0000000000000246 R12: 00007ffd006b7f30
May  1 06:37:33 u1322 kernel: R13: 0000000000000038 R14: 0000000000000001 R15: 0000000000000000
----
And it continues to occurs at roughly 30 second intervals until the system is rebooted.
Brown, Aaron F May 1, 2020, 9:25 p.m. UTC | #3
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of
> Vitaly Lifshits
> Sent: Sunday, April 5, 2020 5:16 AM
> To: intel-wired-lan@osuosl.org
> Subject: [Intel-wired-lan] [PATCH v4] igc: add support to interrupt, eeprom,
> registers and link self-tests
> 
> Introduced igc_diag.c and igc_diag.h, these files have the
> diagnostics functionality of igc driver. For the time being
> these files are being used by ethtool self-test callbacks.
> Which mean that interrupt, eeprom, registers and link self-tests for
> ethtool were implemented.
> 
> Signed-off-by: Vitaly Lifshits <vitaly.lifshits@intel.com>
> Reported-by: kbuild test robot <lkp@intel.com>
> Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> ---
> v2: Fix return 0/1 to boolean value in igc_reg_test function
> v3: Address community comments
> v4: Fix interrupt test and address community comments
> ---
>  drivers/net/ethernet/intel/igc/Makefile      |   2 +-
>  drivers/net/ethernet/intel/igc/igc.h         |   4 +
>  drivers/net/ethernet/intel/igc/igc_diag.c    | 336
> +++++++++++++++++++++++++++
>  drivers/net/ethernet/intel/igc/igc_diag.h    |  37 +++
>  drivers/net/ethernet/intel/igc/igc_ethtool.c |  63 +++++
>  drivers/net/ethernet/intel/igc/igc_main.c    |   4 +-
>  drivers/net/ethernet/intel/igc/igc_regs.h    |   2 +
>  7 files changed, 445 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/net/ethernet/intel/igc/igc_diag.c
>  create mode 100644 drivers/net/ethernet/intel/igc/igc_diag.h
> 

Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Brown, Aaron F May 1, 2020, 9:42 p.m. UTC | #4
> From: Brown, Aaron F
> Sent: Friday, May 1, 2020 2:26 PM
> To: Vitaly Lifshits <vitaly.lifshits@intel.com>; intel-wired-lan@osuosl.org
> Subject: RE: [Intel-wired-lan] [PATCH v4] igc: add support to interrupt,
> eeprom, registers and link self-tests
> 
> > From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of
> > Vitaly Lifshits
> > Sent: Sunday, April 5, 2020 5:16 AM
> > To: intel-wired-lan@osuosl.org
> > Subject: [Intel-wired-lan] [PATCH v4] igc: add support to interrupt, eeprom,
> > registers and link self-tests
> >
> > Introduced igc_diag.c and igc_diag.h, these files have the
> > diagnostics functionality of igc driver. For the time being
> > these files are being used by ethtool self-test callbacks.
> > Which mean that interrupt, eeprom, registers and link self-tests for
> > ethtool were implemented.
> >
> > Signed-off-by: Vitaly Lifshits <vitaly.lifshits@intel.com>
> > Reported-by: kbuild test robot <lkp@intel.com>
> > Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> > ---
> > v2: Fix return 0/1 to boolean value in igc_reg_test function
> > v3: Address community comments
> > v4: Fix interrupt test and address community comments
> > ---
> >  drivers/net/ethernet/intel/igc/Makefile      |   2 +-
> >  drivers/net/ethernet/intel/igc/igc.h         |   4 +
> >  drivers/net/ethernet/intel/igc/igc_diag.c    | 336
> > +++++++++++++++++++++++++++
> >  drivers/net/ethernet/intel/igc/igc_diag.h    |  37 +++
> >  drivers/net/ethernet/intel/igc/igc_ethtool.c |  63 +++++
> >  drivers/net/ethernet/intel/igc/igc_main.c    |   4 +-
> >  drivers/net/ethernet/intel/igc/igc_regs.h    |   2 +
> >  7 files changed, 445 insertions(+), 3 deletions(-)
> >  create mode 100644 drivers/net/ethernet/intel/igc/igc_diag.c
> >  create mode 100644 drivers/net/ethernet/intel/igc/igc_diag.h
> >
> 
> Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Sorry, I was intending the apply this to a different patch.  This is the patch that enables ethtool diags, which causes the call trace I sent out earlier today.
Kirsher, Jeffrey T May 1, 2020, 9:43 p.m. UTC | #5
> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of
> Brown, Aaron F
> Sent: Friday, May 1, 2020 14:42
> To: Lifshits, Vitaly <vitaly.lifshits@intel.com>; intel-wired-lan@osuosl.org
> Subject: Re: [Intel-wired-lan] [PATCH v4] igc: add support to interrupt, eeprom,
> registers and link self-tests
> 
> > From: Brown, Aaron F
> > Sent: Friday, May 1, 2020 2:26 PM
> > To: Vitaly Lifshits <vitaly.lifshits@intel.com>;
> > intel-wired-lan@osuosl.org
> > Subject: RE: [Intel-wired-lan] [PATCH v4] igc: add support to
> > interrupt, eeprom, registers and link self-tests
> >
> > > From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> > > Of Vitaly Lifshits
> > > Sent: Sunday, April 5, 2020 5:16 AM
> > > To: intel-wired-lan@osuosl.org
> > > Subject: [Intel-wired-lan] [PATCH v4] igc: add support to interrupt,
> > > eeprom, registers and link self-tests
> > >
> > > Introduced igc_diag.c and igc_diag.h, these files have the
> > > diagnostics functionality of igc driver. For the time being these
> > > files are being used by ethtool self-test callbacks.
> > > Which mean that interrupt, eeprom, registers and link self-tests for
> > > ethtool were implemented.
> > >
> > > Signed-off-by: Vitaly Lifshits <vitaly.lifshits@intel.com>
> > > Reported-by: kbuild test robot <lkp@intel.com>
> > > Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> > > ---
> > > v2: Fix return 0/1 to boolean value in igc_reg_test function
> > > v3: Address community comments
> > > v4: Fix interrupt test and address community comments
> > > ---
> > >  drivers/net/ethernet/intel/igc/Makefile      |   2 +-
> > >  drivers/net/ethernet/intel/igc/igc.h         |   4 +
> > >  drivers/net/ethernet/intel/igc/igc_diag.c    | 336
> > > +++++++++++++++++++++++++++
> > >  drivers/net/ethernet/intel/igc/igc_diag.h    |  37 +++
> > >  drivers/net/ethernet/intel/igc/igc_ethtool.c |  63 +++++
> > >  drivers/net/ethernet/intel/igc/igc_main.c    |   4 +-
> > >  drivers/net/ethernet/intel/igc/igc_regs.h    |   2 +
> > >  7 files changed, 445 insertions(+), 3 deletions(-)  create mode
> > > 100644 drivers/net/ethernet/intel/igc/igc_diag.c
> > >  create mode 100644 drivers/net/ethernet/intel/igc/igc_diag.h
> > >
> >
> > Tested-by: Aaron Brown <aaron.f.brown@intel.com>
> Sorry, I was intending the apply this to a different patch.  This is the patch that
> enables ethtool diags, which causes the call trace I sent out earlier today.

[Kirsher, Jeffrey T] 
I was just about to ask why the mixed messages...

> _______________________________________________
> Intel-wired-lan mailing list
> Intel-wired-lan@osuosl.org
> https://lists.osuosl.org/mailman/listinfo/intel-wired-lan
diff mbox series

Patch

diff --git a/drivers/net/ethernet/intel/igc/Makefile b/drivers/net/ethernet/intel/igc/Makefile
index 3652f211f351..1c3051db9085 100644
--- a/drivers/net/ethernet/intel/igc/Makefile
+++ b/drivers/net/ethernet/intel/igc/Makefile
@@ -8,4 +8,4 @@ 
 obj-$(CONFIG_IGC) += igc.o
 
 igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \
-igc_ethtool.o igc_ptp.o igc_dump.o igc_tsn.o
+igc_diag.o igc_ethtool.o igc_ptp.o igc_dump.o igc_tsn.o
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index 8098acef4316..6c18c74a68fb 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -198,6 +198,8 @@  struct igc_adapter {
 	unsigned long link_check_timeout;
 	struct igc_info ei;
 
+	u32 test_icr;
+
 	struct ptp_clock *ptp_clock;
 	struct ptp_clock_info ptp_caps;
 	struct work_struct ptp_tx_work;
@@ -215,6 +217,8 @@  struct igc_adapter {
 
 void igc_up(struct igc_adapter *adapter);
 void igc_down(struct igc_adapter *adapter);
+int igc_open(struct net_device *netdev);
+int igc_close(struct net_device *netdev);
 int igc_setup_tx_resources(struct igc_ring *ring);
 int igc_setup_rx_resources(struct igc_ring *ring);
 void igc_free_tx_resources(struct igc_ring *ring);
diff --git a/drivers/net/ethernet/intel/igc/igc_diag.c b/drivers/net/ethernet/intel/igc/igc_diag.c
new file mode 100644
index 000000000000..32675020a3d2
--- /dev/null
+++ b/drivers/net/ethernet/intel/igc/igc_diag.c
@@ -0,0 +1,336 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c)  2020 Intel Corporation */
+
+#include "igc.h"
+#include "igc_diag.h"
+
+struct igc_reg_test reg_test[] = {
+	{ IGC_FCAL,	1,	PATTERN_TEST,	0xFFFFFFFF,	0xFFFFFFFF },
+	{ IGC_FCAH,	1,	PATTERN_TEST,	0x0000FFFF,	0xFFFFFFFF },
+	{ IGC_FCT,	1,	PATTERN_TEST,	0x0000FFFF,	0xFFFFFFFF },
+	{ IGC_RDBAH(0), 4,	PATTERN_TEST,	0xFFFFFFFF,	0xFFFFFFFF },
+	{ IGC_RDBAL(0),	4,	PATTERN_TEST,	0xFFFFFF80,	0xFFFFFF80 },
+	{ IGC_RDLEN(0),	4,	PATTERN_TEST,	0x000FFF80,	0x000FFFFF },
+	{ IGC_RDT(0),	4,	PATTERN_TEST,	0x0000FFFF,	0x0000FFFF },
+	{ IGC_FCRTH,	1,	PATTERN_TEST,	0x0003FFF0,	0x0003FFF0 },
+	{ IGC_FCTTV,	1,	PATTERN_TEST,	0x0000FFFF,	0x0000FFFF },
+	{ IGC_TIPG,	1,	PATTERN_TEST,	0x3FFFFFFF,	0x3FFFFFFF },
+	{ IGC_TDBAH(0),	4,	PATTERN_TEST,	0xFFFFFFFF,     0xFFFFFFFF },
+	{ IGC_TDBAL(0),	4,	PATTERN_TEST,	0xFFFFFF80,     0xFFFFFF80 },
+	{ IGC_TDLEN(0),	4,	PATTERN_TEST,	0x000FFF80,     0x000FFFFF },
+	{ IGC_TDT(0),	4,	PATTERN_TEST,	0x0000FFFF,     0x0000FFFF },
+	{ IGC_RCTL,	1,	SET_READ_TEST,	0xFFFFFFFF,	0x00000000 },
+	{ IGC_RCTL,	1,	SET_READ_TEST,	0x04CFB2FE,	0x003FFFFB },
+	{ IGC_RCTL,	1,	SET_READ_TEST,	0x04CFB2FE,	0xFFFFFFFF },
+	{ IGC_TCTL,	1,	SET_READ_TEST,	0xFFFFFFFF,	0x00000000 },
+	{ IGC_RA,	16,	TABLE64_TEST_LO,
+						0xFFFFFFFF,	0xFFFFFFFF },
+	{ IGC_RA,	16,	TABLE64_TEST_HI,
+						0x900FFFFF,	0xFFFFFFFF },
+	{ IGC_MTA,	128,	TABLE32_TEST,
+						0xFFFFFFFF,	0xFFFFFFFF },
+	{ 0, 0, 0, 0}
+};
+
+static bool reg_pattern_test(struct igc_adapter *adapter, u64 *data, int reg,
+			     u32 mask, u32 write)
+{
+	struct igc_hw *hw = &adapter->hw;
+	u32 pat, val, before;
+	static const u32 test_pattern[] = {
+		0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF
+	};
+
+	for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
+		before = rd32(reg);
+		wr32(reg, test_pattern[pat] & write);
+		val = rd32(reg);
+		if (val != (test_pattern[pat] & write & mask)) {
+			netdev_err(adapter->netdev,
+				   "pattern test reg %04X failed: got 0x%08X expected 0x%08X",
+				   reg, val, test_pattern[pat] & write & mask);
+			*data = reg;
+			wr32(reg, before);
+			return false;
+		}
+		wr32(reg, before);
+	}
+	return true;
+}
+
+static bool reg_set_and_check(struct igc_adapter *adapter, u64 *data, int reg,
+			      u32 mask, u32 write)
+{
+	struct igc_hw *hw = &adapter->hw;
+	u32 val, before;
+
+	before = rd32(reg);
+	wr32(reg, write & mask);
+	val = rd32(reg);
+	if ((write & mask) != (val & mask)) {
+		netdev_err(adapter->netdev,
+			   "set/check reg %04X test failed: got 0x%08X expected 0x%08X",
+			   reg, (val & mask), (write & mask));
+		*data = reg;
+		wr32(reg, before);
+		return false;
+	}
+	wr32(reg, before);
+	return true;
+}
+
+bool igc_reg_test(struct igc_adapter *adapter, u64 *data)
+{
+	struct igc_reg_test *test = reg_test;
+	struct igc_hw *hw = &adapter->hw;
+	u32 value, before, after;
+	u32 i, toggle, b = false;
+
+	/* Because the status register is such a special case,
+	 * we handle it separately from the rest of the register
+	 * tests.  Some bits are read-only, some toggle, and some
+	 * are writeable.
+	 */
+	toggle = 0x6800D3;
+	before = rd32(IGC_STATUS);
+	value = before & toggle;
+	wr32(IGC_STATUS, toggle);
+	after = rd32(IGC_STATUS) & toggle;
+	if (value != after) {
+		netdev_err(adapter->netdev,
+			   "failed STATUS register test got: 0x%08X expected: 0x%08X",
+			   after, value);
+		*data = 1;
+		return false;
+	}
+	/* restore previous status */
+	wr32(IGC_STATUS, before);
+
+	/* Perform the remainder of the register test, looping through
+	 * the test table until we either fail or reach the null entry.
+	 */
+	while (test->reg) {
+		for (i = 0; i < test->array_len; i++) {
+			switch (test->test_type) {
+			case PATTERN_TEST:
+				b = reg_pattern_test(adapter, data,
+						     test->reg + (i * 0x40),
+						     test->mask,
+						     test->write);
+				break;
+			case SET_READ_TEST:
+				b = reg_set_and_check(adapter, data,
+						      test->reg + (i * 0x40),
+						      test->mask,
+						      test->write);
+				break;
+			case TABLE64_TEST_LO:
+				b = reg_pattern_test(adapter, data,
+						     test->reg + (i * 8),
+						     test->mask,
+						     test->write);
+				break;
+			case TABLE64_TEST_HI:
+				b = reg_pattern_test(adapter, data,
+						     test->reg + 4 + (i * 8),
+						     test->mask,
+						     test->write);
+				break;
+			case TABLE32_TEST:
+				b = reg_pattern_test(adapter, data,
+						     test->reg + (i * 4),
+						     test->mask,
+						     test->write);
+				break;
+			}
+			if (!b)
+				return false;
+		}
+		test++;
+	}
+	*data = 0;
+	return true;
+}
+
+bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data)
+{
+	struct igc_hw *hw = &adapter->hw;
+
+	*data = 0;
+
+	if (hw->nvm.ops.validate(hw) != IGC_SUCCESS) {
+		*data = 1;
+		return false;
+	}
+
+	return true;
+}
+
+static irqreturn_t igc_test_intr(int irq, void *data)
+{
+	struct igc_adapter *adapter = (struct igc_adapter *)data;
+	struct igc_hw *hw = &adapter->hw;
+
+	adapter->test_icr |= rd32(IGC_ICR);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t igc_test_intr_msix(int irq, void *data)
+{
+	struct igc_adapter *adapter = (struct igc_adapter *)data;
+	struct igc_hw *hw = &adapter->hw;
+
+	adapter->test_icr |= rd32(IGC_EICR);
+
+	return IRQ_HANDLED;
+}
+
+bool igc_intr_test(struct igc_adapter *adapter, u64 *data)
+{
+	struct igc_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	u32 mask, ics_mask = IGC_ICS_MASK_OTHER, i = 0, shared_int = true;
+	u32 irq = adapter->pdev->irq;
+
+	*data = 0;
+
+	/* Hook up test interrupt handler just for this test */
+	if (adapter->msix_entries) {
+		if (request_irq(adapter->msix_entries[0].vector,
+				&igc_test_intr_msix, 0,
+				netdev->name, adapter)) {
+			*data = 1;
+			return false;
+		}
+		ics_mask = IGC_ICS_MASK_MSIX;
+	} else if (adapter->flags & IGC_FLAG_HAS_MSI) {
+		shared_int = false;
+		if (request_irq(irq,
+				igc_test_intr, 0, netdev->name, adapter)) {
+			*data = 1;
+			return false;
+		}
+	} else if (!request_irq(irq, igc_test_intr, IRQF_PROBE_SHARED,
+				netdev->name, adapter)) {
+		shared_int = false;
+	} else if (request_irq(irq, &igc_test_intr, IRQF_SHARED,
+		 netdev->name, adapter)) {
+		*data = 1;
+		return false;
+	}
+	netdev_info(adapter->netdev, "testing %s interrupt",
+		    (shared_int ? "shared" : "unshared"));
+
+	/* Disable all the interrupts */
+	wr32(IGC_IMC, ~0);
+	wr32(IGC_EIMC, ~0);
+	wrfl();
+	usleep_range(10000, 20000);
+
+	/* Test each interrupt */
+	for (; i < 31; i++) {
+		/* Interrupt to test */
+		mask = BIT(i);
+
+		if (!(mask & ics_mask))
+			continue;
+
+		if (!shared_int) {
+			/* Disable the interrupt to be reported in
+			 * the cause register and then force the same
+			 * interrupt and see if one gets posted.  If
+			 * an interrupt was posted to the bus, the
+			 * test failed.
+			 */
+			adapter->test_icr = 0;
+
+			/* Flush any pending interrupts */
+			wr32(IGC_ICR, ~0);
+
+			wr32(IGC_IMC, mask);
+			wr32(IGC_ICS, mask);
+			wrfl();
+			usleep_range(10000, 20000);
+
+			if (adapter->test_icr & mask) {
+				*data = 3;
+				break;
+			}
+		}
+
+		/* Enable the interrupt to be reported in
+		 * the cause register and then force the same
+		 * interrupt and see if one gets posted.  If
+		 * an interrupt was not posted to the bus, the
+		 * test failed.
+		 */
+		adapter->test_icr = 0;
+
+		wr32(IGC_EIMS, mask);
+		wr32(IGC_EICS, mask);
+		wrfl();
+		usleep_range(10000, 20000);
+
+		if (!(adapter->test_icr & mask)) {
+			*data = 4;
+			break;
+		}
+
+		if (!shared_int) {
+			/* Disable the other interrupts to be reported in
+			 * the cause register and then force the other
+			 * interrupts and see if any get posted.  If
+			 * an interrupt was posted to the bus, the
+			 * test failed.
+			 */
+			adapter->test_icr = 0;
+
+			/* Flush any pending interrupts */
+			wr32(IGC_ICR, ~0);
+
+			wr32(IGC_IMC, ~mask);
+			wr32(IGC_ICS, ~mask);
+			wrfl();
+			usleep_range(10000, 20000);
+
+			if (adapter->test_icr & mask) {
+				*data = 5;
+				break;
+			}
+		}
+	}
+
+	/* Disable all the interrupts */
+	wr32(IGC_EIMC, ~0);
+	wr32(IGC_IMC, ~0);
+	wrfl();
+	usleep_range(10000, 20000);
+
+	/* Unhook test interrupt handler */
+	if (adapter->msix_entries)
+		free_irq(adapter->msix_entries[0].vector, adapter);
+	else
+		free_irq(irq, adapter);
+
+	return true;
+}
+
+bool igc_link_test(struct igc_adapter *adapter, u64 *data)
+{
+	bool link_up;
+
+	*data = 0;
+
+	/* add delay to give enough time for autonegotioation to finish */
+	if (adapter->hw.mac.autoneg)
+		ssleep(5);
+
+	link_up = igc_has_link(adapter);
+	if (!link_up) {
+		*data = 1;
+		return false;
+	}
+
+	return true;
+}
diff --git a/drivers/net/ethernet/intel/igc/igc_diag.h b/drivers/net/ethernet/intel/igc/igc_diag.h
new file mode 100644
index 000000000000..3cffaad01d50
--- /dev/null
+++ b/drivers/net/ethernet/intel/igc/igc_diag.h
@@ -0,0 +1,37 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c)  2020 Intel Corporation */
+
+bool igc_reg_test(struct igc_adapter *adapter, u64 *data);
+bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data);
+bool igc_intr_test(struct igc_adapter *adapter, u64 *data);
+bool igc_link_test(struct igc_adapter *adapter, u64 *data);
+
+struct igc_reg_test {
+	u16 reg;
+	u8 array_len;
+	u8 test_type;
+	u32 mask;
+	u32 write;
+};
+
+/* In the hardware, registers are laid out either singly, in arrays
+ * spaced 0x40 bytes apart, or in contiguous tables.  We assume
+ * most tests take place on arrays or single registers (handled
+ * as a single-element array) and special-case the tables.
+ * Table tests are always pattern tests.
+ *
+ * We also make provision for some required setup steps by specifying
+ * registers to be written without any read-back testing.
+ */
+
+#define PATTERN_TEST	1
+#define SET_READ_TEST	2
+#define TABLE32_TEST	3
+#define TABLE64_TEST_LO	4
+#define TABLE64_TEST_HI	5
+
+/* For interrupt test we are using different registers
+ * and masks for msi-x interrupts and the other methods
+ */
+#define IGC_ICS_MASK_OTHER	0x774CFED5
+#define IGC_ICS_MASK_MSIX	0xF
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 0a8c4a7412a4..c14196663ebb 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -6,6 +6,7 @@ 
 #include <linux/pm_runtime.h>
 
 #include "igc.h"
+#include "igc_diag.h"
 
 /* forward declaration */
 struct igc_stats {
@@ -1896,6 +1897,67 @@  static int igc_set_link_ksettings(struct net_device *netdev,
 	return 0;
 }
 
+static void igc_diag_test(struct net_device *netdev,
+			  struct ethtool_test *eth_test, u64 *data)
+{
+	struct igc_adapter *adapter = netdev_priv(netdev);
+	bool if_running = netif_running(netdev);
+
+	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
+		netdev_info(adapter->netdev, "offline testing starting");
+		set_bit(__IGC_TESTING, &adapter->state);
+
+		/* Link test performed before hardware reset so autoneg doesn't
+		 * interfere with test result
+		 */
+		if (!igc_link_test(adapter, &data[TEST_LINK]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		if (if_running)
+			igc_close(netdev);
+		else
+			igc_reset(adapter);
+
+		netdev_info(adapter->netdev, "register testing starting");
+		if (!igc_reg_test(adapter, &data[TEST_REG]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		igc_reset(adapter);
+
+		netdev_info(adapter->netdev, "eeprom testing starting");
+		if (!igc_eeprom_test(adapter, &data[TEST_EEP]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		igc_reset(adapter);
+
+		netdev_info(adapter->netdev, "interrupt testing starting");
+		if (!igc_intr_test(adapter, &data[TEST_IRQ]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		igc_reset(adapter);
+
+		/* loopback test will be implemented in the future */
+		data[TEST_LOOP] = 0;
+
+		clear_bit(__IGC_TESTING, &adapter->state);
+		if (if_running)
+			igc_open(netdev);
+	} else {
+		netdev_info(adapter->netdev, "online testing starting");
+
+		/* register, eeprom, intr and loopback tests not run online */
+		data[TEST_REG] = 0;
+		data[TEST_EEP] = 0;
+		data[TEST_IRQ] = 0;
+		data[TEST_LOOP] = 0;
+
+		if (!igc_link_test(adapter, &data[TEST_LINK]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+	}
+
+	msleep_interruptible(4 * 1000);
+}
+
 static const struct ethtool_ops igc_ethtool_ops = {
 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS,
 	.get_drvinfo		= igc_get_drvinfo,
@@ -1933,6 +1995,7 @@  static const struct ethtool_ops igc_ethtool_ops = {
 	.complete		= igc_ethtool_complete,
 	.get_link_ksettings	= igc_get_link_ksettings,
 	.set_link_ksettings	= igc_set_link_ksettings,
+	.self_test		= igc_diag_test,
 };
 
 void igc_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index f2bd4bb978a1..a605a02c0479 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -4389,7 +4389,7 @@  static int __igc_open(struct net_device *netdev, bool resuming)
 	return err;
 }
 
-static int igc_open(struct net_device *netdev)
+int igc_open(struct net_device *netdev)
 {
 	return __igc_open(netdev, false);
 }
@@ -4431,7 +4431,7 @@  static int __igc_close(struct net_device *netdev, bool suspending)
 	return 0;
 }
 
-static int igc_close(struct net_device *netdev)
+int igc_close(struct net_device *netdev)
 {
 	if (netif_device_present(netdev) || netdev->dismantle)
 		return __igc_close(netdev, false);
diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h
index 96dee3c1a5f7..ffb2f59ec434 100644
--- a/drivers/net/ethernet/intel/igc/igc_regs.h
+++ b/drivers/net/ethernet/intel/igc/igc_regs.h
@@ -49,6 +49,7 @@ 
 #define IGC_FACTPS		0x05B30
 
 /* Interrupt Register Description */
+#define IGC_EICR		0x01580  /* Ext. Interrupt Cause read - W0 */
 #define IGC_EICS		0x01520  /* Ext. Interrupt Cause Set - W0 */
 #define IGC_EIMS		0x01524  /* Ext. Interrupt Mask Set/Read - RW */
 #define IGC_EIMC		0x01528  /* Ext. Interrupt Mask Clear - WO */
@@ -119,6 +120,7 @@ 
 #define IGC_RLPML		0x05004  /* Rx Long Packet Max Length */
 #define IGC_RFCTL		0x05008  /* Receive Filter Control*/
 #define IGC_MTA			0x05200  /* Multicast Table Array - RW Array */
+#define IGC_RA			0x05400  /* Receive Address - RW Array */
 #define IGC_UTA			0x0A000  /* Unicast Table Array - RW */
 #define IGC_RAL(_n)		(0x05400 + ((_n) * 0x08))
 #define IGC_RAH(_n)		(0x05404 + ((_n) * 0x08))