Re: inteldrm/radeondrm suspend/resume diff
Mark Kettenis mark.kette...@xs4all.nl writes: The recent inteldrm suspend/resume regression thread pointed out that suspend/resume was quite horribly broken and only worked somewhat if you didn't heavily use the 3D acceleration stuff. Here's a diff that should fix most of the problems, by making sure userland programs are properly blocked if they try to use drm while we're suspending or resuming the machine. I would like to see this diff tested some more by people who actually use all that eye candy. The thing to watch for is hangs when you try to suspend your machine. Thanks, Mark P.S. This seems to make hibernation (ZZZ) work with both inteldrm(4) and radeondrm(4) on my t400. Index: drmP.h === RCS file: /cvs/src/sys/dev/pci/drm/drmP.h,v retrieving revision 1.169 diff -u -p -r1.169 drmP.h --- drmP.h9 Mar 2014 07:42:29 - 1.169 +++ drmP.h12 Mar 2014 21:38:43 - @@ -785,6 +785,10 @@ struct drm_device { bus_dma_tag_t dmat; bus_space_tag_t bst; + struct mutexquiesce_mtx; + int quiesce; + int quiesce_count; + char *unique; /* Unique identifier: e.g., busid */ int unique_len; /* Length of unique field */ Index: drm_drv.c === RCS file: /cvs/src/sys/dev/pci/drm/drm_drv.c,v retrieving revision 1.124 diff -u -p -r1.124 drm_drv.c --- drm_drv.c 9 Mar 2014 07:42:29 - 1.124 +++ drm_drv.c 12 Mar 2014 21:38:43 - @@ -63,8 +63,12 @@ int drm_lastclose(struct drm_device *); void drm_attach(struct device *, struct device *, void *); int drm_probe(struct device *, void *, void *); int drm_detach(struct device *, int); +void drm_quiesce(struct drm_device *); +void drm_wakeup(struct drm_device *); +int drm_activate(struct device *, int); int drmprint(void *, const char *); int drmsubmatch(struct device *, void *, void *); +int drm_do_ioctl(struct drm_device *, int, u_long, caddr_t); int drm_dequeue_event(struct drm_device *, struct drm_file *, size_t, struct drm_pending_event **); @@ -212,6 +216,7 @@ drm_attach(struct device *parent, struct rw_init(dev-dev_lock, drmdevlk); mtx_init(dev-event_lock, IPL_TTY); + mtx_init(dev-quiesce_mtx, IPL_NONE); TAILQ_INIT(dev-maplist); SPLAY_INIT(dev-files); @@ -293,9 +298,47 @@ drm_detach(struct device *self, int flag return 0; } +void +drm_quiesce(struct drm_device *dev) +{ + mtx_enter(dev-quiesce_mtx); + dev-quiesce = 1; + while (dev-quiesce_count 0) { + msleep(dev-quiesce_count, dev-quiesce_mtx, + PZERO, drmqui, 0); + } + mtx_leave(dev-quiesce_mtx); +} + +void +drm_wakeup(struct drm_device *dev) +{ + mtx_enter(dev-quiesce_mtx); + dev-quiesce = 0; + wakeup(dev-quiesce); + mtx_leave(dev-quiesce_mtx); +} + +int +drm_activate(struct device *self, int act) +{ + struct drm_device *dev = (struct drm_device *)self; + + switch (act) { + case DVACT_QUIESCE: + drm_quiesce(dev); + break; + case DVACT_WAKEUP: + drm_wakeup(dev); + break; + } + + return (0); +} + struct cfattach drm_ca = { sizeof(struct drm_device), drm_probe, drm_attach, - drm_detach + drm_detach, drm_activate }; struct cfdriver drm_cd = { @@ -540,20 +583,13 @@ done: return (retcode); } -/* drmioctl is called whenever a process performs an ioctl on /dev/drm. - */ int -drmioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, -struct proc *p) +drm_do_ioctl(struct drm_device *dev, int minor, u_long cmd, caddr_t data) { - struct drm_device *dev = drm_get_device_from_kdev(kdev); struct drm_file *file_priv; - if (dev == NULL) - return ENODEV; - DRM_LOCK(); - file_priv = drm_find_file_by_minor(dev, minor(kdev)); + file_priv = drm_find_file_by_minor(dev, minor); DRM_UNLOCK(); if (file_priv == NULL) { DRM_ERROR(can't find authenticator\n); @@ -715,6 +751,34 @@ drmioctl(dev_t kdev, u_long cmd, caddr_t return (EINVAL); } +/* drmioctl is called whenever a process performs an ioctl on /dev/drm. + */ +int +drmioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + struct drm_device *dev = drm_get_device_from_kdev(kdev); + int error; + + if (dev == NULL) + return ENODEV; + + mtx_enter(dev-quiesce_mtx); + while (dev-quiesce) + msleep(dev-quiesce, dev-quiesce_mtx, PZERO, drmioc, 0); + dev-quiesce_count++; + mtx_leave(dev-quiesce_mtx); + + error = drm_do_ioctl(dev, minor(kdev),
Re: inteldrm/radeondrm suspend/resume diff
Date: Wed, 12 Mar 2014 22:54:06 +0100 (CET) From: Mark Kettenis mark.kette...@xs4all.nl The recent inteldrm suspend/resume regression thread pointed out that suspend/resume was quite horribly broken and only worked somewhat if you didn't heavily use the 3D acceleration stuff. Here's a diff that should fix most of the problems, by making sure userland programs are properly blocked if they try to use drm while we're suspending or resuming the machine. I would like to see this diff tested some more by people who actually use all that eye candy. The thing to watch for is hangs when you try to suspend your machine. Thanks, Mark P.S. This seems to make hibernation (ZZZ) work with both inteldrm(4) and radeondrm(4) on my t400. Here's a slightly better diff that should eleminate a (largely theoretical) deadlock. If you didn't test yet, try this version instead. Index: drmP.h === RCS file: /home/cvs/src/sys/dev/pci/drm/drmP.h,v retrieving revision 1.169 diff -u -p -r1.169 drmP.h --- drmP.h 9 Mar 2014 07:42:29 - 1.169 +++ drmP.h 12 Mar 2014 22:06:11 - @@ -785,6 +785,10 @@ struct drm_device { bus_dma_tag_t dmat; bus_space_tag_t bst; + struct mutexquiesce_mtx; + int quiesce; + int quiesce_count; + char *unique; /* Unique identifier: e.g., busid */ int unique_len; /* Length of unique field */ Index: drm_drv.c === RCS file: /home/cvs/src/sys/dev/pci/drm/drm_drv.c,v retrieving revision 1.124 diff -u -p -r1.124 drm_drv.c --- drm_drv.c 9 Mar 2014 07:42:29 - 1.124 +++ drm_drv.c 13 Mar 2014 09:25:38 - @@ -63,8 +63,12 @@ int drm_lastclose(struct drm_device *); voiddrm_attach(struct device *, struct device *, void *); int drm_probe(struct device *, void *, void *); int drm_detach(struct device *, int); +voiddrm_quiesce(struct drm_device *); +voiddrm_wakeup(struct drm_device *); +int drm_activate(struct device *, int); int drmprint(void *, const char *); int drmsubmatch(struct device *, void *, void *); +int drm_do_ioctl(struct drm_device *, int, u_long, caddr_t); int drm_dequeue_event(struct drm_device *, struct drm_file *, size_t, struct drm_pending_event **); @@ -212,6 +216,7 @@ drm_attach(struct device *parent, struct rw_init(dev-dev_lock, drmdevlk); mtx_init(dev-event_lock, IPL_TTY); + mtx_init(dev-quiesce_mtx, IPL_NONE); TAILQ_INIT(dev-maplist); SPLAY_INIT(dev-files); @@ -293,9 +298,47 @@ drm_detach(struct device *self, int flag return 0; } +void +drm_quiesce(struct drm_device *dev) +{ + mtx_enter(dev-quiesce_mtx); + dev-quiesce = 1; + while (dev-quiesce_count 0) { + msleep(dev-quiesce_count, dev-quiesce_mtx, + PZERO, drmqui, 0); + } + mtx_leave(dev-quiesce_mtx); +} + +void +drm_wakeup(struct drm_device *dev) +{ + mtx_enter(dev-quiesce_mtx); + dev-quiesce = 0; + wakeup(dev-quiesce); + mtx_leave(dev-quiesce_mtx); +} + +int +drm_activate(struct device *self, int act) +{ + struct drm_device *dev = (struct drm_device *)self; + + switch (act) { + case DVACT_QUIESCE: + drm_quiesce(dev); + break; + case DVACT_WAKEUP: + drm_wakeup(dev); + break; + } + + return (0); +} + struct cfattach drm_ca = { sizeof(struct drm_device), drm_probe, drm_attach, - drm_detach + drm_detach, drm_activate }; struct cfdriver drm_cd = { @@ -540,20 +583,13 @@ done: return (retcode); } -/* drmioctl is called whenever a process performs an ioctl on /dev/drm. - */ int -drmioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, -struct proc *p) +drm_do_ioctl(struct drm_device *dev, int minor, u_long cmd, caddr_t data) { - struct drm_device *dev = drm_get_device_from_kdev(kdev); struct drm_file *file_priv; - if (dev == NULL) - return ENODEV; - DRM_LOCK(); - file_priv = drm_find_file_by_minor(dev, minor(kdev)); + file_priv = drm_find_file_by_minor(dev, minor); DRM_UNLOCK(); if (file_priv == NULL) { DRM_ERROR(can't find authenticator\n); @@ -715,6 +751,34 @@ drmioctl(dev_t kdev, u_long cmd, caddr_t return (EINVAL); } +/* drmioctl is called whenever a process performs an ioctl on /dev/drm. + */ +int +drmioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + struct drm_device *dev = drm_get_device_from_kdev(kdev); + int error; + + if (dev == NULL) + return ENODEV; + + mtx_enter(dev-quiesce_mtx); + while
Re: inteldrm/radeondrm suspend/resume diff
On Thu, Mar 13, 2014 at 10:31:18AM +0100, Mark Kettenis wrote: [...] P.S. This seems to make hibernation (ZZZ) work with both inteldrm(4) and radeondrm(4) on my t400. Here's a slightly better diff that should eleminate a (largely theoretical) deadlock. If you didn't test yet, try this version instead. [...] Suspend (to RAM) and resume works fine here with vga1 at pci0 dev 2 function 0 Intel GM965 Video rev 0x0c Couldn't test hibernate yet because my system has root on a softraid crypto device and the swap is outside the crypto area. -- Gregor Best
Re: inteldrm/radeondrm suspend/resume diff
On Thu, Mar 13, 2014 at 11:16:42AM +0100, Gregor Best wrote: [...] Couldn't test hibernate yet because my system has root on a softraid crypto device and the swap is outside the crypto area. [...] David gave me a hint on how to hardwire my kernel for swap on sd0b. With that, hibernate works slowly, but it works. The full hibernate + resume cycle takes about one or two minutes, which I guess is fine. I'm not sure whether hibernation working is a direct consequence of this diff, but I think that's OK since the diff didn't break it either. -- Gregor Best
Re: inteldrm/radeondrm suspend/resume diff
On 03/13/14 10:31, Mark Kettenis wrote: Date: Wed, 12 Mar 2014 22:54:06 +0100 (CET) From: Mark Kettenis mark.kette...@xs4all.nl The recent inteldrm suspend/resume regression thread pointed out that suspend/resume was quite horribly broken and only worked somewhat if you didn't heavily use the 3D acceleration stuff. Here's a diff that should fix most of the problems, by making sure userland programs are properly blocked if they try to use drm while we're suspending or resuming the machine. I would like to see this diff tested some more by people who actually use all that eye candy. The thing to watch for is hangs when you try to suspend your machine. Thanks, Mark P.S. This seems to make hibernation (ZZZ) work with both inteldrm(4) and radeondrm(4) on my t400. Here's a slightly better diff that should eleminate a (largely theoretical) deadlock. If you didn't test yet, try this version instead. suspend/resume is working. After waking up, Jira in Chrome is no more dead slow, as it was before. Hibernating is not working at all at my T530 (crypto softraid on SSD with Swap inside the softraid). I don't know, if it was working before, but i usually use suspend. Maybe my swap partition (16G) is to few for the RAM, didn't really check yet. dmesg below. Marc dmesg: OpenBSD 5.5-current (GENERIC.MP) #0: Thu Mar 13 11:14:31 CET 2014 root@trivago-620.trivago.local:/usr/src/sys/arch/amd64/compile/GENERIC.MP real mem = 16845565952 (16065MB) avail mem = 16388415488 (15629MB) mainbus0 at root bios0 at mainbus0: SMBIOS rev. 2.7 @ 0xdae9d000 (68 entries) bios0: vendor LENOVO version G4ET97WW (2.57 ) date 10/17/2013 bios0: LENOVO 24297TG acpi0 at bios0: rev 2 acpi0: sleep states S0 S3 S4 S5 acpi0: tables DSDT FACP SLIC TCPA SSDT SSDT SSDT HPET APIC MCFG ECDT FPDT ASF! UEFI UEFI MSDM SSDT SSDT UEFI DBG2 acpi0: wakeup devices LID_(S4) SLPB(S3) IGBE(S4) EXP3(S4) XHCI(S3) EHC1(S3) EHC2(S3) HDEF(S4) acpitimer0 at acpi0: 3579545 Hz, 24 bits acpihpet0 at acpi0: 14318179 Hz acpimadt0 at acpi0 addr 0xfee0: PC-AT compat cpu0 at mainbus0: apid 0 (boot processor) cpu0: Intel(R) Core(TM) i5-3230M CPU @ 2.60GHz, 2594.58 MHz cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,LONG,LAHF,PERF,ITSC,FSGSBASE,SMEP,ERMS cpu0: 256KB 64b/line 8-way L2 cache cpu0: smt 0, core 0, package 0 mtrr: Pentium Pro MTRR support, 10 var ranges, 88 fixed ranges cpu0: apic clock running at 99MHz cpu0: mwait min=64, max=64, C-substates=0.2.1.1.2, IBE cpu1 at mainbus0: apid 1 (application processor) cpu1: Intel(R) Core(TM) i5-3230M CPU @ 2.60GHz, 2594.11 MHz cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,LONG,LAHF,PERF,ITSC,FSGSBASE,SMEP,ERMS cpu1: 256KB 64b/line 8-way L2 cache cpu1: smt 1, core 0, package 0 cpu2 at mainbus0: apid 2 (application processor) cpu2: Intel(R) Core(TM) i5-3230M CPU @ 2.60GHz, 2594.11 MHz cpu2: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,LONG,LAHF,PERF,ITSC,FSGSBASE,SMEP,ERMS cpu2: 256KB 64b/line 8-way L2 cache cpu2: smt 0, core 1, package 0 cpu3 at mainbus0: apid 3 (application processor) cpu3: Intel(R) Core(TM) i5-3230M CPU @ 2.60GHz, 2594.11 MHz cpu3: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,LONG,LAHF,PERF,ITSC,FSGSBASE,SMEP,ERMS cpu3: 256KB 64b/line 8-way L2 cache cpu3: smt 1, core 1, package 0 ioapic0 at mainbus0: apid 2 pa 0xfec0, version 20, 24 pins acpimcfg0 at acpi0 addr 0xf800, bus 0-63 acpiec0 at acpi0 acpiprt0 at acpi0: bus 0 (PCI0) acpiprt1 at acpi0: bus -1 (PEG_) acpiprt2 at acpi0: bus 2 (EXP1) acpiprt3 at acpi0: bus 3 (EXP2) acpiprt4 at acpi0: bus 4 (EXP3) acpicpu0 at acpi0: C2, C1, PSS acpicpu1 at acpi0: C2, C1, PSS acpicpu2 at acpi0: C2, C1, PSS acpicpu3 at acpi0: C2, C1, PSS acpipwrres0 at acpi0: PUBS, resource for XHCI, EHC1, EHC2 acpitz0 at acpi0: critical temperature is 103 degC acpibtn0 at acpi0: LID_ acpibtn1 at acpi0: SLPB acpibat0 at acpi0: BAT0 model 45N1001 serial 27100 type LION oem SANYO acpibat1 at acpi0: BAT1 not present acpiac0 at acpi0: AC unit online acpithinkpad0 at acpi0 cpu0: Enhanced SpeedStep 2594 MHz: speeds: 2601, 2600, 2500, 2400, 2300, 2200, 2100, 2000, 1900, 1800, 1700, 1600, 1500, 1400, 1300, 1200 MHz pci0 at
Re: inteldrm/radeondrm suspend/resume diff
On Thu, Mar 13, 2014 at 11:53 AM, Gregor Best g...@ring0.de wrote: On Thu, Mar 13, 2014 at 11:16:42AM +0100, Gregor Best wrote: [...] Couldn't test hibernate yet because my system has root on a softraid crypto device and the swap is outside the crypto area. [...] David gave me a hint on how to hardwire my kernel for swap on sd0b. With that, hibernate works slowly, but it works. The full hibernate + resume cycle takes about one or two minutes, which I guess is fine. I'm not sure whether hibernation working is a direct consequence of this diff, but I think that's OK since the diff didn't break it either. I currently have a regression with hibernate (reboot during resume, it was working fine before). I will test tonight if Mark's diff unbreaks it... Ciao, David
Re: inteldrm/radeondrm suspend/resume diff
On Thu, Mar 13, 2014 at 12:23 PM, Marc Peters m...@mpeters.org wrote: On 03/13/14 10:31, Mark Kettenis wrote: Date: Wed, 12 Mar 2014 22:54:06 +0100 (CET) From: Mark Kettenis mark.kette...@xs4all.nl The recent inteldrm suspend/resume regression thread pointed out that suspend/resume was quite horribly broken and only worked somewhat if you didn't heavily use the 3D acceleration stuff. Here's a diff that should fix most of the problems, by making sure userland programs are properly blocked if they try to use drm while we're suspending or resuming the machine. I would like to see this diff tested some more by people who actually use all that eye candy. The thing to watch for is hangs when you try to suspend your machine. Thanks, Mark P.S. This seems to make hibernation (ZZZ) work with both inteldrm(4) and radeondrm(4) on my t400. Here's a slightly better diff that should eleminate a (largely theoretical) deadlock. If you didn't test yet, try this version instead. suspend/resume is working. After waking up, Jira in Chrome is no more dead slow, as it was before. Hibernating is not working at all at my T530 (crypto softraid on SSD with Swap inside the softraid). I don't know, if it was working before, but i usually use suspend. Maybe my swap partition (16G) is to few for the RAM, didn't really check yet. This patch also fixes the problem for me. After multiple suspend/resume cycles, X no longer eats the CPU on my T510 with: vga1 at pci0 dev 2 function 0 Intel HD Graphics rev 0x02 intagp0 at vga1 agp0 at intagp0: aperture at 0xd000, size 0x1000 inteldrm0 at vga1 drm0 at inteldrm0 inteldrm0: 1366x768
Re: inteldrm/radeondrm suspend/resume diff
On Thu, Mar 13, 2014 at 12:31 PM, David Coppa dco...@gmail.com wrote: On Thu, Mar 13, 2014 at 11:53 AM, Gregor Best g...@ring0.de wrote: On Thu, Mar 13, 2014 at 11:16:42AM +0100, Gregor Best wrote: [...] Couldn't test hibernate yet because my system has root on a softraid crypto device and the swap is outside the crypto area. [...] David gave me a hint on how to hardwire my kernel for swap on sd0b. With that, hibernate works slowly, but it works. The full hibernate + resume cycle takes about one or two minutes, which I guess is fine. I'm not sure whether hibernation working is a direct consequence of this diff, but I think that's OK since the diff didn't break it either. I currently have a regression with hibernate (reboot during resume, it was working fine before). I will test tonight if Mark's diff unbreaks it... I confirm this diff fixed my regression with ZZZ. Thanks a lot, Mark. Ciao! David
inteldrm/radeondrm suspend/resume diff
The recent inteldrm suspend/resume regression thread pointed out that suspend/resume was quite horribly broken and only worked somewhat if you didn't heavily use the 3D acceleration stuff. Here's a diff that should fix most of the problems, by making sure userland programs are properly blocked if they try to use drm while we're suspending or resuming the machine. I would like to see this diff tested some more by people who actually use all that eye candy. The thing to watch for is hangs when you try to suspend your machine. Thanks, Mark P.S. This seems to make hibernation (ZZZ) work with both inteldrm(4) and radeondrm(4) on my t400. Index: drmP.h === RCS file: /cvs/src/sys/dev/pci/drm/drmP.h,v retrieving revision 1.169 diff -u -p -r1.169 drmP.h --- drmP.h 9 Mar 2014 07:42:29 - 1.169 +++ drmP.h 12 Mar 2014 21:38:43 - @@ -785,6 +785,10 @@ struct drm_device { bus_dma_tag_t dmat; bus_space_tag_t bst; + struct mutexquiesce_mtx; + int quiesce; + int quiesce_count; + char *unique; /* Unique identifier: e.g., busid */ int unique_len; /* Length of unique field */ Index: drm_drv.c === RCS file: /cvs/src/sys/dev/pci/drm/drm_drv.c,v retrieving revision 1.124 diff -u -p -r1.124 drm_drv.c --- drm_drv.c 9 Mar 2014 07:42:29 - 1.124 +++ drm_drv.c 12 Mar 2014 21:38:43 - @@ -63,8 +63,12 @@ int drm_lastclose(struct drm_device *); voiddrm_attach(struct device *, struct device *, void *); int drm_probe(struct device *, void *, void *); int drm_detach(struct device *, int); +voiddrm_quiesce(struct drm_device *); +voiddrm_wakeup(struct drm_device *); +int drm_activate(struct device *, int); int drmprint(void *, const char *); int drmsubmatch(struct device *, void *, void *); +int drm_do_ioctl(struct drm_device *, int, u_long, caddr_t); int drm_dequeue_event(struct drm_device *, struct drm_file *, size_t, struct drm_pending_event **); @@ -212,6 +216,7 @@ drm_attach(struct device *parent, struct rw_init(dev-dev_lock, drmdevlk); mtx_init(dev-event_lock, IPL_TTY); + mtx_init(dev-quiesce_mtx, IPL_NONE); TAILQ_INIT(dev-maplist); SPLAY_INIT(dev-files); @@ -293,9 +298,47 @@ drm_detach(struct device *self, int flag return 0; } +void +drm_quiesce(struct drm_device *dev) +{ + mtx_enter(dev-quiesce_mtx); + dev-quiesce = 1; + while (dev-quiesce_count 0) { + msleep(dev-quiesce_count, dev-quiesce_mtx, + PZERO, drmqui, 0); + } + mtx_leave(dev-quiesce_mtx); +} + +void +drm_wakeup(struct drm_device *dev) +{ + mtx_enter(dev-quiesce_mtx); + dev-quiesce = 0; + wakeup(dev-quiesce); + mtx_leave(dev-quiesce_mtx); +} + +int +drm_activate(struct device *self, int act) +{ + struct drm_device *dev = (struct drm_device *)self; + + switch (act) { + case DVACT_QUIESCE: + drm_quiesce(dev); + break; + case DVACT_WAKEUP: + drm_wakeup(dev); + break; + } + + return (0); +} + struct cfattach drm_ca = { sizeof(struct drm_device), drm_probe, drm_attach, - drm_detach + drm_detach, drm_activate }; struct cfdriver drm_cd = { @@ -540,20 +583,13 @@ done: return (retcode); } -/* drmioctl is called whenever a process performs an ioctl on /dev/drm. - */ int -drmioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, -struct proc *p) +drm_do_ioctl(struct drm_device *dev, int minor, u_long cmd, caddr_t data) { - struct drm_device *dev = drm_get_device_from_kdev(kdev); struct drm_file *file_priv; - if (dev == NULL) - return ENODEV; - DRM_LOCK(); - file_priv = drm_find_file_by_minor(dev, minor(kdev)); + file_priv = drm_find_file_by_minor(dev, minor); DRM_UNLOCK(); if (file_priv == NULL) { DRM_ERROR(can't find authenticator\n); @@ -715,6 +751,34 @@ drmioctl(dev_t kdev, u_long cmd, caddr_t return (EINVAL); } +/* drmioctl is called whenever a process performs an ioctl on /dev/drm. + */ +int +drmioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + struct drm_device *dev = drm_get_device_from_kdev(kdev); + int error; + + if (dev == NULL) + return ENODEV; + + mtx_enter(dev-quiesce_mtx); + while (dev-quiesce) + msleep(dev-quiesce, dev-quiesce_mtx, PZERO, drmioc, 0); + dev-quiesce_count++; + mtx_leave(dev-quiesce_mtx); + + error = drm_do_ioctl(dev, minor(kdev), cmd, data); + + mtx_enter(dev-quiesce_mtx); +