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.h 9 Mar 2014 07:42:29 -0000 1.169 > +++ drmP.h 12 Mar 2014 21:38:43 -0000 > @@ -785,6 +785,10 @@ struct drm_device { > bus_dma_tag_t dmat; > bus_space_tag_t bst; > > + struct mutex quiesce_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 -0000 1.124 > +++ drm_drv.c 12 Mar 2014 21:38:43 -0000 > @@ -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), cmd, data); > + > + mtx_enter(&dev->quiesce_mtx); > + dev->quiesce_count--; > + if (dev->quiesce) > + wakeup(&dev->quiesce); > + mtx_leave(&dev->quiesce_mtx); > + > + return (error); > +} > + > int > drmread(dev_t kdev, struct uio *uio, int ioflag) > { > @@ -1224,10 +1288,26 @@ drm_fault(struct uvm_faultinfo *ufi, vad > return(VM_PAGER_ERROR); > } > > + mtx_enter(&dev->quiesce_mtx); > + if (dev->quiesce) { > + mtx_leave(&dev->quiesce_mtx); > + uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap, uobj, NULL); > + return(VM_PAGER_OK); > + } > + dev->quiesce_count++; > + mtx_leave(&dev->quiesce_mtx); > + > /* Call down into driver to do the magic */ > ret = dev->driver->gem_fault(obj, ufi, entry->offset + (vaddr - > entry->start), vaddr, pps, npages, centeridx, > access_type, flags); > + > + mtx_enter(&dev->quiesce_mtx); > + dev->quiesce_count--; > + if (dev->quiesce) > + wakeup(&dev->quiesce); > + mtx_leave(&dev->quiesce_mtx); > + > return (ret); > } > > Index: i915/i915_drv.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_drv.c,v > retrieving revision 1.63 > diff -u -p -r1.63 i915_drv.c > --- i915/i915_drv.c 23 Feb 2014 09:36:52 -0000 1.63 > +++ i915/i915_drv.c 12 Mar 2014 21:38:43 -0000 > @@ -1113,24 +1113,29 @@ inteldrm_detach(struct device *self, int > } > > int > -inteldrm_activate(struct device *arg, int act) > +inteldrm_activate(struct device *self, int act) > { > - struct inteldrm_softc *dev_priv = (struct inteldrm_softc *)arg; > - struct drm_device *dev = (struct drm_device *)dev_priv->drmdev; > + struct inteldrm_softc *dev_priv = (struct inteldrm_softc *)self; > + struct drm_device *dev = (struct drm_device *)dev_priv->drmdev; > + int rv = 0; > > switch (act) { > case DVACT_QUIESCE: > + rv = config_activate_children(self, act); > i915_drm_freeze(dev); > break; > case DVACT_SUSPEND: > break; > + case DVACT_RESUME: > + break; > case DVACT_WAKEUP: > i915_drm_thaw(dev); > intel_fb_restore_mode(dev); > + rv = config_activate_children(self, act); > break; > } > > - return (0); > + return (rv); > } > > struct cfattach inteldrm_ca = { > Index: radeon/radeon_kms.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/drm/radeon/radeon_kms.c,v > retrieving revision 1.24 > diff -u -p -r1.24 radeon_kms.c > --- radeon/radeon_kms.c 25 Feb 2014 00:03:38 -0000 1.24 > +++ radeon/radeon_kms.c 12 Mar 2014 21:38:43 -0000 > @@ -750,12 +750,14 @@ radeondrm_attachhook(void *xsc) > } > > int > -radeondrm_activate_kms(struct device *arg, int act) > +radeondrm_activate_kms(struct device *self, int act) > { > - struct radeon_device *rdev = (struct radeon_device *)arg; > + struct radeon_device *rdev = (struct radeon_device *)self; > + int rv = 0; > > switch (act) { > case DVACT_QUIESCE: > + rv = config_activate_children(self, act); > radeon_suspend_kms(rdev->ddev); > break; > case DVACT_SUSPEND: > @@ -764,10 +766,11 @@ radeondrm_activate_kms(struct device *ar > break; > case DVACT_WAKEUP: > radeon_resume_kms(rdev->ddev); > + rv = config_activate_children(self, act); > break; > } > > - return (0); > + return (rv); > } > > /**
Hi, I gave the diff a quick spin on my Thinkpad X201. Previously after suspend I couldn't watch any movies as there was no acceleration so playback only functioned with x11 video out. After the diff the playback appears to work just fine after two suspend/resume cycles. OpenBSD 5.5-current (GENERIC.MP) #19: Thu Mar 13 07:51:46 EET 2014 r...@mandrake.wickedbsd.net:/usr/src/sys/arch/amd64/compile/GENERIC.MP real mem = 8357658624 (7970MB) avail mem = 8126455808 (7749MB) mainbus0 at root bios0 at mainbus0: SMBIOS rev. 2.6 @ 0xe0010 (78 entries) bios0: vendor LENOVO version "6QET69WW (1.39 )" date 04/26/2012 bios0: LENOVO 32492EU acpi0 at bios0: rev 2 acpi0: sleep states S0 S3 S4 S5 acpi0: tables DSDT FACP SSDT ECDT APIC MCFG HPET ASF! SLIC BOOT SSDT TCPA DMAR SSDT SSDT SSDT acpi0: wakeup devices LID_(S3) SLPB(S3) IGBE(S4) EXP1(S4) EXP2(S4) EXP3(S4) EXP4(S4) EXP5(S4) EHC1(S3) EHC2(S3) HDEF(S4) acpitimer0 at acpi0: 3579545 Hz, 24 bits acpiec0 at acpi0 acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat cpu0 at mainbus0: apid 0 (boot processor) cpu0: Intel(R) Core(TM) i5 CPU M 540 @ 2.53GHz, 1197.19 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,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,POPCNT,AES,NXE,LONG,LAHF,PERF,ITSC cpu0: 256KB 64b/line 8-way L2 cache cpu0: smt 0, core 0, package 0 mtrr: Pentium Pro MTRR support, 8 var ranges, 88 fixed ranges cpu0: apic clock running at 133MHz cpu0: mwait min=64, max=64, C-substates=0.2.1.1.0, IBE cpu1 at mainbus0: apid 1 (application processor) cpu1: Intel(R) Core(TM) i5 CPU M 540 @ 2.53GHz, 1197.01 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,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,POPCNT,AES,NXE,LONG,LAHF,PERF,ITSC cpu1: 256KB 64b/line 8-way L2 cache cpu1: smt 1, core 0, package 0 cpu2 at mainbus0: apid 4 (application processor) cpu2: Intel(R) Core(TM) i5 CPU M 540 @ 2.53GHz, 1197.01 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,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,POPCNT,AES,NXE,LONG,LAHF,PERF,ITSC cpu2: 256KB 64b/line 8-way L2 cache cpu2: smt 0, core 2, package 0 cpu3 at mainbus0: apid 5 (application processor) cpu3: Intel(R) Core(TM) i5 CPU M 540 @ 2.53GHz, 1197.01 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,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,POPCNT,AES,NXE,LONG,LAHF,PERF,ITSC cpu3: 256KB 64b/line 8-way L2 cache cpu3: smt 1, core 2, package 0 ioapic0 at mainbus0: apid 1 pa 0xfec00000, version 20, 24 pins ioapic0: misconfigured as apic 2, remapped to apid 1 acpimcfg0 at acpi0 addr 0xe0000000, bus 0-255 acpihpet0 at acpi0: 14318179 Hz acpiprt0 at acpi0: bus 0 (PCI0) acpiprt1 at acpi0: bus -1 (PEG_) acpiprt2 at acpi0: bus 13 (EXP1) acpiprt3 at acpi0: bus -1 (EXP2) acpiprt4 at acpi0: bus -1 (EXP3) acpiprt5 at acpi0: bus 5 (EXP4) acpiprt6 at acpi0: bus 2 (EXP5) acpicpu0 at acpi0: C3, C1, PSS acpicpu1 at acpi0: C3, C1, PSS acpicpu2 at acpi0: C3, C1, PSS acpicpu3 at acpi0: C3, C1, PSS acpipwrres0 at acpi0: PUBS, resource for EHC1, EHC2 acpitz0 at acpi0: critical temperature is 100 degC acpibtn0 at acpi0: LID_ acpibtn1 at acpi0: SLPB acpibat0 at acpi0: BAT0 model "42T4650" serial 8908 type LION oem "Panasonic" acpibat1 at acpi0: BAT1 not present acpiac0 at acpi0: AC unit offline acpithinkpad0 at acpi0 acpidock0 at acpi0: GDCK not docked (0) cpu0: Enhanced SpeedStep 1197 MHz: speeds: 2534, 2533, 2399, 2266, 2133, 1999, 1866, 1733, 1599, 1466, 1333, 1199 MHz pci0 at mainbus0 bus 0 pchb0 at pci0 dev 0 function 0 "Intel Core Host" rev 0x02 vga1 at pci0 dev 2 function 0 "Intel HD Graphics" rev 0x02 intagp0 at vga1 agp0 at intagp0: aperture at 0xd0000000, size 0x10000000 inteldrm0 at vga1 drm0 at inteldrm0 inteldrm0: 1280x800 wsdisplay0 at vga1 mux 1: console (std, vt100 emulation) wsdisplay0: screen 1-5 added (std, vt100 emulation) "Intel 3400 MEI" rev 0x06 at pci0 dev 22 function 0 not configured puc0 at pci0 dev 22 function 3 "Intel 3400 KT" rev 0x06: ports: 1 com com4 at puc0 port 0 apic 1 int 17: ns16550a, 16 byte fifo com4: probed fifo depth: 0 bytes em0 at pci0 dev 25 function 0 "Intel 82577LM" rev 0x06: msi, address 00:26:2d:f1:da:75 ehci0 at pci0 dev 26 function 0 "Intel 3400 USB" rev 0x06: apic 1 int 23 usb0 at ehci0: USB revision 2.0 uhub0 at usb0 "Intel EHCI root hub" rev 2.00/1.00 addr 1 azalia0 at pci0 dev 27 function 0 "Intel 3400 HD Audio" rev 0x06: msi azalia0: codecs: Conexant/0x5069, Intel/0x2804, using Conexant/0x5069 audio0 at azalia0 ppb0 at pci0 dev 28 function 0 "Intel 3400 PCIE" rev 0x06: msi pci1 at ppb0 bus 13 ppb1 at pci0 dev 28 function 3 "Intel 3400 PCIE" rev 0x06: msi pci2 at ppb1 bus 5 ppb2 at pci0 dev 28 function 4 "Intel 3400 PCIE" rev 0x06: msi pci3 at ppb2 bus 2 iwn0 at pci3 dev 0 function 0 "Intel Centrino Advanced-N 6200" rev 0x35: msi, MIMO 2T2R, MoW, address 00:23:14:23:6e:18 ehci1 at pci0 dev 29 function 0 "Intel 3400 USB" rev 0x06: apic 1 int 19 usb1 at ehci1: USB revision 2.0 uhub1 at usb1 "Intel EHCI root hub" rev 2.00/1.00 addr 1 ppb3 at pci0 dev 30 function 0 "Intel 82801BAM Hub-to-PCI" rev 0xa6 pci4 at ppb3 bus 14 pcib0 at pci0 dev 31 function 0 "Intel QM57 LPC" rev 0x06 ahci0 at pci0 dev 31 function 2 "Intel 3400 AHCI" rev 0x06: msi, AHCI 1.3 ahci0: device on port 0 didn't come ready, TFD: 0x80<BSY> ahci0: CLO did not complete scsibus0 at ahci0: 32 targets sd0 at scsibus0 targ 0 lun 0: <ATA, INTEL SSDSA2M160, 2CV1> SCSI3 0/direct fixed naa.5001517959106b36 sd0: 152627MB, 512 bytes/sector, 312581808 sectors, thin ichiic0 at pci0 dev 31 function 3 "Intel 3400 SMBus" rev 0x06: apic 1 int 23 iic0 at ichiic0 spdmem0 at iic0 addr 0x50: 4GB DDR3 SDRAM PC3-10600 SO-DIMM spdmem1 at iic0 addr 0x51: 4GB DDR3 SDRAM PC3-10600 SO-DIMM itherm0 at pci0 dev 31 function 6 "Intel 3400 Thermal" rev 0x06 isa0 at pcib0 isadma0 at isa0 pckbc0 at isa0 port 0x60/5 pckbd0 at pckbc0 (kbd slot) pckbc0: using irq 1 for kbd slot wskbd0 at pckbd0: console keyboard, using wsdisplay0 pms0 at pckbc0 (aux slot) pckbc0: using irq 12 for aux slot wsmouse0 at pms0 mux 0 pcppi0 at isa0 port 0x61 spkr0 at pcppi0 aps0 at isa0 port 0x1600/31 pci5 at mainbus0 bus 255 pchb1 at pci5 dev 0 function 0 "Intel QuickPath" rev 0x02 pchb2 at pci5 dev 0 function 1 "Intel QuickPath" rev 0x02 pchb3 at pci5 dev 2 function 0 "Intel QPI Link" rev 0x02 pchb4 at pci5 dev 2 function 1 "Intel QPI Physical" rev 0x02 pchb5 at pci5 dev 2 function 2 "Intel Reserved" rev 0x02 pchb6 at pci5 dev 2 function 3 "Intel Reserved" rev 0x02 uhub2 at uhub0 port 1 "Intel Rate Matching Hub" rev 2.00/0.00 addr 2 ugen0 at uhub2 port 3 "UPEK Biometric Coprocessor" rev 1.01/0.02 addr 3 ugen1 at uhub2 port 4 "Broadcom Corp Broadcom Bluetooth Device" rev 2.00/3.60 addr 4 uhub3 at uhub1 port 1 "Intel Rate Matching Hub" rev 2.00/0.00 addr 2 vscsi0 at root scsibus1 at vscsi0: 256 targets softraid0 at root scsibus2 at softraid0: 256 targets sd1 at scsibus2 targ 1 lun 0: <OPENBSD, SR CRYPTO, 005> SCSI2 0/direct fixed sd1: 152625MB, 512 bytes/sector, 312576113 sectors root on sd1a (741cf65615793b8b.a) swap on sd1b dump on sd1b ugen0 detached ugen1 detached uhub2 detached uhub2 at uhub0 port 1 "Intel Rate Matching Hub" rev 2.00/0.00 addr 2 ugen0 at uhub2 port 3 "UPEK Biometric Coprocessor" rev 1.01/0.02 addr 3 ugen1 at uhub2 port 4 "Broadcom Corp Broadcom Bluetooth Device" rev 2.00/3.60 addr 4 uhub3 detached uhub3 at uhub1 port 1 "Intel Rate Matching Hub" rev 2.00/0.00 addr 2 ugen0 detached ugen1 detached uhub2 detached uhub2 at uhub0 port 1 "Intel Rate Matching Hub" rev 2.00/0.00 addr 2 ugen0 at uhub2 port 3 "UPEK Biometric Coprocessor" rev 1.01/0.02 addr 3 ugen1 at uhub2 port 4 "Broadcom Corp Broadcom Bluetooth Device" rev 2.00/3.60 addr 4 uhub3 detached uhub3 at uhub1 port 1 "Intel Rate Matching Hub" rev 2.00/0.00 addr 2 timo