1. 13 1月, 2019 1 次提交
  2. 24 9月, 2018 1 次提交
    • E
      bnx2x: remove ndo_poll_controller · d8ea6a91
      Eric Dumazet 提交于
      As diagnosed by Song Liu, ndo_poll_controller() can
      be very dangerous on loaded hosts, since the cpu
      calling ndo_poll_controller() might steal all NAPI
      contexts (for all RX/TX queues of the NIC). This capture
      can last for unlimited amount of time, since one
      cpu is generally not able to drain all the queues under load.
      
      bnx2x uses NAPI for TX completions, so we better let core
      networking stack call the napi->poll() to avoid the capture.
      Signed-off-by: NEric Dumazet <edumazet@google.com>
      Cc: Ariel Elior <ariel.elior@cavium.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      d8ea6a91
  3. 30 6月, 2018 2 次提交
  4. 26 5月, 2018 1 次提交
    • B
      bnx2x: Report PCIe link properties with pcie_print_link_status() · cc04a1dd
      Bjorn Helgaas 提交于
      Previously the driver used pcie_get_minimum_link() to warn when the NIC
      is in a slot that can't supply as much bandwidth as the NIC could use.
      
      pcie_get_minimum_link() can be misleading because it finds the slowest link
      and the narrowest link (which may be different links) without considering
      the total bandwidth of each link.  For a path with a 16 GT/s x1 link and a
      2.5 GT/s x16 link, it returns 2.5 GT/s x1, which corresponds to 250 MB/s of
      bandwidth, not the true available bandwidth of about 1969 MB/s for a
      16 GT/s x1 link.
      
      Use pcie_print_link_status() to report PCIe link speed and possible
      limitations instead of implementing this in the driver itself.  This finds
      the slowest link in the path to the device by computing the total bandwidth
      of each link and compares that with the capabilities of the device.
      
      The dmesg change is:
      
        - %s (%c%d) PCI-E x%d %s found at mem %lx, IRQ %d, node addr %pM
        + %s (%c%d) PCI-E found at mem %lx, IRQ %d, node addr %pM
        + %u.%03u Gb/s available PCIe bandwidth (%s x%d link)
      Signed-off-by: NBjorn Helgaas <bhelgaas@google.com>
      cc04a1dd
  5. 27 3月, 2018 2 次提交
  6. 22 3月, 2018 1 次提交
  7. 01 2月, 2018 1 次提交
    • D
      bnx2x: disable GSO where gso_size is too big for hardware · 8914a595
      Daniel Axtens 提交于
      If a bnx2x card is passed a GSO packet with a gso_size larger than
      ~9700 bytes, it will cause a firmware error that will bring the card
      down:
      
      bnx2x: [bnx2x_attn_int_deasserted3:4323(enP24p1s0f0)]MC assert!
      bnx2x: [bnx2x_mc_assert:720(enP24p1s0f0)]XSTORM_ASSERT_LIST_INDEX 0x2
      bnx2x: [bnx2x_mc_assert:736(enP24p1s0f0)]XSTORM_ASSERT_INDEX 0x0 = 0x00000000 0x25e43e47 0x00463e01 0x00010052
      bnx2x: [bnx2x_mc_assert:750(enP24p1s0f0)]Chip Revision: everest3, FW Version: 7_13_1
      ... (dump of values continues) ...
      
      Detect when the mac length of a GSO packet is greater than the maximum
      packet size (9700 bytes) and disable GSO.
      Signed-off-by: NDaniel Axtens <dja@axtens.net>
      Reviewed-by: NEric Dumazet <edumazet@google.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      8914a595
  8. 28 12月, 2017 1 次提交
  9. 19 12月, 2017 1 次提交
    • M
      bnx2x: Use NETIF_F_GRO_HW. · 3c3def5f
      Michael Chan 提交于
      Advertise NETIF_F_GRO_HW and turn on TPA_MODE_GRO when NETIF_F_GRO_HW
      is set.  Disable NETIF_F_GRO_HW in bnx2x_fix_features() if the MTU
      does not support TPA_MODE_GRO or GRO is not set.  bnx2x_change_mtu() also
      needs to disable NETIF_F_GRO_HW if the MTU does not support it.
      
      Original parameter disable_tpa will continue to disable LRO and GRO_HW.
      
      Preserve the original behavior of enabling LRO by default.  User has
      to run ethtool -K to explicitly enable GRO_HW.
      
      Cc: Ariel Elior <Ariel.Elior@cavium.com>
      Cc: everest-linux-l2@cavium.com
      Signed-off-by: NMichael Chan <michael.chan@broadcom.com>
      Acked-by: NManish Chopra <manish.chopra@cavium.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      3c3def5f
  10. 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
  11. 14 11月, 2017 1 次提交
    • Z
      bnx2x: fix slowpath null crash · 442866ff
      Zhu Yanjun 提交于
      When "NETDEV WATCHDOG: em4 (bnx2x): transmit queue 2 timed out" occurs,
      BNX2X_SP_RTNL_TX_TIMEOUT is set. In the function bnx2x_sp_rtnl_task,
      bnx2x_nic_unload and bnx2x_nic_load are executed to shutdown and open
      NIC. In the function bnx2x_nic_load, bnx2x_alloc_mem allocates dma
      failure. The message "bnx2x: [bnx2x_alloc_mem:8399(em4)]Can't
      allocate memory" pops out. The variable slowpath is set to NULL.
      When shutdown the NIC, the function bnx2x_nic_unload is called. In
      the function bnx2x_nic_unload, the following functions are executed.
      bnx2x_chip_cleanup
          bnx2x_set_storm_rx_mode
              bnx2x_set_q_rx_mode
                  bnx2x_set_q_rx_mode
                      bnx2x_config_rx_mode
                          bnx2x_set_rx_mode_e2
      In the function bnx2x_set_rx_mode_e2, the variable slowpath is operated.
      Then the crash occurs.
      To fix this crash, the variable slowpath is checked. And in the function
      bnx2x_sp_rtnl_task, after dma memory allocation fails, another shutdown
      and open NIC is executed.
      
      CC: Joe Jin <joe.jin@oracle.com>
      CC: Junxiao Bi <junxiao.bi@oracle.com>
      Signed-off-by: NZhu Yanjun <yanjun.zhu@oracle.com>
      Acked-by: NAriel Elior <aelior@cavium.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      442866ff
  12. 22 9月, 2017 1 次提交
  13. 25 6月, 2017 1 次提交
  14. 22 5月, 2017 1 次提交
  15. 17 5月, 2017 1 次提交
  16. 05 4月, 2017 1 次提交
  17. 08 3月, 2017 2 次提交
  18. 25 12月, 2016 1 次提交
  19. 06 12月, 2016 2 次提交
  20. 24 10月, 2016 1 次提交
  21. 18 10月, 2016 1 次提交
    • J
      ethernet/broadcom: use core min/max MTU checking · e1c6dcca
      Jarod Wilson 提交于
      tg3: min_mtu 60, max_mtu 9000/1500
      
      bnxt: min_mtu 60, max_mtu 9000
      
      bnx2x: min_mtu 46, max_mtu 9600
      - Fix up ETH_OVREHEAD -> ETH_OVERHEAD while we're in here, remove
        duplicated defines from bnx2x_link.c.
      
      bnx2: min_mtu 46, max_mtu 9000
      - Use more standard ETH_* defines while we're at it.
      
      bcm63xx_enet: min_mtu 46, max_mtu 2028
      - compute_hw_mtu was made largely pointless, and thus merged back into
        bcm_enet_change_mtu.
      
      b44: min_mtu 60, max_mtu 1500
      
      CC: netdev@vger.kernel.org
      CC: Michael Chan <michael.chan@broadcom.com>
      CC: Sony Chacko <sony.chacko@qlogic.com>
      CC: Ariel Elior <ariel.elior@qlogic.com>
      CC: Dept-HSGLinuxNICDev@qlogic.com
      CC: Siva Reddy Kallam <siva.kallam@broadcom.com>
      CC: Prashant Sreedharan <prashant@broadcom.com>
      Signed-off-by: NJarod Wilson <jarod@redhat.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      e1c6dcca
  22. 26 9月, 2016 1 次提交
  23. 07 9月, 2016 1 次提交
  24. 02 9月, 2016 1 次提交
    • G
      bnx2x: don't reset chip on cleanup if PCI function is offline · b44e108b
      Guilherme G. Piccoli 提交于
      When PCI error is detected, in some architectures (like PowerPC) a slot
      reset is performed - the driver's error handlers are in charge of "disable"
      device before the reset, and re-enable it after a successful slot reset.
      
      There are two cases though that another path is taken on the code: if the
      slot reset is not successful or if too many errors already happened in the
      specific adapter (meaning that possibly the device is experiencing a HW
      failure that slot reset is not able to solve), the core PCI error mechanism
      (called EEH in PowerPC) will remove the adapter from the system, since it
      will consider this as a permanent failure on device. In this case, a path
      is taken that leads to bnx2x_chip_cleanup() calling bnx2x_reset_hw(), which
      then tries to perform a HW reset on chip. This reset won't succeed since
      the HW is in a fault state, which can be seen by multiple messages on
      kernel log like below:
      
      	bnx2x: [bnx2x_issue_dmae_with_comp:552(eth1)]DMAE timeout!
      	bnx2x: [bnx2x_write_dmae:600(eth1)]DMAE returned failure -1
      
      After some time, the PCI error mechanism gives up on waiting the driver's
      correct removal procedure and forcibly remove the adapter from the system.
      We can see soft lockup while core PCI error mechanism is waiting for driver
      to accomplish the right removal process.
      
      This patch adds a verification to avoid a chip reset whenever the function
      is in PCI error state - since this case is only reached when we have a
      device being removed because of a permanent failure, the HW chip reset is
      not expected to work fine neither is necessary.
      
      Also, as a minor improvement in error path, we avoid the MCP information dump
      in case of non-recoverable PCI error (when adapter is about to be removed),
      since it will certainly fail.
      Reported-by: NHarsha Thyagaraja <hathyaga@in.ibm.com>
      Signed-off-by: NGuilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>
      Acked-By: NYuval Mintz <Yuval.Mintz@qlogic.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      b44e108b
  25. 25 8月, 2016 1 次提交
    • Y
      bnx2x: Don't flush multicast MACs · c7b7b483
      Yuval Mintz 提交于
      When ndo_set_rx_mode() is called for bnx2x, as part of process of
      configuring the new MAC address filters [both unicast & multicast]
      driver begins by flushing the existing configuration and then iterating
      over the network device's list of addresses and configures those instead.
      
      This has the side-effect of creating a short gap where traffic wouldn't
      be properly classified, as no filters are configured in HW.
      While for unicasts this is rather insignificant [as unicast MACs don't
      frequently change while interface is actually running],
      for multicast traffic it does pose an issue as there are multicast-based
      networks where new multicast groups would constantly be removed and
      added.
      
      This patch tries to remedy this [at least for the newer adapters] -
      Instead of flushing & reconfiguring all existing multicast filters,
      the driver would instead create the approximate hash match that would
      result from the required filters. It would then compare it against the
      currently configured approximate hash match, and only add and remove the
      delta between those.
      Signed-off-by: NYuval Mintz <Yuval.Mintz@qlogic.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      c7b7b483
  26. 18 6月, 2016 1 次提交
  27. 06 6月, 2016 1 次提交
    • M
      bnx2x: allow adding VLANs while interface is down · a02cc9d3
      Michal Schmidt 提交于
      Since implementing VLAN filtering in commit 05cc5a39
      ("bnx2x: add vlan filtering offload") bnx2x refuses to add a VLAN while
      the interface is down:
      
        # ip link add link enp3s0f0 enp3s0f0_10 type vlan id 10
        RTNETLINK answers: Bad address
      
      and in dmesg (with bnx2x.debug=0x20):
        bnx2x: [bnx2x_vlan_rx_add_vid:12941(enp3s0f0)]Ignoring VLAN
        configuration the interface is down
      
      Other drivers have no problem with this.
      Fix this peculiar behavior in the following way:
       - Accept requests to add/kill VID regardless of the device state.
         Maintain the requested list of VIDs in the bp->vlan_reg list.
       - If the device is up, try to configure the VID list into the hardware.
         If we run out of VLAN credits or encounter a failure configuring an
         entry, fall back to accepting all VLANs.
         If we successfully configure all entries from the list, turn the
         fallback off.
       - Use the same code for reconfiguring VLANs during NIC load.
      Signed-off-by: NMichal Schmidt <mschmidt@redhat.com>
      Acked-by: NYuval Mintz <Yuval.Mintz@qlogic.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      a02cc9d3
  28. 01 6月, 2016 1 次提交
  29. 21 5月, 2016 1 次提交
  30. 19 3月, 2016 1 次提交
  31. 03 3月, 2016 4 次提交
  32. 25 2月, 2016 1 次提交
    • A
      bnx2x: add a separate GENEVE Kconfig symbol · 4fee7dab
      Arnd Bergmann 提交于
      When CONFIG_GENEVE is built as a loadable module, and bnx2x is built-in,
      we get this link error:
      
      drivers/net/built-in.o: In function `bnx2x_open':
      :(.text+0x33322): undefined reference to `geneve_get_rx_port'
      drivers/net/built-in.o: In function `bnx2x_sp_rtnl_task':
      :(.text+0x3e632): undefined reference to `geneve_get_rx_port'
      
      This avoids the problem by adding a separate Kconfig symbol named
      CONFIG_BNX2X_GENEVE that is only enabled when the code is
      reachable from the driver.
      
      This is the same trick that BNX2X does for VXLAN support, and
      is similar to how I40E handles both.
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      Fixes: 883ce97d ("bnx2x: Add Geneve inner-RSS support")
      Acked-By: NYuval Mintz <Yuval.Mintz@qlogic.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      4fee7dab
  33. 17 2月, 2016 1 次提交