1. 22 11月, 2017 12 次提交
    • K
      treewide: setup_timer() -> timer_setup() · e99e88a9
      Kees Cook 提交于
      This converts all remaining cases of the old setup_timer() API into using
      timer_setup(), where the callback argument is the structure already
      holding the struct timer_list. These should have no behavioral changes,
      since they just change which pointer is passed into the callback with
      the same available pointers after conversion. It handles the following
      examples, in addition to some other variations.
      
      Casting from unsigned long:
      
          void my_callback(unsigned long data)
          {
              struct something *ptr = (struct something *)data;
          ...
          }
          ...
          setup_timer(&ptr->my_timer, my_callback, ptr);
      
      and forced object casts:
      
          void my_callback(struct something *ptr)
          {
          ...
          }
          ...
          setup_timer(&ptr->my_timer, my_callback, (unsigned long)ptr);
      
      become:
      
          void my_callback(struct timer_list *t)
          {
              struct something *ptr = from_timer(ptr, t, my_timer);
          ...
          }
          ...
          timer_setup(&ptr->my_timer, my_callback, 0);
      
      Direct function assignments:
      
          void my_callback(unsigned long data)
          {
              struct something *ptr = (struct something *)data;
          ...
          }
          ...
          ptr->my_timer.function = my_callback;
      
      have a temporary cast added, along with converting the args:
      
          void my_callback(struct timer_list *t)
          {
              struct something *ptr = from_timer(ptr, t, my_timer);
          ...
          }
          ...
          ptr->my_timer.function = (TIMER_FUNC_TYPE)my_callback;
      
      And finally, callbacks without a data assignment:
      
          void my_callback(unsigned long data)
          {
          ...
          }
          ...
          setup_timer(&ptr->my_timer, my_callback, 0);
      
      have their argument renamed to verify they're unused during conversion:
      
          void my_callback(struct timer_list *unused)
          {
          ...
          }
          ...
          timer_setup(&ptr->my_timer, my_callback, 0);
      
      The conversion is done with the following Coccinelle script:
      
      spatch --very-quiet --all-includes --include-headers \
      	-I ./arch/x86/include -I ./arch/x86/include/generated \
      	-I ./include -I ./arch/x86/include/uapi \
      	-I ./arch/x86/include/generated/uapi -I ./include/uapi \
      	-I ./include/generated/uapi --include ./include/linux/kconfig.h \
      	--dir . \
      	--cocci-file ~/src/data/timer_setup.cocci
      
      @fix_address_of@
      expression e;
      @@
      
       setup_timer(
      -&(e)
      +&e
       , ...)
      
      // Update any raw setup_timer() usages that have a NULL callback, but
      // would otherwise match change_timer_function_usage, since the latter
      // will update all function assignments done in the face of a NULL
      // function initialization in setup_timer().
      @change_timer_function_usage_NULL@
      expression _E;
      identifier _timer;
      type _cast_data;
      @@
      
      (
      -setup_timer(&_E->_timer, NULL, _E);
      +timer_setup(&_E->_timer, NULL, 0);
      |
      -setup_timer(&_E->_timer, NULL, (_cast_data)_E);
      +timer_setup(&_E->_timer, NULL, 0);
      |
      -setup_timer(&_E._timer, NULL, &_E);
      +timer_setup(&_E._timer, NULL, 0);
      |
      -setup_timer(&_E._timer, NULL, (_cast_data)&_E);
      +timer_setup(&_E._timer, NULL, 0);
      )
      
      @change_timer_function_usage@
      expression _E;
      identifier _timer;
      struct timer_list _stl;
      identifier _callback;
      type _cast_func, _cast_data;
      @@
      
      (
      -setup_timer(&_E->_timer, _callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, &_callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, _callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, &_callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)_callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)&_callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)_callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)&_callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, &_callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, &_callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
       _E->_timer@_stl.function = _callback;
      |
       _E->_timer@_stl.function = &_callback;
      |
       _E->_timer@_stl.function = (_cast_func)_callback;
      |
       _E->_timer@_stl.function = (_cast_func)&_callback;
      |
       _E._timer@_stl.function = _callback;
      |
       _E._timer@_stl.function = &_callback;
      |
       _E._timer@_stl.function = (_cast_func)_callback;
      |
       _E._timer@_stl.function = (_cast_func)&_callback;
      )
      
      // callback(unsigned long arg)
      @change_callback_handle_cast
       depends on change_timer_function_usage@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _origtype;
      identifier _origarg;
      type _handletype;
      identifier _handle;
      @@
      
       void _callback(
      -_origtype _origarg
      +struct timer_list *t
       )
       {
      (
      	... when != _origarg
      	_handletype *_handle =
      -(_handletype *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      |
      	... when != _origarg
      	_handletype *_handle =
      -(void *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      |
      	... when != _origarg
      	_handletype *_handle;
      	... when != _handle
      	_handle =
      -(_handletype *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      |
      	... when != _origarg
      	_handletype *_handle;
      	... when != _handle
      	_handle =
      -(void *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      )
       }
      
      // callback(unsigned long arg) without existing variable
      @change_callback_handle_cast_no_arg
       depends on change_timer_function_usage &&
                           !change_callback_handle_cast@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _origtype;
      identifier _origarg;
      type _handletype;
      @@
      
       void _callback(
      -_origtype _origarg
      +struct timer_list *t
       )
       {
      +	_handletype *_origarg = from_timer(_origarg, t, _timer);
      +
      	... when != _origarg
      -	(_handletype *)_origarg
      +	_origarg
      	... when != _origarg
       }
      
      // Avoid already converted callbacks.
      @match_callback_converted
       depends on change_timer_function_usage &&
                  !change_callback_handle_cast &&
      	    !change_callback_handle_cast_no_arg@
      identifier change_timer_function_usage._callback;
      identifier t;
      @@
      
       void _callback(struct timer_list *t)
       { ... }
      
      // callback(struct something *handle)
      @change_callback_handle_arg
       depends on change_timer_function_usage &&
      	    !match_callback_converted &&
                  !change_callback_handle_cast &&
                  !change_callback_handle_cast_no_arg@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _handletype;
      identifier _handle;
      @@
      
       void _callback(
      -_handletype *_handle
      +struct timer_list *t
       )
       {
      +	_handletype *_handle = from_timer(_handle, t, _timer);
      	...
       }
      
      // If change_callback_handle_arg ran on an empty function, remove
      // the added handler.
      @unchange_callback_handle_arg
       depends on change_timer_function_usage &&
      	    change_callback_handle_arg@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _handletype;
      identifier _handle;
      identifier t;
      @@
      
       void _callback(struct timer_list *t)
       {
      -	_handletype *_handle = from_timer(_handle, t, _timer);
       }
      
      // We only want to refactor the setup_timer() data argument if we've found
      // the matching callback. This undoes changes in change_timer_function_usage.
      @unchange_timer_function_usage
       depends on change_timer_function_usage &&
                  !change_callback_handle_cast &&
                  !change_callback_handle_cast_no_arg &&
      	    !change_callback_handle_arg@
      expression change_timer_function_usage._E;
      identifier change_timer_function_usage._timer;
      identifier change_timer_function_usage._callback;
      type change_timer_function_usage._cast_data;
      @@
      
      (
      -timer_setup(&_E->_timer, _callback, 0);
      +setup_timer(&_E->_timer, _callback, (_cast_data)_E);
      |
      -timer_setup(&_E._timer, _callback, 0);
      +setup_timer(&_E._timer, _callback, (_cast_data)&_E);
      )
      
      // If we fixed a callback from a .function assignment, fix the
      // assignment cast now.
      @change_timer_function_assignment
       depends on change_timer_function_usage &&
                  (change_callback_handle_cast ||
                   change_callback_handle_cast_no_arg ||
                   change_callback_handle_arg)@
      expression change_timer_function_usage._E;
      identifier change_timer_function_usage._timer;
      identifier change_timer_function_usage._callback;
      type _cast_func;
      typedef TIMER_FUNC_TYPE;
      @@
      
      (
       _E->_timer.function =
      -_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E->_timer.function =
      -&_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E->_timer.function =
      -(_cast_func)_callback;
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E->_timer.function =
      -(_cast_func)&_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -&_callback;
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -(_cast_func)_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -(_cast_func)&_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      )
      
      // Sometimes timer functions are called directly. Replace matched args.
      @change_timer_function_calls
       depends on change_timer_function_usage &&
                  (change_callback_handle_cast ||
                   change_callback_handle_cast_no_arg ||
                   change_callback_handle_arg)@
      expression _E;
      identifier change_timer_function_usage._timer;
      identifier change_timer_function_usage._callback;
      type _cast_data;
      @@
      
       _callback(
      (
      -(_cast_data)_E
      +&_E->_timer
      |
      -(_cast_data)&_E
      +&_E._timer
      |
      -_E
      +&_E->_timer
      )
       )
      
      // If a timer has been configured without a data argument, it can be
      // converted without regard to the callback argument, since it is unused.
      @match_timer_function_unused_data@
      expression _E;
      identifier _timer;
      identifier _callback;
      @@
      
      (
      -setup_timer(&_E->_timer, _callback, 0);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, _callback, 0L);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, _callback, 0UL);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, 0);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, 0L);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, 0UL);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_timer, _callback, 0);
      +timer_setup(&_timer, _callback, 0);
      |
      -setup_timer(&_timer, _callback, 0L);
      +timer_setup(&_timer, _callback, 0);
      |
      -setup_timer(&_timer, _callback, 0UL);
      +timer_setup(&_timer, _callback, 0);
      |
      -setup_timer(_timer, _callback, 0);
      +timer_setup(_timer, _callback, 0);
      |
      -setup_timer(_timer, _callback, 0L);
      +timer_setup(_timer, _callback, 0);
      |
      -setup_timer(_timer, _callback, 0UL);
      +timer_setup(_timer, _callback, 0);
      )
      
      @change_callback_unused_data
       depends on match_timer_function_unused_data@
      identifier match_timer_function_unused_data._callback;
      type _origtype;
      identifier _origarg;
      @@
      
       void _callback(
      -_origtype _origarg
      +struct timer_list *unused
       )
       {
      	... when != _origarg
       }
      Signed-off-by: NKees Cook <keescook@chromium.org>
      e99e88a9
    • K
      treewide: init_timer() -> setup_timer() · b9eaf187
      Kees Cook 提交于
      This mechanically converts all remaining cases of ancient open-coded timer
      setup with the old setup_timer() API, which is the first step in timer
      conversions. This has no behavioral changes, since it ultimately just
      changes the order of assignment to fields of struct timer_list when
      finding variations of:
      
          init_timer(&t);
          f.function = timer_callback;
          t.data = timer_callback_arg;
      
      to be converted into:
      
          setup_timer(&t, timer_callback, timer_callback_arg);
      
      The conversion is done with the following Coccinelle script, which
      is an improved version of scripts/cocci/api/setup_timer.cocci, in the
      following ways:
       - assignments-before-init_timer() cases
       - limit the .data case removal to the specific struct timer_list instance
       - handling calls by dereference (timer->field vs timer.field)
      
      spatch --very-quiet --all-includes --include-headers \
      	-I ./arch/x86/include -I ./arch/x86/include/generated \
      	-I ./include -I ./arch/x86/include/uapi \
      	-I ./arch/x86/include/generated/uapi -I ./include/uapi \
      	-I ./include/generated/uapi --include ./include/linux/kconfig.h \
      	--dir . \
      	--cocci-file ~/src/data/setup_timer.cocci
      
      @fix_address_of@
      expression e;
      @@
      
       init_timer(
      -&(e)
      +&e
       , ...)
      
      // Match the common cases first to avoid Coccinelle parsing loops with
      // "... when" clauses.
      
      @match_immediate_function_data_after_init_timer@
      expression e, func, da;
      @@
      
      -init_timer
      +setup_timer
       ( \(&e\|e\)
      +, func, da
       );
      (
      -\(e.function\|e->function\) = func;
      -\(e.data\|e->data\) = da;
      |
      -\(e.data\|e->data\) = da;
      -\(e.function\|e->function\) = func;
      )
      
      @match_immediate_function_data_before_init_timer@
      expression e, func, da;
      @@
      
      (
      -\(e.function\|e->function\) = func;
      -\(e.data\|e->data\) = da;
      |
      -\(e.data\|e->data\) = da;
      -\(e.function\|e->function\) = func;
      )
      -init_timer
      +setup_timer
       ( \(&e\|e\)
      +, func, da
       );
      
      @match_function_and_data_after_init_timer@
      expression e, e2, e3, e4, e5, func, da;
      @@
      
      -init_timer
      +setup_timer
       ( \(&e\|e\)
      +, func, da
       );
       ... when != func = e2
           when != da = e3
      (
      -e.function = func;
      ... when != da = e4
      -e.data = da;
      |
      -e->function = func;
      ... when != da = e4
      -e->data = da;
      |
      -e.data = da;
      ... when != func = e5
      -e.function = func;
      |
      -e->data = da;
      ... when != func = e5
      -e->function = func;
      )
      
      @match_function_and_data_before_init_timer@
      expression e, e2, e3, e4, e5, func, da;
      @@
      (
      -e.function = func;
      ... when != da = e4
      -e.data = da;
      |
      -e->function = func;
      ... when != da = e4
      -e->data = da;
      |
      -e.data = da;
      ... when != func = e5
      -e.function = func;
      |
      -e->data = da;
      ... when != func = e5
      -e->function = func;
      )
      ... when != func = e2
          when != da = e3
      -init_timer
      +setup_timer
       ( \(&e\|e\)
      +, func, da
       );
      
      @r1 exists@
      expression t;
      identifier f;
      position p;
      @@
      
      f(...) { ... when any
        init_timer@p(\(&t\|t\))
        ... when any
      }
      
      @r2 exists@
      expression r1.t;
      identifier g != r1.f;
      expression e8;
      @@
      
      g(...) { ... when any
        \(t.data\|t->data\) = e8
        ... when any
      }
      
      // It is dangerous to use setup_timer if data field is initialized
      // in another function.
      @script:python depends on r2@
      p << r1.p;
      @@
      
      cocci.include_match(False)
      
      @r3@
      expression r1.t, func, e7;
      position r1.p;
      @@
      
      (
      -init_timer@p(&t);
      +setup_timer(&t, func, 0UL);
      ... when != func = e7
      -t.function = func;
      |
      -t.function = func;
      ... when != func = e7
      -init_timer@p(&t);
      +setup_timer(&t, func, 0UL);
      |
      -init_timer@p(t);
      +setup_timer(t, func, 0UL);
      ... when != func = e7
      -t->function = func;
      |
      -t->function = func;
      ... when != func = e7
      -init_timer@p(t);
      +setup_timer(t, func, 0UL);
      )
      Signed-off-by: NKees Cook <keescook@chromium.org>
      b9eaf187
    • K
      treewide: Switch DEFINE_TIMER callbacks to struct timer_list * · 24ed960a
      Kees Cook 提交于
      This changes all DEFINE_TIMER() callbacks to use a struct timer_list
      pointer instead of unsigned long. Since the data argument has already been
      removed, none of these callbacks are using their argument currently, so
      this renames the argument to "unused".
      
      Done using the following semantic patch:
      
      @match_define_timer@
      declarer name DEFINE_TIMER;
      identifier _timer, _callback;
      @@
      
       DEFINE_TIMER(_timer, _callback);
      
      @change_callback depends on match_define_timer@
      identifier match_define_timer._callback;
      type _origtype;
      identifier _origarg;
      @@
      
       void
      -_callback(_origtype _origarg)
      +_callback(struct timer_list *unused)
       { ... }
      Signed-off-by: NKees Cook <keescook@chromium.org>
      24ed960a
    • K
      s390: cmm: Convert timers to use timer_setup() · 6cc73a06
      Kees Cook 提交于
      In preparation for unconditionally passing the struct timer_list pointer to
      all timer callbacks, switch to using the new timer_setup() and from_timer()
      to pass the timer pointer explicitly.
      
      Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
      Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: Geert Uytterhoeven <geert@linux-m68k.org>
      Cc: Arnd Bergmann <arnd@arndb.de>
      Cc: Guenter Roeck <linux@roeck-us.net>
      Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
      Cc: linux-s390@vger.kernel.org
      Signed-off-by: NKees Cook <keescook@chromium.org>
      6cc73a06
    • K
      lightnvm: Convert timers to use timer_setup() · 87c1d2d3
      Kees Cook 提交于
      In preparation for unconditionally passing the struct timer_list pointer to
      all timer callbacks, switch to using the new timer_setup() and from_timer()
      to pass the timer pointer explicitly.
      
      Cc: Matias Bjorling <mb@lightnvm.io>
      Cc: linux-block@vger.kernel.org
      Signed-off-by: NKees Cook <keescook@chromium.org>
      87c1d2d3
    • K
      drivers/net: cris: Convert timers to use timer_setup() · bd1a7b44
      Kees Cook 提交于
      In preparation for unconditionally passing the struct timer_list pointer to
      all timer callbacks, switch to using the new timer_setup() and from_timer()
      to pass the timer pointer explicitly.
      
      Cc: "David S. Miller" <davem@davemloft.net>
      Cc: Kalle Valo <kvalo@codeaurora.org>
      Cc: Arnd Bergmann <arnd@arndb.de>
      Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
      Cc: "yuval.shaia@oracle.com" <yuval.shaia@oracle.com>
      Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
      Cc: Philippe Reynes <tremyfr@gmail.com>
      Cc: netdev@vger.kernel.org
      Signed-off-by: NKees Cook <keescook@chromium.org>
      bd1a7b44
    • K
      drm/vc4: Convert timers to use timer_setup() · 0078730f
      Kees Cook 提交于
      In preparation for unconditionally passing the struct timer_list pointer to
      all timer callbacks, switch to using the new timer_setup() and from_timer()
      to pass the timer pointer explicitly.
      
      Cc: Eric Anholt <eric@anholt.net>
      Cc: David Airlie <airlied@linux.ie>
      Cc: dri-devel@lists.freedesktop.org
      Signed-off-by: NKees Cook <keescook@chromium.org>
      Signed-off-by: NEric Anholt <eric@anholt.net>
      Link: https://patchwork.freedesktop.org/patch/msgid/20171024151648.GA104538@beastReviewed-by: NEric Anholt <eric@anholt.net>
      0078730f
    • K
      block/laptop_mode: Convert timers to use timer_setup() · bca237a5
      Kees Cook 提交于
      In preparation for unconditionally passing the struct timer_list pointer to
      all timer callbacks, switch to using the new timer_setup() and from_timer()
      to pass the timer pointer explicitly.
      
      Cc: Jens Axboe <axboe@kernel.dk>
      Cc: Michal Hocko <mhocko@suse.com>
      Cc: Andrew Morton <akpm@linux-foundation.org>
      Cc: Jan Kara <jack@suse.cz>
      Cc: Johannes Weiner <hannes@cmpxchg.org>
      Cc: Nicholas Piggin <npiggin@gmail.com>
      Cc: Vladimir Davydov <vdavydov.dev@gmail.com>
      Cc: Matthew Wilcox <mawilcox@microsoft.com>
      Cc: Jeff Layton <jlayton@redhat.com>
      Cc: linux-block@vger.kernel.org
      Cc: linux-mm@kvack.org
      Signed-off-by: NKees Cook <keescook@chromium.org>
      bca237a5
    • K
      net/atm/mpc: Avoid open-coded assignment of timer callback function · 1e9aa74e
      Kees Cook 提交于
      Instead of a single function assignment, just fold this into DEFINE_TIMER().
      
      Cc: "David S. Miller" <davem@davemloft.net>
      Signed-off-by: NKees Cook <keescook@chromium.org>
      1e9aa74e
    • K
      drm/i915/selftests: Convert timers to use timer_setup() · 2ea5b4de
      Kees Cook 提交于
      In preparation for unconditionally passing the struct timer_list pointer to
      all timer callbacks, switch to using the new timer_setup() and from_timer()
      to pass the timer pointer explicitly.
      
      Cc: Jani Nikula <jani.nikula@linux.intel.com>
      Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
      Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
      Cc: David Airlie <airlied@linux.ie>
      Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
      Cc: Chris Wilson <chris@chris-wilson.co.uk>
      Cc: intel-gfx@lists.freedesktop.org
      Cc: dri-devel@lists.freedesktop.org
      Signed-off-by: NKees Cook <keescook@chromium.org>
      Acked-by: NJani Nikula <jani.nikula@intel.com>
      2ea5b4de
    • K
      usb: usbatm: Convert timers to use timer_setup() · 72a9f9a4
      Kees Cook 提交于
      In preparation for unconditionally passing the struct timer_list pointer to
      all timer callbacks, switch to using the new timer_setup() and from_timer()
      to pass the timer pointer explicitly. Additionally corrects and on-stack
      timer usage.
      
      Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
      Cc: Duncan Sands <duncan.sands@free.fr>
      Cc: "Gustavo A. R. Silva" <garsilva@embeddedor.com>
      Cc: accessrunner-general@lists.sourceforge.net
      Cc: linux-usb@vger.kernel.org
      Signed-off-by: NKees Cook <keescook@chromium.org>
      Reviewed-by: NAllen Pais <allen.lkml@gmail.com>
      72a9f9a4
    • K
      drivers/firmware: psci: Convert timers to use timer_setup() · ff07a23f
      Kees Cook 提交于
      In preparation for unconditionally passing the struct timer_list pointer to
      all timer callbacks, switch to using the new timer_setup() and from_timer()
      to pass the timer pointer explicitly. Also adds missing call to
      destroy_timer_on_stack().
      
      Cc: Mark Rutland <mark.rutland@arm.com>
      Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
      Cc: linux-arm-kernel@lists.infradead.org
      Signed-off-by: NKees Cook <keescook@chromium.org>
      ff07a23f
  2. 21 11月, 2017 16 次提交
    • L
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net · 0c86a6bd
      Linus Torvalds 提交于
      Pull networking fixes from David Miller:
      
       1) Fix a reference to a module parameter which was lost during the
          GREv6 receive path rewrite, from Alexey Kodanev.
      
       2) Fix deref before NULL check in ipheth, from Gustavo A. R. Silva.
      
       3) RCU read lock imbalance in tun_build_skb(), from Xin Long.
      
       4) Some stragglers from the mac80211 folks:
      
            a) Timer conversions from Kees Cook
      
            b) Fix some sequencing issue when cfg80211 is built statically,
               from Johannes Berg
      
            c) Memory leak in mac80211_hwsim, from Ben Hutchings.
      
       5) Add new qmi_wwan device ID, from Sebastian Sjoholm.
      
       6) Fix use after free in tipc, from Jon Maloy.
      
       7) Missing kdoc in nfp driver, from Jakub Kicinski.
      
      * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
        nfp: flower: add missing kdoc
        tipc: fix access of released memory
        net: qmi_wwan: add Quectel BG96 2c7c:0296
        mlxsw: spectrum: Do not try to create non-existing ports during unsplit
        mac80211: properly free requested-but-not-started TX agg sessions
        mac80211_hwsim: Fix memory leak in hwsim_new_radio_nl()
        cfg80211: initialize regulatory keys/database later
        mac80211: aggregation: Convert timers to use timer_setup()
        nl80211: don't expose wdev->ssid for most interfaces
        mac80211: Convert timers to use timer_setup()
        net: vxge: Fix some indentation issues
        net: ena: fix race condition between device reset and link up setup
        r8169: use same RTL8111EVL green settings as in vendor driver
        r8169: fix RTL8111EVL EEE and green settings
        tun: fix rcu_read_lock imbalance in tun_build_skb
        tcp: when scheduling TLP, time of RTO should account for current ACK
        usbnet: ipheth: fix potential null pointer dereference in ipheth_carrier_set
        gre6: use log_ecn_error module parameter in ip6_tnl_rcv()
      0c86a6bd
    • L
      Merge tag 'for-linus-4.15-ofs1' of git://git.kernel.org/pub/scm/linux/kernel/git/hubcap/linux · b620fd2d
      Linus Torvalds 提交于
      Pull orangefs updates from Mike Marshall:
       "Fix:
      
         - stop setting atime on inode dirty (Martin Brandenburg)
      
        Cleanups:
      
         - remove initialization of i_version (Jeff Layton)
      
         - use ARRAY_SIZE (Jérémy Lefaure)
      
         - call op_release sooner when creating inodes (Mike MarshallMartin
           Brandenburg)"
      
      * tag 'for-linus-4.15-ofs1' of git://git.kernel.org/pub/scm/linux/kernel/git/hubcap/linux:
        orangefs: call op_release sooner when creating inodes
        orangefs: stop setting atime on inode dirty
        orangefs: use ARRAY_SIZE
        orangefs: remove initialization of i_version
      b620fd2d
    • L
      Merge tag 'ceph-for-4.15-rc1' of git://github.com/ceph/ceph-client · adb072d3
      Linus Torvalds 提交于
      Pull ceph updates from Ilya Dryomov:
       "We have a set of file locking improvements from Zheng, rbd rw/ro state
        handling code cleanup from myself and some assorted CephFS fixes from
        Jeff.
      
        rbd now defaults to single-major=Y, lifting the limit of ~240 rbd
        images per host for everyone"
      
      * tag 'ceph-for-4.15-rc1' of git://github.com/ceph/ceph-client:
        rbd: default to single-major device number scheme
        libceph: don't WARN() if user tries to add invalid key
        rbd: set discard_alignment to zero
        ceph: silence sparse endianness warning in encode_caps_cb
        ceph: remove the bump of i_version
        ceph: present consistent fsid, regardless of arch endianness
        ceph: clean up spinlocking and list handling around cleanup_cap_releases()
        rbd: get rid of rbd_mapping::read_only
        rbd: fix and simplify rbd_ioctl_set_ro()
        ceph: remove unused and redundant variable dropping
        ceph: mark expected switch fall-throughs
        ceph: -EINVAL on decoding failure in ceph_mdsc_handle_fsmap()
        ceph: disable cached readdir after dropping positive dentry
        ceph: fix bool initialization/comparison
        ceph: handle 'session get evicted while there are file locks'
        ceph: optimize flock encoding during reconnect
        ceph: make lock_to_ceph_filelock() static
        ceph: keep auth cap when inode has flocks or posix locks
      adb072d3
    • L
      Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk · 11ca75d2
      Linus Torvalds 提交于
      Pull printk updates from Petr Mladek:
      
       - print the warning about dropped messages on consoles on a separate
         line.   It makes it more legible.
      
       - one typo fix and small code clean up.
      
      * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk:
        added new line symbol after warning about dropped messages
        printk: fix typo in printk_safe.c
        printk: simplify no_printk()
      11ca75d2
    • D
      Merge tag 'mac80211-for-davem-2017-11-20' of... · a13e8d41
      David S. Miller 提交于
      Merge tag 'mac80211-for-davem-2017-11-20' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211
      
      Johannes Berg says:
      
      ====================
      A few things:
       * straggler timer conversions from Kees
       * memory leak fix in hwsim
       * fix some fallout from regdb changes if wireless is built-in
       * also free aggregation sessions in startup state when station
         goes away, to avoid crashing the timer
      ====================
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      a13e8d41
    • J
      nfp: flower: add missing kdoc · b48b1f7a
      Jakub Kicinski 提交于
      Commit 0115552e ("nfp: remove false positive offloads
      in flower vxlan") missed adding kdoc for a new parameter
      of nfp_flower_add_offload().
      Signed-off-by: NJakub Kicinski <jakub.kicinski@netronome.com>
      Reviewed-by: NSimon Horman <simon.horman@netronome.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      b48b1f7a
    • J
      tipc: fix access of released memory · e0e853ac
      Jon Maloy 提交于
      When the function tipc_group_filter_msg() finds that a member event
      indicates that the member is leaving the group, it first deletes the
      member instance, and then purges the message queue being handled
      by the call. But the message queue is an aggregated field in the
      just deleted item, leading the purge call to access freed memory.
      
      We fix this by swapping the order of the two actions.
      Signed-off-by: NJon Maloy <jon.maloy@ericsson.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      e0e853ac
    • S
      net: qmi_wwan: add Quectel BG96 2c7c:0296 · f9409e7f
      Sebastian Sjoholm 提交于
      Quectel BG96 is an Qualcomm MDM9206 based IoT modem, supporting both
      CAT-M and NB-IoT. Tested hardware is BG96 mounted on Quectel development
      board (EVB). The USB id is added to qmi_wwan.c to allow QMI
      communication with the BG96.
      Signed-off-by: NSebastian Sjoholm <ssjoholm@mac.com>
      Acked-by: NBjørn Mork <bjorn@mork.no>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      f9409e7f
    • I
      mlxsw: spectrum: Do not try to create non-existing ports during unsplit · bf4e9f24
      Ido Schimmel 提交于
      On some systems, when we unsplit a port we need to re-create two ports
      instead. On other systems, only one needs to be re-created.
      
      Do not try to create a port if during driver initialization it was
      assigned a negative module number, which is invalid.
      
      This avoids the following error during unsplit:
      [  941.012478] mlxsw_spectrum 0000:01:00.0: Port 43: Failed to map module
      
      The error is harmless and caused by the fact that a local port is
      already mapped to module 0.
      
      Fixes: be94535f ("mlxsw: spectrum: Make split flow match firmware requirements")
      Signed-off-by: NIdo Schimmel <idosch@mellanox.com>
      Reviewed-by: NArkadi Sharshevsky <arkadis@mellanox.com>
      Signed-off-by: NJiri Pirko <jiri@mellanox.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      bf4e9f24
    • L
      Merge tag 'fbdev-v4.15' of git://github.com/bzolnier/linux · e1d1ea54
      Linus Torvalds 提交于
      Pull fbdev updates from Bartlomiej Zolnierkiewicz:
       "There is nothing really major here (though removal of the dead igafb
        driver stands out in diffstat).
      
        Summary:
      
         - convert timers to use timer_setup() (Kees Cook, Thierry Reding)
      
         - fix panels support on iMX boards in mxsfb driver (Stefan Agner)
      
         - fix timeout on EDID read in udlfb driver (Ladislav Michl)
      
         - add missing modes to fix out of bounds access in controlfb driver
           (Geert Uytterhoeven)
      
         - update initialisation paths in sa1100fb driver to be more robust
           (Russell King)
      
         - fix error handling path of ->probe method in au1200fb driver
           (Christophe JAILLET)
      
         - fix handling of cases when either panel or crt is defined in
           sm501fb driver (Sudip Mukherjee, Colin Ian King)
      
         - add ability to the Goldfish FB driver to be recognized by OS via DT
           (Aleksandar Markovic)
      
         - structures constifications (Bhumika Goyal)
      
         - misc fixes (Allen Pais, Gustavo A. R. Silva, Dan Carpenter)
      
         - misc cleanups (Colin Ian King, Himanshu Jha, Markus Elfring)
      
         - remove dead igafb driver"
      
      * tag 'fbdev-v4.15' of git://github.com/bzolnier/linux: (42 commits)
        OMAPFB: prevent buffer underflow in omapfb_parse_vram_param()
        video: fbdev: sm501fb: fix potential null pointer dereference on fbi
        fbcon: Initialize ops->info early
        video: fbdev: Convert timers to use timer_setup()
        video: fbdev: pxa3xx_gcu: Convert timers to use timer_setup()
        fbdev: controlfb: Add missing modes to fix out of bounds access
        video: fbdev: sis_main: mark expected switch fall-throughs
        video: fbdev: cirrusfb: mark expected switch fall-throughs
        video: fbdev: aty: radeon_pm: mark expected switch fall-throughs
        video: fbdev: sm501fb: mark expected switch fall-through in sm501fb_blank_crt
        video: fbdev: intelfb: remove redundant variables
        video/fbdev/dnfb: Use common error handling code in dnfb_probe()
        sm501fb: suspend and resume fb if it exists
        sm501fb: unregister framebuffer only if registered
        sm501fb: deallocate colormap only if allocated
        video: goldfishfb: Add support for device tree bindings
        Documentation: Add device tree binding for Goldfish FB driver
        video: udlfb: Fix read EDID timeout
        video: fbdev: remove dead igafb driver
        video: fbdev: mxsfb: fix pixelclock polarity
        ...
      e1d1ea54
    • L
      Merge tag 'devicetree-fixes-for-4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux · c633e898
      Linus Torvalds 提交于
      Pull DeviceTree fixes from Rob Herring:
      
       - Remove mc13892 as a trivial device
      
       - Improve of_find_node_by_name() documentation
      
       - Fix unit test dtc warnings
      
       - Clean-ups of USB binding documentation
      
       - Fix potential NULL deref in of_pci_map_rid
      
      * tag 'devicetree-fixes-for-4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux:
        dt-bindings: trivial-devices: Remove fsl,mc13892
        of: Document exactly what of_find_node_by_name() puts
        of: unittest: disable interrupts_property warning
        of: unittest: let dtc generate __local_fixups__
        dt-bindings: usb: document hub and host-controller properties
        dt-bindings: usb: clean up compatible property
        dt-bindings: usb: fix reg-property port-number range
        dt-bindings: usb: fix example hub node name
        of/pci: Fix theoretical NULL dereference
      c633e898
    • L
      Merge tag 'jfs-4.15-2' of git://github.com/kleikamp/linux-shaggy · bf8973fc
      Linus Torvalds 提交于
      Pull jfs fixlet from Dave Kleikamp:
       "Update jfs git tree in MAINTAINERS"
      
      * tag 'jfs-4.15-2' of git://github.com/kleikamp/linux-shaggy:
        MAINTAINERS: fix jfs tree location
      bf8973fc
    • J
      dt-bindings: trivial-devices: Remove fsl,mc13892 · def4db33
      Jonathan Neuschäfer 提交于
      This device's bindings are not trivial: Additional properties are
      documented in in Documentation/devicetree/bindings/mfd/mc13xxx.txt.
      Signed-off-by: NJonathan Neuschäfer <j.neuschaefer@gmx.net>
      Reviewed-by: NFabio Estevam <fabio.estevam@nxp.com>
      Signed-off-by: NRob Herring <robh@kernel.org>
      def4db33
    • S
      of: Document exactly what of_find_node_by_name() puts · 02a876b5
      Stephen Boyd 提交于
      It isn't clear if this function of_node_put()s the 'from'
      argument, or the node it searches. Clearly indicate which
      variable is touched. Fold in some more fixes from Randy too
      because we're in the area.
      
      Cc: Randy Dunlap <rdunlap@infradead.org>
      Signed-off-by: NStephen Boyd <sboyd@codeaurora.org>
      Acked-by: NRandy Dunlap <rdunlap@infradead.org>
      Signed-off-by: NRob Herring <robh@kernel.org>
      02a876b5
    • T
      MAINTAINERS: fix jfs tree location · 86313903
      Tom Saeger 提交于
      JFS tree has been moved to github.
      Signed-off-by: NTom Saeger <tom.saeger@oracle.com>
      Signed-off-by: NDave Kleikamp <dave.kleikamp@oracle.com>
      86313903
    • J
      mac80211: properly free requested-but-not-started TX agg sessions · 33ddd81e
      Johannes Berg 提交于
      When deleting a station or otherwise tearing down all aggregation
      sessions, make sure to delete requested but not yet started ones,
      to avoid the following scenario:
      
       * session is requested, added to tid_start_tx[]
       * ieee80211_ba_session_work() runs, gets past BLOCK_BA check
       * ieee80211_sta_tear_down_BA_sessions() runs, locks &sta->ampdu_mlme.mtx,
         e.g. while deleting the station - deleting all active sessions
       * ieee80211_ba_session_work() continues since tear down flushes it, and
         calls ieee80211_tx_ba_session_handle_start() for the new session, arms
         the timer for it
       * station deletion continues to __cleanup_single_sta() and frees the
         session struct, while the timer is armed
      Reported-by: NFengguang Wu <fengguang.wu@intel.com>
      Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
      33ddd81e
  3. 20 11月, 2017 10 次提交
    • B
      mac80211_hwsim: Fix memory leak in hwsim_new_radio_nl() · 67bd5238
      Ben Hutchings 提交于
      hwsim_new_radio_nl() now copies the name attribute in order to add a
      null-terminator.  mac80211_hwsim_new_radio() (indirectly) copies it
      again into the net_device structure, so the first copy is not used or
      freed later.  Free the first copy before returning.
      
      Fixes: ff4dd73d ("mac80211_hwsim: check HWSIM_ATTR_RADIO_NAME length")
      Signed-off-by: NBen Hutchings <ben.hutchings@codethink.co.uk>
      Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
      67bd5238
    • J
      cfg80211: initialize regulatory keys/database later · d7be102f
      Johannes Berg 提交于
      When cfg80211 is built as a module, everything is fine, and we
      can keep the code as is; in fact, we have to, because there can
      only be a single module_init().
      
      When cfg80211 is built-in, however, it needs to initialize
      before drivers (device_initcall/module_init), and thus used to
      be at subsys_initcall(). I'd moved it to fs_initcall() earlier,
      where it can remain. However, this is still too early because at
      that point the key infrastructure hasn't been initialized yet,
      so X.509 certificates can't be parsed yet.
      
      To work around this problem, load the regdb keys only later in
      a late_initcall(), at which point the necessary infrastructure
      has been initialized.
      
      Fixes: 90a53e44 ("cfg80211: implement regdb signature checking")
      Reported-by: NXiaolong Ye <xiaolong.ye@intel.com>
      Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
      d7be102f
    • K
      mac80211: aggregation: Convert timers to use timer_setup() · 7cca2acd
      Kees Cook 提交于
      In preparation for unconditionally passing the struct timer_list pointer to
      all timer callbacks, switch to using the new timer_setup() and from_timer()
      to pass the timer pointer explicitly.
      
      This removes the tid mapping array and expands the tid structures to
      add a pointer back to the station, along with the tid index itself.
      
      Cc: Johannes Berg <johannes@sipsolutions.net>
      Cc: "David S. Miller" <davem@davemloft.net>
      Cc: linux-wireless@vger.kernel.org
      Cc: netdev@vger.kernel.org
      Signed-off-by: NKees Cook <keescook@chromium.org>
      [switch tid variables to u8, the valid range is 0-15 at most,
       initialize tid_tx->sta/tid properly]
      Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
      7cca2acd
    • J
      nl80211: don't expose wdev->ssid for most interfaces · 44905265
      Johannes Berg 提交于
      For mesh, this is simply wrong - there's no SSID, only the
      mesh ID, so don't expose it at all.
      For (P2P) client, it's wrong, because it exposes an internal
      value that's only used when certain APIs are used.
      For AP, it's actually the only correct case, so leave that.
      All other interface types shouldn't be setting this anyway,
      so there it won't change anything.
      
      Fixes: b84e7a05 ("nl80211: send the NL80211_ATTR_SSID in nl80211_send_iface()")
      Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
      44905265
    • K
      mac80211: Convert timers to use timer_setup() · 34f11cd3
      Kees Cook 提交于
      In preparation for unconditionally passing the struct timer_list pointer to
      all timer callbacks, switch to using the new timer_setup() and from_timer()
      to pass the timer pointer explicitly.
      
      Cc: Johannes Berg <johannes@sipsolutions.net>
      Cc: "David S. Miller" <davem@davemloft.net>
      Cc: linux-wireless@vger.kernel.org
      Cc: netdev@vger.kernel.org
      Signed-off-by: NKees Cook <keescook@chromium.org>
      Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
      34f11cd3
    • L
      Merge tag 'ntb-4.15' of git://github.com/jonmason/ntb · c8a0739b
      Linus Torvalds 提交于
      Pull ntb updates from Jon Mason:
       "Support for the switchtec ntb and related changes. Also, a couple of
        bug fixes"
      
      [ The timing isn't great. I had asked people to send me pull requests
        before my family vacation, and this code has not even been in
        linux-next as far as I can tell. But Logan Gunthorpe pleaded for its
        inclusion because the Switchtec driver has apparently been around for
        a while, just never in linux-next - Linus ]
      
      * tag 'ntb-4.15' of git://github.com/jonmason/ntb:
        ntb: intel: remove b2b memory window workaround for Skylake NTB
        NTB: make idt_89hpes_cfg const
        NTB: switchtec_ntb: Update switchtec documentation with notes for NTB
        NTB: switchtec_ntb: Add memory window support
        NTB: switchtec_ntb: Implement scratchpad registers
        NTB: switchtec_ntb: Implement doorbell registers
        NTB: switchtec_ntb: Add link management
        NTB: switchtec_ntb: Add skeleton NTB driver
        NTB: switchtec_ntb: Initialize hardware for doorbells and messages
        NTB: switchtec_ntb: Initialize hardware for memory windows
        NTB: switchtec_ntb: Introduce initial NTB driver
        NTB: Add check and comment for link up to mw_count() and mw_get_align()
        NTB: Ensure ntb_mw_get_align() is only called when the link is up
        NTB: switchtec: Add link event notifier callback
        NTB: switchtec: Add NTB hardware register definitions
        NTB: switchtec: Export class symbol for use in upper layer driver
        NTB: switchtec: Move structure definitions into a common header
        ntb: update maintainer list for Intel NTB driver
      c8a0739b
    • C
      net: vxge: Fix some indentation issues · 32a72bbd
      Christophe JAILLET 提交于
      Some statements are not enough or too much indented.
      Fix it to improve readalbility.
      Signed-off-by: NChristophe JAILLET <christophe.jaillet@wanadoo.fr>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      32a72bbd
    • N
      net: ena: fix race condition between device reset and link up setup · d18e4f68
      Netanel Belgazal 提交于
      In rare cases, ena driver would reset and re-start the device,
      for example, in case of misbehaving application that causes
      transmit timeout
      
      The first step in the reset procedure is to stop the Tx traffic by
      calling ena_carrier_off().
      
      After the driver have just started the device reset procedure, device
      happens to send an asynchronous notification (via AENQ) to the driver
      than there was a link change (to link-up state).
      This link change is mapped to a call to netif_carrier_on() which
      re-activates the Tx queues, violating the assumption of no tx traffic
      until device reset is completed, as the reset task might still be in
      the process of queues initialization, leading to an access to
      uninitialized memory.
      Signed-off-by: NNetanel Belgazal <netanel@amazon.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      d18e4f68
    • R
      ima: do not update security.ima if appraisal status is not INTEGRITY_PASS · 020aae3e
      Roberto Sassu 提交于
      Commit b65a9cfc ("Untangling ima mess, part 2: deal with counters")
      moved the call of ima_file_check() from may_open() to do_filp_open() at a
      point where the file descriptor is already opened.
      
      This breaks the assumption made by IMA that file descriptors being closed
      belong to files whose access was granted by ima_file_check(). The
      consequence is that security.ima and security.evm are updated with good
      values, regardless of the current appraisal status.
      
      For example, if a file does not have security.ima, IMA will create it after
      opening the file for writing, even if access is denied. Access to the file
      will be allowed afterwards.
      
      Avoid this issue by checking the appraisal status before updating
      security.ima.
      
      Cc: stable@vger.kernel.org
      Signed-off-by: NRoberto Sassu <roberto.sassu@huawei.com>
      Signed-off-by: NMimi Zohar <zohar@linux.vnet.ibm.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      020aae3e
    • L
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide · ed30b147
      Linus Torvalds 提交于
      Pull small IDE cleanup from David Miller.
      
      * git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide:
        PNP: ide: constify pnp_device_id
      ed30b147
  4. 19 11月, 2017 2 次提交