All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/6] Backlight fixes and cleanup
@ 2018-09-06 21:43 ` Lyude Paul
  0 siblings, 0 replies; 13+ messages in thread
From: Lyude Paul @ 2018-09-06 21:43 UTC (permalink / raw)
  To: nouveau; +Cc: David Airlie, linux-kernel, dri-devel, Ben Skeggs

Refactor for Ben, hopefully this time this should apply to his tree.
Next version of https://patchwork.freedesktop.org/series/48596/

No changes otherwise.

Lyude Paul (6):
  drm/nouveau: Check backlight IDs are >= 0, not > 0
  drm/nouveau: Add NV_PRINTK_ONCE and variants
  drm/nouveau: Move backlight device into nouveau_connector
  drm/nouveau: s/nouveau_backlight_exit/nouveau_backlight_fini/
  drm/nouveau: Cleanup indenting in nouveau_backlight.c
  drm/nouveau: Refactor nvXX_backlight_init()

 drivers/gpu/drm/nouveau/nouveau_backlight.c | 220 ++++++++++----------
 drivers/gpu/drm/nouveau/nouveau_connector.c |  20 ++
 drivers/gpu/drm/nouveau/nouveau_connector.h |  33 +++
 drivers/gpu/drm/nouveau/nouveau_display.c   |   2 -
 drivers/gpu/drm/nouveau/nouveau_display.h   |  25 ---
 drivers/gpu/drm/nouveau/nouveau_drv.h       |  10 +-
 6 files changed, 168 insertions(+), 142 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v4 0/6] Backlight fixes and cleanup
@ 2018-09-06 21:43 ` Lyude Paul
  0 siblings, 0 replies; 13+ messages in thread
From: Lyude Paul @ 2018-09-06 21:43 UTC (permalink / raw)
  To: nouveau; +Cc: David Airlie, linux-kernel, dri-devel, Ben Skeggs

Refactor for Ben, hopefully this time this should apply to his tree.
Next version of https://patchwork.freedesktop.org/series/48596/

No changes otherwise.

Lyude Paul (6):
  drm/nouveau: Check backlight IDs are >= 0, not > 0
  drm/nouveau: Add NV_PRINTK_ONCE and variants
  drm/nouveau: Move backlight device into nouveau_connector
  drm/nouveau: s/nouveau_backlight_exit/nouveau_backlight_fini/
  drm/nouveau: Cleanup indenting in nouveau_backlight.c
  drm/nouveau: Refactor nvXX_backlight_init()

 drivers/gpu/drm/nouveau/nouveau_backlight.c | 220 ++++++++++----------
 drivers/gpu/drm/nouveau/nouveau_connector.c |  20 ++
 drivers/gpu/drm/nouveau/nouveau_connector.h |  33 +++
 drivers/gpu/drm/nouveau/nouveau_display.c   |   2 -
 drivers/gpu/drm/nouveau/nouveau_display.h   |  25 ---
 drivers/gpu/drm/nouveau/nouveau_drv.h       |  10 +-
 6 files changed, 168 insertions(+), 142 deletions(-)

-- 
2.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v4 1/6] drm/nouveau: Check backlight IDs are >= 0, not > 0
  2018-09-06 21:43 ` Lyude Paul
  (?)
@ 2018-09-06 21:43 ` Lyude Paul
  -1 siblings, 0 replies; 13+ messages in thread
From: Lyude Paul @ 2018-09-06 21:43 UTC (permalink / raw)
  To: nouveau; +Cc: stable, Ben Skeggs, David Airlie, dri-devel, linux-kernel

Remember, ida IDs start at 0, not 1!

Signed-off-by: Lyude Paul <lyude@redhat.com>
Reviewed-by: Karol Herbst <kherbst@redhat.com>
Cc: stable@vger.kernel.org
---
 drivers/gpu/drm/nouveau/nouveau_backlight.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 408b955e5c39..6dd72bc32897 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -116,7 +116,7 @@ nv40_backlight_init(struct drm_connector *connector)
 				       &nv40_bl_ops, &props);
 
 	if (IS_ERR(bd)) {
-		if (bl_connector.id > 0)
+		if (bl_connector.id >= 0)
 			ida_simple_remove(&bl_ida, bl_connector.id);
 		return PTR_ERR(bd);
 	}
@@ -249,7 +249,7 @@ nv50_backlight_init(struct drm_connector *connector)
 				       nv_encoder, ops, &props);
 
 	if (IS_ERR(bd)) {
-		if (bl_connector.id > 0)
+		if (bl_connector.id >= 0)
 			ida_simple_remove(&bl_ida, bl_connector.id);
 		return PTR_ERR(bd);
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 2/6] drm/nouveau: Add NV_PRINTK_ONCE and variants
  2018-09-06 21:43 ` Lyude Paul
  (?)
  (?)
@ 2018-09-06 21:43 ` Lyude Paul
  2018-09-07  5:35   ` Joe Perches
  -1 siblings, 1 reply; 13+ messages in thread
From: Lyude Paul @ 2018-09-06 21:43 UTC (permalink / raw)
  To: nouveau; +Cc: Karol Herbst, Ben Skeggs, David Airlie, dri-devel, linux-kernel

Since we're about to use this in nouveau_backlight.c. Same thing as
DRM_WARN_ONCE, DRM_INFO_ONCE, etc...

Signed-off-by: Lyude Paul <lyude@redhat.com>
Cc: Karol Herbst <kherbst@redhat.com>
---
 drivers/gpu/drm/nouveau/nouveau_drv.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 6e1acaec3400..d9d687916553 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -244,10 +244,12 @@ void nouveau_drm_device_remove(struct drm_device *dev);
 	struct nouveau_cli *_cli = (c);                                        \
 	dev_##l(_cli->drm->dev->dev, "%s: "f, _cli->name, ##a);                \
 } while(0)
+
 #define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a)
 #define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a)
 #define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a)
 #define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a)
+
 #define NV_DEBUG(drm,f,a...) do {                                              \
 	if (unlikely(drm_debug & DRM_UT_DRIVER))                               \
 		NV_PRINTK(info, &(drm)->client, f, ##a);                       \
@@ -257,6 +259,12 @@ void nouveau_drm_device_remove(struct drm_device *dev);
 		NV_PRINTK(info, &(drm)->client, f, ##a);                       \
 } while(0)
 
+#define NV_PRINTK_ONCE(l,c,f,a...) NV_PRINTK(l##_once,c,f, ##a)
+
+#define NV_ERROR_ONCE(drm,f,a...) NV_PRINTK_ONCE(err, &(drm)->client, f, ##a)
+#define NV_WARN_ONCE(drm,f,a...) NV_PRINTK_ONCE(warn, &(drm)->client, f, ##a)
+#define NV_INFO_ONCE(drm,f,a...) NV_PRINTK_ONCE(info, &(drm)->client, f, ##a)
+
 extern int nouveau_modeset;
 
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 3/6] drm/nouveau: Move backlight device into nouveau_connector
  2018-09-06 21:43 ` Lyude Paul
