So I've been slowly writing the hotplug support v3 in between all the real jobs I have to do.
[side note: When I started out on hotplug. one of my goals was to avoid changing the server API/ABI too much so I could continue side by side testing.]
how did I get to v3?
v0.1: was called dynerama it failed miserably and proved that using Xinerama as the plugging layer was a bad plan.
v1: was the first time I decided to use an impedance layer between some server objects and driver objects.
v2: was the a major rebase of v1.
v2 was trucking along nicely and I managed to get the design to the stage where PRIME offloading intel/nouveau worked, USB device hotplug with udl worked, and GPU switch worked between two drivers. However v2 duplicated a lot of code and invented a whole new set of API objects called DrvXRec, so DrvScreenRec, DrvPixmapRec, DrvGCRec etc, this lead me to looking at the pain of merging this into the drivers and the server, and my goals of avoiding changing the API/ABI was getting in my way.
So before starting v3 I decided to rework some of the server "APIs".
The X server has two main bodies of code, one called DIX, and one called DDX. The DIX (device independent X) code and the DDX (Device dependent X code). In the X.org tree the dix lives up in the top level dirs, and for X.org server the DDX lives in hw/xfree86. The main object with info about protocol screens and GPUs is called ScreenRec in the DDX and ScrnInfoRec in the DIX. These are stored in two arrays, screenInfo.screens in the DIX and xf86Screens in the DDX, when code wants to convert between these it can do one of a few things.
a) lookup by index, both structs have an index value, so to go from ScrnInfo to Screen you look at screenInfo.screens[scrninfo->scrnIndex] and other way is xf86Screens[screen->myNum]. This is like the I didn't try and make an API, I just exposed everything.
b) ScrnInfo has a ScreenPtr in it, so some code can do ScrnInfo->pScreen to get the pointer to the dix struct. But this pointer is initialised after a bunch of code is called, so you really can't guarantee this pointer is going to be useful for you.
c) XF86SCRNINFO uses the DIX private subsystem to lookup the Scrn in the Screen's privates. This is the least used and probably slowest method.
So also screenInfo.screens contains the protocol screens we exposed to the clients, so this array cannot really change or move around. So I'd like to add screeninfo.gpuscreens and xf86GPUScreens and not have drivers know which set of info they are working on, however (a) totally screws this idea, since the indices are always looked up directly in the global arrays.
Now lots of the Screen/ScrnInfo APIs exposed to the drivers pass an int index as the first parameter, the function in the driver then goes and looks up the global arrays.
So my first API changes introduce some standard conversion functions xf86ScreenToScrn and xf86ScrnToScreen, and converts a lot of the server to use those. Yay an API. The second set of changes then changes all of the index passing APIs to pass ScrnInfoPtr or ScreenPtr, so the drivers don't go poking into global arrays. Now this is a major API change, it will involve slightly messy code in drivers that want to work with both servers, but I can't see a nicer way to do it. I've done a compat header file that will hopefully allows to cover a lot of this stuff where we don't see it.
I've ono other API introduction on the list, Glyph Pictures are another global array indexed by screen index, I've gone and added an accessor function so that drivers don't use the index anymore to get at the array contents directly.
Once this stuff lands in the server, a team of people will go forward and port the drivers to the new APIs (who am I kidding).
No new videos yet, need to fix some more rendering bugs so it looks nicer :)
So I've been working towards 3 setups:
a) intel rendering + nouveau offload
b) nouveau rendering + DVI output + intel LVDS output
c) hotplug USB with either intel or nvidia rendering.
Categorisation of devices roles:
I've identified 4 devices roles so far:
preferred master: the device is happy to be master
reluctant master: the device can be a master but would rather not be
offload slave: device can be used as an additional DRI2 renderer for a master
output slave: device can be used an additional output for a master
For the 3 setups above:
a) intel would be preferred master, nvidia would be offload slave
b) nvidia would be preferred master, intel would be output slave
c) usb devices would be output slaves, however if no master exists, usb device would be reluctant master.
I've rebased the prime work on top of the dma-buf upstream work, and worked through most of the lifetime problems. Some locking issues still exist, and I'll have to get back to them. But the code works and doesn't oops randomly which is good.
prime is the kernel magic needed for this work, as it allows sharing of a buffer between two drm drivers, so for (a) it shares the dri2 front pixmap between devices, for (b/c) it shares a pixmap that the rendering gpu copies dirty updates to and the output slaves use as their scanout pixmap.
So I've done nearly all the work to share between intel and nouveau and I've done the kernel driver work for udl, but I haven't done the last piece in userspace for (c), which is to use the shared pixmap as usb scanout via the modesetting driver.
Today I hacked in a switch on the first randr command, so I can start the X server with intel as master and nouveau in offload mode. I can run gears on intel or nouveau, then after the randr command and another randr command to set a mode, the X server migrates everything to the nouveau driver, puts it in master mode, and places the intel driver into output slave mode. It seems to render my xterm + metacity content fine.
So the current short-term TODO is:
fix some issues with my nouveau/exa port rendering
fix some issues with xcompmgr
add usb output slave support.
worked out how to control this stuff, via randr protocol. How much information do we need to expose to clients about GPUs, and how do we control them. Open issues with atomicity of updates to avoid major uglys. Switching from intel master to nvidia master + intel outputs, means we have to reconfigure the Intel output to point at the new pixmap, but the more steps we put in there for clients to do, the more ugly and flashing we'll see on screen, however we probably want a lot of this to be client driven (i.e. gnome-settings-daemon).
Longer term TODO:
Get GLX_ARB_robustness done, now that Ian has done the context creation stuff, this should be a lot more trivial. (so trivial someone else could do it :)
So today I managed to see something on screen doing X.org hotplug work. So I present to you live X.org plugging.
Pretty much is a laptop running xf86-video-modesetting driver, with my server, an xterm + metacity. Plug in a USB displaylink device, with a kernel drm driver I wrote for it. (Sneaky xrefresh in the background). and the USB device displays the xterm and metacity.
So what actually happens?
The X server at the start had loaded drivers using udev, and the a new driver ABI. It exports one X protocol screen and plugs an internal DrvScreen into it.
When the hotplug happens, the server inits another DrvScreen for the new device, and plugs it into the single protocol screen. It also copies all the driver level pixmaps/pictures/GCs into the new driver. The single protocol screen at the bottom layer multiplexes across the plugged in drvscreens.
This is like Xinerama pushed down a lot further in the stack, so instead of doing iterations at the protocol level, we do it down at the acceleration level. Also I have randr code hooked up so all the outputs appear no matter what GPU they are from.
This isn't exactly what I want for USB hotplug, ideally we'd use the main GPU to render stuff and only scanout using the USB device, but this is step one. I also need the ability to add/remove drvscreens and all the associated data in order to support dynamic GPU switching.
The real solution is a still a long ways off, but this is just a small light in a long tunnel, I've been hacking on this on/off for over a year now, so its nice to see something visible for the first time.
If you've seen the social network, you know when he launches "The Facebook" the first time he needs his friend with the non-nerd contacts email list, I get the feeling that google plus never got this step.
When I joined facebook it was because my mother sent me an invite.
The thing is finding out what my nerd friends are doing is easy, they are always on irc or mailing lists or twittering. I'm not sure what google+ adds to this.
To start off, I don't actually mind arrogant people as long as they back their attitude up with some semblance of sanity, however arrogance without ability pisses me off, and it seems that its the number 1 trait to be a maintainer of glibc.
Today someone pointed out F_SETOWN_EX to me which I can use to fix a problem in the X server, however trying to use gettid made me realise why these guys are considered such fuckwits.
WTF? glibc exposes 3 interfaces that need the result of gettid passed to them and internally relies on gettid to implement raise properly and it won't expose the interface. Notice in the bug he never addresses the problems, just closes it with "CLOSED ARROGANCE".
Other recent glibc fuckwittery includes the whole overlapping memcpy issues in F14 breaking flash for everyone, and trying to remove the rpc implementation a week before the F15 final release freeze, so that if the package had gotten in and packages that needed a rebuild for say a security fix would mean linking the fixed package against a different RPC library than the original which could cause untold pains.
So really if glibc could DIACF already thanks.
This is a test post hidden in an informational post.
I've upgraded the planet generator software for planet.kernel.org and planet.freedesktop.org to the latest venus codebase.
This was mainly due to the older planet software running p.fd.o taking down the webserver once or twice this week.
Hopefully it doesn't do any damage.
First day of LCA 2011 at Kelvin Grove QUT Brisbane.
I'll be organising the Southern Plumbers mini conference today, and will be speaking on Thursday at 11:30 AM about graphics drivers (who'd have guessed).
So I have a T410s with an LVDS panel and switchable graphics between intel and nvidia. I've gotten the basic switching support just like we have on the intel/amd combination.
The code is a start towards generic nvidia/nvidia and intel/nvidia switching but its missing some bits. The MUX switch on some GPUs relies on passing a parameter to the WMI function that we aren't passing, luckily the lenovo doesn't need this parameter at the moment so it works fine. Other laptops in this range may require the parameter.
I'll try and get some more info on the magic value we need to pass on other systems to make it work better, other systems like the Sony Vaios have a number of muxable outputs listed in a table, that the intel acpi code prints out at drm.debug=0x4. Again the lenovo doesn't have this table.
once switched and powered off the Intel, we get log spam from the IPS driver about the MCP limits.
nouveau gets a 1024x768 console since we can't detect the LVDS panel at startup.
also, this only works with open source drivers, i915 and nouveau.
Okay I sat down for a few hours last week with a switchable Intel/NVidia GPU laptop, and at least worked out some more info. I'm going to braindump it here.
Firstly in intel_acpi.c jbarnes has worked out some of the values for outputs in the ACPI tables esp around what is and isn't MUXed.
Now we had suspected that one of the nvidia GPU DSM methods (method 5) might actually do something, but a deeper investigation along with mjg59 made us realise it isn't the mux control, so we started looking elsewhere.
So we tracked down the MXDS method which is attached to the ACPI outputs per GPU, there is one on the LVDS for the internal GPU and one on the LVDS for the external GPU. So it appears that this is the mux switching object. Looking further up it appears that this is called via a WMI interface, so to do this all properly it looks like we need to write a WMI driver to call the mux switching, instead of just banging on ACPI methods.
So going forward a WMI driver needs to be written to which you pass the ACPI output IDs to the WMI MXDS method, and it should switch the mux.
Now despite this we didn't actually get the switching to happen, nouveau never got an auxch connection to the panel on the laptop, so I'd really like to see if anyone is useful enough to take this knowledge and make it do something on an LVDS laptop, all I have locally are a big pile of hacks.
Thanks to Jesse Barnes for the laptop, and Matthew Garrett for the ACPI decoding.
[update: one commentor asked about Macs, they have a non-WMI, non-ACPI method of handling things, sidolin on #nouveau at one stage mostly reverse engineering the mux, which was just reading/writing some memory mapped I/O ports to do the switch, not sure how far he is from pushing some patches out].
As part of LCA 2011, we are organising a mini-conference to provide a place for low-level system developers to gather and discuss interesting aspects of the kernel and lowlevel userspace. This miniconf is aimed at a similar audience to the Linux Plumbers Conference.
We'd really like to have talks that are entry points to open floor discussions and interactive sessions, though if a talk is interesting enough it will be considered depending on the quality of other submissions.
Areas of interest:
- Linux kernel
- X.org / Mesa
- toolchain/gdb (not deep compiler stuff, more system interactions)
- udev/u*/*Kit/hal replacements
The Southern Plumbers mini-conference is planned for Monday 24th Jan 2011.
Please send all submissions to email@example.com. Submissions will close on Friday, October 29th (when I leave for the real Linux Plumbers Conference), though I may accept submission over the week of LPC as well if I can drum up interest.
CFP available at http://planet.kernel.org/splca/cfp.txt
Dave Airlie and Matthew Wilcox.