The GPL doesn't require anyone to contribute back to the upstream project, only contribute forward to downstream users, who may or may not care about source code and even if they do, may or may not bother to publish the code they receive, and even if they do, they/others may or may not try to contribute that code back upstream. It is only a culture of contributing back upstream and more importantly the costs of forking vs merging that leads to upstream contributions. Of course the GPL and copyleft are a big part of forming that culture, but not all of it.
It's not only culture, it's also mutually beneficial, the cost of maintaining a forked version of the kernel is not worth it. Meanwhile working on a patch and publishing it upstream is relatively easy "fire-and-forget", the patch is there, other people will use it and contribute back.
Companies still have a ton of private code that never makes its way into the open source world.