@ 2018-09-06 21:43   ` Lyude Paul
  -1 siblings, 0 replies; 13+ messages in thread
From: Lyude Paul @ 2018-09-06 21:43 UTC (permalink / raw)
  To: nouveau; +Cc: Ben Skeggs, David Airlie, dri-devel, linux-kernel

Currently module unloading is broken in nouveau due to a rather annoying
race condition resulting from nouveau_backlight.c having gone a bit
stale over time:

[ 1960.791143] ==================================================================
[ 1960.791394] BUG: KASAN: use-after-free in nouveau_backlight_exit+0x112/0x150 [nouveau]
[ 1960.791460] Read of size 4 at addr ffff88075accf350 by task zsh/11185
[ 1960.791521]
[ 1960.791545] CPU: 7 PID: 11185 Comm: zsh Kdump: loaded Tainted: G           O      4.18.0Lyude-Test+ #4
[ 1960.791580] Hardware name: LENOVO 20EQS64N0B/20EQS64N0B, BIOS N1EET79W (1.52 ) 07/13/2018
[ 1960.791628] Call Trace:
[ 1960.791680]  dump_stack+0xa4/0xfd
[ 1960.791721]  print_address_description+0x71/0x239
[ 1960.791833]  ? nouveau_backlight_exit+0x112/0x150 [nouveau]
[ 1960.791877]  kasan_report.cold.6+0x242/0x2fe
[ 1960.791919]  __asan_report_load4_noabort+0x19/0x20
[ 1960.792012]  nouveau_backlight_exit+0x112/0x150 [nouveau]
[ 1960.792081]  nouveau_display_destroy+0x76/0x150 [nouveau]
[ 1960.792150]  nouveau_drm_device_fini+0xb7/0x190 [nouveau]
[ 1960.792265]  nouveau_drm_device_remove+0x14b/0x1d0 [nouveau]
[ 1960.792347]  ? nouveau_cli_work_queue+0x2e0/0x2e0 [nouveau]
[ 1960.792378]  ? trace_hardirqs_on_caller+0x38b/0x570
[ 1960.792406]  ? trace_hardirqs_on+0xd/0x10
[ 1960.792472]  nouveau_drm_remove+0x37/0x50 [nouveau]
[ 1960.792502]  pci_device_remove+0x112/0x2d0
[ 1960.792530]  ? pcibios_free_irq+0x10/0x10
[ 1960.792558]  ? kasan_check_write+0x14/0x20
[ 1960.792587]  device_release_driver_internal+0x35c/0x650
[ 1960.792617]  device_release_driver+0x12/0x20
[ 1960.792643]  pci_stop_bus_device+0x172/0x1e0
[ 1960.792671]  pci_stop_and_remove_bus_device_locked+0x1a/0x30
[ 1960.792715]  remove_store+0xcb/0xe0
[ 1960.792753]  ? sriov_numvfs_store+0x2e0/0x2e0
[ 1960.792779]  ? __lock_is_held+0xb5/0x140
[ 1960.792808]  ? component_add+0x530/0x530
[ 1960.792834]  dev_attr_store+0x3f/0x70
[ 1960.792859]  ? sysfs_file_ops+0x11d/0x170
[ 1960.792885]  sysfs_kf_write+0x104/0x150
[ 1960.792915]  ? sysfs_file_ops+0x170/0x170
[ 1960.792940]  kernfs_fop_write+0x24f/0x400
[ 1960.792978]  ? __lock_acquire+0x6ea/0x47f0
[ 1960.793021]  __vfs_write+0xeb/0x760
[ 1960.793048]  ? kernel_read+0x130/0x130
[ 1960.793076]  ? __lock_is_held+0xb5/0x140
[ 1960.793107]  ? rcu_read_lock_sched_held+0xdd/0x110
[ 1960.793135]  ? rcu_sync_lockdep_assert+0x78/0xb0
[ 1960.793162]  ? __sb_start_write+0x183/0x220
[ 1960.793189]  vfs_write+0x14d/0x4a0
[ 1960.793229]  ksys_write+0xd2/0x1b0
[ 1960.793255]  ? __ia32_sys_read+0xb0/0xb0
[ 1960.793298]  ? fput+0x1d/0x120
[ 1960.793324]  ? filp_close+0xf3/0x130
[ 1960.793349]  ? entry_SYSCALL_64_after_hwframe+0x59/0xbe
[ 1960.793380]  __x64_sys_write+0x73/0xb0
[ 1960.793407]  do_syscall_64+0xaa/0x400
[ 1960.793433]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 1960.793460] RIP: 0033:0x7f59df433164
[ 1960.793486] Code: 89 02 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 8d 05 81 38 2d 00 8b 00 85 c0 75 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 41 54 49 89 d4 55 48 89 f5 53
[ 1960.793541] RSP: 002b:00007ffd70ee2fb8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
[ 1960.793576] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007f59df433164
[ 1960.793620] RDX: 0000000000000002 RSI: 00005578088640c0 RDI: 0000000000000001
[ 1960.793665] RBP: 00005578088640c0 R08: 00007f59df7038c0 R09: 00007f59e0995b80
[ 1960.793696] R10: 000000000000000a R11: 0000000000000246 R12: 00007f59df702760
[ 1960.793730] R13: 0000000000000002 R14: 00007f59df6fd760 R15: 0000000000000002
[ 1960.793768]
[ 1960.793790] Allocated by task 11167:
[ 1960.793816]  save_stack+0x43/0xd0
[ 1960.793841]  kasan_kmalloc+0xc4/0xe0
[ 1960.793880]  kasan_slab_alloc+0x11/0x20
[ 1960.793905]  kmem_cache_alloc+0xd7/0x270
[ 1960.793944]  getname_flags+0xbd/0x520
[ 1960.793969]  user_path_at_empty+0x23/0x50
[ 1960.793994]  do_faccessat+0x1fc/0x5d0
[ 1960.794018]  __x64_sys_access+0x59/0x80
[ 1960.794043]  do_syscall_64+0xaa/0x400
[ 1960.794067]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 1960.794093]
[ 1960.794127] Freed by task 11167:
[ 1960.794152]  save_stack+0x43/0xd0
[ 1960.794190]  __kasan_slab_free+0x139/0x190
[ 1960.794215]  kasan_slab_free+0xe/0x10
[ 1960.794239]  kmem_cache_free+0xcb/0x2c0
[ 1960.794264]  putname+0xad/0xe0
[ 1960.794287]  filename_lookup.part.59+0x1f1/0x360
[ 1960.794313]  user_path_at_empty+0x3e/0x50
[ 1960.794338]  do_faccessat+0x1fc/0x5d0
[ 1960.794362]  __x64_sys_access+0x59/0x80
[ 1960.794393]  do_syscall_64+0xaa/0x400
[ 1960.794421]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 1960.794461]
[ 1960.794483] The buggy address belongs to the object at ffff88075acceac0
[ 1960.794483]  which belongs to the cache names_cache of size 4096
[ 1960.794540] The buggy address is located 2192 bytes inside of
[ 1960.794540]  4096-byte region [ffff88075acceac0, ffff88075accfac0)
[ 1960.794581] The buggy address belongs to the page:
[ 1960.794609] page:ffffea001d6b3200 count:1 mapcount:0 mapping:ffff880778e4b1c0 index:0x0 compound_mapcount: 0
[ 1960.794651] flags: 0x8000000000008100(slab|head)
[ 1960.794679] raw: 8000000000008100 ffffea001d39e808 ffffea001d39ea08 ffff880778e4b1c0
[ 1960.794739] raw: 0000000000000000 0000000000070007 00000001ffffffff 0000000000000000
[ 1960.794785] page dumped because: kasan: bad access detected
[ 1960.794813]
[ 1960.794834] Memory state around the buggy address:
[ 1960.794861]  ffff88075accf200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 1960.794894]  ffff88075accf280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 1960.794925] >ffff88075accf300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 1960.794956]                                                  ^
[ 1960.794985]  ffff88075accf380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 1960.795017]  ffff88075accf400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 1960.795061] ==================================================================
[ 1960.795106] Disabling lock debugging due to kernel taint
[ 1960.795131] ------------[ cut here ]------------
[ 1960.795148] ida_remove called for id=1802201963 which is not allocated.
[ 1960.795193] WARNING: CPU: 7 PID: 11185 at lib/idr.c:521 ida_remove+0x184/0x210
[ 1960.795213] Modules linked in: nouveau(O) mxm_wmi ttm i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm joydev vfat fat intel_rapl x86_pkg_temp_thermal coretemp crc32_pclmul iTCO_wdt psmouse wmi_bmof mei_me tpm_tis mei tpm_tis_core tpm i2c_i801 thinkpad_acpi pcc_cpufreq crc32c_intel serio_raw xhci_pci xhci_hcd wmi video i2c_dev i2c_core
[ 1960.795305] CPU: 7 PID: 11185 Comm: zsh Kdump: loaded Tainted: G    B      O      4.18.0Lyude-Test+ #4
[ 1960.795330] Hardware name: LENOVO 20EQS64N0B/20EQS64N0B, BIOS N1EET79W (1.52 ) 07/13/2018
[ 1960.795352] RIP: 0010:ida_remove+0x184/0x210
[ 1960.795370] Code: 4c 89 f7 e8 ae c8 00 00 eb 22 41 83 c4 02 4c 89 e8 41 83 fc 3f 0f 86 64 ff ff ff 44 89 fe 48 c7 c7 20 94 1e 83 e8 54 ed 81 fe <0f> 0b 48 b8 00 00 00 00 00 fc ff df 48 01 c3 c7 03 00 00 00 00 c7
[ 1960.795402] RSP: 0018:ffff88074d4df7b8 EFLAGS: 00010082
[ 1960.795421] RAX: 0000000000000000 RBX: 1ffff100e9a9befa RCX: ffffffff81479975
[ 1960.795440] RDX: 0000000000000000 RSI: 0000000000000008 RDI: ffff88077c1de690
[ 1960.795460] RBP: ffff88074d4df878 R08: ffffed00ef83bcd3 R09: ffffed00ef83bcd2
[ 1960.795479] R10: ffffed00ef83bcd2 R11: ffff88077c1de697 R12: 000000000000036b
[ 1960.795498] R13: 0000000000000202 R14: ffffffffa0aa7fa0 R15: 000000006b6b6b6b
[ 1960.795518] FS:  00007f59e0995b80(0000) GS:ffff88077c1c0000(0000) knlGS:0000000000000000
[ 1960.795553] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1960.795571] CR2: 00007f59e09a2010 CR3: 00000004a1a70005 CR4: 00000000003606e0
[ 1960.795596] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 1960.795629] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 1960.795649] Call Trace:
[ 1960.795667]  ? ida_destroy+0x1d0/0x1d0
[ 1960.795686]  ? kasan_check_write+0x14/0x20
[ 1960.795704]  ? do_raw_spin_lock+0xc2/0x1c0
[ 1960.795724]  ida_simple_remove+0x26/0x40
[ 1960.795794]  nouveau_backlight_exit+0x9d/0x150 [nouveau]
[ 1960.795867]  nouveau_display_destroy+0x76/0x150 [nouveau]
[ 1960.795930]  nouveau_drm_device_fini+0xb7/0x190 [nouveau]
[ 1960.795989]  nouveau_drm_device_remove+0x14b/0x1d0 [nouveau]
[ 1960.796047]  ? nouveau_cli_work_queue+0x2e0/0x2e0 [nouveau]
[ 1960.796067]  ? trace_hardirqs_on_caller+0x38b/0x570
[ 1960.796089]  ? trace_hardirqs_on+0xd/0x10
[ 1960.796146]  nouveau_drm_remove+0x37/0x50 [nouveau]
[ 1960.796167]  pci_device_remove+0x112/0x2d0
[ 1960.796186]  ? pcibios_free_irq+0x10/0x10
[ 1960.796218]  ? kasan_check_write+0x14/0x20
[ 1960.796237]  device_release_driver_internal+0x35c/0x650
[ 1960.796257]  device_release_driver+0x12/0x20
[ 1960.796289]  pci_stop_bus_device+0x172/0x1e0
[ 1960.796308]  pci_stop_and_remove_bus_device_locked+0x1a/0x30
[ 1960.796328]  remove_store+0xcb/0xe0
[ 1960.796345]  ? sriov_numvfs_store+0x2e0/0x2e0
[ 1960.796364]  ? __lock_is_held+0xb5/0x140
[ 1960.796383]  ? component_add+0x530/0x530
[ 1960.796401]  dev_attr_store+0x3f/0x70
[ 1960.796419]  ? sysfs_file_ops+0x11d/0x170
[ 1960.796436]  sysfs_kf_write+0x104/0x150
[ 1960.796454]  ? sysfs_file_ops+0x170/0x170
[ 1960.796471]  kernfs_fop_write+0x24f/0x400
[ 1960.796488]  ? __lock_acquire+0x6ea/0x47f0
[ 1960.796520]  __vfs_write+0xeb/0x760
[ 1960.796538]  ? kernel_read+0x130/0x130
[ 1960.796556]  ? __lock_is_held+0xb5/0x140
[ 1960.796590]  ? rcu_read_lock_sched_held+0xdd/0x110
[ 1960.796608]  ? rcu_sync_lockdep_assert+0x78/0xb0
[ 1960.796626]  ? __sb_start_write+0x183/0x220
[ 1960.796648]  vfs_write+0x14d/0x4a0
[ 1960.796666]  ksys_write+0xd2/0x1b0
[ 1960.796684]  ? __ia32_sys_read+0xb0/0xb0
[ 1960.796701]  ? fput+0x1d/0x120
[ 1960.796732]  ? filp_close+0xf3/0x130
[ 1960.796749]  ? entry_SYSCALL_64_after_hwframe+0x59/0xbe
[ 1960.796768]  __x64_sys_write+0x73/0xb0
[ 1960.796800]  do_syscall_64+0xaa/0x400
[ 1960.796818]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 1960.796836] RIP: 0033:0x7f59df433164
[ 1960.796854] Code: 89 02 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 8d 05 81 38 2d 00 8b 00 85 c0 75 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 41 54 49 89 d4 55 48 89 f5 53
[ 1960.796884] RSP: 002b:00007ffd70ee2fb8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
[ 1960.796906] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007f59df433164
[ 1960.796926] RDX: 0000000000000002 RSI: 00005578088640c0 RDI: 0000000000000001
[ 1960.796946] RBP: 00005578088640c0 R08: 00007f59df7038c0 R09: 00007f59e0995b80
[ 1960.796966] R10: 000000000000000a R11: 0000000000000246 R12: 00007f59df702760
[ 1960.796985] R13: 0000000000000002 R14: 00007f59df6fd760 R15: 0000000000000002
[ 1960.797008] irq event stamp: 509990
[ 1960.797026] hardirqs last  enabled at (509989): [<ffffffff8119ff78>] flush_work+0x4b8/0x6d0
[ 1960.797063] hardirqs last disabled at (509990): [<ffffffff8297c395>] _raw_spin_lock_irqsave+0x25/0x60
[ 1960.797085] softirqs last  enabled at (509744): [<ffffffff82c005ad>] __do_softirq+0x5ad/0x8c0
[ 1960.797121] softirqs last disabled at (509735): [<ffffffff8115aa15>] irq_exit+0x1a5/0x1e0
[ 1960.797142] ---[ end trace fb1342325f1846b8 ]---

While I haven't actually gone into the details of what's causing this to
happen (maybe the kernel removes the backlight device in the device core
before we get to it?), it doesn't really matter anyway because the way
nouveau handles backlights has long since been deprecated.

According to the documentation on the drm_connector->late_register()
hook, the ->late_register() hook should be used for adding extra
connector-related devices. Vice versa, the ->early_unregister() hook is
meant to be used for removing those devices.

So: gut nouveau_drm->bl_list and nouveau_drm->backlight, and replace
them with per-connector backlight structures. Additionally, move
backlight registration/teardown into the ->late_register() and
->early_unregister() hooks so that DRM can give us a chance to remove
the backlight before the connector is even removed. This appears to fix
the problem once and for all.

Changes since v2:
- Use NV_INFO_ONCE for printing GMUX information, since otherwise this
  will end up printing that message for as many times as we have
  connectors

Signed-off-by: Lyude Paul <lyude@redhat.com>
Reviewed-by: Karol Herbst <kherbst@redhat.com>
---
 drivers/gpu/drm/nouveau/nouveau_backlight.c | 151 +++++++++++---------
 drivers/gpu/drm/nouveau/nouveau_connector.c |  20 +++
 drivers/gpu/drm/nouveau/nouveau_connector.h |  33 +++++
 drivers/gpu/drm/nouveau/nouveau_display.c   |   2 -
 drivers/gpu/drm/nouveau/nouveau_display.h   |  25 ----
 drivers/gpu/drm/nouveau/nouveau_drv.h       |   2 -
 6 files changed, 133 insertions(+), 100 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 6dd72bc32897..5d0694680f59 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -37,18 +37,19 @@
 #include "nouveau_drv.h"
 #include "nouveau_reg.h"
 #include "nouveau_encoder.h"
+#include "nouveau_connector.h"
 
 static struct ida bl_ida;
 #define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0'
 
-struct backlight_connector {
-	struct list_head head;
+struct nouveau_backlight {
+	struct backlight_device *dev;
 	int id;
 };
 
 static bool
-nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_connector
-		*connector)
+nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE],
+			   struct nouveau_backlight *bl)
 {
 	const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL);
 	if (nb < 0 || nb >= 100)
@@ -57,7 +58,7 @@ nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_c
 		snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb);
 	else
 		snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight");
-	connector->id = nb;
+	bl->id = nb;
 	return true;
 }
 
@@ -96,36 +97,45 @@ static int
 nv40_backlight_init(struct drm_connector *connector)
 {
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
+	struct nouveau_backlight *bl;
 	struct nvif_object *device = &drm->client.device.object;
 	struct backlight_properties props;
-	struct backlight_device *bd;
-	struct backlight_connector bl_connector;
 	char backlight_name[BL_NAME_SIZE];
+	int ret = 0;
 
 	if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
 		return 0;
 
+	bl = kzalloc(sizeof(*bl), GFP_KERNEL);
+	if (!bl)
+		return -ENOMEM;
+
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 31;
-	if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
+	if (!nouveau_get_backlight_name(backlight_name, bl)) {
 		NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
-		return 0;
+		goto fail_alloc;
 	}
-	bd = backlight_device_register(backlight_name , connector->kdev, drm,
-				       &nv40_bl_ops, &props);
 
-	if (IS_ERR(bd)) {
-		if (bl_connector.id >= 0)
-			ida_simple_remove(&bl_ida, bl_connector.id);
-		return PTR_ERR(bd);
+	bl->dev = backlight_device_register(backlight_name, connector->kdev,
+					    drm, &nv40_bl_ops, &props);
+	if (IS_ERR(bl->dev)) {
+		if (bl->id >= 0)
+			ida_simple_remove(&bl_ida, bl->id);
+
+		ret = PTR_ERR(bl->dev);
+		goto fail_alloc;
 	}
-	list_add(&bl_connector.head, &drm->bl_connectors);
-	drm->backlight = bd;
-	bd->props.brightness = nv40_get_intensity(bd);
-	backlight_update_status(bd);
+
+	nouveau_connector(connector)->backlight = bl;
+	bl->dev->props.brightness = nv40_get_intensity(bl->dev);
+	backlight_update_status(bl->dev);
 
 	return 0;
+fail_alloc:
+	kfree(bl);
+	return ret;
 }
 
 static int
@@ -215,11 +225,11 @@ nv50_backlight_init(struct drm_connector *connector)
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
 	struct nvif_object *device = &drm->client.device.object;
 	struct nouveau_encoder *nv_encoder;
+	struct nouveau_backlight *bl;
 	struct backlight_properties props;
-	struct backlight_device *bd;
 	const struct backlight_ops *ops;
-	struct backlight_connector bl_connector;
 	char backlight_name[BL_NAME_SIZE];
+	int ret = 0;
 
 	nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
 	if (!nv_encoder) {
@@ -231,6 +241,10 @@ nv50_backlight_init(struct drm_connector *connector)
 	if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1)))
 		return 0;
 
+	bl = kzalloc(sizeof(*bl), GFP_KERNEL);
+	if (!bl)
+		return -ENOMEM;
+
 	if (drm->client.device.info.chipset <= 0xa0 ||
 	    drm->client.device.info.chipset == 0xaa ||
 	    drm->client.device.info.chipset == 0xac)
@@ -241,79 +255,74 @@ nv50_backlight_init(struct drm_connector *connector)
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 100;
-	if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
+	if (!nouveau_get_backlight_name(backlight_name, bl)) {
 		NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
-		return 0;
+		goto fail_alloc;
 	}
-	bd = backlight_device_register(backlight_name , connector->kdev,
-				       nv_encoder, ops, &props);
 
-	if (IS_ERR(bd)) {
-		if (bl_connector.id >= 0)
-			ida_simple_remove(&bl_ida, bl_connector.id);
-		return PTR_ERR(bd);
+	bl->dev = backlight_device_register(backlight_name, connector->kdev,
+					    nv_encoder, ops, &props);
+	if (IS_ERR(bl->dev)) {
+		if (bl->id >= 0)
+			ida_simple_remove(&bl_ida, bl->id);
+
+		ret = PTR_ERR(bl->dev);
+		goto fail_alloc;
 	}
 
-	list_add(&bl_connector.head, &drm->bl_connectors);
-	drm->backlight = bd;
-	bd->props.brightness = bd->ops->get_brightness(bd);
-	backlight_update_status(bd);
+	nouveau_connector(connector)->backlight = bl;
+	bl->dev->props.brightness = bl->dev->ops->get_brightness(bl->dev);
+	backlight_update_status(bl->dev);
 	return 0;
+
+fail_alloc:
+	kfree(bl);
+	return ret;
 }
 
 int
-nouveau_backlight_init(struct drm_device *dev)
+nouveau_backlight_init(struct drm_connector *connector)
 {
-	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nouveau_drm *drm = nouveau_drm(connector->dev);
 	struct nvif_device *device = &drm->client.device;
-	struct drm_connector *connector;
-	struct drm_connector_list_iter conn_iter;
-
-	INIT_LIST_HEAD(&drm->bl_connectors);
 
 	if (apple_gmux_present()) {
-		NV_INFO(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n");
+		NV_INFO_ONCE(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n");
 		return 0;
 	}
 
-	drm_connector_list_iter_begin(dev, &conn_iter);
-	drm_for_each_connector_iter(connector, &conn_iter) {
-		if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
-		    connector->connector_type != DRM_MODE_CONNECTOR_eDP)
-			continue;
-
-		switch (device->info.family) {
-		case NV_DEVICE_INFO_V0_CURIE:
-			return nv40_backlight_init(connector);
-		case NV_DEVICE_INFO_V0_TESLA:
-		case NV_DEVICE_INFO_V0_FERMI:
-		case NV_DEVICE_INFO_V0_KEPLER:
-		case NV_DEVICE_INFO_V0_MAXWELL:
-			return nv50_backlight_init(connector);
-		default:
-			break;
-		}
-	}
-	drm_connector_list_iter_end(&conn_iter);
+	if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
+	    connector->connector_type != DRM_MODE_CONNECTOR_eDP)
+		return 0;
 
-	return 0;
+	switch (device->info.family) {
+	case NV_DEVICE_INFO_V0_CURIE:
+		return nv40_backlight_init(connector);
+	case NV_DEVICE_INFO_V0_TESLA:
+	case NV_DEVICE_INFO_V0_FERMI:
+	case NV_DEVICE_INFO_V0_KEPLER:
+	case NV_DEVICE_INFO_V0_MAXWELL:
+		return nv50_backlight_init(connector);
+	default:
+		return 0;
+	}
 }
 
 void
-nouveau_backlight_exit(struct drm_device *dev)
+nouveau_backlight_exit(struct drm_connector *connector)
 {
-	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct backlight_connector *connector;
+	struct nouveau_connector *nv_conn = nouveau_connector(connector);
+	struct nouveau_backlight *bl = nv_conn->backlight;
 
-	list_for_each_entry(connector, &drm->bl_connectors, head) {
-		if (connector->id >= 0)
-			ida_simple_remove(&bl_ida, connector->id);
-	}
+	if (!bl)
+		return;
 
-	if (drm->backlight) {
-		backlight_device_unregister(drm->backlight);
-		drm->backlight = NULL;
-	}
+	if (bl->id >= 0)
+		ida_simple_remove(&bl_ida, bl->id);
+
+	backlight_device_unregister(bl->dev);
+	nv_conn->backlight = NULL;
+	kfree(bl);
 }
 
 void
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 247f72cc4d10..35c538f95167 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -882,6 +882,22 @@ nouveau_connector_detect_depth(struct drm_connector *connector)
 		connector->display_info.bpc = 8;
 }
 
+static int
+nouveau_connector_late_register(struct drm_connector *connector)
+{
+	int ret;
+
+	ret = nouveau_backlight_init(connector);
+
+	return ret;
+}
+
+static void
+nouveau_connector_early_unregister(struct drm_connector *connector)
+{
+	nouveau_backlight_exit(connector);
+}
+
 static int
 nouveau_connector_get_modes(struct drm_connector *connector)
 {
@@ -1066,6 +1082,8 @@ nouveau_connector_funcs = {
 	.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
 	.atomic_set_property = nouveau_conn_atomic_set_property,
 	.atomic_get_property = nouveau_conn_atomic_get_property,
+	.late_register = nouveau_connector_late_register,
+	.early_unregister = nouveau_connector_early_unregister,
 };
 
 static const struct drm_connector_funcs
@@ -1081,6 +1099,8 @@ nouveau_connector_funcs_lvds = {
 	.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
 	.atomic_set_property = nouveau_conn_atomic_set_property,
 	.atomic_get_property = nouveau_conn_atomic_get_property,
+	.late_register = nouveau_connector_late_register,
+	.early_unregister = nouveau_connector_early_unregister,
 };
 
 static int
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index dc7454e7f19a..aefc3cbf8098 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -37,6 +37,10 @@
 
 struct nvkm_i2c_port;
 
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+struct nouveau_backlight;
+#endif
+
 struct nouveau_connector {
 	struct drm_connector base;
 	enum dcb_connector_type type;
@@ -53,6 +57,9 @@ struct nouveau_connector {
 	struct nouveau_encoder *detected_encoder;
 	struct edid *edid;
 	struct drm_display_mode *native_mode;
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+	struct nouveau_backlight *backlight;
+#endif
 };
 
 static inline struct nouveau_connector *nouveau_connector(
@@ -179,4 +186,30 @@ int nouveau_conn_atomic_get_property(struct drm_connector *,
 				     const struct drm_connector_state *,
 				     struct drm_property *, u64 *);
 struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *);
+
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+extern int nouveau_backlight_init(struct drm_connector *);
+extern void nouveau_backlight_exit(struct drm_connector *);
+extern void nouveau_backlight_ctor(void);
+extern void nouveau_backlight_dtor(void);
+#else
+static inline int
+nouveau_backlight_init(struct drm_connector *connector)
+{
+	return 0;
+}
+
+static inline void
+nouveau_backlight_exit(struct drm_connector *connector) {
+}
+
+static inline void
+nouveau_backlight_ctor(void) {
+}
+
+static inline void
+nouveau_backlight_dtor(void) {
+}
+#endif
+
 #endif /* __NOUVEAU_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 540c0cbbfcee..f326ffd86766 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -582,7 +582,6 @@ nouveau_display_create(struct drm_device *dev)
 			goto vblank_err;
 	}
 
-	nouveau_backlight_init(dev);
 	INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work);
 #ifdef CONFIG_ACPI
 	drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy;
@@ -607,7 +606,6 @@ nouveau_display_destroy(struct drm_device *dev)
 #ifdef CONFIG_ACPI
 	unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb);
 #endif
-	nouveau_backlight_exit(dev);
 	nouveau_display_vblank_fini(dev);
 
 	drm_kms_helper_poll_fini(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index ff92b54ce448..eb77e41c2d4e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -85,31 +85,6 @@ int  nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
 
 void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *);
 
-#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
-extern int nouveau_backlight_init(struct drm_device *);
-extern void nouveau_backlight_exit(struct drm_device *);
-extern void nouveau_backlight_ctor(void);
-extern void nouveau_backlight_dtor(void);
-#else
-static inline int
-nouveau_backlight_init(struct drm_device *dev)
-{
-	return 0;
-}
-
-static inline void
-nouveau_backlight_exit(struct drm_device *dev) {
-}
-
-static inline void
-nouveau_backlight_ctor(void) {
-}
-
-static inline void
-nouveau_backlight_dtor(void) {
-}
-#endif
-
 struct drm_framebuffer *
 nouveau_user_framebuffer_create(struct drm_device *, struct drm_file *,
 				const struct drm_mode_fb_cmd2 *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index d9d687916553..0b2191fa96f7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -194,8 +194,6 @@ struct nouveau_drm {
 	/* modesetting */
 	struct nvbios vbios;
 	struct nouveau_display *display;
-	struct backlight_device *backlight;
-	struct list_head bl_connectors;
 	struct work_struct hpd_work;
 	struct work_struct fbcon_work;
 	int fbcon_new_state;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 3/6] drm/nouveau: Move backlight device into nouveau_connector
@ 2018-09-06 21:43   ` Lyude Paul
  0 siblings, 0 replies; 13+ messages in thread
