Netdev List
 help / color / mirror / Atom feed
* [PATCH v2] xen-netback: fix error handling on netback_probe()
From: Filipe Manco @ 2016-09-15 15:10 UTC (permalink / raw)
  To: netdev; +Cc: wei.liu2, xen-devel, Filipe Manco

In case of error during netback_probe() (e.g. an entry missing on the
xenstore) netback_remove() is called on the new device, which will set
the device backend state to XenbusStateClosed by calling
set_backend_state(). However, the backend state wasn't initialized by
netback_probe() at this point, which will cause and invalid transaction
and set_backend_state() to BUG().

Initialize the backend state at the beginning of netback_probe() to
XenbusStateInitialising, and create two new valid state transitions on
set_backend_state(), from XenbusStateInitialising to XenbusStateClosed,
and from XenbusStateInitialising to XenbusStateInitWait.

Signed-off-by: Filipe Manco <filipe.manco@neclab.eu>
---
 drivers/net/xen-netback/xenbus.c | 46 ++++++++++++++++++++++++++--------------
 1 file changed, 30 insertions(+), 16 deletions(-)

diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 6a31f2610c23..daf4c7867102 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -271,6 +271,11 @@ static int netback_probe(struct xenbus_device *dev,
 	be->dev = dev;
 	dev_set_drvdata(&dev->dev, be);
 
+	be->state = XenbusStateInitialising;
+	err = xenbus_switch_state(dev, XenbusStateInitialising);
+	if (err)
+		goto fail;
+
 	sg = 1;
 
 	do {
@@ -383,11 +388,6 @@ static int netback_probe(struct xenbus_device *dev,
 
 	be->hotplug_script = script;
 
-	err = xenbus_switch_state(dev, XenbusStateInitWait);
-	if (err)
-		goto fail;
-
-	be->state = XenbusStateInitWait;
 
 	/* This kicks hotplug scripts, so do it immediately. */
 	err = backend_create_xenvif(be);
@@ -492,20 +492,20 @@ static inline void backend_switch_state(struct backend_info *be,
 
 /* Handle backend state transitions:
  *
- * The backend state starts in InitWait and the following transitions are
+ * The backend state starts in Initialising and the following transitions are
  * allowed.
  *
- * InitWait -> Connected
- *
- *    ^    \         |
- *    |     \        |
- *    |      \       |
- *    |       \      |
- *    |        \     |
- *    |         \    |
- *    |          V   V
+ * Initialising -> InitWait -> Connected
+ *          \
+ *           \        ^    \         |
+ *            \       |     \        |
+ *             \      |      \       |
+ *              \     |       \      |
+ *               \    |        \     |
+ *                \   |         \    |
+ *                 V  |          V   V
  *
- *  Closed  <-> Closing
+ *                  Closed  <-> Closing
  *
  * The state argument specifies the eventual state of the backend and the
  * function transitions to that state via the shortest path.
@@ -515,6 +515,20 @@ static void set_backend_state(struct backend_info *be,
 {
 	while (be->state != state) {
 		switch (be->state) {
+		case XenbusStateInitialising:
+			switch (state) {
+			case XenbusStateInitWait:
+			case XenbusStateConnected:
+			case XenbusStateClosing:
+				backend_switch_state(be, XenbusStateInitWait);
+				break;
+			case XenbusStateClosed:
+				backend_switch_state(be, XenbusStateClosed);
+				break;
+			default:
+				BUG();
+			}
+			break;
 		case XenbusStateClosed:
 			switch (state) {
 			case XenbusStateInitWait:
-- 
2.7.4

^ permalink raw reply related

* pull-request: wireless-drivers-next 2016-09-15
From: Kalle Valo @ 2016-09-15 15:09 UTC (permalink / raw)
  To: David Miller; +Cc: linux-wireless, netdev, linux-kernel

Hi Dave,

here's the first pull request for 4.9. The ones I want to point out are
the FIELD_PREP() and FIELD_GET() macros added to bitfield.h, which are
reviewed by Linus, and make it possible to remove util.h from mt7601u.

Also we have new HW support to various drivers and other smaller
features, the signed tag below contains more information. And I pulled
my ath-current (uses older net tree as the baseline) branch to fix a
conflict in ath10k.

Once again the diffstat from git request-pull was wrong. I fixed it by
manually copying the diffstat from a test pull against net-next, so
everything should be ok. But please let me know if there are any
problems.

Kalle

The following changes since commit e34f2ff40e0339f6a379e1ecf49e8f2759056453:

  ath9k: bring back direction setting in ath9k_{start_stop} (2016-09-07 16:21:04 +0300)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git tags/wireless-drivers-next-for-davem-2016-09-15

for you to fetch changes up to b7450e248d71067e0c1a09614cf3d7571f7e10fa:

  mwifiex: firmware name correction for usb8997 chipset (2016-09-14 20:02:14 +0300)

----------------------------------------------------------------
wireless-drivers-next patches for 4.9

Major changes:

iwlwifi

* preparation for new a000 HW continues
* some DQA improvements
* add support for GMAC
* add support for 9460, 9270 and 9170 series

mwifiex

* support random MAC address for scanning
* add HT aggregation support for adhoc mode
* add custom regulatory domain support
* add manufacturing mode support via nl80211 testmode interface

bcma

* support BCM53573 series of wireless SoCs

bitfield.h

* add FIELD_PREP() and FIELD_GET() macros

mt7601u

* convert to use the new bitfield.h macros

brcmfmac

* add support for bcm4339 chip with modalias sdio:c00v02D0d4339

ath10k

* add nl80211 testmode support for 10.4 firmware
* hide kernel addresses from logs using %pK format specifier
* implement NAPI support
* enable peer stats by default

ath9k

* use ieee80211_tx_status_noskb where possible

wil6210

* extract firmware capabilities from the firmware file

ath6kl

* enable firmware crash dumps on the AR6004

ath-current is also merged to fix a conflict in ath10k.

----------------------------------------------------------------
Amitkumar Karwar (8):
      mwifiex: fix failed to reconnect after interface disabled/enabled
      mwifiex: remove misleading disconnect message
      mwifiex: add CHAN_REGION_CFG command
      mwifiex: add custom regulatory domain support
      mwifiex: add PCIe function level reset support
      mwifiex: PCIe8997 chip specific handling
      mwifiex: handle error if IRQ request fails in mwifiex_sdio_of()
      mwifiex: correction in Rx STBC field of htcapinfo

Arend Van Spriel (2):
      brcmfmac: add support for bcm4339 chip with modalias sdio:c00v02D0d4339
      brcmfmac: sdio: shorten retry loop in brcmf_sdio_kso_control()

Arnd Bergmann (1):
      bcma: use of_dma_configure() to set initial dma mask

Ashok Raj Nagarajan (2):
      ath10k: fix sending frame in management path in push txq logic
      ath10k: fix reporting channel survey data

Ayala Beker (1):
      iwlwifi: mvm: support GMAC protocol

Baoyou Xie (2):
      ath9k: mark ath_fill_led_pin() static
      brcmfmac: add missing header dependencies

Ben Greear (1):
      ath10k: improve logging message

Bob Copeland (2):
      ath9k: fix misleading indent
      ath9k: remove repetitions of mask array size

Chaehyun Lim (1):
      ath10k: remove unused variable ar_pci

Christian Engelmayer (2):
      rtlwifi: rtl8192de: Fix leak in _rtl92de_read_adapter_info()
      rtlwifi: rtl8723ae: Fix leak in _rtl8723e_read_adapter_info()

Christophe Jaillet (4):
      mwifiex: fix the length parameter of a memset
      mwifiex: simplify length computation for some memset
      rt2x00usb: Fix error return code
      mwifiex: scan: Simplify code

Colin Ian King (5):
      ath10k: fix spelling mistake "montior" -> "monitor"
      mwifiex: fix missing break on IEEE80211_STYPE_ACTION case
      zd1211rw: fix spelling mistake "firmeware" -> "firmware"
      ath10k: fix memory leak on caldata on error exit path
      rtl8xxxu: fix spelling mistake "firmare" -> "firmware"

Dan Kephart (1):
      ath6kl: enable firmware crash dumps on the AR6004

Daniel Wagner (2):
      ath10k: use complete() instead complete_all()
      carl9170: Fix wrong completion usage

Eduardo Abinader (1):
      ath9k: consider return code on

Eric Bentley (1):
      ath6kl: Allow the radio to report 0 dbm txpower without timing out

Felix Fietkau (2):
      ath9k: use ieee80211_tx_status_noskb where possible
      ath9k: improve powersave filter handling

Ganapathi Bhat (4):
      mwifiex: support random MAC address for scanning
      mwifiex: fix radar detection issue
      mwifiex: Command 7 handling for USB chipsets
      mwifiex: firmware name correction for usb8997 chipset

Guy Mishol (1):
      wl18xx: add time sync configuration api

Hans de Goede (1):
      rtl8xxxu: Make rtl8xxxu_ampdu_action less chatty

Heinrich Schuchardt (3):
      mwifiex: remove superfluous condition
      mwifiex: key_material_v2 remove superfluous condition
      rtlwifi: remove superfluous condition

Ismael Luceno (1):
      brcmfmac: Add USB ID for Cisco Linksys AE1200

Jakub Kicinski (4):
      add basic register-field manipulation macros
      mt7601u: remove redefinition of GENMASK
      mt7601u: remove unnecessary include
      mt7601u: use linux/bitfield.h

Jes Sorensen (19):
      rtl8xxxu: Mark 0x20f4:0x648b as tested
      rtl8xxxu: Mark 0x2001:0x3308 as tested
      rtl8xxxu: Fix error handling if rtl8xxxu_init_device() fails
      rtl8xxxu: Add TP-Link TL-WN823N v2 to list of supported devices
      rtl8xxxu: Add TX page defines for 8723b
      rtl8xxxu: Switch 8723a to use new rtl8xxxu_init_queue_reserved_page() routine
      rtl8xxxu: Switch 8192cu/8188cu devices to use rtl8xxxu_init_queue_reserved_page()
      rtl8xxxu: Remove now obsolete rtl8xxxu_old_init_queue_reserved_page()
      rtl8xxxu: Simplify code setting TX buffer boundary
      rtl8xxxu: Add bit definitions for REG_FPGA0_TX_INFO
      rtl8xxxu: Add interrupt bit definitions for gen2 parts
      rtl8xxxu: Use flag to indicate whether device has TX report timer support
      rtl8xxxu: Convert flags in rtl8xxxu_fileops to bitflags
      rtl8xxxu: Introduce fops bitflag indicating type of thermal meter
      rtl8xxxu: Simplify calculating of hw value used for setting TX rate
      rtl8xxxu: Determine the need for SGI before handling specific TX desc formats
      rtl8xxxu: Determine need for shore preamble before updating TX descriptors
      rtl8xxxu: Split filling of TX descriptors into separate functions
      rtl8xxxu: Reset device on module unload if still attached

Julia Lawall (3):
      ath: constify local structures
      iwlegacy: constify local structures
      rtlwifi: rtl818x: constify local structures

Kalle Valo (3):
      Merge tag 'iwlwifi-next-for-kalle-2016-08-30-2' of git://git.kernel.org/.../iwlwifi/iwlwifi-next
      Merge branch 'ath-current' into ath-next
      Merge ath-next from git://git.kernel.org/.../kvalo/ath.git

Karthik D A (2):
      mwifiex: Fixed endianness problem for big endian platform
      mwifiex: add region code information in debugfs

Larry Finger (1):
      rtlwifi: Fix missing country code for Great Britain

Lazar Alexei (1):
      wil6210: Fix driver down flow

Liad Kaufman (5):
      iwlwifi: mvm: re-aggregate shared queue after unsharing
      iwlwifi: mvm: keep track of tid associated with each queue
      iwlwifi: mvm: re-assign old queues after hw restart in dqa mode
      iwlwifi: mvm: use defines for SCD_CONFIG_CMD enablement
      iwlwifi: mvm: support txq tid owner change

Lior David (6):
      wil6210: change HALP logging category to IRQ
      wil6210: fix wiphy registration sequence
      wil6210: fix protection of wil->scan_request
      wil6210: align to latest auto generated wmi.h
      wil6210: extract firmware capabilities from FW file
      wil6210: extract firmware version from file header

Maharaja Kennadyrajan (2):
      ath10k: hide kernel addresses from logs using %pK format specifier
      ath10k: Added support for extended dbglog module id for 10.4

Masahiro Yamada (1):
      ath10k: replace config_enabled() with IS_REACHABLE()

Maxim Altshul (1):
      wlcore: Remove wl pointer from wl_sta structure

Maya Erez (5):
      wil6210: align to latest auto generated wmi.h
      wil6210: fix HALP handling in case of HALP vote time-out
      wil6210: support rx key setting for all TIDs
      wil6210: fix stop p2p device handling
      wil6210: prevent usage of incorrect TX hwtail

Michal Kazior (4):
      ath10k: implement wmi echo command
      ath10k: implement wmi echo event
      ath10k: add wmi command barrier utility
      ath10k: fix spurious tx/rx during boot

Mohammed Shafi Shajakhan (3):
      ath10k: suppress warnings when getting wmi WDS peer event id
      ath10k: Fix broken NULL func data frame status for 10.4
      ath10k: remove unnecessary error code assignment

Nicolas Iooss (1):
      brcmfmac: fix pmksa->bssid usage

Oleg Drokin (1):
      rtlwifi/rtl8192de: Fix print format string

Oren Givon (5):
      iwlwifi: rename and reorder 9000 series configuration structs
      iwlwifi: add a new series 9460 with new PCI ID
      iwlwifi: add new 9460 series PCI IDs
      iwlwifi: add the new 9270 series
      iwlwifi: add the new 9170 series

Pavel Andrianov (1):
      wl3501_cs: Add spinlock to wl3501_reset

Rafał Miłecki (1):
      bcma: support BCM53573 series of wireless SoCs

Rajan Vaja (1):
      hostap: Use memdup_user() to reuse code

Rajkumar Manoharan (4):
      ath10k: fix group privacy action frame decryption for qca4019
      ath10k: improve wake_tx_queue ops performance
      ath10k: implement NAPI support
      ath10k: fix throughput regression in multi client mode

Sara Sharon (5):
      iwlwifi: mvm: allow same PN for de-aggregated AMSDU
      iwlwifi: mvm: support new paging command format
      iwlwifi: pcie: refrain from SCD accesses
      iwlwifi: pcie: fix ucode load flow for a000 devices
      iwlwifi: pcie: remove dead code

Sergey Ryazanov (1):
      ath5k: fix EEPROM dumping via debugfs

Stanislaw Gruszka (3):
      mwifiex: make "PCI-E is not the winner" print more informative
      mwifiex: print status of FW ready event
      mwifiex: do not print dot when downloading FW

Tamizh chelvam (4):
      ath10k: move firmware_swap_code_seg_info to ath10k_fw_file
      ath10k: handle testmode events for 10.2 and 10.4 based firmware
      ath10k: add testmode support for 10.4 firmware
      ath10k: Add WMI_SERVICE_PERIODIC_CHAN_STAT_SUPPORT wmi service

Thomas Pedersen (1):
      ath10k: enable peer stats by default

Vasanthakumar Thiagarajan (4):
      ath10k: move ath10k_hw_params definition to hw.h
      ath10k: add provision for Rx descriptor abstraction
      ath10k: properly remove padding from the start of rx payload
      ath10k: remove 4-addr padding related hw_param configuration

Wei Yongjun (2):
      wlcore: spi: fix non static symbol warning
      rtl8xxxu: gen1: Fix non static symbol warning

Xinming Hu (5):
      mwifiex: process rxba_sync event
      mwifiex: add HT aggregation support for adhoc mode
      mwifiex: correct aid value during tdls setup
      mwifiex: add manufacturing mode support
      mwifiex: add cfg80211 testmode support

>From git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
 * tag                         wireless-drivers-next-for-davem-2016-09-15 -> FETCH_HEAD
Removing drivers/net/wireless/mediatek/mt7601u/util.h
Auto-merging drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
Auto-merging drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
Auto-merging drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
Merge made by the 'recursive' strategy.
 drivers/bcma/driver_chipcommon.c                   |   32 +-
 drivers/bcma/main.c                                |    6 +-
 drivers/net/wireless/ath/ath10k/ahb.c              |   12 +-
 drivers/net/wireless/ath/ath10k/bmi.c              |    4 +-
 drivers/net/wireless/ath/ath10k/ce.c               |    4 +-
 drivers/net/wireless/ath/ath10k/core.c             |  125 ++-
 drivers/net/wireless/ath/ath10k/core.h             |   79 +-
 drivers/net/wireless/ath/ath10k/debug.c            |   11 +-
 drivers/net/wireless/ath/ath10k/htc.c              |    6 +-
 drivers/net/wireless/ath/ath10k/htt.h              |    2 +-
 drivers/net/wireless/ath/ath10k/htt_rx.c           |  194 ++--
 drivers/net/wireless/ath/ath10k/htt_tx.c           |    2 -
 drivers/net/wireless/ath/ath10k/hw.c               |   13 +
 drivers/net/wireless/ath/ath10k/hw.h               |   76 +-
 drivers/net/wireless/ath/ath10k/mac.c              |   70 +-
 drivers/net/wireless/ath/ath10k/pci.c              |   77 +-
 drivers/net/wireless/ath/ath10k/pci.h              |    6 +-
 drivers/net/wireless/ath/ath10k/swap.c             |   26 +-
 drivers/net/wireless/ath/ath10k/swap.h             |   11 +-
 drivers/net/wireless/ath/ath10k/testmode.c         |   27 +-
 drivers/net/wireless/ath/ath10k/thermal.c          |    2 +-
 drivers/net/wireless/ath/ath10k/txrx.c             |    4 +-
 drivers/net/wireless/ath/ath10k/wmi-ops.h          |   33 +-
 drivers/net/wireless/ath/ath10k/wmi-tlv.c          |   59 +-
 drivers/net/wireless/ath/ath10k/wmi.c              |  186 +++-
 drivers/net/wireless/ath/ath10k/wmi.h              |   24 +
 drivers/net/wireless/ath/ath5k/debug.c             |    6 +-
 drivers/net/wireless/ath/ath6kl/cfg80211.c         |    4 +-
 drivers/net/wireless/ath/ath6kl/hif.c              |   11 +-
 drivers/net/wireless/ath/ath9k/ar5008_phy.c        |    9 +-
 drivers/net/wireless/ath/ath9k/ar9003_eeprom.c     |    6 +-
 drivers/net/wireless/ath/ath9k/gpio.c              |    2 +-
 drivers/net/wireless/ath/ath9k/main.c              |    2 +-
 drivers/net/wireless/ath/ath9k/xmit.c              |  104 ++-
 drivers/net/wireless/ath/carl9170/usb.c            |    6 +-
 drivers/net/wireless/ath/dfs_pattern_detector.c    |    2 +-
 drivers/net/wireless/ath/wil6210/cfg80211.c        |  151 ++--
 drivers/net/wireless/ath/wil6210/debugfs.c         |   53 +-
 drivers/net/wireless/ath/wil6210/fw.h              |   14 +-
 drivers/net/wireless/ath/wil6210/fw_inc.c          |   92 +-
 drivers/net/wireless/ath/wil6210/interrupt.c       |   15 +-
 drivers/net/wireless/ath/wil6210/main.c            |   63 +-
 drivers/net/wireless/ath/wil6210/netdev.c          |   34 +-
 drivers/net/wireless/ath/wil6210/p2p.c             |   46 +
 drivers/net/wireless/ath/wil6210/pcie_bus.c        |    9 +-
 drivers/net/wireless/ath/wil6210/txrx.c            |    9 +-
 drivers/net/wireless/ath/wil6210/wil6210.h         |   11 +-
 drivers/net/wireless/ath/wil6210/wmi.c             |   12 +-
 drivers/net/wireless/ath/wil6210/wmi.h             |  932 ++++++++++++++++++--
 .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c  |    1 +
 .../broadcom/brcm80211/brcmfmac/cfg80211.c         |    4 +-
 .../wireless/broadcom/brcm80211/brcmfmac/sdio.c    |   14 +-
 .../broadcom/brcm80211/brcmfmac/tracepoint.c       |    1 +
 .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c |    4 +
 .../broadcom/brcm80211/include/brcm_hw_ids.h       |    2 +
 drivers/net/wireless/intel/iwlegacy/3945.c         |    4 +-
 drivers/net/wireless/intel/iwlwifi/iwl-9000.c      |   83 +-
 drivers/net/wireless/intel/iwlwifi/iwl-config.h    |    6 +-
 drivers/net/wireless/intel/iwlwifi/iwl-fh.h        |   15 +-
 drivers/net/wireless/intel/iwlwifi/iwl-prph.h      |   19 +-
 .../net/wireless/intel/iwlwifi/mvm/fw-api-sta.h    |   31 +-
 drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h |   12 +-
 drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h    |    8 +-
 drivers/net/wireless/intel/iwlwifi/mvm/fw.c        |   28 +-
 drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c  |   18 +-
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h       |   26 +-
 drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c      |    6 +-
 drivers/net/wireless/intel/iwlwifi/mvm/sta.c       |  342 ++++++-
 drivers/net/wireless/intel/iwlwifi/mvm/sta.h       |    4 +
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c        |   38 +-
 drivers/net/wireless/intel/iwlwifi/mvm/utils.c     |   24 +-
 drivers/net/wireless/intel/iwlwifi/pcie/drv.c      |   41 +-
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c    |   45 +-
 drivers/net/wireless/intel/iwlwifi/pcie/tx.c       |   13 +-
 .../net/wireless/intersil/hostap/hostap_ioctl.c    |   20 +-
 drivers/net/wireless/marvell/mwifiex/11h.c         |   27 +-
 drivers/net/wireless/marvell/mwifiex/11n.h         |    7 +-
 .../net/wireless/marvell/mwifiex/11n_rxreorder.c   |   78 +-
 .../net/wireless/marvell/mwifiex/11n_rxreorder.h   |    3 +-
 drivers/net/wireless/marvell/mwifiex/cfg80211.c    |  143 ++-
 drivers/net/wireless/marvell/mwifiex/cmdevt.c      |   26 +-
 drivers/net/wireless/marvell/mwifiex/debugfs.c     |    2 +
 drivers/net/wireless/marvell/mwifiex/fw.h          |   73 +-
 drivers/net/wireless/marvell/mwifiex/init.c        |   22 +-
 drivers/net/wireless/marvell/mwifiex/join.c        |    3 +-
 drivers/net/wireless/marvell/mwifiex/main.c        |  270 +++++-
 drivers/net/wireless/marvell/mwifiex/main.h        |    7 +
 drivers/net/wireless/marvell/mwifiex/pcie.c        |  182 +++-
 drivers/net/wireless/marvell/mwifiex/pcie.h        |   13 +-
 drivers/net/wireless/marvell/mwifiex/scan.c        |   28 +-
 drivers/net/wireless/marvell/mwifiex/sdio.c        |    6 +-
 drivers/net/wireless/marvell/mwifiex/sta_cmd.c     |   61 +-
 drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c |  134 ++-
 drivers/net/wireless/marvell/mwifiex/sta_event.c   |  144 ++-
 drivers/net/wireless/marvell/mwifiex/sta_ioctl.c   |    6 +-
 drivers/net/wireless/marvell/mwifiex/uap_event.c   |    7 +-
 drivers/net/wireless/marvell/mwifiex/usb.c         |    6 +-
 drivers/net/wireless/marvell/mwifiex/usb.h         |    3 +-
 drivers/net/wireless/marvell/mwifiex/util.c        |    1 +
 drivers/net/wireless/mediatek/mt7601u/dma.c        |    2 +-
 drivers/net/wireless/mediatek/mt7601u/dma.h        |   10 +-
 drivers/net/wireless/mediatek/mt7601u/eeprom.c     |   12 +-
 drivers/net/wireless/mediatek/mt7601u/init.c       |   10 +-
 drivers/net/wireless/mediatek/mt7601u/mac.c        |   38 +-
 drivers/net/wireless/mediatek/mt7601u/main.c       |    1 -
 drivers/net/wireless/mediatek/mt7601u/mcu.c        |   20 +-
 drivers/net/wireless/mediatek/mt7601u/mt7601u.h    |    4 +-
 drivers/net/wireless/mediatek/mt7601u/phy.c        |   44 +-
 drivers/net/wireless/mediatek/mt7601u/regs.h       |    4 -
 drivers/net/wireless/mediatek/mt7601u/tx.c         |   19 +-
 drivers/net/wireless/mediatek/mt7601u/util.h       |   77 --
 drivers/net/wireless/ralink/rt2x00/rt2x00usb.c     |    4 +-
 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h   |   22 +-
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c |    5 +
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c |    2 +
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c |    5 +
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c |    7 +
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c  |  328 +++----
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h  |   60 ++
 drivers/net/wireless/realtek/rtlwifi/core.c        |    2 +-
 drivers/net/wireless/realtek/rtlwifi/regd.c        |    4 +-
 .../net/wireless/realtek/rtlwifi/rtl8188ee/sw.c    |    2 +-
 .../net/wireless/realtek/rtlwifi/rtl8192ce/sw.c    |    2 +-
 .../net/wireless/realtek/rtlwifi/rtl8192de/hw.c    |    3 +-
 .../net/wireless/realtek/rtlwifi/rtl8192de/phy.c   |    6 +-
 .../net/wireless/realtek/rtlwifi/rtl8192de/sw.c    |    2 +-
 .../net/wireless/realtek/rtlwifi/rtl8192ee/sw.c    |    2 +-
 .../net/wireless/realtek/rtlwifi/rtl8192se/sw.c    |    2 +-
 .../net/wireless/realtek/rtlwifi/rtl8723ae/hw.c    |    2 +-
 .../net/wireless/realtek/rtlwifi/rtl8723ae/sw.c    |    2 +-
 .../net/wireless/realtek/rtlwifi/rtl8723be/sw.c    |    2 +-
 .../net/wireless/realtek/rtlwifi/rtl8821ae/sw.c    |    2 +-
 drivers/net/wireless/ti/wl18xx/acx.c               |   29 +
 drivers/net/wireless/ti/wl18xx/acx.h               |   13 +
 drivers/net/wireless/ti/wl18xx/event.c             |    1 +
 drivers/net/wireless/ti/wlcore/main.c              |    1 -
 drivers/net/wireless/ti/wlcore/spi.c               |    2 +-
 drivers/net/wireless/ti/wlcore/wlcore.h            |    3 +
 drivers/net/wireless/ti/wlcore/wlcore_i.h          |    1 -
 drivers/net/wireless/wl3501_cs.c                   |    7 +-
 drivers/net/wireless/zydas/zd1211rw/zd_usb.c       |    2 +-
 include/linux/bitfield.h                           |   93 ++
 include/linux/bug.h                                |    3 +
 include/linux/mmc/sdio_ids.h                       |    1 +
 144 files changed, 4390 insertions(+), 1218 deletions(-)
 delete mode 100644 drivers/net/wireless/mediatek/mt7601u/util.h
 create mode 100644 include/linux/bitfield.h

-- 
Kalle Valo

^ permalink raw reply

* Re: [PATCH V3 1/3] Documentation: devicetree: add qca8k binding
From: Andrew Lunn @ 2016-09-15 14:54 UTC (permalink / raw)
  To: John Crispin
  Cc: David S. Miller, Florian Fainelli, linux-kernel, netdev,
	qsdk-review, devicetree
In-Reply-To: <1473949601-20674-2-git-send-email-john@phrozen.org>

B1;2802;0cOn Thu, Sep 15, 2016 at 04:26:39PM +0200, John Crispin wrote:
> Add device-tree binding for ar8xxx switch families.
> 
> Cc: devicetree@vger.kernel.org
> Signed-off-by: John Crispin <john@phrozen.org>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply

* Re: [net-next,RFC,1/2] fib: introduce fib notification infrastructure
From: Andy Gospodarek @ 2016-09-15 14:47 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: netdev@vger.kernel.org, David Miller, idosch, eladr, yotamg,
	nogahf, ogerlitz, Roopa Prabhu, nikolay, John Linville,
	Thomas Graf, Scott Feldman, ast, Eric Dumazet, hannes,
	Florian Fainelli, dsa, Jamal Hadi Salim, vivien.didelot,
	john.fastabend, andrew, ivecera
In-Reply-To: <20160915144516.GD6790@nanopsycho>

On Thu, Sep 15, 2016 at 10:45 AM, Jiri Pirko <jiri@resnulli.us> wrote:
> Thu, Sep 15, 2016 at 04:41:20PM CEST, andy@greyhouse.net wrote:
>>On Tue, Sep 6, 2016 at 8:01 AM, Jiri Pirko
>><andrew.gospodarek@broadcom.com> wrote:
>>> From: Jiri Pirko <jiri@mellanox.com>
>>>
>>> This allows to pass information about added/deleted fib entries to
>>> whoever is interested. This is done in a very similar way as devinet
>>> notifies address additions/removals.
>>
>>(Sorry for the delayed response here...)
>>
>>I had tried a slightly different approach, but this one also seems
>>reasonable and possibly better -- especially if this can be made more
>>generic and shared between ipv4 and ipv6 despite their inherent
>>differences.
>>
>>What I did differently was make a more ipv4-specific change to start
>>with that did this:
>>
>>+#define RTNH_F_MODIFIED                (1 << 7)        /* used for
>>internal kernel tracking */
>>+
>>+#define RTNH_F_COMPARE_MASK    (RTNH_F_DEAD | \
>>+                                RTNH_F_LINKDOWN | \
>>+                                RTNH_F_MODIFIED) /* used as mask for
>>route comparisons */
>>
>>Then in various cases where the route was modified (fib_sync_up, etc),
>>I added this:
>>
>>+                                nexthop_nh->nh_flags |= RTNH_F_MODIFIED;
>>
>>Checking for the modified flag was then done in fib_table_update().
>>This new function was a rewrite of fib_table_flush() and checks for
>>RTNH_F_MODIFIED were done there before calling switchdev infra and
>>then announce new routes if routes changed.
>>
>>The main issue I see right now is that neither userspace nor switchdev
>>are notified when a route flag changes.  This needs to be resolved.
>>
>>I think this RFC is along the proper path to provide notification, but
>>I'm not sure that notification will happen when flags change (most
>>notably the LNKDOWN flag) and there are some other corner cases that
>>could probably be covered as well.
>>
>>I need to forward-port my patch from where it was to the latest
>>net-next and see if these cases I was concerned about were still an
>>issue.  I'm happy to do that and see if we can put this all together
>>to fix a few of the outstanding issues.
>
> I believe that "modify" can be easily another fib event. Drivers can
> react accordingly. I'm close to sending v1 (hopefully tomorrow). I
> believe you can base your patchset on top of mine which saves you lot of
> time.
>

Sounds good -- looking forward to it.  If you add this email on the
cc-list rather than the other one, I'll see it more quickly this time.
:-)


>
>>
>>
>>>
>>> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>>> ---
>>>  include/net/ip_fib.h | 19 +++++++++++++++++++
>>>  net/ipv4/fib_trie.c  | 43 +++++++++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 62 insertions(+)
>>>
>>> diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
>>> index 4079fc1..9ad7ba9 100644
>>> --- a/include/net/ip_fib.h
>>> +++ b/include/net/ip_fib.h
>>> @@ -22,6 +22,7 @@
>>>  #include <net/fib_rules.h>
>>>  #include <net/inetpeer.h>
>>>  #include <linux/percpu.h>
>>> +#include <linux/notifier.h>
>>>
>>>  struct fib_config {
>>>         u8                      fc_dst_len;
>>> @@ -184,6 +185,24 @@ __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
>>>  #define FIB_RES_PREFSRC(net, res)      ((res).fi->fib_prefsrc ? : \
>>>                                          FIB_RES_SADDR(net, res))
>>>
>>> +struct fib_notifier_info {
>>> +       u32 dst;
>>> +       int dst_len;
>>> +       struct fib_info *fi;
>>> +       u8 tos;
>>> +       u8 type;
>>> +       u32 tb_id;
>>> +       u32 nlflags;
>>> +};
>>> +
>>> +enum fib_event_type {
>>> +       FIB_EVENT_TYPE_ADD,
>>> +       FIB_EVENT_TYPE_DEL,
>>> +};
>>> +
>>> +int register_fib_notifier(struct notifier_block *nb);
>>> +int unregister_fib_notifier(struct notifier_block *nb);
>>> +
>>>  struct fib_table {
>>>         struct hlist_node       tb_hlist;
>>>         u32                     tb_id;
>>> diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
>>> index e2ffc2a..19ec471 100644
>>> --- a/net/ipv4/fib_trie.c
>>> +++ b/net/ipv4/fib_trie.c
>>> @@ -73,6 +73,7 @@
>>>  #include <linux/slab.h>
>>>  #include <linux/export.h>
>>>  #include <linux/vmalloc.h>
>>> +#include <linux/notifier.h>
>>>  #include <net/net_namespace.h>
>>>  #include <net/ip.h>
>>>  #include <net/protocol.h>
>>> @@ -84,6 +85,36 @@
>>>  #include <trace/events/fib.h>
>>>  #include "fib_lookup.h"
>>>
>>> +static BLOCKING_NOTIFIER_HEAD(fib_chain);
>>> +
>>> +int register_fib_notifier(struct notifier_block *nb)
>>> +{
>>> +       return blocking_notifier_chain_register(&fib_chain, nb);
>>> +}
>>> +EXPORT_SYMBOL(register_fib_notifier);
>>> +
>>> +int unregister_fib_notifier(struct notifier_block *nb)
>>> +{
>>> +       return blocking_notifier_chain_unregister(&fib_chain, nb);
>>> +}
>>> +EXPORT_SYMBOL(unregister_fib_notifier);
>>> +
>>> +static int call_fib_notifiers(enum fib_event_type event_type, u32 dst,
>>> +                             int dst_len, struct fib_info *fi,
>>> +                             u8 tos, u8 type, u32 tb_id, u32 nlflags)
>>> +{
>>> +       struct fib_notifier_info info = {
>>> +               .dst = dst,
>>> +               .dst_len = dst_len,
>>> +               .fi = fi,
>>> +               .tos = tos,
>>> +               .type = type,
>>> +               .tb_id = tb_id,
>>> +               .nlflags = nlflags,
>>> +       };
>>> +       return blocking_notifier_call_chain(&fib_chain, event_type, &info);
>>> +}
>>> +
>>>  #define MAX_STAT_DEPTH 32
>>>
>>>  #define KEYLENGTH      (8*sizeof(t_key))
>>> @@ -1190,6 +1221,10 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
>>>                         fib_release_info(fi_drop);
>>>                         if (state & FA_S_ACCESSED)
>>>                                 rt_cache_flush(cfg->fc_nlinfo.nl_net);
>>> +
>>> +                       call_fib_notifiers(FIB_EVENT_TYPE_ADD, key, plen, fi,
>>> +                                          new_fa->fa_tos, cfg->fc_type,
>>> +                                          tb->tb_id, cfg->fc_nlflags);
>>>                         rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
>>>                                 tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
>>>
>>> @@ -1241,6 +1276,8 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
>>>                 tb->tb_num_default++;
>>>
>>>         rt_cache_flush(cfg->fc_nlinfo.nl_net);
>>> +       call_fib_notifiers(FIB_EVENT_TYPE_ADD, key, plen, fi, tos,
>>> +                          cfg->fc_type, tb->tb_id, cfg->fc_nlflags);
>>>         rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, new_fa->tb_id,
>>>                   &cfg->fc_nlinfo, nlflags);
>>>  succeeded:
>>> @@ -1542,6 +1579,8 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
>>>         switchdev_fib_ipv4_del(key, plen, fa_to_delete->fa_info, tos,
>>>                                cfg->fc_type, tb->tb_id);
>>>
>>> +       call_fib_notifiers(FIB_EVENT_TYPE_DEL, key, plen, fa_to_delete->fa_info,
>>> +                          tos, cfg->fc_type, tb->tb_id, 0);
>>>         rtmsg_fib(RTM_DELROUTE, htonl(key), fa_to_delete, plen, tb->tb_id,
>>>                   &cfg->fc_nlinfo, 0);
>>>
>>> @@ -1857,6 +1896,10 @@ int fib_table_flush(struct fib_table *tb)
>>>                         switchdev_fib_ipv4_del(n->key, KEYLENGTH - fa->fa_slen,
>>>                                                fi, fa->fa_tos, fa->fa_type,
>>>                                                tb->tb_id);
>>> +                       call_fib_notifiers(FIB_EVENT_TYPE_DEL, n->key,
>>> +                                          KEYLENGTH - fa->fa_slen,
>>> +                                          fi, fa->fa_tos, fa->fa_type,
>>> +                                          tb->tb_id, 0);
>>>                         hlist_del_rcu(&fa->fa_list);
>>>                         fib_release_info(fa->fa_info);
>>>                         alias_free_mem_rcu(fa);

^ permalink raw reply

* Re: [net-next,RFC,1/2] fib: introduce fib notification infrastructure
From: Jiri Pirko @ 2016-09-15 14:45 UTC (permalink / raw)
  To: Andy Gospodarek
  Cc: netdev@vger.kernel.org, David Miller, idosch, eladr, yotamg,
	nogahf, ogerlitz, Roopa Prabhu, nikolay, John Linville,
	Thomas Graf, Scott Feldman, ast, Eric Dumazet, hannes,
	Florian Fainelli, dsa, Jamal Hadi Salim, vivien.didelot,
	john.fastabend, andrew, ivecera
In-Reply-To: <CAHashqA2v_hFTZ2oK-Bf=LFyorQRP7Oy-20smywBY6QTb7Lb8Q@mail.gmail.com>

Thu, Sep 15, 2016 at 04:41:20PM CEST, andy@greyhouse.net wrote:
>On Tue, Sep 6, 2016 at 8:01 AM, Jiri Pirko
><andrew.gospodarek@broadcom.com> wrote:
>> From: Jiri Pirko <jiri@mellanox.com>
>>
>> This allows to pass information about added/deleted fib entries to
>> whoever is interested. This is done in a very similar way as devinet
>> notifies address additions/removals.
>
>(Sorry for the delayed response here...)
>
>I had tried a slightly different approach, but this one also seems
>reasonable and possibly better -- especially if this can be made more
>generic and shared between ipv4 and ipv6 despite their inherent
>differences.
>
>What I did differently was make a more ipv4-specific change to start
>with that did this:
>
>+#define RTNH_F_MODIFIED                (1 << 7)        /* used for
>internal kernel tracking */
>+
>+#define RTNH_F_COMPARE_MASK    (RTNH_F_DEAD | \
>+                                RTNH_F_LINKDOWN | \
>+                                RTNH_F_MODIFIED) /* used as mask for
>route comparisons */
>
>Then in various cases where the route was modified (fib_sync_up, etc),
>I added this:
>
>+                                nexthop_nh->nh_flags |= RTNH_F_MODIFIED;
>
>Checking for the modified flag was then done in fib_table_update().
>This new function was a rewrite of fib_table_flush() and checks for
>RTNH_F_MODIFIED were done there before calling switchdev infra and
>then announce new routes if routes changed.
>
>The main issue I see right now is that neither userspace nor switchdev
>are notified when a route flag changes.  This needs to be resolved.
>
>I think this RFC is along the proper path to provide notification, but
>I'm not sure that notification will happen when flags change (most
>notably the LNKDOWN flag) and there are some other corner cases that
>could probably be covered as well.
>
>I need to forward-port my patch from where it was to the latest
>net-next and see if these cases I was concerned about were still an
>issue.  I'm happy to do that and see if we can put this all together
>to fix a few of the outstanding issues.

