1. 14 11月, 2018 2 次提交
  2. 30 7月, 2018 1 次提交
  3. 17 7月, 2018 2 次提交
    • A
      usb: dwc2: Fix inefficient copy of unaligned buffers · 1e111e88
      Antti Seppälä 提交于
      Make sure only to copy any actual data rather than the whole buffer,
      when releasing the temporary buffer used for unaligned non-isochronous
      transfers.
      
      Taken directly from commit 0efd937e ("USB: ehci-tegra: fix inefficient
      copy of unaligned buffers")
      
      Tested with Lantiq xRX200 (MIPS) and RPi Model B Rev 2 (ARM)
      Reviewed-by: NDouglas Anderson <dianders@chromium.org>
      Signed-off-by: NAntti Seppälä <a.seppala@gmail.com>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      1e111e88
    • A
      usb: dwc2: Fix DMA alignment to start at allocated boundary · 56406e01
      Antti Seppälä 提交于
      The commit 3bc04e28 ("usb: dwc2: host: Get aligned DMA in a more
      supported way") introduced a common way to align DMA allocations.
      The code in the commit aligns the struct dma_aligned_buffer but the
      actual DMA address pointed by data[0] gets aligned to an offset from
      the allocated boundary by the kmalloc_ptr and the old_xfer_buffer
      pointers.
      
      This is against the recommendation in Documentation/DMA-API.txt which
      states:
      
        Therefore, it is recommended that driver writers who don't take
        special care to determine the cache line size at run time only map
        virtual regions that begin and end on page boundaries (which are
        guaranteed also to be cache line boundaries).
      
      The effect of this is that architectures with non-coherent DMA caches
      may run into memory corruption or kernel crashes with Unhandled
      kernel unaligned accesses exceptions.
      
      Fix the alignment by positioning the DMA area in front of the allocation
      and use memory at the end of the area for storing the orginal
      transfer_buffer pointer. This may have the added benefit of increased
      performance as the DMA area is now fully aligned on all architectures.
      
      Tested with Lantiq xRX200 (MIPS) and RPi Model B Rev 2 (ARM).
      
      Fixes: 3bc04e28 ("usb: dwc2: host: Get aligned DMA in a more supported way")
      Cc: <stable@vger.kernel.org>
      Reviewed-by: NDouglas Anderson <dianders@chromium.org>
      Signed-off-by: NAntti Seppälä <a.seppala@gmail.com>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      56406e01
  4. 19 6月, 2018 2 次提交
    • W
      usb: dwc2: alloc dma aligned buffer for isoc split in · af424a41
      William Wu 提交于
      The commit 3bc04e28 ("usb: dwc2: host: Get aligned DMA in
      a more supported way") rips out a lot of code to simply the
      allocation of aligned DMA. However, it also introduces a new
      issue when use isoc split in transfer.
      
      In my test case, I connect the dwc2 controller with an usb hs
      Hub (GL852G-12), and plug an usb fs audio device (Plantronics
      headset) into the downstream port of Hub. Then use the usb mic
      to record, we can find noise when playback.
      
      It's because that the usb Hub uses an MDATA for the first
      transaction and a DATA0 for the second transaction for the isoc
      split in transaction. An typical isoc split in transaction sequence
      like this:
      
      - SSPLIT IN transaction
      - CSPLIT IN transaction
        - MDATA packet
      - CSPLIT IN transaction
        - DATA0 packet
      
      The DMA address of MDATA (urb->dma) is always DWORD-aligned, but
      the DMA address of DATA0 (urb->dma + qtd->isoc_split_offset) may
      not be DWORD-aligned, it depends on the qtd->isoc_split_offset (the
      length of MDATA). In my test case, the length of MDATA is usually
      unaligned, this cause DATA0 packet transmission error.
      
      This patch use kmem_cache to allocate aligned DMA buf for isoc
      split in transaction. Note that according to usb 2.0 spec, the
      maximum data payload size is 1023 bytes for each fs isoc ep,
      and the maximum allowable interrupt data payload size is 64 bytes
      or less for fs interrupt ep. So we set the size of object to be
      1024 bytes in the kmem cache.
      Tested-by: NGevorg Sahakyan <sahakyan@synopsys.com>
      Tested-by: NHeiko Stuebner <heiko@sntech.de>
      Acked-by: Minas Harutyunyan hminas@synopsys.com>
      Signed-off-by: NWilliam Wu <william.wu@rock-chips.com>
      Reviewed-by: NDouglas Anderson <dianders@chromium.org>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      af424a41
    • A
      usb: dwc2: Fix host exit from hibernation flow. · 22bb5cfd
      Artur Petrosyan 提交于
      In case when a hub is connected to DWC2 host
      auto suspend occurs and host goes to
      hibernation. When any device connected to hub
      host hibernation exiting incorrectly.
      
      - Added dwc2_hcd_rem_wakeup() function call to
        exit from suspend state by remote wakeup.
      
      - Increase timeout value for port suspend bit to be set.
      Acked-by: NMinas Harutyunyan <hminas@synopsys.com>
      Signed-off-by: NArtur Petrosyan <arturp@synopsys.com>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      22bb5cfd
  5. 13 6月, 2018 1 次提交
    • K
      treewide: kzalloc() -> kcalloc() · 6396bb22
      Kees Cook 提交于
      The kzalloc() function has a 2-factor argument form, kcalloc(). This
      patch replaces cases of:
      
              kzalloc(a * b, gfp)
      
      with:
              kcalloc(a * b, gfp)
      
      as well as handling cases of:
      
              kzalloc(a * b * c, gfp)
      
      with:
      
              kzalloc(array3_size(a, b, c), gfp)
      
      as it's slightly less ugly than:
      
              kzalloc_array(array_size(a, b), c, gfp)
      
      This does, however, attempt to ignore constant size factors like:
      
              kzalloc(4 * 1024, gfp)
      
      though any constants defined via macros get caught up in the conversion.
      
      Any factors with a sizeof() of "unsigned char", "char", and "u8" were
      dropped, since they're redundant.
      
      The Coccinelle script used for this was:
      
      // Fix redundant parens around sizeof().
      @@
      type TYPE;
      expression THING, E;
      @@
      
      (
        kzalloc(
      -	(sizeof(TYPE)) * E
      +	sizeof(TYPE) * E
        , ...)
      |
        kzalloc(
      -	(sizeof(THING)) * E
      +	sizeof(THING) * E
        , ...)
      )
      
      // Drop single-byte sizes and redundant parens.
      @@
      expression COUNT;
      typedef u8;
      typedef __u8;
      @@
      
      (
        kzalloc(
      -	sizeof(u8) * (COUNT)
      +	COUNT
        , ...)
      |
        kzalloc(
      -	sizeof(__u8) * (COUNT)
      +	COUNT
        , ...)
      |
        kzalloc(
      -	sizeof(char) * (COUNT)
      +	COUNT
        , ...)
      |
        kzalloc(
      -	sizeof(unsigned char) * (COUNT)
      +	COUNT
        , ...)
      |
        kzalloc(
      -	sizeof(u8) * COUNT
      +	COUNT
        , ...)
      |
        kzalloc(
      -	sizeof(__u8) * COUNT
      +	COUNT
        , ...)
      |
        kzalloc(
      -	sizeof(char) * COUNT
      +	COUNT
        , ...)
      |
        kzalloc(
      -	sizeof(unsigned char) * COUNT
      +	COUNT
        , ...)
      )
      
      // 2-factor product with sizeof(type/expression) and identifier or constant.
      @@
      type TYPE;
      expression THING;
      identifier COUNT_ID;
      constant COUNT_CONST;
      @@
      
      (
      - kzalloc
      + kcalloc
        (
      -	sizeof(TYPE) * (COUNT_ID)
      +	COUNT_ID, sizeof(TYPE)
        , ...)
      |
      - kzalloc
      + kcalloc
        (
      -	sizeof(TYPE) * COUNT_ID
      +	COUNT_ID, sizeof(TYPE)
        , ...)
      |
      - kzalloc
      + kcalloc
        (
      -	sizeof(TYPE) * (COUNT_CONST)
      +	COUNT_CONST, sizeof(TYPE)
        , ...)
      |
      - kzalloc
      + kcalloc
        (
      -	sizeof(TYPE) * COUNT_CONST
      +	COUNT_CONST, sizeof(TYPE)
        , ...)
      |
      - kzalloc
      + kcalloc
        (
      -	sizeof(THING) * (COUNT_ID)
      +	COUNT_ID, sizeof(THING)
        , ...)
      |
      - kzalloc
      + kcalloc
        (
      -	sizeof(THING) * COUNT_ID
      +	COUNT_ID, sizeof(THING)
        , ...)
      |
      - kzalloc
      + kcalloc
        (
      -	sizeof(THING) * (COUNT_CONST)
      +	COUNT_CONST, sizeof(THING)
        , ...)
      |
      - kzalloc
      + kcalloc
        (
      -	sizeof(THING) * COUNT_CONST
      +	COUNT_CONST, sizeof(THING)
        , ...)
      )
      
      // 2-factor product, only identifiers.
      @@
      identifier SIZE, COUNT;
      @@
      
      - kzalloc
      + kcalloc
        (
      -	SIZE * COUNT
      +	COUNT, SIZE
        , ...)
      
      // 3-factor product with 1 sizeof(type) or sizeof(expression), with
      // redundant parens removed.
      @@
      expression THING;
      identifier STRIDE, COUNT;
      type TYPE;
      @@
      
      (
        kzalloc(
      -	sizeof(TYPE) * (COUNT) * (STRIDE)
      +	array3_size(COUNT, STRIDE, sizeof(TYPE))
        , ...)
      |
        kzalloc(
      -	sizeof(TYPE) * (COUNT) * STRIDE
      +	array3_size(COUNT, STRIDE, sizeof(TYPE))
        , ...)
      |
        kzalloc(
      -	sizeof(TYPE) * COUNT * (STRIDE)
      +	array3_size(COUNT, STRIDE, sizeof(TYPE))
        , ...)
      |
        kzalloc(
      -	sizeof(TYPE) * COUNT * STRIDE
      +	array3_size(COUNT, STRIDE, sizeof(TYPE))
        , ...)
      |
        kzalloc(
      -	sizeof(THING) * (COUNT) * (STRIDE)
      +	array3_size(COUNT, STRIDE, sizeof(THING))
        , ...)
      |
        kzalloc(
      -	sizeof(THING) * (COUNT) * STRIDE
      +	array3_size(COUNT, STRIDE, sizeof(THING))
        , ...)
      |
        kzalloc(
      -	sizeof(THING) * COUNT * (STRIDE)
      +	array3_size(COUNT, STRIDE, sizeof(THING))
        , ...)
      |
        kzalloc(
      -	sizeof(THING) * COUNT * STRIDE
      +	array3_size(COUNT, STRIDE, sizeof(THING))
        , ...)
      )
      
      // 3-factor product with 2 sizeof(variable), with redundant parens removed.
      @@
      expression THING1, THING2;
      identifier COUNT;
      type TYPE1, TYPE2;
      @@
      
      (
        kzalloc(
      -	sizeof(TYPE1) * sizeof(TYPE2) * COUNT
      +	array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
        , ...)
      |
        kzalloc(
      -	sizeof(TYPE1) * sizeof(THING2) * (COUNT)
      +	array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
        , ...)
      |
        kzalloc(
      -	sizeof(THING1) * sizeof(THING2) * COUNT
      +	array3_size(COUNT, sizeof(THING1), sizeof(THING2))
        , ...)
      |
        kzalloc(
      -	sizeof(THING1) * sizeof(THING2) * (COUNT)
      +	array3_size(COUNT, sizeof(THING1), sizeof(THING2))
        , ...)
      |
        kzalloc(
      -	sizeof(TYPE1) * sizeof(THING2) * COUNT
      +	array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
        , ...)
      |
        kzalloc(
      -	sizeof(TYPE1) * sizeof(THING2) * (COUNT)
      +	array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
        , ...)
      )
      
      // 3-factor product, only identifiers, with redundant parens removed.
      @@
      identifier STRIDE, SIZE, COUNT;
      @@
      
      (
        kzalloc(
      -	(COUNT) * STRIDE * SIZE
      +	array3_size(COUNT, STRIDE, SIZE)
        , ...)
      |
        kzalloc(
      -	COUNT * (STRIDE) * SIZE
      +	array3_size(COUNT, STRIDE, SIZE)
        , ...)
      |
        kzalloc(
      -	COUNT * STRIDE * (SIZE)
      +	array3_size(COUNT, STRIDE, SIZE)
        , ...)
      |
        kzalloc(
      -	(COUNT) * (STRIDE) * SIZE
      +	array3_size(COUNT, STRIDE, SIZE)
        , ...)
      |
        kzalloc(
      -	COUNT * (STRIDE) * (SIZE)
      +	array3_size(COUNT, STRIDE, SIZE)
        , ...)
      |
        kzalloc(
      -	(COUNT) * STRIDE * (SIZE)
      +	array3_size(COUNT, STRIDE, SIZE)
        , ...)
      |
        kzalloc(
      -	(COUNT) * (STRIDE) * (SIZE)
      +	array3_size(COUNT, STRIDE, SIZE)
        , ...)
      |
        kzalloc(
      -	COUNT * STRIDE * SIZE
      +	array3_size(COUNT, STRIDE, SIZE)
        , ...)
      )
      
      // Any remaining multi-factor products, first at least 3-factor products,
      // when they're not all constants...
      @@
      expression E1, E2, E3;
      constant C1, C2, C3;
      @@
      
      (
        kzalloc(C1 * C2 * C3, ...)
      |
        kzalloc(
      -	(E1) * E2 * E3
      +	array3_size(E1, E2, E3)
        , ...)
      |
        kzalloc(
      -	(E1) * (E2) * E3
      +	array3_size(E1, E2, E3)
        , ...)
      |
        kzalloc(
      -	(E1) * (E2) * (E3)
      +	array3_size(E1, E2, E3)
        , ...)
      |
        kzalloc(
      -	E1 * E2 * E3
      +	array3_size(E1, E2, E3)
        , ...)
      )
      
      // And then all remaining 2 factors products when they're not all constants,
      // keeping sizeof() as the second factor argument.
      @@
      expression THING, E1, E2;
      type TYPE;
      constant C1, C2, C3;
      @@
      
      (
        kzalloc(sizeof(THING) * C2, ...)
      |
        kzalloc(sizeof(TYPE) * C2, ...)
      |
        kzalloc(C1 * C2 * C3, ...)
      |
        kzalloc(C1 * C2, ...)
      |
      - kzalloc
      + kcalloc
        (
      -	sizeof(TYPE) * (E2)
      +	E2, sizeof(TYPE)
        , ...)
      |
      - kzalloc
      + kcalloc
        (
      -	sizeof(TYPE) * E2
      +	E2, sizeof(TYPE)
        , ...)
      |
      - kzalloc
      + kcalloc
        (
      -	sizeof(THING) * (E2)
      +	E2, sizeof(THING)
        , ...)
      |
      - kzalloc
      + kcalloc
        (
      -	sizeof(THING) * E2
      +	E2, sizeof(THING)
        , ...)
      |
      - kzalloc
      + kcalloc
        (
      -	(E1) * E2
      +	E1, E2
        , ...)
      |
      - kzalloc
      + kcalloc
        (
      -	(E1) * (E2)
      +	E1, E2
        , ...)
      |
      - kzalloc
      + kcalloc
        (
      -	E1 * E2
      +	E1, E2
        , ...)
      )
      Signed-off-by: NKees Cook <keescook@chromium.org>
      6396bb22
  6. 21 5月, 2018 2 次提交
  7. 25 4月, 2018 1 次提交
  8. 14 3月, 2018 1 次提交
  9. 13 3月, 2018 15 次提交
  10. 13 12月, 2017 1 次提交
    • D
      usb: dwc2: host: Don't retry NAKed transactions right away · 38d2b5fb
      Douglas Anderson 提交于
      On rk3288-veyron devices on Chrome OS it was found that plugging in an
      Arduino-based USB device could cause the system to lockup, especially
      if the CPU Frequency was at one of the slower operating points (like
      100 MHz / 200 MHz).
      
      Upon tracing, I found that the following was happening:
      * The USB device (full speed) was connected to a high speed hub and
        then to the rk3288.  Thus, we were dealing with split transactions,
        which is all handled in software on dwc2.
      * Userspace was initiating a BULK IN transfer
      * When we sent the SSPLIT (to start the split transaction), we got an
        ACK.  Good.  Then we issued the CSPLIT.
      * When we sent the CSPLIT, we got back a NAK.  We immediately (from
        the interrupt handler) started to retry and sent another SSPLIT.
      * The device kept NAKing our CSPLIT, so we kept ping-ponging between
        sending a SSPLIT and a CSPLIT, each time sending from the interrupt
        handler.
      * The handling of the interrupts was (because of the low CPU speed and
        the inefficiency of the dwc2 interrupt handler) was actually taking
        _longer_ than it took the other side to send the ACK/NAK.  Thus we
        were _always_ in the USB interrupt routine.
      * The fact that USB interrupts were always going off was preventing
        other things from happening in the system.  This included preventing
        the system from being able to transition to a higher CPU frequency.
      
      As I understand it, there is no requirement to retry super quickly
      after a NAK, we just have to retry sometime in the future.  Thus one
      solution to the above is to just add a delay between getting a NAK and
      retrying the transmission.  If this delay is sufficiently long to get
      out of the interrupt routine then the rest of the system will be able
      to make forward progress.  Even a 25 us delay would probably be
      enough, but we'll be extra conservative and try to delay 1 ms (the
      exact amount depends on HZ and the accuracy of the jiffy and how close
      the current jiffy is to ticking, but could be as much as 20 ms or as
      little as 1 ms).
      
      Presumably adding a delay like this could impact the USB throughput,
      so we only add the delay with repeated NAKs.
      
      NOTE: Upon further testing of a pl2303 serial adapter, I found that
      this fix may help with problems there.  Specifically I found that the
      pl2303 serial adapters tend to respond with a NAK when they have
      nothing to say and thus we end with this same sequence.
      Signed-off-by: NDouglas Anderson <dianders@chromium.org>
      Reviewed-by: NJulius Werner <jwerner@chromium.org>
      Tested-by: NStefan Wahren <stefan.wahren@i2se.com>
      Acked-by: NJohn Youn <johnyoun@synopsys.com>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      38d2b5fb
  11. 22 11月, 2017 1 次提交
    • 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
  12. 04 11月, 2017 1 次提交
  13. 24 10月, 2017 1 次提交
    • J
      usb: dwc2: Improve gadget state disconnection handling · d2471d4a
      John Stultz 提交于
      In the earlier commit dad3f793 ("usb: dwc2: Make sure we
      disconnect the gadget state"), I was trying to fix up the
      fact that we somehow weren't disconnecting the gadget state,
      so that when the OTG port was plugged in the second time we
      would get warnings about the state tracking being wrong.
      
      (This seems to be due to a quirk of the HiKey board where
      we do not ever get any otg interrupts, particularly the session
      end detected signal. Instead we only see status change
      interrupt.)
      
      The fix there was somewhat simple, as it just made sure to
      call dwc2_hsotg_disconnect() before we connected things up
      in OTG mode, ensuring the state handling didn't throw errors.
      
      But in looking at a different issue I was seeing with UDC
      state handling, I realized that it would be much better
      to call dwc2_hsotg_disconnect when we get the state change
      signal moving to host mode.
      
      Thus, this patch removes the earlier disconnect call I added
      and moves it (and the needed locking) to the host mode
      transition.
      
      Cc: Wei Xu <xuwei5@hisilicon.com>
      Cc: Guodong Xu <guodong.xu@linaro.org>
      Cc: Amit Pundir <amit.pundir@linaro.org>
      Cc: YongQin Liu <yongqin.liu@linaro.org>
      Cc: John Youn <johnyoun@synopsys.com>
      Cc: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
      Cc: Douglas Anderson <dianders@chromium.org>
      Cc: Chen Yu <chenyu56@huawei.com>
      Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
      Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
      Cc: linux-usb@vger.kernel.org
      Acked-by: NMinas Harutyunyan <hminas@synopsys.com>
      Tested-by: NMinas Harutyunyan <hminas@synopsys.com>
      Signed-off-by: NJohn Stultz <john.stultz@linaro.org>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      d2471d4a
  14. 19 10月, 2017 1 次提交
  15. 15 8月, 2017 1 次提交
  16. 11 4月, 2017 2 次提交
    • B
      usb: dwc2: Add support for STM32F429/439/469 USB OTG HS/FS in FS mode (internal PHY) · e35b1350
      Bruno Herrera 提交于
      This patch introduces a new parameter to activate USB OTG HS/FS core
      embedded phy transceiver. The STM32F4x9 SoC uses the GGPIO register
      to enable the transceiver.
      Also add the dwc2_set_params function for stm32f4 otg fs.
      Acked-by: NJohn Youn <johnyoun@synopsys.com>
      Signed-off-by: NBruno Herrera <bruherrera@gmail.com>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      e35b1350
    • J
      usb: dwc2: Make sure we disconnect the gadget state · dad3f793
      John Stultz 提交于
      I had seen some odd behavior with HiKey's usb-gadget interface
      that I finally seemed to have chased down. Basically every other
      time I plugged in the OTG port, the gadget interface would
      properly initialize. The other times, I'd get a big WARN_ON
      in dwc2_hsotg_init_fifo() about the fifo_map not being clear.
      
      Ends up if we don't disconnect the gadget state, the fifo-map
      doesn't get cleared properly, which causes WARN_ON messages and
      also results in the device not properly being setup as a gadget
      every other time the OTG port is connected.
      
      So this patch adds a call to dwc2_hsotg_disconnect() in the
      reset path so the state is properly cleared.
      
      With it, the gadget interface initializes properly on every
      plug in.
      
      Cc: Wei Xu <xuwei5@hisilicon.com>
      Cc: Guodong Xu <guodong.xu@linaro.org>
      Cc: Amit Pundir <amit.pundir@linaro.org>
      Cc: Rob Herring <robh+dt@kernel.org>
      Cc: John Youn <johnyoun@synopsys.com>
      Cc: Douglas Anderson <dianders@chromium.org>
      Cc: Chen Yu <chenyu56@huawei.com>
      Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
      Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
      Cc: linux-usb@vger.kernel.org
      Acked-by: NJohn Youn <johnyoun@synopsys.com>
      Signed-off-by: NJohn Stultz <john.stultz@linaro.org>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      dad3f793
  17. 26 1月, 2017 2 次提交
  18. 24 1月, 2017 3 次提交