From: Lyude Paul @ 2018-09-06 21:43 UTC (permalink / raw)
  To: nouveau; +Cc: David Airlie, Ben Skeggs, dri-devel, linux-kernel

Currently module unloading is broken in nouveau due to a rather annoying
race condition resulting from nouveau_backlight.c having gone a bit
stale over time:

[ 1960.791143] ==================================================================
[ 1960.791394] BUG: KASAN: use-after-free in nouveau_backlight_exit+0x112/0x150 [nouveau]
[ 1960.791460] Read of size 4 at addr ffff88075accf350 by task zsh/11185
[ 1960.791521]
[ 1960.791545] CPU: 7 PID: 11185 Comm: zsh Kdump: loaded Tainted: G           O      4.18.0Lyude-Test+ #4
[ 1960.791580] Hardware name: LENOVO 20EQS64N0B/20EQS64N0B, BIOS N1EET79W (1.52 ) 07/13/2018
[ 1960.791628] Call Trace:
[ 1960.791680]  dump_stack+0xa4/0xfd
[ 1960.791721]  print_address_description+0x71/0x239
[ 1960.791833]  ? nouveau_backlight_exit+0x112/0x150 [nouveau]
[ 1960.791877]  kasan_report.cold.6+0x242/0x2fe
[ 1960.791919]  __asan_report_load4_noabort+0x19/0x20
[ 1960.792012]  nouveau_backlight_exit+0x112/0x150 [nouveau]
[ 1960.792081]  nouveau_display_destroy+0x76/0x150 [nouveau]
[ 1960.792150]  nouveau_drm_device_fini+0xb7/0x190 [nouveau]
[ 1960.792265]  nouveau_drm_device_remove+0x14b/0x1d0 [nouveau]
[ 1960.792347]  ? nouveau_cli_work_queue+0x2e0/0x2e0 [nouveau]
[ 1960.792378]  ? trace_hardirqs_on_caller+0x38b/0x570
[ 1960.792406]  ? trace_hardirqs_on+0xd/0x10
[ 1960.792472]  nouveau_drm_remove+0x37/0x50 [nouveau]
[ 1960.792502]  pci_device_remove+0x112/0x2d0
[ 1960.792530]  ? pcibios_free_irq+0x10/0x10
[ 1960.792558]  ? kasan_check_write+0x14/0x20
[ 1960.792587]  device_release_driver_internal+0x35c/0x650
[ 1960.792617]  device_release_driver+0x12/0x20
[ 1960.792643]  pci_stop_bus_device+0x172/0x1e0
[ 1960.792671]  pci_stop_and_remove_bus_device_locked+0x1a/0x30
[ 1960.792715]  remove_store+0xcb/0xe0
[ 1960.792753]  ? sriov_numvfs_store+0x2e0/0x2e0
[ 1960.792779]  ? __lock_is_held+0xb5/0x140
[ 1960.792808]  ? component_add+0x530/0x530
[ 1960.792834]  dev_attr_store+0x3f/0x70
[ 1960.792859]  ? sysfs_file_ops+0x11d/0x170
[ 1960.792885]  sysfs_kf_write+0x104/0x150
[ 1960.792915]  ? sysfs_file_ops+0x170/0x170
[ 1960.792940]  kernfs_fop_write+0x24f/0x400
[ 1960.792978]  ? __lock_acquire+0x6ea/0x47f0
[ 1960.793021]  __vfs_write+0xeb/0x760
[ 1960.793048]  ? kernel_read+0x130/0x130
[ 1960.793076]  ? __lock_is_held+0xb5/0x140
[ 1960.793107]  ? rcu_read_lock_sched_held+0xdd/0x110
[ 1960.793135]  ? rcu_sync_lockdep_assert+0x78/0xb0
[ 1960.793162]  ? __sb_start_write+0x183/0x220
[ 1960.793189]  vfs_write+0x14d/0x4a0
[ 1960.793229]  ksys_write+0xd2/0x1b0
[ 1960.793255]  ? __ia32_sys_read+0xb0/0xb0
[ 1960.793298]  ? fput+0x1d/0x120
[ 1960.793324]  ? filp_close+0xf3/0x130
[ 1960.793349]  ? entry_SYSCALL_64_after_hwframe+0x59/0xbe
[ 1960.793380]  __x64_sys_write+0x73/0xb0
[ 1960.793407]  do_syscall_64+0xaa/0x400
[ 1960.793433]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 1960.793460] RIP: 0033:0x7f59df433164
[ 1960.793486] Code: 89 02 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 8d 05 81 38 2d 00 8b 00 85 c0 75 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 41 54 49 89 d4 55 48 89 f5 53
[ 1960.793541] RSP: 002b:00007ffd70ee2fb8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
[ 1960.793576] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007f59df433164
[ 1960.793620] RDX: 0000000000000002 RSI: 00005578088640c0 RDI: 0000000000000001
[ 1960.793665] RBP: 00005578088640c0 R08: 00007f59df7038c0 R09: 00007f59e0995b80
[ 1960.793696] R10: 000000000000000a R11: 0000000000000246 R12: 00007f59df702760
[ 1960.793730] R13: 0000000000000002 R14: 00007f59df6fd760 R15: 0000000000000002
[ 1960.793768]
[ 1960.793790] Allocated by task 11167:
[ 1960.793816]  save_stack+0x43/0xd0
[ 1960.793841]  kasan_kmalloc+0xc4/0xe0
[ 1960.793880]  kasan_slab_alloc+0x11/0x20
[ 1960.793905]  kmem_cache_alloc+0xd7/0x270
[ 1960.793944]  getname_flags+0xbd/0x520
[ 1960.793969]  user_path_at_empty+0x23/0x50
[ 1960.793994]  do_faccessat+0x1fc/0x5d0
[ 1960.794018]  __x64_sys_access+0x59/0x80
[ 1960.794043]  do_syscall_64+0xaa/0x400
[ 1960.794067]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 1960.794093]
[ 1960.794127] Freed by task 11167:
[ 1960.794152]  save_stack+0x43/0xd0
[ 1960.794190]  __kasan_slab_free+0x139/0x190
[ 1960.794215]  kasan_slab_free+0xe/0x10
[ 1960.794239]  kmem_cache_free+0xcb/0x2c0
[ 1960.794264]  putname+0xad/0xe0
[ 1960.794287]  filename_lookup.part.59+0x1f1/0x360
[ 1960.794313]  user_path_at_empty+0x3e/0x50
[ 1960.794338]  do_faccessat+0x1fc/0x5d0
[ 1960.794362]  __x64_sys_access+0x59/0x80
[ 1960.794393]  do_syscall_64+0xaa/0x400
[ 1960.794421]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 1960.794461]
[ 1960.794483] The buggy address belongs to the object at ffff88075acceac0
[ 1960.794483]  which belongs to the cache names_cache of size 4096
[ 1960.794540] The buggy address is located 2192 bytes inside of
[ 1960.794540]  4096-byte region [ffff88075acceac0, ffff88075accfac0)
[ 1960.794581] The buggy address belongs to the page:
[ 1960.794609] page:ffffea001d6b3200 count:1 mapcount:0 mapping:ffff880778e4b1c0 index:0x0 compound_mapcount: 0
[ 1960.794651] flags: 0x8000000000008100(slab|head)
[ 1960.794679] raw: 8000000000008100 ffffea001d39e808 ffffea001d39ea08 ffff880778e4b1c0
[ 1960.794739] raw: 0000000000000000 0000000000070007 00000001ffffffff 0000000000000000
[ 1960.794785] page dumped because: kasan: bad access detected
[ 1960.794813]
[ 1960.794834] Memory state around the buggy address:
[ 1960.794861]  ffff88075accf200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 1960.794894]  ffff88075accf280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 1960.794925] >ffff88075accf300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 1960.794956]                                                  ^
[ 1960.794985]  ffff88075accf380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 1960.795017]  ffff88075accf400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 1960.795061] ==================================================================
[ 1960.795106] Disabling lock debugging due to kernel taint
[ 1960.795131] ------------[ cut here ]------------
[ 1960.795148] ida_remove called for id=1802201963 which is not allocated.
[ 1960.795193] WARNING: CPU: 7 PID: 11185 at lib/idr.c:521 ida_remove+0x184/0x210
[ 1960.795213] Modules linked in: nouveau(O) mxm_wmi ttm i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm joydev vfat fat intel_rapl x86_pkg_temp_thermal coretemp crc32_pclmul iTCO_wdt psmouse wmi_bmof mei_me tpm_tis mei tpm_tis_core tpm i2c_i801 thinkpad_acpi pcc_cpufreq crc32c_intel serio_raw xhci_pci xhci_hcd wmi video i2c_dev i2c_core
[ 1960.795305] CPU: 7 PID: 11185 Comm: zsh Kdump: loaded Tainted: G    B      O      4.18.0Lyude-Test+ #4
[ 1960.795330] Hardware name: LENOVO 20EQS64N0B/20EQS64N0B, BIOS N1EET79W (1.52 ) 07/13/2018
[ 1960.795352] RIP: 0010:ida_remove+0x184/0x210
[ 1960.795370] Code: 4c 89 f7 e8 ae c8 00 00 eb 22 41 83 c4 02 4c 89 e8 41 83 fc 3f 0f 86 64 ff ff ff 44 89 fe 48 c7 c7 20 94 1e 83 e8 54 ed 81 fe <0f> 0b 48 b8 00 00 00 00 00 fc ff df 48 01 c3 c7 03 00 00 00 00 c7
[ 1960.795402] RSP: 0018:ffff88074d4df7b8 EFLAGS: 00010082
[ 1960.795421] RAX: 0000000000000000 RBX: 1ffff100e9a9befa RCX: ffffffff81479975
[ 1960.795440] RDX: 0000000000000000 RSI: 0000000000000008 RDI: ffff88077c1de690
[ 1960.795460] RBP: ffff88074d4df878 R08: ffffed00ef83bcd3 R09: ffffed00ef83bcd2
[ 1960.795479] R10: ffffed00ef83bcd2 R11: ffff88077c1de697 R12: 000000000000036b
[ 1960.795498] R13: 0000000000000202 R14: ffffffffa0aa7fa0 R15: 000000006b6b6b6b
[ 1960.795518] FS:  00007f59e0995b80(0000) GS:ffff88077c1c0000(0000) knlGS:0000000000000000
[ 1960.795553] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1960.795571] CR2: 00007f59e09a2010 CR3: 00000004a1a70005 CR4: 00000000003606e0
[ 1960.795596] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 1960.795629] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 1960.795649] Call Trace:
[ 1960.795667]  ? ida_destroy+0x1d0/0x1d0
[ 1960.795686]  ? kasan_check_write+0x14/0x20
[ 1960.795704]  ? do_raw_spin_lock+0xc2/0x1c0
[ 1960.795724]  ida_simple_remove+0x26/0x40
[ 1960.795794]  nouveau_backlight_exit+0x9d/0x150 [nouveau]
[ 1960.795867]  nouveau_display_destroy+0x76/0x150 [nouveau]
[ 1960.795930]  nouveau_drm_device_fini+0xb7/0x190 [nouveau]
[ 1960.795989]  nouveau_drm_device_remove+0x14b/0x1d0 [nouveau]
[ 1960.796047]  ? nouveau_cli_work_queue+0x2e0/0x2e0 [nouveau]
[ 1960.796067]  ? trace_hardirqs_on_caller+0x38b/0x570
[ 1960.796089]  ? trace_hardirqs_on+0xd/0x10
[ 1960.796146]  nouveau_drm_remove+0x37/0x50 [nouveau]
[ 1960.796167]  pci_device_remove+0x112/0x2d0
[ 1960.796186]  ? pcibios_free_irq+0x10/0x10
[ 1960.796218]  ? kasan_check_write+0x14/0x20
[ 1960.796237]  device_release_driver_internal+0x35c/0x650
[ 1960.796257]  device_release_driver+0x12/0x20
[ 1960.796289]  pci_stop_bus_device+0x172/0x1e0
[ 1960.796308]  pci_stop_and_remove_bus_device_locked+0x1a/0x30
[ 1960.796328]  remove_store+0xcb/0xe0
[ 1960.796345]  ? sriov_numvfs_store+0x2e0/0x2e0
[ 1960.796364]  ? __lock_is_held+0xb5/0x140
[ 1960.796383]  ? component_add+0x530/0x530
[ 1960.796401]  dev_attr_store+0x3f/0x70
[ 1960.796419]  ? sysfs_file_ops+0x11d/0x170
[ 1960.796436]  sysfs_kf_write+0x104/0x150
[ 1960.796454]  ? sysfs_file_ops+0x170/0x170
[ 1960.796471]  kernfs_fop_write+0x24f/0x400
[ 1960.796488]  ? __lock_acquire+0x6ea/0x47f0
[ 1960.796520]  __vfs_write+0xeb/0x760
[ 1960.796538]  ? kernel_read+0x130/0x130
[ 1960.796556]  ? __lock_is_held+0xb5/0x140
[ 1960.796590]  ? rcu_read_lock_sched_held+0xdd/0x110
[ 1960.796608]  ? rcu_sync_lockdep_assert+0x78/0xb0
[ 1960.796626]  ? __sb_start_write+0x183/0x220
[ 1960.796648]  vfs_write+0x14d/0x4a0
[ 1960.796666]  ksys_write+0xd2/0x1b0
[ 1960.796684]  ? __ia32_sys_read+0xb0/0xb0
[ 1960.796701]  ? fput+0x1d/0x120
[ 1960.796732]  ? filp_close+0xf3/0x130
[ 1960.796749]  ? entry_SYSCALL_64_after_hwframe+0x59/0xbe
[ 1960.796768]  __x64_sys_write+0x73/0xb0
[ 1960.796800]  do_syscall_64+0xaa/0x400
[ 1960.796818]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 1960.796836] RIP: 0033:0x7f59df433164
[ 1960.796854] Code: 89 02 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 8d 05 81 38 2d 00 8b 00 85 c0 75 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 41 54 49 89 d4 55 48 89 f5 53
[ 1960.796884] RSP: 002b:00007ffd70ee2fb8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
[ 1960.796906] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007f59df433164
[ 1960.796926] RDX: 0000000000000002 RSI: 00005578088640c0 RDI: 0000000000000001
[ 1960.796946] RBP: 00005578088640c0 R08: 00007f59df7038c0 R09: 00007f59e0995b80
[ 1960.796966] R10: 000000000000000a R11: 0000000000000246 R12: 00007f59df702760
[ 1960.796985] R13: 0000000000000002 R14: 00007f59df6fd760 R15: 0000000000000002
[ 1960.797008] irq event stamp: 509990
[ 1960.797026] hardirqs last  enabled at (509989): [<ffffffff8119ff78>] flush_work+0x4b8/0x6d0
[ 1960.797063] hardirqs last disabled at (509990): [<ffffffff8297c395>] _raw_spin_lock_irqsave+0x25/0x60
[ 1960.797085] softirqs last  enabled at (509744): [<ffffffff82c005ad>] __do_softirq+0x5ad/0x8c0
[ 1960.797121] softirqs last disabled at (509735): [<ffffffff8115aa15>] irq_exit+0x1a5/0x1e0
[ 1960.797142] ---[ end trace fb1342325f1846b8 ]---