I believe that "modify" can be easily another fib event. Drivers can
react accordingly. I'm close to sending v1 (hopefully tomorrow). I
believe you can base your patchset on top of mine which saves you lot of
time.


>
>
>>
>> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>> ---
>>  include/net/ip_fib.h | 19 +++++++++++++++++++
>>  net/ipv4/fib_trie.c  | 43 +++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 62 insertions(+)
>>
>> diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
>> index 4079fc1..9ad7ba9 100644
>> --- a/include/net/ip_fib.h
>> +++ b/include/net/ip_fib.h
>> @@ -22,6 +22,7 @@
>>  #include <net/fib_rules.h>
>>  #include <net/inetpeer.h>
>>  #include <linux/percpu.h>
>> +#include <linux/notifier.h>
>>
>>  struct fib_config {
>>         u8                      fc_dst_len;
>> @@ -184,6 +185,24 @@ __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
>>  #define FIB_RES_PREFSRC(net, res)      ((res).fi->fib_prefsrc ? : \
>>                                          FIB_RES_SADDR(net, res))
>>
>> +struct fib_notifier_info {
>> +       u32 dst;
>> +       int dst_len;
>> +       struct fib_info *fi;
>> +       u8 tos;
>> +       u8 type;
>> +       u32 tb_id;
>> +       u32 nlflags;
>> +};
>> +
>> +enum fib_event_type {
>> +       FIB_EVENT_TYPE_ADD,
>> +       FIB_EVENT_TYPE_DEL,
>> +};
>> +
>> +int register_fib_notifier(struct notifier_block *nb);
>> +int unregister_fib_notifier(struct notifier_block *nb);
>> +
>>  struct fib_table {
>>         struct hlist_node       tb_hlist;
>>         u32                     tb_id;
>> diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
>> index e2ffc2a..19ec471 100644
>> --- a/net/ipv4/fib_trie.c
>> +++ b/net/ipv4/fib_trie.c
>> @@ -73,6 +73,7 @@
>>  #include <linux/slab.h>
>>  #include <linux/export.h>
>>  #include <linux/vmalloc.h>
>> +#include <linux/notifier.h>
>>  #include <net/net_namespace.h>
>>  #include <net/ip.h>
>>  #include <net/protocol.h>
>> @@ -84,6 +85,36 @@
>>  #include <trace/events/fib.h>
>>  #include "fib_lookup.h"
>>
>> +static BLOCKING_NOTIFIER_HEAD(fib_chain);
>> +
>> +int register_fib_notifier(struct notifier_block *nb)
>> +{
>> +       return blocking_notifier_chain_register(&fib_chain, nb);
>> +}
>> +EXPORT_SYMBOL(register_fib_notifier);
>> +
>> +int unregister_fib_notifier(struct notifier_block *nb)
>> +{
>> +       return blocking_notifier_chain_unregister(&fib_chain, nb);
>> +}
>> +EXPORT_SYMBOL(unregister_fib_notifier);
>> +
>> +static int call_fib_notifiers(enum fib_event_type event_type, u32 dst,
>> +                             int dst_len, struct fib_info *fi,
>> +                             u8 tos, u8 type, u32 tb_id, u32 nlflags)
>> +{
>> +       struct fib_notifier_info info = {
>> +               .dst = dst,
>> +               .dst_len = dst_len,
>> +               .fi = fi,
>> +               .tos = tos,
>> +               .type = type,
>> +               .tb_id = tb_id,
>> +               .nlflags = nlflags,
>> +       };
>> +       return blocking_notifier_call_chain(&fib_chain, event_type, &info);
>> +}
>> +
>>  #define MAX_STAT_DEPTH 32
>>
>>  #define KEYLENGTH      (8*sizeof(t_key))
>> @@ -1190,6 +1221,10 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
>>                         fib_release_info(fi_drop);
>>                         if (state & FA_S_ACCESSED)
>>                                 rt_cache_flush(cfg->fc_nlinfo.nl_net);
>> +
>> +                       call_fib_notifiers(FIB_EVENT_TYPE_ADD, key, plen, fi,
>> +                                          new_fa->fa_tos, cfg->fc_type,
>> +                                          tb->tb_id, cfg->fc_nlflags);
>>                         rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
>>                                 tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
>>
>> @@ -1241,6 +1276,8 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
>>                 tb->tb_num_default++;
>>
>>         rt_cache_flush(cfg->fc_nlinfo.nl_net);
>> +       call_fib_notifiers(FIB_EVENT_TYPE_ADD, key, plen, fi, tos,
>> +                          cfg->fc_type, tb->tb_id, cfg->fc_nlflags);
>>         rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, new_fa->tb_id,
>>                   &cfg->fc_nlinfo, nlflags);
>>  succeeded:
>> @@ -1542,6 +1579,8 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
>>         switchdev_fib_ipv4_del(key, plen, fa_to_delete->fa_info, tos,
>>                                cfg->fc_type, tb->tb_id);
>>
>> +       call_fib_notifiers(FIB_EVENT_TYPE_DEL, key, plen, fa_to_delete->fa_info,
>> +                          tos, cfg->fc_type, tb->tb_id, 0);
>>         rtmsg_fib(RTM_DELROUTE, htonl(key), fa_to_delete, plen, tb->tb_id,
>>                   &cfg->fc_nlinfo, 0);
>>
>> @@ -1857,6 +1896,10 @@ int fib_table_flush(struct fib_table *tb)
>>                         switchdev_fib_ipv4_del(n->key, KEYLENGTH - fa->fa_slen,
>>                                                fi, fa->fa_tos, fa->fa_type,
>>                                                tb->tb_id);
>> +                       call_fib_notifiers(FIB_EVENT_TYPE_DEL, n->key,
>> +                                          KEYLENGTH - fa->fa_slen,
>> +                                          fi, fa->fa_tos, fa->fa_type,
>> +                                          tb->tb_id, 0);
>>                         hlist_del_rcu(&fa->fa_list);
>>                         fib_release_info(fa->fa_info);
>>                         alias_free_mem_rcu(fa);

