One of the biggest differences between working on most other OSs and working upstream on drivers for the Linux kernel is that elsewhere the core is usually a fixed thing that has been released and can’t really be changed, even if source is available (which may not even be the case). If whatever subsystem you’re working in can’t cope with the thing you’re trying to express then one of the things it’s really useful to be good at is working out ways to implement the behaviour that’s required behind the back of the subsystem. It’s very common to see such code in drivers submitted by hardware vendors, particularly those that are new to Linux, as this is such a big mindset shift.
With kernel development the approach is much more to make sure that the core can cope with whatever needs expressing. It’s not always done in the core – for example, sometimes the issue is due to unusually limited hardware and very likely to never come up again – but it’s very unusual to see code merged that doesn’t at least fit in with the design of the subsystem.
This post is inspired by a brief exchange with Thomas Gleixner on linux-kernel who articulated the advantages of doing things this way very well:
- It's usually simpler and faster as the core code has all the necessary information. So that's even an argument which managers might understand. - Such workarounds, when not caught, tend to spread themself magically because driver writers checkout the existing code of similar devices and copy/paste/modify^Wuglify them over and over. - In the worst case such workarounds make the core maintainence harder and in some cases impossible, because they silently imply semantics on the core w/o the core maintainer knowing about them.
The last point is the most important one to me as a subsystem maintainer – I really don’t want to be merging code that is going to create issues with ongoing development of the subsystem. This is all another facet of the policy on stable APIs: APIs are only worth working around if they’re fixed, and the assumptions that end up embedded in a workaroud are as much part of the API as the explicit interfaces.
It’s things like this that make Linux such a pleasure to work on.