While I haven't actually gone into the details of what's causing this to
happen (maybe the kernel removes the backlight device in the device core
before we get to it?), it doesn't really matter anyway because the way
nouveau handles backlights has long since been deprecated.

According to the documentation on the drm_connector->late_register()
hook, the ->late_register() hook should be used for adding extra
connector-related devices. Vice versa, the ->early_unregister() hook is
meant to be used for removing those devices.

So: gut nouveau_drm->bl_list and nouveau_drm->backlight, and replace
them with per-connector backlight structures. Additionally, move
backlight registration/teardown into the ->late_register() and
->early_unregister() hooks so that DRM can give us a chance to remove
the backlight before the connector is even removed. This appears to fix
the problem once and for all.

Changes since v2:
- Use NV_INFO_ONCE for printing GMUX information, since otherwise this
  will end up printing that message for as many times as we have
  connectors

Signed-off-by: Lyude Paul <lyude@redhat.com>
Reviewed-by: Karol Herbst <kherbst@redhat.com>
---
 drivers/gpu/drm/nouveau/nouveau_backlight.c | 151 +++++++++++---------
 drivers/gpu/drm/nouveau/nouveau_connector.c |  20 +++
 drivers/gpu/drm/nouveau/nouveau_connector.h |  33 +++++
 drivers/gpu/drm/nouveau/nouveau_display.c   |   2 -
 drivers/gpu/drm/nouveau/nouveau_display.h   |  25 ----
 drivers/gpu/drm/nouveau/nouveau_drv.h       |   2 -
 6 files changed, 133 insertions(+), 100 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 6dd72bc32897..5d0694680f59 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -37,18 +37,19 @@
 #include "nouveau_drv.h"
 #include "nouveau_reg.h"
 #include "nouveau_encoder.h"