^ permalink raw reply

* Re: [net-next,RFC,1/2] fib: introduce fib notification infrastructure
From: Andy Gospodarek @ 2016-09-15 14:41 UTC (permalink / raw)
  To: Jiří Pírko
  Cc: netdev@vger.kernel.org, David Miller, idosch, eladr, yotamg,
	nogahf, ogerlitz, Roopa Prabhu, nikolay, John Linville,
	Thomas Graf, Scott Feldman, ast, Eric Dumazet, hannes,
	Florian Fainelli, dsa, Jamal Hadi Salim, vivien.didelot,
	john.fastabend, andrew, ivecera
In-Reply-To: <1473163300-2045-2-git-send-email-jiri@resnulli.us>

On Tue, Sep 6, 2016 at 8:01 AM, Jiri Pirko
<andrew.gospodarek@broadcom.com> wrote:
> From: Jiri Pirko <jiri@mellanox.com>
>
> This allows to pass information about added/deleted fib entries to
> whoever is interested. This is done in a very similar way as devinet
> notifies address additions/removals.

(Sorry for the delayed response here...)

I had tried a slightly different approach, but this one also seems
reasonable and possibly better -- especially if this can be made more
generic and shared between ipv4 and ipv6 despite their inherent
differences.

What I did differently was make a more ipv4-specific change to start
with that did this:

+#define RTNH_F_MODIFIED                (1 << 7)        /* used for
internal kernel tracking */
+
+#define RTNH_F_COMPARE_MASK    (RTNH_F_DEAD | \
+                                RTNH_F_LINKDOWN | \
+                                RTNH_F_MODIFIED) /* used as mask for
route comparisons */

Then in various cases where the route was modified (fib_sync_up, etc),
I added this:

+                                nexthop_nh->nh_flags |= RTNH_F_MODIFIED;

Checking for the modified flag was then done in fib_table_update().
This new function was a rewrite of fib_table_flush() and checks for
RTNH_F_MODIFIED were done there before calling switchdev infra and
then announce new routes if routes changed.

The main issue I see right now is that neither userspace nor switchdev
are notified when a route flag changes.  This needs to be resolved.

I think this RFC is along the proper path to provide notification, but
I'm not sure that notification will happen when flags change (most
notably the LNKDOWN flag) and there are some other corner cases that
could probably be covered as well.

I need to forward-port my patch from where it was to the latest
net-next and see if these cases I was concerned about were still an
issue.  I'm happy to do that and see if we can put this all together
to fix a few of the outstanding issues.


>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> ---
>  include/net/ip_fib.h | 19 +++++++++++++++++++
>  net/ipv4/fib_trie.c  | 43 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 62 insertions(+)
>
> diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
> index 4079fc1..9ad7ba9 100644
> --- a/include/net/ip_fib.h
> +++ b/include/net/ip_fib.h
> @@ -22,6 +22,7 @@
>  #include <net/fib_rules.h>
>  #include <net/inetpeer.h>
>  #include <linux/percpu.h>
> +#include <linux/notifier.h>
>
>  struct fib_config {
>         u8                      fc_dst_len;
> @@ -184,6 +185,24 @@ __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
>  #define FIB_RES_PREFSRC(net, res)      ((res).fi->fib_prefsrc ? : \
>                                          FIB_RES_SADDR(net, res))
>
> +struct fib_notifier_info {
> +       u32 dst;
> +       int dst_len;
> +       struct fib_info *fi;
> +       u8 tos;
> +       u8 type;
> +       u32 tb_id;
> +       u32 nlflags;
> +};
> +
> +enum fib_event_type {
> +       FIB_EVENT_TYPE_ADD,
> +       FIB_EVENT_TYPE_DEL,
> +};
> +
> +int register_fib_notifier(struct notifier_block *nb);
> +int unregister_fib_notifier(struct notifier_block *nb);
> +
>  struct fib_table {
>         struct hlist_node       tb_hlist;
>         u32                     tb_id;
> diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
> index e2ffc2a..19ec471 100644
> --- a/net/ipv4/fib_trie.c
> +++ b/net/ipv4/fib_trie.c
> @@ -73,6 +73,7 @@
>  #include <linux/slab.h>
>  #include <linux/export.h>
>  #include <linux/vmalloc.h>
> +#include <linux/notifier.h>
>  #include <net/net_namespace.h>
>  #include <net/ip.h>
>  #include <net/protocol.h>
> @@ -84,6 +85,36 @@
>  #include <trace/events/fib.h>
>  #include "fib_lookup.h"
>
> +static BLOCKING_NOTIFIER_HEAD(fib_chain);
> +
> +int register_fib_notifier(struct notifier_block *nb)
> +{
> +       return blocking_notifier_chain_register(&fib_chain, nb);
> +}
> +EXPORT_SYMBOL(register_fib_notifier);
> +
> +int unregister_fib_notifier(struct notifier_block *nb)
> +{
> +       return blocking_notifier_chain_unregister(&fib_chain, nb);
> +}
> +EXPORT_SYMBOL(unregister_fib_notifier);
> +
> +static int call_fib_notifiers(enum fib_event_type event_type, u32 dst,
> +                             int dst_len, struct fib_info *fi,
> +                             u8 tos, u8 type, u32 tb_id, u32 nlflags)
> +{
> +       struct fib_notifier_info info = {
> +               .dst = dst,
> +               .dst_len = dst_len,
> +               .fi = fi,
> +               .tos = tos,
> +               .type = type,
> +               .tb_id = tb_id,
> +               .nlflags = nlflags,
> +       };
> +       return blocking_notifier_call_chain(&fib_chain, event_type, &info);
> +}
> +
>  #define MAX_STAT_DEPTH 32
>
>  #define KEYLENGTH      (8*sizeof(t_key))
> @@ -1190,6 +1221,10 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
>                         fib_release_info(fi_drop);
>                         if (state & FA_S_ACCESSED)
>                                 rt_cache_flush(cfg->fc_nlinfo.nl_net);
> +
> +                       call_fib_notifiers(FIB_EVENT_TYPE_ADD, key, plen, fi,
> +                                          new_fa->fa_tos, cfg->fc_type,
> +                                          tb->tb_id, cfg->fc_nlflags);
>                         rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
>                                 tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
>
> @@ -1241,6 +1276,8 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
>                 tb->tb_num_default++;
>
>         rt_cache_flush(cfg->fc_nlinfo.nl_net);
> +       call_fib_notifiers(FIB_EVENT_TYPE_ADD, key, plen, fi, tos,
> +                          cfg->fc_type, tb->tb_id, cfg->fc_nlflags);
>         rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, new_fa->tb_id,
>                   &cfg->fc_nlinfo, nlflags);
>  succeeded:
> @@ -1542,6 +1579,8 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
>         switchdev_fib_ipv4_del(key, plen, fa_to_delete->fa_info, tos,
>                                cfg->fc_type, tb->tb_id);
>
> +       call_fib_notifiers(FIB_EVENT_TYPE_DEL, key, plen, fa_to_delete->fa_info,
> +                          tos, cfg->fc_type, tb->tb_id, 0);
>         rtmsg_fib(RTM_DELROUTE, htonl(key), fa_to_delete, plen, tb->tb_id,
>                   &cfg->fc_nlinfo, 0);
>
> @@ -1857,6 +1896,10 @@ int fib_table_flush(struct fib_table *tb)
>                         switchdev_fib_ipv4_del(n->key, KEYLENGTH - fa->fa_slen,
>                                                fi, fa->fa_tos, fa->fa_type,
>                                                tb->tb_id);
> +                       call_fib_notifiers(FIB_EVENT_TYPE_DEL, n->key,
> +                                          KEYLENGTH - fa->fa_slen,
> +                                          fi, fa->fa_tos, fa->fa_type,
> +                                          tb->tb_id, 0);
>                         hlist_del_rcu(&fa->fa_list);
>                         fib_release_info(fa->fa_info);
>                         alias_free_mem_rcu(fa);

^ permalink raw reply

* Re: [4.4-RT PATCH RFC/RFT] drivers: net: cpsw: mark rx/tx irq as IRQF_NO_THREAD
From: Sebastian Andrzej Siewior @ 2016-09-15 14:39 UTC (permalink / raw)
  To: Grygorii Strashko
  Cc: Steven Rostedt, linux-omap, Alison Chaiken, linux-rt-users,
	netdev
In-Reply-To: <cdfe7655-a3b3-9b38-0231-cf90c2af037b@ti.com>

On 2016-09-09 15:46:44 [+0300], Grygorii Strashko wrote:
> 
> It looks like scheduler playing ping-pong between CPUs with threaded irqs irq/354-355.
> And seems this might be the case - if I pin both threaded IRQ handlers to CPU0
> I can see better latency and netperf improvement
> cyclictest -m -Sp98 -q  -D4m
> T: 0 ( 1318) P:98 I:1000 C: 240000 Min:      9 Act:   14 Avg:   15 Max:      42
> T: 1 ( 1319) P:98 I:1500 C: 159909 Min:      9 Act:   14 Avg:   16 Max:      39
> 
> if I arrange hwirqs  and pin pin both threaded IRQ handlers on CPU1 
> I can observe more less similar results as with this patch. 

so no patch then.

> with this change i do not see  "NOHZ: local_softirq_pending 80" any more 
> Tested-by: Grygorii Strashko <grygorii.strashko@ti.com> 

okay. So I need to think what I do about this. Either this or trying to
run the "higher" softirq first but this could break things.
Thanks for the confirmation.

> > - having the hard-IRQ and IRQ-thread on the same CPU might help, too. It
> >   is not strictly required but saves a few cycles if you don't have to
> >   perform cross CPU wake ups and migrate task forth and back. The latter
> >   happens at prio 99.
> 
> I've experimented with this and it improves netperf and I also followed instructions from [1].
> But seems messed ti pin threaded irqs to cpu.
> [1] https://www.osadl.org/Real-time-Ethernet-UDP-worst-case-roun.qa-farm-rt-ethernet-udp-monitor.0.html

