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

Reply via email to