+#include "nouveau_connector.h"
 
 static struct ida bl_ida;
 #define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0'
 
-struct backlight_connector {
-	struct list_head head;
+struct nouveau_backlight {
+	struct backlight_device *dev;
 	int id;
 };
 
 static bool
-nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_connector
-		*connector)
+nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE],
+			   struct nouveau_backlight *bl)
 {
 	const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL);
 	if (nb < 0 || nb >= 100)
@@ -57,7 +58,7 @@ nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_c
 		snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb);
 	else
 		snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight");
-	connector->id = nb;
+	bl->id = nb;
 	return true;
 }
 
@@ -96,36 +97,45 @@ static int
 nv40_backlight_init(struct drm_connector *connector)
 {
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
+	struct nouveau_backlight *bl;
 	struct nvif_object *device = &drm->client.device.object;
 	struct backlight_properties props;
-	struct backlight_device *bd;
-	struct backlight_connector bl_connector;
 	char backlight_name[BL_NAME_SIZE];
+	int ret = 0;
 
 	if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
 		return 0;
 
+	bl = kzalloc(sizeof(*bl), GFP_KERNEL);
+	if (!bl)
+		return -ENOMEM;
+
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 31;
-	if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
+	if (!nouveau_get_backlight_name(backlight_name, bl)) {
 		NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
-		return 0;
+		goto fail_alloc;
 	}
-	bd = backlight_device_register(backlight_name , connector->kdev, drm,
-				       &nv40_bl_ops, &props);
 
-	if (IS_ERR(bd)) {
-		if (bl_connector.id >= 0)
-			ida_simple_remove(&bl_ida, bl_connector.id);
-		return PTR_ERR(bd);
+	bl->dev = backlight_device_register(backlight_name, connector->kdev,
+					    drm, &nv40_bl_ops, &props);
+	if (IS_ERR(bl->dev)) {
+		if (bl->id >= 0)
+			ida_simple_remove(&bl_ida, bl->id);
+
+		ret = PTR_ERR(bl->dev);
+		goto fail_alloc;
 	}
-	list_add(&bl_connector.head, &drm->bl_connectors);
-	drm->backlight = bd;
-	bd->props.brightness = nv40_get_intensity(bd);
-	backlight_update_status(bd);
+
+	nouveau_connector(connector)->backlight = bl;
+	bl->dev->props.brightness = nv40_get_intensity(bl->dev);
+	backlight_update_status(bl->dev);
 
 	return 0;
+fail_alloc:
+	kfree(bl);
+	return ret;
 }
 
 static int
@@ -215,11 +225,11 @@ nv50_backlight_init(struct drm_connector *connector)
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
 	struct nvif_object *device = &drm->client.device.object;
 	struct nouveau_encoder *nv_encoder;
+	struct nouveau_backlight *bl;
 	struct backlight_properties props;
-	struct backlight_device *bd;
 	const struct backlight_ops *ops;
-	struct backlight_connector bl_connector;
 	char backlight_name[BL_NAME_SIZE];
+	int ret = 0;
 
 	nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
 	if (!nv_encoder) {
@@ -231,6 +241,10 @@ nv50_backlight_init(struct drm_connector *connector)
 	if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1)))
 		return 0;
 
+	bl = kzalloc(sizeof(*bl), GFP_KERNEL);
+	if (!bl)
+		return -ENOMEM;
+
 	if (drm->client.device.info.chipset <= 0xa0 ||
 	    drm->client.device.info.chipset == 0xaa ||
 	    drm->client.device.info.chipset == 0xac)
@@ -241,79 +255,74 @@ nv50_backlight_init(struct drm_connector *connector)
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 100;
-	if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
+	if (!nouveau_get_backlight_name(backlight_name, bl)) {
 		NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
-		return 0;
+		goto fail_alloc;
 	}
-	bd = backlight_device_register(backlight_name , connector->kdev,
-				       nv_encoder, ops, &props);
 