There is irq_thread() => irq_thread_check_affinity(). It might not work
as expected on ARM but it makes sense to follow the affinity mask HW irq
for the thread.

> > - I am not sure NAPI works as expected. I would assume so. There is IRQ
> >   354 and 355 which fire after each other. One would be enough I guess.
> >   And they seem to be short living / fire often. If NAPI works then it
> >   should put an end to it and push it to the softirq thread.
> >   If you have IRQ-pacing support I suggest to use something like 10ms or
> >   so. That means your ping response will go from <= 1ms to 10ms in the
> >   worst case but since you process more packets at a time your
> >   throughput should increase.
> >   If I count this correct, it too you alsmost 4ms from "raise SCHED" to
> >   "try process SCHED" and most of the time was spent in 35[45] hard irq,
> >   raise NET_RX or cross wakeup the IRQ thread.
> 
> The question I have to dial with is why switching to RT cause so significant
> netperf drop (without additional tunning) comparing to vanilla - ~120% for 256K and ~200% for 128K windows?

You have a sched / thread ping/pong. That is one thing. !RT with
threaded irqs should show similar problems. The higher latency is caused
by the migration thread.

> It's of course expected to see netperf drop, but I assume not so significant :(
> And I can't find any reports or statistic related to this. Does the same happen on x86?

It should. Maybe at a lower level if it handles migration more
effective. There is this watchdog thread (for instance) which tries to
detect lockups and runs at P99. It causes "worse" cyclictest numbers on
x86 and on ARM but on ARM this is more visible than on x86.

Sebastian

^ permalink raw reply

* Re: [PATCH RFC 01/11] net/mlx5e: Single flow order-0 pages for Striding RQ
From: Tariq Toukan via iovisor-dev @ 2016-09-15 14:34 UTC (permalink / raw)
  To: Alexei Starovoitov, Saeed Mahameed
  Cc: Tom Herbert, netdev-u79uwXL29TY76Z2rM5mHXA, iovisor-dev,
	Jamal Hadi Salim, Eric Dumazet
In-Reply-To: <20160907173131.GA64688-+o4/htvd0TDFYCXBM6kdu7fOX0fSgVTm@public.gmane.org>

Hi Alexei,

On 07/09/2016 8:31 PM, Alexei Starovoitov wrote:
> On Wed, Sep 07, 2016 at 03:42:22PM +0300, Saeed Mahameed wrote:
>> From: Tariq Toukan <tariqt-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>>
>> To improve the memory consumption scheme, we omit the flow that
>> demands and splits high-order pages in Striding RQ, and stay
>> with a single Striding RQ flow that uses order-0 pages.
>>
>> Moving to fragmented memory allows the use of larger MPWQEs,
>> which reduces the number of UMR posts and filler CQEs.
>>
>> Moving to a single flow allows several optimizations that improve
>> performance, especially in production servers where we would
>> anyway fallback to order-0 allocations:
>> - inline functions that were called via function pointers.
>> - improve the UMR post process.
>>
>> This patch alone is expected to give a slight performance reduction.
>> However, the new memory scheme gives the possibility to use a page-cache
>> of a fair size, that doesn't inflate the memory footprint, which will
>> dramatically fix the reduction and even give a huge gain.
>>
>> We ran pktgen single-stream benchmarks, with iptables-raw-drop:
>>
>> Single stride, 64 bytes:
>> * 4,739,057 - baseline
>> * 4,749,550 - this patch
>> no reduction
>>
>> Larger packets, no page cross, 1024 bytes:
>> * 3,982,361 - baseline
>> * 3,845,682 - this patch
>> 3.5% reduction
>>
>> Larger packets, every 3rd packet crosses a page, 1500 bytes:
>> * 3,731,189 - baseline
>> * 3,579,414 - this patch
>> 4% reduction
> imo it's not a realistic use case, but would be good to mention that
> patch 3 brings performance back for this use case anyway.
Exactly, that's what I meant in the previous paragraph (".. will 
dramatically fix the reduction and even give a huge gain.")
Regards,
Tariq

^ permalink raw reply

* Re: [PATCH 3/3] mm: memcontrol: consolidate cgroup socket tracking
From: Johannes Weiner @ 2016-09-15 14:27 UTC (permalink / raw)
  To: Andrew Morton
  Cc: kbuild test robot, kbuild-all, Tejun Heo, David S. Miller,
	Michal Hocko, Vladimir Davydov, linux-mm, cgroups, netdev,
	linux-kernel, kernel-team
In-Reply-To: <20160914151714.f6d1b2a57da0619bf9e2372c@linux-foundation.org>

