Subject: preempting while holding rtnl_lock

From: Flavio Leitner <[email-masked]>
Date: Thu, 14 Jul 2011 18:15:02 -0300

Hi,

I was reviewing driver sources and found that
ethtool ops holds rtnl_lock() and there are few
drivers (for example: tg3, bnx2) that use napi_disable()
in this context.

/**     
 *      napi_disable - prevent NAPI from scheduling
 *      @n: napi context
 *              
 * Stop NAPI from being scheduled on this context.
 * Waits till any outstanding processing completes.
 */
static inline void napi_disable(struct napi_struct *n)
{
        set_bit(NAPI_STATE_DISABLE, &n->state);
        while (test_and_set_bit(NAPI_STATE_SCHED, &n->state))
                msleep(1);
        clear_bit(NAPI_STATE_DISABLE, &n->state);
}

The msleep() above will preempt.  I believe this is wrong.
See the functions below as examples:
bnx2_set_ringparam()
+ bnx2_change_ring_size()
  + bnx2_netif_stop()
    + bnx2_napi_disable()
      + napi_disable()

+ tg3_change_mtu() = ndo_change_mtu
  + tg3_netif_stop()
    + tg3_napi_disable()
      + napi_disable()

What am I missing?
thanks,
fbl