-	if (IS_ERR(bd)) {
-		if (bl_connector.id >= 0)
-			ida_simple_remove(&bl_ida, bl_connector.id);
-		return PTR_ERR(bd);
+	bl->dev = backlight_device_register(backlight_name, connector->kdev,
+					    nv_encoder, ops, &props);
+	if (IS_ERR(bl->dev)) {
+		if (bl->id >= 0)
+			ida_simple_remove(&bl_ida, bl->id);
+
+		ret = PTR_ERR(bl->dev);
+		goto fail_alloc;
 	}
 
-	list_add(&bl_connector.head, &drm->bl_connectors);
-	drm->backlight = bd;
-	bd->props.brightness = bd->ops->get_brightness(bd);
-	backlight_update_status(bd);
+	nouveau_connector(connector)->backlight = bl;
+	bl->dev->props.brightness = bl->dev->ops->get_brightness(bl->dev);
+	backlight_update_status(bl->dev);
 	return 0;
+
+fail_alloc:
+	kfree(bl);
+	return ret;
 }
 
 int
-nouveau_backlight_init(struct drm_device *dev)
+nouveau_backlight_init(struct drm_connector *connector)
 {
-	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nouveau_drm *drm = nouveau_drm(connector->dev);
 	struct nvif_device *device = &drm->client.device;
-	struct drm_connector *connector;
-	struct drm_connector_list_iter conn_iter;
-
-	INIT_LIST_HEAD(&drm->bl_connectors);
 
 	if (apple_gmux_present()) {
-		NV_INFO(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n");
+		NV_INFO_ONCE(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n");
 		return 0;
 	}
 
-	drm_connector_list_iter_begin(dev, &conn_iter);
-	drm_for_each_connector_iter(connector, &conn_iter) {
-		if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
-		    connector->connector_type != DRM_MODE_CONNECTOR_eDP)
-			continue;
-
-		switch (device->info.family) {
-		case NV_DEVICE_INFO_V0_CURIE:
-			return nv40_backlight_init(connector);
-		case NV_DEVICE_INFO_V0_TESLA:
-		case NV_DEVICE_INFO_V0_FERMI:
-		case NV_DEVICE_INFO_V0_KEPLER:
-		case NV_DEVICE_INFO_V0_MAXWELL:
-			return nv50_backlight_init(connector);
-		default:
-			break;
-		}
-	}
-	drm_connector_list_iter_end(&conn_iter);
+	if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
+	    connector->connector_type != DRM_MODE_CONNECTOR_eDP)
+		return 0;
 
-	return 0;
+	switch (device->info.family) {
+	case NV_DEVICE_INFO_V0_CURIE:
+		return nv40_backlight_init(connector);
+	case NV_DEVICE_INFO_V0_TESLA:
+	case NV_DEVICE_INFO_V0_FERMI:
+	case NV_DEVICE_INFO_V0_KEPLER:
+	case NV_DEVICE_INFO_V0_MAXWELL:
+		return nv50_backlight_init(connector);
+	default:
+		return 0;
+	}
 }
 
 void
-nouveau_backlight_exit(struct drm_device *dev)
+nouveau_backlight_exit(struct drm_connector *connector)
 {
-	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct backlight_connector *connector;
+	struct nouveau_connector *nv_conn = nouveau_connector(connector);
+	struct nouveau_backlight *bl = nv_conn->backlight;
 
-	list_for_each_entry(connector, &drm->bl_connectors, head) {
-		if (connector->id >= 0)
-			ida_simple_remove(&bl_ida, connector->id);
-	}
+	if (!bl)
+		return;
 
-	if (drm->backlight) {
-		backlight_device_unregister(drm->backlight);
-		drm->backlight = NULL;
-	}
+	if (bl->id >= 0)
+		ida_simple_remove(&bl_ida, bl->id);
+
+	backlight_device_unregister(bl->dev);
+	nv_conn->backlight = NULL;
+	kfree(bl);
 }
 
 void
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 247f72cc4d10..35c538f95167 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -882,6 +882,22 @@ nouveau_connector_detect_depth(struct drm_connector *connector)
 		connector->display_info.bpc = 8;
 }
 
+static int
+nouveau_connector_late_register(struct drm_connector *connector)
+{
+	int ret;
+
+	ret = nouveau_backlight_init(connector);
+
+	return ret;
+}
+
+static void
+nouveau_connector_early_unregister(struct drm_connector *connector)
+{
+	nouveau_backlight_exit(connector);
+}
+
 static int
 nouveau_connector_get_modes(struct drm_connector *connector)
 {
@@ -1066,6 +1082,8 @@ nouveau_connector_funcs = {
 	.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
 	.atomic_set_property = nouveau_conn_atomic_set_property,
 	.atomic_get_property = nouveau_conn_atomic_get_property,
+	.late_register = nouveau_connector_late_register,
+	.early_unregister = nouveau_connector_early_unregister,
 };
 
 static const struct drm_connector_funcs
@@ -1081,6 +1099,8 @@ nouveau_connector_funcs_lvds = {
 	.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
 	.atomic_set_property = nouveau_conn_atomic_set_property,
 	.atomic_get_property = nouveau_conn_atomic_get_property,
+	.late_register = nouveau_connector_late_register,
+	.early_unregister = nouveau_connector_early_unregister,
 };
 
 static int
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index dc7454e7f19a..aefc3cbf8098 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -37,6 +37,10 @@
 
 struct nvkm_i2c_port;
 
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+struct nouveau_backlight;
+#endif
+
 struct nouveau_connector {
 	struct drm_connector base;
 	enum dcb_connector_type type;
@@ -53,6 +57,9 @@ struct nouveau_connector {
 	struct nouveau_encoder *detected_encoder;
 	struct edid *edid;
 	struct drm_display_mode *native_mode;
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+	struct nouveau_backlight *backlight;
+#endif
 };
 
 static inline struct nouveau_connector *nouveau_connector(
@@ -179,4 +186,30 @@ int nouveau_conn_atomic_get_property(struct drm_connector *,
 				     const struct drm_connector_state *,
 				     struct drm_property *, u64 *);
 struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *);
+
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+extern int nouveau_backlight_init(struct drm_connector *);
+extern void nouveau_backlight_exit(struct drm_connector *);
+extern void nouveau_backlight_ctor(void);
+extern void nouveau_backlight_dtor(void);
+#else
+static inline int
+nouveau_backlight_init(struct drm_connector *connector)
+{
+	return 0;
+}
+
+static inline void
+nouveau_backlight_exit(struct drm_connector *connector) {
+}
+
+static inline void
+nouveau_backlight_ctor(void) {
+}
+
+static inline void
+nouveau_backlight_dtor(void) {
+}
+#endif
+
 #endif /* __NOUVEAU_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 540c0cbbfcee..f326ffd86766 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -582,7 +582,6 @@ nouveau_display_create(struct drm_device *dev)
 			goto vblank_err;
 	}
 
-	nouveau_backlight_init(dev);
 	INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work);
 #ifdef CONFIG_ACPI
 	drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy;
@@ -607,7 +606,6 @@ nouveau_display_destroy(struct drm_device *dev)
 #ifdef CONFIG_ACPI
 	unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb);
 #endif
-	nouveau_backlight_exit(dev);
 	nouveau_display_vblank_fini(dev);
 
 	drm_kms_helper_poll_fini(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index ff92b54ce448..eb77e41c2d4e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -85,31 +85,6 @@ int  nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
 
 void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *);
 
-#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
-extern int nouveau_backlight_init(struct drm_device *);
-extern void nouveau_backlight_exit(struct drm_device *);
-extern void nouveau_backlight_ctor(void);
-extern void nouveau_backlight_dtor(void);
-#else
-static inline int
-nouveau_backlight_init(struct drm_device *dev)
-{
-	return 0;
-}
-
-static inline void
-nouveau_backlight_exit(struct drm_device *dev) {
-}
-
-static inline void
-nouveau_backlight_ctor(void) {
-}
-
-static inline void
-nouveau_backlight_dtor(void) {
-}
-#endif
-
 struct drm_framebuffer *
 nouveau_user_framebuffer_create(struct drm_device *, struct drm_file *,
 				const struct drm_mode_fb_cmd2 *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index d9d687916553..0b2191fa96f7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -194,8 +194,6 @@ struct nouveau_drm {
 	/* modesetting */
 	struct nvbios vbios;
 	struct nouveau_display *display;
-	struct backlight_device *backlight;
-	struct list_head bl_connectors;
 	struct work_struct hpd_work;
 	struct work_struct fbcon_work;
 	int fbcon_new_state;
-- 
2.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 4/6] drm/nouveau: s/nouveau_backlight_exit/nouveau_backlight_fini/
  2018-09-06 21:43 ` Lyude Paul
@ 2018-09-06 21:43   ` Lyude Paul
  -1 siblings, 0 replies; 13+ messages in thread
From: Lyude Paul @ 2018-09-06 21:43 UTC (permalink / raw)
  To: nouveau; +Cc: Ben Skeggs, David Airlie, dri-devel, linux-kernel

More consistent with the rest of the codebase, no functional changes
here.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Reviewed-by: Karol Herbst <kherbst@redhat.com>
---
 drivers/gpu/drm/nouveau/nouveau_backlight.c | 2 +-
 drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +-
 drivers/gpu/drm/nouveau/nouveau_connector.h | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 5d0694680f59..f4400a6408b4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -309,7 +309,7 @@ nouveau_backlight_init(struct drm_connector *connector)
 }
 
 void
-nouveau_backlight_exit(struct drm_connector *connector)
+nouveau_backlight_fini(struct drm_connector *connector)
 {
 	struct nouveau_connector *nv_conn = nouveau_connector(connector);
 	struct nouveau_backlight *bl = nv_conn->backlight;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 35c538f95167..1c0630bd13a3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -895,7 +895,7 @@ nouveau_connector_late_register(struct drm_connector *connector)
 static void
 nouveau_connector_early_unregister(struct drm_connector *connector)
 {
-	nouveau_backlight_exit(connector);
+	nouveau_backlight_fini(connector);
 }
 
 static int
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index aefc3cbf8098..4de597ce60d0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -189,7 +189,7 @@ struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *);
 
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
 extern int nouveau_backlight_init(struct drm_connector *);
-extern void nouveau_backlight_exit(struct drm_connector *);
+extern void nouveau_backlight_fini(struct drm_connector *);
 extern void nouveau_backlight_ctor(void);
 extern void nouveau_backlight_dtor(void);
 #else
@@ -200,7 +200,7 @@ nouveau_backlight_init(struct drm_connector *connector)
 }
 
 static inline void