On Wed, Sep 14, 2016 at 03:17:14PM -0700, Andrew Morton wrote:
> On Thu, 15 Sep 2016 13:34:24 +0800 kbuild test robot <lkp@intel.com> wrote:
> 
> > Hi Johannes,
> > 
> > [auto build test ERROR on net/master]
> > [also build test ERROR on v4.8-rc6 next-20160914]
> > [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> > [Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
> > [Check https://git-scm.com/docs/git-format-patch for more information]
> > 
> > url:    https://github.com/0day-ci/linux/commits/Johannes-Weiner/mm-memcontrol-make-per-cpu-charge-cache-IRQ-safe-for-socket-accounting/20160915-035634
> > config: m68k-sun3_defconfig (attached as .config)
> > compiler: m68k-linux-gcc (GCC) 4.9.0
> > reproduce:
> >         wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
> >         chmod +x ~/bin/make.cross
> >         # save the attached .config to linux build tree
> >         make.cross ARCH=m68k 
> > 
> > All errors (new ones prefixed by >>):
> > 
> >    net/built-in.o: In function `sk_alloc':
> > >> (.text+0x4076): undefined reference to `mem_cgroup_sk_alloc'
> >    net/built-in.o: In function `__sk_destruct':
> > >> sock.c:(.text+0x457e): undefined reference to `mem_cgroup_sk_free'
> >    net/built-in.o: In function `sk_clone_lock':
> >    (.text+0x4f1c): undefined reference to `mem_cgroup_sk_alloc'
> 
> This?

Thanks for fixing it up, Andrew.

I think it'd be nicer to declare the dummy functions for !CONFIG_MEMCG;
it also doesn't look like a hotpath that would necessitate the jump
label in that place. Dave, any preference either way?

Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---

diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index ca11b3e6dd65..61d20c17f3b7 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -773,13 +773,13 @@ static inline void mem_cgroup_wb_stats(struct bdi_writeback *wb,
 #endif	/* CONFIG_CGROUP_WRITEBACK */
 
 struct sock;
-void mem_cgroup_sk_alloc(struct sock *sk);
-void mem_cgroup_sk_free(struct sock *sk);
 bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages);
 void mem_cgroup_uncharge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages);
 #ifdef CONFIG_MEMCG
 extern struct static_key_false memcg_sockets_enabled_key;
 #define mem_cgroup_sockets_enabled static_branch_unlikely(&memcg_sockets_enabled_key)
+void mem_cgroup_sk_alloc(struct sock *sk);
+void mem_cgroup_sk_free(struct sock *sk);
 static inline bool mem_cgroup_under_socket_pressure(struct mem_cgroup *memcg)
 {
 	if (!cgroup_subsys_on_dfl(memory_cgrp_subsys) && memcg->tcpmem_pressure)
@@ -792,6 +792,8 @@ static inline bool mem_cgroup_under_socket_pressure(struct mem_cgroup *memcg)
 }
 #else
 #define mem_cgroup_sockets_enabled 0
+static inline void mem_cgroup_sk_alloc(struct sock *sk) { };
+static inline void mem_cgroup_sk_free(struct sock *sk) { };
 static inline bool mem_cgroup_under_socket_pressure(struct mem_cgroup *memcg)
 {
 	return false;

^ permalink raw reply related

* Re: [PATCH RFC 01/11] net/mlx5e: Single flow order-0 pages for Striding RQ
From: Tariq Toukan via iovisor-dev @ 2016-09-15 14:28 UTC (permalink / raw)
  To: Jesper Dangaard Brouer, Saeed Mahameed
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, iovisor-dev, Jamal Hadi Salim,
	linux-mm, Eric Dumazet, Tom Herbert
In-Reply-To: <20160907211840.36c37ea0-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

Hi Jesper,


On 07/09/2016 10:18 PM, Jesper Dangaard Brouer wrote:
> On Wed,  7 Sep 2016 15:42:22 +0300 Saeed Mahameed <saeedm-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org> wrote:
>
>> From: Tariq Toukan <tariqt-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>>
>> To improve the memory consumption scheme, we omit the flow that
>> demands and splits high-order pages in Striding RQ, and stay
>> with a single Striding RQ flow that uses order-0 pages.
> Thanks you for doing this! MM-list people thanks you!
Thanks. I've just submitted it to net-next.
> For others to understand what this means:  This driver was doing
> split_page() on high-order pages (for Striding RQ).  This was really bad
> because it will cause fragmenting the page-allocator, and depleting the
> high-order pages available quickly.
>
> (I've left rest of patch intact below, if some MM people should be
> interested in looking at the changes).
>
> There is even a funny comment in split_page() relevant to this:
>
> /* [...]
>   * Note: this is probably too low level an operation for use in drivers.
>   * Please consult with lkml before using this in your driver.
>   */
>
>
>> Moving to fragmented memory allows the use of larger MPWQEs,
>> which reduces the number of UMR posts and filler CQEs.
>>
>> Moving to a single flow allows several optimizations that improve
>> performance, especially in production servers where we would
>> anyway fallback to order-0 allocations:
>> - inline functions that were called via function pointers.
>> - improve the UMR post process.
>>
>> This patch alone is expected to give a slight performance reduction.
>> However, the new memory scheme gives the possibility to use a page-cache
>> of a fair size, that doesn't inflate the memory footprint, which will
>> dramatically fix the reduction and even give a huge gain.
>>
>> We ran pktgen single-stream benchmarks, with iptables-raw-drop:
>>
>> Single stride, 64 bytes:
>> * 4,739,057 - baseline
>> * 4,749,550 - this patch
>> no reduction
>>
>> Larger packets, no page cross, 1024 bytes:
>> * 3,982,361 - baseline
>> * 3,845,682 - this patch
>> 3.5% reduction
>>
>> Larger packets, every 3rd packet crosses a page, 1500 bytes:
>> * 3,731,189 - baseline
>> * 3,579,414 - this patch
>> 4% reduction
>>
> Well, the reduction does not really matter than much, because your
> baseline benchmarks are from a freshly booted system, where you have
> not fragmented and depleted the high-order pages yet... ;-)
Indeed. On fragmented systems we'll get a gain, even w/o the page-cache 
mechanism, as no time is wasted looking for high-order-pages.
>
>
>> Fixes: 461017cb006a ("net/mlx5e: Support RX multi-packet WQE (Striding RQ)")
>> Fixes: bc77b240b3c5 ("net/mlx5e: Add fragmented memory support for RX multi packet WQE")
>> Signed-off-by: Tariq Toukan <tariqt-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>> Signed-off-by: Saeed Mahameed <saeedm-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>> ---
>>   drivers/net/ethernet/mellanox/mlx5/core/en.h       |  54 ++--
>>   drivers/net/ethernet/mellanox/mlx5/core/en_main.c  | 136 ++++++++--
>>   drivers/net/ethernet/mellanox/mlx5/core/en_rx.c    | 292 ++++-----------------
>>   drivers/net/ethernet/mellanox/mlx5/core/en_stats.h |   4 -
>>   drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c  |   2 +-
>>   5 files changed, 184 insertions(+), 304 deletions(-)
>>
Regards,
Tariq

^ permalink raw reply

* Re: [PATCH net-next v2 3/5] cxgb4: add parser to translate u32 filters to internal spec
From: John Fastabend @ 2016-09-15 14:27 UTC (permalink / raw)
  To: Rahul Lakkireddy, netdev; +Cc: davem, hariprasad, leedom, nirranjan, indranil
In-Reply-To: <ccd36e66281e2302cb46c7351be22a3ca276c07e.1473759872.git.rahul.lakkireddy@chelsio.com>

On 16-09-13 04:42 AM, Rahul Lakkireddy wrote:
> Parse information sent by u32 into internal filter specification.
> Add support for parsing several fields in IPv4, IPv6, TCP, and UDP.
> 
> Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
> Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
> ---

Looks good to me. Also curious if you would find it worthwhile to
have a cls_u32 mode that starts at L2 instead of the IP header? The
use case would be to use cls_u32 with various encapsulation protocols
in front of the IP header.

Reviewed-by: John Fastabend <john.r.fastabend@intel.com>

^ permalink raw reply

* [PATCH V3 0/3] net-next: dsa: add QCA8K support
From: John Crispin @ 2016-09-15 14:26 UTC (permalink / raw)
  To: David S. Miller, Andrew Lunn, Florian Fainelli
  Cc: linux-kernel, netdev, qsdk-review, John Crispin

This series is based on the AR8xxx series posted by Matthieu Olivari in may
2015. The following changes were made since then

* fixed the nitpicks from the previous review
* updated to latest API
* turned it into an mdio device
* added callbacks for fdb, bridge offloading, stp, eee, port status
* fixed several minor issues to the port setup and arp learning
* changed the namespacing as this driver to qca8k

The driver has so far only been tested on qca8337/N. It should work on other QCA
switches such as the qca8327 with minor changes.

John Crispin (3):
  Documentation: devicetree: add qca8k binding
  net-next: dsa: add Qualcomm tag RX/TX handler
  net-next: dsa: add new driver for qca8xxx family

 .../devicetree/bindings/net/dsa/qca8k.txt          |   89 ++
 drivers/net/dsa/Kconfig                            |    9 +
 drivers/net/dsa/Makefile                           |    1 +
 drivers/net/dsa/qca8k.c                            | 1060 ++++++++++++++++++++
 drivers/net/dsa/qca8k.h                            |  185 ++++
 include/net/dsa.h                                  |    1 +
 net/dsa/Kconfig                                    |    3 +
 net/dsa/Makefile                                   |    1 +
 net/dsa/dsa.c                                      |    3 +
 net/dsa/dsa_priv.h                                 |    2 +
 net/dsa/tag_qca.c                                  |  138 +++
 11 files changed, 1492 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/qca8k.txt
 create mode 100644 drivers/net/dsa/qca8k.c
 create mode 100644 drivers/net/dsa/qca8k.h
 create mode 100644 net/dsa/tag_qca.c

-- 
1.7.10.4

^ permalink raw reply

* [PATCH V3 3/3] net-next: dsa: add new driver for qca8xxx family
From: John Crispin @ 2016-09-15 14:26 UTC (permalink / raw)
  To: David S. Miller, Andrew Lunn, Florian Fainelli
  Cc: linux-kernel, netdev, qsdk-review, John Crispin
In-Reply-To: <1473949601-20674-1-git-send-email-john@phrozen.org>

This patch contains initial support for the QCA8337 switch. It
will detect a QCA8337 switch, if present and declared in the DT.

Each port will be represented through a standalone net_device interface,
as for other DSA switches. CPU can communicate with any of the ports by
setting an IP@ on ethN interface. Most of the extra callbacks of the DSA
subsystem are already supported, such as bridge offloading, stp, fdb.

Signed-off-by: John Crispin <john@phrozen.org>
---
Changes in V2
* add proper locking for the FDB table
* remove udelay when changing the page. neither datasheet nore SDK code
  requires a sleep
* add a cond_resched to the busy wait loop
* use nested locking when accessing the mdio bus
* remove the phy_to_port() wrappers
* remove mmd access function and use existing phy helpers
* fix a copy/paste bug breaking the eee callbacks
* use default vid 1 when fdb entries are added fro vid 0
* remove the phy id check and add a switch id check instead
* add error handling to the mdio read/write functions
* remove inline usage

Changes in V3
* remove qca8k_to_priv() helper
* turn fdb mutex into a generic register mutex
* verify that port0 is the cpu port
* flush MIB counters on startup
* more PHY->port
* implement fdb_prepare properly
* power ports up/down on PM event and shutdown

 drivers/net/dsa/Kconfig  |    9 +
 drivers/net/dsa/Makefile |    1 +
 drivers/net/dsa/qca8k.c  | 1060 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/dsa/qca8k.h  |  185 ++++++++
 4 files changed, 1255 insertions(+)
 create mode 100644 drivers/net/dsa/qca8k.c
 create mode 100644 drivers/net/dsa/qca8k.h

diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index de6d044..0659846 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -25,4 +25,13 @@ source "drivers/net/dsa/b53/Kconfig"
 
 source "drivers/net/dsa/mv88e6xxx/Kconfig"
 
+config NET_DSA_QCA8K
+	tristate "Qualcomm Atheros QCA8K Ethernet switch family support"
+	depends on NET_DSA
+	select NET_DSA_TAG_QCA
+	select REGMAP
+	---help---
+	  This enables support for the Qualcomm Atheros QCA8K Ethernet
+	  switch chips.
+
 endmenu
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index ca1e71b..8346e4f 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
 obj-$(CONFIG_NET_DSA_BCM_SF2)	+= bcm_sf2.o
+obj-$(CONFIG_NET_DSA_QCA8K)	+= qca8k.o
 
 obj-y				+= b53/
 obj-y				+= mv88e6xxx/
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
new file mode 100644
index 0000000..7f3f178
--- /dev/null
+++ b/drivers/net/dsa/qca8k.c
@@ -0,0 +1,1060 @@
+/*
+ * Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
+ * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016 John Crispin <john@phrozen.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+#include <net/dsa.h>
+#include <net/switchdev.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <linux/if_bridge.h>
+#include <linux/mdio.h>
+#include <linux/etherdevice.h>
+
+#include "qca8k.h"
+
+#define MIB_DESC(_s, _o, _n)	\
+	{			\
+		.size = (_s),	\
+		.offset = (_o),	\
+		.name = (_n),	\
+	}
+
+static const struct qca8k_mib_desc ar8327_mib[] = {
+	MIB_DESC(1, 0x00, "RxBroad"),
+	MIB_DESC(1, 0x04, "RxPause"),
+	MIB_DESC(1, 0x08, "RxMulti"),
+	MIB_DESC(1, 0x0c, "RxFcsErr"),
+	MIB_DESC(1, 0x10, "RxAlignErr"),
+	MIB_DESC(1, 0x14, "RxRunt"),
+	MIB_DESC(1, 0x18, "RxFragment"),
+	MIB_DESC(1, 0x1c, "Rx64Byte"),
+	MIB_DESC(1, 0x20, "Rx128Byte"),
+	MIB_DESC(1, 0x24, "Rx256Byte"),
+	MIB_DESC(1, 0x28, "Rx512Byte"),
+	MIB_DESC(1, 0x2c, "Rx1024Byte"),
+	MIB_DESC(1, 0x30, "Rx1518Byte"),
+	MIB_DESC(1, 0x34, "RxMaxByte"),
+	MIB_DESC(1, 0x38, "RxTooLong"),
+	MIB_DESC(2, 0x3c, "RxGoodByte"),
+	MIB_DESC(2, 0x44, "RxBadByte"),
+	MIB_DESC(1, 0x4c, "RxOverFlow"),
+	MIB_DESC(1, 0x50, "Filtered"),
+	MIB_DESC(1, 0x54, "TxBroad"),
+	MIB_DESC(1, 0x58, "TxPause"),
+	MIB_DESC(1, 0x5c, "TxMulti"),
+	MIB_DESC(1, 0x60, "TxUnderRun"),
+	MIB_DESC(1, 0x64, "Tx64Byte"),
+	MIB_DESC(1, 0x68, "Tx128Byte"),
+	MIB_DESC(1, 0x6c, "Tx256Byte"),
+	MIB_DESC(1, 0x70, "Tx512Byte"),
+	MIB_DESC(1, 0x74, "Tx1024Byte"),
+	MIB_DESC(1, 0x78, "Tx1518Byte"),
+	MIB_DESC(1, 0x7c, "TxMaxByte"),
+	MIB_DESC(1, 0x80, "TxOverSize"),
+	MIB_DESC(2, 0x84, "TxByte"),
+	MIB_DESC(1, 0x8c, "TxCollision"),
+	MIB_DESC(1, 0x90, "TxAbortCol"),
+	MIB_DESC(1, 0x94, "TxMultiCol"),
+	MIB_DESC(1, 0x98, "TxSingleCol"),
+	MIB_DESC(1, 0x9c, "TxExcDefer"),
+	MIB_DESC(1, 0xa0, "TxDefer"),
+	MIB_DESC(1, 0xa4, "TxLateCol"),
+};
+
+/* The 32bit switch registers are accessed indirectly. To achieve this we need
+ * to set the page of the register. Track the last page that was set to reduce
+ * mdio writes
+ */
+static u16 qca8k_current_page = 0xffff;
+
+static void
+qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page)
+{
+	regaddr >>= 1;
+	*r1 = regaddr & 0x1e;
+
+	regaddr >>= 5;
+	*r2 = regaddr & 0x7;
+
+	regaddr >>= 3;
+	*page = regaddr & 0x3ff;
+}
+
+static u32
+qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum)
+{
+	u32 val;
+	int ret;
+
+	ret = bus->read(bus, phy_id, regnum);
+	if (ret >= 0) {
+		val = ret;
+		ret = bus->read(bus, phy_id, regnum + 1);
+		val |= ret << 16;
+	}
+
+	if (ret < 0) {
+		dev_err_ratelimited(&bus->dev,
+				    "failed to read qca8k 32bit register\n");
+		return ret;
+	}
+
+	return val;
+}
+
+static void
+qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val)
+{
+	u16 lo, hi;
+	int ret;
+
+	lo = val & 0xffff;
+	hi = (u16)(val >> 16);
+
+	ret = bus->write(bus, phy_id, regnum, lo);
+	if (ret >= 0)
+		ret = bus->write(bus, phy_id, regnum + 1, hi);
+	if (ret < 0)
+		dev_err_ratelimited(&bus->dev,
+				    "failed to write qca8k 32bit register\n");
+}
+
+static void
+qca8k_set_page(struct mii_bus *bus, u16 page)
+{
+	if (page == qca8k_current_page)
+		return;
+
+	if (bus->write(bus, 0x18, 0, page) < 0)
+		dev_err_ratelimited(&bus->dev,
+				    "failed to set qca8k page\n");
+	qca8k_current_page = page;
+}
+
+static u32
+qca8k_read(struct qca8k_priv *priv, u32 reg)
+{
+	u16 r1, r2, page;
+	u32 val;
+
+	qca8k_split_addr(reg, &r1, &r2, &page);
+
+	mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
+
+	qca8k_set_page(priv->bus, page);
+	val = qca8k_mii_read32(priv->bus, 0x10 | r2, r1);
+
+	mutex_unlock(&priv->bus->mdio_lock);
+
+	return val;
+}
+
+static void
+qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
+{
+	u16 r1, r2, page;
+
+	qca8k_split_addr(reg, &r1, &r2, &page);
+
+	mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
+
+	qca8k_set_page(priv->bus, page);
+	qca8k_mii_write32(priv->bus, 0x10 | r2, r1, val);
+
+	mutex_unlock(&priv->bus->mdio_lock);
+}
+
+static u32
+qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 val)
+{
+	u16 r1, r2, page;
+	u32 ret;
+
+	qca8k_split_addr(reg, &r1, &r2, &page);
+
+	mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
+
+	qca8k_set_page(priv->bus, page);
+	ret = qca8k_mii_read32(priv->bus, 0x10 | r2, r1);
+	ret &= ~mask;
+	ret |= val;
+	qca8k_mii_write32(priv->bus, 0x10 | r2, r1, ret);
+
+	mutex_unlock(&priv->bus->mdio_lock);
+
+	return ret;
+}
+
+static void
+qca8k_reg_set(struct qca8k_priv *priv, u32 reg, u32 val)
+{
+	qca8k_rmw(priv, reg, 0, val);
+}
+
+static void
+qca8k_reg_clear(struct qca8k_priv *priv, u32 reg, u32 val)
+{
+	qca8k_rmw(priv, reg, val, 0);
+}
+
+static int
+qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
+
+	*val = qca8k_read(priv, reg);
+
+	return 0;
+}
+
+static int
+qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
+
+	qca8k_write(priv, reg, val);
+
+	return 0;
+}
+
+static const struct regmap_range qca8k_readable_ranges[] = {
+	regmap_reg_range(0x0000, 0x00e4), /* Global control */
+	regmap_reg_range(0x0100, 0x0168), /* EEE control */
+	regmap_reg_range(0x0200, 0x0270), /* Parser control */
+	regmap_reg_range(0x0400, 0x0454), /* ACL */
+	regmap_reg_range(0x0600, 0x0718), /* Lookup */
+	regmap_reg_range(0x0800, 0x0b70), /* QM */
+	regmap_reg_range(0x0c00, 0x0c80), /* PKT */
+	regmap_reg_range(0x0e00, 0x0e98), /* L3 */
+	regmap_reg_range(0x1000, 0x10ac), /* MIB - Port0 */
+	regmap_reg_range(0x1100, 0x11ac), /* MIB - Port1 */
+	regmap_reg_range(0x1200, 0x12ac), /* MIB - Port2 */
+	regmap_reg_range(0x1300, 0x13ac), /* MIB - Port3 */
+	regmap_reg_range(0x1400, 0x14ac), /* MIB - Port4 */
+	regmap_reg_range(0x1500, 0x15ac), /* MIB - Port5 */
+	regmap_reg_range(0x1600, 0x16ac), /* MIB - Port6 */
+
+};
+
+static struct regmap_access_table qca8k_readable_table = {
+	.yes_ranges = qca8k_readable_ranges,
+	.n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges),
+};
+
+struct regmap_config qca8k_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0x16ac, /* end MIB - Port6 range */
+	.reg_read = qca8k_regmap_read,
+	.reg_write = qca8k_regmap_write,
+	.rd_table = &qca8k_readable_table,
+};
+
+static int
+qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
+{
+	unsigned long timeout;
+
+	timeout = jiffies + msecs_to_jiffies(20);
+
+	/* loop until the busy flag has cleared */
+	do {
+		u32 val = qca8k_read(priv, reg);
+		int busy = val & mask;
+
+		if (!busy)
+			break;
+		cond_resched();
+	} while (!time_after_eq(jiffies, timeout));
+
+	return time_after_eq(jiffies, timeout);
+}
+
+static void
+qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb)
+{
+	u32 reg[4];
+	int i;
+
+	/* load the ARL table into an array */
+	for (i = 0; i < 4; i++)
+		reg[i] = qca8k_read(priv, QCA8K_REG_ATU_DATA0 + (i * 4));
+
+	/* vid - 83:72 */
+	fdb->vid = (reg[2] >> QCA8K_ATU_VID_S) & QCA8K_ATU_VID_M;
+	/* aging - 67:64 */
+	fdb->aging = reg[2] & QCA8K_ATU_STATUS_M;
+	/* portmask - 54:48 */
+	fdb->port_mask = (reg[1] >> QCA8K_ATU_PORT_S) & QCA8K_ATU_PORT_M;
+	/* mac - 47:0 */
+	fdb->mac[0] = (reg[1] >> QCA8K_ATU_ADDR0_S) & 0xff;
+	fdb->mac[1] = reg[1] & 0xff;
+	fdb->mac[2] = (reg[0] >> QCA8K_ATU_ADDR2_S) & 0xff;
+	fdb->mac[3] = (reg[0] >> QCA8K_ATU_ADDR3_S) & 0xff;
+	fdb->mac[4] = (reg[0] >> QCA8K_ATU_ADDR4_S) & 0xff;
+	fdb->mac[5] = reg[0] & 0xff;
+}
+
+static void
+qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, const u8 *mac,
+		u8 aging)
+{
+	u32 reg[3] = { 0 };
+	int i;
+
+	/* vid - 83:72 */
+	reg[2] = (vid & QCA8K_ATU_VID_M) << QCA8K_ATU_VID_S;
+	/* aging - 67:64 */
+	reg[2] |= aging & QCA8K_ATU_STATUS_M;
+	/* portmask - 54:48 */
+	reg[1] = (port_mask & QCA8K_ATU_PORT_M) << QCA8K_ATU_PORT_S;
+	/* mac - 47:0 */
+	reg[1] |= mac[0] << QCA8K_ATU_ADDR0_S;
+	reg[1] |= mac[1];
+	reg[0] |= mac[2] << QCA8K_ATU_ADDR2_S;
+	reg[0] |= mac[3] << QCA8K_ATU_ADDR3_S;
+	reg[0] |= mac[4] << QCA8K_ATU_ADDR4_S;
+	reg[0] |= mac[5];
+
+	/* load the array into the ARL table */
+	for (i = 0; i < 3; i++)
+		qca8k_write(priv, QCA8K_REG_ATU_DATA0 + (i * 4), reg[i]);
+}
+
+static int
+qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, int port)
+{
+	u32 reg;
+
+	/* Set the command and FDB index */
+	reg = QCA8K_ATU_FUNC_BUSY;
+	reg |= cmd;
+	if (port >= 0) {
+		reg |= QCA8K_ATU_FUNC_PORT_EN;
+		reg |= (port & QCA8K_ATU_FUNC_PORT_M) << QCA8K_ATU_FUNC_PORT_S;
+	}
+
+	/* Write the function register triggering the table access */
+	qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg);
+
+	/* wait for completion */
+	if (qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY))
+		return -1;
+
+	/* Check for table full violation when adding an entry */
+	if (cmd == QCA8K_FDB_LOAD) {
+		reg = qca8k_read(priv, QCA8K_REG_ATU_FUNC);
+		if (reg & QCA8K_ATU_FUNC_FULL)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int
+qca8k_fdb_next(struct qca8k_priv *priv, struct qca8k_fdb *fdb, int port)
+{
+	int ret;
+
+	qca8k_fdb_write(priv, fdb->vid, fdb->port_mask, fdb->mac, fdb->aging);
+	ret = qca8k_fdb_access(priv, QCA8K_FDB_NEXT, port);
+	if (ret >= 0)
+		qca8k_fdb_read(priv, fdb);
+
+	return ret;
+}
+
+static int
+qca8k_fdb_add(struct qca8k_priv *priv, const u8 *mac, u16 port_mask,
+	      u16 vid, u8 aging)
+{
+	int ret;
+
+	mutex_lock(&priv->reg_mutex);
+	qca8k_fdb_write(priv, vid, port_mask, mac, aging);
+	ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
+	mutex_unlock(&priv->reg_mutex);
+
+	return ret;
+}
+
+static int
+qca8k_fdb_del(struct qca8k_priv *priv, const u8 *mac, u16 port_mask, u16 vid)
+{
+	int ret;
+
+	mutex_lock(&priv->reg_mutex);
+	qca8k_fdb_write(priv, vid, port_mask, mac, 0);
+	ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
+	mutex_unlock(&priv->reg_mutex);
+
+	return ret;
+}
+
+static void
+qca8k_fdb_flush(struct qca8k_priv *priv)
+{
+	mutex_lock(&priv->reg_mutex);
+	qca8k_fdb_access(priv, QCA8K_FDB_FLUSH, -1);
+	mutex_unlock(&priv->reg_mutex);
+}
+
+static void
+qca8k_mib_init(struct qca8k_priv *priv)
+{
+	mutex_lock(&priv->reg_mutex);
+	qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
+	qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY);
+	qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
+	qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB);
+	mutex_unlock(&priv->reg_mutex);
+}
+
+static int
+qca8k_set_pad_ctrl(struct qca8k_priv *priv, int port, int mode)
+{
+	u32 reg;
+
+	switch (port) {
+	case 0:
+		reg = QCA8K_REG_PORT0_PAD_CTRL;
+		break;
+	case 6:
+		reg = QCA8K_REG_PORT6_PAD_CTRL;
+		break;
+	default:
+		pr_err("Can't set PAD_CTRL on port %d\n", port);
+		return -EINVAL;
+	}
+
+	/* Configure a port to be directly connected to an external
+	 * PHY or MAC.
+	 */
+	switch (mode) {
+	case PHY_INTERFACE_MODE_RGMII:
+		qca8k_write(priv, reg,
+			    QCA8K_PORT_PAD_RGMII_EN |
+			    QCA8K_PORT_PAD_RGMII_TX_DELAY(3) |
+			    QCA8K_PORT_PAD_RGMII_RX_DELAY(3));
+
+		/* According to the datasheet, RGMII delay is enabled through
+		 * PORT5_PAD_CTRL for all ports, rather than individual port
+		 * registers
+		 */
+		qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL,
+			    QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
+		break;
+	case PHY_INTERFACE_MODE_SGMII:
+		qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN);
+		break;
+	default:
+		pr_err("xMII mode %d not supported\n", mode);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void
+qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable)
+{
+	u32 mask = QCA8K_PORT_STATUS_TXMAC;
+
+	/* Port 0 and 6 have no internal PHY */
+	if ((port > 0) && (port < 6))
+		mask |= QCA8K_PORT_STATUS_LINK_AUTO;
+
+	if (enable)
+		qca8k_reg_set(priv, QCA8K_REG_PORT_STATUS(port), mask);
+	else
+		qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask);
+}
+
+static int
+qca8k_setup(struct dsa_switch *ds)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+	int ret, i, phy_mode = -1;
+
+	/* Make sure that port 0 is the cpu port */
+	if (!dsa_is_cpu_port(ds, 0)) {
+		pr_err("port 0 is not the CPU port\n");
+		return -EINVAL;
+	}
+
+	mutex_init(&priv->reg_mutex);
+
+	/* Start by setting up the register mapping */
+	priv->regmap = devm_regmap_init(ds->dev, NULL, priv,
+					&qca8k_regmap_config);
+	if (IS_ERR(priv->regmap))
+		pr_warn("regmap initialization failed");
+
+	/* Initialize CPU port pad mode (xMII type, delays...) */
+	phy_mode = of_get_phy_mode(ds->ports[ds->dst->cpu_port].dn);
+	if (phy_mode < 0) {
+		pr_err("Can't find phy-mode for master device\n");
+		return phy_mode;
+	}
+	ret = qca8k_set_pad_ctrl(priv, QCA8K_CPU_PORT, phy_mode);
+	if (ret < 0)
+		return ret;
+
+	/* Enable CPU Port */
+	qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
+		      QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
+	qca8k_port_set_status(priv, QCA8K_CPU_PORT, 1);
+	priv->port_sts[QCA8K_CPU_PORT].enabled = 1;
+
+	/* Enable MIB counters */
+	qca8k_mib_init(priv);
+
+	/* Enable QCA header mode on the cpu port */
+	qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT),
+		    QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
+		    QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
+
+	/* Disable forwarding by default on all ports */
+	for (i = 0; i < QCA8K_NUM_PORTS; i++)
+		qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
+			  QCA8K_PORT_LOOKUP_MEMBER, 0);
+
+	/* Disable MAC by default on all user ports */
+	for (i = 1; i < QCA8K_NUM_PORTS; i++)
+		if (ds->enabled_port_mask & BIT(i))
+			qca8k_port_set_status(priv, i, 0);
+
+	/* Forward all unknown frames to CPU port for Linux processing */
+	qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
+		    BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
+		    BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
+		    BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
+		    BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
+
+	/* Setup connection between CPU port & user ports */
+	for (i = 0; i < DSA_MAX_PORTS; i++) {
+		/* CPU port gets connected to all user ports of the switch */
+		if (dsa_is_cpu_port(ds, i)) {
+			qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT),
+				  QCA8K_PORT_LOOKUP_MEMBER,
+				  ds->enabled_port_mask);
+		}
+
+		/* Invividual user ports get connected to CPU port only */
+		if (ds->enabled_port_mask & BIT(i)) {
+			int shift = 16 * (i % 2);
+
+			qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
+				  QCA8K_PORT_LOOKUP_MEMBER,
+				  BIT(QCA8K_CPU_PORT));
+
+			/* Enable ARP Auto-learning by default */
+			qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i),
+				      QCA8K_PORT_LOOKUP_LEARN);
+
+			/* For port based vlans to work we need to set the
+			 * default egress vid
+			 */
+			qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i),
+				  0xffff << shift, 1 << shift);
+			qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i),
+				    QCA8K_PORT_VLAN_CVID(1) |
+				    QCA8K_PORT_VLAN_SVID(1));
+		}
+	}
+
+	/* Flush the FDB table */
+	qca8k_fdb_flush(priv);
+
+	return 0;
+}
+
+static int
+qca8k_set_addr(struct dsa_switch *ds, u8 *addr)
+{
+	/* The subsystem always calls this function so add an empty stub */
+	return 0;
+}
+
+static int
+qca8k_phy_read(struct dsa_switch *ds, int phy, int regnum)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+
+	return mdiobus_read(priv->bus, phy, regnum);
+}
+
+static int
+qca8k_phy_write(struct dsa_switch *ds, int phy, int regnum, u16 val)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+
+	return mdiobus_write(priv->bus, phy, regnum, val);
+}
+
+static void
+qca8k_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++)
+		strncpy(data + i * ETH_GSTRING_LEN, ar8327_mib[i].name,
+			ETH_GSTRING_LEN);
+}
+
+static void
+qca8k_get_ethtool_stats(struct dsa_switch *ds, int port,
+			uint64_t *data)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+	const struct qca8k_mib_desc *mib;
+	u32 reg, i;
+	u64 hi;
+
+	for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) {
+		mib = &ar8327_mib[i];
+		reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset;
+
+		data[i] = qca8k_read(priv, reg);
+		if (mib->size == 2) {
+			hi = qca8k_read(priv, reg + 4);
+			data[i] |= hi << 32;
+		}
+	}
+}
+
+static int
+qca8k_get_sset_count(struct dsa_switch *ds)
+{
+	return ARRAY_SIZE(ar8327_mib);
+}
+
+static void
+qca8k_eee_enable_set(struct dsa_switch *ds, int port, bool enable)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+	u32 lpi_en = QCA8K_REG_EEE_CTRL_LPI_EN(port);
+	u32 reg;
+
+	mutex_lock(&priv->reg_mutex);
+	reg = qca8k_read(priv, QCA8K_REG_EEE_CTRL);
+	if (enable)
+		reg |= lpi_en;
+	else
+		reg &= ~lpi_en;
+	qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg);
+	mutex_unlock(&priv->reg_mutex);
+}
+
+static int
+qca8k_eee_init(struct dsa_switch *ds, int port,
+	       struct phy_device *phy)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+	struct ethtool_eee *p = &priv->port_sts[port].eee;
+	int ret;
+
+	p->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full);
+
+	ret = phy_init_eee(phy, 0);
+	if (ret)
+		return ret;
+
+	qca8k_eee_enable_set(ds, port, true);
+
+	return 0;
+}
+
+static int
+qca8k_set_eee(struct dsa_switch *ds, int port,
+	      struct phy_device *phydev,
+	      struct ethtool_eee *e)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+	struct ethtool_eee *p = &priv->port_sts[port].eee;
+	int ret = 0;
+
+	p->eee_enabled = e->eee_enabled;
+
+	if (e->eee_enabled) {
+		p->eee_enabled = qca8k_eee_init(ds, port, phydev);
+		if (!p->eee_enabled)
+			ret = -EOPNOTSUPP;
+	}
+	qca8k_eee_enable_set(ds, port, p->eee_enabled);
+
+	return ret;
+}
+
+static int
+qca8k_get_eee(struct dsa_switch *ds, int port,
+	      struct ethtool_eee *e)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+	struct ethtool_eee *p = &priv->port_sts[port].eee;
+	struct net_device *netdev = ds->ports[port].netdev;
+	int ret;
+
+	ret = phy_ethtool_get_eee(netdev->phydev, p);
+	if (!ret)
+		e->eee_active =
+			!!(p->supported & p->advertised & p->lp_advertised);
+	else
+		e->eee_active = 0;
+
+	e->eee_enabled = p->eee_enabled;
+
+	return ret;
+}
+
+static void
+qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+	u32 stp_state;
+
+	switch (state) {
+	case BR_STATE_DISABLED:
+		stp_state = QCA8K_PORT_LOOKUP_STATE_DISABLED;
+		break;
+	case BR_STATE_BLOCKING:
+		stp_state = QCA8K_PORT_LOOKUP_STATE_BLOCKING;
+		break;
+	case BR_STATE_LISTENING:
+		stp_state = QCA8K_PORT_LOOKUP_STATE_LISTENING;
+		break;
+	case BR_STATE_LEARNING:
+		stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING;
+		break;
+	case BR_STATE_FORWARDING:
+	default:
+		stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD;
+		break;
+	}
+
+	qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
+		  QCA8K_PORT_LOOKUP_STATE_MASK, stp_state);
+}
+
+static int
+qca8k_port_bridge_join(struct dsa_switch *ds, int port,
+		       struct net_device *bridge)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+	int port_mask = BIT(QCA8K_CPU_PORT);
+	int i;
+
+	priv->port_sts[port].bridge_dev = bridge;
+
+	for (i = 1; i < QCA8K_NUM_PORTS; i++) {
+		if (priv->port_sts[i].bridge_dev != bridge)
+			continue;
+		/* Add this port to the portvlan mask of the other ports
+		 * in the bridge
+		 */
+		qca8k_reg_set(priv,
+			      QCA8K_PORT_LOOKUP_CTRL(i),
+			      BIT(port));
+		if (i != port)
+			port_mask |= BIT(i);
+	}
+	/* Add all other ports to this ports portvlan mask */
+	qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
+		  QCA8K_PORT_LOOKUP_MEMBER, port_mask);
+
+	return 0;
+}
+
+static void
+qca8k_port_bridge_leave(struct dsa_switch *ds, int port)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+	int i;
+
+	for (i = 1; i < QCA8K_NUM_PORTS; i++) {
+		if (priv->port_sts[i].bridge_dev !=
+		    priv->port_sts[port].bridge_dev)
+			continue;
+		/* Remove this port to the portvlan mask of the other ports
+		 * in the bridge
+		 */
+		qca8k_reg_clear(priv,
+				QCA8K_PORT_LOOKUP_CTRL(i),
+				BIT(port));
+	}
+	priv->port_sts[port].bridge_dev = NULL;
+	/* Set the cpu port to be the only one in the portvlan mask of
+	 * this port
+	 */
+	qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
+		  QCA8K_PORT_LOOKUP_MEMBER, BIT(QCA8K_CPU_PORT));
+}
+
+static int
+qca8k_port_enable(struct dsa_switch *ds, int port,
+		  struct phy_device *phy)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+
+	qca8k_port_set_status(priv, port, 1);
+	priv->port_sts[port].enabled = 1;
+
+	return 0;
+}
+
+static void
+qca8k_port_disable(struct dsa_switch *ds, int port,
+		   struct phy_device *phy)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+
+	qca8k_port_set_status(priv, port, 0);
+	priv->port_sts[port].enabled = 0;
+}
+
+static int
+qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr,
+		      u16 port_mask, u16 vid)
+{
+	/* Set the vid to the port vlan id if no vid is set */
+	if (!vid)
+		vid = 1;
+
+	return qca8k_fdb_add(priv, addr, port_mask, vid,
+			     QCA8K_ATU_STATUS_STATIC);
+}
+
+static int
+qca8k_port_fdb_prepare(struct dsa_switch *ds, int port,
+		       const struct switchdev_obj_port_fdb *fdb,
+		       struct switchdev_trans *trans)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+
+	/* The FDB table for static and auto learned entries is the same. We
+	 * need to reserve an entry with no port_mask set to make sure that
+	 * when port_fdb_add is called an entry is still available. Otherwise
+	 * the last free entry might have been used up by auto learning
+	 */
+	return qca8k_port_fdb_insert(priv, fdb->addr, 0, fdb->vid);
+}
+
+static void
+qca8k_port_fdb_add(struct dsa_switch *ds, int port,
+		   const struct switchdev_obj_port_fdb *fdb,
+		   struct switchdev_trans *trans)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+	u16 port_mask = BIT(port);
+
+	/* Update the FDB entry adding the port_mask */
+	qca8k_port_fdb_insert(priv, fdb->addr, port_mask, fdb->vid);
+}
+
+static int
+qca8k_port_fdb_del(struct dsa_switch *ds, int port,
+		   const struct switchdev_obj_port_fdb *fdb)
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+	u16 port_mask = BIT(port);
+	u16 vid = fdb->vid;
+
+	if (!vid)
+		vid = 1;
+
+	return qca8k_fdb_del(priv, fdb->addr, port_mask, vid);
+}
+
+static int
+qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
+		    struct switchdev_obj_port_fdb *fdb,
+		    int (*cb)(struct switchdev_obj *obj))
+{
+	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+	struct qca8k_fdb _fdb = { 0 };
+	int cnt = QCA8K_NUM_FDB_RECORDS;
+	int ret = 0;
+
+	mutex_lock(&priv->reg_mutex);
+	while (cnt-- && !qca8k_fdb_next(priv, &_fdb, port)) {
+		if (!_fdb.aging)
+			break;
+
+		ether_addr_copy(fdb->addr, _fdb.mac);
+		fdb->vid = _fdb.vid;
+		if (_fdb.aging == QCA8K_ATU_STATUS_STATIC)
+			fdb->ndm_state = NUD_NOARP;
+		else
+			fdb->ndm_state = NUD_REACHABLE;
+
+		ret = cb(&fdb->obj);
+		if (ret)
+			break;
+	}
+	mutex_unlock(&priv->reg_mutex);
+
+	return 0;
+}
+
+static enum dsa_tag_protocol
+qca8k_get_tag_protocol(struct dsa_switch *ds)
+{
+	return DSA_TAG_PROTO_QCA;
+}
+
+static struct dsa_switch_ops qca8k_switch_ops = {
+	.get_tag_protocol	= qca8k_get_tag_protocol,
+	.setup			= qca8k_setup,
+	.set_addr		= qca8k_set_addr,
+	.get_strings		= qca8k_get_strings,
+	.phy_read		= qca8k_phy_read,
+	.phy_write		= qca8k_phy_write,
+	.get_ethtool_stats	= qca8k_get_ethtool_stats,
+	.get_sset_count		= qca8k_get_sset_count,
+	.get_eee		= qca8k_get_eee,
+	.set_eee		= qca8k_set_eee,
+	.port_enable		= qca8k_port_enable,
+	.port_disable		= qca8k_port_disable,
+	.port_stp_state_set	= qca8k_port_stp_state_set,
+	.port_bridge_join	= qca8k_port_bridge_join,
+	.port_bridge_leave	= qca8k_port_bridge_leave,
+	.port_fdb_prepare	= qca8k_port_fdb_prepare,
+	.port_fdb_add		= qca8k_port_fdb_add,
+	.port_fdb_del		= qca8k_port_fdb_del,
+	.port_fdb_dump		= qca8k_port_fdb_dump,
+};
+
+static int
+qca8k_sw_probe(struct mdio_device *mdiodev)
+{
+	struct qca8k_priv *priv;
+	u32 id;
+
+	/* allocate the private data struct so that we can probe the switches
+	 * ID register
+	 */
+	priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->bus = mdiodev->bus;
+
+	/* read the switches ID register */
+	id = qca8k_read(priv, QCA8K_REG_MASK_CTRL);
+	id >>= QCA8K_MASK_CTRL_ID_S;
+	id &= QCA8K_MASK_CTRL_ID_M;
+	if (id != QCA8K_ID_QCA8337)
+		return -ENODEV;
+
+	priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL);
+	if (!priv->ds)
+		return -ENOMEM;
+
+	priv->ds->priv = priv;
+	priv->ds->dev = &mdiodev->dev;
+	priv->ds->ops = &qca8k_switch_ops;
+	mutex_init(&priv->reg_mutex);
+	dev_set_drvdata(&mdiodev->dev, priv);
+
+	return dsa_register_switch(priv->ds, priv->ds->dev->of_node);
+}
+
+static void
+qca8k_sw_remove(struct mdio_device *mdiodev)
+{
+	struct qca8k_priv *priv = dev_get_drvdata(&mdiodev->dev);
+	int i;
+
+	for (i = 0; i < QCA8K_NUM_PORTS; i++)
+		qca8k_port_set_status(priv, i, 0);
+
+	dsa_unregister_switch(priv->ds);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static void
+qca8k_set_pm(struct qca8k_priv *priv, int enable)
+{
+	int i;
+
+	for (i = 0; i < QCA8K_NUM_PORTS; i++) {
+		if (!priv->port_sts[i].enabled)
+			continue;
+
+		qca8k_port_set_status(priv, i, enable);
+	}
+}
+
+static int qca8k_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct qca8k_priv *priv = platform_get_drvdata(pdev);
+
+	qca8k_set_pm(priv, 0);
+
+	return dsa_switch_suspend(priv->ds);
+}
+
+static int qca8k_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct qca8k_priv *priv = platform_get_drvdata(pdev);
+
+	qca8k_set_pm(priv, 1);
+
+	return dsa_switch_resume(priv->ds);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(qca8k_pm_ops,
+			 qca8k_suspend, qca8k_resume);
+
+static const struct of_device_id qca8k_of_match[] = {
+	{ .compatible = "qca,qca8337" },
+	{ /* sentinel */ },
+};
+
+static struct mdio_driver qca8kmdio_driver = {
+	.probe  = qca8k_sw_probe,
+	.remove = qca8k_sw_remove,
+	.mdiodrv.driver = {
+		.name = "qca8k",
+		.of_match_table = qca8k_of_match,
+		.pm = &qca8k_pm_ops,
+	},
+};
+
+static int __init
+qca8kmdio_driver_register(void)
+{
+	return mdio_driver_register(&qca8kmdio_driver);
+}
+module_init(qca8kmdio_driver_register);
+
+static void __exit
+qca8kmdio_driver_unregister(void)
+{
+	mdio_driver_unregister(&qca8kmdio_driver);
+}
+module_exit(qca8kmdio_driver_unregister);
+
+MODULE_AUTHOR("Mathieu Olivari, John Crispin <john@phrozen.org>");
+MODULE_DESCRIPTION("Driver for QCA8K ethernet switch family");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qca8k");
diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h
new file mode 100644
index 0000000..2014647
--- /dev/null
+++ b/drivers/net/dsa/qca8k.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
+ * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __QCA8K_H
+#define __QCA8K_H
+
+#include <linux/delay.h>
+#include <linux/regmap.h>
+
+#define QCA8K_NUM_PORTS					7
+
+#define PHY_ID_QCA8337					0x004dd036
+#define QCA8K_ID_QCA8337				0x13
+
+#define QCA8K_NUM_FDB_RECORDS				2048
+
+#define QCA8K_CPU_PORT					0
+
+/* Global control registers */
+#define QCA8K_REG_MASK_CTRL				0x000
+#define   QCA8K_MASK_CTRL_ID_M				0xff
+#define   QCA8K_MASK_CTRL_ID_S				8
+#define QCA8K_REG_PORT0_PAD_CTRL			0x004
+#define QCA8K_REG_PORT5_PAD_CTRL			0x008
+#define QCA8K_REG_PORT6_PAD_CTRL			0x00c
+#define   QCA8K_PORT_PAD_RGMII_EN			BIT(26)
+#define   QCA8K_PORT_PAD_RGMII_TX_DELAY(x)		\
+						((0x8 + (x & 0x3)) << 22)
+#define   QCA8K_PORT_PAD_RGMII_RX_DELAY(x)		\
+						((0x10 + (x & 0x3)) << 20)
+#define   QCA8K_PORT_PAD_RGMII_RX_DELAY_EN		BIT(24)
+#define   QCA8K_PORT_PAD_SGMII_EN			BIT(7)
+#define QCA8K_REG_MODULE_EN				0x030
+#define   QCA8K_MODULE_EN_MIB				BIT(0)
+#define QCA8K_REG_MIB					0x034
+#define   QCA8K_MIB_FLUSH				BIT(24)
+#define   QCA8K_MIB_CPU_KEEP				BIT(20)
+#define   QCA8K_MIB_BUSY				BIT(17)
+#define QCA8K_GOL_MAC_ADDR0				0x60
+#define QCA8K_GOL_MAC_ADDR1				0x64
+#define QCA8K_REG_PORT_STATUS(_i)			(0x07c + (_i) * 4)
+#define   QCA8K_PORT_STATUS_SPEED			GENMASK(2, 0)
+#define   QCA8K_PORT_STATUS_SPEED_S			0
+#define   QCA8K_PORT_STATUS_TXMAC			BIT(2)
+#define   QCA8K_PORT_STATUS_RXMAC			BIT(3)
+#define   QCA8K_PORT_STATUS_TXFLOW			BIT(4)
+#define   QCA8K_PORT_STATUS_RXFLOW			BIT(5)
+#define   QCA8K_PORT_STATUS_DUPLEX			BIT(6)
+#define   QCA8K_PORT_STATUS_LINK_UP			BIT(8)
+#define   QCA8K_PORT_STATUS_LINK_AUTO			BIT(9)
+#define   QCA8K_PORT_STATUS_LINK_PAUSE			BIT(10)
+#define QCA8K_REG_PORT_HDR_CTRL(_i)			(0x9c + (_i * 4))
+#define   QCA8K_PORT_HDR_CTRL_RX_MASK			GENMASK(3, 2)
+#define   QCA8K_PORT_HDR_CTRL_RX_S			2
+#define   QCA8K_PORT_HDR_CTRL_TX_MASK			GENMASK(1, 0)
+#define   QCA8K_PORT_HDR_CTRL_TX_S			0
+#define   QCA8K_PORT_HDR_CTRL_ALL			2
+#define   QCA8K_PORT_HDR_CTRL_MGMT			1
+#define   QCA8K_PORT_HDR_CTRL_NONE			0
+
+/* EEE control registers */
+#define QCA8K_REG_EEE_CTRL				0x100
+#define  QCA8K_REG_EEE_CTRL_LPI_EN(_i)			((_i + 1) * 2)
+
+/* ACL registers */
+#define QCA8K_REG_PORT_VLAN_CTRL0(_i)			(0x420 + (_i * 8))
+#define   QCA8K_PORT_VLAN_CVID(x)			(x << 16)
+#define   QCA8K_PORT_VLAN_SVID(x)			x
+#define QCA8K_REG_PORT_VLAN_CTRL1(_i)			(0x424 + (_i * 8))
+#define QCA8K_REG_IPV4_PRI_BASE_ADDR			0x470
+#define QCA8K_REG_IPV4_PRI_ADDR_MASK			0x474
+
+/* Lookup registers */
+#define QCA8K_REG_ATU_DATA0				0x600
+#define   QCA8K_ATU_ADDR2_S				24
+#define   QCA8K_ATU_ADDR3_S				16
+#define   QCA8K_ATU_ADDR4_S				8
+#define QCA8K_REG_ATU_DATA1				0x604
+#define   QCA8K_ATU_PORT_M				0x7f
+#define   QCA8K_ATU_PORT_S				16
+#define   QCA8K_ATU_ADDR0_S				8
+#define QCA8K_REG_ATU_DATA2				0x608
+#define   QCA8K_ATU_VID_M				0xfff
+#define   QCA8K_ATU_VID_S				8
+#define   QCA8K_ATU_STATUS_M				0xf
+#define   QCA8K_ATU_STATUS_STATIC			0xf
+#define QCA8K_REG_ATU_FUNC				0x60c
+#define   QCA8K_ATU_FUNC_BUSY				BIT(31)
+#define   QCA8K_ATU_FUNC_PORT_EN			BIT(14)
+#define   QCA8K_ATU_FUNC_MULTI_EN			BIT(13)
+#define   QCA8K_ATU_FUNC_FULL				BIT(12)
+#define   QCA8K_ATU_FUNC_PORT_M				0xf
+#define   QCA8K_ATU_FUNC_PORT_S				8
+#define QCA8K_REG_GLOBAL_FW_CTRL0			0x620
+#define   QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN		BIT(10)
+#define QCA8K_REG_GLOBAL_FW_CTRL1			0x624
+#define   QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S		24
+#define   QCA8K_GLOBAL_FW_CTRL1_BC_DP_S			16
+#define   QCA8K_GLOBAL_FW_CTRL1_MC_DP_S			8
+#define   QCA8K_GLOBAL_FW_CTRL1_UC_DP_S			0
+#define QCA8K_PORT_LOOKUP_CTRL(_i)			(0x660 + (_i) * 0xc)
+#define   QCA8K_PORT_LOOKUP_MEMBER			GENMASK(6, 0)
+#define   QCA8K_PORT_LOOKUP_STATE_MASK			GENMASK(18, 16)
+#define   QCA8K_PORT_LOOKUP_STATE_DISABLED		(0 << 16)
+#define   QCA8K_PORT_LOOKUP_STATE_BLOCKING		(1 << 16)
+#define   QCA8K_PORT_LOOKUP_STATE_LISTENING		(2 << 16)
+#define   QCA8K_PORT_LOOKUP_STATE_LEARNING		(3 << 16)
+#define   QCA8K_PORT_LOOKUP_STATE_FORWARD		(4 << 16)
+#define   QCA8K_PORT_LOOKUP_STATE			GENMASK(18, 16)
+#define   QCA8K_PORT_LOOKUP_LEARN			BIT(20)
+
+/* Pkt edit registers */
+#define QCA8K_EGRESS_VLAN(x)				(0x0c70 + (4 * (x / 2)))
+
+/* L3 registers */
+#define QCA8K_HROUTER_CONTROL				0xe00
+#define   QCA8K_HROUTER_CONTROL_GLB_LOCKTIME_M		GENMASK(17, 16)
+#define   QCA8K_HROUTER_CONTROL_GLB_LOCKTIME_S		16
+#define   QCA8K_HROUTER_CONTROL_ARP_AGE_MODE		1
+#define QCA8K_HROUTER_PBASED_CONTROL1			0xe08
+#define QCA8K_HROUTER_PBASED_CONTROL2			0xe0c
+#define QCA8K_HNAT_CONTROL				0xe38
+
+/* MIB registers */
+#define QCA8K_PORT_MIB_COUNTER(_i)			(0x1000 + (_i) * 0x100)
+
+/* QCA specific MII registers */
+#define MII_ATH_MMD_ADDR				0x0d
+#define MII_ATH_MMD_DATA				0x0e
+
+enum {
+	QCA8K_PORT_SPEED_10M = 0,
+	QCA8K_PORT_SPEED_100M = 1,
+	QCA8K_PORT_SPEED_1000M = 2,
+	QCA8K_PORT_SPEED_ERR = 3,
+};
+
+enum qca8k_fdb_cmd {
+	QCA8K_FDB_FLUSH	= 1,
+	QCA8K_FDB_LOAD = 2,
+	QCA8K_FDB_PURGE = 3,
+	QCA8K_FDB_NEXT = 6,
+	QCA8K_FDB_SEARCH = 7,
+};
+
+struct ar8xxx_port_status {
+	struct ethtool_eee eee;
+	struct net_device *bridge_dev;
+	int enabled;
+};
+
+struct qca8k_priv {
+	struct regmap *regmap;
+	struct mii_bus *bus;
+	struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];
+	struct dsa_switch *ds;
+	struct mutex reg_mutex;
+};
+
+struct qca8k_mib_desc {
+	unsigned int size;
+	unsigned int offset;
+	const char *name;
+};
+
+struct qca8k_fdb {
+	u16 vid;
+	u8 port_mask;
+	u8 aging;
+	u8 mac[6];
+};
+
+#endif /* __QCA8K_H */
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH V3 2/3] net-next: dsa: add Qualcomm tag RX/TX handler
From: John Crispin @ 2016-09-15 14:26 UTC (permalink / raw)
  To: David S. Miller, Andrew Lunn, Florian Fainelli
  Cc: linux-kernel, netdev, qsdk-review, John Crispin
