FreeBSDDesktop / kms-drm

the DRM part of the linuxkpi-based KMS
63 stars 26 forks source link

[i915kms] i2c non-recursive mutex used recursively while querying EDID (on an ancient GMA 950 Mac mini) #134

Closed valpackett closed 5 years ago

valpackett commented 5 years ago

(4.16)

panic: _sx_xlock_hard: recursed on non-recursive sx i2c_core @ /disk/src/github.com/FreeBSDDesktop/kms-drm/linuxkpi/gplv2/src/linux_i2c.c:565

cpuid = 1
time = 1551474449
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe0026d1c380
vpanic() at vpanic+0x1b4/frame 0xfffffe0026d1c3e0
panic() at panic+0x43/frame 0xfffffe0026d1c440
_sx_xlock_hard() at _sx_xlock_hard+0x95f/frame 0xfffffe0026d1c4e0
_sx_xlock() at _sx_xlock+0xc1/frame 0xfffffe0026d1c520
i2c_transfer() at i2c_transfer+0x64/frame 0xfffffe0026d1c570
__intel_sdvo_write_cmd() at __intel_sdvo_write_cmd+0x3c3/frame 0xfffffe0026d1c6f0
intel_sdvo_ddc_proxy_xfer() at intel_sdvo_ddc_proxy_xfer+0x33/frame 0xfffffe0026d1c720
i2c_transfer() at i2c_transfer+0x90/frame 0xfffffe0026d1c770
drm_do_probe_ddc_edid() at drm_do_probe_ddc_edid+0x8f/frame 0xfffffe0026d1c7e0
drm_get_edid() at drm_get_edid+0x42/frame 0xfffffe0026d1c850
intel_sdvo_detect() at intel_sdvo_detect+0x108/frame 0xfffffe0026d1c8a0
drm_helper_probe_single_connector_modes() at drm_helper_probe_single_connector_modes+0x18e/frame 0xfffffe0026d1c940
drm_setup_crtcs() at drm_setup_crtcs+0x17b/frame 0xfffffe0026d1ca10
__drm_fb_helper_initial_config_and_unlock() at __drm_fb_helper_initial_config_and_unlock+0x30/frame 0xfffffe0026d1ca80
intel_fbdev_initial_config() at intel_fbdev_initial_config+0x14/frame 0xfffffe0026d1caa0
async_run_entry_fn() at async_run_entry_fn+0x27/frame 0xfffffe0026d1cac0
linux_work_fn() at linux_work_fn+0xe7/frame 0xfffffe0026d1cb20
taskqueue_run_locked() at taskqueue_run_locked+0x10c/frame 0xfffffe0026d1cb80
taskqueue_thread_loop() at taskqueue_thread_loop+0x88/frame 0xfffffe0026d1cbb0
fork_exit() at fork_exit+0x84/frame 0xfffffe0026d1cbf0
fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe0026d1cbf0

dmesg:

vgapci0: <VGA-compatible display> port 0x20f0-0x20f7 mem 0x90380000-0x903fffff,0x80000000-0x8fffffff,0x90400000-0x9043ffff at device 2.0 on pci0
agp0: <Intel 82945GM (945GM GMCH) SVGA controller> on vgapci0
agp0: aperture size is 256M, detected 16124k stolen memory
vgapci0: Boot video device
vgapci1: <VGA-compatible display> mem 0x90300000-0x9037ffff at device 2.1 on pci0
[…]
drmn0: <drmn> on vgapci0
vgapci0: child drmn0 requested pci_enable_io
vgapci0: child drmn0 requested pci_enable_io
[drm] Unable to create a private tmpfs mount, hugepage support will be disabled(-19).
__pm_runtime_resume not implemented -- see your local kernel hacker
Successfully added WC MTRR for [0x80000000-0x8fffffff]: 0; 
[drm] Got stolen memory base 0x7f000000, size 0x1000000
[drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
[drm] Driver supports precise vblank timestamp query.
Mar  2 00:07:28 pinepeak kernel: __pm_runtime_resume not implemented -- see your local kernel hacker
Mar  2 00:07:28 pinepeak kernel: Successfully added WC MTRR for [0x80000000-0x8fffffff]: 0; 
[drm] Failed to find VBIOS tables (VBT)
[drm] applying backlight present quirk
[drm] Connector LVDS-1: get mode from tunables:
[drm]   - kern.vt.fb.modes.LVDS-1
[drm]   - kern.vt.fb.default_mode
pm_runtime_mark_last_busy not implemented -- see your local kernel hacker
__pm_runtime_suspend not implemented -- see your local kernel hacker
pm_runtime_get_if_in_use not implemented -- see your local kernel hacker
[drm] Connector VGA-1: get mode from tunables:
[drm]   - kern.vt.fb.modes.VGA-1
[drm]   - kern.vt.fb.default_mode
[drm] Connector DVI-D-1: get mode from tunables:
[drm]   - kern.vt.fb.modes.DVI-D-1
[drm]   - kern.vt.fb.default_mode
[drm] Connector SVIDEO-1: get mode from tunables:
[drm]   - kern.vt.fb.modes.SVIDEO-1
[drm]   - kern.vt.fb.default_mode
sched_setscheduler_nocheck not implemented -- see your local kernel hacker
[drm] RC6 disabled, disabling runtime PM support
[drm] initialized overlay support
register_oom_notifier not implemented -- see your local kernel hacker
[drm] Initialized i915 1.6.0 20171222 for drmn0 on minor 0
async_schedule is dodgy -- see your local kernel hacker
pm_runtime_set_autosuspend_delay not implemented -- see your local kernel hacker
__pm_runtime_use_autosuspend not implemented -- see your local kernel hacker
Mar  2 00:07:29 pinepeak kernel: pm_runtime_mark_last_busy not implemented -- see your local kernel hacker
Mar  2 00:07:29 pinepeak kernel: __pm_runtime_suspend not implemented -- see your local kernel hacker
Mar  2 00:07:29 pinepeak kernel: pm_runtime_get_if_in_use not implemented -- see your local kernel hacker
Mar  2 00:07:29 pinepeak kernel: sched_setscheduler_nocheck not implemented -- see your local kernel hacker
Mar  2 00:07:29 pinepeak kernel: register_oom_notifier not implemented -- see your local kernel hacker
Mar  2 00:07:29 pinepeak kernel: async_schedule is dodgy -- see your local kernel hacker
Mar  2 00:07:29 pinepeak kernel: pm_runtime_set_autosuspend_delay not implemented -- see your local kernel hacker
Mar  2 00:07:29 pinepeak kernel: __pm_runtime_use_autosuspend not implemented -- see your local kernel hacker

Workaround:

diff --git i/linuxkpi/gplv2/src/linux_i2c.c w/linuxkpi/gplv2/src/linux_i2c.c
index 3db2d36d6..c379d99da 100644
--- i/linuxkpi/gplv2/src/linux_i2c.c
+++ w/linuxkpi/gplv2/src/linux_i2c.c
@@ -562,9 +562,9 @@ i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
    if (adap->algo->master_xfer == NULL)
        return (-EOPNOTSUPP);

-   mutex_lock(&i2c_core);
+   //mutex_lock(&i2c_core);
    rc = linux_i2c_transfer(adap, msgs, num);
-   mutex_unlock(&i2c_core);
+   //mutex_unlock(&i2c_core);
    return (rc);
 }
 /*

p.s. full dmesg

johalun commented 5 years ago

Thanks for the report. So it seems this does matter

// XXX: locked or unlocked, does it matter since we have our own lock
// and don't lock with provided lock_bus function?
#define __i2c_transfer(a, m, n) i2c_transfer(a, m, n)

Used here

    if (unlocked)
        ret = i2c_transfer(intel_sdvo->i2c, msgs, i+3);
    else
        ret = __i2c_transfer(intel_sdvo->i2c, msgs, i+3);

I'll add this to my todo list.

johalun commented 5 years ago

@myfreeweb try this

diff --git a/linuxkpi/gplv2/include/linux/i2c.h b/linuxkpi/gplv2/include/linux/i2c.h
index a31addc169d4..9bd398075144 100644
--- a/linuxkpi/gplv2/include/linux/i2c.h
+++ b/linuxkpi/gplv2/include/linux/i2c.h
@@ -225,11 +225,10 @@ extern int i2c_register_driver(struct module *, struct i2c_driver *);
 extern void i2c_del_driver(struct i2c_driver *);

+extern int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+                        int num);
 extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
                         int num);
-// XXX: locked or unlocked, does it matter since we have our own lock
-// and don't lock with provided lock_bus function?
-#define        __i2c_transfer(a, m, n) i2c_transfer(a, m, n)

 static inline void
 i2c_unregister_device(struct i2c_client *client)
diff --git a/linuxkpi/gplv2/src/linux_i2c.c b/linuxkpi/gplv2/src/linux_i2c.c
index 3db2d36d6582..2edfbf230544 100644
--- a/linuxkpi/gplv2/src/linux_i2c.c
+++ b/linuxkpi/gplv2/src/linux_i2c.c
@@ -554,6 +554,18 @@ linux_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
        return (rc);
 }

+int
+__i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+       int rc;
+
+       if (adap->algo->master_xfer == NULL)
+               return (-EOPNOTSUPP);
+
+       rc = linux_i2c_transfer(adap, msgs, num);
+       return (rc);
+}
+
 int
 i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
valpackett commented 5 years ago

Yes, this works

zeising commented 5 years ago

graphics/drm-current-kmod and graphics/drm-fbsd12.0-kmod updated, and MFH done. https://svnweb.freebsd.org/changeset/ports/494747 https://svnweb.freebsd.org/changeset/ports/494748