-nouveau_backlight_exit(struct drm_connector *connector) {
+nouveau_backlight_fini(struct drm_connector *connector) {
 }
 
 static inline void
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 4/6] drm/nouveau: s/nouveau_backlight_exit/nouveau_backlight_fini/
@ 2018-09-06 21:43   ` Lyude Paul
  0 siblings, 0 replies; 13+ messages in thread
From: Lyude Paul @ 2018-09-06 21:43 UTC (permalink / raw)
  To: nouveau; +Cc: David Airlie, Ben Skeggs, dri-devel, linux-kernel

More consistent with the rest of the codebase, no functional changes
here.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Reviewed-by: Karol Herbst <kherbst@redhat.com>
---
 drivers/gpu/drm/nouveau/nouveau_backlight.c | 2 +-
 drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +-
 drivers/gpu/drm/nouveau/nouveau_connector.h | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 5d0694680f59..f4400a6408b4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -309,7 +309,7 @@ nouveau_backlight_init(struct drm_connector *connector)
 }
 
 void
-nouveau_backlight_exit(struct drm_connector *connector)
+nouveau_backlight_fini(struct drm_connector *connector)
 {
 	struct nouveau_connector *nv_conn = nouveau_connector(connector);
 	struct nouveau_backlight *bl = nv_conn->backlight;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 35c538f95167..1c0630bd13a3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -895,7 +895,7 @@ nouveau_connector_late_register(struct drm_connector *connector)
 static void
 nouveau_connector_early_unregister(struct drm_connector *connector)
 {
-	nouveau_backlight_exit(connector);
+	nouveau_backlight_fini(connector);
 }
 
 static int
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index aefc3cbf8098..4de597ce60d0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -189,7 +189,7 @@ struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *);
 
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
 extern int nouveau_backlight_init(struct drm_connector *);
-extern void nouveau_backlight_exit(struct drm_connector *);
+extern void nouveau_backlight_fini(struct drm_connector *);
 extern void nouveau_backlight_ctor(void);
 extern void nouveau_backlight_dtor(void);
 #else
@@ -200,7 +200,7 @@ nouveau_backlight_init(struct drm_connector *connector)
 }
 
 static inline void
-nouveau_backlight_exit(struct drm_connector *connector) {
+nouveau_backlight_fini(struct drm_connector *connector) {
 }
 
 static inline void
-- 
2.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 5/6] drm/nouveau: Cleanup indenting in nouveau_backlight.c
  2018-09-06 21:43 ` Lyude Paul
                   ` (4 preceding siblings ...)
  (?)
@ 2018-09-06 21:43 ` Lyude Paul
  -1 siblings, 0 replies; 13+ messages in thread
From: Lyude Paul @ 2018-09-06 21:43 UTC (permalink / raw)
  To: nouveau; +Cc: Ben Skeggs, David Airlie, dri-devel, linux-kernel

Still no functional changes.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Reviewed-by: Karol Herbst <kherbst@redhat.com>
---
 drivers/gpu/drm/nouveau/nouveau_backlight.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index f4400a6408b4..01d08acac2f0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -68,7 +68,7 @@ nv40_get_intensity(struct backlight_device *bd)
 	struct nouveau_drm *drm = bl_get_data(bd);
 	struct nvif_object *device = &drm->client.device.object;
 	int val = (nvif_rd32(device, NV40_PMC_BACKLIGHT) &
-				   NV40_PMC_BACKLIGHT_MASK) >> 16;
+		   NV40_PMC_BACKLIGHT_MASK) >> 16;
 
 	return val;
 }
@@ -82,7 +82,7 @@ nv40_set_intensity(struct backlight_device *bd)
 	int reg = nvif_rd32(device, NV40_PMC_BACKLIGHT);
 
 	nvif_wr32(device, NV40_PMC_BACKLIGHT,
-		 (val << 16) | (reg & ~NV40_PMC_BACKLIGHT_MASK));
+		  (val << 16) | (reg & ~NV40_PMC_BACKLIGHT_MASK));
 
 	return 0;
 }
@@ -164,7 +164,7 @@ nv50_set_intensity(struct backlight_device *bd)
 	u32 val = (bd->props.brightness * div) / 100;
 
 	nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
-			NV50_PDISP_SOR_PWM_CTL_NEW | val);
+		  NV50_PDISP_SOR_PWM_CTL_NEW | val);
 	return 0;
 }
 
@@ -204,9 +204,10 @@ nva3_set_intensity(struct backlight_device *bd)
 	div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
 	val = (bd->props.brightness * div) / 100;
 	if (div) {
-		nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or), val |
-				NV50_PDISP_SOR_PWM_CTL_NEW |
-				NVA3_PDISP_SOR_PWM_CTL_UNK);
+		nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
+			  val |
+			  NV50_PDISP_SOR_PWM_CTL_NEW |
+			  NVA3_PDISP_SOR_PWM_CTL_UNK);
 		return 0;
 	}
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 6/6] drm/nouveau: Refactor nvXX_backlight_init()
  2018-09-06 21:43 ` Lyude Paul
                   ` (5 preceding siblings ...)
  (?)
@ 2018-09-06 21:43 ` Lyude Paul
  -1 siblings, 0 replies; 13+ messages in thread
From: Lyude Paul @ 2018-09-06 21:43 UTC (permalink / raw)
  To: nouveau
  Cc: Jeffery Miller, Karol Herbst, Ben Skeggs, David Airlie,
	dri-devel, linux-kernel

There's literally no difference between any of the backlight init
functions besides the backlight properties they set and the backlight
callbacks that they set, so move all of the duplicated backlight init
code out of there and into nouveau_backlight_init().

This gets rid of a lot of copy pasta!

Changes since v1:
- Some of the pre-refactor callbacks were storing nv_encoder in callback
  data for the backlight devices that they registered, as opposed to
  nouveau_drm. This got missed and caused some bugs that didn't
  originally appear on my setup (NULL kernel derefs) for some reason.
  So, fix this by finding the nouveau_encoder in
  nouveau_backlight_init(), and using that as the callback data for all
  gens instead even if they don't care about the encoder.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Cc: Jeffery Miller <jmiller@neverware.com>
Cc: Karol Herbst <kherbst@redhat.com>
---
 drivers/gpu/drm/nouveau/nouveau_backlight.c | 160 +++++++++-----------
 1 file changed, 72 insertions(+), 88 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 01d08acac2f0..5f5be6368aed 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -65,7 +65,8 @@ nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE],
 static int
 nv40_get_intensity(struct backlight_device *bd)
 {
-	struct nouveau_drm *drm = bl_get_data(bd);
+	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+	struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
 	struct nvif_object *device = &drm->client.device.object;
 	int val = (nvif_rd32(device, NV40_PMC_BACKLIGHT) &
 		   NV40_PMC_BACKLIGHT_MASK) >> 16;
@@ -76,7 +77,8 @@ nv40_get_intensity(struct backlight_device *bd)
 static int
 nv40_set_intensity(struct backlight_device *bd)
 {
-	struct nouveau_drm *drm = bl_get_data(bd);
+	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+	struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
 	struct nvif_object *device = &drm->client.device.object;
 	int val = bd->props.brightness;
 	int reg = nvif_rd32(device, NV40_PMC_BACKLIGHT);
@@ -94,48 +96,20 @@ static const struct backlight_ops nv40_bl_ops = {
 };
 
 static int
-nv40_backlight_init(struct drm_connector *connector)
+nv40_backlight_init(struct nouveau_encoder *encoder,
+		    struct backlight_properties *props,
+		    const struct backlight_ops **ops)
 {
-	struct nouveau_drm *drm = nouveau_drm(connector->dev);
-	struct nouveau_backlight *bl;
+	struct nouveau_drm *drm = nouveau_drm(encoder->base.base.dev);
 	struct nvif_object *device = &drm->client.device.object;
-	struct backlight_properties props;
-	char backlight_name[BL_NAME_SIZE];
-	int ret = 0;
 
 	if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
-		return 0;
-
-	bl = kzalloc(sizeof(*bl), GFP_KERNEL);
-	if (!bl)
-		return -ENOMEM;
-
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.type = BACKLIGHT_RAW;
-	props.max_brightness = 31;
-	if (!nouveau_get_backlight_name(backlight_name, bl)) {
-		NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
-		goto fail_alloc;
-	}
-
-	bl->dev = backlight_device_register(backlight_name, connector->kdev,
-					    drm, &nv40_bl_ops, &props);
-	if (IS_ERR(bl->dev)) {
-		if (bl->id >= 0)
-			ida_simple_remove(&bl_ida, bl->id);
-
-		ret = PTR_ERR(bl->dev);
-		goto fail_alloc;
-	}
-
-	nouveau_connector(connector)->backlight = bl;
-	bl->dev->props.brightness = nv40_get_intensity(bl->dev);
-	backlight_update_status(bl->dev);
+		return -ENODEV;
 
+	props->type = BACKLIGHT_RAW;
+	props->max_brightness = 31;
+	*ops = &nv40_bl_ops;
 	return 0;
-fail_alloc:
-	kfree(bl);
-	return ret;
 }
 
 static int
@@ -221,92 +195,102 @@ static const struct backlight_ops nva3_bl_ops = {
 };
 
 static int
-nv50_backlight_init(struct drm_connector *connector)
+nv50_backlight_init(struct nouveau_encoder *nv_encoder,
+		    struct backlight_properties *props,
+		    const struct backlight_ops **ops)
 {
-	struct nouveau_drm *drm = nouveau_drm(connector->dev);
+	struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
 	struct nvif_object *device = &drm->client.device.object;
-	struct nouveau_encoder *nv_encoder;
-	struct nouveau_backlight *bl;
-	struct backlight_properties props;
-	const struct backlight_ops *ops;
-	char backlight_name[BL_NAME_SIZE];
-	int ret = 0;
-
-	nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
-	if (!nv_encoder) {
-		nv_encoder = find_encoder(connector, DCB_OUTPUT_DP);
-		if (!nv_encoder)
-			return -ENODEV;
-	}
 
 	if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1)))
-		return 0;
-
-	bl = kzalloc(sizeof(*bl), GFP_KERNEL);
-	if (!bl)
-		return -ENOMEM;
+		return -ENODEV;
 
 	if (drm->client.device.info.chipset <= 0xa0 ||
 	    drm->client.device.info.chipset == 0xaa ||
 	    drm->client.device.info.chipset == 0xac)
-		ops = &nv50_bl_ops;
+		*ops = &nv50_bl_ops;
 	else
-		ops = &nva3_bl_ops;
+		*ops = &nva3_bl_ops;
 
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.type = BACKLIGHT_RAW;
-	props.max_brightness = 100;
-	if (!nouveau_get_backlight_name(backlight_name, bl)) {
-		NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
-		goto fail_alloc;
-	}
+	props->type = BACKLIGHT_RAW;
+	props->max_brightness = 100;
 
-	bl->dev = backlight_device_register(backlight_name, connector->kdev,
-					    nv_encoder, ops, &props);
-	if (IS_ERR(bl->dev)) {
-		if (bl->id >= 0)
-			ida_simple_remove(&bl_ida, bl->id);
-
-		ret = PTR_ERR(bl->dev);
-		goto fail_alloc;
-	}
-
-	nouveau_connector(connector)->backlight = bl;
-	bl->dev->props.brightness = bl->dev->ops->get_brightness(bl->dev);
-	backlight_update_status(bl->dev);
 	return 0;
-
-fail_alloc:
-	kfree(bl);
-	return ret;
 }
 
 int
 nouveau_backlight_init(struct drm_connector *connector)
 {
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
+	struct nouveau_backlight *bl;
+	struct nouveau_encoder *nv_encoder = NULL;
 	struct nvif_device *device = &drm->client.device;
+	char backlight_name[BL_NAME_SIZE];
+	struct backlight_properties props = {0};
+	const struct backlight_ops *ops;
+	int ret;
 
 	if (apple_gmux_present()) {
 		NV_INFO_ONCE(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n");
 		return 0;
 	}
 
-	if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
-	    connector->connector_type != DRM_MODE_CONNECTOR_eDP)
+	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+		nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
+	else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+		nv_encoder = find_encoder(connector, DCB_OUTPUT_DP);
+	else
+		return 0;
+
+	if (!nv_encoder)
 		return 0;
 
 	switch (device->info.family) {
 	case NV_DEVICE_INFO_V0_CURIE:
-		return nv40_backlight_init(connector);
+		ret = nv40_backlight_init(nv_encoder, &props, &ops);
+		break;
 	case NV_DEVICE_INFO_V0_TESLA:
 	case NV_DEVICE_INFO_V0_FERMI:
 	case NV_DEVICE_INFO_V0_KEPLER:
 	case NV_DEVICE_INFO_V0_MAXWELL:
-		return nv50_backlight_init(connector);
+		ret = nv50_backlight_init(nv_encoder, &props, &ops);
+		break;
 	default:
 		return 0;
 	}
+
+	if (ret == -ENODEV)
+		return 0;
+	else if (ret)
+		return ret;
+
+	bl = kzalloc(sizeof(*bl), GFP_KERNEL);
+	if (!bl)
+		return -ENOMEM;
+
+	if (!nouveau_get_backlight_name(backlight_name, bl)) {
+		NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
+		goto fail_alloc;
+	}
+
+	bl->dev = backlight_device_register(backlight_name, connector->kdev,
+					    nv_encoder, ops, &props);
+	if (IS_ERR(bl->dev)) {
+		if (bl->id >= 0)
+			ida_simple_remove(&bl_ida, bl->id);
+		ret = PTR_ERR(bl->dev);
+		goto fail_alloc;
+	}
+
+	nouveau_connector(connector)->backlight = bl;
+	bl->dev->props.brightness = bl->dev->ops->get_brightness(bl->dev);
+	backlight_update_status(bl->dev);
+
+	return 0;
+
+fail_alloc:
+	kfree(bl);
+	return ret;
 }
 
 void
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 2/6] drm/nouveau: Add NV_PRINTK_ONCE and variants
  2018-09-06 21:43 ` [PATCH v4 2/6] drm/nouveau: Add NV_PRINTK_ONCE and variants Lyude Paul
