1. 09 1月, 2018 5 次提交
  2. 19 12月, 2017 5 次提交
    • J
      serial: max310x: Reduce RX work starvation · 22587612
      Jan Kundrát 提交于
      Prior to this patch, the code would happily trigger TX on some ports
      before having a chance of reading the RX buffer from the rest of them.
      When no flow control was used, this led to RX buffer overruns and
      therefore lost data under certain circumstances.
      
      I was able to reproduce this with MAX14830 (that's a quad channel one)
      and a simple daisy-chain of RX and TX ports on the eval board:
      
      - TX0 -> RX1
      - TX1 -> RX2
      - TX2 -> RX3
      - TX3 -> RX0
      
      I was testing this by transferring 2MB of data at 115200 baud via each
      port. I used a Solidrun Clearfog Base (Armada 388) which was talking to
      the UART over an SPI bus clocked at 26MHz (the chip's maximum). Without
      this patch, I would always get a "Possible RX FIFO overrun" in dmesg,
      and fewer-than-expected amount of bytes received over ttyMAX0. Results
      on ttyMAX{1,2,3} tended to be correct all the time, even without the
      previous patches in this series and with PIO SPI transfers ("indirect
      mode" as the Marvell datasheet calls it), so I assume that heavy
      congestion is needed in order to reproduce this.
      
      A drawback of this patch is that the throughput gets reduced "a bit".
      Previously, a 115200 baud resulted in about 11.2kBps throughput as
      reported by a simple `pv`. With this patch, the throughput of four
      parallel streams is roughly 7kBps each, and 9kBps for three streams.
      There is no slowdown for one or two parallel streams.
      
      Situation is worse if bytes are being read one-by-one (such as if the
      userspace wants to perform parity/framing/break checking) and therefore
      without the batched reads.
      
      With just this patch and no other modifications on top of 4.14, I was
      only getting roughly 3.6kBps with four parallel streams. The
      single-stream performance was the same, and I was seeing about 7.2kBps
      with two parallel streams. `perf top` said that a substantial amount of
      time was spent in `finish_task_switch`, `_raw_spin_unlock_irqrestore`
      and `__timer_delay`.
      Signed-off-by: NJan Kundrát <jan.kundrat@cesnet.cz>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      22587612
    • J
      serial: max310x: Use batched reads when reasonably safe · 2b4bac48
      Jan Kundrát 提交于
      The hardware has a 128 byte RX FIFO buffer for each independent UART.
      Previously, the code was always reading that byte-by-byte via
      independent SPI transactions and the associated overhead. In practice,
      this led to up to eight bytes over SPI for just one byte in the UART's
      RX FIFO:
      
      - reading the global IRQ register (two bytes, one for command, the other
      for data)
      - reading one UART's ISR (again two bytes)
      - reading the byte count (two bytes yet again)
      - finally, reading one byte of the FIFO via another two-byte transaction
      
      We cannot always use a batched read. If the TTY is set to intercept
      break conditions or report framing or parity errors, then it is required
      to check the Line Status Register (LSR) for each byte which is read from
      the RX FIFO. The documentation does not show a way of doing that in a
      single SPI transaction; registers 0x00 and 0x04 are separate.
      
      In my testing, this is no silver bullet. I was feeding 2MB of random
      data over four daisy-chaned UARTs of MAX14830, and this is the
      distribution that I was getting:
      
      - R <= 1: 7437322
      - R <= 2: 162093
      - R <= 4: 4093
      - R <= 8: 4196
      - R <= 16: 645
      - R <= 32: 165
      - R <= 64: 58
      - R <= 128: 0
      
      For a reference, batching the write operations works much better:
      
      - W <= 1: 2664
      - W <= 2: 1305
      - W <= 4: 627
      - W <= 8: 371
      - W <= 16: 121
      - W <= 32: 68
      - W <= 64: 33
      - W <= 128: 63139
      
      That's probably because this HW/SW combination (Clearfog Base, Armada
      388) is probably "good enough" to react to the chip's IRQ "fast enough"
      most of the time. Still, I was getting RX overruns every now and then.
      In future, I plan to improve this by letting the RX FIFO be filled a
      little more (the chip has support for that and also for a "stale
      timeout" to prevent additional starvation).
      Signed-off-by: NJan Kundrát <jan.kundrat@cesnet.cz>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      2b4bac48
    • J
      serial: max310x: use a batch write op for UART transmit · d584b65c
      Jan Kundrát 提交于
      The transmit register supports batched writes. The key is simply to keep
      sending additional bytes up to the FIFO size in the same SPI
      transaction with the CS pin still being held low.
      
      This duplicates the regmap infrastructure to a certain extent. There are
      some provisions for multiple writes in there, but there does not appear
      to be any support for those writes which are destined to the *same*
      register (and also no standard for SPI bus transfers of these, anyway).
      
      This patch does not solve every case (if the UART xmit circular buffer
      wraps around, we're still doing two SPI transactions), but at least
      it's not one-byte-per-transaction anymore.
      
      This change does not touch the receive path at this time. Doing that in
      the generic case appears to be impossible in the general case, because
      the chips' status register contains data about the *current* byte in the
      HW's Rx FIFO. We cannot read these two registers in one go,
      unfortunately.
      Signed-off-by: NJan Kundrát <jan.kundrat@cesnet.cz>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      d584b65c
    • J
      serial: max310x: Support IRQ sharing with other devices · 78be70c8
      Jan Kundrát 提交于
      According to my chip's datasheet [1], the IRQ output is an open
      collector pin which is suitable for sharing with other chips. The chip
      also has a register which indicates which UART performed a change and
      the driver checks that register already, so we have everything what is
      needed to effectively share the IRQ GPIO.
      
      [1] https://datasheets.maximintegrated.com/en/ds/MAX14830.pdfSigned-off-by: NJan Kundrát <jan.kundrat@cesnet.cz>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      78be70c8
    • J
      serial: max310x: Do not hard-code the IRQ type · bceb4839
      Jan Kundrát 提交于
      As suggested by Russell King, a driver should not really care about bits
      such as the interrupt polarity or whether it is edge- or level-
      triggered. The reasons for that include:
      
      - an upstream IRQ controller which cannot support edge- or
      level-triggered interrupts,
      - board design with a built-in inverter
      
      The interrupt type is being already specified by the Device Tree,
      anyway. Other drivers (gpio/gpio-tc3589x.c for example) already work in
      this way, delegating the proper IRQ line setup to the DT and not
      specifying anything by hand.
      
      Also, there's no reason to have the IRQ flags split between two places.
      The SPI probing is the only entry point anyway.
      Signed-off-by: NJan Kundrát <jan.kundrat@cesnet.cz>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      bceb4839
  3. 18 12月, 2017 1 次提交
  4. 16 12月, 2017 10 次提交
  5. 28 11月, 2017 12 次提交
  6. 22 11月, 2017 2 次提交
    • K
      treewide: Remove TIMER_FUNC_TYPE and TIMER_DATA_TYPE casts · 841b86f3
      Kees Cook 提交于
      With all callbacks converted, and the timer callback prototype
      switched over, the TIMER_FUNC_TYPE cast is no longer needed,
      so remove it. Conversion was done with the following scripts:
      
          perl -pi -e 's|\(TIMER_FUNC_TYPE\)||g' \
              $(git grep TIMER_FUNC_TYPE | cut -d: -f1 | sort -u)
      
          perl -pi -e 's|\(TIMER_DATA_TYPE\)||g' \
              $(git grep TIMER_DATA_TYPE | cut -d: -f1 | sort -u)
      
      The now unused macros are also dropped from include/linux/timer.h.
      Signed-off-by: NKees Cook <keescook@chromium.org>
      841b86f3
    • 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
  7. 08 11月, 2017 5 次提交
    • T
      tty: serial: meson: allow baud-rates lower than 9600 · 9b11f19e
      Thomas Rohloff 提交于
      Devices like DCF77 receivers need the baud-rate to be as low as 50.
      
      I have tested this on a Meson GXL device with uart_A.
      
      Cc: Jiri Slaby <jslaby@suse.com>
      Cc: Carlo Caione <carlo@caione.org>
      Cc: Kevin Hilman <khilman@baylibre.com>
      Cc: linux-amlogic@lists.infradead.org
      Cc: linux-arm-kernel@lists.infradead.org
      Cc: linux-kernel@vger.kernel.org
      Signed-off-by: NThomas Rohloff <v10lator@myway.de>
      Reviewed-by: NNeil Armstrong <narmstrong@baylibre.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      9b11f19e
    • J
      serial: 8250_fintek: Fix crash with baud rate B0 · 07a708f0
      Ji-Ze Hong (Peter Hong) 提交于
      The 8250_fintek.c is support the Fintek F81866/F81216 with dynamic clock.
      But It'll generate "division by zero" exception and crash in
      fintek_8250_set_termios() with baud rate 0 on baudrate_table[i] % baud.
      
      It can be tested with following C code:
      
      	...
      	struct termios options;
      
      	tcgetattr(fd, &options);
      	...
      	options.c_cflag = CS8 | CREAD; /* baud rate 0 */
      	tcsetattr(fd, TCSANOW, &options);
      	tcflush(fd, TCIOFLUSH);
      
      Fixes: 195638b6 ("serial: 8250_fintek: UART dynamic clocksource on Fintek F81866")
      Reported-by: NLukas Redlinger <rel+kernel@agilox.net>
      Cc: Lukas Redlinger <rel+kernel@agilox.net>
      Signed-off-by: NJi-Ze Hong (Peter Hong) <hpeter+linux_kernel@gmail.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      07a708f0
    • R
      serial: 8250_fintek: Disable delays for ports != 0 · 21c4e7f2
      Ricardo Ribalda Delgado 提交于
      According to the datasheet, only the first port supports delay before
      send and delay after send.
      Reported-by: N"Ji-Ze Hong (Peter Hong)" <hpeter@gmail.com>
      Signed-off-by: NRicardo Ribalda Delgado <ricardo.ribalda@gmail.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      21c4e7f2
    • R
      serial: 8250_fintek: Return -EINVAL on invalid configuration · 7ecc7701
      Ricardo Ribalda Delgado 提交于
      Hardware does not support having the same RTS level during RX and TX
      when RS485 mode is on (URA in Fintek terminology).
      
      The manufacturer has also confirmed that the delays are not enabled if
      the RS485 mode is not enabled.
      
      Therefore we should return -EINVAL if the user wants to have the same
      value for RTS_ON_SEND and RTS_AFTER_SEND.
      
      Cc: "Ji-Ze Hong (Peter Hong)" <hpeter@gmail.com>
      Cc: Lukas Wunner <lukas@wunner.de>
      Signed-off-by: NRicardo Ribalda Delgado <ricardo.ribalda@gmail.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      7ecc7701
    • G
      tty: serial: Remove redundant license text · 4793f2eb
      Greg Kroah-Hartman 提交于
      Now that the SPDX tag is in all tty files, that identifies the license
      in a specific and legally-defined manner.  So the extra GPL text wording
      can be removed as it is no longer needed at all.
      
      This is done on a quest to remove the 700+ different ways that files in
      the kernel describe the GPL license text.  And there's unneeded stuff
      like the address (sometimes incorrect) for the FSF which is never
      needed.
      
      No copyright headers or other non-license-description text was removed.
      
      Cc: Jiri Slaby <jslaby@suse.com>
      Cc: Eric Anholt <eric@anholt.net>
      Cc: Stefan Wahren <stefan.wahren@i2se.com>
      Cc: Florian Fainelli <f.fainelli@gmail.com>
      Cc: Ray Jui <rjui@broadcom.com>
      Cc: Scott Branden <sbranden@broadcom.com>
      Cc: bcm-kernel-feedback-list@broadcom.com
      Cc: "James E.J. Bottomley" <jejb@parisc-linux.org>
      Cc: Helge Deller <deller@gmx.de>
      Cc: Joachim Eastwood <manabian@gmail.com>
      Cc: Matthias Brugger <matthias.bgg@gmail.com>
      Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
      Cc: Tobias Klauser <tklauser@distanz.ch>
      Cc: Russell King <linux@armlinux.org.uk>
      Cc: Vineet Gupta <vgupta@synopsys.com>
      Cc: Richard Genoud <richard.genoud@gmail.com>
      Cc: Alexander Shiyan <shc_work@mail.ru>
      Cc: Baruch Siach <baruch@tkos.co.il>
      Cc: Pat Gefre <pfg@sgi.com>
      Cc: "Guilherme G. Piccoli" <gpiccoli@linux.vnet.ibm.com>
      Cc: Jason Wessel <jason.wessel@windriver.com>
      Cc: Vladimir Zapolskiy <vz@mleia.com>
      Cc: Sylvain Lemieux <slemieux.tyco@gmail.com>
      Cc: Carlo Caione <carlo@caione.org>
      Cc: Kevin Hilman <khilman@baylibre.com>
      Cc: Liviu Dudau <liviu.dudau@arm.com>
      Cc: Sudeep Holla <sudeep.holla@arm.com>
      Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
      Cc: Andy Gross <andy.gross@linaro.org>
      Cc: David Brown <david.brown@linaro.org>
      Cc: "Andreas Färber" <afaerber@suse.de>
      Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
      Cc: Paul Mackerras <paulus@samba.org>
      Cc: Michael Ellerman <mpe@ellerman.id.au>
      Cc: Kevin Cernekee <cernekee@gmail.com>
      Cc: Laxman Dewangan <ldewangan@nvidia.com>
      Cc: Thierry Reding <thierry.reding@gmail.com>
      Cc: Jonathan Hunter <jonathanh@nvidia.com>
      Cc: Barry Song <baohua@kernel.org>
      Cc: Patrice Chotard <patrice.chotard@st.com>
      Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
      Cc: Alexandre Torgue <alexandre.torgue@st.com>
      Cc: Chris Metcalf <cmetcalf@mellanox.com>
      Cc: Peter Korsgaard <jacmet@sunsite.dk>
      Cc: Timur Tabi <timur@tabi.org>
      Cc: Tony Prisk <linux@prisktech.co.nz>
      Cc: Michal Simek <michal.simek@xilinx.com>
      Cc: "Sören Brinkmann" <soren.brinkmann@xilinx.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      4793f2eb