In-Reply-To: <1473949601-20674-1-git-send-email-john@phrozen.org>

Add support for the 2-bytes Qualcomm tag that gigabit switches such as
the QCA8337/N might insert when receiving packets, or that we need
to insert while targeting specific switch ports. The tag is inserted
directly behind the ethernet header.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: John Crispin <john@phrozen.org>
---
Changes in V2
* fix some comments
* remove dead code
* rename variable from phy->reg

 include/net/dsa.h  |    1 +
 net/dsa/Kconfig    |    3 ++
 net/dsa/Makefile   |    1 +
 net/dsa/dsa.c      |    3 ++
 net/dsa/dsa_priv.h |    2 +
 net/dsa/tag_qca.c  |  138 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 148 insertions(+)
 create mode 100644 net/dsa/tag_qca.c

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 24ee961..7fdd63e 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -26,6 +26,7 @@ enum dsa_tag_protocol {
 	DSA_TAG_PROTO_TRAILER,
 	DSA_TAG_PROTO_EDSA,
 	DSA_TAG_PROTO_BRCM,
+	DSA_TAG_PROTO_QCA,
 	DSA_TAG_LAST,		/* MUST BE LAST */
 };
 
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index ff7736f..96e47c5 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -38,4 +38,7 @@ config NET_DSA_TAG_EDSA
 config NET_DSA_TAG_TRAILER
 	bool
 
