Use sleep mutexes. Spin mutexes should only be used in very special cases and only with the approval of -smp.
Do not tsleep()/msleep()/cv_wait() while holding a mutex other than Giant.
Do not call a function that can grab Giant and then sleep unless no mutexes (other than possibly Giant) are held.
If calling msleep()/cv_wait() while holding Giant and another mutex, Giant must be acquired first and released last.
Except for the Giant mutex used during the transition phase, mutexes protect data, not code.
Do not msleep()/cv_wait() with a recursed mutex. (Note that Giant is a special case and is handled automagically behind the scenes, so don't pass Giant to msleep()/cv_wait().)
Try to hold mutexes for as little time as possible.
Try to avoid recursing on mutexes if at all possible. In general, if a mutex is recursively entered, the mutex is being held for too long, and a redesign is in order.