First, I'll grant that there's very little internal documentation. This hurts. But I find I can still figure out what's going on by reading the code, and that the really obtuse things have comments.
The coding style is consistent - I don't think I've ever seen a single deviation. Linux kernel code is fit for print. This helps enormously with readability. It's rare to find such a large codebase written by so many people that uniform.
The directory structure and file names are straightforward. Want to know where the main scheduling code is? kernel/sched.c. What about the data structures for scheduling? include/linux/sched.h. How is fork implemented? kernel/fork.c. This is important because it means the source is discoverable.
Functions are just the right length. A single function conceptually does one thing, as it should. I've never read through a function and thought "This should be factored out into several different functions."
Consistent and intuitive names. Even if I've never read a function, or seen the definition of a variable, I have a good idea of what it does just by the name. This is should be true for all code, but considering the size and complexity of the code, I find it impressive I've never thought "That's a stupid name." It helps that special functions follow certain naming conventions. For example, if I encounter a function named do_foo(), I know that it is the function called for a foo system call.
And most importantly, any time I've wanted to know how something works in the Linux kernel, I've always been able to figure it out with focused study and tracing. Focused study, not a heroic effort. If it takes longer than I thought it would, it's always because I had to learn a few new concepts along the way, not because the code was obtuse.
Reading the Linux kernel code helps if you do it using LXR, http://lxr.linux.no/, which does a cross-reference of the code. Most variable names, functions and structures are links to their definitions and occurrences.