+config NET_DSA_TAG_QCA
+	bool
+
 endif
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index 8af4ded..a3380ed 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -7,3 +7,4 @@ dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
 dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
+dsa_core-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index d8d267e..66e31ac 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -54,6 +54,9 @@ const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = {
 #ifdef CONFIG_NET_DSA_TAG_BRCM
 	[DSA_TAG_PROTO_BRCM] = &brcm_netdev_ops,
 #endif
+#ifdef CONFIG_NET_DSA_TAG_QCA
+	[DSA_TAG_PROTO_QCA] = &qca_netdev_ops,
+#endif
 	[DSA_TAG_PROTO_NONE] = &none_ops,
 };
 
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 00077a9..6cfd738 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -81,5 +81,7 @@ extern const struct dsa_device_ops trailer_netdev_ops;
 /* tag_brcm.c */
 extern const struct dsa_device_ops brcm_netdev_ops;
 
+/* tag_qca.c */
+extern const struct dsa_device_ops qca_netdev_ops;
 
 #endif
diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c
new file mode 100644
index 0000000..0c90cac
--- /dev/null
+++ b/net/dsa/tag_qca.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/etherdevice.h>
+#include "dsa_priv.h"
+
+#define QCA_HDR_LEN	2
+#define QCA_HDR_VERSION	0x2
+
+#define QCA_HDR_RECV_VERSION_MASK	GENMASK(15, 14)
+#define QCA_HDR_RECV_VERSION_S		14
+#define QCA_HDR_RECV_PRIORITY_MASK	GENMASK(13, 11)
+#define QCA_HDR_RECV_PRIORITY_S		11
+#define QCA_HDR_RECV_TYPE_MASK		GENMASK(10, 6)
+#define QCA_HDR_RECV_TYPE_S		6
+#define QCA_HDR_RECV_FRAME_IS_TAGGED	BIT(3)
+#define QCA_HDR_RECV_SOURCE_PORT_MASK	GENMASK(2, 0)
+
+#define QCA_HDR_XMIT_VERSION_MASK	GENMASK(15, 14)
+#define QCA_HDR_XMIT_VERSION_S		14
+#define QCA_HDR_XMIT_PRIORITY_MASK	GENMASK(13, 11)
+#define QCA_HDR_XMIT_PRIORITY_S		11
+#define QCA_HDR_XMIT_CONTROL_MASK	GENMASK(10, 8)
+#define QCA_HDR_XMIT_CONTROL_S		8
+#define QCA_HDR_XMIT_FROM_CPU		BIT(7)
+#define QCA_HDR_XMIT_DP_BIT_MASK	GENMASK(6, 0)
+
+static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct dsa_slave_priv *p = netdev_priv(dev);
+	u16 *phdr, hdr;
+
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+
+	if (skb_cow_head(skb, 0) < 0)
+		goto out_free;
+
+	skb_push(skb, QCA_HDR_LEN);
+
+	memmove(skb->data, skb->data + QCA_HDR_LEN, 2 * ETH_ALEN);
+	phdr = (u16 *)(skb->data + 2 * ETH_ALEN);
+
+	/* Set the version field, and set destination port information */
+	hdr = QCA_HDR_VERSION << QCA_HDR_XMIT_VERSION_S |
+		QCA_HDR_XMIT_FROM_CPU |
+		BIT(p->port);
+
+	*phdr = htons(hdr);
+
+	return skb;
+
+out_free:
+	kfree_skb(skb);
+	return NULL;
+}
+
+static int qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
+		       struct packet_type *pt, struct net_device *orig_dev)
+{
+	struct dsa_switch_tree *dst = dev->dsa_ptr;
+	struct dsa_switch *ds;
+	u8 ver;
+	int port;
+	__be16 *phdr, hdr;
+
+	if (unlikely(!dst))
+		goto out_drop;
+
+	skb = skb_unshare(skb, GFP_ATOMIC);
+	if (!skb)
+		goto out;
+
+	if (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN)))
+		goto out_drop;
+
+	/* The QCA header is added by the switch between src addr and Ethertype
+	 * At this point, skb->data points to ethertype so header should be
+	 * right before
+	 */
+	phdr = (__be16 *)(skb->data - 2);
+	hdr = ntohs(*phdr);
+
+	/* Make sure the version is correct */
+	ver = (hdr & QCA_HDR_RECV_VERSION_MASK) >> QCA_HDR_RECV_VERSION_S;
+	if (unlikely(ver != QCA_HDR_VERSION))
+		goto out_drop;
+
+	/* Remove QCA tag and recalculate checksum */
+	skb_pull_rcsum(skb, QCA_HDR_LEN);
+	memmove(skb->data - ETH_HLEN, skb->data - ETH_HLEN - QCA_HDR_LEN,
+		ETH_HLEN - QCA_HDR_LEN);
+
+	/* This protocol doesn't support cascading multiple switches so it's
+	 * safe to assume the switch is first in the tree
+	 */
+	ds = dst->ds[0];
+	if (!ds)
+		goto out_drop;
+
+	/* Get source port information */
+	port = (hdr & QCA_HDR_RECV_SOURCE_PORT_MASK);
+	if (!ds->ports[port].netdev)
+		goto out_drop;
+
+	/* Update skb & forward the frame accordingly */
+	skb_push(skb, ETH_HLEN);
+	skb->pkt_type = PACKET_HOST;
+	skb->dev = ds->ports[port].netdev;
+	skb->protocol = eth_type_trans(skb, skb->dev);
+
+	skb->dev->stats.rx_packets++;
+	skb->dev->stats.rx_bytes += skb->len;
+
+	netif_receive_skb(skb);
+
+	return 0;
+
+out_drop:
+	kfree_skb(skb);
+out:
+	return 0;
+}
+
+const struct dsa_device_ops qca_netdev_ops = {
+	.xmit	= qca_tag_xmit,
+	.rcv	= qca_tag_rcv,
+};
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH V3 1/3] Documentation: devicetree: add qca8k binding
From: John Crispin @ 2016-09-15 14:26 UTC (permalink / raw)
  To: David S. Miller, Andrew Lunn, Florian Fainelli
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, qsdk-review-A+ZNKFmMK5xy9aJCnZT0Uw,
	John Crispin, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1473949601-20674-1-git-send-email-john-Pj+rj9U5foFAfugRpC6u6w@public.gmane.org>

Add device-tree binding for ar8xxx switch families.

Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: John Crispin <john-Pj+rj9U5foFAfugRpC6u6w@public.gmane.org>
---
Changes in V2
* fixup example to include phy nodes and corresponding phandles
* add a note explaining why we need to phy nodes

Changes in V3
* add note stating that the cpu port is always 0

 .../devicetree/bindings/net/dsa/qca8k.txt          |   89 ++++++++++++++++++++
 1 file changed, 89 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/qca8k.txt

diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.txt b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
new file mode 100644
index 0000000..9c67ee4
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
@@ -0,0 +1,89 @@
+* Qualcomm Atheros QCA8xxx switch family
+
+Required properties:
+
+- compatible: should be "qca,qca8337"
+- #size-cells: must be 0
+- #address-cells: must be 1
+
+Subnodes:
+
+The integrated switch subnode should be specified according to the binding
+described in dsa/dsa.txt. As the QCA8K switches do not have a N:N mapping of
+port and PHY id, each subnode describing a port needs to have a valid phandle
+referencing the internal PHY connected to it. The CPU port of this switch is
+always port 0.
+
+Example:
+
+
+	&mdio0 {
+		phy_port1: phy@0 {
+			reg = <0>;
+		};
+
+		phy_port2: phy@1 {
+			reg = <1>;
+		};
+
+		phy_port3: phy@2 {
+			reg = <2>;
+		};
+
+		phy_port4: phy@3 {
+			reg = <3>;
+		};
+
+		phy_port5: phy@4 {
+			reg = <4>;
+		};
+
+		switch0@0 {
+			compatible = "qca,qca8337";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			reg = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				port@0 {
+					reg = <0>;
+					label = "cpu";
+					ethernet = <&gmac1>;
+					phy-mode = "rgmii";
+				};
+
+				port@1 {
+					reg = <1>;
+					label = "lan1";
+					phy-handle = <&phy_port1>;
+				};
+
+				port@2 {
+					reg = <2>;
+					label = "lan2";
+					phy-handle = <&phy_port2>;
+				};
+
+				port@3 {
+					reg = <3>;
+					label = "lan3";
+					phy-handle = <&phy_port3>;
+				};
+
+				port@4 {
+					reg = <4>;
+					label = "lan4";
+					phy-handle = <&phy_port4>;
+				};
+
+				port@5 {
+					reg = <5>;
+					label = "wan";
+					phy-handle = <&phy_port5>;
+				};
+			};
+		};
+	};
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [Xen-devel] [RFC PATCH] xen-netback: fix error handling on netback_probe()
From: Wei Liu @ 2016-09-15 14:10 UTC (permalink / raw)
  To: Filipe Manco; +Cc: Wei Liu, netdev, Xen-devel
In-Reply-To: <c8e11688-cb11-69f6-2c79-daa0f2b3e8b4@neclab.eu>

On Thu, Sep 15, 2016 at 04:05:17PM +0200, Filipe Manco wrote:
> On 14-09-2016 12:10, Wei Liu wrote:
> >CC xen-devel as well.
> >
> >On Tue, Sep 13, 2016 at 02:11:27PM +0200, Filipe Manco wrote:
> >>In case of error during netback_probe() (e.g. an entry missing on the
> >>xenstore) netback_remove() is called on the new device, which will set
> >>the device backend state to XenbusStateClosed by calling
> >>set_backend_state(). However, the backend state wasn't initialized by
> >>netback_probe() at this point, which will cause and invalid transaction
> >>and set_backend_state() to BUG().
> >>
> >>Initialize the backend state at the beginning of netback_probe() to
> >>XenbusStateInitialising, and create a new valid state transaction on
> >>set_backend_state(), from XenbusStateInitialising to XenbusStateClosed.
> >>
> >>Signed-off-by: Filipe Manco <filipe.manco@neclab.eu>
> >There is a state machine right before set_backend_state. You would also
> >need to update that.
> Good point I'll update the diagram.
> 
> After looking at the diagram and for consistency, shouldn't the transition
> Initialising -> InitWait be handled using set_backend_state()? Currently it
> is done directly in netback_probe() code. If you agree I'll submit a v2 with
> these two changes.

That's fine with me.

Wei.

^ permalink raw reply

* Re: [Xen-devel] [RFC PATCH] xen-netback: fix error handling on netback_probe()
From: Filipe Manco @ 2016-09-15 14:05 UTC (permalink / raw)
  To: Wei Liu; +Cc: netdev, Xen-devel
In-Reply-To: <20160914101023.GY15958@citrix.com>

On 14-09-2016 12:10, Wei Liu wrote:
> CC xen-devel as well.
>
> On Tue, Sep 13, 2016 at 02:11:27PM +0200, Filipe Manco wrote:
>> In case of error during netback_probe() (e.g. an entry missing on the
>> xenstore) netback_remove() is called on the new device, which will set
>> the device backend state to XenbusStateClosed by calling
>> set_backend_state(). However, the backend state wasn't initialized by
>> netback_probe() at this point, which will cause and invalid transaction
>> and set_backend_state() to BUG().
>>
>> Initialize the backend state at the beginning of netback_probe() to
>> XenbusStateInitialising, and create a new valid state transaction on
>> set_backend_state(), from XenbusStateInitialising to XenbusStateClosed.
>>
>> Signed-off-by: Filipe Manco <filipe.manco@neclab.eu>
> There is a state machine right before set_backend_state. You would also
> need to update that.
Good point I'll update the diagram.