@ 2018-09-07  5:35   ` Joe Perches
  2018-09-07 17:27       ` Lyude Paul
  0 siblings, 1 reply; 13+ messages in thread
From: Joe Perches @ 2018-09-07  5:35 UTC (permalink / raw)
  To: Lyude Paul, nouveau
  Cc: Karol Herbst, Ben Skeggs, David Airlie, dri-devel, linux-kernel

On Thu, 2018-09-06 at 17:43 -0400, Lyude Paul wrote:
> Since we're about to use this in nouveau_backlight.c. Same thing as
> DRM_WARN_ONCE, DRM_INFO_ONCE, etc...

Can you redefine this in terms of the patches I submitted
instead?

https://lore.kernel.org/patchwork/patch/979598/
https://lore.kernel.org/patchwork/patch/979601/


> Signed-off-by: Lyude Paul <lyude@redhat.com>
> Cc: Karol Herbst <kherbst@redhat.com>
> ---
>  drivers/gpu/drm/nouveau/nouveau_drv.h | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
> index 6e1acaec3400..d9d687916553 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
> @@ -244,10 +244,12 @@ void nouveau_drm_device_remove(struct drm_device *dev);
>  	struct nouveau_cli *_cli = (c);                                        \
>  	dev_##l(_cli->drm->dev->dev, "%s: "f, _cli->name, ##a);                \
>  } while(0)
> +
>  #define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a)
>  #define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a)
>  #define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a)
>  #define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a)
> +
>  #define NV_DEBUG(drm,f,a...) do {                                              \
>  	if (unlikely(drm_debug & DRM_UT_DRIVER))                               \
>  		NV_PRINTK(info, &(drm)->client, f, ##a);                       \
> @@ -257,6 +259,12 @@ void nouveau_drm_device_remove(struct drm_device *dev);
>  		NV_PRINTK(info, &(drm)->client, f, ##a);                       \
>  } while(0)
>  
> +#define NV_PRINTK_ONCE(l,c,f,a...) NV_PRINTK(l##_once,c,f, ##a)
> +
> +#define NV_ERROR_ONCE(drm,f,a...) NV_PRINTK_ONCE(err, &(drm)->client, f, ##a)
> +#define NV_WARN_ONCE(drm,f,a...) NV_PRINTK_ONCE(warn, &(drm)->client, f, ##a)
> +#define NV_INFO_ONCE(drm,f,a...) NV_PRINTK_ONCE(info, &(drm)->client, f, ##a)
> +
>  extern int nouveau_modeset;
>  
>  #endif

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 2/6] drm/nouveau: Add NV_PRINTK_ONCE and variants
@ 2018-09-07 17:27       ` Lyude Paul
  0 siblings, 0 replies; 13+ messages in thread
From: Lyude Paul @ 2018-09-07 17:27 UTC (permalink / raw)
  To: Joe Perches, nouveau
  Cc: Karol Herbst, Ben Skeggs, David Airlie, dri-devel, linux-kernel

On Thu, 2018-09-06 at 22:35 -0700, Joe Perches wrote:
> On Thu, 2018-09-06 at 17:43 -0400, Lyude Paul wrote:
> > Since we're about to use this in nouveau_backlight.c. Same thing as
> > DRM_WARN_ONCE, DRM_INFO_ONCE, etc...
> 
> Can you redefine this in terms of the patches I submitted
> instead?
> 
> https://lore.kernel.org/patchwork/patch/979598/
> https://lore.kernel.org/patchwork/patch/979601/

Unfortunately this patch series has already been merged:

https://github.com/skeggsb/nouveau/commit/c5082a8e3d84330140b9250692a3f4c38d7da3ea

So it is probably a better idea to do this the other way around and just
rebase your patches on top of that
> 
> 
> > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > Cc: Karol Herbst <kherbst@redhat.com>
> > ---
> >  drivers/gpu/drm/nouveau/nouveau_drv.h | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h
> > b/drivers/gpu/drm/nouveau/nouveau_drv.h
> > index 6e1acaec3400..d9d687916553 100644
> > --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
> > +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
> > @@ -244,10 +244,12 @@ void nouveau_drm_device_remove(struct drm_device
> > *dev);
> >  	struct nouveau_cli *_cli =
> > (c);                                        \
> >  	dev_##l(_cli->drm->dev->dev, "%s: "f, _cli->name,
> > ##a);                \
> >  } while(0)
> > +
> >  #define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a)
> >  #define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a)
> >  #define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a)
> >  #define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a)
> > +
> >  #define NV_DEBUG(drm,f,a...) do
> > {                                              \
> >  	if (unlikely(drm_debug &
> > DRM_UT_DRIVER))                               \
> >  		NV_PRINTK(info, &(drm)->client, f,
> > ##a);                       \
> > @@ -257,6 +259,12 @@ void nouveau_drm_device_remove(struct drm_device
> > *dev);
> >  		NV_PRINTK(info, &(drm)->client, f,
> > ##a);                       \
> >  } while(0)
> >  
> > +#define NV_PRINTK_ONCE(l,c,f,a...) NV_PRINTK(l##_once,c,f, ##a)
> > +
> > +#define NV_ERROR_ONCE(drm,f,a...) NV_PRINTK_ONCE(err, &(drm)->client, f,
> > ##a)
> > +#define NV_WARN_ONCE(drm,f,a...) NV_PRINTK_ONCE(warn, &(drm)->client, f,
> > ##a)
> > +#define NV_INFO_ONCE(drm,f,a...) NV_PRINTK_ONCE(info, &(drm)->client, f,
> > ##a)
> > +
> >  extern int nouveau_modeset;
> >  
> >  #endif
-- 
Cheers,
	Lyude Paul


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 2/6] drm/nouveau: Add NV_PRINTK_ONCE and variants
@ 2018-09-07 17:27       ` Lyude Paul
  0 siblings, 0 replies; 13+ messages in thread
From: Lyude Paul @ 2018-09-07 17:27 UTC (permalink / raw)
  To: Joe Perches, nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: David Airlie, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	Ben Skeggs, linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Thu, 2018-09-06 at 22:35 -0700, Joe Perches wrote:
> On Thu, 2018-09-06 at 17:43 -0400, Lyude Paul wrote:
> > Since we're about to use this in nouveau_backlight.c. Same thing as
> > DRM_WARN_ONCE, DRM_INFO_ONCE, etc...
> 
> Can you redefine this in terms of the patches I submitted
> instead?
> 
> https://lore.kernel.org/patchwork/patch/979598/
> https://lore.kernel.org/patchwork/patch/979601/

Unfortunately this patch series has already been merged:

https://github.com/skeggsb/nouveau/commit/c5082a8e3d84330140b9250692a3f4c38d7da3ea

So it is probably a better idea to do this the other way around and just
rebase your patches on top of that
> 
> 
> > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > Cc: Karol Herbst <kherbst@redhat.com>
> > ---
> >  drivers/gpu/drm/nouveau/nouveau_drv.h | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h
> > b/drivers/gpu/drm/nouveau/nouveau_drv.h
> > index 6e1acaec3400..d9d687916553 100644
> > --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
> > +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
> > @@ -244,10 +244,12 @@ void nouveau_drm_device_remove(struct drm_device
> > *dev);
> >  	struct nouveau_cli *_cli =
> > (c);                                        \
> >  	dev_##l(_cli->drm->dev->dev, "%s: "f, _cli->name,
> > ##a);                \
> >  } while(0)
> > +
> >  #define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a)
> >  #define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a)
> >  #define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a)
> >  #define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a)
> > +
> >  #define NV_DEBUG(drm,f,a...) do
> > {                                              \
> >  	if (unlikely(drm_debug &
> > DRM_UT_DRIVER))                               \
> >  		NV_PRINTK(info, &(drm)->client, f,
> > ##a);                       \
> > @@ -257,6 +259,12 @@ void nouveau_drm_device_remove(struct drm_device
> > *dev);
> >  		NV_PRINTK(info, &(drm)->client, f,
> > ##a);                       \
> >  } while(0)
> >  
> > +#define NV_PRINTK_ONCE(l,c,f,a...) NV_PRINTK(l##_once,c,f, ##a)
> > +
> > +#define NV_ERROR_ONCE(drm,f,a...) NV_PRINTK_ONCE(err, &(drm)->client, f,
> > ##a)
> > +#define NV_WARN_ONCE(drm,f,a...) NV_PRINTK_ONCE(warn, &(drm)->client, f,
> > ##a)
> > +#define NV_INFO_ONCE(drm,f,a...) NV_PRINTK_ONCE(info, &(drm)->client, f,
> > ##a)
> > +
> >  extern int nouveau_modeset;
> >  
> >  #endif
-- 
Cheers,
	Lyude Paul

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2018-09-07 17:27 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-06 21:43 [PATCH v4 0/6] Backlight fixes and cleanup Lyude Paul
2018-09-06 21:43 ` Lyude Paul
2018-09-06 21:43 ` [PATCH v4 1/6] drm/nouveau: Check backlight IDs are >= 0, not > 0 Lyude Paul
2018-09-06 21:43 ` [PATCH v4 2/6] drm/nouveau: Add NV_PRINTK_ONCE and variants Lyude Paul
2018-09-07  5:35   ` Joe Perches
2018-09-07 17:27     ` Lyude Paul
2018-09-07 17:27       ` Lyude Paul
2018-09-06 21:43 ` [PATCH v4 3/6] drm/nouveau: Move backlight device into nouveau_connector Lyude Paul
2018-09-06 21:43   ` Lyude Paul
2018-09-06 21:43 ` [PATCH v4 4/6] drm/nouveau: s/nouveau_backlight_exit/nouveau_backlight_fini/ Lyude Paul
2018-09-06 21:43   ` Lyude Paul
2018-09-06 21:43 ` [PATCH v4 5/6] drm/nouveau: Cleanup indenting in nouveau_backlight.c Lyude Paul
2018-09-06 21:43 ` [PATCH v4 6/6] drm/nouveau: Refactor nvXX_backlight_init() Lyude Paul

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.