After looking at the diagram and for consistency, shouldn't the transition
Initialising -> InitWait be handled using set_backend_state()? Currently it
is done directly in netback_probe() code. If you agree I'll submit a v2 with
these two changes.
> According to the definition of XenbusStateInitialising, this patch looks
> plausible to me.
>
> Wei.
>
Filipe
>> ---
>>   drivers/net/xen-netback/xenbus.c | 10 ++++++++++
>>   1 file changed, 10 insertions(+)
>>
>> diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
>> index 6a31f2610c23..c0e5f6994d01 100644
>> --- a/drivers/net/xen-netback/xenbus.c
>> +++ b/drivers/net/xen-netback/xenbus.c
>> @@ -270,6 +270,7 @@ static int netback_probe(struct xenbus_device *dev,
>>   
>>   	be->dev = dev;
>>   	dev_set_drvdata(&dev->dev, be);
>> +	be->state = XenbusStateInitialising;
>>   
>>   	sg = 1;
>>   
>> @@ -515,6 +516,15 @@ static void set_backend_state(struct backend_info *be,
>>   {
>>   	while (be->state != state) {
>>   		switch (be->state) {
>> +		case XenbusStateInitialising:
>> +			switch (state) {
>> +			case XenbusStateClosed:
>> +				backend_switch_state(be, XenbusStateClosed);
>> +				break;
>> +			default:
>> +				BUG();
>> +			}
>> +			break;
>>   		case XenbusStateClosed:
>>   			switch (state) {
>>   			case XenbusStateInitWait:
>> -- 
>> 2.7.4
>>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> https://lists.xen.org/xen-devel

^ permalink raw reply

* Re: [PATCH] mwifiex: fix null pointer deference when adapter is null
From: Julian Calaby @ 2016-09-15 13:56 UTC (permalink / raw)
  To: Colin King
  Cc: Amitkumar Karwar, Nishant Sarmukadam, Kalle Valo, linux-wireless,
	netdev, linux-kernel@vger.kernel.org
In-Reply-To: <20160915134238.5167-1-colin.king@canonical.com>

Hi All,

On Thu, Sep 15, 2016 at 11:42 PM, Colin King <colin.king@canonical.com> wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> If adapter is null the error exit path in mwifiex_shutdown_sw is
> to down the semaphore sem and print some debug via mwifiex_dbg.
> However, passing a NULL adapter to mwifiex_dbg causes a null
> pointer deference when accessing adapter->dev.  This fix checks
> for a null adapter at the start of the function and to exit
> without the need to up the semaphore and we also skip the debug
> to avoid the null pointer dereference.
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>

Reviewed-by: Julian Calaby <julian.calaby@gmail.com>

Thanks,

-- 
Julian Calaby

Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/

^ permalink raw reply

* Re: [PATCH 7/9] net: ethernet: ti: cpts: calc mult and shift from refclk freq
From: Richard Cochran @ 2016-09-15 13:49 UTC (permalink / raw)
  To: Grygorii Strashko
  Cc: David S. Miller, netdev, Mugunthan V N, Sekhar Nori, linux-kernel,
	linux-omap, WingMan Kwok
In-Reply-To: <20160915115814.GB24676@localhost.localdomain>

On Thu, Sep 15, 2016 at 01:58:15PM +0200, Richard Cochran wrote:
> Can the input clock be higher than 1 GHz?  If not, I suggest using
> clocks_calc_mult_shift() with maxsec=4 and a setting the watchdog also
> to 4*HZ.

On second thought, with the new 12% timer batching, using 4*HZ for 32
bits of 1 GHz is cutting it too close.  So just keep it like you had
it, with maxsec=mask/freq and timeout=maxsec/2, to stay on the safe
side.

Thanks,
Richard

^ permalink raw reply

* [PATCH] mwifiex: fix null pointer deference when adapter is null
From: Colin King @ 2016-09-15 13:42 UTC (permalink / raw)
  To: Amitkumar Karwar, Nishant Sarmukadam, Kalle Valo, linux-wireless,
	netdev
  Cc: linux-kernel

From: Colin Ian King <colin.king@canonical.com>

If adapter is null the error exit path in mwifiex_shutdown_sw is
to down the semaphore sem and print some debug via mwifiex_dbg.
However, passing a NULL adapter to mwifiex_dbg causes a null
pointer deference when accessing adapter->dev.  This fix checks
for a null adapter at the start of the function and to exit
without the need to up the semaphore and we also skip the debug
to avoid the null pointer dereference.

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 drivers/net/wireless/marvell/mwifiex/main.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 9b2e98c..7a4f8cc 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1369,12 +1369,12 @@ mwifiex_shutdown_sw(struct mwifiex_adapter *adapter, struct semaphore *sem)
 	struct mwifiex_private *priv;
 	int i;
 
+	if (!adapter)
+		goto exit_return;
+
 	if (down_interruptible(sem))
 		goto exit_sem_err;
 
-	if (!adapter)
-		goto exit_remove;
-
 	priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 	mwifiex_deauthenticate(priv, NULL);
 
@@ -1434,6 +1434,7 @@ mwifiex_shutdown_sw(struct mwifiex_adapter *adapter, struct semaphore *sem)
 	up(sem);
 exit_sem_err:
 	mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
+exit_return:
 	return 0;
 }
 
-- 
2.9.3

^ permalink raw reply related

* [PATCH net-next 0/2] i40e: clean-up and fix for the i40e debug code
From: Stefan Assmann @ 2016-09-15 13:38 UTC (permalink / raw)
  To: intel-wired-lan; +Cc: netdev, davem, jeffrey.t.kirsher, sassmann

Stefan Assmann (2):
  i40e: remove superfluous I40E_DEBUG_USER statement
  i40e: fix setting debug parameter early

 drivers/net/ethernet/intel/i40e/i40e_common.c  |  3 --
 drivers/net/ethernet/intel/i40e/i40e_debugfs.c |  6 ----
 drivers/net/ethernet/intel/i40e/i40e_ethtool.c |  2 --
 drivers/net/ethernet/intel/i40e/i40e_main.c    | 43 ++++++++++++--------------
 drivers/net/ethernet/intel/i40e/i40e_type.h    |  2 --
 5 files changed, 20 insertions(+), 36 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH net-next 2/2] i40e: fix setting debug parameter early
From: Stefan Assmann @ 2016-09-15 13:38 UTC (permalink / raw)
  To: intel-wired-lan; +Cc: netdev, davem, jeffrey.t.kirsher, sassmann
In-Reply-To: <1473946689-28427-1-git-send-email-sassmann@kpanic.de>

pf->msg_enable is a bitmask, therefore assigning the value of the
"debug" parameter is wrong. It is initialized again later in
i40e_sw_init() so it didn't cause any problem, except that we missed
early debug messages. Moved the initialization and assigned
pf->hw.debug_mask the bitmask as that's what the driver actually uses
in i40e_debug(). Otherwise the debug parameter is just a noop.

Fixes: 5b5faa4 ("i40e: enable debug earlier")

Signed-off-by: Stefan Assmann <sassmann@kpanic.de>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 56369761..f972f0d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -8498,11 +8498,6 @@ static int i40e_sw_init(struct i40e_pf *pf)
 	int err = 0;
 	int size;
 
-	pf->msg_enable = netif_msg_init(debug,
-					NETIF_MSG_DRV    |
-					NETIF_MSG_PROBE  |
-					NETIF_MSG_LINK);
-
 	/* Set default capability flags */
 	pf->flags = I40E_FLAG_RX_CSUM_ENABLED |
 		    I40E_FLAG_MSI_ENABLED     |
@@ -10812,10 +10807,13 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	mutex_init(&hw->aq.asq_mutex);
 	mutex_init(&hw->aq.arq_mutex);
 
-	if (debug != -1) {
-		pf->msg_enable = pf->hw.debug_mask;
-		pf->msg_enable = debug;
-	}
+	/* enable debug prints if requested */
+	pf->msg_enable = netif_msg_init(debug,
+					NETIF_MSG_DRV   |
+					NETIF_MSG_PROBE |
+					NETIF_MSG_LINK);
+	if (debug != -1)
+		pf->hw.debug_mask = pf->msg_enable;
 
 	/* do a special CORER for clearing PXE mode once at init */
 	if (hw->revision_id == 0 &&
-- 
2.7.4

^ permalink raw reply related

* [PATCH net-next 1/2] i40e: remove superfluous I40E_DEBUG_USER statement
From: Stefan Assmann @ 2016-09-15 13:38 UTC (permalink / raw)
  To: intel-wired-lan; +Cc: netdev, davem, jeffrey.t.kirsher, sassmann
In-Reply-To: <1473946689-28427-1-git-send-email-sassmann@kpanic.de>

This debug statement is confusing and never set in the code. Any debug
output should be guarded by the proper I40E_DEBUG_* statement which can
be enabled via the debug module parameter.
Remove or convert the I40E_DEBUG_USER cases to I40E_DEBUG_INIT.

Signed-off-by: Stefan Assmann <sassmann@kpanic.de>
---
 drivers/net/ethernet/intel/i40e/i40e_common.c  |  3 ---
 drivers/net/ethernet/intel/i40e/i40e_debugfs.c |  6 -----
 drivers/net/ethernet/intel/i40e/i40e_ethtool.c |  2 --
 drivers/net/ethernet/intel/i40e/i40e_main.c    | 35 +++++++++++++-------------
 drivers/net/ethernet/intel/i40e/i40e_type.h    |  2 --
 5 files changed, 17 insertions(+), 31 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index 2154a34..8ccb09c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -3207,9 +3207,6 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
 			break;
 		case I40E_AQ_CAP_ID_MSIX:
 			p->num_msix_vectors = number;
-			i40e_debug(hw, I40E_DEBUG_INIT,
-				   "HW Capability: MSIX vector count = %d\n",
-				   p->num_msix_vectors);
 			break;
 		case I40E_AQ_CAP_ID_VF_MSIX:
 			p->num_msix_vectors_vf = number;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index 05cf9a7..e9c6f1c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -1210,12 +1210,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
 		u32 level;
 		cnt = sscanf(&cmd_buf[10], "%i", &level);
 		if (cnt) {
-			if (I40E_DEBUG_USER & level) {
-				pf->hw.debug_mask = level;
-				dev_info(&pf->pdev->dev,
-					 "set hw.debug_mask = 0x%08x\n",
-					 pf->hw.debug_mask);
-			}
 			pf->msg_enable = level;
 			dev_info(&pf->pdev->dev, "set msg_enable = 0x%08x\n",
 				 pf->msg_enable);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index 1835186..c56877c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -987,8 +987,6 @@ static void i40e_set_msglevel(struct net_device *netdev, u32 data)
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_pf *pf = np->vsi->back;
 
-	if (I40E_DEBUG_USER & data)
-		pf->hw.debug_mask = data;
 	pf->msg_enable = data;
 }
 
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 61b0fc4..56369761 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -6665,16 +6665,19 @@ static int i40e_get_capabilities(struct i40e_pf *pf)
 		}
 	} while (err);
 
-	if (pf->hw.debug_mask & I40E_DEBUG_USER)
-		dev_info(&pf->pdev->dev,
-			 "pf=%d, num_vfs=%d, msix_pf=%d, msix_vf=%d, fd_g=%d, fd_b=%d, pf_max_q=%d num_vsi=%d\n",
-			 pf->hw.pf_id, pf->hw.func_caps.num_vfs,
-			 pf->hw.func_caps.num_msix_vectors,
-			 pf->hw.func_caps.num_msix_vectors_vf,
-			 pf->hw.func_caps.fd_filters_guaranteed,
-			 pf->hw.func_caps.fd_filters_best_effort,
-			 pf->hw.func_caps.num_tx_qp,
-			 pf->hw.func_caps.num_vsis);
+	i40e_debug(&pf->hw, I40E_DEBUG_INIT,
+		   "HW Capabilities: PF-id[%d] num_vfs=%d, msix_pf=%d, msix_vf=%d\n",
+		   pf->hw.pf_id,
+		   pf->hw.func_caps.num_vfs,
+		   pf->hw.func_caps.num_msix_vectors,
+		   pf->hw.func_caps.num_msix_vectors_vf);
+	i40e_debug(&pf->hw, I40E_DEBUG_INIT,
+		   "HW Capabilities: PF-id[%d] fd_g=%d, fd_b=%d, pf_max_qp=%d num_vsis=%d\n",
+		   pf->hw.pf_id,
+		   pf->hw.func_caps.fd_filters_guaranteed,
+		   pf->hw.func_caps.fd_filters_best_effort,
+		   pf->hw.func_caps.num_tx_qp,
+		   pf->hw.func_caps.num_vsis);
 
 #define DEF_NUM_VSI (1 + (pf->hw.func_caps.fcoe ? 1 : 0) \
 		       + pf->hw.func_caps.num_vfs)
@@ -8495,14 +8498,10 @@ static int i40e_sw_init(struct i40e_pf *pf)
 	int err = 0;
 	int size;
 
-	pf->msg_enable = netif_msg_init(I40E_DEFAULT_MSG_ENABLE,
-				(NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK));
-	if (debug != -1 && debug != I40E_DEFAULT_MSG_ENABLE) {
-		if (I40E_DEBUG_USER & debug)
-			pf->hw.debug_mask = debug;
-		pf->msg_enable = netif_msg_init((debug & ~I40E_DEBUG_USER),
-						I40E_DEFAULT_MSG_ENABLE);
-	}
+	pf->msg_enable = netif_msg_init(debug,
+					NETIF_MSG_DRV    |
+					NETIF_MSG_PROBE  |
+					NETIF_MSG_LINK);
 
 	/* Set default capability flags */
 	pf->flags = I40E_FLAG_RX_CSUM_ENABLED |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
index bd5f13b..7e88e35 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
@@ -85,8 +85,6 @@ enum i40e_debug_mask {
 	I40E_DEBUG_AQ_COMMAND		= 0x06000000,
 	I40E_DEBUG_AQ			= 0x0F000000,
 
-	I40E_DEBUG_USER			= 0xF0000000,
-
 	I40E_DEBUG_ALL			= 0xFFFFFFFF
 };
 
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH] iproute2: build nsid-name cache only for commands that need it
From: Nicolas Dichtel @ 2016-09-15 13:26 UTC (permalink / raw)
  To: Anton Aksola, netdev
In-Reply-To: <20160915082326.GA1635@toys.tundra.dog-lvm.novalocal>

Le 15/09/2016 à 10:23, Anton Aksola a écrit :
[snip]
> --- a/ip/ipnetns.c
> +++ b/ip/ipnetns.c
> @@ -775,8 +775,6 @@ static int netns_monitor(int argc, char **argv)
>  
>  int do_netns(int argc, char **argv)
>  {
> -	netns_map_init();
> -
>  	if (argc < 1)
>  		return netns_list(0, NULL);
>  
> @@ -784,8 +782,10 @@ int do_netns(int argc, char **argv)
>  	    (matches(*argv, "lst") == 0))
>  		return netns_list(argc-1, argv+1);
>  
> -	if ((matches(*argv, "list-id") == 0))
> +	if ((matches(*argv, "list-id") == 0)) {
> +		netns_map_init();
>  		return netns_list_id(argc-1, argv+1);
> +	}
'ip netns' (ip netns list) also need it.

^ permalink raw reply

* [PATCH net-next 2/3] net/mlx5e: Introduce API for RX mapped pages
From: Tariq Toukan @ 2016-09-15 13:08 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, Eran Ben Elisha, Saeed Mahameed, Tariq Toukan
In-Reply-To: <1473944918-31290-1-git-send-email-tariqt@mellanox.com>

Manage the allocation and deallocation of mapped RX pages only
through dedicated API functions.

Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 46 +++++++++++++++----------
 1 file changed, 27 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 5d1b7b5e4f36..0c34daa04c43 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -305,26 +305,32 @@ static inline void mlx5e_post_umr_wqe(struct mlx5e_rq *rq, u16 ix)
 	mlx5e_tx_notify_hw(sq, &wqe->ctrl, 0);
 }
 
-static inline int mlx5e_alloc_and_map_page(struct mlx5e_rq *rq,
-					   struct mlx5e_mpw_info *wi,
-					   int i)
+static inline int mlx5e_page_alloc_mapped(struct mlx5e_rq *rq,
+					  struct mlx5e_dma_info *dma_info)
 {
 	struct page *page = dev_alloc_page();
+
 	if (unlikely(!page))
 		return -ENOMEM;
 
-	wi->umr.dma_info[i].page = page;
-	wi->umr.dma_info[i].addr = dma_map_page(rq->pdev, page, 0, PAGE_SIZE,
-						PCI_DMA_FROMDEVICE);
-	if (unlikely(dma_mapping_error(rq->pdev, wi->umr.dma_info[i].addr))) {
+	dma_info->page = page;
+	dma_info->addr = dma_map_page(rq->pdev, page, 0, PAGE_SIZE,
+				      DMA_FROM_DEVICE);
+	if (unlikely(dma_mapping_error(rq->pdev, dma_info->addr))) {
 		put_page(page);
 		return -ENOMEM;
 	}
-	wi->umr.mtt[i] = cpu_to_be64(wi->umr.dma_info[i].addr | MLX5_EN_WR);
 
 	return 0;
 }
 
+static inline void mlx5e_page_release(struct mlx5e_rq *rq,
+				      struct mlx5e_dma_info *dma_info)
+{
+	dma_unmap_page(rq->pdev, dma_info->addr, PAGE_SIZE, DMA_FROM_DEVICE);
+	put_page(dma_info->page);
+}
+
 static int mlx5e_alloc_rx_umr_mpwqe(struct mlx5e_rq *rq,
 				    struct mlx5e_rx_wqe *wqe,
 				    u16 ix)
@@ -336,10 +342,13 @@ static int mlx5e_alloc_rx_umr_mpwqe(struct mlx5e_rq *rq,
 	int i;
 
 	for (i = 0; i < MLX5_MPWRQ_PAGES_PER_WQE; i++) {
-		err = mlx5e_alloc_and_map_page(rq, wi, i);
+		struct mlx5e_dma_info *dma_info = &wi->umr.dma_info[i];
+
+		err = mlx5e_page_alloc_mapped(rq, dma_info);
 		if (unlikely(err))
 			goto err_unmap;
-		page_ref_add(wi->umr.dma_info[i].page, pg_strides);
+		wi->umr.mtt[i] = cpu_to_be64(dma_info->addr | MLX5_EN_WR);
+		page_ref_add(dma_info->page, pg_strides);
 		wi->skbs_frags[i] = 0;
 	}
 
@@ -350,10 +359,10 @@ static int mlx5e_alloc_rx_umr_mpwqe(struct mlx5e_rq *rq,
 
 err_unmap:
 	while (--i >= 0) {
-		dma_unmap_page(rq->pdev, wi->umr.dma_info[i].addr, PAGE_SIZE,
-			       PCI_DMA_FROMDEVICE);
-		page_ref_sub(wi->umr.dma_info[i].page, pg_strides);
-		put_page(wi->umr.dma_info[i].page);
+		struct mlx5e_dma_info *dma_info = &wi->umr.dma_info[i];
+
+		page_ref_sub(dma_info->page, pg_strides);
+		mlx5e_page_release(rq, dma_info);
 	}
 
 	return err;
@@ -365,11 +374,10 @@ void mlx5e_free_rx_mpwqe(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi)
 	int i;
 
 	for (i = 0; i < MLX5_MPWRQ_PAGES_PER_WQE; i++) {
-		dma_unmap_page(rq->pdev, wi->umr.dma_info[i].addr, PAGE_SIZE,
-			       PCI_DMA_FROMDEVICE);
-		page_ref_sub(wi->umr.dma_info[i].page,
-			     pg_strides - wi->skbs_frags[i]);
-		put_page(wi->umr.dma_info[i].page);
+		struct mlx5e_dma_info *dma_info = &wi->umr.dma_info[i];
+
+		page_ref_sub(dma_info->page, pg_strides - wi->skbs_frags[i]);
+		mlx5e_page_release(rq, dma_info);
 	}
 }
 
-- 
1.8.3.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox