]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'mac80211-next-for-davem-2017-06-13' of git://git.kernel.org/pub/scm/linux...
authorDavid S. Miller <davem@davemloft.net>
Tue, 13 Jun 2017 17:52:37 +0000 (13:52 -0400)
committerDavid S. Miller <davem@davemloft.net>
Tue, 13 Jun 2017 17:52:37 +0000 (13:52 -0400)
Johannes Berg says:

====================
A couple of weeks worth of updates - looks like things are quiet:
 * merged net-next back to get a patch from net that another patch
   here depends on
 * various small improvements/cleanups across the board
 * 4-way handshake offload (many thanks to Arend for shepherding that)
 * mesh CSA/DFS support in mac80211
 * the skb_put_zero() we discussed previously
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
350 files changed:
Documentation/networking/rxrpc.txt
MAINTAINERS
arch/arm64/net/bpf_jit_comp.c
arch/powerpc/include/asm/hvcall.h
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/qedr/main.c
drivers/infiniband/hw/qedr/qedr.h
drivers/infiniband/hw/qedr/qedr_cm.c
drivers/isdn/hardware/mISDN/mISDNipac.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_main.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/chip.h
drivers/net/dsa/mv88e6xxx/phy.c
drivers/net/dsa/mv88e6xxx/phy.h
drivers/net/dsa/mv88e6xxx/port.c
drivers/net/dsa/mv88e6xxx/port.h
drivers/net/dsa/mv88e6xxx/serdes.c
drivers/net/ethernet/amd/xgbe/xgbe-drv.c
drivers/net/ethernet/apm/xgene-v2/ethtool.c
drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bcm63xx_enet.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/ucc_geth_ethtool.c
drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
drivers/net/ethernet/ibm/emac/phy.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/mvpp2.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
drivers/net/ethernet/netronome/nfp/nfp_app.c
drivers/net/ethernet/netronome/nfp/nfp_app.h
drivers/net/ethernet/netronome/nfp/nfp_app_nic.c
drivers/net/ethernet/netronome/nfp/nfp_main.c
drivers/net/ethernet/netronome/nfp/nfp_main.h
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
drivers/net/ethernet/netronome/nfp/nfp_net_main.c
drivers/net/ethernet/netronome/nfp/nfpcore/nfp.h
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_hwinfo.c
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_mip.c
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nffw.h
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c
drivers/net/ethernet/qlogic/qed/qed.h
drivers/net/ethernet/qlogic/qed/qed_ll2.c
drivers/net/ethernet/qlogic/qed/qed_ll2.h
drivers/net/ethernet/qlogic/qed/qed_roce.c
drivers/net/ethernet/qlogic/qed/qed_roce.h
drivers/net/ethernet/qlogic/qed/qed_vf.h
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/rocker/rocker.h
drivers/net/ethernet/rocker/rocker_main.c
drivers/net/ethernet/rocker/rocker_ofdpa.c
drivers/net/ethernet/sfc/efx.h
drivers/net/ethernet/sfc/falcon/efx.h
drivers/net/ethernet/sfc/falcon/tx.c
drivers/net/ethernet/sfc/tx.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/davinci_cpdma.c
drivers/net/ethernet/ti/netcp_core.c
drivers/net/ethernet/ti/netcp_ethss.c
drivers/net/geneve.c
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/ipvlan/ipvlan_main.c
drivers/net/phy/marvell.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/phy.c
drivers/net/sungem_phy.c
drivers/net/team/team.c
drivers/net/usb/lan78xx.c
drivers/net/usb/r8152.c
drivers/net/vxlan.c
drivers/net/wireless/Kconfig
drivers/net/wireless/Makefile
drivers/net/wireless/ath/ath10k/Kconfig
drivers/net/wireless/ath/ath10k/Makefile
drivers/net/wireless/ath/ath10k/bmi.c
drivers/net/wireless/ath/ath10k/bmi.h
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/debug.c
drivers/net/wireless/ath/ath10k/debug.h
drivers/net/wireless/ath/ath10k/htc.c
drivers/net/wireless/ath/ath10k/htc.h
drivers/net/wireless/ath/ath10k/hw.h
drivers/net/wireless/ath/ath10k/sdio.c [new file with mode: 0644]
drivers/net/wireless/ath/ath10k/sdio.h [new file with mode: 0644]
drivers/net/wireless/ath/ath10k/targaddrs.h
drivers/net/wireless/ath/ath10k/testmode.c
drivers/net/wireless/ath/ath10k/testmode_i.h
drivers/net/wireless/ath/ath5k/debug.c
drivers/net/wireless/ath/ath6kl/txrx.c
drivers/net/wireless/ath/ath9k/common.c
drivers/net/wireless/ath/ath9k/eeprom.c
drivers/net/wireless/ath/ath9k/tx99.c
drivers/net/wireless/ath/wil6210/debugfs.c
drivers/net/wireless/broadcom/b43/main.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
drivers/net/wireless/intel/iwlegacy/common.c
drivers/net/wireless/intel/iwlegacy/common.h
drivers/net/wireless/intersil/hostap/hostap_hw.c
drivers/net/wireless/intersil/hostap/hostap_wlan.h
drivers/net/wireless/intersil/orinoco/orinoco_usb.c
drivers/net/wireless/intersil/p54/fwio.c
drivers/net/wireless/marvell/libertas/cfg.c
drivers/net/wireless/marvell/libertas/cmd.c
drivers/net/wireless/marvell/libertas/cmdresp.c
drivers/net/wireless/marvell/libertas/defs.h
drivers/net/wireless/marvell/libertas/ethtool.c
drivers/net/wireless/marvell/libertas/if_cs.c
drivers/net/wireless/marvell/libertas/if_sdio.c
drivers/net/wireless/marvell/libertas/if_spi.c
drivers/net/wireless/marvell/libertas/if_usb.c
drivers/net/wireless/marvell/libertas/main.c
drivers/net/wireless/marvell/libertas/mesh.c
drivers/net/wireless/marvell/libertas/rx.c
drivers/net/wireless/marvell/libertas/tx.c
drivers/net/wireless/marvell/mwifiex/11h.c
drivers/net/wireless/marvell/mwifiex/11n.c
drivers/net/wireless/marvell/mwifiex/11n_aggr.c
drivers/net/wireless/marvell/mwifiex/cfg80211.c
drivers/net/wireless/marvell/mwifiex/cmdevt.c
drivers/net/wireless/marvell/mwifiex/fw.h
drivers/net/wireless/marvell/mwifiex/init.c
drivers/net/wireless/marvell/mwifiex/main.c
drivers/net/wireless/marvell/mwifiex/main.h
drivers/net/wireless/marvell/mwifiex/pcie.c
drivers/net/wireless/marvell/mwifiex/sdio.c
drivers/net/wireless/marvell/mwifiex/sta_cmd.c
drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
drivers/net/wireless/marvell/mwifiex/sta_tx.c
drivers/net/wireless/marvell/mwifiex/tdls.c
drivers/net/wireless/marvell/mwifiex/txrx.c
drivers/net/wireless/marvell/mwifiex/uap_event.c
drivers/net/wireless/marvell/mwifiex/uap_txrx.c
drivers/net/wireless/marvell/mwifiex/usb.c
drivers/net/wireless/marvell/mwifiex/usb.h
drivers/net/wireless/marvell/mwifiex/wmm.c
drivers/net/wireless/quantenna/Kconfig [new file with mode: 0644]
drivers/net/wireless/quantenna/Makefile [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/Kconfig [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/Makefile [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/bus.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/cfg80211.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/commands.c [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/commands.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/core.c [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/core.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/debug.c [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/debug.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/event.c [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/event.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_ipc.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_regs_pearl.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/qlink.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/qlink_util.c [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/qlink_util.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/trans.c [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/trans.h [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/util.c [new file with mode: 0644]
drivers/net/wireless/quantenna/qtnfmac/util.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2400pci.c
drivers/net/wireless/ralink/rt2x00/rt2500pci.c
drivers/net/wireless/ralink/rt2x00/rt2500usb.c
drivers/net/wireless/ralink/rt2x00/rt2800lib.c
drivers/net/wireless/ralink/rt2x00/rt2800lib.h
drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
drivers/net/wireless/ralink/rt2x00/rt2800pci.c
drivers/net/wireless/ralink/rt2x00/rt2800usb.c
drivers/net/wireless/ralink/rt2x00/rt2x00.h
drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
drivers/net/wireless/ralink/rt2x00/rt2x00debug.h
drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c
drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h
drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
drivers/net/wireless/ralink/rt2x00/rt2x00usb.h
drivers/net/wireless/ralink/rt2x00/rt61pci.c
drivers/net/wireless/ralink/rt2x00/rt73usb.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
drivers/net/wireless/rsi/Makefile
drivers/net/wireless/rsi/rsi_91x_core.c
drivers/net/wireless/rsi/rsi_91x_hal.c [new file with mode: 0644]
drivers/net/wireless/rsi/rsi_91x_pkt.c [deleted file]
drivers/net/wireless/rsi/rsi_91x_sdio.c
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
drivers/net/wireless/rsi/rsi_91x_usb.c
drivers/net/wireless/rsi/rsi_91x_usb_ops.c
drivers/net/wireless/rsi/rsi_common.h
drivers/net/wireless/rsi/rsi_hal.h [new file with mode: 0644]
drivers/net/wireless/rsi/rsi_main.h
drivers/net/wireless/rsi/rsi_sdio.h
drivers/net/wireless/rsi/rsi_usb.h
drivers/net/wireless/ti/wlcore/debugfs.c
drivers/net/wireless/ti/wlcore/spi.c
drivers/of/of_mdio.c
drivers/ssb/main.c
drivers/staging/netlogic/xlr_net.c
fs/afs/rxrpc.c
include/linux/inetdevice.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mlx5/port.h
include/linux/netdevice.h
include/linux/phy.h
include/linux/qed/qed_ll2_if.h
include/linux/qed/qed_roce_if.h
include/linux/rxrpc.h
include/linux/skbuff.h
include/net/addrconf.h
include/net/af_rxrpc.h
include/net/netns/ipv4.h
include/net/secure_seq.h
include/net/sock.h
include/net/switchdev.h
include/net/tcp.h
include/uapi/linux/bpf.h
include/uapi/linux/mroute.h
include/uapi/linux/neighbour.h
include/uapi/linux/snmp.h
kernel/bpf/verifier.c
kernel/trace/bpf_trace.c
net/8021q/vlan_dev.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/bat_v.c
net/batman-adv/bat_v_elp.c
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/distributed-arp-table.c
net/batman-adv/main.h
net/batman-adv/network-coding.c
net/batman-adv/routing.c
net/batman-adv/send.c
net/batman-adv/tp_meter.c
net/batman-adv/translation-table.c
net/bridge/br.c
net/bridge/br_fdb.c
net/bridge/br_netlink.c
net/bridge/br_private.h
net/bridge/br_switchdev.c
net/core/datagram.c
net/core/filter.c
net/core/net_namespace.c
net/core/secure_seq.c
net/core/skbuff.c
net/core/sock.c
net/decnet/af_decnet.c
net/dsa/slave.c
net/dsa/switch.c
net/ipv4/devinet.c
net/ipv4/ipmr.c
net/ipv4/proc.c
net/ipv4/syncookies.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/addrconf_core.c
net/ipv6/ip6_output.c
net/ipv6/syncookies.c
net/ipv6/tcp_ipv6.c
net/packet/af_packet.c
net/qrtr/qrtr.c
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/call_object.c
net/rxrpc/sendmsg.c
net/sched/cls_bpf.c
net/sched/cls_flower.c
net/sched/cls_matchall.c
net/sched/cls_u32.c
net/sched/sch_mqprio.c
net/sctp/associola.c
net/sctp/proc.c
net/sctp/socket.c
net/switchdev/switchdev.c
tools/include/uapi/linux/bpf.h
tools/testing/selftests/bpf/test_align.c
tools/testing/selftests/bpf/test_maps.c
tools/testing/selftests/bpf/test_obj_id.c
tools/testing/selftests/bpf/test_progs.c

index 18078e630a6325abdd9746a7c385ec8867bcbd15..8c70ba5dee4d0072da0ac8666d987248758afa0f 100644 (file)
@@ -327,6 +327,7 @@ calls, to invoke certain actions and to report certain conditions.  These are:
        RXRPC_ACCEPT            s-- n/a         Accept new call
        RXRPC_EXCLUSIVE_CALL    s-- n/a         Make an exclusive client call
        RXRPC_UPGRADE_SERVICE   s-- n/a         Client call can be upgraded
+       RXRPC_TX_LENGTH         s-- data len    Total length of Tx data
 
        (SRT = usable in Sendmsg / delivered by Recvmsg / Terminal message)
 
@@ -406,6 +407,23 @@ calls, to invoke certain actions and to report certain conditions.  These are:
      future communication to that server and RXRPC_UPGRADE_SERVICE should no
      longer be set.
 
+ (*) RXRPC_TX_LENGTH
+
+     This is used to inform the kernel of the total amount of data that is
+     going to be transmitted by a call (whether in a client request or a
+     service response).  If given, it allows the kernel to encrypt from the
+     userspace buffer directly to the packet buffers, rather than copying into
+     the buffer and then encrypting in place.  This may only be given with the
+     first sendmsg() providing data for a call.  EMSGSIZE will be generated if
+     the amount of data actually given is different.
+
+     This takes a parameter of __s64 type that indicates how much will be
+     transmitted.  This may not be less than zero.
+
+The symbol RXRPC__SUPPORTED is defined as one more than the highest control
+message type supported.  At run time this can be queried by means of the
+RXRPC_SUPPORTED_CMSG socket option (see below).
+
 
 ==============
 SOCKET OPTIONS
@@ -459,6 +477,11 @@ AF_RXRPC sockets support a few socket options at the SOL_RXRPC level:
      must point to an array of two unsigned short ints.  The first is the
      service ID to upgrade from and the second the service ID to upgrade to.
 
+ (*) RXRPC_SUPPORTED_CMSG
+
+     This is a read-only option that writes an int into the buffer indicating
+     the highest control message type supported.
+
 
 ========
 SECURITY
@@ -568,6 +591,9 @@ A client would issue an operation by:
      MSG_MORE should be set in msghdr::msg_flags on all but the last part of
      the request.  Multiple requests may be made simultaneously.
 
+     An RXRPC_TX_LENGTH control message can also be specified on the first
+     sendmsg() call.
+
      If a call is intended to go to a destination other than the default
      specified through connect(), then msghdr::msg_name should be set on the
      first request message of that call.
@@ -755,6 +781,7 @@ The kernel interface functions are as follows:
                                struct sockaddr_rxrpc *srx,
                                struct key *key,
                                unsigned long user_call_ID,
+                               s64 tx_total_len,
                                gfp_t gfp);
 
      This allocates the infrastructure to make a new RxRPC call and assigns
@@ -771,6 +798,11 @@ The kernel interface functions are as follows:
      control data buffer.  It is entirely feasible to use this to point to a
      kernel data structure.
 
+     tx_total_len is the amount of data the caller is intending to transmit
+     with this call (or -1 if unknown at this point).  Setting the data size
+     allows the kernel to encrypt directly to the packet buffers, thereby
+     saving a copy.  The value may not be less than -1.
+
      If this function is successful, an opaque reference to the RxRPC call is
      returned.  The caller now holds a reference on this and it must be
      properly ended.
@@ -922,6 +954,17 @@ The kernel interface functions are as follows:
 
      This is used to find the remote peer address of a call.
 
+ (*) Set the total transmit data size on a call.
+
+       void rxrpc_kernel_set_tx_length(struct socket *sock,
+                                       struct rxrpc_call *call,
+                                       s64 tx_total_len);
+
+     This sets the amount of data that the caller is intending to transmit on a
+     call.  It's intended to be used for setting the reply size as the request
+     size should be set when the call is begun.  tx_total_len may not be less
+     than zero.
+
 
 =======================
 CONFIGURABLE PARAMETERS
index 8b8249b576bf57e5420b147d60c764ca1750cd15..f4e682c67475d1958d7aa3dba5e06307d74c5fe9 100644 (file)
@@ -10634,6 +10634,14 @@ L:     qemu-devel@nongnu.org
 S:     Maintained
 F:     drivers/firmware/qemu_fw_cfg.c
 
+QUANTENNA QTNFMAC WIRELESS DRIVER
+M:   Igor Mitsyanko <imitsyanko@quantenna.com>
+M:   Avinash Patil <avinashp@quantenna.com>
+M:   Sergey Matyukevich <smatyukevich@quantenna.com>
+L:   linux-wireless@vger.kernel.org
+S:   Maintained
+F:   drivers/net/wireless/quantenna
+
 RADOS BLOCK DEVICE (RBD)
 M:     Ilya Dryomov <idryomov@gmail.com>
 M:     Sage Weil <sage@redhat.com>
index 4f95873d71426b1b7131d795aff75323908c2219..73de2c71cfb08ce4bca60786482ca3ed71b21809 100644 (file)
@@ -69,6 +69,7 @@ struct jit_ctx {
        int epilogue_offset;
        int *offset;
        u32 *image;
+       u32 stack_size;
 };
 
 static inline void emit(const u32 insn, struct jit_ctx *ctx)
@@ -145,16 +146,11 @@ static inline int epilogue_offset(const struct jit_ctx *ctx)
 /* Stack must be multiples of 16B */
 #define STACK_ALIGN(sz) (((sz) + 15) & ~15)
 
-#define _STACK_SIZE \
-       (MAX_BPF_STACK \
-        + 4 /* extra for skb_copy_bits buffer */)
-
-#define STACK_SIZE STACK_ALIGN(_STACK_SIZE)
-
 #define PROLOGUE_OFFSET 8
 
 static int build_prologue(struct jit_ctx *ctx)
 {
+       const struct bpf_prog *prog = ctx->prog;
        const u8 r6 = bpf2a64[BPF_REG_6];
        const u8 r7 = bpf2a64[BPF_REG_7];
        const u8 r8 = bpf2a64[BPF_REG_8];
@@ -176,9 +172,9 @@ static int build_prologue(struct jit_ctx *ctx)
         *                        |     |
         *                        | ... | BPF prog stack
         *                        |     |
-        *                        +-----+ <= (BPF_FP - MAX_BPF_STACK)
+        *                        +-----+ <= (BPF_FP - prog->aux->stack_depth)
         *                        |RSVD | JIT scratchpad
-        * current A64_SP =>      +-----+ <= (BPF_FP - STACK_SIZE)
+        * current A64_SP =>      +-----+ <= (BPF_FP - ctx->stack_size)
         *                        |     |
         *                        | ... | Function call stack
         *                        |     |
@@ -202,8 +198,12 @@ static int build_prologue(struct jit_ctx *ctx)
        /* Initialize tail_call_cnt */
        emit(A64_MOVZ(1, tcc, 0, 0), ctx);
 
+       /* 4 byte extra for skb_copy_bits buffer */
+       ctx->stack_size = prog->aux->stack_depth + 4;
+       ctx->stack_size = STACK_ALIGN(ctx->stack_size);
+
        /* Set up function call stack */
-       emit(A64_SUB_I(1, A64_SP, A64_SP, STACK_SIZE), ctx);
+       emit(A64_SUB_I(1, A64_SP, A64_SP, ctx->stack_size), ctx);
 
        cur_offset = ctx->idx - idx0;
        if (cur_offset != PROLOGUE_OFFSET) {
@@ -288,7 +288,7 @@ static void build_epilogue(struct jit_ctx *ctx)
        const u8 fp = bpf2a64[BPF_REG_FP];
 
        /* We're done with BPF stack */
-       emit(A64_ADD_I(1, A64_SP, A64_SP, STACK_SIZE), ctx);
+       emit(A64_ADD_I(1, A64_SP, A64_SP, ctx->stack_size), ctx);
 
        /* Restore fs (x25) and x26 */
        emit(A64_POP(fp, A64_R(26), A64_SP), ctx);
@@ -732,7 +732,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                        return -EINVAL;
                }
                emit_a64_mov_i64(r3, size, ctx);
-               emit(A64_SUB_I(1, r4, fp, STACK_SIZE), ctx);
+               emit(A64_SUB_I(1, r4, fp, ctx->stack_size), ctx);
                emit_a64_mov_i64(r5, (unsigned long)bpf_load_pointer, ctx);
                emit(A64_BLR(r5), ctx);
                emit(A64_MOV(1, r0, A64_R(0)), ctx);
index d73755fafbb0002544459b58fdf73d41375f641f..57d38b504ff773facfeaee601cd5bab8e2d9796c 100644 (file)
 #define H_DISABLE_ALL_VIO_INTS 0x0A
 #define H_DISABLE_VIO_INTERRUPT        0x0B
 #define H_ENABLE_VIO_INTERRUPT 0x0C
+#define H_GET_SESSION_TOKEN    0x19
+#define H_SESSION_ERR_DETECTED 0x1A
 
 
 /* Platform specific hcalls, used by KVM */
index b0ae4f0c8aa7f143bed5967b97c7006ad61db4a1..2f1136bf7b1f6bc9721c9883f54900d9195dedf3 100644 (file)
@@ -3756,7 +3756,7 @@ static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos)
         */
        memset(&tmp_opt, 0, sizeof(tmp_opt));
        tcp_clear_options(&tmp_opt);
-       tcp_parse_options(skb, &tmp_opt, 0, NULL);
+       tcp_parse_options(&init_net, skb, &tmp_opt, 0, NULL);
 
        req = (struct cpl_pass_accept_req *)__skb_push(skb, sizeof(*req));
        memset(req, 0, sizeof(*req));
index 6a72095d6c7acf7b4c62ce6720118f8a128de523..485c1fef238bc45b7e83fa14064ce1f33de78b56 100644 (file)
@@ -886,9 +886,9 @@ static void qedr_mac_address_change(struct qedr_dev *dev)
        memcpy(&sgid->raw[8], guid, sizeof(guid));
 
        /* Update LL2 */
-       rc = dev->ops->roce_ll2_set_mac_filter(dev->cdev,
-                                              dev->gsi_ll2_mac_address,
-                                              dev->ndev->dev_addr);
+       rc = dev->ops->ll2_set_mac_filter(dev->cdev,
+                                         dev->gsi_ll2_mac_address,
+                                         dev->ndev->dev_addr);
 
        ether_addr_copy(dev->gsi_ll2_mac_address, dev->ndev->dev_addr);
 
index aa08c76a42450a2ef86d1854b45a80d7bcd4387c..80333ec2c8b66d6061e7fc62492c5402395f5074 100644 (file)
@@ -150,6 +150,8 @@ struct qedr_dev {
        u32                     dp_module;
        u8                      dp_level;
        u8                      num_hwfns;
+       u8                      gsi_ll2_handle;
+
        uint                    wq_multiplier;
        u8                      gsi_ll2_mac_address[ETH_ALEN];
        int                     gsi_qp_created;
index d86dbe814d98fbe00adf22acb6d1ee658efc5ef5..eb3dce72fc21dac1844016cb75d6a5c66a0feec9 100644 (file)
@@ -64,9 +64,14 @@ void qedr_store_gsi_qp_cq(struct qedr_dev *dev, struct qedr_qp *qp,
        dev->gsi_qp = qp;
 }
 
-void qedr_ll2_tx_cb(void *_qdev, struct qed_roce_ll2_packet *pkt)
+void qedr_ll2_complete_tx_packet(void *cxt,
+                                u8 connection_handle,
+                                void *cookie,
+                                dma_addr_t first_frag_addr,
+                                bool b_last_fragment, bool b_last_packet)
 {
-       struct qedr_dev *dev = (struct qedr_dev *)_qdev;
+       struct qedr_dev *dev = (struct qedr_dev *)cxt;
+       struct qed_roce_ll2_packet *pkt = cookie;
        struct qedr_cq *cq = dev->gsi_sqcq;
        struct qedr_qp *qp = dev->gsi_qp;
        unsigned long flags;
@@ -88,20 +93,26 @@ void qedr_ll2_tx_cb(void *_qdev, struct qed_roce_ll2_packet *pkt)
                (*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context);
 }
 
-void qedr_ll2_rx_cb(void *_dev, struct qed_roce_ll2_packet *pkt,
-                   struct qed_roce_ll2_rx_params *params)
+void qedr_ll2_complete_rx_packet(void *cxt,
+                                struct qed_ll2_comp_rx_data *data)
 {
-       struct qedr_dev *dev = (struct qedr_dev *)_dev;
+       struct qedr_dev *dev = (struct qedr_dev *)cxt;
        struct qedr_cq *cq = dev->gsi_rqcq;
        struct qedr_qp *qp = dev->gsi_qp;
        unsigned long flags;
 
        spin_lock_irqsave(&qp->q_lock, flags);
 
-       qp->rqe_wr_id[qp->rq.gsi_cons].rc = params->rc;
-       qp->rqe_wr_id[qp->rq.gsi_cons].vlan_id = params->vlan_id;
-       qp->rqe_wr_id[qp->rq.gsi_cons].sg_list[0].length = pkt->payload[0].len;
-       ether_addr_copy(qp->rqe_wr_id[qp->rq.gsi_cons].smac, params->smac);
+       qp->rqe_wr_id[qp->rq.gsi_cons].rc = data->u.data_length_error ?
+               -EINVAL : 0;
+       qp->rqe_wr_id[qp->rq.gsi_cons].vlan_id = data->vlan;
+       /* note: length stands for data length i.e. GRH is excluded */
+       qp->rqe_wr_id[qp->rq.gsi_cons].sg_list[0].length =
+               data->length.data_length;
+       *((u32 *)&qp->rqe_wr_id[qp->rq.gsi_cons].smac[0]) =
+               ntohl(data->opaque_data_0);
+       *((u16 *)&qp->rqe_wr_id[qp->rq.gsi_cons].smac[4]) =
+               ntohs((u16)data->opaque_data_1);
 
        qedr_inc_sw_gsi_cons(&qp->rq);
 
@@ -111,6 +122,14 @@ void qedr_ll2_rx_cb(void *_dev, struct qed_roce_ll2_packet *pkt,
                (*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context);
 }
 
+void qedr_ll2_release_rx_packet(void *cxt,
+                               u8 connection_handle,
+                               void *cookie,
+                               dma_addr_t rx_buf_addr, bool b_last_packet)
+{
+       /* Do nothing... */
+}
+
 static void qedr_destroy_gsi_cq(struct qedr_dev *dev,
                                struct ib_qp_init_attr *attrs)
 {
@@ -159,27 +178,159 @@ static inline int qedr_check_gsi_qp_attrs(struct qedr_dev *dev,
        return 0;
 }
 
+static int qedr_ll2_post_tx(struct qedr_dev *dev,
+                           struct qed_roce_ll2_packet *pkt)
+{
+       enum qed_ll2_roce_flavor_type roce_flavor;
+       struct qed_ll2_tx_pkt_info ll2_tx_pkt;
+       int rc;
+       int i;
+
+       memset(&ll2_tx_pkt, 0, sizeof(ll2_tx_pkt));
+
+       roce_flavor = (pkt->roce_mode == ROCE_V1) ?
+           QED_LL2_ROCE : QED_LL2_RROCE;
+
+       if (pkt->roce_mode == ROCE_V2_IPV4)
+               ll2_tx_pkt.enable_ip_cksum = 1;
+
+       ll2_tx_pkt.num_of_bds = 1 /* hdr */  + pkt->n_seg;
+       ll2_tx_pkt.vlan = 0;
+       ll2_tx_pkt.tx_dest = pkt->tx_dest;
+       ll2_tx_pkt.qed_roce_flavor = roce_flavor;
+       ll2_tx_pkt.first_frag = pkt->header.baddr;
+       ll2_tx_pkt.first_frag_len = pkt->header.len;
+       ll2_tx_pkt.cookie = pkt;
+
+       /* tx header */
+       rc = dev->ops->ll2_prepare_tx_packet(dev->rdma_ctx,
+                                            dev->gsi_ll2_handle,
+                                            &ll2_tx_pkt, 1);
+       if (rc) {
+               /* TX failed while posting header - release resources */
+               dma_free_coherent(&dev->pdev->dev, pkt->header.len,
+                                 pkt->header.vaddr, pkt->header.baddr);
+               kfree(pkt);
+
+               DP_ERR(dev, "roce ll2 tx: header failed (rc=%d)\n", rc);
+               return rc;
+       }
+
+       /* tx payload */
+       for (i = 0; i < pkt->n_seg; i++) {
+               rc = dev->ops->ll2_set_fragment_of_tx_packet(
+                       dev->rdma_ctx,
+                       dev->gsi_ll2_handle,
+                       pkt->payload[i].baddr,
+                       pkt->payload[i].len);
+
+               if (rc) {
+                       /* if failed not much to do here, partial packet has
+                        * been posted we can't free memory, will need to wait
+                        * for completion
+                        */
+                       DP_ERR(dev, "ll2 tx: payload failed (rc=%d)\n", rc);
+                       return rc;
+               }
+       }
+
+       return 0;
+}
+
+int qedr_ll2_stop(struct qedr_dev *dev)
+{
+       int rc;
+
+       if (dev->gsi_ll2_handle == QED_LL2_UNUSED_HANDLE)
+               return 0;
+
+       /* remove LL2 MAC address filter */
+       rc = dev->ops->ll2_set_mac_filter(dev->cdev,
+                                         dev->gsi_ll2_mac_address, NULL);
+
+       rc = dev->ops->ll2_terminate_connection(dev->rdma_ctx,
+                                               dev->gsi_ll2_handle);
+       if (rc)
+               DP_ERR(dev, "Failed to terminate LL2 connection (rc=%d)\n", rc);
+
+       dev->ops->ll2_release_connection(dev->rdma_ctx, dev->gsi_ll2_handle);
+
+       dev->gsi_ll2_handle = QED_LL2_UNUSED_HANDLE;
+
+       return rc;
+}
+
+int qedr_ll2_start(struct qedr_dev *dev,
+                  struct ib_qp_init_attr *attrs, struct qedr_qp *qp)
+{
+       struct qed_ll2_acquire_data data;
+       struct qed_ll2_cbs cbs;
+       int rc;
+
+       /* configure and start LL2 */
+       cbs.rx_comp_cb = qedr_ll2_complete_rx_packet;
+       cbs.tx_comp_cb = qedr_ll2_complete_tx_packet;
+       cbs.rx_release_cb = qedr_ll2_release_rx_packet;
+       cbs.tx_release_cb = qedr_ll2_complete_tx_packet;
+       cbs.cookie = dev;
+
+       memset(&data, 0, sizeof(data));
+       data.input.conn_type = QED_LL2_TYPE_ROCE;
+       data.input.mtu = dev->ndev->mtu;
+       data.input.rx_num_desc = attrs->cap.max_recv_wr;
+       data.input.rx_drop_ttl0_flg = true;
+       data.input.rx_vlan_removal_en = false;
+       data.input.tx_num_desc = attrs->cap.max_send_wr;
+       data.input.tx_tc = 0;
+       data.input.tx_dest = QED_LL2_TX_DEST_NW;
+       data.input.ai_err_packet_too_big = QED_LL2_DROP_PACKET;
+       data.input.ai_err_no_buf = QED_LL2_DROP_PACKET;
+       data.input.gsi_enable = 1;
+       data.p_connection_handle = &dev->gsi_ll2_handle;
+       data.cbs = &cbs;
+
+       rc = dev->ops->ll2_acquire_connection(dev->rdma_ctx, &data);
+       if (rc) {
+               DP_ERR(dev,
+                      "ll2 start: failed to acquire LL2 connection (rc=%d)\n",
+                      rc);
+               return rc;
+       }
+
+       rc = dev->ops->ll2_establish_connection(dev->rdma_ctx,
+                                               dev->gsi_ll2_handle);
+       if (rc) {
+               DP_ERR(dev,
+                      "ll2 start: failed to establish LL2 connection (rc=%d)\n",
+                      rc);
+               goto err1;
+       }
+
+       rc = dev->ops->ll2_set_mac_filter(dev->cdev, NULL, dev->ndev->dev_addr);
+       if (rc)
+               goto err2;
+
+       return 0;
+
+err2:
+       dev->ops->ll2_terminate_connection(dev->rdma_ctx, dev->gsi_ll2_handle);
+err1:
+       dev->ops->ll2_release_connection(dev->rdma_ctx, dev->gsi_ll2_handle);
+
+       return rc;
+}
+
 struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
                                 struct ib_qp_init_attr *attrs,
                                 struct qedr_qp *qp)
 {
-       struct qed_roce_ll2_params ll2_params;
        int rc;
 
        rc = qedr_check_gsi_qp_attrs(dev, attrs);
        if (rc)
                return ERR_PTR(rc);
 
-       /* configure and start LL2 */
-       memset(&ll2_params, 0, sizeof(ll2_params));
-       ll2_params.max_tx_buffers = attrs->cap.max_send_wr;
-       ll2_params.max_rx_buffers = attrs->cap.max_recv_wr;
-       ll2_params.cbs.tx_cb = qedr_ll2_tx_cb;
-       ll2_params.cbs.rx_cb = qedr_ll2_rx_cb;
-       ll2_params.cb_cookie = (void *)dev;
-       ll2_params.mtu = dev->ndev->mtu;
-       ether_addr_copy(ll2_params.mac_address, dev->ndev->dev_addr);
-       rc = dev->ops->roce_ll2_start(dev->cdev, &ll2_params);
+       rc = qedr_ll2_start(dev, attrs, qp);
        if (rc) {
                DP_ERR(dev, "create gsi qp: failed on ll2 start. rc=%d\n", rc);
                return ERR_PTR(rc);
@@ -214,7 +365,7 @@ struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
 err:
        kfree(qp->rqe_wr_id);
 
-       rc = dev->ops->roce_ll2_stop(dev->cdev);
+       rc = qedr_ll2_stop(dev);
        if (rc)
                DP_ERR(dev, "create gsi qp: failed destroy on create\n");
 
@@ -223,15 +374,7 @@ struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
 
 int qedr_destroy_gsi_qp(struct qedr_dev *dev)
 {
-       int rc;
-
-       rc = dev->ops->roce_ll2_stop(dev->cdev);
-       if (rc)
-               DP_ERR(dev, "destroy gsi qp: failed (rc=%d)\n", rc);
-       else
-               DP_DEBUG(dev, QEDR_MSG_GSI, "destroy gsi qp: success\n");
-
-       return rc;
+       return qedr_ll2_stop(dev);
 }
 
 #define QEDR_MAX_UD_HEADER_SIZE        (100)
@@ -421,7 +564,6 @@ int qedr_gsi_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 {
        struct qed_roce_ll2_packet *pkt = NULL;
        struct qedr_qp *qp = get_qedr_qp(ibqp);
-       struct qed_roce_ll2_tx_params params;
        struct qedr_dev *dev = qp->dev;
        unsigned long flags;
        int rc;
@@ -449,8 +591,6 @@ int qedr_gsi_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                goto err;
        }
 
-       memset(&params, 0, sizeof(params));
-
        spin_lock_irqsave(&qp->q_lock, flags);
 
        rc = qedr_gsi_build_packet(dev, qp, wr, &pkt);
@@ -459,7 +599,8 @@ int qedr_gsi_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                goto err;
        }
 
-       rc = dev->ops->roce_ll2_tx(dev->cdev, pkt, &params);
+       rc = qedr_ll2_post_tx(dev, pkt);
+
        if (!rc) {
                qp->wqe_wr_id[qp->sq.prod].wr_id = wr->wr_id;
                qedr_inc_sw_prod(&qp->sq);
@@ -467,17 +608,6 @@ int qedr_gsi_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                         "gsi post send: opcode=%d, in_irq=%ld, irqs_disabled=%d, wr_id=%llx\n",
                         wr->opcode, in_irq(), irqs_disabled(), wr->wr_id);
        } else {
-               if (rc == QED_ROCE_TX_HEAD_FAILURE) {
-                       /* TX failed while posting header - release resources */
-                       dma_free_coherent(&dev->pdev->dev, pkt->header.len,
-                                         pkt->header.vaddr, pkt->header.baddr);
-                       kfree(pkt);
-               } else if (rc == QED_ROCE_TX_FRAG_FAILURE) {
-                       /* NTD since TX failed while posting a fragment. We will
-                        * release the resources on TX callback
-                        */
-               }
-
                DP_ERR(dev, "gsi post send: failed to transmit (rc=%d)\n", rc);
                rc = -EAGAIN;
                *bad_wr = wr;
@@ -504,10 +634,8 @@ int qedr_gsi_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 {
        struct qedr_dev *dev = get_qedr_dev(ibqp->device);
        struct qedr_qp *qp = get_qedr_qp(ibqp);
-       struct qed_roce_ll2_buffer buf;
        unsigned long flags;
-       int status = 0;
-       int rc;
+       int rc = 0;
 
        if ((qp->state != QED_ROCE_QP_STATE_RTR) &&
            (qp->state != QED_ROCE_QP_STATE_RTS)) {
@@ -518,8 +646,6 @@ int qedr_gsi_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
                return -EINVAL;
        }
 
-       memset(&buf, 0, sizeof(buf));
-
        spin_lock_irqsave(&qp->q_lock, flags);
 
        while (wr) {
@@ -530,10 +656,12 @@ int qedr_gsi_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
                        goto err;
                }
 
-               buf.baddr = wr->sg_list[0].addr;
-               buf.len = wr->sg_list[0].length;
-
-               rc = dev->ops->roce_ll2_post_rx_buffer(dev->cdev, &buf, 0, 1);
+               rc = dev->ops->ll2_post_rx_buffer(dev->rdma_ctx,
+                                                 dev->gsi_ll2_handle,
+                                                 wr->sg_list[0].addr,
+                                                 wr->sg_list[0].length,
+                                                 0 /* cookie */,
+                                                 1 /* notify_fw */);
                if (rc) {
                        DP_ERR(dev,
                               "gsi post recv: failed to post rx buffer (rc=%d)\n",
@@ -553,7 +681,7 @@ int qedr_gsi_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 
        spin_unlock_irqrestore(&qp->q_lock, flags);
 
-       return status;
+       return rc;
 err:
        spin_unlock_irqrestore(&qp->q_lock, flags);
        *bad_wr = wr;
index 6742b0dc082115df347955c77c619e5a47ffb2d6..e240010b93fa0b568517fb696f8053b9f8ae28f8 100644 (file)
@@ -364,8 +364,8 @@ isac_mos_irq(struct isac_hw *isac)
                        WriteISAC(isac, ISAC_MOCR, isac->mocr);
                        if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
                                if (isac->monitor)
-                                       ret = isac->monitor(isac->dch.hw,
-                                                           MONITOR_TX_0, NULL, 0);
+                                       isac->monitor(isac->dch.hw,
+                                                     MONITOR_TX_0, NULL, 0);
                        }
                        kfree(isac->mon_tx);
                        isac->mon_tx = NULL;
@@ -375,8 +375,8 @@ isac_mos_irq(struct isac_hw *isac)
                }
                if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
                        if (isac->monitor)
-                               ret = isac->monitor(isac->dch.hw,
-                                                   MONITOR_TX_0, NULL, 0);
+                               isac->monitor(isac->dch.hw,
+                                             MONITOR_TX_0, NULL, 0);
                        kfree(isac->mon_tx);
                        isac->mon_tx = NULL;
                        isac->mon_txc = 0;
@@ -397,8 +397,8 @@ isac_mos_irq(struct isac_hw *isac)
                        WriteISAC(isac, ISAC_MOCR, isac->mocr);
                        if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
                                if (isac->monitor)
-                                       ret = isac->monitor(isac->dch.hw,
-                                                           MONITOR_TX_1, NULL, 0);
+                                       isac->monitor(isac->dch.hw,
+                                                     MONITOR_TX_1, NULL, 0);
                        }
                        kfree(isac->mon_tx);
                        isac->mon_tx = NULL;
@@ -408,8 +408,8 @@ isac_mos_irq(struct isac_hw *isac)
                }
                if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
                        if (isac->monitor)
-                               ret = isac->monitor(isac->dch.hw,
-                                                   MONITOR_TX_1, NULL, 0);
+                               isac->monitor(isac->dch.hw,
+                                             MONITOR_TX_1, NULL, 0);
                        kfree(isac->mon_tx);
                        isac->mon_tx = NULL;
                        isac->mon_txc = 0;
index b44a6aeb346d0404144dde0304a502268de1da91..165a8009c640100c45d5022575bedb0c88af1a04 100644 (file)
@@ -322,6 +322,11 @@ static u16 __get_link_speed(struct port *port)
 
                default:
                        /* unknown speed value from ethtool. shouldn't happen */
+                       if (slave->speed != SPEED_UNKNOWN)
+                               pr_warn_once("%s: unknown ethtool speed (%d) for port %d (set it to 0)\n",
+                                            slave->bond->dev->name,
+                                            slave->speed,
+                                            port->actor_port_number);
                        speed = 0;
                        break;
                }
index d4484d1a81644826bb30a98681f32e3b81f69485..7d9474352c36164b8ddb2c77a7f60416d8296f6d 100644 (file)
@@ -4175,12 +4175,6 @@ static const struct net_device_ops bond_netdev_ops = {
        .ndo_add_slave          = bond_enslave,
        .ndo_del_slave          = bond_release,
        .ndo_fix_features       = bond_fix_features,
-       .ndo_bridge_setlink     = switchdev_port_bridge_setlink,
-       .ndo_bridge_getlink     = switchdev_port_bridge_getlink,
-       .ndo_bridge_dellink     = switchdev_port_bridge_dellink,
-       .ndo_fdb_add            = switchdev_port_fdb_add,
-       .ndo_fdb_del            = switchdev_port_fdb_del,
-       .ndo_fdb_dump           = switchdev_port_fdb_dump,
        .ndo_features_check     = passthru_features_check,
 };
 
index 44c87027623b696b63566e03e72df4bf047b6fc7..fb950ca290817571d245bdc070dfa91182d2051d 100644 (file)
@@ -489,8 +489,7 @@ static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
        err = 0;
 restore_link:
        if (chip->info->ops->port_set_link(chip, port, link))
-               netdev_err(chip->ds->ports[port].netdev,
-                          "failed to restore MAC's link\n");
+               dev_err(chip->dev, "p%d: failed to restore MAC's link\n", port);
 
        return err;
 }
@@ -514,7 +513,7 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
        mutex_unlock(&chip->reg_lock);
 
        if (err && err != -EOPNOTSUPP)
-               netdev_err(ds->ports[port].netdev, "failed to configure MAC\n");
+               dev_err(ds->dev, "p%d: failed to configure MAC\n", port);
 }
 
 static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
@@ -829,11 +828,11 @@ static int mv88e6xxx_get_eee(struct dsa_switch *ds, int port,
        e->eee_enabled = !!(reg & 0x0200);
        e->tx_lpi_enabled = !!(reg & 0x0100);
 
-       err = mv88e6xxx_port_read(chip, port, PORT_STATUS, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
        if (err)
                goto out;
 
-       e->eee_active = !!(reg & PORT_STATUS_EEE);
+       e->eee_active = !!(reg & MV88E6352_PORT_STS_EEE);
 out:
        mutex_unlock(&chip->reg_lock);
 
@@ -916,32 +915,14 @@ static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
                                         u8 state)
 {
        struct mv88e6xxx_chip *chip = ds->priv;
-       int stp_state;
        int err;
 
-       switch (state) {
-       case BR_STATE_DISABLED:
-               stp_state = PORT_CONTROL_STATE_DISABLED;
-               break;
-       case BR_STATE_BLOCKING:
-       case BR_STATE_LISTENING:
-               stp_state = PORT_CONTROL_STATE_BLOCKING;
-               break;
-       case BR_STATE_LEARNING:
-               stp_state = PORT_CONTROL_STATE_LEARNING;
-               break;
-       case BR_STATE_FORWARDING:
-       default:
-               stp_state = PORT_CONTROL_STATE_FORWARDING;
-               break;
-       }
-
        mutex_lock(&chip->reg_lock);
-       err = mv88e6xxx_port_set_state(chip, port, stp_state);
+       err = mv88e6xxx_port_set_state(chip, port, state);
        mutex_unlock(&chip->reg_lock);
 
        if (err)
-               netdev_err(ds->ports[port].netdev, "failed to update state\n");
+               dev_err(ds->dev, "p%d: failed to update state\n", port);
 }
 
 static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip)
@@ -1009,7 +990,7 @@ static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
        mutex_unlock(&chip->reg_lock);
 
        if (err)
-               netdev_err(ds->ports[port].netdev, "failed to flush ATU\n");
+               dev_err(ds->dev, "p%d: failed to flush ATU\n", port);
 }
 
 static int mv88e6xxx_vtu_setup(struct mv88e6xxx_chip *chip)
@@ -1159,11 +1140,10 @@ static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,
                entry->valid = true;
                entry->vid = vid;
 
-               /* Include only CPU and DSA ports */
+               /* Exclude all ports */
                for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
-                       entry->member[i] = dsa_is_normal_port(chip->ds, i) ?
-                               GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER :
-                               GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED;
+                       entry->member[i] =
+                               GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
 
                return mv88e6xxx_atu_new(chip, &entry->fid);
        }
@@ -1215,10 +1195,9 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
                        if (!ds->ports[i].bridge_dev)
                                continue;
 
-                       netdev_warn(ds->ports[port].netdev,
-                                   "hardware VLAN %d already used by %s\n",
-                                   vlan.vid,
-                                   netdev_name(ds->ports[i].bridge_dev));
+                       dev_err(ds->dev, "p%d: hw VLAN %d already used by %s\n",
+                               port, vlan.vid,
+                               netdev_name(ds->ports[i].bridge_dev));
                        err = -EOPNOTSUPP;
                        goto unlock;
                }
@@ -1234,8 +1213,8 @@ static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
                                         bool vlan_filtering)
 {
        struct mv88e6xxx_chip *chip = ds->priv;
-       u16 mode = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE :
-               PORT_CONTROL_2_8021Q_DISABLED;
+       u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE :
+               MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED;
        int err;
 
        if (!chip->info->max_vid)
@@ -1274,7 +1253,7 @@ mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
 }
 
 static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port,
-                                   u16 vid, bool untagged)
+                                   u16 vid, u8 member)
 {
        struct mv88e6xxx_vtu_entry vlan;
        int err;
@@ -1283,9 +1262,7 @@ static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port,
        if (err)
                return err;
 
-       vlan.member[port] = untagged ?
-               GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED :
-               GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED;
+       vlan.member[port] = member;
 
        return mv88e6xxx_vtu_loadpurge(chip, &vlan);
 }
@@ -1297,22 +1274,29 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
        struct mv88e6xxx_chip *chip = ds->priv;
        bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
        bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
+       u8 member;
        u16 vid;
 
        if (!chip->info->max_vid)
                return;
 
+       if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
+               member = GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED;
+       else if (untagged)
+               member = GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED;
+       else
+               member = GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED;
+
        mutex_lock(&chip->reg_lock);
 
        for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid)
-               if (_mv88e6xxx_port_vlan_add(chip, port, vid, untagged))
-                       netdev_err(ds->ports[port].netdev,
-                                  "failed to add VLAN %d%c\n",
-                                  vid, untagged ? 'u' : 't');
+               if (_mv88e6xxx_port_vlan_add(chip, port, vid, member))
+                       dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port,
+                               vid, untagged ? 'u' : 't');
 
        if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end))
-               netdev_err(ds->ports[port].netdev, "failed to set PVID %d\n",
-                          vlan->vid_end);
+               dev_err(ds->dev, "p%d: failed to set PVID %d\n", port,
+                       vlan->vid_end);
 
        mutex_unlock(&chip->reg_lock);
 }
@@ -1320,7 +1304,6 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
 static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip,
                                    int port, u16 vid)
 {
-       struct dsa_switch *ds = chip->ds;
        struct mv88e6xxx_vtu_entry vlan;
        int i, err;
 
@@ -1337,9 +1320,6 @@ static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip,
        /* keep the VLAN unless all ports are excluded */
        vlan.valid = false;
        for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
-               if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
-                       continue;
-
                if (vlan.member[i] != GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
                        vlan.valid = true;
                        break;
@@ -1450,7 +1430,8 @@ static void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
        mutex_lock(&chip->reg_lock);
        if (mv88e6xxx_port_db_load_purge(chip, port, fdb->addr, fdb->vid,
                                         GLOBAL_ATU_DATA_STATE_UC_STATIC))
-               netdev_err(ds->ports[port].netdev, "failed to load unicast MAC address\n");
+               dev_err(ds->dev, "p%d: failed to load unicast MAC address\n",
+                       port);
        mutex_unlock(&chip->reg_lock);
 }
 
@@ -1695,8 +1676,7 @@ static int mv88e6xxx_disable_ports(struct mv88e6xxx_chip *chip)
 
        /* Set all ports to the Disabled state */
        for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
-               err = mv88e6xxx_port_set_state(chip, i,
-                                              PORT_CONTROL_STATE_DISABLED);
+               err = mv88e6xxx_port_set_state(chip, i, BR_STATE_DISABLED);
                if (err)
                        return err;
        }
@@ -1723,8 +1703,8 @@ static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
 }
 
 static int mv88e6xxx_set_port_mode(struct mv88e6xxx_chip *chip, int port,
-                                  enum mv88e6xxx_frame_mode frame, u16 egress,
-                                  u16 etype)
+                                  enum mv88e6xxx_frame_mode frame,
+                                  enum mv88e6xxx_egress_mode egress, u16 etype)
 {
        int err;
 
@@ -1748,22 +1728,23 @@ static int mv88e6xxx_set_port_mode(struct mv88e6xxx_chip *chip, int port,
 static int mv88e6xxx_set_port_mode_normal(struct mv88e6xxx_chip *chip, int port)
 {
        return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_NORMAL,
-                                      PORT_CONTROL_EGRESS_UNMODIFIED,
-                                      PORT_ETH_TYPE_DEFAULT);
+                                      MV88E6XXX_EGRESS_MODE_UNMODIFIED,
+                                      MV88E6XXX_PORT_ETH_TYPE_DEFAULT);
 }
 
 static int mv88e6xxx_set_port_mode_dsa(struct mv88e6xxx_chip *chip, int port)
 {
        return mv88e6xxx_set_port_mode(chip, port, MV88E6XXX_FRAME_MODE_DSA,
-                                      PORT_CONTROL_EGRESS_UNMODIFIED,
-                                      PORT_ETH_TYPE_DEFAULT);
+                                      MV88E6XXX_EGRESS_MODE_UNMODIFIED,
+                                      MV88E6XXX_PORT_ETH_TYPE_DEFAULT);
 }
 
 static int mv88e6xxx_set_port_mode_edsa(struct mv88e6xxx_chip *chip, int port)
 {
        return mv88e6xxx_set_port_mode(chip, port,
                                       MV88E6XXX_FRAME_MODE_ETHERTYPE,
-                                      PORT_CONTROL_EGRESS_ADD_TAG, ETH_P_EDSA);
+                                      MV88E6XXX_EGRESS_MODE_ETHERTYPE,
+                                      ETH_P_EDSA);
 }
 
 static int mv88e6xxx_setup_port_mode(struct mv88e6xxx_chip *chip, int port)
@@ -1847,10 +1828,10 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
         * If this is the upstream port for this switch, enable
         * forwarding of unknown unicasts and multicasts.
         */
-       reg = PORT_CONTROL_IGMP_MLD_SNOOP |
-               PORT_CONTROL_USE_TAG | PORT_CONTROL_USE_IP |
-               PORT_CONTROL_STATE_FORWARDING;
-       err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+       reg = MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP |
+               MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP |
+               MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
+       err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
        if (err)
                return err;
 
@@ -1891,12 +1872,12 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
        }
 
        err = mv88e6xxx_port_set_8021q_mode(chip, port,
-                                           PORT_CONTROL_2_8021Q_DISABLED);
+                               MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED);
        if (err)
                return err;
 
-       if (chip->info->ops->port_jumbo_config) {
-               err = chip->info->ops->port_jumbo_config(chip, port);
+       if (chip->info->ops->port_set_jumbo_size) {
+               err = chip->info->ops->port_set_jumbo_size(chip, port, 10240);
                if (err)
                        return err;
        }
@@ -1911,17 +1892,19 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
        if (dsa_is_cpu_port(ds, port))
                reg = 0;
 
-       err = mv88e6xxx_port_write(chip, port, PORT_ASSOC_VECTOR, reg);
+       err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR,
+                                  reg);
        if (err)
                return err;
 
        /* Egress rate control 2: disable egress rate control. */
-       err = mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL_2, 0x0000);
+       err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL2,
+                                  0x0000);
        if (err)
                return err;
 
-       if (chip->info->ops->port_pause_config) {
-               err = chip->info->ops->port_pause_config(chip, port);
+       if (chip->info->ops->port_pause_limit) {
+               err = chip->info->ops->port_pause_limit(chip, port, 0, 0);
                if (err)
                        return err;
        }
@@ -1969,7 +1952,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
        /* Default VLAN ID and priority: don't set a default VLAN
         * ID, and set the default packet priority to zero.
         */
-       return mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, 0x0000);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN, 0);
 }
 
 static int mv88e6xxx_port_enable(struct dsa_switch *ds, int port,
@@ -2034,14 +2017,14 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
        u32 upstream_port = dsa_upstream_port(ds);
        int err;
 
-       if (chip->info->ops->g1_set_cpu_port) {
-               err = chip->info->ops->g1_set_cpu_port(chip, upstream_port);
+       if (chip->info->ops->set_cpu_port) {
+               err = chip->info->ops->set_cpu_port(chip, upstream_port);
                if (err)
                        return err;
        }
 
-       if (chip->info->ops->g1_set_egress_port) {
-               err = chip->info->ops->g1_set_egress_port(chip, upstream_port);
+       if (chip->info->ops->set_egress_port) {
+               err = chip->info->ops->set_egress_port(chip, upstream_port);
                if (err)
                        return err;
        }
@@ -2200,7 +2183,7 @@ static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
                 * the mv88e6390 family model number instead.
                 */
                if (!(val & 0x3f0))
-                       val |= PORT_SWITCH_ID_PROD_NUM_6390;
+                       val |= MV88E6XXX_PORT_SWITCH_ID_PROD_6390 >> 4;
        }
 
        return err ? err : val;
@@ -2381,15 +2364,15 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .ppu_enable = mv88e6185_g1_ppu_enable,
@@ -2434,17 +2417,17 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2468,8 +2451,8 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2490,15 +2473,15 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
        .port_set_egress_floods = mv88e6185_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
        .port_set_upstream_port = mv88e6095_port_set_upstream_port,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .ppu_enable = mv88e6185_g1_ppu_enable,
@@ -2523,17 +2506,17 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6390_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
        .stats_get_strings = mv88e6320_stats_get_strings,
        .stats_get_stats = mv88e6390_stats_get_stats,
-       .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+       .set_cpu_port = mv88e6390_g1_set_cpu_port,
+       .set_egress_port = mv88e6390_g1_set_egress_port,
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2553,17 +2536,17 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6320_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2585,8 +2568,8 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2607,17 +2590,17 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6320_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2640,17 +2623,17 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6320_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2672,17 +2655,17 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6320_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2705,17 +2688,17 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6320_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2740,8 +2723,8 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .ppu_enable = mv88e6185_g1_ppu_enable,
@@ -2766,7 +2749,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_pause_config = mv88e6390_port_pause_config,
+       .port_pause_limit = mv88e6390_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6390_g1_stats_snapshot,
@@ -2774,8 +2757,8 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
        .stats_get_strings = mv88e6320_stats_get_strings,
        .stats_get_stats = mv88e6390_stats_get_stats,
-       .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+       .set_cpu_port = mv88e6390_g1_set_cpu_port,
+       .set_egress_port = mv88e6390_g1_set_egress_port,
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2799,7 +2782,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_pause_config = mv88e6390_port_pause_config,
+       .port_pause_limit = mv88e6390_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6390_g1_stats_snapshot,
@@ -2807,8 +2790,8 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
        .stats_get_strings = mv88e6320_stats_get_strings,
        .stats_get_stats = mv88e6390_stats_get_stats,
-       .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+       .set_cpu_port = mv88e6390_g1_set_cpu_port,
+       .set_egress_port = mv88e6390_g1_set_egress_port,
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2832,7 +2815,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_pause_config = mv88e6390_port_pause_config,
+       .port_pause_limit = mv88e6390_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6390_g1_stats_snapshot,
@@ -2840,8 +2823,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
        .stats_get_strings = mv88e6320_stats_get_strings,
        .stats_get_stats = mv88e6390_stats_get_stats,
-       .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+       .set_cpu_port = mv88e6390_g1_set_cpu_port,
+       .set_egress_port = mv88e6390_g1_set_egress_port,
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2865,17 +2848,17 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6320_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2899,7 +2882,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_pause_config = mv88e6390_port_pause_config,
+       .port_pause_limit = mv88e6390_port_pause_limit,
        .port_set_cmode = mv88e6390x_port_set_cmode,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
@@ -2908,8 +2891,8 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
        .stats_get_strings = mv88e6320_stats_get_strings,
        .stats_get_stats = mv88e6390_stats_get_stats,
-       .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+       .set_cpu_port = mv88e6390_g1_set_cpu_port,
+       .set_egress_port = mv88e6390_g1_set_egress_port,
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -2932,17 +2915,17 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6320_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
        .stats_get_strings = mv88e6320_stats_get_strings,
        .stats_get_stats = mv88e6320_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6185_g1_vtu_getnext,
@@ -2963,17 +2946,17 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6320_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
        .stats_get_strings = mv88e6320_stats_get_strings,
        .stats_get_stats = mv88e6320_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6185_g1_vtu_getnext,
        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
@@ -2994,17 +2977,17 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6390_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
        .stats_get_strings = mv88e6320_stats_get_strings,
        .stats_get_stats = mv88e6390_stats_get_stats,
-       .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+       .set_cpu_port = mv88e6390_g1_set_cpu_port,
+       .set_egress_port = mv88e6390_g1_set_egress_port,
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -3025,17 +3008,17 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6320_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -3056,17 +3039,17 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6320_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -3089,17 +3072,17 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6097_port_pause_config,
+       .port_pause_limit = mv88e6097_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6320_g1_stats_snapshot,
        .stats_get_sset_count = mv88e6095_stats_get_sset_count,
        .stats_get_strings = mv88e6095_stats_get_strings,
        .stats_get_stats = mv88e6095_stats_get_stats,
-       .g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6095_g1_set_egress_port,
+       .set_cpu_port = mv88e6095_g1_set_cpu_port,
+       .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -3123,9 +3106,9 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6390_port_pause_config,
+       .port_pause_limit = mv88e6390_port_pause_limit,
        .port_set_cmode = mv88e6390x_port_set_cmode,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
@@ -3134,8 +3117,8 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
        .stats_get_strings = mv88e6320_stats_get_strings,
        .stats_get_stats = mv88e6390_stats_get_stats,
-       .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+       .set_cpu_port = mv88e6390_g1_set_cpu_port,
+       .set_egress_port = mv88e6390_g1_set_egress_port,
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -3159,9 +3142,9 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
        .port_set_frame_mode = mv88e6351_port_set_frame_mode,
        .port_set_egress_floods = mv88e6352_port_set_egress_floods,
        .port_set_ether_type = mv88e6351_port_set_ether_type,
-       .port_jumbo_config = mv88e6165_port_jumbo_config,
+       .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
        .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
-       .port_pause_config = mv88e6390_port_pause_config,
+       .port_pause_limit = mv88e6390_port_pause_limit,
        .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
        .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
        .stats_snapshot = mv88e6390_g1_stats_snapshot,
@@ -3169,8 +3152,8 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
        .stats_get_sset_count = mv88e6320_stats_get_sset_count,
        .stats_get_strings = mv88e6320_stats_get_strings,
        .stats_get_stats = mv88e6390_stats_get_stats,
-       .g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
-       .g1_set_egress_port = mv88e6390_g1_set_egress_port,
+       .set_cpu_port = mv88e6390_g1_set_cpu_port,
+       .set_egress_port = mv88e6390_g1_set_egress_port,
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .reset = mv88e6352_g1_reset,
@@ -3181,7 +3164,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
 
 static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        [MV88E6085] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6085,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6085,
                .family = MV88E6XXX_FAMILY_6097,
                .name = "Marvell 88E6085",
                .num_databases = 4096,
@@ -3199,7 +3182,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6095] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6095,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6095,
                .family = MV88E6XXX_FAMILY_6095,
                .name = "Marvell 88E6095/88E6095F",
                .num_databases = 256,
@@ -3216,7 +3199,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6097] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6097,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6097,
                .family = MV88E6XXX_FAMILY_6097,
                .name = "Marvell 88E6097/88E6097F",
                .num_databases = 4096,
@@ -3234,7 +3217,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6123] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6123,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6123,
                .family = MV88E6XXX_FAMILY_6165,
                .name = "Marvell 88E6123",
                .num_databases = 4096,
@@ -3252,7 +3235,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6131] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6131,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6131,
                .family = MV88E6XXX_FAMILY_6185,
                .name = "Marvell 88E6131",
                .num_databases = 256,
@@ -3269,7 +3252,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6141] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6141,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141,
                .family = MV88E6XXX_FAMILY_6341,
                .name = "Marvell 88E6341",
                .num_databases = 4096,
@@ -3286,7 +3269,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6161] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6161,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6161,
                .family = MV88E6XXX_FAMILY_6165,
                .name = "Marvell 88E6161",
                .num_databases = 4096,
@@ -3304,7 +3287,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6165] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6165,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6165,
                .family = MV88E6XXX_FAMILY_6165,
                .name = "Marvell 88E6165",
                .num_databases = 4096,
@@ -3322,7 +3305,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6171] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6171,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6171,
                .family = MV88E6XXX_FAMILY_6351,
                .name = "Marvell 88E6171",
                .num_databases = 4096,
@@ -3340,7 +3323,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6172] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6172,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6172,
                .family = MV88E6XXX_FAMILY_6352,
                .name = "Marvell 88E6172",
                .num_databases = 4096,
@@ -3358,7 +3341,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6175] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6175,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6175,
                .family = MV88E6XXX_FAMILY_6351,
                .name = "Marvell 88E6175",
                .num_databases = 4096,
@@ -3376,7 +3359,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6176] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6176,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6176,
                .family = MV88E6XXX_FAMILY_6352,
                .name = "Marvell 88E6176",
                .num_databases = 4096,
@@ -3394,7 +3377,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6185] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6185,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6185,
                .family = MV88E6XXX_FAMILY_6185,
                .name = "Marvell 88E6185",
                .num_databases = 256,
@@ -3411,7 +3394,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6190] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6190,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190,
                .family = MV88E6XXX_FAMILY_6390,
                .name = "Marvell 88E6190",
                .num_databases = 4096,
@@ -3429,7 +3412,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6190X] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6190X,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6190X,
                .family = MV88E6XXX_FAMILY_6390,
                .name = "Marvell 88E6190X",
                .num_databases = 4096,
@@ -3447,7 +3430,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6191] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6191,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6191,
                .family = MV88E6XXX_FAMILY_6390,
                .name = "Marvell 88E6191",
                .num_databases = 4096,
@@ -3465,7 +3448,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6240] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6240,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6240,
                .family = MV88E6XXX_FAMILY_6352,
                .name = "Marvell 88E6240",
                .num_databases = 4096,
@@ -3483,7 +3466,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6290] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6290,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290,
                .family = MV88E6XXX_FAMILY_6390,
                .name = "Marvell 88E6290",
                .num_databases = 4096,
@@ -3501,7 +3484,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6320] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6320,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6320,
                .family = MV88E6XXX_FAMILY_6320,
                .name = "Marvell 88E6320",
                .num_databases = 4096,
@@ -3519,7 +3502,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6321] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6321,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6321,
                .family = MV88E6XXX_FAMILY_6320,
                .name = "Marvell 88E6321",
                .num_databases = 4096,
@@ -3536,7 +3519,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6341] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6341,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
                .family = MV88E6XXX_FAMILY_6341,
                .name = "Marvell 88E6341",
                .num_databases = 4096,
@@ -3553,7 +3536,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6350] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6350,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6350,
                .family = MV88E6XXX_FAMILY_6351,
                .name = "Marvell 88E6350",
                .num_databases = 4096,
@@ -3571,7 +3554,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6351] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6351,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6351,
                .family = MV88E6XXX_FAMILY_6351,
                .name = "Marvell 88E6351",
                .num_databases = 4096,
@@ -3589,7 +3572,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
        },
 
        [MV88E6352] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6352,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6352,
                .family = MV88E6XXX_FAMILY_6352,
                .name = "Marvell 88E6352",
                .num_databases = 4096,
@@ -3606,7 +3589,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .ops = &mv88e6352_ops,
        },
        [MV88E6390] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6390,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390,
                .family = MV88E6XXX_FAMILY_6390,
                .name = "Marvell 88E6390",
                .num_databases = 4096,
@@ -3623,7 +3606,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .ops = &mv88e6390_ops,
        },
        [MV88E6390X] = {
-               .prod_num = PORT_SWITCH_ID_PROD_NUM_6390X,
+               .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390X,
                .family = MV88E6XXX_FAMILY_6390,
                .name = "Marvell 88E6390X",
                .num_databases = 4096,
@@ -3660,13 +3643,13 @@ static int mv88e6xxx_detect(struct mv88e6xxx_chip *chip)
        int err;
 
        mutex_lock(&chip->reg_lock);
-       err = mv88e6xxx_port_read(chip, 0, PORT_SWITCH_ID, &id);
+       err = mv88e6xxx_port_read(chip, 0, MV88E6XXX_PORT_SWITCH_ID, &id);
        mutex_unlock(&chip->reg_lock);
        if (err)
                return err;
 
-       prod_num = (id & 0xfff0) >> 4;
-       rev = id & 0x000f;
+       prod_num = id & MV88E6XXX_PORT_SWITCH_ID_PROD_MASK;
+       rev = id & MV88E6XXX_PORT_SWITCH_ID_REV_MASK;
 
        info = mv88e6xxx_lookup_info(prod_num);
        if (!info)
@@ -3792,7 +3775,8 @@ static void mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port,
        mutex_lock(&chip->reg_lock);
        if (mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid,
                                         GLOBAL_ATU_DATA_STATE_MC_STATIC))
-               netdev_err(ds->ports[port].netdev, "failed to load multicast MAC address\n");
+               dev_err(ds->dev, "p%d: failed to load multicast MAC address\n",
+                       port);
        mutex_unlock(&chip->reg_lock);
 }
 
index 98c24af977fd674710bb59a22878781efde3c0c8..d70873498501f5918d9a89186761546bb8d281fe 100644 (file)
 #define MV88E6XXX_MAX_PVT_SWITCHES     32
 #define MV88E6XXX_MAX_PVT_PORTS                16
 
+enum mv88e6xxx_egress_mode {
+       MV88E6XXX_EGRESS_MODE_UNMODIFIED,
+       MV88E6XXX_EGRESS_MODE_UNTAGGED,
+       MV88E6XXX_EGRESS_MODE_TAGGED,
+       MV88E6XXX_EGRESS_MODE_ETHERTYPE,
+};
+
 enum mv88e6xxx_frame_mode {
        MV88E6XXX_FRAME_MODE_NORMAL,
        MV88E6XXX_FRAME_MODE_DSA,
@@ -415,10 +422,12 @@ struct mv88e6xxx_ops {
                                      bool unicast, bool multicast);
        int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port,
                                   u16 etype);
-       int (*port_jumbo_config)(struct mv88e6xxx_chip *chip, int port);
+       int (*port_set_jumbo_size)(struct mv88e6xxx_chip *chip, int port,
+                                  size_t size);
 
        int (*port_egress_rate_limiting)(struct mv88e6xxx_chip *chip, int port);
-       int (*port_pause_config)(struct mv88e6xxx_chip *chip, int port);
+       int (*port_pause_limit)(struct mv88e6xxx_chip *chip, int port, u8 in,
+                               u8 out);
        int (*port_disable_learn_limit)(struct mv88e6xxx_chip *chip, int port);
        int (*port_disable_pri_override)(struct mv88e6xxx_chip *chip, int port);
 
@@ -449,8 +458,8 @@ struct mv88e6xxx_ops {
        void (*stats_get_strings)(struct mv88e6xxx_chip *chip,  uint8_t *data);
        void (*stats_get_stats)(struct mv88e6xxx_chip *chip,  int port,
                                uint64_t *data);
-       int (*g1_set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
-       int (*g1_set_egress_port)(struct mv88e6xxx_chip *chip, int port);
+       int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
+       int (*set_egress_port)(struct mv88e6xxx_chip *chip, int port);
        const struct mv88e6xxx_irq_ops *watchdog_ops;
 
        /* Can be either in g1 or g2, so don't use a prefix */
index 0db624f0993c34149d61d7a3f05072aaa3a0f8cb..3500ac0ea8489e3659dbe4eed36123de735bbd1e 100644 (file)
@@ -62,7 +62,7 @@ int mv88e6xxx_phy_write(struct mv88e6xxx_chip *chip, int phy, int reg, u16 val)
 
 static int mv88e6xxx_phy_page_get(struct mv88e6xxx_chip *chip, int phy, u8 page)
 {
-       return mv88e6xxx_phy_write(chip, phy, PHY_PAGE, page);
+       return mv88e6xxx_phy_write(chip, phy, MV88E6XXX_PHY_PAGE, page);
 }
 
 static void mv88e6xxx_phy_page_put(struct mv88e6xxx_chip *chip, int phy)
@@ -72,7 +72,8 @@ static void mv88e6xxx_phy_page_put(struct mv88e6xxx_chip *chip, int phy)
        /* Restore PHY page Copper 0x0 for access via the registered
         * MDIO bus
         */
-       err = mv88e6xxx_phy_write(chip, phy, PHY_PAGE, PHY_PAGE_COPPER);
+       err = mv88e6xxx_phy_write(chip, phy, MV88E6XXX_PHY_PAGE,
+                                 MV88E6XXX_PHY_PAGE_COPPER);
        if (unlikely(err)) {
                dev_err(chip->dev,
                        "failed to restore PHY %d page Copper (%d)\n",
@@ -86,7 +87,7 @@ int mv88e6xxx_phy_page_read(struct mv88e6xxx_chip *chip, int phy,
        int err;
 
        /* There is no paging for registers 22 */
-       if (reg == PHY_PAGE)
+       if (reg == MV88E6XXX_PHY_PAGE)
                return -EINVAL;
 
        err = mv88e6xxx_phy_page_get(chip, phy, page);
@@ -104,12 +105,12 @@ int mv88e6xxx_phy_page_write(struct mv88e6xxx_chip *chip, int phy,
        int err;
 
        /* There is no paging for registers 22 */
-       if (reg == PHY_PAGE)
+       if (reg == MV88E6XXX_PHY_PAGE)
                return -EINVAL;
 
        err = mv88e6xxx_phy_page_get(chip, phy, page);
        if (!err) {
-               err = mv88e6xxx_phy_write(chip, phy, PHY_PAGE, page);
+               err = mv88e6xxx_phy_write(chip, phy, MV88E6XXX_PHY_PAGE, page);
                mv88e6xxx_phy_page_put(chip, phy);
        }
 
index 4131a4e8206a3437dff57c1710e7d7be0deef7bd..556b74a0502a776538adf091e336bc77e5f49b72 100644 (file)
@@ -14,8 +14,8 @@
 #ifndef _MV88E6XXX_PHY_H
 #define _MV88E6XXX_PHY_H
 
-#define PHY_PAGE               0x16
-#define PHY_PAGE_COPPER                0x00
+#define MV88E6XXX_PHY_PAGE             0x16
+#define MV88E6XXX_PHY_PAGE_COPPER      0x00
 
 /* PHY Registers accesses implementations */
 int mv88e6165_phy_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
index 3719ece60c615a16d5abbbeedf608822a1fe876a..73d825e08be386646eb7471b1bfe70ac2df9dfc0 100644 (file)
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/if_bridge.h>
 #include <linux/phy.h>
 
 #include "chip.h"
@@ -48,23 +49,23 @@ static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
        u16 reg;
        int err;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
        if (err)
                return err;
 
-       reg &= ~(PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
-                PORT_PCS_CTRL_RGMII_DELAY_TXCLK);
+       reg &= ~(MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
+                MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK);
 
        switch (mode) {
        case PHY_INTERFACE_MODE_RGMII_RXID:
-               reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
+               reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK;
                break;
        case PHY_INTERFACE_MODE_RGMII_TXID:
-               reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
+               reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
                break;
        case PHY_INTERFACE_MODE_RGMII_ID:
-               reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
-                       PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
+               reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
+                       MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
                break;
        case PHY_INTERFACE_MODE_RGMII:
                break;
@@ -72,13 +73,13 @@ static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
                return 0;
        }
 
-       err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+       err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
        if (err)
                return err;
 
-       netdev_dbg(chip->ds->ports[port].netdev, "delay RXCLK %s, TXCLK %s\n",
-                  reg & PORT_PCS_CTRL_RGMII_DELAY_RXCLK ? "yes" : "no",
-                  reg & PORT_PCS_CTRL_RGMII_DELAY_TXCLK ? "yes" : "no");
+       dev_dbg(chip->dev, "p%d: delay RXCLK %s, TXCLK %s\n", port,
+               reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK ? "yes" : "no",
+               reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK ? "yes" : "no");
 
        return 0;
 }
@@ -106,18 +107,20 @@ int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
        u16 reg;
        int err;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
        if (err)
                return err;
 
-       reg &= ~(PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP);
+       reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
+                MV88E6XXX_PORT_MAC_CTL_LINK_UP);
 
        switch (link) {
        case LINK_FORCED_DOWN:
-               reg |= PORT_PCS_CTRL_FORCE_LINK;
+               reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK;
                break;
        case LINK_FORCED_UP:
-               reg |= PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP;
+               reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
+                       MV88E6XXX_PORT_MAC_CTL_LINK_UP;
                break;
        case LINK_UNFORCED:
                /* normal link detection */
@@ -126,13 +129,13 @@ int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
                return -EINVAL;
        }
 
-       err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+       err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
        if (err)
                return err;
 
-       netdev_dbg(chip->ds->ports[port].netdev, "%s link %s\n",
-                  reg & PORT_PCS_CTRL_FORCE_LINK ? "Force" : "Unforce",
-                  reg & PORT_PCS_CTRL_LINK_UP ? "up" : "down");
+       dev_dbg(chip->dev, "p%d: %s link %s\n", port,
+               reg & MV88E6XXX_PORT_MAC_CTL_FORCE_LINK ? "Force" : "Unforce",
+               reg & MV88E6XXX_PORT_MAC_CTL_LINK_UP ? "up" : "down");
 
        return 0;
 }
@@ -142,18 +145,20 @@ int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup)
        u16 reg;
        int err;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
        if (err)
                return err;
 
-       reg &= ~(PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL);
+       reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
+                MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL);
 
        switch (dup) {
        case DUPLEX_HALF:
-               reg |= PORT_PCS_CTRL_FORCE_DUPLEX;
+               reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX;
                break;
        case DUPLEX_FULL:
-               reg |= PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL;
+               reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
+                       MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL;
                break;
        case DUPLEX_UNFORCED:
                /* normal duplex detection */
@@ -162,13 +167,13 @@ int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup)
                return -EINVAL;
        }
 
-       err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+       err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
        if (err)
                return err;
 
-       netdev_dbg(chip->ds->ports[port].netdev, "%s %s duplex\n",
-                  reg & PORT_PCS_CTRL_FORCE_DUPLEX ? "Force" : "Unforce",
-                  reg & PORT_PCS_CTRL_DUPLEX_FULL ? "full" : "half");
+       dev_dbg(chip->dev, "p%d: %s %s duplex\n", port,
+               reg & MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX ? "Force" : "Unforce",
+               reg & MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL ? "full" : "half");
 
        return 0;
 }
@@ -181,55 +186,56 @@ static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
 
        switch (speed) {
        case 10:
-               ctrl = PORT_PCS_CTRL_SPEED_10;
+               ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_10;
                break;
        case 100:
-               ctrl = PORT_PCS_CTRL_SPEED_100;
+               ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100;
                break;
        case 200:
                if (alt_bit)
-                       ctrl = PORT_PCS_CTRL_SPEED_100 | PORT_PCS_CTRL_ALTSPEED;
+                       ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100 |
+                               MV88E6390_PORT_MAC_CTL_ALTSPEED;
                else
-                       ctrl = PORT_PCS_CTRL_SPEED_200;
+                       ctrl = MV88E6065_PORT_MAC_CTL_SPEED_200;
                break;
        case 1000:
-               ctrl = PORT_PCS_CTRL_SPEED_1000;
+               ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_1000;
                break;
        case 2500:
-               ctrl = PORT_PCS_CTRL_SPEED_10000 | PORT_PCS_CTRL_ALTSPEED;
+               ctrl = MV88E6390_PORT_MAC_CTL_SPEED_10000 |
+                       MV88E6390_PORT_MAC_CTL_ALTSPEED;
                break;
        case 10000:
                /* all bits set, fall through... */
        case SPEED_UNFORCED:
-               ctrl = PORT_PCS_CTRL_SPEED_UNFORCED;
+               ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_UNFORCED;
                break;
        default:
                return -EOPNOTSUPP;
        }
 
-       err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
        if (err)
                return err;
 
-       reg &= ~PORT_PCS_CTRL_SPEED_MASK;
+       reg &= ~MV88E6XXX_PORT_MAC_CTL_SPEED_MASK;
        if (alt_bit)
-               reg &= ~PORT_PCS_CTRL_ALTSPEED;
+               reg &= ~MV88E6390_PORT_MAC_CTL_ALTSPEED;
        if (force_bit) {
-               reg &= ~PORT_PCS_CTRL_FORCE_SPEED;
+               reg &= ~MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
                if (speed != SPEED_UNFORCED)
-                       ctrl |= PORT_PCS_CTRL_FORCE_SPEED;
+                       ctrl |= MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
        }
        reg |= ctrl;
 
-       err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+       err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
        if (err)
                return err;
 
        if (speed)
-               netdev_dbg(chip->ds->ports[port].netdev,
-                          "Speed set to %d Mbps\n", speed);
+               dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed);
        else
-               netdev_dbg(chip->ds->ports[port].netdev, "Speed unforced\n");
+               dev_dbg(chip->dev, "p%d: Speed unforced\n", port);
 
        return 0;
 }
@@ -322,33 +328,33 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
 
        switch (mode) {
        case PHY_INTERFACE_MODE_1000BASEX:
-               cmode = PORT_STATUS_CMODE_1000BASE_X;
+               cmode = MV88E6XXX_PORT_STS_CMODE_1000BASE_X;
                break;
        case PHY_INTERFACE_MODE_SGMII:
-               cmode = PORT_STATUS_CMODE_SGMII;
+               cmode = MV88E6XXX_PORT_STS_CMODE_SGMII;
                break;
        case PHY_INTERFACE_MODE_2500BASEX:
-               cmode = PORT_STATUS_CMODE_2500BASEX;
+               cmode = MV88E6XXX_PORT_STS_CMODE_2500BASEX;
                break;
        case PHY_INTERFACE_MODE_XGMII:
-               cmode = PORT_STATUS_CMODE_XAUI;
+               cmode = MV88E6XXX_PORT_STS_CMODE_XAUI;
                break;
        case PHY_INTERFACE_MODE_RXAUI:
-               cmode = PORT_STATUS_CMODE_RXAUI;
+               cmode = MV88E6XXX_PORT_STS_CMODE_RXAUI;
                break;
        default:
                cmode = 0;
        }
 
        if (cmode) {
-               err = mv88e6xxx_port_read(chip, port, PORT_STATUS, &reg);
+               err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
                if (err)
                        return err;
 
-               reg &= ~PORT_STATUS_CMODE_MASK;
+               reg &= ~MV88E6XXX_PORT_STS_CMODE_MASK;
                reg |= cmode;
 
-               err = mv88e6xxx_port_write(chip, port, PORT_STATUS, reg);
+               err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);
                if (err)
                        return err;
        }
@@ -361,46 +367,51 @@ int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
        int err;
        u16 reg;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_STATUS, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
        if (err)
                return err;
 
-       *cmode = reg & PORT_STATUS_CMODE_MASK;
+       *cmode = reg & MV88E6XXX_PORT_STS_CMODE_MASK;
 
        return 0;
 }
 
-/* Offset 0x02: Pause Control
+/* Offset 0x02: Jamming Control
  *
  * Do not limit the period of time that this port can be paused for by
  * the remote end or the period of time that this port can pause the
  * remote end.
  */
-int mv88e6097_port_pause_config(struct mv88e6xxx_chip *chip, int port)
+int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
+                              u8 out)
 {
-       return mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL, 0x0000);
+       return mv88e6xxx_port_write(chip, port, MV88E6097_PORT_JAM_CTL,
+                                   out << 8 | in);
 }
 
-int mv88e6390_port_pause_config(struct mv88e6xxx_chip *chip, int port)
+int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
+                              u8 out)
 {
        int err;
 
-       err = mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL,
-                                  PORT_FLOW_CTRL_LIMIT_IN | 0);
+       err = mv88e6xxx_port_write(chip, port, MV88E6390_PORT_FLOW_CTL,
+                                  MV88E6390_PORT_FLOW_CTL_UPDATE |
+                                  MV88E6390_PORT_FLOW_CTL_LIMIT_IN | in);
        if (err)
                return err;
 
-       return mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL,
-                                   PORT_FLOW_CTRL_LIMIT_OUT | 0);
+       return mv88e6xxx_port_write(chip, port, MV88E6390_PORT_FLOW_CTL,
+                                   MV88E6390_PORT_FLOW_CTL_UPDATE |
+                                   MV88E6390_PORT_FLOW_CTL_LIMIT_OUT | out);
 }
 
 /* Offset 0x04: Port Control Register */
 
 static const char * const mv88e6xxx_port_state_names[] = {
-       [PORT_CONTROL_STATE_DISABLED] = "Disabled",
-       [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening",
-       [PORT_CONTROL_STATE_LEARNING] = "Learning",
-       [PORT_CONTROL_STATE_FORWARDING] = "Forwarding",
+       [MV88E6XXX_PORT_CTL0_STATE_DISABLED] = "Disabled",
+       [MV88E6XXX_PORT_CTL0_STATE_BLOCKING] = "Blocking/Listening",
+       [MV88E6XXX_PORT_CTL0_STATE_LEARNING] = "Learning",
+       [MV88E6XXX_PORT_CTL0_STATE_FORWARDING] = "Forwarding",
 };
 
 int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state)
@@ -408,37 +419,72 @@ int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state)
        u16 reg;
        int err;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
        if (err)
                return err;
 
-       reg &= ~PORT_CONTROL_STATE_MASK;
+       reg &= ~MV88E6XXX_PORT_CTL0_STATE_MASK;
+
+       switch (state) {
+       case BR_STATE_DISABLED:
+               state = MV88E6XXX_PORT_CTL0_STATE_DISABLED;
+               break;
+       case BR_STATE_BLOCKING:
+       case BR_STATE_LISTENING:
+               state = MV88E6XXX_PORT_CTL0_STATE_BLOCKING;
+               break;
+       case BR_STATE_LEARNING:
+               state = MV88E6XXX_PORT_CTL0_STATE_LEARNING;
+               break;
+       case BR_STATE_FORWARDING:
+               state = MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
+               break;
+       default:
+               return -EINVAL;
+       }
+
        reg |= state;
 
-       err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+       err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
        if (err)
                return err;
 
-       netdev_dbg(chip->ds->ports[port].netdev, "PortState set to %s\n",
-                  mv88e6xxx_port_state_names[state]);
+       dev_dbg(chip->dev, "p%d: PortState set to %s\n", port,
+               mv88e6xxx_port_state_names[state]);
 
        return 0;
 }
 
 int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
-                                  u16 mode)
+                                  enum mv88e6xxx_egress_mode mode)
 {
        int err;
        u16 reg;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
        if (err)
                return err;
 
-       reg &= ~PORT_CONTROL_EGRESS_MASK;
-       reg |= mode;
+       reg &= ~MV88E6XXX_PORT_CTL0_EGRESS_MODE_MASK;
+
+       switch (mode) {
+       case MV88E6XXX_EGRESS_MODE_UNMODIFIED:
+               reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNMODIFIED;
+               break;
+       case MV88E6XXX_EGRESS_MODE_UNTAGGED:
+               reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNTAGGED;
+               break;
+       case MV88E6XXX_EGRESS_MODE_TAGGED:
+               reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_TAGGED;
+               break;
+       case MV88E6XXX_EGRESS_MODE_ETHERTYPE:
+               reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_ETHER_TYPE_DSA;
+               break;
+       default:
+               return -EINVAL;
+       }
 
-       return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
 }
 
 int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
@@ -447,24 +493,24 @@ int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
        int err;
        u16 reg;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
        if (err)
                return err;
 
-       reg &= ~PORT_CONTROL_FRAME_MASK;
+       reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
 
        switch (mode) {
        case MV88E6XXX_FRAME_MODE_NORMAL:
-               reg |= PORT_CONTROL_FRAME_MODE_NORMAL;
+               reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
                break;
        case MV88E6XXX_FRAME_MODE_DSA:
-               reg |= PORT_CONTROL_FRAME_MODE_DSA;
+               reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
                break;
        default:
                return -EINVAL;
        }
 
-       return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
 }
 
 int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
@@ -473,30 +519,30 @@ int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
        int err;
        u16 reg;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
        if (err)
                return err;
 
-       reg &= ~PORT_CONTROL_FRAME_MASK;
+       reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
 
        switch (mode) {
        case MV88E6XXX_FRAME_MODE_NORMAL:
-               reg |= PORT_CONTROL_FRAME_MODE_NORMAL;
+               reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
                break;
        case MV88E6XXX_FRAME_MODE_DSA:
-               reg |= PORT_CONTROL_FRAME_MODE_DSA;
+               reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
                break;
        case MV88E6XXX_FRAME_MODE_PROVIDER:
-               reg |= PORT_CONTROL_FRAME_MODE_PROVIDER;
+               reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_PROVIDER;
                break;
        case MV88E6XXX_FRAME_MODE_ETHERTYPE:
-               reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA;
+               reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_ETHER_TYPE_DSA;
                break;
        default:
                return -EINVAL;
        }
 
-       return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
 }
 
 static int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip,
@@ -505,16 +551,16 @@ static int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip,
        int err;
        u16 reg;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
        if (err)
                return err;
 
        if (unicast)
-               reg |= PORT_CONTROL_FORWARD_UNKNOWN;
+               reg |= MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
        else
-               reg &= ~PORT_CONTROL_FORWARD_UNKNOWN;
+               reg &= ~MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
 
-       return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
 }
 
 int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
@@ -523,22 +569,22 @@ int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
        int err;
        u16 reg;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
        if (err)
                return err;
 
-       reg &= ~PORT_CONTROL_EGRESS_FLOODS_MASK;
+       reg &= ~MV88E6352_PORT_CTL0_EGRESS_FLOODS_MASK;
 
        if (unicast && multicast)
-               reg |= PORT_CONTROL_EGRESS_FLOODS_ALL_UNKNOWN_DA;
+               reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_ALL_UNKNOWN_DA;
        else if (unicast)
-               reg |= PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_MC_DA;
+               reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_MC_DA;
        else if (multicast)
-               reg |= PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_UC_DA;
+               reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_UC_DA;
        else
-               reg |= PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_DA;
+               reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_DA;
 
-       return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
 }
 
 /* Offset 0x05: Port Control 1 */
@@ -549,16 +595,16 @@ int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
        u16 val;
        int err;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &val);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1, &val);
        if (err)
                return err;
 
        if (message_port)
-               val |= PORT_CONTROL_1_MESSAGE_PORT;
+               val |= MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
        else
-               val &= ~PORT_CONTROL_1_MESSAGE_PORT;
+               val &= ~MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
 
-       return mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, val);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1, val);
 }
 
 /* Offset 0x06: Port Based VLAN Map */
@@ -569,19 +615,18 @@ int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
        u16 reg;
        int err;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
        if (err)
                return err;
 
        reg &= ~mask;
        reg |= map & mask;
 
-       err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
+       err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
        if (err)
                return err;
 
-       netdev_dbg(chip->ds->ports[port].netdev, "VLANTable set to %.3x\n",
-                  map);
+       dev_dbg(chip->dev, "p%d: VLANTable set to %.3x\n", port, map);
 
        return 0;
 }
@@ -593,7 +638,7 @@ int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid)
        int err;
 
        /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
-       err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
        if (err)
                return err;
 
@@ -601,7 +646,8 @@ int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid)
 
        /* Port's default FID upper bits are located in reg 0x05, offset 0 */
        if (upper_mask) {
-               err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &reg);
+               err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
+                                         &reg);
                if (err)
                        return err;
 
@@ -621,32 +667,34 @@ int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid)
                return -EINVAL;
 
        /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
-       err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
        if (err)
                return err;
 
        reg &= 0x0fff;
        reg |= (fid & 0x000f) << 12;
 
-       err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
+       err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
        if (err)
                return err;
 
        /* Port's default FID upper bits are located in reg 0x05, offset 0 */
        if (upper_mask) {
-               err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &reg);
+               err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
+                                         &reg);
                if (err)
                        return err;
 
                reg &= ~upper_mask;
                reg |= (fid >> 4) & upper_mask;
 
-               err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, reg);
+               err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1,
+                                          reg);
                if (err)
                        return err;
        }
 
-       netdev_dbg(chip->ds->ports[port].netdev, "FID set to %u\n", fid);
+       dev_dbg(chip->dev, "p%d: FID set to %u\n", port, fid);
 
        return 0;
 }
@@ -658,11 +706,12 @@ int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid)
        u16 reg;
        int err;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
+                                 &reg);
        if (err)
                return err;
 
-       *pvid = reg & PORT_DEFAULT_VLAN_MASK;
+       *pvid = reg & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
 
        return 0;
 }
@@ -672,19 +721,20 @@ int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid)
        u16 reg;
        int err;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
+                                 &reg);
        if (err)
                return err;
 
-       reg &= ~PORT_DEFAULT_VLAN_MASK;
-       reg |= pvid & PORT_DEFAULT_VLAN_MASK;
+       reg &= ~MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
+       reg |= pvid & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
 
-       err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg);
+       err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
+                                  reg);
        if (err)
                return err;
 
-       netdev_dbg(chip->ds->ports[port].netdev, "DefaultVID set to %u\n",
-                  pvid);
+       dev_dbg(chip->dev, "p%d: DefaultVID set to %u\n", port, pvid);
 
        return 0;
 }
@@ -692,10 +742,10 @@ int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid)
 /* Offset 0x08: Port Control 2 Register */
 
 static const char * const mv88e6xxx_port_8021q_mode_names[] = {
-       [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled",
-       [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback",
-       [PORT_CONTROL_2_8021Q_CHECK] = "Check",
-       [PORT_CONTROL_2_8021Q_SECURE] = "Secure",
+       [MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED] = "Disabled",
+       [MV88E6XXX_PORT_CTL2_8021Q_MODE_FALLBACK] = "Fallback",
+       [MV88E6XXX_PORT_CTL2_8021Q_MODE_CHECK] = "Check",
+       [MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE] = "Secure",
 };
 
 static int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip,
@@ -704,16 +754,16 @@ static int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip,
        int err;
        u16 reg;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
        if (err)
                return err;
 
        if (multicast)
-               reg |= PORT_CONTROL_2_DEFAULT_FORWARD;
+               reg |= MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
        else
-               reg &= ~PORT_CONTROL_2_DEFAULT_FORWARD;
+               reg &= ~MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
 
-       return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
 }
 
 int mv88e6185_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
@@ -734,14 +784,14 @@ int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
        int err;
        u16 reg;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
        if (err)
                return err;
 
-       reg &= ~PORT_CONTROL_2_UPSTREAM_MASK;
+       reg &= ~MV88E6095_PORT_CTL2_CPU_PORT_MASK;
        reg |= upstream_port;
 
-       return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
 }
 
 int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
@@ -750,19 +800,19 @@ int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
        u16 reg;
        int err;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
        if (err)
                return err;
 
-       reg &= ~PORT_CONTROL_2_8021Q_MASK;
-       reg |= mode & PORT_CONTROL_2_8021Q_MASK;
+       reg &= ~MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
+       reg |= mode & MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
 
-       err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
+       err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
        if (err)
                return err;
 
-       netdev_dbg(chip->ds->ports[port].netdev, "802.1QMode set to %s\n",
-                  mv88e6xxx_port_8021q_mode_names[mode]);
+       dev_dbg(chip->dev, "p%d: 802.1QMode set to %s\n", port,
+               mv88e6xxx_port_8021q_mode_names[mode]);
 
        return 0;
 }
@@ -772,53 +822,65 @@ int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port)
        u16 reg;
        int err;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
        if (err)
                return err;
 
-       reg |= PORT_CONTROL_2_MAP_DA;
+       reg |= MV88E6XXX_PORT_CTL2_MAP_DA;
 
-       return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
 }
 
-int mv88e6165_port_jumbo_config(struct mv88e6xxx_chip *chip, int port)
+int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
+                                 size_t size)
 {
        u16 reg;
        int err;
 
-       err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
        if (err)
                return err;
 
-       reg |= PORT_CONTROL_2_JUMBO_10240;
+       reg &= ~MV88E6XXX_PORT_CTL2_JUMBO_MODE_MASK;
+
+       if (size <= 1522)
+               reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_1522;
+       else if (size <= 2048)
+               reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_2048;
+       else if (size <= 10240)
+               reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_10240;
+       else
+               return -ERANGE;
 
-       return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
 }
 
 /* Offset 0x09: Port Rate Control */
 
 int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
 {
-       return mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL, 0x0000);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
+                                   0x0000);
 }
 
 int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
 {
-       return mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL, 0x0001);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
+                                   0x0001);
 }
 
 /* Offset 0x0C: Port ATU Control */
 
 int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port)
 {
-       return mv88e6xxx_port_write(chip, port, PORT_ATU_CONTROL, 0);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ATU_CTL, 0);
 }
 
 /* Offset 0x0D: (Priority) Override Register */
 
 int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port)
 {
-       return mv88e6xxx_port_write(chip, port, PORT_PRI_OVERRIDE, 0);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_PRI_OVERRIDE, 0);
 }
 
 /* Offset 0x0f: Port Ether type */
@@ -826,7 +888,7 @@ int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port)
 int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
                                  u16 etype)
 {
-       return mv88e6xxx_port_write(chip, port, PORT_ETH_TYPE, etype);
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ETH_TYPE, etype);
 }
 
 /* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
@@ -838,11 +900,15 @@ int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
        int err;
 
        /* Use a direct priority mapping for all IEEE tagged frames */
-       err = mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_0123, 0x3210);
+       err = mv88e6xxx_port_write(chip, port,
+                                  MV88E6095_PORT_IEEE_PRIO_REMAP_0123,
+                                  0x3210);
        if (err)
                return err;
 
-       return mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_4567, 0x7654);
+       return mv88e6xxx_port_write(chip, port,
+                                   MV88E6095_PORT_IEEE_PRIO_REMAP_4567,
+                                   0x7654);
 }
 
 static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
@@ -851,40 +917,39 @@ static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
 {
        u16 reg;
 
-       reg = PORT_IEEE_PRIO_MAP_TABLE_UPDATE |
+       reg = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE |
                table |
-               (pointer << PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT) |
+               (pointer << MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT) |
                data;
 
-       return mv88e6xxx_port_write(chip, port, PORT_IEEE_PRIO_MAP_TABLE, reg);
+       return mv88e6xxx_port_write(chip, port,
+                                   MV88E6390_PORT_IEEE_PRIO_MAP_TABLE, reg);
 }
 
 int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
 {
        int err, i;
+       u16 table;
 
        for (i = 0; i <= 7; i++) {
-               err = mv88e6xxx_port_ieeepmt_write(
-                       chip, port, PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP,
-                       i, (i | i << 4));
+               table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP;
+               err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i,
+                                                  (i | i << 4));
                if (err)
                        return err;
 
-               err = mv88e6xxx_port_ieeepmt_write(
-                       chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP,
-                       i, i);
+               table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP;
+               err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
                if (err)
                        return err;
 
-               err = mv88e6xxx_port_ieeepmt_write(
-                       chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP,
-                       i, i);
+               table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP;
+               err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
                if (err)
                        return err;
 
-               err = mv88e6xxx_port_ieeepmt_write(
-                       chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP,
-                       i, i);
+               table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP;
+               err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
                if (err)
                        return err;
        }
index 4f5e1ccfadc65da8dadab9c3ee7d9cce803cbcf8..8a34ea7c868a97a20d14205abfbc6520cd65e8ee 100644 (file)
 
 #include "chip.h"
 
-#define PORT_STATUS            0x00
-#define PORT_STATUS_PAUSE_EN   BIT(15)
-#define PORT_STATUS_MY_PAUSE   BIT(14)
-#define PORT_STATUS_HD_FLOW    BIT(13)
-#define PORT_STATUS_PHY_DETECT BIT(12)
-#define PORT_STATUS_LINK       BIT(11)
-#define PORT_STATUS_DUPLEX     BIT(10)
-#define PORT_STATUS_SPEED_MASK 0x0300
-#define PORT_STATUS_SPEED_10   0x0000
-#define PORT_STATUS_SPEED_100  0x0100
-#define PORT_STATUS_SPEED_1000 0x0200
-#define PORT_STATUS_EEE                BIT(6) /* 6352 */
-#define PORT_STATUS_AM_DIS     BIT(6) /* 6165 */
-#define PORT_STATUS_MGMII      BIT(6) /* 6185 */
-#define PORT_STATUS_TX_PAUSED  BIT(5)
-#define PORT_STATUS_FLOW_CTRL  BIT(4)
-#define PORT_STATUS_CMODE_MASK 0x0f
-#define PORT_STATUS_CMODE_100BASE_X    0x8
-#define PORT_STATUS_CMODE_1000BASE_X   0x9
-#define PORT_STATUS_CMODE_SGMII                0xa
-#define PORT_STATUS_CMODE_2500BASEX    0xb
-#define PORT_STATUS_CMODE_XAUI         0xc
-#define PORT_STATUS_CMODE_RXAUI                0xd
-#define PORT_PCS_CTRL          0x01
-#define PORT_PCS_CTRL_RGMII_DELAY_RXCLK        BIT(15)
-#define PORT_PCS_CTRL_RGMII_DELAY_TXCLK        BIT(14)
-#define PORT_PCS_CTRL_FORCE_SPEED      BIT(13) /* 6390 */
-#define PORT_PCS_CTRL_ALTSPEED         BIT(12) /* 6390 */
-#define PORT_PCS_CTRL_200BASE          BIT(12) /* 6352 */
-#define PORT_PCS_CTRL_FC               BIT(7)
-#define PORT_PCS_CTRL_FORCE_FC         BIT(6)
-#define PORT_PCS_CTRL_LINK_UP          BIT(5)
-#define PORT_PCS_CTRL_FORCE_LINK       BIT(4)
-#define PORT_PCS_CTRL_DUPLEX_FULL      BIT(3)
-#define PORT_PCS_CTRL_FORCE_DUPLEX     BIT(2)
-#define PORT_PCS_CTRL_SPEED_MASK       (0x03)
-#define PORT_PCS_CTRL_SPEED_10         (0x00)
-#define PORT_PCS_CTRL_SPEED_100                (0x01)
-#define PORT_PCS_CTRL_SPEED_200                (0x02) /* 6065 and non Gb chips */
-#define PORT_PCS_CTRL_SPEED_1000       (0x02)
-#define PORT_PCS_CTRL_SPEED_10000      (0x03) /* 6390X */
-#define PORT_PCS_CTRL_SPEED_UNFORCED   (0x03)
-#define PORT_PAUSE_CTRL                0x02
-#define PORT_FLOW_CTRL_LIMIT_IN                ((0x00 << 8) | BIT(15))
-#define PORT_FLOW_CTRL_LIMIT_OUT       ((0x01 << 8) | BIT(15))
-#define PORT_SWITCH_ID         0x03
-#define PORT_SWITCH_ID_PROD_NUM_6085   0x04a
-#define PORT_SWITCH_ID_PROD_NUM_6095   0x095
-#define PORT_SWITCH_ID_PROD_NUM_6097   0x099
-#define PORT_SWITCH_ID_PROD_NUM_6131   0x106
-#define PORT_SWITCH_ID_PROD_NUM_6320   0x115
-#define PORT_SWITCH_ID_PROD_NUM_6123   0x121
-#define PORT_SWITCH_ID_PROD_NUM_6141   0x340
-#define PORT_SWITCH_ID_PROD_NUM_6161   0x161
-#define PORT_SWITCH_ID_PROD_NUM_6165   0x165
-#define PORT_SWITCH_ID_PROD_NUM_6171   0x171
-#define PORT_SWITCH_ID_PROD_NUM_6172   0x172
-#define PORT_SWITCH_ID_PROD_NUM_6175   0x175
-#define PORT_SWITCH_ID_PROD_NUM_6176   0x176
-#define PORT_SWITCH_ID_PROD_NUM_6185   0x1a7
-#define PORT_SWITCH_ID_PROD_NUM_6190   0x190
-#define PORT_SWITCH_ID_PROD_NUM_6190X  0x0a0
-#define PORT_SWITCH_ID_PROD_NUM_6191   0x191
-#define PORT_SWITCH_ID_PROD_NUM_6240   0x240
-#define PORT_SWITCH_ID_PROD_NUM_6290   0x290
-#define PORT_SWITCH_ID_PROD_NUM_6321   0x310
-#define PORT_SWITCH_ID_PROD_NUM_6341   0x341
-#define PORT_SWITCH_ID_PROD_NUM_6352   0x352
-#define PORT_SWITCH_ID_PROD_NUM_6350   0x371
-#define PORT_SWITCH_ID_PROD_NUM_6351   0x375
-#define PORT_SWITCH_ID_PROD_NUM_6390   0x390
-#define PORT_SWITCH_ID_PROD_NUM_6390X  0x0a1
-#define PORT_CONTROL           0x04
-#define PORT_CONTROL_USE_CORE_TAG      BIT(15)
-#define PORT_CONTROL_DROP_ON_LOCK      BIT(14)
-#define PORT_CONTROL_EGRESS_UNMODIFIED (0x0 << 12)
-#define PORT_CONTROL_EGRESS_UNTAGGED   (0x1 << 12)
-#define PORT_CONTROL_EGRESS_TAGGED     (0x2 << 12)
-#define PORT_CONTROL_EGRESS_ADD_TAG    (0x3 << 12)
-#define PORT_CONTROL_EGRESS_MASK       (0x3 << 12)
-#define PORT_CONTROL_HEADER            BIT(11)
-#define PORT_CONTROL_IGMP_MLD_SNOOP    BIT(10)
-#define PORT_CONTROL_DOUBLE_TAG                BIT(9)
-#define PORT_CONTROL_FRAME_MODE_NORMAL         (0x0 << 8)
-#define PORT_CONTROL_FRAME_MODE_DSA            (0x1 << 8)
-#define PORT_CONTROL_FRAME_MODE_PROVIDER       (0x2 << 8)
-#define PORT_CONTROL_FRAME_ETHER_TYPE_DSA      (0x3 << 8)
-#define PORT_CONTROL_FRAME_MASK                        (0x3 << 8)
-#define PORT_CONTROL_DSA_TAG           BIT(8)
-#define PORT_CONTROL_VLAN_TUNNEL       BIT(7)
-#define PORT_CONTROL_TAG_IF_BOTH       BIT(6)
-#define PORT_CONTROL_USE_IP            BIT(5)
-#define PORT_CONTROL_USE_TAG           BIT(4)
-#define PORT_CONTROL_FORWARD_UNKNOWN   BIT(2)
-#define PORT_CONTROL_EGRESS_FLOODS_MASK                        (0x3 << 2)
-#define PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_DA       (0x0 << 2)
-#define PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_MC_DA    (0x1 << 2)
-#define PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_UC_DA    (0x2 << 2)
-#define PORT_CONTROL_EGRESS_FLOODS_ALL_UNKNOWN_DA      (0x3 << 2)
-#define PORT_CONTROL_STATE_MASK                0x03
-#define PORT_CONTROL_STATE_DISABLED    0x00
-#define PORT_CONTROL_STATE_BLOCKING    0x01
-#define PORT_CONTROL_STATE_LEARNING    0x02
-#define PORT_CONTROL_STATE_FORWARDING  0x03
-#define PORT_CONTROL_1         0x05
-#define PORT_CONTROL_1_MESSAGE_PORT    BIT(15)
-#define PORT_CONTROL_1_FID_11_4_MASK   (0xff << 0)
-#define PORT_BASE_VLAN         0x06
-#define PORT_BASE_VLAN_FID_3_0_MASK    (0xf << 12)
-#define PORT_DEFAULT_VLAN      0x07
-#define PORT_DEFAULT_VLAN_MASK 0xfff
-#define PORT_CONTROL_2         0x08
-#define PORT_CONTROL_2_IGNORE_FCS      BIT(15)
-#define PORT_CONTROL_2_VTU_PRI_OVERRIDE        BIT(14)
-#define PORT_CONTROL_2_SA_PRIO_OVERRIDE        BIT(13)
-#define PORT_CONTROL_2_DA_PRIO_OVERRIDE        BIT(12)
-#define PORT_CONTROL_2_JUMBO_1522      (0x00 << 12)
-#define PORT_CONTROL_2_JUMBO_2048      (0x01 << 12)
-#define PORT_CONTROL_2_JUMBO_10240     (0x02 << 12)
-#define PORT_CONTROL_2_8021Q_MASK      (0x03 << 10)
-#define PORT_CONTROL_2_8021Q_DISABLED  (0x00 << 10)
-#define PORT_CONTROL_2_8021Q_FALLBACK  (0x01 << 10)
-#define PORT_CONTROL_2_8021Q_CHECK     (0x02 << 10)
-#define PORT_CONTROL_2_8021Q_SECURE    (0x03 << 10)
-#define PORT_CONTROL_2_DISCARD_TAGGED  BIT(9)
-#define PORT_CONTROL_2_DISCARD_UNTAGGED        BIT(8)
-#define PORT_CONTROL_2_MAP_DA          BIT(7)
-#define PORT_CONTROL_2_DEFAULT_FORWARD BIT(6)
-#define PORT_CONTROL_2_EGRESS_MONITOR  BIT(5)
-#define PORT_CONTROL_2_INGRESS_MONITOR BIT(4)
-#define PORT_CONTROL_2_UPSTREAM_MASK   0x0f
-#define PORT_RATE_CONTROL      0x09
-#define PORT_RATE_CONTROL_2    0x0a
-#define PORT_ASSOC_VECTOR      0x0b
-#define PORT_ASSOC_VECTOR_HOLD_AT_1            BIT(15)
-#define PORT_ASSOC_VECTOR_INT_AGE_OUT          BIT(14)
-#define PORT_ASSOC_VECTOR_LOCKED_PORT          BIT(13)
-#define PORT_ASSOC_VECTOR_IGNORE_WRONG         BIT(12)
-#define PORT_ASSOC_VECTOR_REFRESH_LOCKED       BIT(11)
-#define PORT_ATU_CONTROL       0x0c
-#define PORT_PRI_OVERRIDE      0x0d
-#define PORT_ETH_TYPE          0x0f
-#define PORT_ETH_TYPE_DEFAULT  0x9100
-#define PORT_IN_DISCARD_LO     0x10
-#define PORT_IN_DISCARD_HI     0x11
-#define PORT_IN_FILTERED       0x12
-#define PORT_OUT_FILTERED      0x13
-#define PORT_TAG_REGMAP_0123   0x18
-#define PORT_TAG_REGMAP_4567   0x19
-#define PORT_IEEE_PRIO_MAP_TABLE       0x18    /* 6390 */
-#define PORT_IEEE_PRIO_MAP_TABLE_UPDATE                BIT(15)
-#define PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP           (0x0 << 12)
-#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP      (0x1 << 12)
-#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP     (0x2 << 12)
-#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP                (0x3 << 12)
-#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_DSCP     (0x5 << 12)
-#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_DSCP    (0x6 << 12)
-#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_DSCP       (0x7 << 12)
-#define PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT         9
+/* Offset 0x00: Port Status Register */
+#define MV88E6XXX_PORT_STS                     0x00
+#define MV88E6XXX_PORT_STS_PAUSE_EN            0x8000
+#define MV88E6XXX_PORT_STS_MY_PAUSE            0x4000
+#define MV88E6XXX_PORT_STS_HD_FLOW             0x2000
+#define MV88E6XXX_PORT_STS_PHY_DETECT          0x1000
+#define MV88E6XXX_PORT_STS_LINK                        0x0800
+#define MV88E6XXX_PORT_STS_DUPLEX              0x0400
+#define MV88E6XXX_PORT_STS_SPEED_MASK          0x0300
+#define MV88E6XXX_PORT_STS_SPEED_10            0x0000
+#define MV88E6XXX_PORT_STS_SPEED_100           0x0100
+#define MV88E6XXX_PORT_STS_SPEED_1000          0x0200
+#define MV88E6352_PORT_STS_EEE                 0x0040
+#define MV88E6165_PORT_STS_AM_DIS              0x0040
+#define MV88E6185_PORT_STS_MGMII               0x0040
+#define MV88E6XXX_PORT_STS_TX_PAUSED           0x0020
+#define MV88E6XXX_PORT_STS_FLOW_CTL            0x0010
+#define MV88E6XXX_PORT_STS_CMODE_MASK          0x000f
+#define MV88E6XXX_PORT_STS_CMODE_100BASE_X     0x0008
+#define MV88E6XXX_PORT_STS_CMODE_1000BASE_X    0x0009
+#define MV88E6XXX_PORT_STS_CMODE_SGMII         0x000a
+#define MV88E6XXX_PORT_STS_CMODE_2500BASEX     0x000b
+#define MV88E6XXX_PORT_STS_CMODE_XAUI          0x000c
+#define MV88E6XXX_PORT_STS_CMODE_RXAUI         0x000d
+
+/* Offset 0x01: MAC (or PCS or Physical) Control Register */
+#define MV88E6XXX_PORT_MAC_CTL                         0x01
+#define MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK       0x8000
+#define MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK       0x4000
+#define MV88E6390_PORT_MAC_CTL_FORCE_SPEED             0x2000
+#define MV88E6390_PORT_MAC_CTL_ALTSPEED                        0x1000
+#define MV88E6352_PORT_MAC_CTL_200BASE                 0x1000
+#define MV88E6XXX_PORT_MAC_CTL_FC                      0x0080
+#define MV88E6XXX_PORT_MAC_CTL_FORCE_FC                        0x0040
+#define MV88E6XXX_PORT_MAC_CTL_LINK_UP                 0x0020
+#define MV88E6XXX_PORT_MAC_CTL_FORCE_LINK              0x0010
+#define MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL             0x0008
+#define MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX            0x0004
+#define MV88E6XXX_PORT_MAC_CTL_SPEED_MASK              0x0003
+#define MV88E6XXX_PORT_MAC_CTL_SPEED_10                        0x0000
+#define MV88E6XXX_PORT_MAC_CTL_SPEED_100               0x0001
+#define MV88E6065_PORT_MAC_CTL_SPEED_200               0x0002
+#define MV88E6XXX_PORT_MAC_CTL_SPEED_1000              0x0002
+#define MV88E6390_PORT_MAC_CTL_SPEED_10000             0x0003
+#define MV88E6XXX_PORT_MAC_CTL_SPEED_UNFORCED          0x0003
+
+/* Offset 0x02: Jamming Control Register */
+#define MV88E6097_PORT_JAM_CTL                 0x02
+#define MV88E6097_PORT_JAM_CTL_LIMIT_OUT_MASK  0xff00
+#define MV88E6097_PORT_JAM_CTL_LIMIT_IN_MASK   0x00ff
+
+/* Offset 0x02: Flow Control Register */
+#define MV88E6390_PORT_FLOW_CTL                        0x02
+#define MV88E6390_PORT_FLOW_CTL_UPDATE         0x8000
+#define MV88E6390_PORT_FLOW_CTL_PTR_MASK       0x7f00
+#define MV88E6390_PORT_FLOW_CTL_LIMIT_IN       0x0000
+#define MV88E6390_PORT_FLOW_CTL_LIMIT_OUT      0x0100
+#define MV88E6390_PORT_FLOW_CTL_DATA_MASK      0x00ff
+
+/* Offset 0x03: Switch Identifier Register */
+#define MV88E6XXX_PORT_SWITCH_ID               0x03
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_MASK     0xfff0
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6085     0x04a0
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6095     0x0950
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6097     0x0990
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6190X    0x0a00
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6390X    0x0a10
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6131     0x1060
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6320     0x1150
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6123     0x1210
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6161     0x1610
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6165     0x1650
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6171     0x1710
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6172     0x1720
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6175     0x1750
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6176     0x1760
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6190     0x1900
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6191     0x1910
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6185     0x1a70
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6240     0x2400
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6290     0x2900
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6321     0x3100
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6141     0x3400
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6341     0x3410
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6352     0x3520
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6350     0x3710
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6351     0x3750
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6390     0x3900
+#define MV88E6XXX_PORT_SWITCH_ID_REV_MASK      0x000f
+
+/* Offset 0x04: Port Control Register */
+#define MV88E6XXX_PORT_CTL0                                    0x04
+#define MV88E6XXX_PORT_CTL0_USE_CORE_TAG                       0x8000
+#define MV88E6XXX_PORT_CTL0_DROP_ON_LOCK                       0x4000
+#define MV88E6XXX_PORT_CTL0_EGRESS_MODE_MASK                   0x3000
+#define MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNMODIFIED             0x0000
+#define MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNTAGGED               0x1000
+#define MV88E6XXX_PORT_CTL0_EGRESS_MODE_TAGGED                 0x2000
+#define MV88E6XXX_PORT_CTL0_EGRESS_MODE_ETHER_TYPE_DSA         0x3000
+#define MV88E6XXX_PORT_CTL0_HEADER                             0x0800
+#define MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP                     0x0400
+#define MV88E6XXX_PORT_CTL0_DOUBLE_TAG                         0x0200
+#define MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK                    0x0300
+#define MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL                  0x0000
+#define MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA                     0x0100
+#define MV88E6XXX_PORT_CTL0_FRAME_MODE_PROVIDER                        0x0200
+#define MV88E6XXX_PORT_CTL0_FRAME_MODE_ETHER_TYPE_DSA          0x0300
+#define MV88E6XXX_PORT_CTL0_DSA_TAG                            0x0100
+#define MV88E6XXX_PORT_CTL0_VLAN_TUNNEL                                0x0080
+#define MV88E6XXX_PORT_CTL0_TAG_IF_BOTH                                0x0040
+#define MV88E6185_PORT_CTL0_USE_IP                             0x0020
+#define MV88E6185_PORT_CTL0_USE_TAG                            0x0010
+#define MV88E6185_PORT_CTL0_FORWARD_UNKNOWN                    0x0004
+#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_MASK                 0x000c
+#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_DA                0x0000
+#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_MC_DA     0x0004
+#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_UC_DA     0x0008
+#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_ALL_UNKNOWN_DA       0x000c
+#define MV88E6XXX_PORT_CTL0_STATE_MASK                         0x0003
+#define MV88E6XXX_PORT_CTL0_STATE_DISABLED                     0x0000
+#define MV88E6XXX_PORT_CTL0_STATE_BLOCKING                     0x0001
+#define MV88E6XXX_PORT_CTL0_STATE_LEARNING                     0x0002
+#define MV88E6XXX_PORT_CTL0_STATE_FORWARDING                   0x0003
+
+/* Offset 0x05: Port Control 1 */
+#define MV88E6XXX_PORT_CTL1                    0x05
+#define MV88E6XXX_PORT_CTL1_MESSAGE_PORT       0x8000
+#define MV88E6XXX_PORT_CTL1_FID_11_4_MASK      0x00ff
+
+/* Offset 0x06: Port Based VLAN Map */
+#define MV88E6XXX_PORT_BASE_VLAN               0x06
+#define MV88E6XXX_PORT_BASE_VLAN_FID_3_0_MASK  0xf000
+
+/* Offset 0x07: Default Port VLAN ID & Priority */
+#define MV88E6XXX_PORT_DEFAULT_VLAN            0x07
+#define MV88E6XXX_PORT_DEFAULT_VLAN_MASK       0x0fff
+
+/* Offset 0x08: Port Control 2 Register */
+#define MV88E6XXX_PORT_CTL2                            0x08
+#define MV88E6XXX_PORT_CTL2_IGNORE_FCS                 0x8000
+#define MV88E6XXX_PORT_CTL2_VTU_PRI_OVERRIDE           0x4000
+#define MV88E6XXX_PORT_CTL2_SA_PRIO_OVERRIDE           0x2000
+#define MV88E6XXX_PORT_CTL2_DA_PRIO_OVERRIDE           0x1000
+#define MV88E6XXX_PORT_CTL2_JUMBO_MODE_MASK            0x3000
+#define MV88E6XXX_PORT_CTL2_JUMBO_MODE_1522            0x0000
+#define MV88E6XXX_PORT_CTL2_JUMBO_MODE_2048            0x1000
+#define MV88E6XXX_PORT_CTL2_JUMBO_MODE_10240           0x2000
+#define MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK            0x0c00
+#define MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED                0x0000
+#define MV88E6XXX_PORT_CTL2_8021Q_MODE_FALLBACK                0x0400
+#define MV88E6XXX_PORT_CTL2_8021Q_MODE_CHECK           0x0800
+#define MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE          0x0c00
+#define MV88E6XXX_PORT_CTL2_DISCARD_TAGGED             0x0200
+#define MV88E6XXX_PORT_CTL2_DISCARD_UNTAGGED           0x0100
+#define MV88E6XXX_PORT_CTL2_MAP_DA                     0x0080
+#define MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD            0x0040
+#define MV88E6XXX_PORT_CTL2_EGRESS_MONITOR             0x0020
+#define MV88E6XXX_PORT_CTL2_INGRESS_MONITOR            0x0010
+#define MV88E6095_PORT_CTL2_CPU_PORT_MASK              0x000f
+
+/* Offset 0x09: Egress Rate Control */
+#define MV88E6XXX_PORT_EGRESS_RATE_CTL1                0x09
+
+/* Offset 0x0A: Egress Rate Control 2 */
+#define MV88E6XXX_PORT_EGRESS_RATE_CTL2                0x0a
+
+/* Offset 0x0B: Port Association Vector */
+#define MV88E6XXX_PORT_ASSOC_VECTOR                    0x0b
+#define MV88E6XXX_PORT_ASSOC_VECTOR_HOLD_AT_1          0x8000
+#define MV88E6XXX_PORT_ASSOC_VECTOR_INT_AGE_OUT                0x4000
+#define MV88E6XXX_PORT_ASSOC_VECTOR_LOCKED_PORT                0x2000
+#define MV88E6XXX_PORT_ASSOC_VECTOR_IGNORE_WRONG       0x1000
+#define MV88E6XXX_PORT_ASSOC_VECTOR_REFRESH_LOCKED     0x0800
+
+/* Offset 0x0C: Port ATU Control */
+#define MV88E6XXX_PORT_ATU_CTL         0x0c
+
+/* Offset 0x0D: Priority Override Register */
+#define MV88E6XXX_PORT_PRI_OVERRIDE    0x0d
+
+/* Offset 0x0E: Policy Control Register */
+#define MV88E6XXX_PORT_POLICY_CTL      0x0e
+
+/* Offset 0x0F: Port Special Ether Type */
+#define MV88E6XXX_PORT_ETH_TYPE                0x0f
+#define MV88E6XXX_PORT_ETH_TYPE_DEFAULT        0x9100
+
+/* Offset 0x10: InDiscards Low Counter */
+#define MV88E6XXX_PORT_IN_DISCARD_LO   0x10
+
+/* Offset 0x11: InDiscards High Counter */
+#define MV88E6XXX_PORT_IN_DISCARD_HI   0x11
+
+/* Offset 0x12: InFiltered Counter */
+#define MV88E6XXX_PORT_IN_FILTERED     0x12
+
+/* Offset 0x13: OutFiltered Counter */
+#define MV88E6XXX_PORT_OUT_FILTERED    0x13
+
+/* Offset 0x16: LED Control */
+#define MV88E6XXX_PORT_LED_CONTROL     0x16
+
+/* Offset 0x18: IEEE Priority Mapping Table */
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE                     0x18
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE              0x8000
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP         0x0000
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP    0x1000
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP   0x2000
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP      0x3000
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_DSCP   0x5000
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_DSCP  0x6000
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_DSCP     0x7000
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT       9
+
+/* Offset 0x18: Port IEEE Priority Remapping Registers (0-3) */
+#define MV88E6095_PORT_IEEE_PRIO_REMAP_0123    0x18
+
+/* Offset 0x19: Port IEEE Priority Remapping Registers (4-7) */
+#define MV88E6095_PORT_IEEE_PRIO_REMAP_4567    0x19
 
 int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
                        u16 *val);
@@ -212,7 +272,7 @@ int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
 int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port);
 int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port);
 int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
-                                  u16 mode);
+                                  enum mv88e6xxx_egress_mode mode);
 int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
                                  enum mv88e6xxx_frame_mode mode);
 int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
@@ -225,11 +285,14 @@ int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
                                  u16 etype);
 int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
                                    bool message_port);
-int mv88e6165_port_jumbo_config(struct mv88e6xxx_chip *chip, int port);
+int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
+                                 size_t size);
 int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
 int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
-int mv88e6097_port_pause_config(struct mv88e6xxx_chip *chip, int port);
-int mv88e6390_port_pause_config(struct mv88e6xxx_chip *chip, int port);
+int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
+                              u8 out);
+int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
+                              u8 out);
 int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
                              phy_interface_t mode);
 int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
index 78f5b1eb44ea4425f8af624dcf3393c21f62c6cf..411b4f52279252e842e7518d08c960ba1b783ae6 100644 (file)
@@ -64,9 +64,9 @@ int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
        if (err)
                return err;
 
-       if ((cmode == PORT_STATUS_CMODE_100BASE_X) ||
-           (cmode == PORT_STATUS_CMODE_1000BASE_X) ||
-           (cmode == PORT_STATUS_CMODE_SGMII)) {
+       if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASE_X) ||
+           (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) ||
+           (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII)) {
                err = mv88e6352_serdes_power_set(chip, on);
                if (err < 0)
                        return err;
@@ -139,15 +139,15 @@ static int mv88e6390_serdes_lower(struct mv88e6xxx_chip *chip, u8 cmode,
                return err;
 
        switch (cmode_donor) {
-       case PORT_STATUS_CMODE_RXAUI:
+       case MV88E6XXX_PORT_STS_CMODE_RXAUI:
                if (!rxaui)
                        break;
                /* Fall through */
-       case PORT_STATUS_CMODE_1000BASE_X:
-       case PORT_STATUS_CMODE_SGMII:
-       case PORT_STATUS_CMODE_2500BASEX:
-               if (cmode == PORT_STATUS_CMODE_1000BASE_X ||
-                   cmode == PORT_STATUS_CMODE_SGMII)
+       case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+       case MV88E6XXX_PORT_STS_CMODE_SGMII:
+       case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
+               if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+                   cmode == MV88E6XXX_PORT_STS_CMODE_SGMII)
                        return  mv88e6390_serdes_sgmii(chip, lane, on);
        }
        return 0;
@@ -157,12 +157,12 @@ static int mv88e6390_serdes_port9(struct mv88e6xxx_chip *chip, u8 cmode,
                                  bool on)
 {
        switch (cmode) {
-       case PORT_STATUS_CMODE_1000BASE_X:
-       case PORT_STATUS_CMODE_SGMII:
+       case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+       case MV88E6XXX_PORT_STS_CMODE_SGMII:
                return mv88e6390_serdes_sgmii(chip, MV88E6390_PORT9_LANE0, on);
-       case PORT_STATUS_CMODE_XAUI:
-       case PORT_STATUS_CMODE_RXAUI:
-       case PORT_STATUS_CMODE_2500BASEX:
+       case MV88E6XXX_PORT_STS_CMODE_XAUI:
+       case MV88E6XXX_PORT_STS_CMODE_RXAUI:
+       case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
                return mv88e6390_serdes_10g(chip, MV88E6390_PORT9_LANE0, on);
        }
 
@@ -173,12 +173,12 @@ static int mv88e6390_serdes_port10(struct mv88e6xxx_chip *chip, u8 cmode,
                                   bool on)
 {
        switch (cmode) {
-       case PORT_STATUS_CMODE_SGMII:
+       case MV88E6XXX_PORT_STS_CMODE_SGMII:
                return mv88e6390_serdes_sgmii(chip, MV88E6390_PORT10_LANE0, on);
-       case PORT_STATUS_CMODE_XAUI:
-       case PORT_STATUS_CMODE_RXAUI:
-       case PORT_STATUS_CMODE_1000BASE_X:
-       case PORT_STATUS_CMODE_2500BASEX:
+       case MV88E6XXX_PORT_STS_CMODE_XAUI:
+       case MV88E6XXX_PORT_STS_CMODE_RXAUI:
+       case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+       case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
                return mv88e6390_serdes_10g(chip, MV88E6390_PORT10_LANE0, on);
        }
 
index 5a2ad9c5faab16a8206bde14a7fb28f079e0ec15..a934bd5d05075308f6087c5a4aaa0e099251fda3 100644 (file)
@@ -1846,7 +1846,8 @@ static void xgbe_poll_controller(struct net_device *netdev)
 }
 #endif /* End CONFIG_NET_POLL_CONTROLLER */
 
-static int xgbe_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
+static int xgbe_setup_tc(struct net_device *netdev, u32 handle, u32 chain_index,
+                        __be16 proto,
                         struct tc_to_netdev *tc_to_netdev)
 {
        struct xgbe_prv_data *pdata = netdev_priv(netdev);
index b6666e418e79fd1c0bfc4f33a9b17e4c094c36b9..d31ad8270d93a887df9496427ef0cb07d4c7a2c7 100644 (file)
@@ -157,7 +157,9 @@ static int xge_get_link_ksettings(struct net_device *ndev,
        if (!phydev)
                return -ENODEV;
 
-       return phy_ethtool_ksettings_get(phydev, cmd);
+       phy_ethtool_ksettings_get(phydev, cmd);
+
+       return 0;
 }
 
 static int xge_set_link_ksettings(struct net_device *ndev,
index 559963b1aa3243506f9c27f0636706bf13c50d64..4f50f11718f4b73bd8f883aa94b209c7a07d78c0 100644 (file)
@@ -131,13 +131,17 @@ static int xgene_get_link_ksettings(struct net_device *ndev,
                if (phydev == NULL)
                        return -ENODEV;
 
-               return phy_ethtool_ksettings_get(phydev, cmd);
+               phy_ethtool_ksettings_get(phydev, cmd);
+
+               return 0;
        } else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
                if (pdata->mdio_driver) {
                        if (!phydev)
                                return -ENODEV;
 
-                       return phy_ethtool_ksettings_get(phydev, cmd);
+                       phy_ethtool_ksettings_get(phydev, cmd);
+
+                       return 0;
                }
 
                supported = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
index 5b95bb48ce97dd9c0d02968badb05949f7eb4214..f411936b744cb1fa4d331f7b439a181916fa118e 100644 (file)
@@ -1836,7 +1836,9 @@ static int b44_get_link_ksettings(struct net_device *dev,
 
        if (bp->flags & B44_FLAG_EXTERNAL_PHY) {
                BUG_ON(!dev->phydev);
-               return phy_ethtool_ksettings_get(dev->phydev, cmd);
+               phy_ethtool_ksettings_get(dev->phydev, cmd);
+
+               return 0;
        }
 
        supported = (SUPPORTED_Autoneg);
index 50d88d3e03b68af9bb09f11b2aec09e7d2977c80..ea3c906fa0e43ab56edf491350ffe429048f0fe8 100644 (file)
@@ -1453,7 +1453,10 @@ static int bcm_enet_get_link_ksettings(struct net_device *dev,
        if (priv->has_phy) {
                if (!dev->phydev)
                        return -ENODEV;
-               return phy_ethtool_ksettings_get(dev->phydev, cmd);
+
+               phy_ethtool_ksettings_get(dev->phydev, cmd);
+
+               return 0;
        } else {
                cmd->base.autoneg = 0;
                cmd->base.speed = (priv->force_speed_100) ?
index 5f49334dcad5a8c8602cc3aa2e8795b2d489bb43..ef734675885e72fd61013d663940f25fa95d44c5 100644 (file)
@@ -4273,8 +4273,8 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
        return 0;
 }
 
-int __bnx2x_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-                    struct tc_to_netdev *tc)
+int __bnx2x_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+                    __be16 proto, struct tc_to_netdev *tc)
 {
        if (tc->type != TC_SETUP_MQPRIO)
                return -EINVAL;
index 243cb9748d35da488463f60d0e59a035a4330333..c26688d2f32663f348b5c21dff1931f07b7487c8 100644 (file)
@@ -486,8 +486,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
 /* setup_tc callback */
 int bnx2x_setup_tc(struct net_device *dev, u8 num_tc);
-int __bnx2x_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-                    struct tc_to_netdev *tc);
+int __bnx2x_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+                    __be16 proto, struct tc_to_netdev *tc);
 
 int bnx2x_get_vf_config(struct net_device *dev, int vf,
                        struct ifla_vf_info *ivi);
index c1cd72a5eccf80d8ab171681d24f608bd6dace1b..11e8a866a31232e123567fc539b4a1ae45a7cfad 100644 (file)
@@ -7103,8 +7103,8 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
        return 0;
 }
 
-static int bnxt_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-                        struct tc_to_netdev *ntc)
+static int bnxt_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+                        __be16 proto, struct tc_to_netdev *ntc)
 {
        if (ntc->type != TC_SETUP_MQPRIO)
                return -EINVAL;
index a205a9ff9e179ba9b5f854b9e9707a29b36a45bb..daca1c9d254be4b4f2b513f1754c7534c104c757 100644 (file)
@@ -477,7 +477,9 @@ static int bcmgenet_get_link_ksettings(struct net_device *dev,
        if (!priv->phydev)
                return -ENODEV;
 
-       return phy_ethtool_ksettings_get(priv->phydev, cmd);
+       phy_ethtool_ksettings_get(priv->phydev, cmd);
+
+       return 0;
 }
 
 static int bcmgenet_set_link_ksettings(struct net_device *dev,
index 537d571ee60171f303b52f692a83a3eecdeef358..d600c41fb1dc18c853e52ac1aa446c6d6d2f03b9 100644 (file)
@@ -12097,7 +12097,9 @@ static int tg3_get_link_ksettings(struct net_device *dev,
                if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED))
                        return -EAGAIN;
                phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
-               return phy_ethtool_ksettings_get(phydev, cmd);
+               phy_ethtool_ksettings_get(phydev, cmd);
+
+               return 0;
        }
 
        supported = (SUPPORTED_Autoneg);
index 2e253061460b76e8e3136586926b97f532566e52..53856af07d46396ddc3ee2d5dbe73fe792f70cb8 100644 (file)
@@ -700,6 +700,13 @@ static void lio_set_msglevel(struct net_device *netdev, u32 msglvl)
        lio->msg_enable = msglvl;
 }
 
+static void lio_vf_set_msglevel(struct net_device *netdev, u32 msglvl)
+{
+       struct lio *lio = GET_LIO(netdev);
+
+       lio->msg_enable = msglvl;
+}
+
 static void
 lio_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
 {
@@ -2611,7 +2618,7 @@ static const struct ethtool_ops lio_vf_ethtool_ops = {
        .get_regs_len           = lio_get_regs_len,
        .get_regs               = lio_get_regs,
        .get_msglevel           = lio_get_msglevel,
-       .set_msglevel           = lio_set_msglevel,
+       .set_msglevel           = lio_vf_set_msglevel,
        .get_sset_count         = lio_vf_get_sset_count,
        .get_coalesce           = lio_get_intr_coalesce,
        .set_coalesce           = lio_set_intr_coalesce,
index 07124096db48b8bb399155003f7e23a8ff5098c4..1f7032614ae589ba9d2c6b7134af909e6b398cba 100644 (file)
@@ -2997,10 +2997,6 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
                        liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,
                                             OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
 
-               if ((debug != -1) && (debug & NETIF_MSG_HW))
-                       liquidio_set_feature(netdev, OCTNET_CMD_VERBOSE_ENABLE,
-                                            0);
-
                if (setup_link_status_change_wq(netdev))
                        goto setup_nic_dev_fail;
 
index 91685bf21878c62d72e8ab9e3d37e80ead2dc7d9..01c9710fc62e683f883fdab58526b6c66fb7c153 100644 (file)
@@ -2823,12 +2823,15 @@ static int cxgb_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
        return err;
 }
 
-static int cxgb_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-                        struct tc_to_netdev *tc)
+static int cxgb_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+                        __be16 proto, struct tc_to_netdev *tc)
 {
        struct port_info *pi = netdev2pinfo(dev);
        struct adapter *adap = netdev2adap(dev);
 
+       if (chain_index)
+               return -EOPNOTSUPP;
+
        if (!(adap->flags & FULL_INIT_DONE)) {
                dev_err(adap->pdev_dev,
                        "Failed to setup tc on port %d. Link Down?\n",
@@ -5166,13 +5169,15 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                              &v, &port_vec);
        if (err < 0) {
                dev_err(adapter->pdev_dev, "Could not fetch port params\n");
-               goto free_adapter;
+               goto free_mbox_log;
        }
 
        adapter->params.nports = hweight32(port_vec);
        pci_set_drvdata(pdev, adapter);
        return 0;
 
+free_mbox_log:
+       kfree(adapter->mbox_log);
  free_adapter:
        kfree(adapter);
  free_pci_region:
@@ -5272,6 +5277,7 @@ static void remove_one(struct pci_dev *pdev)
                        unregister_netdev(adapter->port[0]);
                iounmap(adapter->regs);
                kfree(adapter->vfinfo);
+               kfree(adapter->mbox_log);
                kfree(adapter);
                pci_disable_sriov(pdev);
                pci_release_regions(pdev);
@@ -5318,6 +5324,7 @@ static void shutdown_one(struct pci_dev *pdev)
                        unregister_netdev(adapter->port[0]);
                iounmap(adapter->regs);
                kfree(adapter->vfinfo);
+               kfree(adapter->mbox_log);
                kfree(adapter);
                pci_disable_sriov(pdev);
                pci_release_regions(pdev);
index 4618185d6bc20822e6b1cf377f44579e4a57c201..16af646a7fe426fd9a0827f3a8751bef423a63eb 100644 (file)
@@ -4040,6 +4040,7 @@ static void cim_intr_handler(struct adapter *adapter)
                { MBHOSTPARERR_F, "CIM mailbox host parity error", -1, 1 },
                { TIEQINPARERRINT_F, "CIM TIEQ outgoing parity error", -1, 1 },
                { TIEQOUTPARERRINT_F, "CIM TIEQ incoming parity error", -1, 1 },
+               { TIMER0INT_F, "CIM TIMER0 interrupt", -1, 1 },
                { 0 }
        };
        static const struct intr_info cim_upintr_info[] = {
@@ -4074,11 +4075,27 @@ static void cim_intr_handler(struct adapter *adapter)
                { 0 }
        };
 
+       u32 val, fw_err;
        int fat;
 
-       if (t4_read_reg(adapter, PCIE_FW_A) & PCIE_FW_ERR_F)
+       fw_err = t4_read_reg(adapter, PCIE_FW_A);
+       if (fw_err & PCIE_FW_ERR_F)
                t4_report_fw_error(adapter);
 
+       /* When the Firmware detects an internal error which normally
+        * wouldn't raise a Host Interrupt, it forces a CIM Timer0 interrupt
+        * in order to make sure the Host sees the Firmware Crash.  So
+        * if we have a Timer0 interrupt and don't see a Firmware Crash,
+        * ignore the Timer0 interrupt.
+        */
+
+       val = t4_read_reg(adapter, CIM_HOST_INT_CAUSE_A);
+       if (val & TIMER0INT_F)
+               if (!(fw_err & PCIE_FW_ERR_F) ||
+                   (PCIE_FW_EVAL_G(fw_err) != PCIE_FW_EVAL_CRASH))
+                       t4_write_reg(adapter, CIM_HOST_INT_CAUSE_A,
+                                    TIMER0INT_F);
+
        fat = t4_handle_intr_status(adapter, CIM_HOST_INT_CAUSE_A,
                                    cim_intr_info) +
              t4_handle_intr_status(adapter, CIM_HOST_UPACC_INT_CAUSE_A,
@@ -7688,10 +7705,9 @@ int t4_shutdown_adapter(struct adapter *adapter)
        t4_intr_disable(adapter);
        t4_write_reg(adapter, DBG_GPIO_EN_A, 0);
        for_each_port(adapter, port) {
-               u32 a_port_cfg = PORT_REG(port,
-                                         is_t4(adapter->params.chip)
-                                         ? XGMAC_PORT_CFG_A
-                                         : MAC_PORT_CFG_A);
+               u32 a_port_cfg = is_t4(adapter->params.chip) ?
+                                      PORT_REG(port, XGMAC_PORT_CFG_A) :
+                                      T5_PORT_REG(port, MAC_PORT_CFG_A);
 
                t4_write_reg(adapter, a_port_cfg,
                             t4_read_reg(adapter, a_port_cfg)
index 3348d33c36faca900e92bca25607ac79b0246908..3884336ce23ca79c2730e3c294601af092e0afaa 100644 (file)
 #define TIEQINPARERRINT_V(x) ((x) << TIEQINPARERRINT_S)
 #define TIEQINPARERRINT_F    TIEQINPARERRINT_V(1U)
 
+#define TIMER0INT_S    2
+#define TIMER0INT_V(x) ((x) << TIMER0INT_S)
+#define TIMER0INT_F    TIMER0INT_V(1U)
+
 #define PREFDROPINT_S    1
 #define PREFDROPINT_V(x) ((x) << PREFDROPINT_S)
 #define PREFDROPINT_F    PREFDROPINT_V(1U)
index c65c33c03bcbba027ad32af7bc20c5f8d8412fd8..f47461aa658b482139bbec350cbf9f5ffe6498fc 100644 (file)
@@ -3088,6 +3088,10 @@ struct fw_debug_cmd {
 #define FW_DEBUG_CMD_TYPE_G(x) \
        (((x) >> FW_DEBUG_CMD_TYPE_S) & FW_DEBUG_CMD_TYPE_M)
 
+enum pcie_fw_eval {
+       PCIE_FW_EVAL_CRASH = 0,
+};
+
 #define PCIE_FW_ERR_S          31
 #define PCIE_FW_ERR_V(x)       ((x) << PCIE_FW_ERR_S)
 #define PCIE_FW_ERR_F          PCIE_FW_ERR_V(1U)
index 9a520e4f0df9a0d47b75f71f01557414ba3d4eab..a5501af6db991fdd49438f905902f2a4eb65e7e5 100644 (file)
@@ -342,8 +342,8 @@ static void dpaa_get_stats64(struct net_device *net_dev,
        }
 }
 
-static int dpaa_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
-                        struct tc_to_netdev *tc)
+static int dpaa_setup_tc(struct net_device *net_dev, u32 handle,
+                        u32 chain_index, __be16 proto, struct tc_to_netdev *tc)
 {
        struct dpaa_priv *priv = netdev_priv(net_dev);
        u8 num_tc;
index 15571e251fb910c3f17d70c643c33ef894438a58..aad8250883573302fbe3e765594d7199572b6d1f 100644 (file)
@@ -75,16 +75,14 @@ static char dpaa_stats_global[][ETH_GSTRING_LEN] = {
 static int dpaa_get_link_ksettings(struct net_device *net_dev,
                                   struct ethtool_link_ksettings *cmd)
 {
-       int err;
-
        if (!net_dev->phydev) {
                netdev_dbg(net_dev, "phy device not initialized\n");
                return 0;
        }
 
-       err = phy_ethtool_ksettings_get(net_dev->phydev, cmd);
+       phy_ethtool_ksettings_get(net_dev->phydev, cmd);
 
-       return err;
+       return 0;
 }
 
 static int dpaa_set_link_ksettings(struct net_device *net_dev,
index 297fd196c8793d3ed7e00afb96adea6fccd7db83..a6e323f1563745c3a0cedd91d240e05af6606f33 100644 (file)
@@ -2379,6 +2379,10 @@ static void fec_enet_clear_ethtool_stats(struct net_device *dev)
 static inline void fec_enet_update_ethtool_stats(struct net_device *dev)
 {
 }
+
+static inline void fec_enet_clear_ethtool_stats(struct net_device *dev)
+{
+}
 #endif /* !defined(CONFIG_M5272) */
 
 /* ITR clock source is enet system clock (clk_ahb).
index b642990b549c2c2414937bb9479f494b05971aec..4df282ed22c7962f7e10ab6d17be11b50a1ac44f 100644 (file)
@@ -113,7 +113,9 @@ uec_get_ksettings(struct net_device *netdev, struct ethtool_link_ksettings *cmd)
        if (!phydev)
                return -ENODEV;
 
-       return phy_ethtool_ksettings_get(phydev, cmd);
+       phy_ethtool_ksettings_get(phydev, cmd);
+
+       return 0;
 }
 
 static int
index b8fab149690f880394f0d973560aecca69d1171e..af1b15cc6a7f24ef5ed194db560cff2e73637ca3 100644 (file)
@@ -150,7 +150,7 @@ static int hns_nic_get_link_ksettings(struct net_device *net_dev,
        cmd->base.duplex = duplex;
 
        if (net_dev->phydev)
-               (void)phy_ethtool_ksettings_get(net_dev->phydev, cmd);
+               phy_ethtool_ksettings_get(net_dev->phydev, cmd);
 
        link_stat = hns_nic_get_link(net_dev);
        if (!link_stat) {
index 5b88cc690c22c1ce8e123cdb3c0d23908414f8df..35865d05fccd3709fad96d41fa3a6b83edd213f8 100644 (file)
@@ -276,7 +276,7 @@ static int genmii_read_link(struct mii_phy *phy)
 }
 
 /* Generic implementation for most 10/100/1000 PHYs */
-static struct mii_phy_ops generic_phy_ops = {
+static const struct mii_phy_ops generic_phy_ops = {
        .setup_aneg     = genmii_setup_aneg,
        .setup_forced   = genmii_setup_forced,
        .poll_link      = genmii_poll_link,
@@ -340,7 +340,7 @@ static int cis8201_init(struct mii_phy *phy)
        return 0;
 }
 
-static struct mii_phy_ops cis8201_phy_ops = {
+static const struct mii_phy_ops cis8201_phy_ops = {
        .init           = cis8201_init,
        .setup_aneg     = genmii_setup_aneg,
        .setup_forced   = genmii_setup_forced,
@@ -420,7 +420,7 @@ static int et1011c_init(struct mii_phy *phy)
        return 0;
 }
 
-static struct mii_phy_ops et1011c_phy_ops = {
+static const struct mii_phy_ops et1011c_phy_ops = {
        .init           = et1011c_init,
        .setup_aneg     = genmii_setup_aneg,
        .setup_forced   = genmii_setup_forced,
@@ -439,7 +439,7 @@ static struct mii_phy_def et1011c_phy_def = {
 
 
 
-static struct mii_phy_ops m88e1111_phy_ops = {
+static const struct mii_phy_ops m88e1111_phy_ops = {
        .init           = m88e1111_init,
        .setup_aneg     = genmii_setup_aneg,
        .setup_forced   = genmii_setup_forced,
@@ -455,7 +455,7 @@ static struct mii_phy_def m88e1111_phy_def = {
        .ops            = &m88e1111_phy_ops,
 };
 
-static struct mii_phy_ops m88e1112_phy_ops = {
+static const struct mii_phy_ops m88e1112_phy_ops = {
        .init           = m88e1112_init,
        .setup_aneg     = genmii_setup_aneg,
        .setup_forced   = genmii_setup_forced,
@@ -480,7 +480,7 @@ static int ar8035_init(struct mii_phy *phy)
        return 0;
 }
 
-static struct mii_phy_ops ar8035_phy_ops = {
+static const struct mii_phy_ops ar8035_phy_ops = {
        .init           = ar8035_init,
        .setup_aneg     = genmii_setup_aneg,
        .setup_forced   = genmii_setup_forced,
index 7d84e20b4887a778a179d90fe297e76920bdd949..59ea7a5ae776cbfc0b82e6941b3c98bdd3e6cc4f 100644 (file)
@@ -1364,7 +1364,9 @@ static int do_reset(struct ibmvnic_adapter *adapter,
        for (i = 0; i < adapter->req_rx_queues; i++)
                napi_schedule(&adapter->napi[i]);
 
-       netdev_notify_peers(netdev);
+       if (adapter->reset_reason != VNIC_RESET_FAILOVER)
+               netdev_notify_peers(netdev);
+
        return 0;
 }
 
@@ -3656,6 +3658,8 @@ static int ibmvnic_init(struct ibmvnic_adapter *adapter)
        return rc;
 }
 
+static struct device_attribute dev_attr_failover;
+
 static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
 {
        struct ibmvnic_adapter *adapter;
@@ -3712,9 +3716,16 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
 
        netdev->mtu = adapter->req_mtu - ETH_HLEN;
 
+       rc = device_create_file(&dev->dev, &dev_attr_failover);
+       if (rc) {
+               free_netdev(netdev);
+               return rc;
+       }
+
        rc = register_netdev(netdev);
        if (rc) {
                dev_err(&dev->dev, "failed to register netdev rc=%d\n", rc);
+               device_remove_file(&dev->dev, &dev_attr_failover);
                free_netdev(netdev);
                return rc;
        }
@@ -3740,12 +3751,49 @@ static int ibmvnic_remove(struct vio_dev *dev)
        adapter->state = VNIC_REMOVED;
 
        mutex_unlock(&adapter->reset_lock);
+       device_remove_file(&dev->dev, &dev_attr_failover);
        free_netdev(netdev);
        dev_set_drvdata(&dev->dev, NULL);
 
        return 0;
 }
 
+static ssize_t failover_store(struct device *dev, struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct net_device *netdev = dev_get_drvdata(dev);
+       struct ibmvnic_adapter *adapter = netdev_priv(netdev);
+       unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+       __be64 session_token;
+       long rc;
+
+       if (!sysfs_streq(buf, "1"))
+               return -EINVAL;
+
+       rc = plpar_hcall(H_VIOCTL, retbuf, adapter->vdev->unit_address,
+                        H_GET_SESSION_TOKEN, 0, 0, 0);
+       if (rc) {
+               netdev_err(netdev, "Couldn't retrieve session token, rc %ld\n",
+                          rc);
+               return -EINVAL;
+       }
+
+       session_token = (__be64)retbuf[0];
+       netdev_dbg(netdev, "Initiating client failover, session id %llx\n",
+                  be64_to_cpu(session_token));
+       rc = plpar_hcall_norets(H_VIOCTL, adapter->vdev->unit_address,
+                               H_SESSION_ERR_DETECTED, session_token, 0, 0);
+       if (rc) {
+               netdev_err(netdev, "Client initiated failover failed, rc %ld\n",
+                          rc);
+               return -EINVAL;
+       }
+
+       return count;
+}
+
+static DEVICE_ATTR(failover, 0200, NULL, failover_store);
+
 static unsigned long ibmvnic_get_desired_dma(struct vio_dev *vdev)
 {
        struct net_device *netdev = dev_get_drvdata(&vdev->dev);
index e1d46c11cb61b1920fac6287d2eda6f115715bf3..2dcb5463d9b86176e5d915a5e602f52cab43ae1f 100644 (file)
@@ -6640,12 +6640,17 @@ static int e1000e_pm_thaw(struct device *dev)
 static int e1000e_pm_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
+       int rc;
 
        e1000e_flush_lpic(pdev);
 
        e1000e_pm_freeze(dev);
 
-       return __e1000_shutdown(pdev, false);
+       rc = __e1000_shutdown(pdev, false);
+       if (rc)
+               e1000e_pm_thaw(dev);
+
+       return rc;
 }
 
 static int e1000e_pm_resume(struct device *dev)
index 24f2f6f86f5a3a50929eb52b5dbe6eb08e0e8635..5e37387c70825db8c1edc425c21478787e213a5e 100644 (file)
@@ -1265,8 +1265,8 @@ int fm10k_setup_tc(struct net_device *dev, u8 tc)
        return err;
 }
 
-static int __fm10k_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-                           struct tc_to_netdev *tc)
+static int __fm10k_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+                           __be16 proto, struct tc_to_netdev *tc)
 {
        if (tc->type != TC_SETUP_MQPRIO)
                return -EINVAL;
index 5fef27ebfa52671b9dfea5bcf8a1e273f5678253..abab7fb7a3fcc0af654260e95b4b28637a1c481e 100644 (file)
@@ -5509,7 +5509,8 @@ static int i40e_setup_tc(struct net_device *netdev, u8 tc)
        return ret;
 }
 
-static int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
+static int __i40e_setup_tc(struct net_device *netdev, u32 handle,
+                          u32 chain_index, __be16 proto,
                           struct tc_to_netdev *tc)
 {
        if (tc->type != TC_SETUP_MQPRIO)
index 7e433344a13cbaf90c4c2c1c1bcbaf13376d6e60..ec62410b035a1ba9678e405ab4ddb53f060901b6 100644 (file)
@@ -6469,8 +6469,8 @@ static void igb_set_default_mac_filter(struct igb_adapter *adapter)
        igb_rar_set_index(adapter, 0);
 }
 
-int igb_add_mac_filter(struct igb_adapter *adapter, const u8 *addr,
-                      const u8 queue)
+static int igb_add_mac_filter(struct igb_adapter *adapter, const u8 *addr,
+                             const u8 queue)
 {
        struct e1000_hw *hw = &adapter->hw;
        int rar_entries = hw->mac.rar_entry_count -
@@ -6499,8 +6499,8 @@ int igb_add_mac_filter(struct igb_adapter *adapter, const u8 *addr,
        return -ENOSPC;
 }
 
-int igb_del_mac_filter(struct igb_adapter *adapter, const u8 *addr,
-                      const u8 queue)
+static int igb_del_mac_filter(struct igb_adapter *adapter, const u8 *addr,
+                             const u8 queue)
 {
        struct e1000_hw *hw = &adapter->hw;
        int rar_entries = hw->mac.rar_entry_count -
@@ -6552,8 +6552,8 @@ static int igb_uc_unsync(struct net_device *netdev, const unsigned char *addr)
        return 0;
 }
 
-int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf,
-                         const u32 info, const u8 *addr)
+static int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf,
+                                const u32 info, const u8 *addr)
 {
        struct pci_dev *pdev = adapter->pdev;
        struct vf_data_storage *vf_data = &adapter->vf_data[vf];
index 54463f03b3db50e6b5b0329c94a419ea6b2a7a9a..812319ab77db9612e91ea19583a6cb21a80cf4d5 100644 (file)
@@ -9200,11 +9200,14 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
        return err;
 }
 
-static int __ixgbe_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-                           struct tc_to_netdev *tc)
+static int __ixgbe_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+                           __be16 proto, struct tc_to_netdev *tc)
 {
        struct ixgbe_adapter *adapter = netdev_priv(dev);
 
+       if (chain_index)
+               return -EOPNOTSUPP;
+
        if (TC_H_MAJ(handle) == TC_H_MAJ(TC_H_INGRESS) &&
            tc->type == TC_SETUP_CLSU32) {
                switch (tc->cls_u32->command) {
index 25642dee49d328f0ab963d03d06e507bdbfeddbc..5794d98d946f35c132f010b58368a15b5534070d 100644 (file)
@@ -1501,10 +1501,9 @@ mv643xx_eth_get_link_ksettings_phy(struct mv643xx_eth_private *mp,
                                   struct ethtool_link_ksettings *cmd)
 {
        struct net_device *dev = mp->dev;
-       int err;
        u32 supported, advertising;
 
-       err = phy_ethtool_ksettings_get(dev->phydev, cmd);
+       phy_ethtool_ksettings_get(dev->phydev, cmd);
 
        /*
         * The MAC does not support 1000baseT_Half.
@@ -1520,7 +1519,7 @@ mv643xx_eth_get_link_ksettings_phy(struct mv643xx_eth_private *mp,
        ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
                                                advertising);
 
-       return err;
+       return 0;
 }
 
 static int
index 9b875d776b296d165c4ae3a994bd527a8dafb698..fe1458450e447ffd2e8aecf2df6bea440d1a1451 100644 (file)
 /* Per-port XGMAC registers. PPv2.2 only, only for GOP port 0,
  * relative to port->base.
  */
+#define MVPP22_XLG_CTRL0_REG                   0x100
+#define      MVPP22_XLG_CTRL0_PORT_EN          BIT(0)
+#define      MVPP22_XLG_CTRL0_MAC_RESET_DIS    BIT(1)
+#define      MVPP22_XLG_CTRL0_MIB_CNT_DIS      BIT(14)
+
 #define MVPP22_XLG_CTRL3_REG                   0x11c
 #define      MVPP22_XLG_CTRL3_MACMODESELECT_MASK       (7 << 13)
 #define      MVPP22_XLG_CTRL3_MACMODESELECT_GMAC       (0 << 13)
+#define      MVPP22_XLG_CTRL3_MACMODESELECT_10G                (1 << 13)
 
 /* SMI registers. PPv2.2 only, relative to priv->iface_base. */
 #define MVPP22_SMI_MISC_CFG_REG                        0x1204
@@ -4192,7 +4198,13 @@ static void mvpp22_port_mii_set(struct mvpp2_port *port)
        if (port->gop_id == 0) {
                val = readl(port->base + MVPP22_XLG_CTRL3_REG);
                val &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK;
-               val |= MVPP22_XLG_CTRL3_MACMODESELECT_GMAC;
+
+               if (port->phy_interface == PHY_INTERFACE_MODE_XAUI ||
+                   port->phy_interface == PHY_INTERFACE_MODE_10GKR)
+                       val |= MVPP22_XLG_CTRL3_MACMODESELECT_10G;
+               else
+                       val |= MVPP22_XLG_CTRL3_MACMODESELECT_GMAC;
+
                writel(val, port->base + MVPP22_XLG_CTRL3_REG);
        }
 
@@ -4242,19 +4254,40 @@ static void mvpp2_port_enable(struct mvpp2_port *port)
 {
        u32 val;
 
-       val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
-       val |= MVPP2_GMAC_PORT_EN_MASK;
-       val |= MVPP2_GMAC_MIB_CNTR_EN_MASK;
-       writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+       /* Only GOP port 0 has an XLG MAC */
+       if (port->gop_id == 0 &&
+           (port->phy_interface == PHY_INTERFACE_MODE_XAUI ||
+            port->phy_interface == PHY_INTERFACE_MODE_10GKR)) {
+               val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+               val |= MVPP22_XLG_CTRL0_PORT_EN |
+                      MVPP22_XLG_CTRL0_MAC_RESET_DIS;
+               val &= ~MVPP22_XLG_CTRL0_MIB_CNT_DIS;
+               writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+       } else {
+               val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+               val |= MVPP2_GMAC_PORT_EN_MASK;
+               val |= MVPP2_GMAC_MIB_CNTR_EN_MASK;
+               writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+       }
 }
 
 static void mvpp2_port_disable(struct mvpp2_port *port)
 {
        u32 val;
 
-       val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
-       val &= ~(MVPP2_GMAC_PORT_EN_MASK);
-       writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+       /* Only GOP port 0 has an XLG MAC */
+       if (port->gop_id == 0 &&
+           (port->phy_interface == PHY_INTERFACE_MODE_XAUI ||
+            port->phy_interface == PHY_INTERFACE_MODE_10GKR)) {
+               val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+               val &= ~(MVPP22_XLG_CTRL0_PORT_EN |
+                        MVPP22_XLG_CTRL0_MAC_RESET_DIS);
+               writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+       } else {
+               val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+               val &= ~(MVPP2_GMAC_PORT_EN_MASK);
+               writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+       }
 }
 
 /* Set IEEE 802.3x Flow Control Xon Packet Transmission Mode */
index 16f97552ae983b6f8e9df9fb4abf956764b49d28..962975d192d10c45f348453f4954071e5c2df03a 100644 (file)
@@ -2056,7 +2056,9 @@ static int mtk_get_link_ksettings(struct net_device *ndev,
        if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
                return -EBUSY;
 
-       return phy_ethtool_ksettings_get(ndev->phydev, cmd);
+       phy_ethtool_ksettings_get(ndev->phydev, cmd);
+
+       return 0;
 }
 
 static int mtk_set_link_ksettings(struct net_device *ndev,
index 82436742ad75b011847cde250bc26f7a2d9e7175..c1de75fc399a31fc30d34b4a8ffe84a05baa7a85 100644 (file)
@@ -86,7 +86,8 @@ int mlx4_en_setup_tc(struct net_device *dev, u8 up)
        return 0;
 }
 
-static int __mlx4_en_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
+static int __mlx4_en_setup_tc(struct net_device *dev, u32 handle,
+                             u32 chain_index, __be16 proto,
                              struct tc_to_netdev *tc)
 {
        if (tc->type != TC_SETUP_MQPRIO)
index 2fd044b238750fedc61384fda55bf25206d25b51..f4b95dbd1c7f2304a87315890259865769237799 100644 (file)
@@ -623,6 +623,8 @@ struct mlx5e_tc_table {
 
        struct rhashtable_params        ht_params;
        struct rhashtable               ht;
+
+       DECLARE_HASHTABLE(mod_hdr_tbl, 8);
 };
 
 struct mlx5e_vlan_table {
index e9e33fd682796e48322b74280c86690ecd5d6ba3..b4514f2474024dc1f73a13ecd82f6d6c64378ca5 100644 (file)
@@ -723,24 +723,81 @@ static void ptys2ethtool_adver_link(unsigned long *advertising_modes,
                          __ETHTOOL_LINK_MODE_MASK_NBITS);
 }
 
-static void ptys2ethtool_supported_port(struct ethtool_link_ksettings *link_ksettings,
-                                       u32 eth_proto_cap)
+static void ptys2ethtool_supported_advertised_port(struct ethtool_link_ksettings *link_ksettings,
+                                                  u32 eth_proto_cap,
+                                                  u8 connector_type)
 {
-       if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_10GBASE_CR)
-                          | MLX5E_PROT_MASK(MLX5E_10GBASE_SR)
-                          | MLX5E_PROT_MASK(MLX5E_40GBASE_CR4)
-                          | MLX5E_PROT_MASK(MLX5E_40GBASE_SR4)
-                          | MLX5E_PROT_MASK(MLX5E_100GBASE_SR4)
-                          | MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII))) {
-               ethtool_link_ksettings_add_link_mode(link_ksettings, supported, FIBRE);
+       if (!connector_type || connector_type >= MLX5E_CONNECTOR_TYPE_NUMBER) {
+               if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_10GBASE_CR)
+                                  | MLX5E_PROT_MASK(MLX5E_10GBASE_SR)
+                                  | MLX5E_PROT_MASK(MLX5E_40GBASE_CR4)
+                                  | MLX5E_PROT_MASK(MLX5E_40GBASE_SR4)
+                                  | MLX5E_PROT_MASK(MLX5E_100GBASE_SR4)
+                                  | MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII))) {
+                       ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                            supported,
+                                                            FIBRE);
+                       ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                            advertising,
+                                                            FIBRE);
+               }
+
+               if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_100GBASE_KR4)
+                                  | MLX5E_PROT_MASK(MLX5E_40GBASE_KR4)
+                                  | MLX5E_PROT_MASK(MLX5E_10GBASE_KR)
+                                  | MLX5E_PROT_MASK(MLX5E_10GBASE_KX4)
+                                  | MLX5E_PROT_MASK(MLX5E_1000BASE_KX))) {
+                       ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                            supported,
+                                                            Backplane);
+                       ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                            advertising,
+                                                            Backplane);
+               }
+               return;
        }
 
-       if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_100GBASE_KR4)
-                          | MLX5E_PROT_MASK(MLX5E_40GBASE_KR4)
-                          | MLX5E_PROT_MASK(MLX5E_10GBASE_KR)
-                          | MLX5E_PROT_MASK(MLX5E_10GBASE_KX4)
-                          | MLX5E_PROT_MASK(MLX5E_1000BASE_KX))) {
-               ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Backplane);
+       switch (connector_type) {
+       case MLX5E_PORT_TP:
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    supported, TP);
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    advertising, TP);
+               break;
+       case MLX5E_PORT_AUI:
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    supported, AUI);
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    advertising, AUI);
+               break;
+       case MLX5E_PORT_BNC:
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    supported, BNC);
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    advertising, BNC);
+               break;
+       case MLX5E_PORT_MII:
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    supported, MII);
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    advertising, MII);
+               break;
+       case MLX5E_PORT_FIBRE:
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    supported, FIBRE);
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    advertising, FIBRE);
+               break;
+       case MLX5E_PORT_DA:
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    supported, Backplane);
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    advertising, Backplane);
+               break;
+       case MLX5E_PORT_NONE:
+       case MLX5E_PORT_OTHER:
+       default:
+               break;
        }
 }
 
@@ -791,7 +848,6 @@ static void get_supported(u32 eth_proto_cap,
 {
        unsigned long *supported = link_ksettings->link_modes.supported;
 
-       ptys2ethtool_supported_port(link_ksettings, eth_proto_cap);
        ptys2ethtool_supported_link(supported, eth_proto_cap);
        ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause);
 }
@@ -809,8 +865,23 @@ static void get_advertising(u32 eth_proto_cap, u8 tx_pause,
                ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Asym_Pause);
 }
 
-static u8 get_connector_port(u32 eth_proto)
+static int ptys2connector_type[MLX5E_CONNECTOR_TYPE_NUMBER] = {
+               [MLX5E_PORT_UNKNOWN]            = PORT_OTHER,
+               [MLX5E_PORT_NONE]               = PORT_NONE,
+               [MLX5E_PORT_TP]                 = PORT_TP,
+               [MLX5E_PORT_AUI]                = PORT_AUI,
+               [MLX5E_PORT_BNC]                = PORT_BNC,
+               [MLX5E_PORT_MII]                = PORT_MII,
+               [MLX5E_PORT_FIBRE]              = PORT_FIBRE,
+               [MLX5E_PORT_DA]                 = PORT_DA,
+               [MLX5E_PORT_OTHER]              = PORT_OTHER,
+       };
+
+static u8 get_connector_port(u32 eth_proto, u8 connector_type)
 {
+       if (connector_type && connector_type < MLX5E_CONNECTOR_TYPE_NUMBER)
+               return ptys2connector_type[connector_type];
+
        if (eth_proto & (MLX5E_PROT_MASK(MLX5E_10GBASE_SR)
                         | MLX5E_PROT_MASK(MLX5E_40GBASE_SR4)
                         | MLX5E_PROT_MASK(MLX5E_100GBASE_SR4)
@@ -856,6 +927,7 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
        u32 eth_proto_oper;
        u8 an_disable_admin;
        u8 an_status;
+       u8 connector_type;
        int err;
 
        err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, 1);
@@ -871,6 +943,7 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
        eth_proto_lp     = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise);
        an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
        an_status        = MLX5_GET(ptys_reg, out, an_status);
+       connector_type   = MLX5_GET(ptys_reg, out, connector_type);
 
        mlx5_query_port_pause(mdev, &rx_pause, &tx_pause);
 
@@ -883,7 +956,10 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
 
        eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
 
-       link_ksettings->base.port = get_connector_port(eth_proto_oper);
+       link_ksettings->base.port = get_connector_port(eth_proto_oper,
+                                                      connector_type);
+       ptys2ethtool_supported_advertised_port(link_ksettings, eth_proto_admin,
+                                              connector_type);
        get_lp_advertising(eth_proto_lp, link_ksettings);
 
        if (an_status == MLX5_AN_COMPLETE)
index cdff04b2aea19de6c32779686c953a5caedd2cdf..5afec0f4a6588b8198603ff3f890a24e617ff53a 100644 (file)
@@ -2991,13 +2991,17 @@ static int mlx5e_setup_tc(struct net_device *netdev, u8 tc)
 }
 
 static int mlx5e_ndo_setup_tc(struct net_device *dev, u32 handle,
-                             __be16 proto, struct tc_to_netdev *tc)
+                             u32 chain_index, __be16 proto,
+                             struct tc_to_netdev *tc)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
 
        if (TC_H_MAJ(handle) != TC_H_MAJ(TC_H_INGRESS))
                goto mqprio;
 
+       if (chain_index)
+               return -EOPNOTSUPP;
+
        switch (tc->type) {
        case TC_SETUP_CLSFLOWER:
                switch (tc->cls_flower->command) {
index 79462c0368a0781ca7a38354726ed628097c0c89..70c2b8d020bd6d45311c4469de058a0a9f581bf6 100644 (file)
@@ -652,7 +652,8 @@ static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
 }
 
 static int mlx5e_rep_ndo_setup_tc(struct net_device *dev, u32 handle,
-                                 __be16 proto, struct tc_to_netdev *tc)
+                                 u32 chain_index, __be16 proto,
+                                 struct tc_to_netdev *tc)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
 
@@ -664,9 +665,13 @@ static int mlx5e_rep_ndo_setup_tc(struct net_device *dev, u32 handle,
                struct net_device *uplink_dev = mlx5_eswitch_get_uplink_netdev(esw);
 
                return uplink_dev->netdev_ops->ndo_setup_tc(uplink_dev, handle,
+                                                           chain_index,
                                                            proto, tc);
        }
 
+       if (chain_index)
+               return -EOPNOTSUPP;
+
        switch (tc->type) {
        case TC_SETUP_CLSFLOWER:
                switch (tc->cls_flower->command) {
index 8ec13f9be66014098332db1b76198f9fa3bd5508..f5afacfbe914c98fada5833f3471681420c5ea4f 100644 (file)
@@ -69,7 +69,8 @@ struct mlx5e_tc_flow {
        u64                     cookie;
        u8                      flags;
        struct mlx5_flow_handle *rule;
-       struct list_head        encap; /* flows sharing the same encap */
+       struct list_head        encap;   /* flows sharing the same encap ID */
+       struct list_head        mod_hdr; /* flows sharing the same mod hdr ID */
        union {
                struct mlx5_esw_flow_attr esw_attr[0];
                struct mlx5_nic_flow_attr nic_attr[0];
@@ -90,6 +91,135 @@ enum {
 #define MLX5E_TC_TABLE_NUM_ENTRIES 1024
 #define MLX5E_TC_TABLE_NUM_GROUPS 4
 
+struct mod_hdr_key {
+       int num_actions;
+       void *actions;
+};
+
+struct mlx5e_mod_hdr_entry {
+       /* a node of a hash table which keeps all the mod_hdr entries */
+       struct hlist_node mod_hdr_hlist;
+
+       /* flows sharing the same mod_hdr entry */
+       struct list_head flows;
+
+       struct mod_hdr_key key;
+
+       u32 mod_hdr_id;
+};
+
+#define MLX5_MH_ACT_SZ MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto)
+
+static inline u32 hash_mod_hdr_info(struct mod_hdr_key *key)
+{
+       return jhash(key->actions,
+                    key->num_actions * MLX5_MH_ACT_SZ, 0);
+}
+
+static inline int cmp_mod_hdr_info(struct mod_hdr_key *a,
+                                  struct mod_hdr_key *b)
+{
+       if (a->num_actions != b->num_actions)
+               return 1;
+
+       return memcmp(a->actions, b->actions, a->num_actions * MLX5_MH_ACT_SZ);
+}
+
+static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv,
+                               struct mlx5e_tc_flow *flow,
+                               struct mlx5e_tc_flow_parse_attr *parse_attr)
+{
+       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+       int num_actions, actions_size, namespace, err;
+       struct mlx5e_mod_hdr_entry *mh;
+       struct mod_hdr_key key;
+       bool found = false;
+       u32 hash_key;
+
+       num_actions  = parse_attr->num_mod_hdr_actions;
+       actions_size = MLX5_MH_ACT_SZ * num_actions;
+
+       key.actions = parse_attr->mod_hdr_actions;
+       key.num_actions = num_actions;
+
+       hash_key = hash_mod_hdr_info(&key);
+
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
+               namespace = MLX5_FLOW_NAMESPACE_FDB;
+               hash_for_each_possible(esw->offloads.mod_hdr_tbl, mh,
+                                      mod_hdr_hlist, hash_key) {
+                       if (!cmp_mod_hdr_info(&mh->key, &key)) {
+                               found = true;
+                               break;
+                       }
+               }
+       } else {
+               namespace = MLX5_FLOW_NAMESPACE_KERNEL;
+               hash_for_each_possible(priv->fs.tc.mod_hdr_tbl, mh,
+                                      mod_hdr_hlist, hash_key) {
+                       if (!cmp_mod_hdr_info(&mh->key, &key)) {
+                               found = true;
+                               break;
+                       }
+               }
+       }
+
+       if (found)
+               goto attach_flow;
+
+       mh = kzalloc(sizeof(*mh) + actions_size, GFP_KERNEL);
+       if (!mh)
+               return -ENOMEM;
+
+       mh->key.actions = (void *)mh + sizeof(*mh);
+       memcpy(mh->key.actions, key.actions, actions_size);
+       mh->key.num_actions = num_actions;
+       INIT_LIST_HEAD(&mh->flows);
+
+       err = mlx5_modify_header_alloc(priv->mdev, namespace,
+                                      mh->key.num_actions,
+                                      mh->key.actions,
+                                      &mh->mod_hdr_id);
+       if (err)
+               goto out_err;
+
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
+               hash_add(esw->offloads.mod_hdr_tbl, &mh->mod_hdr_hlist, hash_key);
+       else
+               hash_add(priv->fs.tc.mod_hdr_tbl, &mh->mod_hdr_hlist, hash_key);
+
+attach_flow:
+       list_add(&flow->mod_hdr, &mh->flows);
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
+               flow->esw_attr->mod_hdr_id = mh->mod_hdr_id;
+       else
+               flow->nic_attr->mod_hdr_id = mh->mod_hdr_id;
+
+       return 0;
+
+out_err:
+       kfree(mh);
+       return err;
+}
+
+static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv,
+                                struct mlx5e_tc_flow *flow)
+{
+       struct list_head *next = flow->mod_hdr.next;
+
+       list_del(&flow->mod_hdr);
+
+       if (list_empty(next)) {
+               struct mlx5e_mod_hdr_entry *mh;
+
+               mh = list_entry(next, struct mlx5e_mod_hdr_entry, flows);
+
+               mlx5_modify_header_dealloc(priv->mdev, mh->mod_hdr_id);
+               hash_del(&mh->mod_hdr_hlist);
+               kfree(mh);
+       }
+}
+
 static struct mlx5_flow_handle *
 mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
                      struct mlx5e_tc_flow_parse_attr *parse_attr,
@@ -121,10 +251,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
        }
 
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
-               err = mlx5_modify_header_alloc(dev, MLX5_FLOW_NAMESPACE_KERNEL,
-                                              parse_attr->num_mod_hdr_actions,
-                                              parse_attr->mod_hdr_actions,
-                                              &attr->mod_hdr_id);
+               err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
                flow_act.modify_id = attr->mod_hdr_id;
                kfree(parse_attr->mod_hdr_actions);
                if (err) {
@@ -166,8 +293,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
        }
 err_create_ft:
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
-               mlx5_modify_header_dealloc(priv->mdev,
-                                          attr->mod_hdr_id);
+               mlx5e_detach_mod_hdr(priv, flow);
 err_create_mod_hdr_id:
        mlx5_fc_destroy(dev, counter);
 
@@ -177,6 +303,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
 static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
                                  struct mlx5e_tc_flow *flow)
 {
+       struct mlx5_nic_flow_attr *attr = flow->nic_attr;
        struct mlx5_fc *counter = NULL;
 
        counter = mlx5_flow_rule_counter(flow->rule);
@@ -188,9 +315,8 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
                priv->fs.tc.t = NULL;
        }
 
-       if (flow->nic_attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
-               mlx5_modify_header_dealloc(priv->mdev,
-                                          flow->nic_attr->mod_hdr_id);
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
+               mlx5e_detach_mod_hdr(priv, flow);
 }
 
 static void mlx5e_detach_encap(struct mlx5e_priv *priv,
@@ -213,10 +339,7 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
        }
 
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
-               err = mlx5_modify_header_alloc(priv->mdev, MLX5_FLOW_NAMESPACE_FDB,
-                                              parse_attr->num_mod_hdr_actions,
-                                              parse_attr->mod_hdr_actions,
-                                              &attr->mod_hdr_id);
+               err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
                kfree(parse_attr->mod_hdr_actions);
                if (err) {
                        rule = ERR_PTR(err);
@@ -231,9 +354,8 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
        return rule;
 
 err_add_rule:
-       if (flow->esw_attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
-               mlx5_modify_header_dealloc(priv->mdev,
-                                          attr->mod_hdr_id);
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
+               mlx5e_detach_mod_hdr(priv, flow);
 err_mod_hdr:
        mlx5_eswitch_del_vlan_action(esw, attr);
 err_add_vlan:
@@ -250,19 +372,18 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
 
        if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
                flow->flags &= ~MLX5E_TC_FLOW_OFFLOADED;
-               mlx5_eswitch_del_offloaded_rule(esw, flow->rule, flow->esw_attr);
+               mlx5_eswitch_del_offloaded_rule(esw, flow->rule, attr);
        }
 
-       mlx5_eswitch_del_vlan_action(esw, flow->esw_attr);
+       mlx5_eswitch_del_vlan_action(esw, attr);
 
-       if (flow->esw_attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP) {
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP) {
                mlx5e_detach_encap(priv, flow);
-               kvfree(flow->esw_attr->parse_attr);
+               kvfree(attr->parse_attr);
        }
 
-       if (flow->esw_attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
-               mlx5_modify_header_dealloc(priv->mdev,
-                                          attr->mod_hdr_id);
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
+               mlx5e_detach_mod_hdr(priv, flow);
 }
 
 void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
@@ -970,12 +1091,14 @@ static int offload_pedit_fields(struct pedit_headers *masks,
                                struct mlx5e_tc_flow_parse_attr *parse_attr)
 {
        struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals;
-       int i, action_size, nactions, max_actions, first, last, first_z;
+       int i, action_size, nactions, max_actions, first, last, next_z;
        void *s_masks_p, *a_masks_p, *vals_p;
        struct mlx5_fields *f;
        u8 cmd, field_bsize;
        u32 s_mask, a_mask;
        unsigned long mask;
+       __be32 mask_be32;
+       __be16 mask_be16;
        void *action;
 
        set_masks = &masks[TCA_PEDIT_KEY_EX_CMD_SET];
@@ -1029,11 +1152,19 @@ static int offload_pedit_fields(struct pedit_headers *masks,
 
                field_bsize = f->size * BITS_PER_BYTE;
 
-               first_z = find_first_zero_bit(&mask, field_bsize);
+               if (field_bsize == 32) {
+                       mask_be32 = *(__be32 *)&mask;
+                       mask = (__force unsigned long)cpu_to_le32(be32_to_cpu(mask_be32));
+               } else if (field_bsize == 16) {
+                       mask_be16 = *(__be16 *)&mask;
+                       mask = (__force unsigned long)cpu_to_le16(be16_to_cpu(mask_be16));
+               }
+
                first = find_first_bit(&mask, field_bsize);
+               next_z = find_next_zero_bit(&mask, field_bsize, first);
                last  = find_last_bit(&mask, field_bsize);
-               if (first > 0 || last != (field_bsize - 1) || first_z < last) {
-                       printk(KERN_WARNING "mlx5: partial rewrite (mask %lx) is currently not offloaded\n",
+               if (first < next_z && next_z < last) {
+                       printk(KERN_WARNING "mlx5: rewrite of few sub-fields (mask %lx) isn't offloaded\n",
                               mask);
                        return -EOPNOTSUPP;
                }
@@ -1042,17 +1173,17 @@ static int offload_pedit_fields(struct pedit_headers *masks,
                MLX5_SET(set_action_in, action, field, f->field);
 
                if (cmd == MLX5_ACTION_TYPE_SET) {
-                       MLX5_SET(set_action_in, action, offset, 0);
+                       MLX5_SET(set_action_in, action, offset, first);
                        /* length is num of bits to be written, zero means length of 32 */
-                       MLX5_SET(set_action_in, action, length, field_bsize);
+                       MLX5_SET(set_action_in, action, length, (last - first + 1));
                }
 
                if (field_bsize == 32)
-                       MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p));
+                       MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p) >> first);
                else if (field_bsize == 16)
-                       MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p));
+                       MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p) >> first);
                else if (field_bsize == 8)
-                       MLX5_SET(set_action_in, action, data, *(u8 *)vals_p);
+                       MLX5_SET(set_action_in, action, data, *(u8 *)vals_p >> first);
 
                action += action_size;
                nactions++;
@@ -1194,10 +1325,6 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
 
        tcf_exts_to_list(exts, &actions);
        list_for_each_entry(a, &actions, list) {
-               /* Only support a single action per rule */
-               if (attr->action)
-                       return -EINVAL;
-
                if (is_tcf_gact_shot(a)) {
                        attr->action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
                        if (MLX5_CAP_FLOWTABLE(priv->mdev,
@@ -1942,6 +2069,8 @@ int mlx5e_tc_init(struct mlx5e_priv *priv)
 {
        struct mlx5e_tc_table *tc = &priv->fs.tc;
 
+       hash_init(tc->mod_hdr_tbl);
+
        tc->ht_params = mlx5e_tc_flow_ht_params;
        return rhashtable_init(&tc->ht, &tc->ht_params);
 }
index 81dfcd90b1f54b5430518080040801a63c63278e..37927156f258cb50cb29f0ea4d23a559b4f8a81f 100644 (file)
@@ -1769,6 +1769,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
        }
 
        hash_init(esw->offloads.encap_tbl);
+       hash_init(esw->offloads.mod_hdr_tbl);
        mutex_init(&esw->state_lock);
 
        for (vport_num = 0; vport_num < total_vports; vport_num++) {
index b746f62c8c79b17a64c0923665917170a075092a..834a33050969719ca6e13b27c11b6eb895c02257 100644 (file)
@@ -207,6 +207,7 @@ struct mlx5_esw_offload {
        struct mlx5_flow_group *vport_rx_group;
        struct mlx5_eswitch_rep *vport_reps;
        DECLARE_HASHTABLE(encap_tbl, 8);
+       DECLARE_HASHTABLE(mod_hdr_tbl, 8);
        u8 inline_mode;
        u64 num_flows;
        u8 encap;
index abb44a268563e4b12577278e62b34e7c553d594e..e750f07793b829de4b0383f93770f301e20eb196 100644 (file)
@@ -78,28 +78,33 @@ int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
                 MLX5_CMD_OP_CREATE_FLOW_TABLE);
 
        MLX5_SET(create_flow_table_in, in, table_type, type);
-       MLX5_SET(create_flow_table_in, in, level, level);
-       MLX5_SET(create_flow_table_in, in, log_size, log_size);
+       MLX5_SET(create_flow_table_in, in, flow_table_context.level, level);
+       MLX5_SET(create_flow_table_in, in, flow_table_context.log_size, log_size);
        if (vport) {
                MLX5_SET(create_flow_table_in, in, vport_number, vport);
                MLX5_SET(create_flow_table_in, in, other_vport, 1);
        }
 
-       MLX5_SET(create_flow_table_in, in, decap_en, en_encap_decap);
-       MLX5_SET(create_flow_table_in, in, encap_en, en_encap_decap);
+       MLX5_SET(create_flow_table_in, in, flow_table_context.decap_en,
+                en_encap_decap);
+       MLX5_SET(create_flow_table_in, in, flow_table_context.encap_en,
+                en_encap_decap);
 
        switch (op_mod) {
        case FS_FT_OP_MOD_NORMAL:
                if (next_ft) {
-                       MLX5_SET(create_flow_table_in, in, table_miss_mode, 1);
-                       MLX5_SET(create_flow_table_in, in, table_miss_id, next_ft->id);
+                       MLX5_SET(create_flow_table_in, in,
+                                flow_table_context.table_miss_action, 1);
+                       MLX5_SET(create_flow_table_in, in,
+                                flow_table_context.table_miss_id, next_ft->id);
                }
                break;
 
        case FS_FT_OP_MOD_LAG_DEMUX:
                MLX5_SET(create_flow_table_in, in, op_mod, 0x1);
                if (next_ft)
-                       MLX5_SET(create_flow_table_in, in, lag_master_next_table_id,
+                       MLX5_SET(create_flow_table_in, in,
+                                flow_table_context.lag_master_next_table_id,
                                 next_ft->id);
                break;
        }
@@ -146,10 +151,10 @@ int mlx5_cmd_modify_flow_table(struct mlx5_core_dev *dev,
                         MLX5_MODIFY_FLOW_TABLE_LAG_NEXT_TABLE_ID);
                if (next_ft) {
                        MLX5_SET(modify_flow_table_in, in,
-                                lag_master_next_table_id, next_ft->id);
+                                flow_table_context.lag_master_next_table_id, next_ft->id);
                } else {
                        MLX5_SET(modify_flow_table_in, in,
-                                lag_master_next_table_id, 0);
+                                flow_table_context.lag_master_next_table_id, 0);
                }
        } else {
                if (ft->vport) {
@@ -160,11 +165,14 @@ int mlx5_cmd_modify_flow_table(struct mlx5_core_dev *dev,
                MLX5_SET(modify_flow_table_in, in, modify_field_select,
                         MLX5_MODIFY_FLOW_TABLE_MISS_TABLE_ID);
                if (next_ft) {
-                       MLX5_SET(modify_flow_table_in, in, table_miss_mode, 1);
-                       MLX5_SET(modify_flow_table_in, in, table_miss_id,
+                       MLX5_SET(modify_flow_table_in, in,
+                                flow_table_context.table_miss_action, 1);
+                       MLX5_SET(modify_flow_table_in, in,
+                                flow_table_context.table_miss_id,
                                 next_ft->id);
                } else {
-                       MLX5_SET(modify_flow_table_in, in, table_miss_mode, 0);
+                       MLX5_SET(modify_flow_table_in, in,
+                                flow_table_context.table_miss_action, 0);
                }
        }
 
index f60e2ba515d030b283047dc3ba49408816dd6444..0e51c3693243539de1b7bf973db78a036e0bbf99 100644 (file)
@@ -860,21 +860,13 @@ static int mlxsw_sp_port_mtu_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu)
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmtu), pmtu_pl);
 }
 
-static int __mlxsw_sp_port_swid_set(struct mlxsw_sp *mlxsw_sp, u8 local_port,
-                                   u8 swid)
-{
-       char pspa_pl[MLXSW_REG_PSPA_LEN];
-
-       mlxsw_reg_pspa_pack(pspa_pl, swid, local_port);
-       return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pspa), pspa_pl);
-}
-
 static int mlxsw_sp_port_swid_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 swid)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+       char pspa_pl[MLXSW_REG_PSPA_LEN];
 
-       return __mlxsw_sp_port_swid_set(mlxsw_sp, mlxsw_sp_port->local_port,
-                                       swid);
+       mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sp_port->local_port);
+       return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pspa), pspa_pl);
 }
 
 int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable)
@@ -975,13 +967,14 @@ static int mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp,
        return 0;
 }
 
-static int mlxsw_sp_port_module_map(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+static int mlxsw_sp_port_module_map(struct mlxsw_sp_port *mlxsw_sp_port,
                                    u8 module, u8 width, u8 lane)
 {
+       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        char pmlp_pl[MLXSW_REG_PMLP_LEN];
        int i;
 
-       mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
+       mlxsw_reg_pmlp_pack(pmlp_pl, mlxsw_sp_port->local_port);
        mlxsw_reg_pmlp_width_set(pmlp_pl, width);
        for (i = 0; i < width; i++) {
                mlxsw_reg_pmlp_module_set(pmlp_pl, i, module);
@@ -991,11 +984,12 @@ static int mlxsw_sp_port_module_map(struct mlxsw_sp *mlxsw_sp, u8 local_port,
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl);
 }
 
-static int mlxsw_sp_port_module_unmap(struct mlxsw_sp *mlxsw_sp, u8 local_port)
+static int mlxsw_sp_port_module_unmap(struct mlxsw_sp_port *mlxsw_sp_port)
 {
+       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        char pmlp_pl[MLXSW_REG_PMLP_LEN];
 
-       mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
+       mlxsw_reg_pmlp_pack(pmlp_pl, mlxsw_sp_port->local_port);
        mlxsw_reg_pmlp_width_set(pmlp_pl, 0);
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl);
 }
@@ -1699,11 +1693,15 @@ static void mlxsw_sp_port_del_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
 }
 
 static int mlxsw_sp_setup_tc(struct net_device *dev, u32 handle,
-                            __be16 proto, struct tc_to_netdev *tc)
+                            u32 chain_index, __be16 proto,
+                            struct tc_to_netdev *tc)
 {
        struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
        bool ingress = TC_H_MAJ(handle) == TC_H_MAJ(TC_H_INGRESS);
 
+       if (chain_index)
+               return -EOPNOTSUPP;
+
        switch (tc->type) {
        case TC_SETUP_MATCHALL:
                switch (tc->cls_mall->command) {
@@ -1752,12 +1750,6 @@ static const struct net_device_ops mlxsw_sp_port_netdev_ops = {
        .ndo_get_offload_stats  = mlxsw_sp_port_get_offload_stats,
        .ndo_vlan_rx_add_vid    = mlxsw_sp_port_add_vid,
        .ndo_vlan_rx_kill_vid   = mlxsw_sp_port_kill_vid,
-       .ndo_fdb_add            = switchdev_port_fdb_add,
-       .ndo_fdb_del            = switchdev_port_fdb_del,
-       .ndo_fdb_dump           = switchdev_port_fdb_dump,
-       .ndo_bridge_setlink     = switchdev_port_bridge_setlink,
-       .ndo_bridge_getlink     = switchdev_port_bridge_getlink,
-       .ndo_bridge_dellink     = switchdev_port_bridge_dellink,
        .ndo_get_phys_port_name = mlxsw_sp_port_get_phys_port_name,
 };
 
@@ -2657,17 +2649,26 @@ static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port)
        return 0;
 }
 
-static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
-                                 bool split, u8 module, u8 width, u8 lane)
+static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+                               bool split, u8 module, u8 width, u8 lane)
 {
        struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
        struct mlxsw_sp_port *mlxsw_sp_port;
        struct net_device *dev;
        int err;
 
+       err = mlxsw_core_port_init(mlxsw_sp->core, local_port);
+       if (err) {
+               dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n",
+                       local_port);
+               return err;
+       }
+
        dev = alloc_etherdev(sizeof(struct mlxsw_sp_port));
-       if (!dev)
-               return -ENOMEM;
+       if (!dev) {
+               err = -ENOMEM;
+               goto err_alloc_etherdev;
+       }
        SET_NETDEV_DEV(dev, mlxsw_sp->bus_info->dev);
        mlxsw_sp_port = netdev_priv(dev);
        mlxsw_sp_port->dev = dev;
@@ -2709,6 +2710,13 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
        dev->netdev_ops = &mlxsw_sp_port_netdev_ops;
        dev->ethtool_ops = &mlxsw_sp_port_ethtool_ops;
 
+       err = mlxsw_sp_port_module_map(mlxsw_sp_port, module, width, lane);
+       if (err) {
+               dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to map module\n",
+                       mlxsw_sp_port->local_port);
+               goto err_port_module_map;
+       }
+
        err = mlxsw_sp_port_swid_set(mlxsw_sp_port, 0);
        if (err) {
                dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set SWID\n",
@@ -2831,6 +2839,8 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 err_dev_addr_init:
        mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT);
 err_port_swid_set:
+       mlxsw_sp_port_module_unmap(mlxsw_sp_port);
+err_port_module_map:
        kfree(mlxsw_sp_port->hw_stats.cache);
 err_alloc_hw_stats:
        kfree(mlxsw_sp_port->sample);
@@ -2838,32 +2848,12 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
        free_percpu(mlxsw_sp_port->pcpu_stats);
 err_alloc_stats:
        free_netdev(dev);
-       return err;
-}
-
-static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
-                               bool split, u8 module, u8 width, u8 lane)
-{
-       int err;
-
-       err = mlxsw_core_port_init(mlxsw_sp->core, local_port);
-       if (err) {
-               dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n",
-                       local_port);
-               return err;
-       }
-       err = __mlxsw_sp_port_create(mlxsw_sp, local_port, split,
-                                    module, width, lane);
-       if (err)
-               goto err_port_create;
-       return 0;
-
-err_port_create:
+err_alloc_etherdev:
        mlxsw_core_port_fini(mlxsw_sp->core, local_port);
        return err;
 }
 
-static void __mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
+static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
 {
        struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
 
@@ -2876,17 +2866,12 @@ static void __mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
        mlxsw_sp_port_fids_fini(mlxsw_sp_port);
        mlxsw_sp_port_dcb_fini(mlxsw_sp_port);
        mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT);
-       mlxsw_sp_port_module_unmap(mlxsw_sp, mlxsw_sp_port->local_port);
+       mlxsw_sp_port_module_unmap(mlxsw_sp_port);
        kfree(mlxsw_sp_port->hw_stats.cache);
        kfree(mlxsw_sp_port->sample);
        free_percpu(mlxsw_sp_port->pcpu_stats);
        WARN_ON_ONCE(!list_empty(&mlxsw_sp_port->vlans_list));
        free_netdev(mlxsw_sp_port->dev);
-}
-
-static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
-{
-       __mlxsw_sp_port_remove(mlxsw_sp, local_port);
        mlxsw_core_port_fini(mlxsw_sp->core, local_port);
 }
 
@@ -2964,19 +2949,6 @@ static int mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, u8 base_port,
        u8 width = MLXSW_PORT_MODULE_MAX_WIDTH / count;
        int err, i;
 
-       for (i = 0; i < count; i++) {
-               err = mlxsw_sp_port_module_map(mlxsw_sp, base_port + i, module,
-                                              width, i * width);
-               if (err)
-                       goto err_port_module_map;
-       }
-
-       for (i = 0; i < count; i++) {
-               err = __mlxsw_sp_port_swid_set(mlxsw_sp, base_port + i, 0);
-               if (err)
-                       goto err_port_swid_set;
-       }
-
        for (i = 0; i < count; i++) {
                err = mlxsw_sp_port_create(mlxsw_sp, base_port + i, true,
                                           module, width, i * width);
@@ -2990,15 +2962,6 @@ static int mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, u8 base_port,
        for (i--; i >= 0; i--)
                if (mlxsw_sp_port_created(mlxsw_sp, base_port + i))
                        mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
-       i = count;
-err_port_swid_set:
-       for (i--; i >= 0; i--)
-               __mlxsw_sp_port_swid_set(mlxsw_sp, base_port + i,
-                                        MLXSW_PORT_SWID_DISABLED_PORT);
-       i = count;
-err_port_module_map:
-       for (i--; i >= 0; i--)
-               mlxsw_sp_port_module_unmap(mlxsw_sp, base_port + i);
        return err;
 }
 
@@ -3013,17 +2976,6 @@ static void mlxsw_sp_port_unsplit_create(struct mlxsw_sp *mlxsw_sp,
         */
        count = count / 2;
 
-       for (i = 0; i < count; i++) {
-               local_port = base_port + i * 2;
-               module = mlxsw_sp->port_to_module[local_port];
-
-               mlxsw_sp_port_module_map(mlxsw_sp, local_port, module, width,
-                                        0);
-       }
-
-       for (i = 0; i < count; i++)
-               __mlxsw_sp_port_swid_set(mlxsw_sp, base_port + i * 2, 0);
-
        for (i = 0; i < count; i++) {
                local_port = base_port + i * 2;
                module = mlxsw_sp->port_to_module[local_port];
@@ -3705,7 +3657,7 @@ struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev)
        return mlxsw_sp_port ? mlxsw_sp_port->mlxsw_sp : NULL;
 }
 
-static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev)
+struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev)
 {
        struct mlxsw_sp_port *mlxsw_sp_port;
 
index 4a7a39a9f1a13d3770d2b4fb05c1f7af3393c311..5ef98d4d0ab6c8d3fa36781a72cd954bea26fe59 100644 (file)
@@ -361,6 +361,7 @@ struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev);
 struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev);
 struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev);
 void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port);
+struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev);
 
 /* spectrum_dcb.c */
 #ifdef CONFIG_MLXSW_SPECTRUM_DCB
index 20061058801ecee066a144e7c5cb0ab86e1a68c7..700cc8c6aa5be69c9c6135c0572259434143955e 100644 (file)
@@ -591,7 +591,7 @@ static int mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
        return 0;
 }
 
-#define MLXSW_SP_LPM_TREE_MIN 2 /* trees 0 and 1 are reserved */
+#define MLXSW_SP_LPM_TREE_MIN 1 /* tree 0 is reserved */
 
 static int mlxsw_sp_lpm_init(struct mlxsw_sp *mlxsw_sp)
 {
index edcc273d7597677cb04a34612da9f1554a2b6200..cd89a3e6cd8184c1b80037b8a86e3dc3bc0e3a6d 100644 (file)
@@ -102,8 +102,6 @@ struct mlxsw_sp_bridge_vlan {
        struct list_head list;
        struct list_head port_vlan_list;
        u16 vid;
-       u8 egress_untagged:1,
-          pvid:1;
 };
 
 struct mlxsw_sp_bridge_ops {
@@ -456,6 +454,9 @@ static int mlxsw_sp_port_attr_get(struct net_device *dev,
                mlxsw_sp_port_bridge_flags_get(mlxsw_sp->bridge, attr->orig_dev,
                                               &attr->u.brport_flags);
                break;
+       case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
+               attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD;
+               break;
        default:
                return -EOPNOTSUPP;
        }
@@ -1000,8 +1001,6 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
                goto err_port_vlan_bridge_join;
 
        bridge_vlan = mlxsw_sp_bridge_vlan_find(bridge_port, vid);
-       bridge_vlan->egress_untagged = is_untagged;
-       bridge_vlan->pvid = is_pvid;
 
        return 0;
 
@@ -1142,44 +1141,40 @@ static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id,
 }
 
 static int
-mlxsw_sp_port_fdb_static_add(struct mlxsw_sp_port *mlxsw_sp_port,
-                            const struct switchdev_obj_port_fdb *fdb,
-                            struct switchdev_trans *trans)
+mlxsw_sp_port_fdb_set(struct mlxsw_sp_port *mlxsw_sp_port,
+                     struct switchdev_notifier_fdb_info *fdb_info, bool adding)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-       struct net_device *orig_dev = fdb->obj.orig_dev;
+       struct net_device *orig_dev = fdb_info->info.dev;
        struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
        struct mlxsw_sp_bridge_device *bridge_device;
        struct mlxsw_sp_bridge_port *bridge_port;
        u16 fid_index, vid;
 
-       if (switchdev_trans_ph_prepare(trans))
-               return 0;
-
        bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
-       if (WARN_ON(!bridge_port))
+       if (!bridge_port)
                return -EINVAL;
 
        bridge_device = bridge_port->bridge_device;
        mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_bridge(mlxsw_sp_port,
                                                               bridge_device,
-                                                              fdb->vid);
+                                                              fdb_info->vid);
        if (!mlxsw_sp_port_vlan)
                return 0;
 
        fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid);
        vid = mlxsw_sp_port_vlan->vid;
 
-       if (!mlxsw_sp_port->lagged)
+       if (!bridge_port->lagged)
                return mlxsw_sp_port_fdb_uc_op(mlxsw_sp,
-                                              mlxsw_sp_port->local_port,
-                                              fdb->addr, fid_index, true,
-                                              false);
+                                              bridge_port->system_port,
+                                              fdb_info->addr, fid_index,
+                                              adding, false);
        else
                return mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp,
-                                                  mlxsw_sp_port->lag_id,
-                                                  fdb->addr, fid_index, vid,
-                                                  true, false);
+                                                  bridge_port->lag_id,
+                                                  fdb_info->addr, fid_index,
+                                                  vid, adding, false);
 }
 
 static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr,
@@ -1349,11 +1344,6 @@ static int mlxsw_sp_port_obj_add(struct net_device *dev,
                                              SWITCHDEV_OBJ_PORT_VLAN(obj),
                                              trans);
                break;
-       case SWITCHDEV_OBJ_ID_PORT_FDB:
-               err = mlxsw_sp_port_fdb_static_add(mlxsw_sp_port,
-                                                  SWITCHDEV_OBJ_PORT_FDB(obj),
-                                                  trans);
-               break;
        case SWITCHDEV_OBJ_ID_PORT_MDB:
                err = mlxsw_sp_port_mdb_add(mlxsw_sp_port,
                                            SWITCHDEV_OBJ_PORT_MDB(obj),
@@ -1405,43 +1395,6 @@ static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
        return 0;
 }
 
-static int
-mlxsw_sp_port_fdb_static_del(struct mlxsw_sp_port *mlxsw_sp_port,
-                            const struct switchdev_obj_port_fdb *fdb)
-{
-       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-       struct net_device *orig_dev = fdb->obj.orig_dev;
-       struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
-       struct mlxsw_sp_bridge_device *bridge_device;
-       struct mlxsw_sp_bridge_port *bridge_port;
-       u16 fid_index, vid;
-
-       bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
-       if (WARN_ON(!bridge_port))
-               return -EINVAL;
-
-       bridge_device = bridge_port->bridge_device;
-       mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_bridge(mlxsw_sp_port,
-                                                              bridge_device,
-                                                              fdb->vid);
-       if (!mlxsw_sp_port_vlan)
-               return 0;
-
-       fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid);
-       vid = mlxsw_sp_port_vlan->vid;
-
-       if (!mlxsw_sp_port->lagged)
-               return mlxsw_sp_port_fdb_uc_op(mlxsw_sp,
-                                              mlxsw_sp_port->local_port,
-                                              fdb->addr, fid_index, false,
-                                              false);
-       else
-               return mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp,
-                                                  mlxsw_sp_port->lag_id,
-                                                  fdb->addr, fid_index, vid,
-                                                  false, false);
-}
-
 static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
                                 const struct switchdev_obj_port_mdb *mdb)
 {
@@ -1501,10 +1454,6 @@ static int mlxsw_sp_port_obj_del(struct net_device *dev,
                err = mlxsw_sp_port_vlans_del(mlxsw_sp_port,
                                              SWITCHDEV_OBJ_PORT_VLAN(obj));
                break;
-       case SWITCHDEV_OBJ_ID_PORT_FDB:
-               err = mlxsw_sp_port_fdb_static_del(mlxsw_sp_port,
-                                                  SWITCHDEV_OBJ_PORT_FDB(obj));
-               break;
        case SWITCHDEV_OBJ_ID_PORT_MDB:
                err = mlxsw_sp_port_mdb_del(mlxsw_sp_port,
                                            SWITCHDEV_OBJ_PORT_MDB(obj));
@@ -1534,161 +1483,11 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp,
        return NULL;
 }
 
-static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port,
-                                 struct switchdev_obj_port_fdb *fdb,
-                                 switchdev_obj_dump_cb_t *cb)
-{
-       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-       struct net_device *orig_dev = fdb->obj.orig_dev;
-       struct mlxsw_sp_bridge_port *bridge_port;
-       u16 lag_id, fid_index;
-       char mac[ETH_ALEN];
-       int stored_err = 0;
-       char *sfd_pl;
-       u8 num_rec;
-       int err;
-
-       bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
-       if (!bridge_port)
-               return 0;
-
-       sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
-       if (!sfd_pl)
-               return -ENOMEM;
-
-       mlxsw_reg_sfd_pack(sfd_pl, MLXSW_REG_SFD_OP_QUERY_DUMP, 0);
-       do {
-               struct mlxsw_sp_port *tmp;
-               u8 local_port;
-               int i;
-
-               mlxsw_reg_sfd_num_rec_set(sfd_pl, MLXSW_REG_SFD_REC_MAX_COUNT);
-               err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
-               if (err)
-                       goto out;
-
-               num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
-
-               /* Even in case of error, we have to run the dump to the end
-                * so the session in firmware is finished.
-                */
-               if (stored_err)
-                       continue;
-
-               for (i = 0; i < num_rec; i++) {
-                       switch (mlxsw_reg_sfd_rec_type_get(sfd_pl, i)) {
-                       case MLXSW_REG_SFD_REC_TYPE_UNICAST:
-                               mlxsw_reg_sfd_uc_unpack(sfd_pl, i, mac,
-                                                       &fid_index,
-                                                       &local_port);
-                               if (bridge_port->lagged)
-                                       continue;
-                               if (bridge_port->system_port != local_port)
-                                       continue;
-                               if (bridge_port->bridge_device->vlan_enabled)
-                                       fdb->vid = fid_index;
-                               else
-                                       fdb->vid = 0;
-                               ether_addr_copy(fdb->addr, mac);
-                               fdb->ndm_state = NUD_REACHABLE;
-                               err = cb(&fdb->obj);
-                               if (err)
-                                       stored_err = err;
-                               break;
-                       case MLXSW_REG_SFD_REC_TYPE_UNICAST_LAG:
-                               mlxsw_reg_sfd_uc_lag_unpack(sfd_pl, i,
-                                                           mac, &fid_index,
-                                                           &lag_id);
-                               if (!bridge_port->lagged)
-                                       continue;
-                               if (bridge_port->lag_id != lag_id)
-                                       continue;
-                               tmp = mlxsw_sp_lag_rep_port(mlxsw_sp, lag_id);
-                               if (tmp->local_port !=
-                                   mlxsw_sp_port->local_port)
-                                       continue;
-                               if (bridge_port->bridge_device->vlan_enabled)
-                                       fdb->vid = fid_index;
-                               else
-                                       fdb->vid = 0;
-                               ether_addr_copy(fdb->addr, mac);
-                               fdb->ndm_state = NUD_REACHABLE;
-                               err = cb(&fdb->obj);
-                               if (err)
-                                       stored_err = err;
-                               break;
-                       }
-               }
-       } while (num_rec == MLXSW_REG_SFD_REC_MAX_COUNT);
-
-out:
-       kfree(sfd_pl);
-       return stored_err ? stored_err : err;
-}
-
-static int mlxsw_sp_port_vlan_dump(struct mlxsw_sp_port *mlxsw_sp_port,
-                                  struct switchdev_obj_port_vlan *vlan,
-                                  switchdev_obj_dump_cb_t *cb)
-{
-       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-       struct net_device *orig_dev = vlan->obj.orig_dev;
-       struct mlxsw_sp_bridge_port *bridge_port;
-       struct mlxsw_sp_bridge_vlan *bridge_vlan;
-       int err = 0;
-
-       bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
-       if (WARN_ON(!bridge_port))
-               return -EINVAL;
-
-       if (!bridge_port->bridge_device->vlan_enabled)
-               return 0;
-
-       list_for_each_entry(bridge_vlan, &bridge_port->vlans_list, list) {
-               vlan->flags = 0;
-               if (bridge_vlan->pvid)
-                       vlan->flags |= BRIDGE_VLAN_INFO_PVID;
-               if (bridge_vlan->egress_untagged)
-                       vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
-               vlan->vid_begin = bridge_vlan->vid;
-               vlan->vid_end = bridge_vlan->vid;
-               err = cb(&vlan->obj);
-               if (err)
-                       break;
-       }
-
-       return err;
-}
-
-static int mlxsw_sp_port_obj_dump(struct net_device *dev,
-                                 struct switchdev_obj *obj,
-                                 switchdev_obj_dump_cb_t *cb)
-{
-       struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
-       int err = 0;
-
-       switch (obj->id) {
-       case SWITCHDEV_OBJ_ID_PORT_VLAN:
-               err = mlxsw_sp_port_vlan_dump(mlxsw_sp_port,
-                                             SWITCHDEV_OBJ_PORT_VLAN(obj), cb);
-               break;
-       case SWITCHDEV_OBJ_ID_PORT_FDB:
-               err = mlxsw_sp_port_fdb_dump(mlxsw_sp_port,
-                                            SWITCHDEV_OBJ_PORT_FDB(obj), cb);
-               break;
-       default:
-               err = -EOPNOTSUPP;
-               break;
-       }
-
-       return err;
-}
-
 static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = {
        .switchdev_port_attr_get        = mlxsw_sp_port_attr_get,
        .switchdev_port_attr_set        = mlxsw_sp_port_attr_set,
        .switchdev_port_obj_add         = mlxsw_sp_port_obj_add,
        .switchdev_port_obj_del         = mlxsw_sp_port_obj_del,
-       .switchdev_port_obj_dump        = mlxsw_sp_port_obj_dump,
 };
 
 static int
@@ -1857,19 +1656,16 @@ void mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
        mlxsw_sp_bridge_port_put(mlxsw_sp->bridge, bridge_port);
 }
 
-static void mlxsw_sp_fdb_call_notifiers(bool learning_sync, bool adding,
-                                       char *mac, u16 vid,
-                                       struct net_device *dev)
+static void
+mlxsw_sp_fdb_call_notifiers(enum switchdev_notifier_type type,
+                           const char *mac, u16 vid,
+                           struct net_device *dev)
 {
        struct switchdev_notifier_fdb_info info;
-       unsigned long notifier_type;
 
-       if (learning_sync) {
-               info.addr = mac;
-               info.vid = vid;
-               notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL;
-               call_switchdev_notifiers(notifier_type, dev, &info.info);
-       }
+       info.addr = mac;
+       info.vid = vid;
+       call_switchdev_notifiers(type, dev, &info.info);
 }
 
 static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
@@ -1880,6 +1676,7 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
        struct mlxsw_sp_bridge_device *bridge_device;
        struct mlxsw_sp_bridge_port *bridge_port;
        struct mlxsw_sp_port *mlxsw_sp_port;
+       enum switchdev_notifier_type type;
        char mac[ETH_ALEN];
        u8 local_port;
        u16 vid, fid;
@@ -1918,8 +1715,9 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
 
        if (!do_notification)
                return;
-       mlxsw_sp_fdb_call_notifiers(bridge_port->flags & BR_LEARNING_SYNC,
-                                   adding, mac, vid, bridge_port->dev);
+       type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
+       mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev);
+
        return;
 
 just_remove:
@@ -1936,6 +1734,7 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
        struct mlxsw_sp_bridge_device *bridge_device;
        struct mlxsw_sp_bridge_port *bridge_port;
        struct mlxsw_sp_port *mlxsw_sp_port;
+       enum switchdev_notifier_type type;
        char mac[ETH_ALEN];
        u16 lag_vid = 0;
        u16 lag_id;
@@ -1976,8 +1775,9 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
 
        if (!do_notification)
                return;
-       mlxsw_sp_fdb_call_notifiers(bridge_port->flags & BR_LEARNING_SYNC,
-                                   adding, mac, vid, bridge_port->dev);
+       type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
+       mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev);
+
        return;
 
 just_remove:
@@ -2050,6 +1850,97 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
        mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
 }
 
+struct mlxsw_sp_switchdev_event_work {
+       struct work_struct work;
+       struct switchdev_notifier_fdb_info fdb_info;
+       struct net_device *dev;
+       unsigned long event;
+};
+
+static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
+{
+       struct mlxsw_sp_switchdev_event_work *switchdev_work =
+               container_of(work, struct mlxsw_sp_switchdev_event_work, work);
+       struct net_device *dev = switchdev_work->dev;
+       struct switchdev_notifier_fdb_info *fdb_info;
+       struct mlxsw_sp_port *mlxsw_sp_port;
+       int err;
+
+       rtnl_lock();
+       mlxsw_sp_port = mlxsw_sp_port_dev_lower_find(dev);
+       if (!mlxsw_sp_port)
+               goto out;
+
+       switch (switchdev_work->event) {
+       case SWITCHDEV_FDB_ADD_TO_DEVICE:
+               fdb_info = &switchdev_work->fdb_info;
+               err = mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, true);
+               if (err)
+                       break;
+               mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
+                                           fdb_info->addr,
+                                           fdb_info->vid, dev);
+               break;
+       case SWITCHDEV_FDB_DEL_TO_DEVICE:
+               fdb_info = &switchdev_work->fdb_info;
+               mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, false);
+               break;
+       }
+
+out:
+       rtnl_unlock();
+       kfree(switchdev_work->fdb_info.addr);
+       kfree(switchdev_work);
+       dev_put(dev);
+}
+
+/* Called under rcu_read_lock() */
+static int mlxsw_sp_switchdev_event(struct notifier_block *unused,
+                                   unsigned long event, void *ptr)
+{
+       struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+       struct mlxsw_sp_switchdev_event_work *switchdev_work;
+       struct switchdev_notifier_fdb_info *fdb_info = ptr;
+
+       if (!mlxsw_sp_port_dev_lower_find_rcu(dev))
+               return NOTIFY_DONE;
+
+       switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC);
+       if (!switchdev_work)
+               return NOTIFY_BAD;
+
+       INIT_WORK(&switchdev_work->work, mlxsw_sp_switchdev_event_work);
+       switchdev_work->dev = dev;
+       switchdev_work->event = event;
+
+       switch (event) {
+       case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
+       case SWITCHDEV_FDB_DEL_TO_DEVICE:
+               memcpy(&switchdev_work->fdb_info, ptr,
+                      sizeof(switchdev_work->fdb_info));
+               switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
+               ether_addr_copy((u8 *)switchdev_work->fdb_info.addr,
+                               fdb_info->addr);
+               /* Take a reference on the device. This can be either
+                * upper device containig mlxsw_sp_port or just a
+                * mlxsw_sp_port
+                */
+               dev_hold(dev);
+               break;
+       default:
+               kfree(switchdev_work);
+               return NOTIFY_DONE;
+       }
+
+       mlxsw_core_schedule_work(&switchdev_work->work);
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block mlxsw_sp_switchdev_notifier = {
+       .notifier_call = mlxsw_sp_switchdev_event,
+};
+
 static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
 {
        struct mlxsw_sp_bridge *bridge = mlxsw_sp->bridge;
@@ -2060,6 +1951,13 @@ static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
                dev_err(mlxsw_sp->bus_info->dev, "Failed to set default ageing time\n");
                return err;
        }
+
+       err = register_switchdev_notifier(&mlxsw_sp_switchdev_notifier);
+       if (err) {
+               dev_err(mlxsw_sp->bus_info->dev, "Failed to register switchdev notifier\n");
+               return err;
+       }
+
        INIT_DELAYED_WORK(&bridge->fdb_notify.dw, mlxsw_sp_fdb_notify_work);
        bridge->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
        mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
@@ -2069,6 +1967,8 @@ static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
 static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp)
 {
        cancel_delayed_work_sync(&mlxsw_sp->bridge->fdb_notify.dw);
+       unregister_switchdev_notifier(&mlxsw_sp_switchdev_notifier);
+
 }
 
 int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
index de07517da1bd7b011377393826ffb05845769897..396b93f54823f9d44badfd682ebf7a21ba5de5a6 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 
 #include "nfpcore/nfp_cpp.h"
+#include "nfpcore/nfp_nffw.h"
 #include "nfp_app.h"
 #include "nfp_main.h"
 
@@ -43,6 +44,13 @@ static const struct nfp_app_type *apps[] = {
        &app_bpf,
 };
 
+const char *nfp_app_mip_name(struct nfp_app *app)
+{
+       if (!app || !app->pf->mip)
+               return "";
+       return nfp_mip_name(app->pf->mip);
+}
+
 struct sk_buff *nfp_app_ctrl_msg_alloc(struct nfp_app *app, unsigned int size)
 {
        struct sk_buff *skb;
index 3fbf68f8577c005f6ffbacfd923b6d6d0d932995..f5e373fa8c3bbc1a815e87854a9cdebb2c80f98c 100644 (file)
@@ -216,6 +216,7 @@ static inline void nfp_app_ctrl_rx(struct nfp_app *app, struct sk_buff *skb)
        app->type->ctrl_msg_rx(app, skb);
 }
 
+const char *nfp_app_mip_name(struct nfp_app *app);
 struct sk_buff *nfp_app_ctrl_msg_alloc(struct nfp_app *app, unsigned int size);
 
 struct nfp_app *nfp_app_alloc(struct nfp_pf *pf, enum nfp_app_id id);
index 1a33ad9f4170c0f75e4af35e9a38902b620185a6..83c65e6291eee195beb5fb958bb8688bcb22d5dc 100644 (file)
@@ -80,7 +80,7 @@ int nfp_app_nic_vnic_init(struct nfp_app *app, struct nfp_net *nn,
        if (err)
                return err < 0 ? err : 0;
 
-       nfp_net_get_mac_addr(nn, app->cpp, id);
+       nfp_net_get_mac_addr(app->pf, nn, id);
 
        return 0;
 }
index 0c2e64d217b5aa6f14725abb5faacb65a7e4ae55..4e59dcb78c3697ed12f9e7511a687ccddd4f91dc 100644 (file)
@@ -77,7 +77,7 @@ static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf)
 {
        int err;
 
-       pf->limit_vfs = nfp_rtsym_read_le(pf->cpp, "nfd_vf_cfg_max_vfs", &err);
+       pf->limit_vfs = nfp_rtsym_read_le(pf->rtbl, "nfd_vf_cfg_max_vfs", &err);
        if (!err)
                return pci_sriov_set_totalvfs(pf->pdev, pf->limit_vfs);
 
@@ -170,7 +170,7 @@ nfp_net_fw_find(struct pci_dev *pdev, struct nfp_pf *pf)
                return NULL;
        }
 
-       fw_model = nfp_hwinfo_lookup(pf->cpp, "assembly.partno");
+       fw_model = nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno");
        if (!fw_model) {
                dev_err(&pdev->dev, "Error: can't read part number\n");
                return NULL;
@@ -358,21 +358,26 @@ static int nfp_pci_probe(struct pci_dev *pdev,
                goto err_disable_msix;
        }
 
+       pf->hwinfo = nfp_hwinfo_read(pf->cpp);
+
        dev_info(&pdev->dev, "Assembly: %s%s%s-%s CPLD: %s\n",
-                nfp_hwinfo_lookup(pf->cpp, "assembly.vendor"),
-                nfp_hwinfo_lookup(pf->cpp, "assembly.partno"),
-                nfp_hwinfo_lookup(pf->cpp, "assembly.serial"),
-                nfp_hwinfo_lookup(pf->cpp, "assembly.revision"),
-                nfp_hwinfo_lookup(pf->cpp, "cpld.version"));
+                nfp_hwinfo_lookup(pf->hwinfo, "assembly.vendor"),
+                nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno"),
+                nfp_hwinfo_lookup(pf->hwinfo, "assembly.serial"),
+                nfp_hwinfo_lookup(pf->hwinfo, "assembly.revision"),
+                nfp_hwinfo_lookup(pf->hwinfo, "cpld.version"));
 
        err = devlink_register(devlink, &pdev->dev);
        if (err)
-               goto err_cpp_free;
+               goto err_hwinfo_free;
 
        err = nfp_nsp_init(pdev, pf);
        if (err)
                goto err_devlink_unreg;
 
+       pf->mip = nfp_mip_open(pf->cpp);
+       pf->rtbl = __nfp_rtsym_table_read(pf->cpp, pf->mip);
+
        err = nfp_pcie_sriov_read_nfd_limit(pf);
        if (err)
                goto err_fw_unload;
@@ -394,13 +399,16 @@ static int nfp_pci_probe(struct pci_dev *pdev,
 err_sriov_unlimit:
        pci_sriov_set_totalvfs(pf->pdev, 0);
 err_fw_unload:
+       kfree(pf->rtbl);
+       nfp_mip_close(pf->mip);
        if (pf->fw_loaded)
                nfp_fw_unload(pf);
        kfree(pf->eth_tbl);
        kfree(pf->nspi);
 err_devlink_unreg:
        devlink_unregister(devlink);
-err_cpp_free:
+err_hwinfo_free:
+       kfree(pf->hwinfo);
        nfp_cpp_free(pf->cpp);
 err_disable_msix:
        pci_set_drvdata(pdev, NULL);
@@ -430,10 +438,13 @@ static void nfp_pci_remove(struct pci_dev *pdev)
 
        devlink_unregister(devlink);
 
+       kfree(pf->rtbl);
+       nfp_mip_close(pf->mip);
        if (pf->fw_loaded)
                nfp_fw_unload(pf);
 
        pci_set_drvdata(pdev, NULL);
+       kfree(pf->hwinfo);
        nfp_cpp_free(pf->cpp);
 
        kfree(pf->eth_tbl);
index 37832853b0b39312359d344b65973c26bd041109..88724f8d0dcdd91ed8734d2d299b366f189b9afb 100644 (file)
@@ -54,8 +54,11 @@ struct pci_dev;
 struct nfp_cpp;
 struct nfp_cpp_area;
 struct nfp_eth_table;
+struct nfp_hwinfo;
+struct nfp_mip;
 struct nfp_net;
 struct nfp_nsp_identify;
+struct nfp_rtsym_table;
 
 /**
  * struct nfp_pf - NFP PF-specific device structure
@@ -70,6 +73,9 @@ struct nfp_nsp_identify;
  * @num_vfs:           Number of SR-IOV VFs enabled
  * @fw_loaded:         Is the firmware loaded?
  * @ctrl_vnic:         Pointer to the control vNIC if available
+ * @mip:               MIP handle
+ * @rtbl:              RTsym table
+ * @hwinfo:            HWInfo table
  * @eth_tbl:           NSP ETH table
  * @nspi:              NSP identification info
  * @hwmon_dev:         pointer to hwmon device
@@ -101,6 +107,9 @@ struct nfp_pf {
 
        struct nfp_net *ctrl_vnic;
 
+       const struct nfp_mip *mip;
+       struct nfp_rtsym_table *rtbl;
+       struct nfp_hwinfo *hwinfo;
        struct nfp_eth_table *eth_tbl;
        struct nfp_nsp_identify *nspi;
 
@@ -130,7 +139,7 @@ void nfp_hwmon_unregister(struct nfp_pf *pf);
 struct nfp_eth_table_port *
 nfp_net_find_port(struct nfp_eth_table *eth_tbl, unsigned int id);
 void
-nfp_net_get_mac_addr(struct nfp_net *nn, struct nfp_cpp *cpp, unsigned int id);
+nfp_net_get_mac_addr(struct nfp_pf *pf, struct nfp_net *nn, unsigned int id);
 
 bool nfp_ctrl_tx(struct nfp_net *nn, struct sk_buff *skb);
 
index 4f0df63de626484022c5cb4a5922385bd38051a8..49d1756d6a8e0e74b4045b58e6b34c546ad48cc1 100644 (file)
@@ -2994,11 +2994,14 @@ static void nfp_net_stat64(struct net_device *netdev,
 }
 
 static int
-nfp_net_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
-                struct tc_to_netdev *tc)
+nfp_net_setup_tc(struct net_device *netdev, u32 handle, u32 chain_index,
+                __be16 proto, struct tc_to_netdev *tc)
 {
        struct nfp_net *nn = netdev_priv(netdev);
 
+       if (chain_index)
+               return -EOPNOTSUPP;
+
        return nfp_app_setup_tc(nn->app, netdev, handle, proto, tc);
 }
 
index 83664ca2521382cde49fdaa1ec7d8969bd96a6c4..6e31355c3567ac62b32837044fcd918d41932f09 100644 (file)
@@ -166,10 +166,10 @@ static void nfp_net_get_drvinfo(struct net_device *netdev,
 
        nfp_net_get_nspinfo(nn->app, nsp_version);
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
-                "%d.%d.%d.%d %s %s",
+                "%d.%d.%d.%d %s %s %s",
                 nn->fw_ver.resv, nn->fw_ver.class,
                 nn->fw_ver.major, nn->fw_ver.minor, nsp_version,
-                nfp_app_name(nn->app));
+                nfp_app_mip_name(nn->app), nfp_app_name(nn->app));
        strlcpy(drvinfo->bus_info, pci_name(nn->pdev),
                sizeof(drvinfo->bus_info));
 
index 5f27703060c242b0b2d49f49dce0a72b49b48a50..bc2bc0886176e5a3bff856aa2037715ae14543f9 100644 (file)
 
 #define NFP_PF_CSR_SLICE_SIZE  (32 * 1024)
 
-static int nfp_is_ready(struct nfp_cpp *cpp)
+static int nfp_is_ready(struct nfp_pf *pf)
 {
        const char *cp;
        long state;
        int err;
 
-       cp = nfp_hwinfo_lookup(cpp, "board.state");
+       cp = nfp_hwinfo_lookup(pf->hwinfo, "board.state");
        if (!cp)
                return 0;
 
@@ -134,15 +134,15 @@ static u8 __iomem *nfp_net_map_area(struct nfp_cpp *cpp,
 
 /**
  * nfp_net_get_mac_addr() - Get the MAC address.
+ * @pf:       NFP PF handle
  * @nn:       NFP Network structure
- * @cpp:      NFP CPP handle
  * @id:              NFP port id
  *
  * First try to get the MAC address from NSP ETH table. If that
  * fails try HWInfo.  As a last resort generate a random address.
  */
 void
-nfp_net_get_mac_addr(struct nfp_net *nn, struct nfp_cpp *cpp, unsigned int id)
+nfp_net_get_mac_addr(struct nfp_pf *pf, struct nfp_net *nn, unsigned int id)
 {
        struct nfp_eth_table_port *eth_port;
        struct nfp_net_dp *dp = &nn->dp;
@@ -159,7 +159,7 @@ nfp_net_get_mac_addr(struct nfp_net *nn, struct nfp_cpp *cpp, unsigned int id)
 
        snprintf(name, sizeof(name), "eth%d.mac", id);
 
-       mac_str = nfp_hwinfo_lookup(cpp, name);
+       mac_str = nfp_hwinfo_lookup(pf->hwinfo, name);
        if (!mac_str) {
                dev_warn(dp->dev, "Can't lookup MAC address. Generate\n");
                eth_hw_addr_random(dp->netdev);
@@ -201,7 +201,7 @@ nfp_net_pf_rtsym_read_optional(struct nfp_pf *pf, const char *format,
 
        snprintf(name, sizeof(name), format, nfp_cppcore_pcie_unit(pf->cpp));
 
-       val = nfp_rtsym_read_le(pf->cpp, name, &err);
+       val = nfp_rtsym_read_le(pf->rtbl, name, &err);
        if (err) {
                if (err == -ENOENT)
                        return default_val;
@@ -234,7 +234,7 @@ nfp_net_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt,
        snprintf(pf_symbol, sizeof(pf_symbol), sym_fmt,
                 nfp_cppcore_pcie_unit(pf->cpp));
 
-       sym = nfp_rtsym_lookup(pf->cpp, pf_symbol);
+       sym = nfp_rtsym_lookup(pf->rtbl, pf_symbol);
        if (!sym) {
                nfp_err(pf->cpp, "Failed to find PF symbol %s\n", pf_symbol);
                return (u8 __iomem *)ERR_PTR(-ENOENT);
@@ -713,7 +713,7 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
        INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_vnics);
 
        /* Verify that the board has completed initialization */
-       if (!nfp_is_ready(pf->cpp)) {
+       if (!nfp_is_ready(pf)) {
                nfp_err(pf->cpp, "NFP is not ready for NIC operation.\n");
                return -EINVAL;
        }
@@ -813,6 +813,7 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
        nfp_cpp_area_release_free(pf->data_vnic_bar);
 err_unlock:
        mutex_unlock(&pf->lock);
+       cancel_work_sync(&pf->port_refresh_work);
        return err;
 }
 
index 94641b4c2c553c8d13b3403cb43005e3f19c48a3..1a8d04a1e11327f8ec4411c258469bca728ffb32 100644 (file)
@@ -46,7 +46,9 @@
 
 /* Implemented in nfp_hwinfo.c */
 
-const char *nfp_hwinfo_lookup(struct nfp_cpp *cpp, const char *lookup);
+struct nfp_hwinfo;
+struct nfp_hwinfo *nfp_hwinfo_read(struct nfp_cpp *cpp);
+const char *nfp_hwinfo_lookup(struct nfp_hwinfo *hwinfo, const char *lookup);
 
 /* Implemented in nfp_nsp.c, low level functions */
 
index 0a46c0984e6869b385a33ccce2f98047b603a8d3..25a967158ce9cb6706e617d79d642f05630bcc99 100644 (file)
@@ -222,13 +222,6 @@ u32 nfp_cpp_model(struct nfp_cpp *cpp);
 u16 nfp_cpp_interface(struct nfp_cpp *cpp);
 int nfp_cpp_serial(struct nfp_cpp *cpp, const u8 **serial);
 
-void *nfp_hwinfo_cache(struct nfp_cpp *cpp);
-void nfp_hwinfo_cache_set(struct nfp_cpp *cpp, void *val);
-void *nfp_rtsym_cache(struct nfp_cpp *cpp);
-void nfp_rtsym_cache_set(struct nfp_cpp *cpp, void *val);
-
-void nfp_nffw_cache_flush(struct nfp_cpp *cpp);
-
 struct nfp_cpp_area *nfp_cpp_area_alloc_with_name(struct nfp_cpp *cpp,
                                                  u32 cpp_id,
                                                  const char *name,
index 5672d309d07db46fcfdc47f64549591f455cea65..9b69dcf87be934b10d57727626388a2b0b76e958 100644 (file)
@@ -76,10 +76,6 @@ struct nfp_cpp_resource {
  * @serial:            chip serial number
  * @imb_cat_table:     CPP Mapping Table
  *
- * Following fields can be used only in probe() or with rtnl held:
- * @hwinfo:            HWInfo database fetched from the device
- * @rtsym:             firmware run time symbols
- *
  * Following fields use explicit locking:
  * @resource_list:     NFP CPP resource list
  * @resource_lock:     protects @resource_list
@@ -107,9 +103,6 @@ struct nfp_cpp {
 
        struct mutex area_cache_mutex;
        struct list_head area_cache_list;
-
-       void *hwinfo;
-       void *rtsym;
 };
 
 /* Element of the area_cache_list */
@@ -233,9 +226,6 @@ void nfp_cpp_free(struct nfp_cpp *cpp)
        if (cpp->op->free)
                cpp->op->free(cpp);
 
-       kfree(cpp->hwinfo);
-       kfree(cpp->rtsym);
-
        device_unregister(&cpp->dev);
 
        kfree(cpp);
@@ -276,39 +266,6 @@ int nfp_cpp_serial(struct nfp_cpp *cpp, const u8 **serial)
        return sizeof(cpp->serial);
 }
 
-void *nfp_hwinfo_cache(struct nfp_cpp *cpp)
-{
-       return cpp->hwinfo;
-}
-
-void nfp_hwinfo_cache_set(struct nfp_cpp *cpp, void *val)
-{
-       cpp->hwinfo = val;
-}
-
-void *nfp_rtsym_cache(struct nfp_cpp *cpp)
-{
-       return cpp->rtsym;
-}
-
-void nfp_rtsym_cache_set(struct nfp_cpp *cpp, void *val)
-{
-       cpp->rtsym = val;
-}
-
-/**
- * nfp_nffw_cache_flush() - Flush cached firmware information
- * @cpp:       NFP CPP handle
- *
- * Flush cached firmware information.  This function should be called
- * every time firmware is loaded on unloaded.
- */
-void nfp_nffw_cache_flush(struct nfp_cpp *cpp)
-{
-       kfree(nfp_rtsym_cache(cpp));
-       nfp_rtsym_cache_set(cpp, NULL);
-}
-
 /**
  * nfp_cpp_area_alloc_with_name() - allocate a new CPP area
  * @cpp:       CPP device handle
index 8d8f311ffa6edb19ecc5af6340bb8191ae199627..4f24aff1e772b16a6fb4af8d0bdf85bbf33e966f 100644 (file)
@@ -178,7 +178,8 @@ hwinfo_db_validate(struct nfp_cpp *cpp, struct nfp_hwinfo *db, u32 len)
        return hwinfo_db_walk(cpp, db, size);
 }
 
-static int hwinfo_try_fetch(struct nfp_cpp *cpp, size_t *cpp_size)
+static struct nfp_hwinfo *
+hwinfo_try_fetch(struct nfp_cpp *cpp, size_t *cpp_size)
 {
        struct nfp_hwinfo *header;
        struct nfp_resource *res;
@@ -196,7 +197,7 @@ static int hwinfo_try_fetch(struct nfp_cpp *cpp, size_t *cpp_size)
                nfp_resource_release(res);
 
                if (*cpp_size < HWINFO_SIZE_MIN)
-                       return -ENOENT;
+                       return NULL;
        } else if (PTR_ERR(res) == -ENOENT) {
                /* Try getting the HWInfo table from the 'classic' location */
                cpp_id = NFP_CPP_ISLAND_ID(NFP_CPP_TARGET_MU,
@@ -204,101 +205,86 @@ static int hwinfo_try_fetch(struct nfp_cpp *cpp, size_t *cpp_size)
                cpp_addr = 0x30000;
                *cpp_size = 0x0e000;
        } else {
-               return PTR_ERR(res);
+               return NULL;
        }
 
        db = kmalloc(*cpp_size + 1, GFP_KERNEL);
        if (!db)
-               return -ENOMEM;
+               return NULL;
 
        err = nfp_cpp_read(cpp, cpp_id, cpp_addr, db, *cpp_size);
-       if (err != *cpp_size) {
-               kfree(db);
-               return err < 0 ? err : -EIO;
-       }
+       if (err != *cpp_size)
+               goto exit_free;
 
        header = (void *)db;
-       if (nfp_hwinfo_is_updating(header)) {
-               kfree(db);
-               return -EBUSY;
-       }
+       if (nfp_hwinfo_is_updating(header))
+               goto exit_free;
 
        if (le32_to_cpu(header->version) != NFP_HWINFO_VERSION_2) {
                nfp_err(cpp, "Unknown HWInfo version: 0x%08x\n",
                        le32_to_cpu(header->version));
-               kfree(db);
-               return -EINVAL;
+               goto exit_free;
        }
 
        /* NULL-terminate for safety */
        db[*cpp_size] = '\0';
 
-       nfp_hwinfo_cache_set(cpp, db);
-
-       return 0;
+       return (void *)db;
+exit_free:
+       kfree(db);
+       return NULL;
 }
 
-static int hwinfo_fetch(struct nfp_cpp *cpp, size_t *hwdb_size)
+static struct nfp_hwinfo *hwinfo_fetch(struct nfp_cpp *cpp, size_t *hwdb_size)
 {
        const unsigned long wait_until = jiffies + HWINFO_WAIT * HZ;
+       struct nfp_hwinfo *db;
        int err;
 
        for (;;) {
                const unsigned long start_time = jiffies;
 
-               err = hwinfo_try_fetch(cpp, hwdb_size);
-               if (!err)
-                       return 0;
+               db = hwinfo_try_fetch(cpp, hwdb_size);
+               if (db)
+                       return db;
 
                err = msleep_interruptible(100);
                if (err || time_after(start_time, wait_until)) {
                        nfp_err(cpp, "NFP access error\n");
-                       return -EIO;
+                       return NULL;
                }
        }
 }
 
-static int nfp_hwinfo_load(struct nfp_cpp *cpp)
+struct nfp_hwinfo *nfp_hwinfo_read(struct nfp_cpp *cpp)
 {
        struct nfp_hwinfo *db;
        size_t hwdb_size = 0;
        int err;
 
-       err = hwinfo_fetch(cpp, &hwdb_size);
-       if (err)
-               return err;
+       db = hwinfo_fetch(cpp, &hwdb_size);
+       if (!db)
+               return NULL;
 
-       db = nfp_hwinfo_cache(cpp);
        err = hwinfo_db_validate(cpp, db, hwdb_size);
        if (err) {
                kfree(db);
-               nfp_hwinfo_cache_set(cpp, NULL);
-               return err;
+               return NULL;
        }
 
-       return 0;
+       return db;
 }
 
 /**
  * nfp_hwinfo_lookup() - Find a value in the HWInfo table by name
- * @cpp:       NFP CPP handle
+ * @hwinfo:    NFP HWinfo table
  * @lookup:    HWInfo name to search for
  *
  * Return: Value of the HWInfo name, or NULL
  */
-const char *nfp_hwinfo_lookup(struct nfp_cpp *cpp, const char *lookup)
+const char *nfp_hwinfo_lookup(struct nfp_hwinfo *hwinfo, const char *lookup)
 {
        const char *key, *val, *end;
-       struct nfp_hwinfo *hwinfo;
-       int err;
-
-       hwinfo = nfp_hwinfo_cache(cpp);
-       if (!hwinfo) {
-               err = nfp_hwinfo_load(cpp);
-               if (err)
-                       return NULL;
-               hwinfo = nfp_hwinfo_cache(cpp);
-       }
 
        if (!hwinfo || !lookup)
                return NULL;
index 3d15dd03647e8383a981f1c67b1cd62ab893f897..5f193fe2d69e8d98ddbc3006806b318aba6e2874 100644 (file)
@@ -141,6 +141,8 @@ const struct nfp_mip *nfp_mip_open(struct nfp_cpp *cpp)
                return NULL;
        }
 
+       mip->name[sizeof(mip->name) - 1] = 0;
+
        return mip;
 }
 
@@ -149,6 +151,11 @@ void nfp_mip_close(const struct nfp_mip *mip)
        kfree(mip);
 }
 
+const char *nfp_mip_name(const struct nfp_mip *mip)
+{
+       return mip->name;
+}
+
 /**
  * nfp_mip_symtab() - Get the address and size of the MIP symbol table
  * @mip:       MIP handle
index 988badd230d1f210496a8b41dab5516e37602d28..d27d29782a1262be31f7e067122ec2f2bcca2f18 100644 (file)
@@ -55,6 +55,7 @@ struct nfp_mip;
 const struct nfp_mip *nfp_mip_open(struct nfp_cpp *cpp);
 void nfp_mip_close(const struct nfp_mip *mip);
 
+const char *nfp_mip_name(const struct nfp_mip *mip);
 void nfp_mip_symtab(const struct nfp_mip *mip, u32 *addr, u32 *size);
 void nfp_mip_strtab(const struct nfp_mip *mip, u32 *addr, u32 *size);
 
@@ -87,9 +88,16 @@ struct nfp_rtsym {
        int domain;
 };
 
-int nfp_rtsym_count(struct nfp_cpp *cpp);
-const struct nfp_rtsym *nfp_rtsym_get(struct nfp_cpp *cpp, int idx);
-const struct nfp_rtsym *nfp_rtsym_lookup(struct nfp_cpp *cpp, const char *name);
-u64 nfp_rtsym_read_le(struct nfp_cpp *cpp, const char *name, int *error);
+struct nfp_rtsym_table;
+
+struct nfp_rtsym_table *nfp_rtsym_table_read(struct nfp_cpp *cpp);
+struct nfp_rtsym_table *
+__nfp_rtsym_table_read(struct nfp_cpp *cpp, const struct nfp_mip *mip);
+int nfp_rtsym_count(struct nfp_rtsym_table *rtbl);
+const struct nfp_rtsym *nfp_rtsym_get(struct nfp_rtsym_table *rtbl, int idx);
+const struct nfp_rtsym *
+nfp_rtsym_lookup(struct nfp_rtsym_table *rtbl, const char *name);
+u64 nfp_rtsym_read_le(struct nfp_rtsym_table *rtbl, const char *name,
+                     int *error);
 
 #endif /* NFP_NFFW_H */
index eefdb756d74ea1af78302cc9b4d93cee9f84ca94..37364555c42b3fe60438713c4b7ffd1ca3d4a9a6 100644 (file)
@@ -474,13 +474,7 @@ int nfp_nsp_wait(struct nfp_nsp *state)
 
 int nfp_nsp_device_soft_reset(struct nfp_nsp *state)
 {
-       int err;
-
-       err = nfp_nsp_command(state, SPCODE_SOFT_RESET, 0, 0, 0);
-
-       nfp_nffw_cache_flush(state->cpp);
-
-       return err;
+       return nfp_nsp_command(state, SPCODE_SOFT_RESET, 0, 0, 0);
 }
 
 int nfp_nsp_load_fw(struct nfp_nsp *state, const struct firmware *fw)
index 0e3870ecfb8cd69d99fafc03a6a20748dc29de79..203f9cbae0fbc79271f4e6c724a90acb89a20137 100644 (file)
@@ -65,7 +65,8 @@ struct nfp_rtsym_entry {
        __le32  size_lo;
 };
 
-struct nfp_rtsym_cache {
+struct nfp_rtsym_table {
+       struct nfp_cpp *cpp;
        int num;
        char *strtab;
        struct nfp_rtsym symtab[];
@@ -78,7 +79,7 @@ static int nfp_meid(u8 island_id, u8 menum)
 }
 
 static void
-nfp_rtsym_sw_entry_init(struct nfp_rtsym_cache *cache, u32 strtab_size,
+nfp_rtsym_sw_entry_init(struct nfp_rtsym_table *cache, u32 strtab_size,
                        struct nfp_rtsym *sw, struct nfp_rtsym_entry *fw)
 {
        sw->type = fw->type;
@@ -106,26 +107,36 @@ nfp_rtsym_sw_entry_init(struct nfp_rtsym_cache *cache, u32 strtab_size,
                sw->domain = -1;
 }
 
-static int nfp_rtsymtab_probe(struct nfp_cpp *cpp)
+struct nfp_rtsym_table *nfp_rtsym_table_read(struct nfp_cpp *cpp)
+{
+       struct nfp_rtsym_table *rtbl;
+       const struct nfp_mip *mip;
+
+       mip = nfp_mip_open(cpp);
+       rtbl = __nfp_rtsym_table_read(cpp, mip);
+       nfp_mip_close(mip);
+
+       return rtbl;
+}
+
+struct nfp_rtsym_table *
+__nfp_rtsym_table_read(struct nfp_cpp *cpp, const struct nfp_mip *mip)
 {
        const u32 dram = NFP_CPP_ID(NFP_CPP_TARGET_MU, NFP_CPP_ACTION_RW, 0) |
                NFP_ISL_EMEM0;
        u32 strtab_addr, symtab_addr, strtab_size, symtab_size;
        struct nfp_rtsym_entry *rtsymtab;
-       struct nfp_rtsym_cache *cache;
-       const struct nfp_mip *mip;
+       struct nfp_rtsym_table *cache;
        int err, n, size;
 
-       mip = nfp_mip_open(cpp);
        if (!mip)
-               return -EIO;
+               return NULL;
 
        nfp_mip_strtab(mip, &strtab_addr, &strtab_size);
        nfp_mip_symtab(mip, &symtab_addr, &symtab_size);
-       nfp_mip_close(mip);
 
        if (!symtab_size || !strtab_size || symtab_size % sizeof(*rtsymtab))
-               return -ENXIO;
+               return NULL;
 
        /* Align to 64 bits */
        symtab_size = round_up(symtab_size, 8);
@@ -133,27 +144,26 @@ static int nfp_rtsymtab_probe(struct nfp_cpp *cpp)
 
        rtsymtab = kmalloc(symtab_size, GFP_KERNEL);
        if (!rtsymtab)
-               return -ENOMEM;
+               return NULL;
 
        size = sizeof(*cache);
        size += symtab_size / sizeof(*rtsymtab) * sizeof(struct nfp_rtsym);
        size += strtab_size + 1;
        cache = kmalloc(size, GFP_KERNEL);
-       if (!cache) {
-               err = -ENOMEM;
-               goto err_free_rtsym_raw;
-       }
+       if (!cache)
+               goto exit_free_rtsym_raw;
 
+       cache->cpp = cpp;
        cache->num = symtab_size / sizeof(*rtsymtab);
        cache->strtab = (void *)&cache->symtab[cache->num];
 
        err = nfp_cpp_read(cpp, dram, symtab_addr, rtsymtab, symtab_size);
        if (err != symtab_size)
-               goto err_free_cache;
+               goto exit_free_cache;
 
        err = nfp_cpp_read(cpp, dram, strtab_addr, cache->strtab, strtab_size);
        if (err != strtab_size)
-               goto err_free_cache;
+               goto exit_free_cache;
        cache->strtab[strtab_size] = '\0';
 
        for (n = 0; n < cache->num; n++)
@@ -161,97 +171,71 @@ static int nfp_rtsymtab_probe(struct nfp_cpp *cpp)
                                        &cache->symtab[n], &rtsymtab[n]);
 
        kfree(rtsymtab);
-       nfp_rtsym_cache_set(cpp, cache);
-       return 0;
 
-err_free_cache:
+       return cache;
+
+exit_free_cache:
        kfree(cache);
-err_free_rtsym_raw:
+exit_free_rtsym_raw:
        kfree(rtsymtab);
-       return err;
-}
-
-static struct nfp_rtsym_cache *nfp_rtsym(struct nfp_cpp *cpp)
-{
-       struct nfp_rtsym_cache *cache;
-       int err;
-
-       cache = nfp_rtsym_cache(cpp);
-       if (cache)
-               return cache;
-
-       err = nfp_rtsymtab_probe(cpp);
-       if (err < 0)
-               return ERR_PTR(err);
-
-       return nfp_rtsym_cache(cpp);
+       return NULL;
 }
 
 /**
  * nfp_rtsym_count() - Get the number of RTSYM descriptors
- * @cpp:       NFP CPP handle
+ * @rtbl:      NFP RTsym table
  *
- * Return: Number of RTSYM descriptors, or -ERRNO
+ * Return: Number of RTSYM descriptors
  */
-int nfp_rtsym_count(struct nfp_cpp *cpp)
+int nfp_rtsym_count(struct nfp_rtsym_table *rtbl)
 {
-       struct nfp_rtsym_cache *cache;
-
-       cache = nfp_rtsym(cpp);
-       if (IS_ERR(cache))
-               return PTR_ERR(cache);
-
-       return cache->num;
+       if (!rtbl)
+               return -EINVAL;
+       return rtbl->num;
 }
 
 /**
  * nfp_rtsym_get() - Get the Nth RTSYM descriptor
- * @cpp:       NFP CPP handle
+ * @rtbl:      NFP RTsym table
  * @idx:       Index (0-based) of the RTSYM descriptor
  *
  * Return: const pointer to a struct nfp_rtsym descriptor, or NULL
  */
-const struct nfp_rtsym *nfp_rtsym_get(struct nfp_cpp *cpp, int idx)
+const struct nfp_rtsym *nfp_rtsym_get(struct nfp_rtsym_table *rtbl, int idx)
 {
-       struct nfp_rtsym_cache *cache;
-
-       cache = nfp_rtsym(cpp);
-       if (IS_ERR(cache))
+       if (!rtbl)
                return NULL;
-
-       if (idx >= cache->num)
+       if (idx >= rtbl->num)
                return NULL;
 
-       return &cache->symtab[idx];
+       return &rtbl->symtab[idx];
 }
 
 /**
  * nfp_rtsym_lookup() - Return the RTSYM descriptor for a symbol name
- * @cpp:       NFP CPP handle
+ * @rtbl:      NFP RTsym table
  * @name:      Symbol name
  *
  * Return: const pointer to a struct nfp_rtsym descriptor, or NULL
  */
-const struct nfp_rtsym *nfp_rtsym_lookup(struct nfp_cpp *cpp, const char *name)
+const struct nfp_rtsym *
+nfp_rtsym_lookup(struct nfp_rtsym_table *rtbl, const char *name)
 {
-       struct nfp_rtsym_cache *cache;
        int n;
 
-       cache = nfp_rtsym(cpp);
-       if (IS_ERR(cache))
+       if (!rtbl)
                return NULL;
 
-       for (n = 0; n < cache->num; n++) {
-               if (strcmp(name, cache->symtab[n].name) == 0)
-                       return &cache->symtab[n];
-       }
+       for (n = 0; n < rtbl->num; n++)
+               if (strcmp(name, rtbl->symtab[n].name) == 0)
+                       return &rtbl->symtab[n];
 
        return NULL;
 }
 
 /**
  * nfp_rtsym_read_le() - Read a simple unsigned scalar value from symbol
- * @cpp:       NFP CPP handle
+ * @rtbl:      NFP RTsym table
  * @name:      Symbol name
  * @error:     Poniter to error code (optional)
  *
@@ -261,14 +245,15 @@ const struct nfp_rtsym *nfp_rtsym_lookup(struct nfp_cpp *cpp, const char *name)
  *
  * Return: value read, on error sets the error and returns ~0ULL.
  */
-u64 nfp_rtsym_read_le(struct nfp_cpp *cpp, const char *name, int *error)
+u64 nfp_rtsym_read_le(struct nfp_rtsym_table *rtbl, const char *name,
+                     int *error)
 {
        const struct nfp_rtsym *sym;
        u32 val32, id;
        u64 val;
        int err;
 
-       sym = nfp_rtsym_lookup(cpp, name);
+       sym = nfp_rtsym_lookup(rtbl, name);
        if (!sym) {
                err = -ENOENT;
                goto exit;
@@ -278,14 +263,14 @@ u64 nfp_rtsym_read_le(struct nfp_cpp *cpp, const char *name, int *error)
 
        switch (sym->size) {
        case 4:
-               err = nfp_cpp_readl(cpp, id, sym->addr, &val32);
+               err = nfp_cpp_readl(rtbl->cpp, id, sym->addr, &val32);
                val = val32;
                break;
        case 8:
-               err = nfp_cpp_readq(cpp, id, sym->addr, &val);
+               err = nfp_cpp_readq(rtbl->cpp, id, sym->addr, &val);
                break;
        default:
-               nfp_err(cpp,
+               nfp_err(rtbl->cpp,
                        "rtsym '%s' unsupported or non-scalar size: %lld\n",
                        name, sym->size);
                err = -EINVAL;
index d7afc42f766cefee67303dcc7a55a8270b93ebf0..14b08ee9e3ade1db0bf5053de37fa9e76f140e2b 100644 (file)
@@ -552,7 +552,6 @@ struct qed_hwfn {
 #endif
 
        struct z_stream_s               *stream;
-       struct qed_roce_ll2_info        *ll2;
 };
 
 struct pci_params {
index f67ed6d39dfd4043f54f73c4fc97c95be847950d..0e26193156e44ea426ba15f3c9dbbbcd64465931 100644 (file)
@@ -73,7 +73,6 @@ struct qed_cb_ll2_info {
        int rx_cnt;
        u32 rx_size;
        u8 handle;
-       bool frags_mapped;
 
        /* Lock protecting LL2 buffer lists in sleepless context */
        spinlock_t lock;
@@ -89,13 +88,14 @@ struct qed_ll2_buffer {
        dma_addr_t phys_addr;
 };
 
-static void qed_ll2b_complete_tx_packet(struct qed_hwfn *p_hwfn,
+static void qed_ll2b_complete_tx_packet(void *cxt,
                                        u8 connection_handle,
                                        void *cookie,
                                        dma_addr_t first_frag_addr,
                                        bool b_last_fragment,
                                        bool b_last_packet)
 {
+       struct qed_hwfn *p_hwfn = cxt;
        struct qed_dev *cdev = p_hwfn->cdev;
        struct sk_buff *skb = cookie;
 
@@ -107,12 +107,6 @@ static void qed_ll2b_complete_tx_packet(struct qed_hwfn *p_hwfn,
                cdev->ll2->cbs->tx_cb(cdev->ll2->cb_cookie, skb,
                                      b_last_fragment);
 
-       if (cdev->ll2->frags_mapped)
-               /* Case where mapped frags were received, need to
-                * free skb with nr_frags marked as 0
-                */
-               skb_shinfo(skb)->nr_frags = 0;
-
        dev_kfree_skb_any(skb);
 }
 
@@ -164,42 +158,34 @@ static void qed_ll2_kill_buffers(struct qed_dev *cdev)
                qed_ll2_dealloc_buffer(cdev, buffer);
 }
 
-static void qed_ll2b_complete_rx_packet(struct qed_hwfn *p_hwfn,
-                                       u8 connection_handle,
-                                       struct qed_ll2_rx_packet *p_pkt,
-                                       struct core_rx_fast_path_cqe *p_cqe,
-                                       bool b_last_packet)
+void qed_ll2b_complete_rx_packet(void *cxt, struct qed_ll2_comp_rx_data *data)
 {
-       u16 packet_length = le16_to_cpu(p_cqe->packet_length);
-       struct qed_ll2_buffer *buffer = p_pkt->cookie;
+       struct qed_hwfn *p_hwfn = cxt;
+       struct qed_ll2_buffer *buffer = data->cookie;
        struct qed_dev *cdev = p_hwfn->cdev;
-       u16 vlan = le16_to_cpu(p_cqe->vlan);
-       u32 opaque_data_0, opaque_data_1;
-       u8 pad = p_cqe->placement_offset;
        dma_addr_t new_phys_addr;
        struct sk_buff *skb;
        bool reuse = false;
        int rc = -EINVAL;
        u8 *new_data;
 
-       opaque_data_0 = le32_to_cpu(p_cqe->opaque_data.data[0]);
-       opaque_data_1 = le32_to_cpu(p_cqe->opaque_data.data[1]);
-
        DP_VERBOSE(p_hwfn,
                   (NETIF_MSG_RX_STATUS | QED_MSG_STORAGE | NETIF_MSG_PKTDATA),
                   "Got an LL2 Rx completion: [Buffer at phys 0x%llx, offset 0x%02x] Length 0x%04x Parse_flags 0x%04x vlan 0x%04x Opaque data [0x%08x:0x%08x]\n",
-                  (u64)p_pkt->rx_buf_addr, pad, packet_length,
-                  le16_to_cpu(p_cqe->parse_flags.flags), vlan,
-                  opaque_data_0, opaque_data_1);
+                  (u64)data->rx_buf_addr,
+                  data->u.placement_offset,
+                  data->length.packet_length,
+                  data->parse_flags,
+                  data->vlan, data->opaque_data_0, data->opaque_data_1);
 
        if ((cdev->dp_module & NETIF_MSG_PKTDATA) && buffer->data) {
                print_hex_dump(KERN_INFO, "",
                               DUMP_PREFIX_OFFSET, 16, 1,
-                              buffer->data, packet_length, false);
+                              buffer->data, data->length.packet_length, false);
        }
 
        /* Determine if data is valid */
-       if (packet_length < ETH_HLEN)
+       if (data->length.packet_length < ETH_HLEN)
                reuse = true;
 
        /* Allocate a replacement for buffer; Reuse upon failure */
@@ -219,9 +205,9 @@ static void qed_ll2b_complete_rx_packet(struct qed_hwfn *p_hwfn,
                goto out_post;
        }
 
-       pad += NET_SKB_PAD;
-       skb_reserve(skb, pad);
-       skb_put(skb, packet_length);
+       data->u.placement_offset += NET_SKB_PAD;
+       skb_reserve(skb, data->u.placement_offset);
+       skb_put(skb, data->length.packet_length);
        skb_checksum_none_assert(skb);
 
        /* Get parital ethernet information instead of eth_type_trans(),
@@ -232,10 +218,12 @@ static void qed_ll2b_complete_rx_packet(struct qed_hwfn *p_hwfn,
 
        /* Pass SKB onward */
        if (cdev->ll2->cbs && cdev->ll2->cbs->rx_cb) {
-               if (vlan)
-                       __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan);
+               if (data->vlan)
+                       __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+                                              data->vlan);
                cdev->ll2->cbs->rx_cb(cdev->ll2->cb_cookie, skb,
-                                     opaque_data_0, opaque_data_1);
+                                     data->opaque_data_0,
+                                     data->opaque_data_1);
        }
 
        /* Update Buffer information and update FW producer */
@@ -321,7 +309,7 @@ static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
                list_del(&p_pkt->list_entry);
                b_last_packet = list_empty(&p_tx->active_descq);
                list_add_tail(&p_pkt->list_entry, &p_tx->free_descq);
-               if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO) {
+               if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_ISCSI_OOO) {
                        struct qed_ooo_buffer *p_buffer;
 
                        p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;
@@ -333,21 +321,12 @@ static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
                        b_last_frag =
                                p_tx->cur_completing_bd_idx == p_pkt->bd_used;
                        tx_frag = p_pkt->bds_set[0].tx_frag;
-                       if (p_ll2_conn->conn.gsi_enable)
-                               qed_ll2b_release_tx_gsi_packet(p_hwfn,
-                                                              p_ll2_conn->
-                                                              my_id,
-                                                              p_pkt->cookie,
-                                                              tx_frag,
-                                                              b_last_frag,
-                                                              b_last_packet);
-                       else
-                               qed_ll2b_complete_tx_packet(p_hwfn,
-                                                           p_ll2_conn->my_id,
-                                                           p_pkt->cookie,
-                                                           tx_frag,
-                                                           b_last_frag,
-                                                           b_last_packet);
+                       p_ll2_conn->cbs.tx_release_cb(p_ll2_conn->cbs.cookie,
+                                                     p_ll2_conn->my_id,
+                                                     p_pkt->cookie,
+                                                     tx_frag,
+                                                     b_last_frag,
+                                                     b_last_packet);
                }
        }
 }
@@ -360,7 +339,6 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
        struct qed_ll2_tx_packet *p_pkt;
        bool b_last_frag = false;
        unsigned long flags;
-       dma_addr_t tx_frag;
        int rc = -EINVAL;
 
        spin_lock_irqsave(&p_tx->lock, flags);
@@ -401,19 +379,13 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
                list_add_tail(&p_pkt->list_entry, &p_tx->free_descq);
 
                spin_unlock_irqrestore(&p_tx->lock, flags);
-               tx_frag = p_pkt->bds_set[0].tx_frag;
-               if (p_ll2_conn->conn.gsi_enable)
-                       qed_ll2b_complete_tx_gsi_packet(p_hwfn,
-                                                       p_ll2_conn->my_id,
-                                                       p_pkt->cookie,
-                                                       tx_frag,
-                                                       b_last_frag, !num_bds);
-               else
-                       qed_ll2b_complete_tx_packet(p_hwfn,
-                                                   p_ll2_conn->my_id,
-                                                   p_pkt->cookie,
-                                                   tx_frag,
-                                                   b_last_frag, !num_bds);
+
+               p_ll2_conn->cbs.tx_comp_cb(p_ll2_conn->cbs.cookie,
+                                          p_ll2_conn->my_id,
+                                          p_pkt->cookie,
+                                          p_pkt->bds_set[0].tx_frag,
+                                          b_last_frag, !num_bds);
+
                spin_lock_irqsave(&p_tx->lock, flags);
        }
 
@@ -424,81 +396,71 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
        return rc;
 }
 
-static int
-qed_ll2_rxq_completion_gsi(struct qed_hwfn *p_hwfn,
-                          struct qed_ll2_info *p_ll2_info,
-                          union core_rx_cqe_union *p_cqe,
-                          unsigned long lock_flags, bool b_last_cqe)
+static void qed_ll2_rxq_parse_gsi(struct qed_hwfn *p_hwfn,
+                                 union core_rx_cqe_union *p_cqe,
+                                 struct qed_ll2_comp_rx_data *data)
 {
-       struct qed_ll2_rx_queue *p_rx = &p_ll2_info->rx_queue;
-       struct qed_ll2_rx_packet *p_pkt = NULL;
-       u16 packet_length, parse_flags, vlan;
-       u32 src_mac_addrhi;
-       u16 src_mac_addrlo;
-
-       if (!list_empty(&p_rx->active_descq))
-               p_pkt = list_first_entry(&p_rx->active_descq,
-                                        struct qed_ll2_rx_packet, list_entry);
-       if (!p_pkt) {
-               DP_NOTICE(p_hwfn,
-                         "GSI Rx completion but active_descq is empty\n");
-               return -EIO;
-       }
-
-       list_del(&p_pkt->list_entry);
-       parse_flags = le16_to_cpu(p_cqe->rx_cqe_gsi.parse_flags.flags);
-       packet_length = le16_to_cpu(p_cqe->rx_cqe_gsi.data_length);
-       vlan = le16_to_cpu(p_cqe->rx_cqe_gsi.vlan);
-       src_mac_addrhi = le32_to_cpu(p_cqe->rx_cqe_gsi.src_mac_addrhi);
-       src_mac_addrlo = le16_to_cpu(p_cqe->rx_cqe_gsi.src_mac_addrlo);
-       if (qed_chain_consume(&p_rx->rxq_chain) != p_pkt->rxq_bd)
-               DP_NOTICE(p_hwfn,
-                         "Mismatch between active_descq and the LL2 Rx chain\n");
-       list_add_tail(&p_pkt->list_entry, &p_rx->free_descq);
-
-       spin_unlock_irqrestore(&p_rx->lock, lock_flags);
-       qed_ll2b_complete_rx_gsi_packet(p_hwfn,
-                                       p_ll2_info->my_id,
-                                       p_pkt->cookie,
-                                       p_pkt->rx_buf_addr,
-                                       packet_length,
-                                       p_cqe->rx_cqe_gsi.data_length_error,
-                                       parse_flags,
-                                       vlan,
-                                       src_mac_addrhi,
-                                       src_mac_addrlo, b_last_cqe);
-       spin_lock_irqsave(&p_rx->lock, lock_flags);
+       data->parse_flags = le16_to_cpu(p_cqe->rx_cqe_gsi.parse_flags.flags);
+       data->length.data_length = le16_to_cpu(p_cqe->rx_cqe_gsi.data_length);
+       data->vlan = le16_to_cpu(p_cqe->rx_cqe_gsi.vlan);
+       data->opaque_data_0 = le32_to_cpu(p_cqe->rx_cqe_gsi.src_mac_addrhi);
+       data->opaque_data_1 = le16_to_cpu(p_cqe->rx_cqe_gsi.src_mac_addrlo);
+       data->u.data_length_error = p_cqe->rx_cqe_gsi.data_length_error;
+}
 
-       return 0;
+static void qed_ll2_rxq_parse_reg(struct qed_hwfn *p_hwfn,
+                                 union core_rx_cqe_union *p_cqe,
+                                 struct qed_ll2_comp_rx_data *data)
+{
+       data->parse_flags = le16_to_cpu(p_cqe->rx_cqe_fp.parse_flags.flags);
+       data->length.packet_length =
+           le16_to_cpu(p_cqe->rx_cqe_fp.packet_length);
+       data->vlan = le16_to_cpu(p_cqe->rx_cqe_fp.vlan);
+       data->opaque_data_0 = le32_to_cpu(p_cqe->rx_cqe_fp.opaque_data.data[0]);
+       data->opaque_data_1 = le32_to_cpu(p_cqe->rx_cqe_fp.opaque_data.data[1]);
+       data->u.placement_offset = p_cqe->rx_cqe_fp.placement_offset;
 }
 
-static int qed_ll2_rxq_completion_reg(struct qed_hwfn *p_hwfn,
-                                     struct qed_ll2_info *p_ll2_conn,
-                                     union core_rx_cqe_union *p_cqe,
-                                     unsigned long *p_lock_flags,
-                                     bool b_last_cqe)
+static int
+qed_ll2_rxq_handle_completion(struct qed_hwfn *p_hwfn,
+                             struct qed_ll2_info *p_ll2_conn,
+                             union core_rx_cqe_union *p_cqe,
+                             unsigned long *p_lock_flags, bool b_last_cqe)
 {
        struct qed_ll2_rx_queue *p_rx = &p_ll2_conn->rx_queue;
        struct qed_ll2_rx_packet *p_pkt = NULL;
+       struct qed_ll2_comp_rx_data data;
 
        if (!list_empty(&p_rx->active_descq))
                p_pkt = list_first_entry(&p_rx->active_descq,
                                         struct qed_ll2_rx_packet, list_entry);
        if (!p_pkt) {
                DP_NOTICE(p_hwfn,
-                         "LL2 Rx completion but active_descq is empty\n");
+                         "[%d] LL2 Rx completion but active_descq is empty\n",
+                         p_ll2_conn->input.conn_type);
+
                return -EIO;
        }
        list_del(&p_pkt->list_entry);
 
+       if (p_cqe->rx_cqe_sp.type == CORE_RX_CQE_TYPE_REGULAR)
+               qed_ll2_rxq_parse_reg(p_hwfn, p_cqe, &data);
+       else
+               qed_ll2_rxq_parse_gsi(p_hwfn, p_cqe, &data);
        if (qed_chain_consume(&p_rx->rxq_chain) != p_pkt->rxq_bd)
                DP_NOTICE(p_hwfn,
                          "Mismatch between active_descq and the LL2 Rx chain\n");
+
        list_add_tail(&p_pkt->list_entry, &p_rx->free_descq);
 
+       data.connection_handle = p_ll2_conn->my_id;
+       data.cookie = p_pkt->cookie;
+       data.rx_buf_addr = p_pkt->rx_buf_addr;
+       data.b_last_packet = b_last_cqe;
+
        spin_unlock_irqrestore(&p_rx->lock, *p_lock_flags);
-       qed_ll2b_complete_rx_packet(p_hwfn, p_ll2_conn->my_id,
-                                   p_pkt, &p_cqe->rx_cqe_fp, b_last_cqe);
+       p_ll2_conn->cbs.rx_comp_cb(p_ll2_conn->cbs.cookie, &data);
+
        spin_lock_irqsave(&p_rx->lock, *p_lock_flags);
 
        return 0;
@@ -506,7 +468,7 @@ static int qed_ll2_rxq_completion_reg(struct qed_hwfn *p_hwfn,
 
 static int qed_ll2_rxq_completion(struct qed_hwfn *p_hwfn, void *cookie)
 {
-       struct qed_ll2_info *p_ll2_conn = cookie;
+       struct qed_ll2_info *p_ll2_conn = (struct qed_ll2_info *)cookie;
        struct qed_ll2_rx_queue *p_rx = &p_ll2_conn->rx_queue;
        union core_rx_cqe_union *cqe = NULL;
        u16 cq_new_idx = 0, cq_old_idx = 0;
@@ -520,7 +482,9 @@ static int qed_ll2_rxq_completion(struct qed_hwfn *p_hwfn, void *cookie)
        while (cq_new_idx != cq_old_idx) {
                bool b_last_cqe = (cq_new_idx == cq_old_idx);
 
-               cqe = qed_chain_consume(&p_rx->rcq_chain);
+               cqe =
+                   (union core_rx_cqe_union *)
+                   qed_chain_consume(&p_rx->rcq_chain);
                cq_old_idx = qed_chain_get_cons_idx(&p_rx->rcq_chain);
 
                DP_VERBOSE(p_hwfn,
@@ -534,13 +498,10 @@ static int qed_ll2_rxq_completion(struct qed_hwfn *p_hwfn, void *cookie)
                        rc = -EINVAL;
                        break;
                case CORE_RX_CQE_TYPE_GSI_OFFLOAD:
-                       rc = qed_ll2_rxq_completion_gsi(p_hwfn, p_ll2_conn,
-                                                       cqe, flags, b_last_cqe);
-                       break;
                case CORE_RX_CQE_TYPE_REGULAR:
-                       rc = qed_ll2_rxq_completion_reg(p_hwfn, p_ll2_conn,
-                                                       cqe, &flags,
-                                                       b_last_cqe);
+                       rc = qed_ll2_rxq_handle_completion(p_hwfn, p_ll2_conn,
+                                                          cqe, &flags,
+                                                          b_last_cqe);
                        break;
                default:
                        rc = -EIO;
@@ -564,10 +525,6 @@ static void qed_ll2_rxq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
        p_rx = &p_ll2_conn->rx_queue;
 
        while (!list_empty(&p_rx->active_descq)) {
-               dma_addr_t rx_buf_addr;
-               void *cookie;
-               bool b_last;
-
                p_pkt = list_first_entry(&p_rx->active_descq,
                                         struct qed_ll2_rx_packet, list_entry);
                if (!p_pkt)
@@ -575,22 +532,26 @@ static void qed_ll2_rxq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
 
                list_move_tail(&p_pkt->list_entry, &p_rx->free_descq);
 
-               if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO) {
+               if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_ISCSI_OOO) {
                        struct qed_ooo_buffer *p_buffer;
 
                        p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;
                        qed_ooo_put_free_buffer(p_hwfn, p_hwfn->p_ooo_info,
                                                p_buffer);
                } else {
-                       rx_buf_addr = p_pkt->rx_buf_addr;
-                       cookie = p_pkt->cookie;
+                       dma_addr_t rx_buf_addr = p_pkt->rx_buf_addr;
+                       void *cookie = p_pkt->cookie;
+                       bool b_last;
 
                        b_last = list_empty(&p_rx->active_descq);
+                       p_ll2_conn->cbs.rx_release_cb(p_ll2_conn->cbs.cookie,
+                                                     p_ll2_conn->my_id,
+                                                     cookie,
+                                                     rx_buf_addr, b_last);
                }
        }
 }
 
-#if IS_ENABLED(CONFIG_QED_ISCSI)
 static u8 qed_ll2_convert_rx_parse_to_tx_flags(u16 parse_flags)
 {
        u8 bd_flags = 0;
@@ -740,12 +701,13 @@ static void
 qed_ooo_submit_tx_buffers(struct qed_hwfn *p_hwfn,
                          struct qed_ll2_info *p_ll2_conn)
 {
+       struct qed_ll2_tx_pkt_info tx_pkt;
        struct qed_ooo_buffer *p_buffer;
-       int rc;
        u16 l4_hdr_offset_w;
        dma_addr_t first_frag;
        u16 parse_flags;
        u8 bd_flags;
+       int rc;
 
        /* Submit Tx buffers here */
        while ((p_buffer = qed_ooo_get_ready_buffer(p_hwfn,
@@ -760,13 +722,18 @@ qed_ooo_submit_tx_buffers(struct qed_hwfn *p_hwfn,
                SET_FIELD(bd_flags, CORE_TX_BD_DATA_FORCE_VLAN_MODE, 1);
                SET_FIELD(bd_flags, CORE_TX_BD_DATA_L4_PROTOCOL, 1);
 
-               rc = qed_ll2_prepare_tx_packet(p_hwfn, p_ll2_conn->my_id, 1,
-                                              p_buffer->vlan, bd_flags,
-                                              l4_hdr_offset_w,
-                                              p_ll2_conn->conn.tx_dest, 0,
-                                              first_frag,
-                                              p_buffer->packet_length,
-                                              p_buffer, true);
+               memset(&tx_pkt, 0, sizeof(tx_pkt));
+               tx_pkt.num_of_bds = 1;
+               tx_pkt.vlan = p_buffer->vlan;
+               tx_pkt.bd_flags = bd_flags;
+               tx_pkt.l4_hdr_offset_w = l4_hdr_offset_w;
+               tx_pkt.tx_dest = p_ll2_conn->tx_dest;
+               tx_pkt.first_frag = first_frag;
+               tx_pkt.first_frag_len = p_buffer->packet_length;
+               tx_pkt.cookie = p_buffer;
+
+               rc = qed_ll2_prepare_tx_packet(p_hwfn, p_ll2_conn->my_id,
+                                              &tx_pkt, true);
                if (rc) {
                        qed_ooo_put_ready_buffer(p_hwfn, p_hwfn->p_ooo_info,
                                                 p_buffer, false);
@@ -873,85 +840,6 @@ static int qed_ll2_lb_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
        return 0;
 }
 
-static int
-qed_ll2_acquire_connection_ooo(struct qed_hwfn *p_hwfn,
-                              struct qed_ll2_info *p_ll2_info,
-                              u16 rx_num_ooo_buffers, u16 mtu)
-{
-       struct qed_ooo_buffer *p_buf = NULL;
-       void *p_virt;
-       u16 buf_idx;
-       int rc = 0;
-
-       if (p_ll2_info->conn.conn_type != QED_LL2_TYPE_ISCSI_OOO)
-               return rc;
-
-       if (!rx_num_ooo_buffers)
-               return -EINVAL;
-
-       for (buf_idx = 0; buf_idx < rx_num_ooo_buffers; buf_idx++) {
-               p_buf = kzalloc(sizeof(*p_buf), GFP_KERNEL);
-               if (!p_buf) {
-                       rc = -ENOMEM;
-                       goto out;
-               }
-
-               p_buf->rx_buffer_size = mtu + 26 + ETH_CACHE_LINE_SIZE;
-               p_buf->rx_buffer_size = (p_buf->rx_buffer_size +
-                                        ETH_CACHE_LINE_SIZE - 1) &
-                                       ~(ETH_CACHE_LINE_SIZE - 1);
-               p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
-                                           p_buf->rx_buffer_size,
-                                           &p_buf->rx_buffer_phys_addr,
-                                           GFP_KERNEL);
-               if (!p_virt) {
-                       kfree(p_buf);
-                       rc = -ENOMEM;
-                       goto out;
-               }
-
-               p_buf->rx_buffer_virt_addr = p_virt;
-               qed_ooo_put_free_buffer(p_hwfn, p_hwfn->p_ooo_info, p_buf);
-       }
-
-       DP_VERBOSE(p_hwfn, QED_MSG_LL2,
-                  "Allocated [%04x] LL2 OOO buffers [each of size 0x%08x]\n",
-                  rx_num_ooo_buffers, p_buf->rx_buffer_size);
-
-out:
-       return rc;
-}
-
-static void
-qed_ll2_establish_connection_ooo(struct qed_hwfn *p_hwfn,
-                                struct qed_ll2_info *p_ll2_conn)
-{
-       if (p_ll2_conn->conn.conn_type != QED_LL2_TYPE_ISCSI_OOO)
-               return;
-
-       qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
-       qed_ooo_submit_rx_buffers(p_hwfn, p_ll2_conn);
-}
-
-static void qed_ll2_release_connection_ooo(struct qed_hwfn *p_hwfn,
-                                          struct qed_ll2_info *p_ll2_conn)
-{
-       struct qed_ooo_buffer *p_buffer;
-
-       if (p_ll2_conn->conn.conn_type != QED_LL2_TYPE_ISCSI_OOO)
-               return;
-
-       qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
-       while ((p_buffer = qed_ooo_get_free_buffer(p_hwfn,
-                                                  p_hwfn->p_ooo_info))) {
-               dma_free_coherent(&p_hwfn->cdev->pdev->dev,
-                                 p_buffer->rx_buffer_size,
-                                 p_buffer->rx_buffer_virt_addr,
-                                 p_buffer->rx_buffer_phys_addr);
-               kfree(p_buffer);
-       }
-}
-
 static void qed_ll2_stop_ooo(struct qed_dev *cdev)
 {
        struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
@@ -965,69 +853,11 @@ static void qed_ll2_stop_ooo(struct qed_dev *cdev)
        *handle = QED_LL2_UNUSED_HANDLE;
 }
 
-static int qed_ll2_start_ooo(struct qed_dev *cdev,
-                            struct qed_ll2_params *params)
-{
-       struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
-       u8 *handle = &hwfn->pf_params.iscsi_pf_params.ll2_ooo_queue_id;
-       struct qed_ll2_conn ll2_info = { 0 };
-       int rc;
-
-       ll2_info.conn_type = QED_LL2_TYPE_ISCSI_OOO;
-       ll2_info.mtu = params->mtu;
-       ll2_info.rx_drop_ttl0_flg = params->drop_ttl0_packets;
-       ll2_info.rx_vlan_removal_en = params->rx_vlan_stripping;
-       ll2_info.tx_tc = OOO_LB_TC;
-       ll2_info.tx_dest = CORE_TX_DEST_LB;
-
-       rc = qed_ll2_acquire_connection(hwfn, &ll2_info,
-                                       QED_LL2_RX_SIZE, QED_LL2_TX_SIZE,
-                                       handle);
-       if (rc) {
-               DP_INFO(cdev, "Failed to acquire LL2 OOO connection\n");
-               goto out;
-       }
-
-       rc = qed_ll2_establish_connection(hwfn, *handle);
-       if (rc) {
-               DP_INFO(cdev, "Failed to establist LL2 OOO connection\n");
-               goto fail;
-       }
-
-       return 0;
-
-fail:
-       qed_ll2_release_connection(hwfn, *handle);
-out:
-       *handle = QED_LL2_UNUSED_HANDLE;
-       return rc;
-}
-#else /* IS_ENABLED(CONFIG_QED_ISCSI) */
-static int qed_ll2_lb_rxq_completion(struct qed_hwfn *p_hwfn,
-                                    void *p_cookie) { return -EINVAL; }
-static int qed_ll2_lb_txq_completion(struct qed_hwfn *p_hwfn,
-                                    void *p_cookie) { return -EINVAL; }
-static inline int
-qed_ll2_acquire_connection_ooo(struct qed_hwfn *p_hwfn,
-                              struct qed_ll2_info *p_ll2_info,
-                              u16 rx_num_ooo_buffers, u16 mtu) { return 0; }
-static inline void
-qed_ll2_establish_connection_ooo(struct qed_hwfn *p_hwfn,
-                                struct qed_ll2_info *p_ll2_conn) { return; }
-static inline void
-qed_ll2_release_connection_ooo(struct qed_hwfn *p_hwfn,
-                              struct qed_ll2_info *p_ll2_conn) { return; }
-static inline void qed_ll2_stop_ooo(struct qed_dev *cdev) { return; }
-static inline int qed_ll2_start_ooo(struct qed_dev *cdev,
-                                   struct qed_ll2_params *params)
-                                   { return -EINVAL; }
-#endif /* IS_ENABLED(CONFIG_QED_ISCSI) */
-
 static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,
                                     struct qed_ll2_info *p_ll2_conn,
                                     u8 action_on_error)
 {
-       enum qed_ll2_conn_type conn_type = p_ll2_conn->conn.conn_type;
+       enum qed_ll2_conn_type conn_type = p_ll2_conn->input.conn_type;
        struct qed_ll2_rx_queue *p_rx = &p_ll2_conn->rx_queue;
        struct core_rx_start_ramrod_data *p_ramrod = NULL;
        struct qed_spq_entry *p_ent = NULL;
@@ -1053,16 +883,15 @@ static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,
        p_ramrod->sb_index = p_rx->rx_sb_index;
        p_ramrod->complete_event_flg = 1;
 
-       p_ramrod->mtu = cpu_to_le16(p_ll2_conn->conn.mtu);
-       DMA_REGPAIR_LE(p_ramrod->bd_base,
-                      p_rx->rxq_chain.p_phys_addr);
+       p_ramrod->mtu = cpu_to_le16(p_ll2_conn->input.mtu);
+       DMA_REGPAIR_LE(p_ramrod->bd_base, p_rx->rxq_chain.p_phys_addr);
        cqe_pbl_size = (u16)qed_chain_get_page_cnt(&p_rx->rcq_chain);
        p_ramrod->num_of_pbl_pages = cpu_to_le16(cqe_pbl_size);
        DMA_REGPAIR_LE(p_ramrod->cqe_pbl_addr,
                       qed_chain_get_pbl_phys(&p_rx->rcq_chain));
 
-       p_ramrod->drop_ttl0_flg = p_ll2_conn->conn.rx_drop_ttl0_flg;
-       p_ramrod->inner_vlan_removal_en = p_ll2_conn->conn.rx_vlan_removal_en;
+       p_ramrod->drop_ttl0_flg = p_ll2_conn->input.rx_drop_ttl0_flg;
+       p_ramrod->inner_vlan_removal_en = p_ll2_conn->input.rx_vlan_removal_en;
        p_ramrod->queue_id = p_ll2_conn->queue_id;
        p_ramrod->main_func_queue = (conn_type == QED_LL2_TYPE_ISCSI_OOO) ? 0
                                                                          : 1;
@@ -1077,14 +906,14 @@ static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,
        }
 
        p_ramrod->action_on_error.error_type = action_on_error;
-       p_ramrod->gsi_offload_flag = p_ll2_conn->conn.gsi_enable;
+       p_ramrod->gsi_offload_flag = p_ll2_conn->input.gsi_enable;
        return qed_spq_post(p_hwfn, p_ent, NULL);
 }
 
 static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
                                     struct qed_ll2_info *p_ll2_conn)
 {
-       enum qed_ll2_conn_type conn_type = p_ll2_conn->conn.conn_type;
+       enum qed_ll2_conn_type conn_type = p_ll2_conn->input.conn_type;
        struct qed_ll2_tx_queue *p_tx = &p_ll2_conn->tx_queue;
        struct core_tx_start_ramrod_data *p_ramrod = NULL;
        struct qed_spq_entry *p_ent = NULL;
@@ -1095,7 +924,7 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
        if (!QED_LL2_TX_REGISTERED(p_ll2_conn))
                return 0;
 
-       if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO)
+       if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_ISCSI_OOO)
                p_ll2_conn->tx_stats_en = 0;
        else
                p_ll2_conn->tx_stats_en = 1;
@@ -1116,7 +945,7 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
 
        p_ramrod->sb_id = cpu_to_le16(qed_int_get_sp_sb_id(p_hwfn));
        p_ramrod->sb_index = p_tx->tx_sb_index;
-       p_ramrod->mtu = cpu_to_le16(p_ll2_conn->conn.mtu);
+       p_ramrod->mtu = cpu_to_le16(p_ll2_conn->input.mtu);
        p_ramrod->stats_en = p_ll2_conn->tx_stats_en;
        p_ramrod->stats_id = p_ll2_conn->tx_stats_id;
 
@@ -1125,7 +954,7 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
        pbl_size = qed_chain_get_page_cnt(&p_tx->txq_chain);
        p_ramrod->pbl_size = cpu_to_le16(pbl_size);
 
-       switch (p_ll2_conn->conn.tx_tc) {
+       switch (p_ll2_conn->input.tx_tc) {
        case LB_TC:
                pq_id = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_LB);
                break;
@@ -1155,7 +984,8 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
                DP_NOTICE(p_hwfn, "Unknown connection type: %d\n", conn_type);
        }
 
-       p_ramrod->gsi_offload_flag = p_ll2_conn->conn.gsi_enable;
+       p_ramrod->gsi_offload_flag = p_ll2_conn->input.gsi_enable;
+
        return qed_spq_post(p_hwfn, p_ent, NULL);
 }
 
@@ -1211,20 +1041,20 @@ static int qed_sp_ll2_tx_queue_stop(struct qed_hwfn *p_hwfn,
 
 static int
 qed_ll2_acquire_connection_rx(struct qed_hwfn *p_hwfn,
-                             struct qed_ll2_info *p_ll2_info, u16 rx_num_desc)
+                             struct qed_ll2_info *p_ll2_info)
 {
        struct qed_ll2_rx_packet *p_descq;
        u32 capacity;
        int rc = 0;
 
-       if (!rx_num_desc)
+       if (!p_ll2_info->input.rx_num_desc)
                goto out;
 
        rc = qed_chain_alloc(p_hwfn->cdev,
                             QED_CHAIN_USE_TO_CONSUME_PRODUCE,
                             QED_CHAIN_MODE_NEXT_PTR,
                             QED_CHAIN_CNT_TYPE_U16,
-                            rx_num_desc,
+                            p_ll2_info->input.rx_num_desc,
                             sizeof(struct core_rx_bd),
                             &p_ll2_info->rx_queue.rxq_chain);
        if (rc) {
@@ -1246,7 +1076,7 @@ qed_ll2_acquire_connection_rx(struct qed_hwfn *p_hwfn,
                             QED_CHAIN_USE_TO_CONSUME_PRODUCE,
                             QED_CHAIN_MODE_PBL,
                             QED_CHAIN_CNT_TYPE_U16,
-                            rx_num_desc,
+                            p_ll2_info->input.rx_num_desc,
                             sizeof(struct core_rx_fast_path_cqe),
                             &p_ll2_info->rx_queue.rcq_chain);
        if (rc) {
@@ -1256,28 +1086,27 @@ qed_ll2_acquire_connection_rx(struct qed_hwfn *p_hwfn,
 
        DP_VERBOSE(p_hwfn, QED_MSG_LL2,
                   "Allocated LL2 Rxq [Type %08x] with 0x%08x buffers\n",
-                  p_ll2_info->conn.conn_type, rx_num_desc);
+                  p_ll2_info->input.conn_type, p_ll2_info->input.rx_num_desc);
 
 out:
        return rc;
 }
 
 static int qed_ll2_acquire_connection_tx(struct qed_hwfn *p_hwfn,
-                                        struct qed_ll2_info *p_ll2_info,
-                                        u16 tx_num_desc)
+                                        struct qed_ll2_info *p_ll2_info)
 {
        struct qed_ll2_tx_packet *p_descq;
        u32 capacity;
        int rc = 0;
 
-       if (!tx_num_desc)
+       if (!p_ll2_info->input.tx_num_desc)
                goto out;
 
        rc = qed_chain_alloc(p_hwfn->cdev,
                             QED_CHAIN_USE_TO_CONSUME_PRODUCE,
                             QED_CHAIN_MODE_PBL,
                             QED_CHAIN_CNT_TYPE_U16,
-                            tx_num_desc,
+                            p_ll2_info->input.tx_num_desc,
                             sizeof(struct core_tx_bd),
                             &p_ll2_info->tx_queue.txq_chain);
        if (rc)
@@ -1294,28 +1123,112 @@ static int qed_ll2_acquire_connection_tx(struct qed_hwfn *p_hwfn,
 
        DP_VERBOSE(p_hwfn, QED_MSG_LL2,
                   "Allocated LL2 Txq [Type %08x] with 0x%08x buffers\n",
-                  p_ll2_info->conn.conn_type, tx_num_desc);
+                  p_ll2_info->input.conn_type, p_ll2_info->input.tx_num_desc);
 
 out:
        if (rc)
                DP_NOTICE(p_hwfn,
                          "Can't allocate memory for Tx LL2 with 0x%08x buffers\n",
-                         tx_num_desc);
+                         p_ll2_info->input.tx_num_desc);
+       return rc;
+}
+
+static int
+qed_ll2_acquire_connection_ooo(struct qed_hwfn *p_hwfn,
+                              struct qed_ll2_info *p_ll2_info, u16 mtu)
+{
+       struct qed_ooo_buffer *p_buf = NULL;
+       void *p_virt;
+       u16 buf_idx;
+       int rc = 0;
+
+       if (p_ll2_info->input.conn_type != QED_LL2_TYPE_ISCSI_OOO)
+               return rc;
+
+       /* Correct number of requested OOO buffers if needed */
+       if (!p_ll2_info->input.rx_num_ooo_buffers) {
+               u16 num_desc = p_ll2_info->input.rx_num_desc;
+
+               if (!num_desc)
+                       return -EINVAL;
+               p_ll2_info->input.rx_num_ooo_buffers = num_desc * 2;
+       }
+
+       for (buf_idx = 0; buf_idx < p_ll2_info->input.rx_num_ooo_buffers;
+            buf_idx++) {
+               p_buf = kzalloc(sizeof(*p_buf), GFP_KERNEL);
+               if (!p_buf) {
+                       rc = -ENOMEM;
+                       goto out;
+               }
+
+               p_buf->rx_buffer_size = mtu + 26 + ETH_CACHE_LINE_SIZE;
+               p_buf->rx_buffer_size = (p_buf->rx_buffer_size +
+                                        ETH_CACHE_LINE_SIZE - 1) &
+                                       ~(ETH_CACHE_LINE_SIZE - 1);
+               p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+                                           p_buf->rx_buffer_size,
+                                           &p_buf->rx_buffer_phys_addr,
+                                           GFP_KERNEL);
+               if (!p_virt) {
+                       kfree(p_buf);
+                       rc = -ENOMEM;
+                       goto out;
+               }
+
+               p_buf->rx_buffer_virt_addr = p_virt;
+               qed_ooo_put_free_buffer(p_hwfn, p_hwfn->p_ooo_info, p_buf);
+       }
+
+       DP_VERBOSE(p_hwfn, QED_MSG_LL2,
+                  "Allocated [%04x] LL2 OOO buffers [each of size 0x%08x]\n",
+                  p_ll2_info->input.rx_num_ooo_buffers, p_buf->rx_buffer_size);
+
+out:
        return rc;
 }
 
-int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
-                              struct qed_ll2_conn *p_params,
-                              u16 rx_num_desc,
-                              u16 tx_num_desc,
-                              u8 *p_connection_handle)
+static int
+qed_ll2_set_cbs(struct qed_ll2_info *p_ll2_info, const struct qed_ll2_cbs *cbs)
 {
+       if (!cbs || (!cbs->rx_comp_cb ||
+                    !cbs->rx_release_cb ||
+                    !cbs->tx_comp_cb || !cbs->tx_release_cb || !cbs->cookie))
+               return -EINVAL;
+
+       p_ll2_info->cbs.rx_comp_cb = cbs->rx_comp_cb;
+       p_ll2_info->cbs.rx_release_cb = cbs->rx_release_cb;
+       p_ll2_info->cbs.tx_comp_cb = cbs->tx_comp_cb;
+       p_ll2_info->cbs.tx_release_cb = cbs->tx_release_cb;
+       p_ll2_info->cbs.cookie = cbs->cookie;
+
+       return 0;
+}
+
+static enum core_error_handle
+qed_ll2_get_error_choice(enum qed_ll2_error_handle err)
+{
+       switch (err) {
+       case QED_LL2_DROP_PACKET:
+               return LL2_DROP_PACKET;
+       case QED_LL2_DO_NOTHING:
+               return LL2_DO_NOTHING;
+       case QED_LL2_ASSERT:
+               return LL2_ASSERT;
+       default:
+               return LL2_DO_NOTHING;
+       }
+}
+
+int qed_ll2_acquire_connection(void *cxt, struct qed_ll2_acquire_data *data)
+{
+       struct qed_hwfn *p_hwfn = cxt;
        qed_int_comp_cb_t comp_rx_cb, comp_tx_cb;
        struct qed_ll2_info *p_ll2_info = NULL;
+       u8 i, *p_tx_max;
        int rc;
-       u8 i;
 
-       if (!p_connection_handle || !p_hwfn->p_ll2_info)
+       if (!data->p_connection_handle || !p_hwfn->p_ll2_info)
                return -EINVAL;
 
        /* Find a free connection to be used */
@@ -1334,23 +1247,40 @@ int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
        if (!p_ll2_info)
                return -EBUSY;
 
-       p_ll2_info->conn = *p_params;
+       memcpy(&p_ll2_info->input, &data->input, sizeof(p_ll2_info->input));
 
-       rc = qed_ll2_acquire_connection_rx(p_hwfn, p_ll2_info, rx_num_desc);
+       p_ll2_info->tx_dest = (data->input.tx_dest == QED_LL2_TX_DEST_NW) ?
+                             CORE_TX_DEST_NW : CORE_TX_DEST_LB;
+
+       /* Correct maximum number of Tx BDs */
+       p_tx_max = &p_ll2_info->input.tx_max_bds_per_packet;
+       if (*p_tx_max == 0)
+               *p_tx_max = CORE_LL2_TX_MAX_BDS_PER_PACKET;
+       else
+               *p_tx_max = min_t(u8, *p_tx_max,
+                                 CORE_LL2_TX_MAX_BDS_PER_PACKET);
+
+       rc = qed_ll2_set_cbs(p_ll2_info, data->cbs);
+       if (rc) {
+               DP_NOTICE(p_hwfn, "Invalid callback functions\n");
+               goto q_allocate_fail;
+       }
+
+       rc = qed_ll2_acquire_connection_rx(p_hwfn, p_ll2_info);
        if (rc)
                goto q_allocate_fail;
 
-       rc = qed_ll2_acquire_connection_tx(p_hwfn, p_ll2_info, tx_num_desc);
+       rc = qed_ll2_acquire_connection_tx(p_hwfn, p_ll2_info);
        if (rc)
                goto q_allocate_fail;
 
        rc = qed_ll2_acquire_connection_ooo(p_hwfn, p_ll2_info,
-                                           rx_num_desc * 2, p_params->mtu);
+                                           data->input.mtu);
        if (rc)
                goto q_allocate_fail;
 
        /* Register callbacks for the Rx/Tx queues */
-       if (p_params->conn_type == QED_LL2_TYPE_ISCSI_OOO) {
+       if (data->input.conn_type == QED_LL2_TYPE_ISCSI_OOO) {
                comp_rx_cb = qed_ll2_lb_rxq_completion;
                comp_tx_cb = qed_ll2_lb_txq_completion;
        } else {
@@ -1358,7 +1288,7 @@ int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
                comp_tx_cb = qed_ll2_txq_completion;
        }
 
-       if (rx_num_desc) {
+       if (data->input.rx_num_desc) {
                qed_int_register_cb(p_hwfn, comp_rx_cb,
                                    &p_hwfn->p_ll2_info[i],
                                    &p_ll2_info->rx_queue.rx_sb_index,
@@ -1366,7 +1296,7 @@ int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
                p_ll2_info->rx_queue.b_cb_registred = true;
        }
 
-       if (tx_num_desc) {
+       if (data->input.tx_num_desc) {
                qed_int_register_cb(p_hwfn,
                                    comp_tx_cb,
                                    &p_hwfn->p_ll2_info[i],
@@ -1375,7 +1305,7 @@ int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
                p_ll2_info->tx_queue.b_cb_registred = true;
        }
 
-       *p_connection_handle = i;
+       *data->p_connection_handle = i;
        return rc;
 
 q_allocate_fail:
@@ -1386,24 +1316,39 @@ int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
 static int qed_ll2_establish_connection_rx(struct qed_hwfn *p_hwfn,
                                           struct qed_ll2_info *p_ll2_conn)
 {
+       enum qed_ll2_error_handle error_input;
+       enum core_error_handle error_mode;
        u8 action_on_error = 0;
 
        if (!QED_LL2_RX_REGISTERED(p_ll2_conn))
                return 0;
 
        DIRECT_REG_WR(p_ll2_conn->rx_queue.set_prod_addr, 0x0);
-
-       SET_FIELD(action_on_error,
-                 CORE_RX_ACTION_ON_ERROR_PACKET_TOO_BIG,
-                 p_ll2_conn->conn.ai_err_packet_too_big);
+       error_input = p_ll2_conn->input.ai_err_packet_too_big;
+       error_mode = qed_ll2_get_error_choice(error_input);
        SET_FIELD(action_on_error,
-                 CORE_RX_ACTION_ON_ERROR_NO_BUFF, p_ll2_conn->conn.ai_err_no_buf);
+                 CORE_RX_ACTION_ON_ERROR_PACKET_TOO_BIG, error_mode);
+       error_input = p_ll2_conn->input.ai_err_no_buf;
+       error_mode = qed_ll2_get_error_choice(error_input);
+       SET_FIELD(action_on_error, CORE_RX_ACTION_ON_ERROR_NO_BUFF, error_mode);
 
        return qed_sp_ll2_rx_queue_start(p_hwfn, p_ll2_conn, action_on_error);
 }
 
-int qed_ll2_establish_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
+static void
+qed_ll2_establish_connection_ooo(struct qed_hwfn *p_hwfn,
+                                struct qed_ll2_info *p_ll2_conn)
+{
+       if (p_ll2_conn->input.conn_type != QED_LL2_TYPE_ISCSI_OOO)
+               return;
+
+       qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
+       qed_ooo_submit_rx_buffers(p_hwfn, p_ll2_conn);
+}
+
+int qed_ll2_establish_connection(void *cxt, u8 connection_handle)
 {
+       struct qed_hwfn *p_hwfn = cxt;
        struct qed_ll2_info *p_ll2_conn;
        struct qed_ll2_rx_queue *p_rx;
        struct qed_ll2_tx_queue *p_tx;
@@ -1481,7 +1426,7 @@ int qed_ll2_establish_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
 
        qed_ll2_establish_connection_ooo(p_hwfn, p_ll2_conn);
 
-       if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_FCOE) {
+       if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_FCOE) {
                qed_llh_add_protocol_filter(p_hwfn, p_ptt,
                                            0x8906, 0,
                                            QED_LLH_FILTER_ETHERTYPE);
@@ -1530,11 +1475,12 @@ static void qed_ll2_post_rx_buffer_notify_fw(struct qed_hwfn *p_hwfn,
        DIRECT_REG_WR(p_rx->set_prod_addr, *((u32 *)&rx_prod));
 }
 
-int qed_ll2_post_rx_buffer(struct qed_hwfn *p_hwfn,
+int qed_ll2_post_rx_buffer(void *cxt,
                           u8 connection_handle,
                           dma_addr_t addr,
                           u16 buf_len, void *cookie, u8 notify_fw)
 {
+       struct qed_hwfn *p_hwfn = cxt;
        struct core_rx_bd_with_buff_len *p_curb = NULL;
        struct qed_ll2_rx_packet *p_curp = NULL;
        struct qed_ll2_info *p_ll2_conn;
@@ -1593,20 +1539,18 @@ int qed_ll2_post_rx_buffer(struct qed_hwfn *p_hwfn,
 static void qed_ll2_prepare_tx_packet_set(struct qed_hwfn *p_hwfn,
                                          struct qed_ll2_tx_queue *p_tx,
                                          struct qed_ll2_tx_packet *p_curp,
-                                         u8 num_of_bds,
-                                         dma_addr_t first_frag,
-                                         u16 first_frag_len, void *p_cookie,
+                                         struct qed_ll2_tx_pkt_info *pkt,
                                          u8 notify_fw)
 {
        list_del(&p_curp->list_entry);
-       p_curp->cookie = p_cookie;
-       p_curp->bd_used = num_of_bds;
+       p_curp->cookie = pkt->cookie;
+       p_curp->bd_used = pkt->num_of_bds;
        p_curp->notify_fw = notify_fw;
        p_tx->cur_send_packet = p_curp;
        p_tx->cur_send_frag_num = 0;
 
-       p_curp->bds_set[p_tx->cur_send_frag_num].tx_frag = first_frag;
-       p_curp->bds_set[p_tx->cur_send_frag_num].frag_len = first_frag_len;
+       p_curp->bds_set[p_tx->cur_send_frag_num].tx_frag = pkt->first_frag;
+       p_curp->bds_set[p_tx->cur_send_frag_num].frag_len = pkt->first_frag_len;
        p_tx->cur_send_frag_num++;
 }
 
@@ -1614,51 +1558,52 @@ static void
 qed_ll2_prepare_tx_packet_set_bd(struct qed_hwfn *p_hwfn,
                                 struct qed_ll2_info *p_ll2,
                                 struct qed_ll2_tx_packet *p_curp,
-                                u8 num_of_bds,
-                                enum core_tx_dest tx_dest,
-                                u16 vlan,
-                                u8 bd_flags,
-                                u16 l4_hdr_offset_w,
-                                enum core_roce_flavor_type roce_flavor,
-                                dma_addr_t first_frag,
-                                u16 first_frag_len)
+                                struct qed_ll2_tx_pkt_info *pkt)
 {
        struct qed_chain *p_tx_chain = &p_ll2->tx_queue.txq_chain;
        u16 prod_idx = qed_chain_get_prod_idx(p_tx_chain);
        struct core_tx_bd *start_bd = NULL;
+       enum core_roce_flavor_type roce_flavor;
+       enum core_tx_dest tx_dest;
        u16 bd_data = 0, frag_idx;
 
+       roce_flavor = (pkt->qed_roce_flavor == QED_LL2_ROCE) ? CORE_ROCE
+                                                            : CORE_RROCE;
+
+       tx_dest = (pkt->tx_dest == QED_LL2_TX_DEST_NW) ? CORE_TX_DEST_NW
+                                                      : CORE_TX_DEST_LB;
+
        start_bd = (struct core_tx_bd *)qed_chain_produce(p_tx_chain);
-       start_bd->nw_vlan_or_lb_echo = cpu_to_le16(vlan);
+       start_bd->nw_vlan_or_lb_echo = cpu_to_le16(pkt->vlan);
        SET_FIELD(start_bd->bitfield1, CORE_TX_BD_L4_HDR_OFFSET_W,
-                 cpu_to_le16(l4_hdr_offset_w));
+                 cpu_to_le16(pkt->l4_hdr_offset_w));
        SET_FIELD(start_bd->bitfield1, CORE_TX_BD_TX_DST, tx_dest);
-       bd_data |= bd_flags;
+       bd_data |= pkt->bd_flags;
        SET_FIELD(bd_data, CORE_TX_BD_DATA_START_BD, 0x1);
-       SET_FIELD(bd_data, CORE_TX_BD_DATA_NBDS, num_of_bds);
+       SET_FIELD(bd_data, CORE_TX_BD_DATA_NBDS, pkt->num_of_bds);
        SET_FIELD(bd_data, CORE_TX_BD_DATA_ROCE_FLAV, roce_flavor);
        start_bd->bd_data.as_bitfield = cpu_to_le16(bd_data);
-       DMA_REGPAIR_LE(start_bd->addr, first_frag);
-       start_bd->nbytes = cpu_to_le16(first_frag_len);
+       DMA_REGPAIR_LE(start_bd->addr, pkt->first_frag);
+       start_bd->nbytes = cpu_to_le16(pkt->first_frag_len);
 
        DP_VERBOSE(p_hwfn,
                   (NETIF_MSG_TX_QUEUED | QED_MSG_LL2),
                   "LL2 [q 0x%02x cid 0x%08x type 0x%08x] Tx Producer at [0x%04x] - set with a %04x bytes %02x BDs buffer at %08x:%08x\n",
                   p_ll2->queue_id,
                   p_ll2->cid,
-                  p_ll2->conn.conn_type,
+                  p_ll2->input.conn_type,
                   prod_idx,
-                  first_frag_len,
-                  num_of_bds,
+                  pkt->first_frag_len,
+                  pkt->num_of_bds,
                   le32_to_cpu(start_bd->addr.hi),
                   le32_to_cpu(start_bd->addr.lo));
 
-       if (p_ll2->tx_queue.cur_send_frag_num == num_of_bds)
+       if (p_ll2->tx_queue.cur_send_frag_num == pkt->num_of_bds)
                return;
 
        /* Need to provide the packet with additional BDs for frags */
        for (frag_idx = p_ll2->tx_queue.cur_send_frag_num;
-            frag_idx < num_of_bds; frag_idx++) {
+            frag_idx < pkt->num_of_bds; frag_idx++) {
                struct core_tx_bd **p_bd = &p_curp->bds_set[frag_idx].txq_bd;
 
                *p_bd = (struct core_tx_bd *)qed_chain_produce(p_tx_chain);
@@ -1721,26 +1666,20 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn *p_hwfn,
                   (NETIF_MSG_TX_QUEUED | QED_MSG_LL2),
                   "LL2 [q 0x%02x cid 0x%08x type 0x%08x] Doorbelled [producer 0x%04x]\n",
                   p_ll2_conn->queue_id,
-                  p_ll2_conn->cid, p_ll2_conn->conn.conn_type, db_msg.spq_prod);
+                  p_ll2_conn->cid,
+                  p_ll2_conn->input.conn_type, db_msg.spq_prod);
 }
 
-int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
+int qed_ll2_prepare_tx_packet(void *cxt,
                              u8 connection_handle,
-                             u8 num_of_bds,
-                             u16 vlan,
-                             u8 bd_flags,
-                             u16 l4_hdr_offset_w,
-                             enum qed_ll2_tx_dest e_tx_dest,
-                             enum qed_ll2_roce_flavor_type qed_roce_flavor,
-                             dma_addr_t first_frag,
-                             u16 first_frag_len, void *cookie, u8 notify_fw)
+                             struct qed_ll2_tx_pkt_info *pkt,
+                             bool notify_fw)
 {
+       struct qed_hwfn *p_hwfn = cxt;
        struct qed_ll2_tx_packet *p_curp = NULL;
        struct qed_ll2_info *p_ll2_conn = NULL;
-       enum core_roce_flavor_type roce_flavor;
        struct qed_ll2_tx_queue *p_tx;
        struct qed_chain *p_tx_chain;
-       enum core_tx_dest tx_dest;
        unsigned long flags;
        int rc = 0;
 
@@ -1750,7 +1689,7 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
        p_tx = &p_ll2_conn->tx_queue;
        p_tx_chain = &p_tx->txq_chain;
 
-       if (num_of_bds > CORE_LL2_TX_MAX_BDS_PER_PACKET)
+       if (pkt->num_of_bds > CORE_LL2_TX_MAX_BDS_PER_PACKET)
                return -EIO;
 
        spin_lock_irqsave(&p_tx->lock, flags);
@@ -1763,7 +1702,7 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
        if (!list_empty(&p_tx->free_descq))
                p_curp = list_first_entry(&p_tx->free_descq,
                                          struct qed_ll2_tx_packet, list_entry);
-       if (p_curp && qed_chain_get_elem_left(p_tx_chain) < num_of_bds)
+       if (p_curp && qed_chain_get_elem_left(p_tx_chain) < pkt->num_of_bds)
                p_curp = NULL;
 
        if (!p_curp) {
@@ -1771,26 +1710,10 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
                goto out;
        }
 
-       tx_dest = e_tx_dest == QED_LL2_TX_DEST_NW ? CORE_TX_DEST_NW :
-                                                   CORE_TX_DEST_LB;
-       if (qed_roce_flavor == QED_LL2_ROCE) {
-               roce_flavor = CORE_ROCE;
-       } else if (qed_roce_flavor == QED_LL2_RROCE) {
-               roce_flavor = CORE_RROCE;
-       } else {
-               rc = -EINVAL;
-               goto out;
-       }
-
        /* Prepare packet and BD, and perhaps send a doorbell to FW */
-       qed_ll2_prepare_tx_packet_set(p_hwfn, p_tx, p_curp,
-                                     num_of_bds, first_frag,
-                                     first_frag_len, cookie, notify_fw);
-       qed_ll2_prepare_tx_packet_set_bd(p_hwfn, p_ll2_conn, p_curp,
-                                        num_of_bds, tx_dest,
-                                        vlan, bd_flags, l4_hdr_offset_w,
-                                        roce_flavor,
-                                        first_frag, first_frag_len);
+       qed_ll2_prepare_tx_packet_set(p_hwfn, p_tx, p_curp, pkt, notify_fw);
+
+       qed_ll2_prepare_tx_packet_set_bd(p_hwfn, p_ll2_conn, p_curp, pkt);
 
        qed_ll2_tx_packet_notify(p_hwfn, p_ll2_conn);
 
@@ -1799,11 +1722,12 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
        return rc;
 }
 
-int qed_ll2_set_fragment_of_tx_packet(struct qed_hwfn *p_hwfn,
+int qed_ll2_set_fragment_of_tx_packet(void *cxt,
                                      u8 connection_handle,
                                      dma_addr_t addr, u16 nbytes)
 {
        struct qed_ll2_tx_packet *p_cur_send_packet = NULL;
+       struct qed_hwfn *p_hwfn = cxt;
        struct qed_ll2_info *p_ll2_conn = NULL;
        u16 cur_send_frag_num = 0;
        struct core_tx_bd *p_bd;
@@ -1838,8 +1762,9 @@ int qed_ll2_set_fragment_of_tx_packet(struct qed_hwfn *p_hwfn,
        return 0;
 }
 
-int qed_ll2_terminate_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
+int qed_ll2_terminate_connection(void *cxt, u8 connection_handle)
 {
+       struct qed_hwfn *p_hwfn = cxt;
        struct qed_ll2_info *p_ll2_conn = NULL;
        int rc = -EINVAL;
        struct qed_ptt *p_ptt;
@@ -1869,10 +1794,10 @@ int qed_ll2_terminate_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
                qed_ll2_rxq_flush(p_hwfn, connection_handle);
        }
 
-       if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO)
+       if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_ISCSI_OOO)
                qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
 
-       if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_FCOE) {
+       if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_FCOE) {
                qed_llh_remove_protocol_filter(p_hwfn, p_ptt,
                                               0x8906, 0,
                                               QED_LLH_FILTER_ETHERTYPE);
@@ -1886,8 +1811,28 @@ int qed_ll2_terminate_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
        return rc;
 }
 
-void qed_ll2_release_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
+static void qed_ll2_release_connection_ooo(struct qed_hwfn *p_hwfn,
+                                          struct qed_ll2_info *p_ll2_conn)
 {
+       struct qed_ooo_buffer *p_buffer;
+
+       if (p_ll2_conn->input.conn_type != QED_LL2_TYPE_ISCSI_OOO)
+               return;
+
+       qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
+       while ((p_buffer = qed_ooo_get_free_buffer(p_hwfn,
+                                                  p_hwfn->p_ooo_info))) {
+               dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+                                 p_buffer->rx_buffer_size,
+                                 p_buffer->rx_buffer_virt_addr,
+                                 p_buffer->rx_buffer_phys_addr);
+               kfree(p_buffer);
+       }
+}
+
+void qed_ll2_release_connection(void *cxt, u8 connection_handle)
+{
+       struct qed_hwfn *p_hwfn = cxt;
        struct qed_ll2_info *p_ll2_conn = NULL;
 
        p_ll2_conn = qed_ll2_handle_sanity(p_hwfn, connection_handle);
@@ -1957,6 +1902,27 @@ void qed_ll2_free(struct qed_hwfn *p_hwfn)
        p_hwfn->p_ll2_info = NULL;
 }
 
+static void _qed_ll2_get_port_stats(struct qed_hwfn *p_hwfn,
+                                   struct qed_ptt *p_ptt,
+                                   struct qed_ll2_stats *p_stats)
+{
+       struct core_ll2_port_stats port_stats;
+
+       memset(&port_stats, 0, sizeof(port_stats));
+       qed_memcpy_from(p_hwfn, p_ptt, &port_stats,
+                       BAR0_MAP_REG_TSDM_RAM +
+                       TSTORM_LL2_PORT_STAT_OFFSET(MFW_PORT(p_hwfn)),
+                       sizeof(port_stats));
+
+       p_stats->gsi_invalid_hdr = HILO_64_REGPAIR(port_stats.gsi_invalid_hdr);
+       p_stats->gsi_invalid_pkt_length =
+           HILO_64_REGPAIR(port_stats.gsi_invalid_pkt_length);
+       p_stats->gsi_unsupported_pkt_typ =
+           HILO_64_REGPAIR(port_stats.gsi_unsupported_pkt_typ);
+       p_stats->gsi_crcchksm_error =
+           HILO_64_REGPAIR(port_stats.gsi_crcchksm_error);
+}
+
 static void _qed_ll2_get_tstats(struct qed_hwfn *p_hwfn,
                                struct qed_ptt *p_ptt,
                                struct qed_ll2_info *p_ll2_conn,
@@ -2020,9 +1986,10 @@ static void _qed_ll2_get_pstats(struct qed_hwfn *p_hwfn,
        p_stats->sent_bcast_pkts = HILO_64_REGPAIR(pstats.sent_bcast_pkts);
 }
 
-int qed_ll2_get_stats(struct qed_hwfn *p_hwfn,
+int qed_ll2_get_stats(void *cxt,
                      u8 connection_handle, struct qed_ll2_stats *p_stats)
 {
+       struct qed_hwfn *p_hwfn = cxt;
        struct qed_ll2_info *p_ll2_conn = NULL;
        struct qed_ptt *p_ptt;
 
@@ -2040,6 +2007,8 @@ int qed_ll2_get_stats(struct qed_hwfn *p_hwfn,
                return -EINVAL;
        }
 
+       if (p_ll2_conn->input.gsi_enable)
+               _qed_ll2_get_port_stats(p_hwfn, p_ptt, p_stats);
        _qed_ll2_get_tstats(p_hwfn, p_ptt, p_ll2_conn, p_stats);
        _qed_ll2_get_ustats(p_hwfn, p_ptt, p_ll2_conn, p_stats);
        if (p_ll2_conn->tx_stats_en)
@@ -2049,6 +2018,17 @@ int qed_ll2_get_stats(struct qed_hwfn *p_hwfn,
        return 0;
 }
 
+static void qed_ll2b_release_rx_packet(void *cxt,
+                                      u8 connection_handle,
+                                      void *cookie,
+                                      dma_addr_t rx_buf_addr,
+                                      bool b_last_packet)
+{
+       struct qed_hwfn *p_hwfn = cxt;
+
+       qed_ll2_dealloc_buffer(p_hwfn->cdev, cookie);
+}
+
 static void qed_ll2_register_cb_ops(struct qed_dev *cdev,
                                    const struct qed_ll2_cb_ops *ops,
                                    void *cookie)
@@ -2057,21 +2037,86 @@ static void qed_ll2_register_cb_ops(struct qed_dev *cdev,
        cdev->ll2->cb_cookie = cookie;
 }
 
+struct qed_ll2_cbs ll2_cbs = {
+       .rx_comp_cb = &qed_ll2b_complete_rx_packet,
+       .rx_release_cb = &qed_ll2b_release_rx_packet,
+       .tx_comp_cb = &qed_ll2b_complete_tx_packet,
+       .tx_release_cb = &qed_ll2b_complete_tx_packet,
+};
+
+static void qed_ll2_set_conn_data(struct qed_dev *cdev,
+                                 struct qed_ll2_acquire_data *data,
+                                 struct qed_ll2_params *params,
+                                 enum qed_ll2_conn_type conn_type,
+                                 u8 *handle, bool lb)
+{
+       memset(data, 0, sizeof(*data));
+
+       data->input.conn_type = conn_type;
+       data->input.mtu = params->mtu;
+       data->input.rx_num_desc = QED_LL2_RX_SIZE;
+       data->input.rx_drop_ttl0_flg = params->drop_ttl0_packets;
+       data->input.rx_vlan_removal_en = params->rx_vlan_stripping;
+       data->input.tx_num_desc = QED_LL2_TX_SIZE;
+       data->p_connection_handle = handle;
+       data->cbs = &ll2_cbs;
+       ll2_cbs.cookie = QED_LEADING_HWFN(cdev);
+
+       if (lb) {
+               data->input.tx_tc = OOO_LB_TC;
+               data->input.tx_dest = QED_LL2_TX_DEST_LB;
+       } else {
+               data->input.tx_tc = 0;
+               data->input.tx_dest = QED_LL2_TX_DEST_NW;
+       }
+}
+
+static int qed_ll2_start_ooo(struct qed_dev *cdev,
+                            struct qed_ll2_params *params)
+{
+       struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
+       u8 *handle = &hwfn->pf_params.iscsi_pf_params.ll2_ooo_queue_id;
+       struct qed_ll2_acquire_data data;
+       int rc;
+
+       qed_ll2_set_conn_data(cdev, &data, params,
+                             QED_LL2_TYPE_ISCSI_OOO, handle, true);
+
+       rc = qed_ll2_acquire_connection(hwfn, &data);
+       if (rc) {
+               DP_INFO(cdev, "Failed to acquire LL2 OOO connection\n");
+               goto out;
+       }
+
+       rc = qed_ll2_establish_connection(hwfn, *handle);
+       if (rc) {
+               DP_INFO(cdev, "Failed to establist LL2 OOO connection\n");
+               goto fail;
+       }
+
+       return 0;
+
+fail:
+       qed_ll2_release_connection(hwfn, *handle);
+out:
+       *handle = QED_LL2_UNUSED_HANDLE;
+       return rc;
+}
+
 static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
 {
-       struct qed_ll2_conn ll2_info;
        struct qed_ll2_buffer *buffer, *tmp_buffer;
        enum qed_ll2_conn_type conn_type;
+       struct qed_ll2_acquire_data data;
        struct qed_ptt *p_ptt;
        int rc, i;
-       u8 gsi_enable = 1;
+
 
        /* Initialize LL2 locks & lists */
        INIT_LIST_HEAD(&cdev->ll2->list);
        spin_lock_init(&cdev->ll2->lock);
        cdev->ll2->rx_size = NET_SKB_PAD + ETH_HLEN +
                             L1_CACHE_BYTES + params->mtu;
-       cdev->ll2->frags_mapped = params->frags_mapped;
 
        /*Allocate memory for LL2 */
        DP_INFO(cdev, "Allocating LL2 buffers of size %08x bytes\n",
@@ -2096,11 +2141,9 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
        switch (QED_LEADING_HWFN(cdev)->hw_info.personality) {
        case QED_PCI_FCOE:
                conn_type = QED_LL2_TYPE_FCOE;
-               gsi_enable = 0;
                break;
        case QED_PCI_ISCSI:
                conn_type = QED_LL2_TYPE_ISCSI;
-               gsi_enable = 0;
                break;
        case QED_PCI_ETH_ROCE:
                conn_type = QED_LL2_TYPE_ROCE;
@@ -2109,20 +2152,10 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
                conn_type = QED_LL2_TYPE_TEST;
        }
 
-       /* Prepare the temporary ll2 information */
-       memset(&ll2_info, 0, sizeof(ll2_info));
+       qed_ll2_set_conn_data(cdev, &data, params, conn_type,
+                             &cdev->ll2->handle, false);
 
-       ll2_info.conn_type = conn_type;
-       ll2_info.mtu = params->mtu;
-       ll2_info.rx_drop_ttl0_flg = params->drop_ttl0_packets;
-       ll2_info.rx_vlan_removal_en = params->rx_vlan_stripping;
-       ll2_info.tx_tc = 0;
-       ll2_info.tx_dest = CORE_TX_DEST_NW;
-       ll2_info.gsi_enable = gsi_enable;
-
-       rc = qed_ll2_acquire_connection(QED_LEADING_HWFN(cdev), &ll2_info,
-                                       QED_LL2_RX_SIZE, QED_LL2_TX_SIZE,
-                                       &cdev->ll2->handle);
+       rc = qed_ll2_acquire_connection(QED_LEADING_HWFN(cdev), &data);
        if (rc) {
                DP_INFO(cdev, "Failed to acquire LL2 connection\n");
                goto fail;
@@ -2245,6 +2278,7 @@ static int qed_ll2_stop(struct qed_dev *cdev)
 
 static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb)
 {
+       struct qed_ll2_tx_pkt_info pkt;
        const skb_frag_t *frag;
        int rc = -EINVAL, i;
        dma_addr_t mapping;
@@ -2279,32 +2313,30 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb)
                flags |= BIT(CORE_TX_BD_DATA_VLAN_INSERTION_SHIFT);
        }
 
-       rc = qed_ll2_prepare_tx_packet(QED_LEADING_HWFN(cdev),
-                                      cdev->ll2->handle,
-                                      1 + skb_shinfo(skb)->nr_frags,
-                                      vlan, flags, 0, QED_LL2_TX_DEST_NW,
-                                      0 /* RoCE FLAVOR */,
-                                      mapping, skb->len, skb, 1);
+       memset(&pkt, 0, sizeof(pkt));
+       pkt.num_of_bds = 1 + skb_shinfo(skb)->nr_frags;
+       pkt.vlan = vlan;
+       pkt.bd_flags = flags;
+       pkt.tx_dest = QED_LL2_TX_DEST_NW;
+       pkt.first_frag = mapping;
+       pkt.first_frag_len = skb->len;
+       pkt.cookie = skb;
+
+       rc = qed_ll2_prepare_tx_packet(&cdev->hwfns[0], cdev->ll2->handle,
+                                      &pkt, 1);
        if (rc)
                goto err;
 
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                frag = &skb_shinfo(skb)->frags[i];
-               if (!cdev->ll2->frags_mapped) {
-                       mapping = skb_frag_dma_map(&cdev->pdev->dev, frag, 0,
-                                                  skb_frag_size(frag),
-                                                  DMA_TO_DEVICE);
-
-                       if (unlikely(dma_mapping_error(&cdev->pdev->dev,
-                                                      mapping))) {
-                               DP_NOTICE(cdev,
-                                         "Unable to map frag - dropping packet\n");
-                               rc = -ENOMEM;
-                               goto err;
-                       }
-               } else {
-                       mapping = page_to_phys(skb_frag_page(frag)) |
-                           frag->page_offset;
+
+               mapping = skb_frag_dma_map(&cdev->pdev->dev, frag, 0,
+                                          skb_frag_size(frag), DMA_TO_DEVICE);
+
+               if (unlikely(dma_mapping_error(&cdev->pdev->dev, mapping))) {
+                       DP_NOTICE(cdev,
+                                 "Unable to map frag - dropping packet\n");
+                       goto err;
                }
 
                rc = qed_ll2_set_fragment_of_tx_packet(QED_LEADING_HWFN(cdev),
index 2c07d0ed971a6de112037085a31a581d11fab77b..a822528e9c63012d689a878233a47f11f00d701a 100644 (file)
 
 #define QED_MAX_NUM_OF_LL2_CONNECTIONS                    (4)
 
-enum qed_ll2_roce_flavor_type {
-       QED_LL2_ROCE,
-       QED_LL2_RROCE,
-       MAX_QED_LL2_ROCE_FLAVOR_TYPE
-};
-
-enum qed_ll2_conn_type {
-       QED_LL2_TYPE_FCOE,
-       QED_LL2_TYPE_ISCSI,
-       QED_LL2_TYPE_TEST,
-       QED_LL2_TYPE_ISCSI_OOO,
-       QED_LL2_TYPE_RESERVED2,
-       QED_LL2_TYPE_ROCE,
-       QED_LL2_TYPE_RESERVED3,
-       MAX_QED_LL2_RX_CONN_TYPE
-};
-
-enum qed_ll2_tx_dest {
-       QED_LL2_TX_DEST_NW, /* Light L2 TX Destination to the Network */
-       QED_LL2_TX_DEST_LB, /* Light L2 TX Destination to the Loopback */
-       QED_LL2_TX_DEST_MAX
-};
-
 struct qed_ll2_rx_packet {
        struct list_head list_entry;
        struct core_rx_bd_with_buff_len *rxq_bd;
@@ -135,30 +112,21 @@ struct qed_ll2_tx_queue {
        bool b_completing_packet;
 };
 
-struct qed_ll2_conn {
-       enum qed_ll2_conn_type conn_type;
-       u16 mtu;
-       u8 rx_drop_ttl0_flg;
-       u8 rx_vlan_removal_en;
-       u8 tx_tc;
-       enum core_tx_dest tx_dest;
-       enum core_error_handle ai_err_packet_too_big;
-       enum core_error_handle ai_err_no_buf;
-       u8 gsi_enable;
-};
-
 struct qed_ll2_info {
        /* Lock protecting the state of LL2 */
        struct mutex mutex;
-       struct qed_ll2_conn conn;
+
+       struct qed_ll2_acquire_data_inputs input;
        u32 cid;
        u8 my_id;
        u8 queue_id;
        u8 tx_stats_id;
        bool b_active;
+       enum core_tx_dest tx_dest;
        u8 tx_stats_en;
        struct qed_ll2_rx_queue rx_queue;
        struct qed_ll2_tx_queue tx_queue;
+       struct qed_ll2_cbs cbs;
 };
 
 /**
@@ -166,38 +134,30 @@ struct qed_ll2_info {
  *        starts rx & tx (if relevant) queues pair. Provides
  *        connecion handler as output parameter.
  *
- * @param p_hwfn
- * @param p_params             Contain various configuration properties
- * @param rx_num_desc
- * @param tx_num_desc
- *
- * @param p_connection_handle  Output container for LL2 connection's handle
  *
- * @return 0 on success, failure otherwise
+ * @param cxt - pointer to the hw-function [opaque to some]
+ * @param data - describes connection parameters
+ * @return int
  */
-int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
-                              struct qed_ll2_conn *p_params,
-                              u16 rx_num_desc,
-                              u16 tx_num_desc,
-                              u8 *p_connection_handle);
+int qed_ll2_acquire_connection(void *cxt, struct qed_ll2_acquire_data *data);
 
 /**
  * @brief qed_ll2_establish_connection - start previously
  *        allocated LL2 queues pair
  *
- * @param p_hwfn
+ * @param cxt - pointer to the hw-function [opaque to some]
  * @param p_ptt
  * @param connection_handle    LL2 connection's handle obtained from
  *                              qed_ll2_require_connection
  *
  * @return 0 on success, failure otherwise
  */
-int qed_ll2_establish_connection(struct qed_hwfn *p_hwfn, u8 connection_handle);
+int qed_ll2_establish_connection(void *cxt, u8 connection_handle);
 
 /**
  * @brief qed_ll2_post_rx_buffers - submit buffers to LL2 Rx queue.
  *
- * @param p_hwfn
+ * @param cxt - pointer to the hw-function [opaque to some]
  * @param connection_handle    LL2 connection's handle obtained from
  *                             qed_ll2_require_connection
  * @param addr                 rx (physical address) buffers to submit
@@ -206,7 +166,7 @@ int qed_ll2_establish_connection(struct qed_hwfn *p_hwfn, u8 connection_handle);
  *
  * @return 0 on success, failure otherwise
  */
-int qed_ll2_post_rx_buffer(struct qed_hwfn *p_hwfn,
+int qed_ll2_post_rx_buffer(void *cxt,
                           u8 connection_handle,
                           dma_addr_t addr,
                           u16 buf_len, void *cookie, u8 notify_fw);
@@ -215,53 +175,34 @@ int qed_ll2_post_rx_buffer(struct qed_hwfn *p_hwfn,
  * @brief qed_ll2_prepare_tx_packet - request for start Tx BD
  *                                   to prepare Tx packet submission to FW.
  *
- * @param p_hwfn
- * @param connection_handle    LL2 connection's handle obtained from
- *                             qed_ll2_require_connection
- * @param num_of_bds           a number of requested BD equals a number of
- *                             fragments in Tx packet
- * @param vlan                 VLAN to insert to packet (if insertion set)
- * @param bd_flags
- * @param l4_hdr_offset_w      L4 Header Offset from start of packet
- *                             (in words). This is needed if both l4_csum
- *                             and ipv6_ext are set
- * @param e_tx_dest             indicates if the packet is to be transmitted via
- *                              loopback or to the network
- * @param first_frag
- * @param first_frag_len
- * @param cookie
- *
- * @param notify_fw
+ * @param cxt - pointer to the hw-function [opaque to some]
+ * @param connection_handle
+ * @param pkt - info regarding the tx packet
+ * @param notify_fw - issue doorbell to fw for this packet
  *
  * @return 0 on success, failure otherwise
  */
-int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
+int qed_ll2_prepare_tx_packet(void *cxt,
                              u8 connection_handle,
-                             u8 num_of_bds,
-                             u16 vlan,
-                             u8 bd_flags,
-                             u16 l4_hdr_offset_w,
-                             enum qed_ll2_tx_dest e_tx_dest,
-                             enum qed_ll2_roce_flavor_type qed_roce_flavor,
-                             dma_addr_t first_frag,
-                             u16 first_frag_len, void *cookie, u8 notify_fw);
+                             struct qed_ll2_tx_pkt_info *pkt,
+                             bool notify_fw);
 
 /**
  * @brief qed_ll2_release_connection - releases resources
  *                                     allocated for LL2 connection
  *
- * @param p_hwfn
+ * @param cxt - pointer to the hw-function [opaque to some]
  * @param connection_handle            LL2 connection's handle obtained from
  *                                     qed_ll2_require_connection
  */
-void qed_ll2_release_connection(struct qed_hwfn *p_hwfn, u8 connection_handle);
+void qed_ll2_release_connection(void *cxt, u8 connection_handle);
 
 /**
  * @brief qed_ll2_set_fragment_of_tx_packet -  provides fragments to fill
  *                                             Tx BD of BDs requested by
  *                                             qed_ll2_prepare_tx_packet
  *
- * @param p_hwfn
+ * @param cxt - pointer to the hw-function [opaque to some]
  * @param connection_handle                    LL2 connection's handle
  *                                             obtained from
  *                                             qed_ll2_require_connection
@@ -270,7 +211,7 @@ void qed_ll2_release_connection(struct qed_hwfn *p_hwfn, u8 connection_handle);
  *
  * @return 0 on success, failure otherwise
  */
-int qed_ll2_set_fragment_of_tx_packet(struct qed_hwfn *p_hwfn,
+int qed_ll2_set_fragment_of_tx_packet(void *cxt,
                                      u8 connection_handle,
                                      dma_addr_t addr, u16 nbytes);
 
@@ -278,27 +219,27 @@ int qed_ll2_set_fragment_of_tx_packet(struct qed_hwfn *p_hwfn,
  * @brief qed_ll2_terminate_connection -       stops Tx/Rx queues
  *
  *
- * @param p_hwfn
+ * @param cxt - pointer to the hw-function [opaque to some]
  * @param connection_handle                    LL2 connection's handle
  *                                             obtained from
  *                                             qed_ll2_require_connection
  *
  * @return 0 on success, failure otherwise
  */
-int qed_ll2_terminate_connection(struct qed_hwfn *p_hwfn, u8 connection_handle);
+int qed_ll2_terminate_connection(void *cxt, u8 connection_handle);
 
 /**
  * @brief qed_ll2_get_stats -  get LL2 queue's statistics
  *
  *
- * @param p_hwfn
+ * @param cxt - pointer to the hw-function [opaque to some]
  * @param connection_handle    LL2 connection's handle obtained from
  *                             qed_ll2_require_connection
  * @param p_stats
  *
  * @return 0 on success, failure otherwise
  */
-int qed_ll2_get_stats(struct qed_hwfn *p_hwfn,
+int qed_ll2_get_stats(void *cxt,
                      u8 connection_handle, struct qed_ll2_stats *p_stats);
 
 /**
index b9434b707b0821ac4564a657ef7d1be2f361aae0..4bc2f6c47f69b7826c92628378bb8e3bfa82221e 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/errno.h>
-#include <linux/etherdevice.h>
 #include <linux/if_ether.h>
 #include <linux/if_vlan.h>
 #include <linux/io.h>
@@ -65,6 +64,7 @@
 #include "qed_sp.h"
 #include "qed_roce.h"
 #include "qed_ll2.h"
+#include <linux/qed/qed_ll2_if.h>
 
 static void qed_roce_free_real_icid(struct qed_hwfn *p_hwfn, u16 icid);
 
@@ -2709,301 +2709,35 @@ static void qed_rdma_remove_user(void *rdma_cxt, u16 dpi)
        spin_unlock_bh(&p_hwfn->p_rdma_info->lock);
 }
 
-void qed_ll2b_complete_tx_gsi_packet(struct qed_hwfn *p_hwfn,
-                                    u8 connection_handle,
-                                    void *cookie,
-                                    dma_addr_t first_frag_addr,
-                                    bool b_last_fragment, bool b_last_packet)
-{
-       struct qed_roce_ll2_packet *packet = cookie;
-       struct qed_roce_ll2_info *roce_ll2 = p_hwfn->ll2;
-
-       roce_ll2->cbs.tx_cb(roce_ll2->cb_cookie, packet);
-}
-
-void qed_ll2b_release_tx_gsi_packet(struct qed_hwfn *p_hwfn,
-                                   u8 connection_handle,
-                                   void *cookie,
-                                   dma_addr_t first_frag_addr,
-                                   bool b_last_fragment, bool b_last_packet)
-{
-       qed_ll2b_complete_tx_gsi_packet(p_hwfn, connection_handle,
-                                       cookie, first_frag_addr,
-                                       b_last_fragment, b_last_packet);
-}
-
-void qed_ll2b_complete_rx_gsi_packet(struct qed_hwfn *p_hwfn,
-                                    u8 connection_handle,
-                                    void *cookie,
-                                    dma_addr_t rx_buf_addr,
-                                    u16 data_length,
-                                    u8 data_length_error,
-                                    u16 parse_flags,
-                                    u16 vlan,
-                                    u32 src_mac_addr_hi,
-                                    u16 src_mac_addr_lo, bool b_last_packet)
-{
-       struct qed_roce_ll2_info *roce_ll2 = p_hwfn->ll2;
-       struct qed_roce_ll2_rx_params params;
-       struct qed_dev *cdev = p_hwfn->cdev;
-       struct qed_roce_ll2_packet pkt;
-
-       DP_VERBOSE(cdev,
-                  QED_MSG_LL2,
-                  "roce ll2 rx complete: bus_addr=%p, len=%d, data_len_err=%d\n",
-                  (void *)(uintptr_t)rx_buf_addr,
-                  data_length, data_length_error);
-
-       memset(&pkt, 0, sizeof(pkt));
-       pkt.n_seg = 1;
-       pkt.payload[0].baddr = rx_buf_addr;
-       pkt.payload[0].len = data_length;
-
-       memset(&params, 0, sizeof(params));
-       params.vlan_id = vlan;
-       *((u32 *)&params.smac[0]) = ntohl(src_mac_addr_hi);
-       *((u16 *)&params.smac[4]) = ntohs(src_mac_addr_lo);
-
-       if (data_length_error) {
-               DP_ERR(cdev,
-                      "roce ll2 rx complete: data length error %d, length=%d\n",
-                      data_length_error, data_length);
-               params.rc = -EINVAL;
-       }
-
-       roce_ll2->cbs.rx_cb(roce_ll2->cb_cookie, &pkt, &params);
-}
-
 static int qed_roce_ll2_set_mac_filter(struct qed_dev *cdev,
                                       u8 *old_mac_address,
                                       u8 *new_mac_address)
 {
-       struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
+       struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
        struct qed_ptt *p_ptt;
        int rc = 0;
 
-       if (!hwfn->ll2 || hwfn->ll2->handle == QED_LL2_UNUSED_HANDLE) {
-               DP_ERR(cdev,
-                      "qed roce mac filter failed - roce_info/ll2 NULL\n");
-               return -EINVAL;
-       }
-
-       p_ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev));
+       p_ptt = qed_ptt_acquire(p_hwfn);
        if (!p_ptt) {
                DP_ERR(cdev,
                       "qed roce ll2 mac filter set: failed to acquire PTT\n");
                return -EINVAL;
        }
 
-       mutex_lock(&hwfn->ll2->lock);
        if (old_mac_address)
-               qed_llh_remove_mac_filter(QED_LEADING_HWFN(cdev), p_ptt,
-                                         old_mac_address);
+               qed_llh_remove_mac_filter(p_hwfn, p_ptt, old_mac_address);
        if (new_mac_address)
-               rc = qed_llh_add_mac_filter(QED_LEADING_HWFN(cdev), p_ptt,
-                                           new_mac_address);
-       mutex_unlock(&hwfn->ll2->lock);
-
-       qed_ptt_release(QED_LEADING_HWFN(cdev), p_ptt);
-
-       if (rc)
-               DP_ERR(cdev,
-                      "qed roce ll2 mac filter set: failed to add mac filter\n");
-
-       return rc;
-}
-
-static int qed_roce_ll2_start(struct qed_dev *cdev,
-                             struct qed_roce_ll2_params *params)
-{
-       struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
-       struct qed_roce_ll2_info *roce_ll2;
-       struct qed_ll2_conn ll2_params;
-       int rc;
-
-       if (!params) {
-               DP_ERR(cdev, "qed roce ll2 start: failed due to NULL params\n");
-               return -EINVAL;
-       }
-       if (!params->cbs.tx_cb || !params->cbs.rx_cb) {
-               DP_ERR(cdev,
-                      "qed roce ll2 start: failed due to NULL tx/rx. tx_cb=%p, rx_cb=%p\n",
-                      params->cbs.tx_cb, params->cbs.rx_cb);
-               return -EINVAL;
-       }
-       if (!is_valid_ether_addr(params->mac_address)) {
-               DP_ERR(cdev,
-                      "qed roce ll2 start: failed due to invalid Ethernet address %pM\n",
-                      params->mac_address);
-               return -EINVAL;
-       }
-
-       /* Initialize */
-       roce_ll2 = kzalloc(sizeof(*roce_ll2), GFP_ATOMIC);
-       if (!roce_ll2) {
-               DP_ERR(cdev, "qed roce ll2 start: failed memory allocation\n");
-               return -ENOMEM;
-       }
-       roce_ll2->handle = QED_LL2_UNUSED_HANDLE;
-       roce_ll2->cbs = params->cbs;
-       roce_ll2->cb_cookie = params->cb_cookie;
-       mutex_init(&roce_ll2->lock);
-
-       memset(&ll2_params, 0, sizeof(ll2_params));
-       ll2_params.conn_type = QED_LL2_TYPE_ROCE;
-       ll2_params.mtu = params->mtu;
-       ll2_params.rx_drop_ttl0_flg = true;
-       ll2_params.rx_vlan_removal_en = false;
-       ll2_params.tx_dest = CORE_TX_DEST_NW;
-       ll2_params.ai_err_packet_too_big = LL2_DROP_PACKET;
-       ll2_params.ai_err_no_buf = LL2_DROP_PACKET;
-       ll2_params.gsi_enable = true;
-
-       rc = qed_ll2_acquire_connection(QED_LEADING_HWFN(cdev), &ll2_params,
-                                       params->max_rx_buffers,
-                                       params->max_tx_buffers,
-                                       &roce_ll2->handle);
-       if (rc) {
-               DP_ERR(cdev,
-                      "qed roce ll2 start: failed to acquire LL2 connection (rc=%d)\n",
-                      rc);
-               goto err;
-       }
-
-       rc = qed_ll2_establish_connection(QED_LEADING_HWFN(cdev),
-                                         roce_ll2->handle);
-       if (rc) {
-               DP_ERR(cdev,
-                      "qed roce ll2 start: failed to establish LL2 connection (rc=%d)\n",
-                      rc);
-               goto err1;
-       }
-
-       hwfn->ll2 = roce_ll2;
-
-       rc = qed_roce_ll2_set_mac_filter(cdev, NULL, params->mac_address);
-       if (rc) {
-               hwfn->ll2 = NULL;
-               goto err2;
-       }
-       ether_addr_copy(roce_ll2->mac_address, params->mac_address);
-
-       return 0;
-
-err2:
-       qed_ll2_terminate_connection(QED_LEADING_HWFN(cdev), roce_ll2->handle);
-err1:
-       qed_ll2_release_connection(QED_LEADING_HWFN(cdev), roce_ll2->handle);
-err:
-       kfree(roce_ll2);
-       return rc;
-}
+               rc = qed_llh_add_mac_filter(p_hwfn, p_ptt, new_mac_address);
 
-static int qed_roce_ll2_stop(struct qed_dev *cdev)
-{
-       struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
-       struct qed_roce_ll2_info *roce_ll2 = hwfn->ll2;
-       int rc;
-
-       if (roce_ll2->handle == QED_LL2_UNUSED_HANDLE) {
-               DP_ERR(cdev, "qed roce ll2 stop: cannot stop an unused LL2\n");
-               return -EINVAL;
-       }
-
-       /* remove LL2 MAC address filter */
-       rc = qed_roce_ll2_set_mac_filter(cdev, roce_ll2->mac_address, NULL);
-       eth_zero_addr(roce_ll2->mac_address);
+       qed_ptt_release(p_hwfn, p_ptt);
 
-       rc = qed_ll2_terminate_connection(QED_LEADING_HWFN(cdev),
-                                         roce_ll2->handle);
        if (rc)
                DP_ERR(cdev,
-                      "qed roce ll2 stop: failed to terminate LL2 connection (rc=%d)\n",
-                      rc);
-
-       qed_ll2_release_connection(QED_LEADING_HWFN(cdev), roce_ll2->handle);
-
-       roce_ll2->handle = QED_LL2_UNUSED_HANDLE;
-
-       kfree(roce_ll2);
+                      "qed roce ll2 mac filter set: failed to add MAC filter\n");
 
        return rc;
 }
 
-static int qed_roce_ll2_tx(struct qed_dev *cdev,
-                          struct qed_roce_ll2_packet *pkt,
-                          struct qed_roce_ll2_tx_params *params)
-{
-       struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
-       struct qed_roce_ll2_info *roce_ll2 = hwfn->ll2;
-       enum qed_ll2_roce_flavor_type qed_roce_flavor;
-       u8 flags = 0;
-       int rc;
-       int i;
-
-       if (!pkt || !params) {
-               DP_ERR(cdev,
-                      "roce ll2 tx: failed tx because one of the following is NULL - drv=%p, pkt=%p, params=%p\n",
-                      cdev, pkt, params);
-               return -EINVAL;
-       }
-
-       qed_roce_flavor = (pkt->roce_mode == ROCE_V1) ? QED_LL2_ROCE
-                                                     : QED_LL2_RROCE;
-
-       if (pkt->roce_mode == ROCE_V2_IPV4)
-               flags |= BIT(CORE_TX_BD_DATA_IP_CSUM_SHIFT);
-
-       /* Tx header */
-       rc = qed_ll2_prepare_tx_packet(QED_LEADING_HWFN(cdev), roce_ll2->handle,
-                                      1 + pkt->n_seg, 0, flags, 0,
-                                      QED_LL2_TX_DEST_NW,
-                                      qed_roce_flavor, pkt->header.baddr,
-                                      pkt->header.len, pkt, 1);
-       if (rc) {
-               DP_ERR(cdev, "roce ll2 tx: header failed (rc=%d)\n", rc);
-               return QED_ROCE_TX_HEAD_FAILURE;
-       }
-
-       /* Tx payload */
-       for (i = 0; i < pkt->n_seg; i++) {
-               rc = qed_ll2_set_fragment_of_tx_packet(QED_LEADING_HWFN(cdev),
-                                                      roce_ll2->handle,
-                                                      pkt->payload[i].baddr,
-                                                      pkt->payload[i].len);
-               if (rc) {
-                       /* If failed not much to do here, partial packet has
-                        * been posted * we can't free memory, will need to wait
-                        * for completion
-                        */
-                       DP_ERR(cdev,
-                              "roce ll2 tx: payload failed (rc=%d)\n", rc);
-                       return QED_ROCE_TX_FRAG_FAILURE;
-               }
-       }
-
-       return 0;
-}
-
-static int qed_roce_ll2_post_rx_buffer(struct qed_dev *cdev,
-                                      struct qed_roce_ll2_buffer *buf,
-                                      u64 cookie, u8 notify_fw)
-{
-       return qed_ll2_post_rx_buffer(QED_LEADING_HWFN(cdev),
-                                     QED_LEADING_HWFN(cdev)->ll2->handle,
-                                     buf->baddr, buf->len,
-                                     (void *)(uintptr_t)cookie, notify_fw);
-}
-
-static int qed_roce_ll2_stats(struct qed_dev *cdev, struct qed_ll2_stats *stats)
-{
-       struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
-       struct qed_roce_ll2_info *roce_ll2 = hwfn->ll2;
-
-       return qed_ll2_get_stats(QED_LEADING_HWFN(cdev),
-                                roce_ll2->handle, stats);
-}
-
 static const struct qed_rdma_ops qed_rdma_ops_pass = {
        .common = &qed_common_ops_pass,
        .fill_dev_info = &qed_fill_rdma_dev_info,
@@ -3031,12 +2765,15 @@ static const struct qed_rdma_ops qed_rdma_ops_pass = {
        .rdma_free_tid = &qed_rdma_free_tid,
        .rdma_register_tid = &qed_rdma_register_tid,
        .rdma_deregister_tid = &qed_rdma_deregister_tid,
-       .roce_ll2_start = &qed_roce_ll2_start,
-       .roce_ll2_stop = &qed_roce_ll2_stop,
-       .roce_ll2_tx = &qed_roce_ll2_tx,
-       .roce_ll2_post_rx_buffer = &qed_roce_ll2_post_rx_buffer,
-       .roce_ll2_set_mac_filter = &qed_roce_ll2_set_mac_filter,
-       .roce_ll2_stats = &qed_roce_ll2_stats,
+       .ll2_acquire_connection = &qed_ll2_acquire_connection,
+       .ll2_establish_connection = &qed_ll2_establish_connection,
+       .ll2_terminate_connection = &qed_ll2_terminate_connection,
+       .ll2_release_connection = &qed_ll2_release_connection,
+       .ll2_post_rx_buffer = &qed_ll2_post_rx_buffer,
+       .ll2_prepare_tx_packet = &qed_ll2_prepare_tx_packet,
+       .ll2_set_fragment_of_tx_packet = &qed_ll2_set_fragment_of_tx_packet,
+       .ll2_set_mac_filter = &qed_roce_ll2_set_mac_filter,
+       .ll2_get_stats = &qed_ll2_get_stats,
 };
 
 const struct qed_rdma_ops *qed_get_rdma_ops(void)
index 9742af51618301c633997a939bb6242f2e83a61c..94be3b5a39c481c821e86ce8210ac3a9fa23099c 100644 (file)
@@ -170,53 +170,10 @@ struct qed_rdma_qp {
 void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
 void qed_roce_async_event(struct qed_hwfn *p_hwfn,
                          u8 fw_event_code, union rdma_eqe_data *rdma_data);
-void qed_ll2b_complete_tx_gsi_packet(struct qed_hwfn *p_hwfn,
-                                    u8 connection_handle,
-                                    void *cookie,
-                                    dma_addr_t first_frag_addr,
-                                    bool b_last_fragment, bool b_last_packet);
-void qed_ll2b_release_tx_gsi_packet(struct qed_hwfn *p_hwfn,
-                                   u8 connection_handle,
-                                   void *cookie,
-                                   dma_addr_t first_frag_addr,
-                                   bool b_last_fragment, bool b_last_packet);
-void qed_ll2b_complete_rx_gsi_packet(struct qed_hwfn *p_hwfn,
-                                    u8 connection_handle,
-                                    void *cookie,
-                                    dma_addr_t rx_buf_addr,
-                                    u16 data_length,
-                                    u8 data_length_error,
-                                    u16 parse_flags,
-                                    u16 vlan,
-                                    u32 src_mac_addr_hi,
-                                    u16 src_mac_addr_lo, bool b_last_packet);
 #else
 static inline void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) {}
 static inline void qed_roce_async_event(struct qed_hwfn *p_hwfn,
                                        u8 fw_event_code,
                                        union rdma_eqe_data *rdma_data) {}
-static inline void qed_ll2b_complete_tx_gsi_packet(struct qed_hwfn *p_hwfn,
-                                                  u8 connection_handle,
-                                                  void *cookie,
-                                                  dma_addr_t first_frag_addr,
-                                                  bool b_last_fragment,
-                                                  bool b_last_packet) {}
-static inline void qed_ll2b_release_tx_gsi_packet(struct qed_hwfn *p_hwfn,
-                                                 u8 connection_handle,
-                                                 void *cookie,
-                                                 dma_addr_t first_frag_addr,
-                                                 bool b_last_fragment,
-                                                 bool b_last_packet) {}
-static inline void qed_ll2b_complete_rx_gsi_packet(struct qed_hwfn *p_hwfn,
-                                                  u8 connection_handle,
-                                                  void *cookie,
-                                                  dma_addr_t rx_buf_addr,
-                                                  u16 data_length,
-                                                  u8 data_length_error,
-                                                  u16 parse_flags,
-                                                  u16 vlan,
-                                                  u32 src_mac_addr_hi,
-                                                  u16 src_mac_addr_lo,
-                                                  bool b_last_packet) {}
 #endif
 #endif
index b65bbc54a097937b0539eb8331c25edb5a0577d9..34d9b882a7807a63f6fde24ce75922f50606b7a8 100644 (file)
@@ -1105,6 +1105,11 @@ static inline u16 qed_vf_get_igu_sb_id(struct qed_hwfn *p_hwfn, u16 sb_id)
        return 0;
 }
 
+static inline void qed_vf_set_sb_info(struct qed_hwfn *p_hwfn, u16 sb_id,
+                                     struct qed_sb_info *p_sb)
+{
+}
+
 static inline int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn,
                                        u8 vport_id,
                                        u16 mtu,
index 784782da3a85b638e9e2a195fe66b15c72fe0fe5..5931e859876c2aee79d9a90e510a25aecab7f1ee 100644 (file)
@@ -1076,16 +1076,16 @@ static int ravb_get_link_ksettings(struct net_device *ndev,
                                   struct ethtool_link_ksettings *cmd)
 {
        struct ravb_private *priv = netdev_priv(ndev);
-       int error = -ENODEV;
        unsigned long flags;
 
-       if (ndev->phydev) {
-               spin_lock_irqsave(&priv->lock, flags);
-               error = phy_ethtool_ksettings_get(ndev->phydev, cmd);
-               spin_unlock_irqrestore(&priv->lock, flags);
-       }
+       if (!ndev->phydev)
+               return -ENODEV;
 
-       return error;
+       spin_lock_irqsave(&priv->lock, flags);
+       phy_ethtool_ksettings_get(ndev->phydev, cmd);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return 0;
 }
 
 static int ravb_set_link_ksettings(struct net_device *ndev,
index 2d686ccf971b1b6525d7ded8ec5e43b65b67ee6c..d2dc0a8ef3056237d273128c34a75f66c1ee4c90 100644 (file)
@@ -1915,16 +1915,15 @@ static int sh_eth_get_link_ksettings(struct net_device *ndev,
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        unsigned long flags;
-       int ret;
 
        if (!ndev->phydev)
                return -ENODEV;
 
        spin_lock_irqsave(&mdp->lock, flags);
-       ret = phy_ethtool_ksettings_get(ndev->phydev, cmd);
+       phy_ethtool_ksettings_get(ndev->phydev, cmd);
        spin_unlock_irqrestore(&mdp->lock, flags);
 
-       return ret;
+       return 0;
 }
 
 static int sh_eth_set_link_ksettings(struct net_device *ndev,
@@ -2558,6 +2557,17 @@ static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
        return phy_mii_ioctl(phydev, rq, cmd);
 }
 
+static int sh_eth_change_mtu(struct net_device *ndev, int new_mtu)
+{
+       if (netif_running(ndev))
+               return -EBUSY;
+
+       ndev->mtu = new_mtu;
+       netdev_update_features(ndev);
+
+       return 0;
+}
+
 /* For TSU_POSTn. Please refer to the manual about this (strange) bitfields */
 static void *sh_eth_tsu_get_post_reg_offset(struct sh_eth_private *mdp,
                                            int entry)
@@ -3029,6 +3039,7 @@ static const struct net_device_ops sh_eth_netdev_ops = {
        .ndo_set_rx_mode        = sh_eth_set_rx_mode,
        .ndo_tx_timeout         = sh_eth_tx_timeout,
        .ndo_do_ioctl           = sh_eth_do_ioctl,
+       .ndo_change_mtu         = sh_eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 };
@@ -3043,6 +3054,7 @@ static const struct net_device_ops sh_eth_netdev_ops_tsu = {
        .ndo_vlan_rx_kill_vid   = sh_eth_vlan_rx_kill_vid,
        .ndo_tx_timeout         = sh_eth_tx_timeout,
        .ndo_do_ioctl           = sh_eth_do_ioctl,
+       .ndo_change_mtu         = sh_eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 };
@@ -3171,6 +3183,13 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
        }
        sh_eth_set_default_cpu_data(mdp->cd);
 
+       /* User's manual states max MTU should be 2048 but due to the
+        * alignment calculations in sh_eth_ring_init() the practical
+        * MTU is a bit less. Maybe this can be optimized some more.
+        */
+       ndev->max_mtu = 2000 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
+       ndev->min_mtu = ETH_MIN_MTU;
+
        /* set function */
        if (mdp->cd->tsu)
                ndev->netdev_ops = &sh_eth_netdev_ops_tsu;
index ee9675db5bf953b92cf46ead04e19f744ba36204..748fb12260a629d15c7018f73aa16c356eef0da6 100644 (file)
@@ -105,32 +105,27 @@ struct rocker_world_ops {
        int (*port_open)(struct rocker_port *rocker_port);
        void (*port_stop)(struct rocker_port *rocker_port);
        int (*port_attr_stp_state_set)(struct rocker_port *rocker_port,
-                                      u8 state,
-                                      struct switchdev_trans *trans);
+                                      u8 state);
        int (*port_attr_bridge_flags_set)(struct rocker_port *rocker_port,
                                          unsigned long brport_flags,
                                          struct switchdev_trans *trans);
        int (*port_attr_bridge_flags_get)(const struct rocker_port *rocker_port,
                                          unsigned long *p_brport_flags);
+       int (*port_attr_bridge_flags_support_get)(const struct rocker_port *
+                                                 rocker_port,
+                                                 unsigned long *
+                                                 p_brport_flags);
        int (*port_attr_bridge_ageing_time_set)(struct rocker_port *rocker_port,
                                                u32 ageing_time,
                                                struct switchdev_trans *trans);
        int (*port_obj_vlan_add)(struct rocker_port *rocker_port,
-                                const struct switchdev_obj_port_vlan *vlan,
-                                struct switchdev_trans *trans);
+                                const struct switchdev_obj_port_vlan *vlan);
        int (*port_obj_vlan_del)(struct rocker_port *rocker_port,
                                 const struct switchdev_obj_port_vlan *vlan);
-       int (*port_obj_vlan_dump)(const struct rocker_port *rocker_port,
-                                 struct switchdev_obj_port_vlan *vlan,
-                                 switchdev_obj_dump_cb_t *cb);
        int (*port_obj_fdb_add)(struct rocker_port *rocker_port,
-                               const struct switchdev_obj_port_fdb *fdb,
-                               struct switchdev_trans *trans);
+                               u16 vid, const unsigned char *addr);
        int (*port_obj_fdb_del)(struct rocker_port *rocker_port,
-                               const struct switchdev_obj_port_fdb *fdb);
-       int (*port_obj_fdb_dump)(const struct rocker_port *rocker_port,
-                                struct switchdev_obj_port_fdb *fdb,
-                                switchdev_obj_dump_cb_t *cb);
+                               u16 vid, const unsigned char *addr);
        int (*port_master_linked)(struct rocker_port *rocker_port,
                                  struct net_device *master);
        int (*port_master_unlinked)(struct rocker_port *rocker_port,
index bab13613b138cc15c734d9e9fff5f465ef480a44..b1e5c07099fa1f607e2092d4c60ff31305ce02c1 100644 (file)
@@ -1557,7 +1557,11 @@ static int rocker_world_port_attr_stp_state_set(struct rocker_port *rocker_port,
 
        if (!wops->port_attr_stp_state_set)
                return -EOPNOTSUPP;
-       return wops->port_attr_stp_state_set(rocker_port, state, trans);
+
+       if (switchdev_trans_ph_prepare(trans))
+               return 0;
+
+       return wops->port_attr_stp_state_set(rocker_port, state);
 }
 
 static int
@@ -1569,6 +1573,10 @@ rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port,
 
        if (!wops->port_attr_bridge_flags_set)
                return -EOPNOTSUPP;
+
+       if (switchdev_trans_ph_prepare(trans))
+               return 0;
+
        return wops->port_attr_bridge_flags_set(rocker_port, brport_flags,
                                                trans);
 }
@@ -1584,6 +1592,20 @@ rocker_world_port_attr_bridge_flags_get(const struct rocker_port *rocker_port,
        return wops->port_attr_bridge_flags_get(rocker_port, p_brport_flags);
 }
 
+static int
+rocker_world_port_attr_bridge_flags_support_get(const struct rocker_port *
+                                               rocker_port,
+                                               unsigned long *
+                                               p_brport_flags_support)
+{
+       struct rocker_world_ops *wops = rocker_port->rocker->wops;
+
+       if (!wops->port_attr_bridge_flags_support_get)
+               return -EOPNOTSUPP;
+       return wops->port_attr_bridge_flags_support_get(rocker_port,
+                                                       p_brport_flags_support);
+}
+
 static int
 rocker_world_port_attr_bridge_ageing_time_set(struct rocker_port *rocker_port,
                                              u32 ageing_time,
@@ -1594,6 +1616,10 @@ rocker_world_port_attr_bridge_ageing_time_set(struct rocker_port *rocker_port,
 
        if (!wops->port_attr_bridge_ageing_time_set)
                return -EOPNOTSUPP;
+
+       if (switchdev_trans_ph_prepare(trans))
+               return 0;
+
        return wops->port_attr_bridge_ageing_time_set(rocker_port, ageing_time,
                                                      trans);
 }
@@ -1607,7 +1633,11 @@ rocker_world_port_obj_vlan_add(struct rocker_port *rocker_port,
 
        if (!wops->port_obj_vlan_add)
                return -EOPNOTSUPP;
-       return wops->port_obj_vlan_add(rocker_port, vlan, trans);
+
+       if (switchdev_trans_ph_prepare(trans))
+               return 0;
+
+       return wops->port_obj_vlan_add(rocker_port, vlan);
 }
 
 static int
@@ -1622,50 +1652,26 @@ rocker_world_port_obj_vlan_del(struct rocker_port *rocker_port,
 }
 
 static int
-rocker_world_port_obj_vlan_dump(const struct rocker_port *rocker_port,
-                               struct switchdev_obj_port_vlan *vlan,
-                               switchdev_obj_dump_cb_t *cb)
-{
-       struct rocker_world_ops *wops = rocker_port->rocker->wops;
-
-       if (!wops->port_obj_vlan_dump)
-               return -EOPNOTSUPP;
-       return wops->port_obj_vlan_dump(rocker_port, vlan, cb);
-}
-
-static int
-rocker_world_port_obj_fdb_add(struct rocker_port *rocker_port,
-                             const struct switchdev_obj_port_fdb *fdb,
-                             struct switchdev_trans *trans)
+rocker_world_port_fdb_add(struct rocker_port *rocker_port,
+                         struct switchdev_notifier_fdb_info *info)
 {
        struct rocker_world_ops *wops = rocker_port->rocker->wops;
 
        if (!wops->port_obj_fdb_add)
                return -EOPNOTSUPP;
-       return wops->port_obj_fdb_add(rocker_port, fdb, trans);
-}
-
-static int
-rocker_world_port_obj_fdb_del(struct rocker_port *rocker_port,
-                             const struct switchdev_obj_port_fdb *fdb)
-{
-       struct rocker_world_ops *wops = rocker_port->rocker->wops;
 
-       if (!wops->port_obj_fdb_del)
-               return -EOPNOTSUPP;
-       return wops->port_obj_fdb_del(rocker_port, fdb);
+       return wops->port_obj_fdb_add(rocker_port, info->vid, info->addr);
 }
 
 static int
-rocker_world_port_obj_fdb_dump(const struct rocker_port *rocker_port,
-                              struct switchdev_obj_port_fdb *fdb,
-                              switchdev_obj_dump_cb_t *cb)
+rocker_world_port_fdb_del(struct rocker_port *rocker_port,
+                         struct switchdev_notifier_fdb_info *info)
 {
        struct rocker_world_ops *wops = rocker_port->rocker->wops;
 
-       if (!wops->port_obj_fdb_dump)
+       if (!wops->port_obj_fdb_del)
                return -EOPNOTSUPP;
-       return wops->port_obj_fdb_dump(rocker_port, fdb, cb);
+       return wops->port_obj_fdb_del(rocker_port, info->vid, info->addr);
 }
 
 static int rocker_world_port_master_linked(struct rocker_port *rocker_port,
@@ -2022,12 +2028,6 @@ static const struct net_device_ops rocker_port_netdev_ops = {
        .ndo_start_xmit                 = rocker_port_xmit,
        .ndo_set_mac_address            = rocker_port_set_mac_address,
        .ndo_change_mtu                 = rocker_port_change_mtu,
-       .ndo_bridge_getlink             = switchdev_port_bridge_getlink,
-       .ndo_bridge_setlink             = switchdev_port_bridge_setlink,
-       .ndo_bridge_dellink             = switchdev_port_bridge_dellink,
-       .ndo_fdb_add                    = switchdev_port_fdb_add,
-       .ndo_fdb_del                    = switchdev_port_fdb_del,
-       .ndo_fdb_dump                   = switchdev_port_fdb_dump,
        .ndo_get_phys_port_name         = rocker_port_get_phys_port_name,
        .ndo_change_proto_down          = rocker_port_change_proto_down,
        .ndo_neigh_destroy              = rocker_port_neigh_destroy,
@@ -2053,6 +2053,10 @@ static int rocker_port_attr_get(struct net_device *dev,
                err = rocker_world_port_attr_bridge_flags_get(rocker_port,
                                                              &attr->u.brport_flags);
                break;
+       case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
+               err = rocker_world_port_attr_bridge_flags_support_get(rocker_port,
+                                                                     &attr->u.brport_flags_support);
+               break;
        default:
                return -EOPNOTSUPP;
        }
@@ -2104,11 +2108,6 @@ static int rocker_port_obj_add(struct net_device *dev,
                                                     SWITCHDEV_OBJ_PORT_VLAN(obj),
                                                     trans);
                break;
-       case SWITCHDEV_OBJ_ID_PORT_FDB:
-               err = rocker_world_port_obj_fdb_add(rocker_port,
-                                                   SWITCHDEV_OBJ_PORT_FDB(obj),
-                                                   trans);
-               break;
        default:
                err = -EOPNOTSUPP;
                break;
@@ -2128,36 +2127,6 @@ static int rocker_port_obj_del(struct net_device *dev,
                err = rocker_world_port_obj_vlan_del(rocker_port,
                                                     SWITCHDEV_OBJ_PORT_VLAN(obj));
                break;
-       case SWITCHDEV_OBJ_ID_PORT_FDB:
-               err = rocker_world_port_obj_fdb_del(rocker_port,
-                                                   SWITCHDEV_OBJ_PORT_FDB(obj));
-               break;
-       default:
-               err = -EOPNOTSUPP;
-               break;
-       }
-
-       return err;
-}
-
-static int rocker_port_obj_dump(struct net_device *dev,
-                               struct switchdev_obj *obj,
-                               switchdev_obj_dump_cb_t *cb)
-{
-       const struct rocker_port *rocker_port = netdev_priv(dev);
-       int err = 0;
-
-       switch (obj->id) {
-       case SWITCHDEV_OBJ_ID_PORT_FDB:
-               err = rocker_world_port_obj_fdb_dump(rocker_port,
-                                                    SWITCHDEV_OBJ_PORT_FDB(obj),
-                                                    cb);
-               break;
-       case SWITCHDEV_OBJ_ID_PORT_VLAN:
-               err = rocker_world_port_obj_vlan_dump(rocker_port,
-                                                     SWITCHDEV_OBJ_PORT_VLAN(obj),
-                                                     cb);
-               break;
        default:
                err = -EOPNOTSUPP;
                break;
@@ -2171,7 +2140,6 @@ static const struct switchdev_ops rocker_port_switchdev_ops = {
        .switchdev_port_attr_set        = rocker_port_attr_set,
        .switchdev_port_obj_add         = rocker_port_obj_add,
        .switchdev_port_obj_del         = rocker_port_obj_del,
-       .switchdev_port_obj_dump        = rocker_port_obj_dump,
 };
 
 struct rocker_fib_event_work {
@@ -2729,6 +2697,109 @@ static void rocker_msix_fini(const struct rocker *rocker)
        kfree(rocker->msix_entries);
 }
 
+static bool rocker_port_dev_check(const struct net_device *dev)
+{
+       return dev->netdev_ops == &rocker_port_netdev_ops;
+}
+
+struct rocker_switchdev_event_work {
+       struct work_struct work;
+       struct switchdev_notifier_fdb_info fdb_info;
+       struct rocker_port *rocker_port;
+       unsigned long event;
+};
+
+static void
+rocker_fdb_offload_notify(struct rocker_port *rocker_port,
+                         struct switchdev_notifier_fdb_info *recv_info)
+{
+       struct switchdev_notifier_fdb_info info;
+
+       info.addr = recv_info->addr;
+       info.vid = recv_info->vid;
+       call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED,
+                                rocker_port->dev, &info.info);
+}
+
+static void rocker_switchdev_event_work(struct work_struct *work)
+{
+       struct rocker_switchdev_event_work *switchdev_work =
+               container_of(work, struct rocker_switchdev_event_work, work);
+       struct rocker_port *rocker_port = switchdev_work->rocker_port;
+       struct switchdev_notifier_fdb_info *fdb_info;
+       int err;
+
+       rtnl_lock();
+       switch (switchdev_work->event) {
+       case SWITCHDEV_FDB_ADD_TO_DEVICE:
+               fdb_info = &switchdev_work->fdb_info;
+               err = rocker_world_port_fdb_add(rocker_port, fdb_info);
+               if (err) {
+                       netdev_dbg(rocker_port->dev, "fdb add failed err=%d\n", err);
+                       break;
+               }
+               rocker_fdb_offload_notify(rocker_port, fdb_info);
+               break;
+       case SWITCHDEV_FDB_DEL_TO_DEVICE:
+               fdb_info = &switchdev_work->fdb_info;
+               err = rocker_world_port_fdb_del(rocker_port, fdb_info);
+               if (err)
+                       netdev_dbg(rocker_port->dev, "fdb add failed err=%d\n", err);
+               break;
+       }
+       rtnl_unlock();
+
+       kfree(switchdev_work->fdb_info.addr);
+       kfree(switchdev_work);
+       dev_put(rocker_port->dev);
+}
+
+/* called under rcu_read_lock() */
+static int rocker_switchdev_event(struct notifier_block *unused,
+                                 unsigned long event, void *ptr)
+{
+       struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+       struct rocker_switchdev_event_work *switchdev_work;
+       struct switchdev_notifier_fdb_info *fdb_info = ptr;
+       struct rocker_port *rocker_port;
+
+       if (!rocker_port_dev_check(dev))
+               return NOTIFY_DONE;
+
+       rocker_port = netdev_priv(dev);
+       switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC);
+       if (WARN_ON(!switchdev_work))
+               return NOTIFY_BAD;
+
+       INIT_WORK(&switchdev_work->work, rocker_switchdev_event_work);
+       switchdev_work->rocker_port = rocker_port;
+       switchdev_work->event = event;
+
+       switch (event) {
+       case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
+       case SWITCHDEV_FDB_DEL_TO_DEVICE:
+               memcpy(&switchdev_work->fdb_info, ptr,
+                      sizeof(switchdev_work->fdb_info));
+               switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
+               ether_addr_copy((u8 *)switchdev_work->fdb_info.addr,
+                               fdb_info->addr);
+               /* Take a reference on the rocker device */
+               dev_hold(dev);
+               break;
+       default:
+               kfree(switchdev_work);
+               return NOTIFY_DONE;
+       }
+
+       queue_work(rocker_port->rocker->rocker_owq,
+                  &switchdev_work->work);
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block rocker_switchdev_notifier = {
+       .notifier_call = rocker_switchdev_event,
+};
+
 static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct rocker *rocker;
@@ -2834,6 +2905,12 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (err)
                goto err_register_fib_notifier;
 
+       err = register_switchdev_notifier(&rocker_switchdev_notifier);
+       if (err) {
+               dev_err(&pdev->dev, "Failed to register switchdev notifier\n");
+               goto err_register_switchdev_notifier;
+       }
+
        rocker->hw.id = rocker_read64(rocker, SWITCH_ID);
 
        err = rocker_probe_ports(rocker);
@@ -2848,6 +2925,8 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        return 0;
 
 err_probe_ports:
+       unregister_switchdev_notifier(&rocker_switchdev_notifier);
+err_register_switchdev_notifier:
        unregister_fib_notifier(&rocker->fib_nb);
 err_register_fib_notifier:
        destroy_workqueue(rocker->rocker_owq);
@@ -2878,6 +2957,7 @@ static void rocker_remove(struct pci_dev *pdev)
        struct rocker *rocker = pci_get_drvdata(pdev);
 
        rocker_remove_ports(rocker);
+       unregister_switchdev_notifier(&rocker_switchdev_notifier);
        unregister_fib_notifier(&rocker->fib_nb);
        rocker_write32(rocker, CONTROL, ROCKER_CONTROL_RESET);
        destroy_workqueue(rocker->rocker_owq);
@@ -2902,11 +2982,6 @@ static struct pci_driver rocker_pci_driver = {
  * Net device notifier event handler
  ************************************/
 
-static bool rocker_port_dev_check(const struct net_device *dev)
-{
-       return dev->netdev_ops == &rocker_port_netdev_ops;
-}
-
 static bool rocker_port_dev_check_under(const struct net_device *dev,
                                        struct rocker *rocker)
 {
index 2ae85245478087d2d640617bd79bfbfabd5f0763..bd0e3f157e9e8629eaf0ebe591a475eb9e7b5979 100644 (file)
@@ -300,64 +300,6 @@ static bool ofdpa_flags_nowait(int flags)
        return flags & OFDPA_OP_FLAG_NOWAIT;
 }
 
-static void *__ofdpa_mem_alloc(struct switchdev_trans *trans, int flags,
-                              size_t size)
-{
-       struct switchdev_trans_item *elem = NULL;
-       gfp_t gfp_flags = (flags & OFDPA_OP_FLAG_NOWAIT) ?
-                         GFP_ATOMIC : GFP_KERNEL;
-
-       /* If in transaction prepare phase, allocate the memory
-        * and enqueue it on a transaction.  If in transaction
-        * commit phase, dequeue the memory from the transaction
-        * rather than re-allocating the memory.  The idea is the
-        * driver code paths for prepare and commit are identical
-        * so the memory allocated in the prepare phase is the
-        * memory used in the commit phase.
-        */
-
-       if (!trans) {
-               elem = kzalloc(size + sizeof(*elem), gfp_flags);
-       } else if (switchdev_trans_ph_prepare(trans)) {
-               elem = kzalloc(size + sizeof(*elem), gfp_flags);
-               if (!elem)
-                       return NULL;
-               switchdev_trans_item_enqueue(trans, elem, kfree, elem);
-       } else {
-               elem = switchdev_trans_item_dequeue(trans);
-       }
-
-       return elem ? elem + 1 : NULL;
-}
-
-static void *ofdpa_kzalloc(struct switchdev_trans *trans, int flags,
-                          size_t size)
-{
-       return __ofdpa_mem_alloc(trans, flags, size);
-}
-
-static void *ofdpa_kcalloc(struct switchdev_trans *trans, int flags,
-                          size_t n, size_t size)
-{
-       return __ofdpa_mem_alloc(trans, flags, n * size);
-}
-
-static void ofdpa_kfree(struct switchdev_trans *trans, const void *mem)
-{
-       struct switchdev_trans_item *elem;
-
-       /* Frees are ignored if in transaction prepare phase.  The
-        * memory remains on the per-port list until freed in the
-        * commit phase.
-        */
-
-       if (switchdev_trans_ph_prepare(trans))
-               return;
-
-       elem = (struct switchdev_trans_item *) mem - 1;
-       kfree(elem);
-}
-
 /*************************************************************
  * Flow, group, FDB, internal VLAN and neigh command prepares
  *************************************************************/
@@ -815,8 +757,7 @@ ofdpa_flow_tbl_find(const struct ofdpa *ofdpa,
 }
 
 static int ofdpa_flow_tbl_add(struct ofdpa_port *ofdpa_port,
-                             struct switchdev_trans *trans, int flags,
-                             struct ofdpa_flow_tbl_entry *match)
+                             int flags, struct ofdpa_flow_tbl_entry *match)
 {
        struct ofdpa *ofdpa = ofdpa_port->ofdpa;
        struct ofdpa_flow_tbl_entry *found;
@@ -831,9 +772,8 @@ static int ofdpa_flow_tbl_add(struct ofdpa_port *ofdpa_port,
 
        if (found) {
                match->cookie = found->cookie;
-               if (!switchdev_trans_ph_prepare(trans))
-                       hash_del(&found->entry);
-               ofdpa_kfree(trans, found);
+               hash_del(&found->entry);
+               kfree(found);
                found = match;
                found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_MOD;
        } else {
@@ -842,22 +782,18 @@ static int ofdpa_flow_tbl_add(struct ofdpa_port *ofdpa_port,
                found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_ADD;
        }
 
-       if (!switchdev_trans_ph_prepare(trans))
-               hash_add(ofdpa->flow_tbl, &found->entry, found->key_crc32);
-
+       hash_add(ofdpa->flow_tbl, &found->entry, found->key_crc32);
        spin_unlock_irqrestore(&ofdpa->flow_tbl_lock, lock_flags);
 
-       if (!switchdev_trans_ph_prepare(trans))
-               return rocker_cmd_exec(ofdpa_port->rocker_port,
-                                      ofdpa_flags_nowait(flags),
-                                      ofdpa_cmd_flow_tbl_add,
-                                      found, NULL, NULL);
+       return rocker_cmd_exec(ofdpa_port->rocker_port,
+                              ofdpa_flags_nowait(flags),
+                              ofdpa_cmd_flow_tbl_add,
+                              found, NULL, NULL);
        return 0;
 }
 
 static int ofdpa_flow_tbl_del(struct ofdpa_port *ofdpa_port,
-                             struct switchdev_trans *trans, int flags,
-                             struct ofdpa_flow_tbl_entry *match)
+                             int flags, struct ofdpa_flow_tbl_entry *match)
 {
        struct ofdpa *ofdpa = ofdpa_port->ofdpa;
        struct ofdpa_flow_tbl_entry *found;
@@ -872,45 +808,41 @@ static int ofdpa_flow_tbl_del(struct ofdpa_port *ofdpa_port,
        found = ofdpa_flow_tbl_find(ofdpa, match);
 
        if (found) {
-               if (!switchdev_trans_ph_prepare(trans))
-                       hash_del(&found->entry);
+               hash_del(&found->entry);
                found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_DEL;
        }
 
        spin_unlock_irqrestore(&ofdpa->flow_tbl_lock, lock_flags);
 
-       ofdpa_kfree(trans, match);
+       kfree(match);
 
        if (found) {
-               if (!switchdev_trans_ph_prepare(trans))
-                       err = rocker_cmd_exec(ofdpa_port->rocker_port,
-                                             ofdpa_flags_nowait(flags),
-                                             ofdpa_cmd_flow_tbl_del,
-                                             found, NULL, NULL);
-               ofdpa_kfree(trans, found);
+               err = rocker_cmd_exec(ofdpa_port->rocker_port,
+                                     ofdpa_flags_nowait(flags),
+                                     ofdpa_cmd_flow_tbl_del,
+                                     found, NULL, NULL);
+               kfree(found);
        }
 
        return err;
 }
 
-static int ofdpa_flow_tbl_do(struct ofdpa_port *ofdpa_port,
-                            struct switchdev_trans *trans, int flags,
+static int ofdpa_flow_tbl_do(struct ofdpa_port *ofdpa_port, int flags,
                             struct ofdpa_flow_tbl_entry *entry)
 {
        if (flags & OFDPA_OP_FLAG_REMOVE)
-               return ofdpa_flow_tbl_del(ofdpa_port, trans, flags, entry);
+               return ofdpa_flow_tbl_del(ofdpa_port, flags, entry);
        else
-               return ofdpa_flow_tbl_add(ofdpa_port, trans, flags, entry);
+               return ofdpa_flow_tbl_add(ofdpa_port, flags, entry);
 }
 
-static int ofdpa_flow_tbl_ig_port(struct ofdpa_port *ofdpa_port,
-                                 struct switchdev_trans *trans, int flags,
+static int ofdpa_flow_tbl_ig_port(struct ofdpa_port *ofdpa_port, int flags,
                                  u32 in_pport, u32 in_pport_mask,
                                  enum rocker_of_dpa_table_id goto_tbl)
 {
        struct ofdpa_flow_tbl_entry *entry;
 
-       entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
 
@@ -920,11 +852,11 @@ static int ofdpa_flow_tbl_ig_port(struct ofdpa_port *ofdpa_port,
        entry->key.ig_port.in_pport_mask = in_pport_mask;
        entry->key.ig_port.goto_tbl = goto_tbl;
 
-       return ofdpa_flow_tbl_do(ofdpa_port, trans, flags, entry);
+       return ofdpa_flow_tbl_do(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_flow_tbl_vlan(struct ofdpa_port *ofdpa_port,
-                              struct switchdev_trans *trans, int flags,
+                              int flags,
                               u32 in_pport, __be16 vlan_id,
                               __be16 vlan_id_mask,
                               enum rocker_of_dpa_table_id goto_tbl,
@@ -932,7 +864,7 @@ static int ofdpa_flow_tbl_vlan(struct ofdpa_port *ofdpa_port,
 {
        struct ofdpa_flow_tbl_entry *entry;
 
-       entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
 
@@ -946,11 +878,10 @@ static int ofdpa_flow_tbl_vlan(struct ofdpa_port *ofdpa_port,
        entry->key.vlan.untagged = untagged;
        entry->key.vlan.new_vlan_id = new_vlan_id;
 
-       return ofdpa_flow_tbl_do(ofdpa_port, trans, flags, entry);
+       return ofdpa_flow_tbl_do(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_flow_tbl_term_mac(struct ofdpa_port *ofdpa_port,
-                                  struct switchdev_trans *trans,
                                   u32 in_pport, u32 in_pport_mask,
                                   __be16 eth_type, const u8 *eth_dst,
                                   const u8 *eth_dst_mask, __be16 vlan_id,
@@ -959,7 +890,7 @@ static int ofdpa_flow_tbl_term_mac(struct ofdpa_port *ofdpa_port,
 {
        struct ofdpa_flow_tbl_entry *entry;
 
-       entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
 
@@ -983,13 +914,13 @@ static int ofdpa_flow_tbl_term_mac(struct ofdpa_port *ofdpa_port,
        entry->key.term_mac.vlan_id_mask = vlan_id_mask;
        entry->key.term_mac.copy_to_cpu = copy_to_cpu;
 
-       return ofdpa_flow_tbl_do(ofdpa_port, trans, flags, entry);
+       return ofdpa_flow_tbl_do(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_flow_tbl_bridge(struct ofdpa_port *ofdpa_port,
-                                struct switchdev_trans *trans, int flags,
-                                const u8 *eth_dst, const u8 *eth_dst_mask,
-                                __be16 vlan_id, u32 tunnel_id,
+                                int flags, const u8 *eth_dst,
+                                const u8 *eth_dst_mask,  __be16 vlan_id,
+                                u32 tunnel_id,
                                 enum rocker_of_dpa_table_id goto_tbl,
                                 u32 group_id, bool copy_to_cpu)
 {
@@ -999,7 +930,7 @@ static int ofdpa_flow_tbl_bridge(struct ofdpa_port *ofdpa_port,
        bool dflt = !eth_dst || (eth_dst && eth_dst_mask);
        bool wild = false;
 
-       entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+       entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
        if (!entry)
                return -ENOMEM;
 
@@ -1037,11 +968,10 @@ static int ofdpa_flow_tbl_bridge(struct ofdpa_port *ofdpa_port,
        entry->key.bridge.group_id = group_id;
        entry->key.bridge.copy_to_cpu = copy_to_cpu;
 
-       return ofdpa_flow_tbl_do(ofdpa_port, trans, flags, entry);
+       return ofdpa_flow_tbl_do(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_flow_tbl_ucast4_routing(struct ofdpa_port *ofdpa_port,
-                                        struct switchdev_trans *trans,
                                         __be16 eth_type, __be32 dst,
                                         __be32 dst_mask, u32 priority,
                                         enum rocker_of_dpa_table_id goto_tbl,
@@ -1050,7 +980,7 @@ static int ofdpa_flow_tbl_ucast4_routing(struct ofdpa_port *ofdpa_port,
 {
        struct ofdpa_flow_tbl_entry *entry;
 
-       entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
 
@@ -1065,11 +995,10 @@ static int ofdpa_flow_tbl_ucast4_routing(struct ofdpa_port *ofdpa_port,
                                  ucast_routing.group_id);
        entry->fi = fi;
 
-       return ofdpa_flow_tbl_do(ofdpa_port, trans, flags, entry);
+       return ofdpa_flow_tbl_do(ofdpa_port, flags, entry);
 }
 
-static int ofdpa_flow_tbl_acl(struct ofdpa_port *ofdpa_port,
-                             struct switchdev_trans *trans, int flags,
+static int ofdpa_flow_tbl_acl(struct ofdpa_port *ofdpa_port, int flags,
                              u32 in_pport, u32 in_pport_mask,
                              const u8 *eth_src, const u8 *eth_src_mask,
                              const u8 *eth_dst, const u8 *eth_dst_mask,
@@ -1081,7 +1010,7 @@ static int ofdpa_flow_tbl_acl(struct ofdpa_port *ofdpa_port,
        u32 priority;
        struct ofdpa_flow_tbl_entry *entry;
 
-       entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
 
@@ -1116,7 +1045,7 @@ static int ofdpa_flow_tbl_acl(struct ofdpa_port *ofdpa_port,
        entry->key.acl.ip_tos_mask = ip_tos_mask;
        entry->key.acl.group_id = group_id;
 
-       return ofdpa_flow_tbl_do(ofdpa_port, trans, flags, entry);
+       return ofdpa_flow_tbl_do(ofdpa_port, flags, entry);
 }
 
 static struct ofdpa_group_tbl_entry *
@@ -1134,22 +1063,20 @@ ofdpa_group_tbl_find(const struct ofdpa *ofdpa,
        return NULL;
 }
 
-static void ofdpa_group_tbl_entry_free(struct switchdev_trans *trans,
-                                      struct ofdpa_group_tbl_entry *entry)
+static void ofdpa_group_tbl_entry_free(struct ofdpa_group_tbl_entry *entry)
 {
        switch (ROCKER_GROUP_TYPE_GET(entry->group_id)) {
        case ROCKER_OF_DPA_GROUP_TYPE_L2_FLOOD:
        case ROCKER_OF_DPA_GROUP_TYPE_L2_MCAST:
-               ofdpa_kfree(trans, entry->group_ids);
+               kfree(entry->group_ids);
                break;
        default:
                break;
        }
-       ofdpa_kfree(trans, entry);
+       kfree(entry);
 }
 
-static int ofdpa_group_tbl_add(struct ofdpa_port *ofdpa_port,
-                              struct switchdev_trans *trans, int flags,
+static int ofdpa_group_tbl_add(struct ofdpa_port *ofdpa_port, int flags,
                               struct ofdpa_group_tbl_entry *match)
 {
        struct ofdpa *ofdpa = ofdpa_port->ofdpa;
@@ -1161,9 +1088,8 @@ static int ofdpa_group_tbl_add(struct ofdpa_port *ofdpa_port,
        found = ofdpa_group_tbl_find(ofdpa, match);
 
        if (found) {
-               if (!switchdev_trans_ph_prepare(trans))
-                       hash_del(&found->entry);
-               ofdpa_group_tbl_entry_free(trans, found);
+               hash_del(&found->entry);
+               ofdpa_group_tbl_entry_free(found);
                found = match;
                found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_MOD;
        } else {
@@ -1171,21 +1097,17 @@ static int ofdpa_group_tbl_add(struct ofdpa_port *ofdpa_port,
                found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_ADD;
        }
 
-       if (!switchdev_trans_ph_prepare(trans))
-               hash_add(ofdpa->group_tbl, &found->entry, found->group_id);
+       hash_add(ofdpa->group_tbl, &found->entry, found->group_id);
 
        spin_unlock_irqrestore(&ofdpa->group_tbl_lock, lock_flags);
 
-       if (!switchdev_trans_ph_prepare(trans))
-               return rocker_cmd_exec(ofdpa_port->rocker_port,
-                                      ofdpa_flags_nowait(flags),
-                                      ofdpa_cmd_group_tbl_add,
-                                      found, NULL, NULL);
-       return 0;
+       return rocker_cmd_exec(ofdpa_port->rocker_port,
+                              ofdpa_flags_nowait(flags),
+                              ofdpa_cmd_group_tbl_add,
+                              found, NULL, NULL);
 }
 
-static int ofdpa_group_tbl_del(struct ofdpa_port *ofdpa_port,
-                              struct switchdev_trans *trans, int flags,
+static int ofdpa_group_tbl_del(struct ofdpa_port *ofdpa_port, int flags,
                               struct ofdpa_group_tbl_entry *match)
 {
        struct ofdpa *ofdpa = ofdpa_port->ofdpa;
@@ -1198,97 +1120,90 @@ static int ofdpa_group_tbl_del(struct ofdpa_port *ofdpa_port,
        found = ofdpa_group_tbl_find(ofdpa, match);
 
        if (found) {
-               if (!switchdev_trans_ph_prepare(trans))
-                       hash_del(&found->entry);
+               hash_del(&found->entry);
                found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_DEL;
        }
 
        spin_unlock_irqrestore(&ofdpa->group_tbl_lock, lock_flags);
 
-       ofdpa_group_tbl_entry_free(trans, match);
+       ofdpa_group_tbl_entry_free(match);
 
        if (found) {
-               if (!switchdev_trans_ph_prepare(trans))
-                       err = rocker_cmd_exec(ofdpa_port->rocker_port,
-                                             ofdpa_flags_nowait(flags),
-                                             ofdpa_cmd_group_tbl_del,
-                                             found, NULL, NULL);
-               ofdpa_group_tbl_entry_free(trans, found);
+               err = rocker_cmd_exec(ofdpa_port->rocker_port,
+                                     ofdpa_flags_nowait(flags),
+                                     ofdpa_cmd_group_tbl_del,
+                                     found, NULL, NULL);
+               ofdpa_group_tbl_entry_free(found);
        }
 
        return err;
 }
 
-static int ofdpa_group_tbl_do(struct ofdpa_port *ofdpa_port,
-                             struct switchdev_trans *trans, int flags,
+static int ofdpa_group_tbl_do(struct ofdpa_port *ofdpa_port, int flags,
                              struct ofdpa_group_tbl_entry *entry)
 {
        if (flags & OFDPA_OP_FLAG_REMOVE)
-               return ofdpa_group_tbl_del(ofdpa_port, trans, flags, entry);
+               return ofdpa_group_tbl_del(ofdpa_port, flags, entry);
        else
-               return ofdpa_group_tbl_add(ofdpa_port, trans, flags, entry);
+               return ofdpa_group_tbl_add(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_group_l2_interface(struct ofdpa_port *ofdpa_port,
-                                   struct switchdev_trans *trans, int flags,
-                                   __be16 vlan_id, u32 out_pport,
-                                   int pop_vlan)
+                                   int flags, __be16 vlan_id,
+                                   u32 out_pport, int pop_vlan)
 {
        struct ofdpa_group_tbl_entry *entry;
 
-       entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
 
        entry->group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport);
        entry->l2_interface.pop_vlan = pop_vlan;
 
-       return ofdpa_group_tbl_do(ofdpa_port, trans, flags, entry);
+       return ofdpa_group_tbl_do(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_group_l2_fan_out(struct ofdpa_port *ofdpa_port,
-                                 struct switchdev_trans *trans,
                                  int flags, u8 group_count,
                                  const u32 *group_ids, u32 group_id)
 {
        struct ofdpa_group_tbl_entry *entry;
 
-       entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
 
        entry->group_id = group_id;
        entry->group_count = group_count;
 
-       entry->group_ids = ofdpa_kcalloc(trans, flags,
-                                        group_count, sizeof(u32));
+       entry->group_ids = kcalloc(flags, group_count, sizeof(u32));
        if (!entry->group_ids) {
-               ofdpa_kfree(trans, entry);
+               kfree(entry);
                return -ENOMEM;
        }
        memcpy(entry->group_ids, group_ids, group_count * sizeof(u32));
 
-       return ofdpa_group_tbl_do(ofdpa_port, trans, flags, entry);
+       return ofdpa_group_tbl_do(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_group_l2_flood(struct ofdpa_port *ofdpa_port,
-                               struct switchdev_trans *trans, int flags,
-                               __be16 vlan_id, u8 group_count,
-                               const u32 *group_ids, u32 group_id)
+                               int flags, __be16 vlan_id,
+                               u8 group_count, const u32 *group_ids,
+                               u32 group_id)
 {
-       return ofdpa_group_l2_fan_out(ofdpa_port, trans, flags,
+       return ofdpa_group_l2_fan_out(ofdpa_port, flags,
                                      group_count, group_ids,
                                      group_id);
 }
 
-static int ofdpa_group_l3_unicast(struct ofdpa_port *ofdpa_port,
-                                 struct switchdev_trans *trans, int flags,
+static int ofdpa_group_l3_unicast(struct ofdpa_port *ofdpa_port, int flags,
                                  u32 index, const u8 *src_mac, const u8 *dst_mac,
                                  __be16 vlan_id, bool ttl_check, u32 pport)
 {
        struct ofdpa_group_tbl_entry *entry;
 
-       entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
 
@@ -1301,7 +1216,7 @@ static int ofdpa_group_l3_unicast(struct ofdpa_port *ofdpa_port,
        entry->l3_unicast.ttl_check = ttl_check;
        entry->l3_unicast.group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, pport);
 
-       return ofdpa_group_tbl_do(ofdpa_port, trans, flags, entry);
+       return ofdpa_group_tbl_do(ofdpa_port, flags, entry);
 }
 
 static struct ofdpa_neigh_tbl_entry *
@@ -1318,43 +1233,34 @@ ofdpa_neigh_tbl_find(const struct ofdpa *ofdpa, __be32 ip_addr)
 }
 
 static void ofdpa_neigh_add(struct ofdpa *ofdpa,
-                           struct switchdev_trans *trans,
                            struct ofdpa_neigh_tbl_entry *entry)
 {
-       if (!switchdev_trans_ph_commit(trans))
-               entry->index = ofdpa->neigh_tbl_next_index++;
-       if (switchdev_trans_ph_prepare(trans))
-               return;
+       entry->index = ofdpa->neigh_tbl_next_index++;
        entry->ref_count++;
        hash_add(ofdpa->neigh_tbl, &entry->entry,
                 be32_to_cpu(entry->ip_addr));
 }
 
-static void ofdpa_neigh_del(struct switchdev_trans *trans,
-                           struct ofdpa_neigh_tbl_entry *entry)
+static void ofdpa_neigh_del(struct ofdpa_neigh_tbl_entry *entry)
 {
-       if (switchdev_trans_ph_prepare(trans))
-               return;
        if (--entry->ref_count == 0) {
                hash_del(&entry->entry);
-               ofdpa_kfree(trans, entry);
+               kfree(entry);
        }
 }
 
 static void ofdpa_neigh_update(struct ofdpa_neigh_tbl_entry *entry,
-                              struct switchdev_trans *trans,
                               const u8 *eth_dst, bool ttl_check)
 {
        if (eth_dst) {
                ether_addr_copy(entry->eth_dst, eth_dst);
                entry->ttl_check = ttl_check;
-       } else if (!switchdev_trans_ph_prepare(trans)) {
+       } else {
                entry->ref_count++;
        }
 }
 
 static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
-                                struct switchdev_trans *trans,
                                 int flags, __be32 ip_addr, const u8 *eth_dst)
 {
        struct ofdpa *ofdpa = ofdpa_port->ofdpa;
@@ -1371,7 +1277,7 @@ static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
        bool removing;
        int err = 0;
 
-       entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
 
@@ -1388,12 +1294,12 @@ static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
                entry->dev = ofdpa_port->dev;
                ether_addr_copy(entry->eth_dst, eth_dst);
                entry->ttl_check = true;
-               ofdpa_neigh_add(ofdpa, trans, entry);
+               ofdpa_neigh_add(ofdpa, entry);
        } else if (removing) {
                memcpy(entry, found, sizeof(*entry));
-               ofdpa_neigh_del(trans, found);
+               ofdpa_neigh_del(found);
        } else if (updating) {
-               ofdpa_neigh_update(found, trans, eth_dst, true);
+               ofdpa_neigh_update(found, eth_dst, true);
                memcpy(entry, found, sizeof(*entry));
        } else {
                err = -ENOENT;
@@ -1410,7 +1316,7 @@ static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
         * other routes' nexthops.
         */
 
-       err = ofdpa_group_l3_unicast(ofdpa_port, trans, flags,
+       err = ofdpa_group_l3_unicast(ofdpa_port, flags,
                                     entry->index,
                                     ofdpa_port->dev->dev_addr,
                                     entry->eth_dst,
@@ -1425,7 +1331,7 @@ static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
 
        if (adding || removing) {
                group_id = ROCKER_GROUP_L3_UNICAST(entry->index);
-               err = ofdpa_flow_tbl_ucast4_routing(ofdpa_port, trans,
+               err = ofdpa_flow_tbl_ucast4_routing(ofdpa_port,
                                                    eth_type, ip_addr,
                                                    inet_make_mask(32),
                                                    priority, goto_tbl,
@@ -1438,13 +1344,12 @@ static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
 
 err_out:
        if (!adding)
-               ofdpa_kfree(trans, entry);
+               kfree(entry);
 
        return err;
 }
 
 static int ofdpa_port_ipv4_resolve(struct ofdpa_port *ofdpa_port,
-                                  struct switchdev_trans *trans,
                                   __be32 ip_addr)
 {
        struct net_device *dev = ofdpa_port->dev;
@@ -1463,7 +1368,7 @@ static int ofdpa_port_ipv4_resolve(struct ofdpa_port *ofdpa_port,
         */
 
        if (n->nud_state & NUD_VALID)
-               err = ofdpa_port_ipv4_neigh(ofdpa_port, trans, 0,
+               err = ofdpa_port_ipv4_neigh(ofdpa_port, 0,
                                            ip_addr, n->ha);
        else
                neigh_event_send(n, NULL);
@@ -1473,8 +1378,7 @@ static int ofdpa_port_ipv4_resolve(struct ofdpa_port *ofdpa_port,
 }
 
 static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
-                             struct switchdev_trans *trans, int flags,
-                             __be32 ip_addr, u32 *index)
+                             int flags, __be32 ip_addr, u32 *index)
 {
        struct ofdpa *ofdpa = ofdpa_port->ofdpa;
        struct ofdpa_neigh_tbl_entry *entry;
@@ -1486,7 +1390,7 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
        bool resolved = true;
        int err = 0;
 
-       entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
 
@@ -1501,14 +1405,14 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
        if (adding) {
                entry->ip_addr = ip_addr;
                entry->dev = ofdpa_port->dev;
-               ofdpa_neigh_add(ofdpa, trans, entry);
+               ofdpa_neigh_add(ofdpa, entry);
                *index = entry->index;
                resolved = false;
        } else if (removing) {
-               ofdpa_neigh_del(trans, found);
+               ofdpa_neigh_del(found);
                *index = found->index;
        } else if (updating) {
-               ofdpa_neigh_update(found, trans, NULL, false);
+               ofdpa_neigh_update(found, NULL, false);
                resolved = !is_zero_ether_addr(found->eth_dst);
                *index = found->index;
        } else {
@@ -1518,7 +1422,7 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
        spin_unlock_irqrestore(&ofdpa->neigh_tbl_lock, lock_flags);
 
        if (!adding)
-               ofdpa_kfree(trans, entry);
+               kfree(entry);
 
        if (err)
                return err;
@@ -1526,7 +1430,7 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
        /* Resolved means neigh ip_addr is resolved to neigh mac. */
 
        if (!resolved)
-               err = ofdpa_port_ipv4_resolve(ofdpa_port, trans, ip_addr);
+               err = ofdpa_port_ipv4_resolve(ofdpa_port, ip_addr);
 
        return err;
 }
@@ -1541,7 +1445,6 @@ static struct ofdpa_port *ofdpa_port_get(const struct ofdpa *ofdpa,
 }
 
 static int ofdpa_port_vlan_flood_group(struct ofdpa_port *ofdpa_port,
-                                      struct switchdev_trans *trans,
                                       int flags, __be16 vlan_id)
 {
        struct ofdpa_port *p;
@@ -1553,7 +1456,7 @@ static int ofdpa_port_vlan_flood_group(struct ofdpa_port *ofdpa_port,
        int err = 0;
        int i;
 
-       group_ids = ofdpa_kcalloc(trans, flags, port_count, sizeof(u32));
+       group_ids = kcalloc(flags, port_count, sizeof(u32));
        if (!group_ids)
                return -ENOMEM;
 
@@ -1578,18 +1481,17 @@ static int ofdpa_port_vlan_flood_group(struct ofdpa_port *ofdpa_port,
        if (group_count == 0)
                goto no_ports_in_vlan;
 
-       err = ofdpa_group_l2_flood(ofdpa_port, trans, flags, vlan_id,
+       err = ofdpa_group_l2_flood(ofdpa_port, flags, vlan_id,
                                   group_count, group_ids, group_id);
        if (err)
                netdev_err(ofdpa_port->dev, "Error (%d) port VLAN l2 flood group\n", err);
 
 no_ports_in_vlan:
-       ofdpa_kfree(trans, group_ids);
+       kfree(group_ids);
        return err;
 }
 
-static int ofdpa_port_vlan_l2_groups(struct ofdpa_port *ofdpa_port,
-                                    struct switchdev_trans *trans, int flags,
+static int ofdpa_port_vlan_l2_groups(struct ofdpa_port *ofdpa_port, int flags,
                                     __be16 vlan_id, bool pop_vlan)
 {
        const struct ofdpa *ofdpa = ofdpa_port->ofdpa;
@@ -1608,7 +1510,7 @@ static int ofdpa_port_vlan_l2_groups(struct ofdpa_port *ofdpa_port,
        if (ofdpa_port->stp_state == BR_STATE_LEARNING ||
            ofdpa_port->stp_state == BR_STATE_FORWARDING) {
                out_pport = ofdpa_port->pport;
-               err = ofdpa_group_l2_interface(ofdpa_port, trans, flags,
+               err = ofdpa_group_l2_interface(ofdpa_port, flags,
                                               vlan_id, out_pport, pop_vlan);
                if (err) {
                        netdev_err(ofdpa_port->dev, "Error (%d) port VLAN l2 group for pport %d\n",
@@ -1632,7 +1534,7 @@ static int ofdpa_port_vlan_l2_groups(struct ofdpa_port *ofdpa_port,
                return 0;
 
        out_pport = 0;
-       err = ofdpa_group_l2_interface(ofdpa_port, trans, flags,
+       err = ofdpa_group_l2_interface(ofdpa_port, flags,
                                       vlan_id, out_pport, pop_vlan);
        if (err) {
                netdev_err(ofdpa_port->dev, "Error (%d) port VLAN l2 group for CPU port\n", err);
@@ -1693,8 +1595,7 @@ static struct ofdpa_ctrl {
        },
 };
 
-static int ofdpa_port_ctrl_vlan_acl(struct ofdpa_port *ofdpa_port,
-                                   struct switchdev_trans *trans, int flags,
+static int ofdpa_port_ctrl_vlan_acl(struct ofdpa_port *ofdpa_port, int flags,
                                    const struct ofdpa_ctrl *ctrl, __be16 vlan_id)
 {
        u32 in_pport = ofdpa_port->pport;
@@ -1710,7 +1611,7 @@ static int ofdpa_port_ctrl_vlan_acl(struct ofdpa_port *ofdpa_port,
        u32 group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport);
        int err;
 
-       err = ofdpa_flow_tbl_acl(ofdpa_port, trans, flags,
+       err = ofdpa_flow_tbl_acl(ofdpa_port, flags,
                                 in_pport, in_pport_mask,
                                 eth_src, eth_src_mask,
                                 ctrl->eth_dst, ctrl->eth_dst_mask,
@@ -1727,9 +1628,7 @@ static int ofdpa_port_ctrl_vlan_acl(struct ofdpa_port *ofdpa_port,
 }
 
 static int ofdpa_port_ctrl_vlan_bridge(struct ofdpa_port *ofdpa_port,
-                                      struct switchdev_trans *trans,
-                                      int flags,
-                                      const struct ofdpa_ctrl *ctrl,
+                                      int flags, const struct ofdpa_ctrl *ctrl,
                                       __be16 vlan_id)
 {
        enum rocker_of_dpa_table_id goto_tbl =
@@ -1741,7 +1640,7 @@ static int ofdpa_port_ctrl_vlan_bridge(struct ofdpa_port *ofdpa_port,
        if (!ofdpa_port_is_bridged(ofdpa_port))
                return 0;
 
-       err = ofdpa_flow_tbl_bridge(ofdpa_port, trans, flags,
+       err = ofdpa_flow_tbl_bridge(ofdpa_port, flags,
                                    ctrl->eth_dst, ctrl->eth_dst_mask,
                                    vlan_id, tunnel_id,
                                    goto_tbl, group_id, ctrl->copy_to_cpu);
@@ -1752,8 +1651,7 @@ static int ofdpa_port_ctrl_vlan_bridge(struct ofdpa_port *ofdpa_port,
        return err;
 }
 
-static int ofdpa_port_ctrl_vlan_term(struct ofdpa_port *ofdpa_port,
-                                    struct switchdev_trans *trans, int flags,
+static int ofdpa_port_ctrl_vlan_term(struct ofdpa_port *ofdpa_port, int flags,
                                     const struct ofdpa_ctrl *ctrl, __be16 vlan_id)
 {
        u32 in_pport_mask = 0xffffffff;
@@ -1763,8 +1661,7 @@ static int ofdpa_port_ctrl_vlan_term(struct ofdpa_port *ofdpa_port,
        if (ntohs(vlan_id) == 0)
                vlan_id = ofdpa_port->internal_vlan_id;
 
-       err = ofdpa_flow_tbl_term_mac(ofdpa_port, trans,
-                                     ofdpa_port->pport, in_pport_mask,
+       err = ofdpa_flow_tbl_term_mac(ofdpa_port, ofdpa_port->pport, in_pport_mask,
                                      ctrl->eth_type, ctrl->eth_dst,
                                      ctrl->eth_dst_mask, vlan_id,
                                      vlan_id_mask, ctrl->copy_to_cpu,
@@ -1776,26 +1673,24 @@ static int ofdpa_port_ctrl_vlan_term(struct ofdpa_port *ofdpa_port,
        return err;
 }
 
-static int ofdpa_port_ctrl_vlan(struct ofdpa_port *ofdpa_port,
-                               struct switchdev_trans *trans, int flags,
+static int ofdpa_port_ctrl_vlan(struct ofdpa_port *ofdpa_port, int flags,
                                const struct ofdpa_ctrl *ctrl, __be16 vlan_id)
 {
        if (ctrl->acl)
-               return ofdpa_port_ctrl_vlan_acl(ofdpa_port, trans, flags,
+               return ofdpa_port_ctrl_vlan_acl(ofdpa_port, flags,
                                                ctrl, vlan_id);
        if (ctrl->bridge)
-               return ofdpa_port_ctrl_vlan_bridge(ofdpa_port, trans, flags,
+               return ofdpa_port_ctrl_vlan_bridge(ofdpa_port, flags,
                                                   ctrl, vlan_id);
 
        if (ctrl->term)
-               return ofdpa_port_ctrl_vlan_term(ofdpa_port, trans, flags,
+               return ofdpa_port_ctrl_vlan_term(ofdpa_port, flags,
                                                 ctrl, vlan_id);
 
        return -EOPNOTSUPP;
 }
 
-static int ofdpa_port_ctrl_vlan_add(struct ofdpa_port *ofdpa_port,
-                                   struct switchdev_trans *trans, int flags,
+static int ofdpa_port_ctrl_vlan_add(struct ofdpa_port *ofdpa_port, int flags,
                                    __be16 vlan_id)
 {
        int err = 0;
@@ -1803,7 +1698,7 @@ static int ofdpa_port_ctrl_vlan_add(struct ofdpa_port *ofdpa_port,
 
        for (i = 0; i < OFDPA_CTRL_MAX; i++) {
                if (ofdpa_port->ctrls[i]) {
-                       err = ofdpa_port_ctrl_vlan(ofdpa_port, trans, flags,
+                       err = ofdpa_port_ctrl_vlan(ofdpa_port, flags,
                                                   &ofdpa_ctrls[i], vlan_id);
                        if (err)
                                return err;
@@ -1813,8 +1708,7 @@ static int ofdpa_port_ctrl_vlan_add(struct ofdpa_port *ofdpa_port,
        return err;
 }
 
-static int ofdpa_port_ctrl(struct ofdpa_port *ofdpa_port,
-                          struct switchdev_trans *trans, int flags,
+static int ofdpa_port_ctrl(struct ofdpa_port *ofdpa_port, int flags,
                           const struct ofdpa_ctrl *ctrl)
 {
        u16 vid;
@@ -1823,7 +1717,7 @@ static int ofdpa_port_ctrl(struct ofdpa_port *ofdpa_port,
        for (vid = 1; vid < VLAN_N_VID; vid++) {
                if (!test_bit(vid, ofdpa_port->vlan_bitmap))
                        continue;
-               err = ofdpa_port_ctrl_vlan(ofdpa_port, trans, flags,
+               err = ofdpa_port_ctrl_vlan(ofdpa_port, flags,
                                           ctrl, htons(vid));
                if (err)
                        break;
@@ -1832,8 +1726,8 @@ static int ofdpa_port_ctrl(struct ofdpa_port *ofdpa_port,
        return err;
 }
 
-static int ofdpa_port_vlan(struct ofdpa_port *ofdpa_port,
-                          struct switchdev_trans *trans, int flags, u16 vid)
+static int ofdpa_port_vlan(struct ofdpa_port *ofdpa_port, int flags,
+                          u16 vid)
 {
        enum rocker_of_dpa_table_id goto_tbl =
                        ROCKER_OF_DPA_TABLE_ID_TERMINATION_MAC;
@@ -1857,43 +1751,44 @@ static int ofdpa_port_vlan(struct ofdpa_port *ofdpa_port,
        change_bit(ntohs(internal_vlan_id), ofdpa_port->vlan_bitmap);
 
        if (adding) {
-               err = ofdpa_port_ctrl_vlan_add(ofdpa_port, trans, flags,
+               err = ofdpa_port_ctrl_vlan_add(ofdpa_port, flags,
                                               internal_vlan_id);
                if (err) {
                        netdev_err(ofdpa_port->dev, "Error (%d) port ctrl vlan add\n", err);
-                       goto err_out;
+                       goto err_vlan_add;
                }
        }
 
-       err = ofdpa_port_vlan_l2_groups(ofdpa_port, trans, flags,
+       err = ofdpa_port_vlan_l2_groups(ofdpa_port, flags,
                                        internal_vlan_id, untagged);
        if (err) {
                netdev_err(ofdpa_port->dev, "Error (%d) port VLAN l2 groups\n", err);
-               goto err_out;
+               goto err_vlan_l2_groups;
        }
 
-       err = ofdpa_port_vlan_flood_group(ofdpa_port, trans, flags,
+       err = ofdpa_port_vlan_flood_group(ofdpa_port, flags,
                                          internal_vlan_id);
        if (err) {
                netdev_err(ofdpa_port->dev, "Error (%d) port VLAN l2 flood group\n", err);
-               goto err_out;
+               goto err_flood_group;
        }
 
-       err = ofdpa_flow_tbl_vlan(ofdpa_port, trans, flags,
+       err = ofdpa_flow_tbl_vlan(ofdpa_port, flags,
                                  in_pport, vlan_id, vlan_id_mask,
                                  goto_tbl, untagged, internal_vlan_id);
        if (err)
                netdev_err(ofdpa_port->dev, "Error (%d) port VLAN table\n", err);
 
-err_out:
-       if (switchdev_trans_ph_prepare(trans))
-               change_bit(ntohs(internal_vlan_id), ofdpa_port->vlan_bitmap);
+       return 0;
 
+err_vlan_add:
+err_vlan_l2_groups:
+err_flood_group:
+       change_bit(ntohs(internal_vlan_id), ofdpa_port->vlan_bitmap);
        return err;
 }
 
-static int ofdpa_port_ig_tbl(struct ofdpa_port *ofdpa_port,
-                            struct switchdev_trans *trans, int flags)
+static int ofdpa_port_ig_tbl(struct ofdpa_port *ofdpa_port, int flags)
 {
        enum rocker_of_dpa_table_id goto_tbl;
        u32 in_pport;
@@ -1908,7 +1803,7 @@ static int ofdpa_port_ig_tbl(struct ofdpa_port *ofdpa_port,
        in_pport_mask = 0xffff0000;
        goto_tbl = ROCKER_OF_DPA_TABLE_ID_VLAN;
 
-       err = ofdpa_flow_tbl_ig_port(ofdpa_port, trans, flags,
+       err = ofdpa_flow_tbl_ig_port(ofdpa_port, flags,
                                     in_pport, in_pport_mask,
                                     goto_tbl);
        if (err)
@@ -1920,7 +1815,6 @@ static int ofdpa_port_ig_tbl(struct ofdpa_port *ofdpa_port,
 struct ofdpa_fdb_learn_work {
        struct work_struct work;
        struct ofdpa_port *ofdpa_port;
-       struct switchdev_trans *trans;
        int flags;
        u8 addr[ETH_ALEN];
        u16 vid;
@@ -1939,19 +1833,18 @@ static void ofdpa_port_fdb_learn_work(struct work_struct *work)
 
        rtnl_lock();
        if (learned && removing)
-               call_switchdev_notifiers(SWITCHDEV_FDB_DEL,
+               call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE,
                                         lw->ofdpa_port->dev, &info.info);
        else if (learned && !removing)
-               call_switchdev_notifiers(SWITCHDEV_FDB_ADD,
+               call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE,
                                         lw->ofdpa_port->dev, &info.info);
        rtnl_unlock();
 
-       ofdpa_kfree(lw->trans, work);
+       kfree(work);
 }
 
 static int ofdpa_port_fdb_learn(struct ofdpa_port *ofdpa_port,
-                               struct switchdev_trans *trans, int flags,
-                               const u8 *addr, __be16 vlan_id)
+                               int flags, const u8 *addr, __be16 vlan_id)
 {
        struct ofdpa_fdb_learn_work *lw;
        enum rocker_of_dpa_table_id goto_tbl =
@@ -1959,7 +1852,6 @@ static int ofdpa_port_fdb_learn(struct ofdpa_port *ofdpa_port,
        u32 out_pport = ofdpa_port->pport;
        u32 tunnel_id = 0;
        u32 group_id = ROCKER_GROUP_NONE;
-       bool syncing = !!(ofdpa_port->brport_flags & BR_LEARNING_SYNC);
        bool copy_to_cpu = false;
        int err;
 
@@ -1967,36 +1859,28 @@ static int ofdpa_port_fdb_learn(struct ofdpa_port *ofdpa_port,
                group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport);
 
        if (!(flags & OFDPA_OP_FLAG_REFRESH)) {
-               err = ofdpa_flow_tbl_bridge(ofdpa_port, trans, flags, addr,
+               err = ofdpa_flow_tbl_bridge(ofdpa_port, flags, addr,
                                            NULL, vlan_id, tunnel_id, goto_tbl,
                                            group_id, copy_to_cpu);
                if (err)
                        return err;
        }
 
-       if (!syncing)
-               return 0;
-
        if (!ofdpa_port_is_bridged(ofdpa_port))
                return 0;
 
-       lw = ofdpa_kzalloc(trans, flags, sizeof(*lw));
+       lw = kzalloc(sizeof(*lw), GFP_ATOMIC);
        if (!lw)
                return -ENOMEM;
 
        INIT_WORK(&lw->work, ofdpa_port_fdb_learn_work);
 
        lw->ofdpa_port = ofdpa_port;
-       lw->trans = trans;
        lw->flags = flags;
        ether_addr_copy(lw->addr, addr);
        lw->vid = ofdpa_port_vlan_to_vid(ofdpa_port, vlan_id);
 
-       if (switchdev_trans_ph_prepare(trans))
-               ofdpa_kfree(trans, lw);
-       else
-               schedule_work(&lw->work);
-
+       schedule_work(&lw->work);
        return 0;
 }
 
@@ -2014,7 +1898,6 @@ ofdpa_fdb_tbl_find(const struct ofdpa *ofdpa,
 }
 
 static int ofdpa_port_fdb(struct ofdpa_port *ofdpa_port,
-                         struct switchdev_trans *trans,
                          const unsigned char *addr,
                          __be16 vlan_id, int flags)
 {
@@ -2024,7 +1907,7 @@ static int ofdpa_port_fdb(struct ofdpa_port *ofdpa_port,
        bool removing = (flags & OFDPA_OP_FLAG_REMOVE);
        unsigned long lock_flags;
 
-       fdb = ofdpa_kzalloc(trans, flags, sizeof(*fdb));
+       fdb = kzalloc(sizeof(*fdb), GFP_KERNEL);
        if (!fdb)
                return -ENOMEM;
 
@@ -2042,32 +1925,29 @@ static int ofdpa_port_fdb(struct ofdpa_port *ofdpa_port,
        if (found) {
                found->touched = jiffies;
                if (removing) {
-                       ofdpa_kfree(trans, fdb);
-                       if (!switchdev_trans_ph_prepare(trans))
-                               hash_del(&found->entry);
+                       kfree(fdb);
+                       hash_del(&found->entry);
                }
        } else if (!removing) {
-               if (!switchdev_trans_ph_prepare(trans))
-                       hash_add(ofdpa->fdb_tbl, &fdb->entry,
-                                fdb->key_crc32);
+               hash_add(ofdpa->fdb_tbl, &fdb->entry,
+                        fdb->key_crc32);
        }
 
        spin_unlock_irqrestore(&ofdpa->fdb_tbl_lock, lock_flags);
 
        /* Check if adding and already exists, or removing and can't find */
        if (!found != !removing) {
-               ofdpa_kfree(trans, fdb);
+               kfree(fdb);
                if (!found && removing)
                        return 0;
                /* Refreshing existing to update aging timers */
                flags |= OFDPA_OP_FLAG_REFRESH;
        }
 
-       return ofdpa_port_fdb_learn(ofdpa_port, trans, flags, addr, vlan_id);
+       return ofdpa_port_fdb_learn(ofdpa_port, flags, addr, vlan_id);
 }
 
-static int ofdpa_port_fdb_flush(struct ofdpa_port *ofdpa_port,
-                               struct switchdev_trans *trans, int flags)
+static int ofdpa_port_fdb_flush(struct ofdpa_port *ofdpa_port, int flags)
 {
        struct ofdpa *ofdpa = ofdpa_port->ofdpa;
        struct ofdpa_fdb_tbl_entry *found;
@@ -2089,13 +1969,12 @@ static int ofdpa_port_fdb_flush(struct ofdpa_port *ofdpa_port,
                        continue;
                if (!found->learned)
                        continue;
-               err = ofdpa_port_fdb_learn(ofdpa_port, trans, flags,
+               err = ofdpa_port_fdb_learn(ofdpa_port, flags,
                                           found->key.addr,
                                           found->key.vlan_id);
                if (err)
                        goto err_out;
-               if (!switchdev_trans_ph_prepare(trans))
-                       hash_del(&found->entry);
+               hash_del(&found->entry);
        }
 
 err_out:
@@ -2125,8 +2004,8 @@ static void ofdpa_fdb_cleanup(unsigned long data)
                ofdpa_port = entry->key.ofdpa_port;
                expires = entry->touched + ofdpa_port->ageing_time;
                if (time_before_eq(expires, jiffies)) {
-                       ofdpa_port_fdb_learn(ofdpa_port, NULL,
-                                            flags, entry->key.addr,
+                       ofdpa_port_fdb_learn(ofdpa_port, flags,
+                                            entry->key.addr,
                                             entry->key.vlan_id);
                        hash_del(&entry->entry);
                } else if (time_before(expires, next_timer)) {
@@ -2140,8 +2019,7 @@ static void ofdpa_fdb_cleanup(unsigned long data)
 }
 
 static int ofdpa_port_router_mac(struct ofdpa_port *ofdpa_port,
-                                struct switchdev_trans *trans, int flags,
-                                __be16 vlan_id)
+                                int flags, __be16 vlan_id)
 {
        u32 in_pport_mask = 0xffffffff;
        __be16 eth_type;
@@ -2154,26 +2032,25 @@ static int ofdpa_port_router_mac(struct ofdpa_port *ofdpa_port,
                vlan_id = ofdpa_port->internal_vlan_id;
 
        eth_type = htons(ETH_P_IP);
-       err = ofdpa_flow_tbl_term_mac(ofdpa_port, trans,
-                                     ofdpa_port->pport, in_pport_mask,
-                                     eth_type, ofdpa_port->dev->dev_addr,
+       err = ofdpa_flow_tbl_term_mac(ofdpa_port, ofdpa_port->pport,
+                                     in_pport_mask, eth_type,
+                                     ofdpa_port->dev->dev_addr,
                                      dst_mac_mask, vlan_id, vlan_id_mask,
                                      copy_to_cpu, flags);
        if (err)
                return err;
 
        eth_type = htons(ETH_P_IPV6);
-       err = ofdpa_flow_tbl_term_mac(ofdpa_port, trans,
-                                     ofdpa_port->pport, in_pport_mask,
-                                     eth_type, ofdpa_port->dev->dev_addr,
+       err = ofdpa_flow_tbl_term_mac(ofdpa_port, ofdpa_port->pport,
+                                     in_pport_mask, eth_type,
+                                     ofdpa_port->dev->dev_addr,
                                      dst_mac_mask, vlan_id, vlan_id_mask,
                                      copy_to_cpu, flags);
 
        return err;
 }
 
-static int ofdpa_port_fwding(struct ofdpa_port *ofdpa_port,
-                            struct switchdev_trans *trans, int flags)
+static int ofdpa_port_fwding(struct ofdpa_port *ofdpa_port, int flags)
 {
        bool pop_vlan;
        u32 out_pport;
@@ -2198,7 +2075,7 @@ static int ofdpa_port_fwding(struct ofdpa_port *ofdpa_port,
                        continue;
                vlan_id = htons(vid);
                pop_vlan = ofdpa_vlan_id_is_internal(vlan_id);
-               err = ofdpa_group_l2_interface(ofdpa_port, trans, flags,
+               err = ofdpa_group_l2_interface(ofdpa_port, flags,
                                               vlan_id, out_pport, pop_vlan);
                if (err) {
                        netdev_err(ofdpa_port->dev, "Error (%d) port VLAN l2 group for pport %d\n",
@@ -2211,7 +2088,6 @@ static int ofdpa_port_fwding(struct ofdpa_port *ofdpa_port,
 }
 
 static int ofdpa_port_stp_update(struct ofdpa_port *ofdpa_port,
-                                struct switchdev_trans *trans,
                                 int flags, u8 state)
 {
        bool want[OFDPA_CTRL_MAX] = { 0, };
@@ -2220,11 +2096,12 @@ static int ofdpa_port_stp_update(struct ofdpa_port *ofdpa_port,
        int err;
        int i;
 
+       memcpy(prev_ctrls, ofdpa_port->ctrls, sizeof(prev_ctrls));
        prev_state = ofdpa_port->stp_state;
-       if (prev_state == state)
+
+       if (ofdpa_port->stp_state == state)
                return 0;
 
-       memcpy(prev_ctrls, ofdpa_port->ctrls, sizeof(prev_ctrls));
        ofdpa_port->stp_state = state;
 
        switch (state) {
@@ -2254,26 +2131,29 @@ static int ofdpa_port_stp_update(struct ofdpa_port *ofdpa_port,
                if (want[i] != ofdpa_port->ctrls[i]) {
                        int ctrl_flags = flags |
                                         (want[i] ? 0 : OFDPA_OP_FLAG_REMOVE);
-                       err = ofdpa_port_ctrl(ofdpa_port, trans, ctrl_flags,
+                       err = ofdpa_port_ctrl(ofdpa_port, ctrl_flags,
                                              &ofdpa_ctrls[i]);
                        if (err)
-                               goto err_out;
+                               goto err_port_ctrl;
                        ofdpa_port->ctrls[i] = want[i];
                }
        }
 
-       err = ofdpa_port_fdb_flush(ofdpa_port, trans, flags);
+       err = ofdpa_port_fdb_flush(ofdpa_port, flags);
        if (err)
-               goto err_out;
+               goto err_fdb_flush;
 
-       err = ofdpa_port_fwding(ofdpa_port, trans, flags);
+       err = ofdpa_port_fwding(ofdpa_port, flags);
+       if (err)
+               goto err_port_fwding;
 
-err_out:
-       if (switchdev_trans_ph_prepare(trans)) {
-               memcpy(ofdpa_port->ctrls, prev_ctrls, sizeof(prev_ctrls));
-               ofdpa_port->stp_state = prev_state;
-       }
+       return 0;
 
+err_port_ctrl:
+err_fdb_flush:
+err_port_fwding:
+       memcpy(ofdpa_port->ctrls, prev_ctrls, sizeof(prev_ctrls));
+       ofdpa_port->stp_state = prev_state;
        return err;
 }
 
@@ -2284,7 +2164,7 @@ static int ofdpa_port_fwd_enable(struct ofdpa_port *ofdpa_port, int flags)
                return 0;
 
        /* port is not bridged, so simulate going to FORWARDING state */
-       return ofdpa_port_stp_update(ofdpa_port, NULL, flags,
+       return ofdpa_port_stp_update(ofdpa_port, flags,
                                     BR_STATE_FORWARDING);
 }
 
@@ -2295,25 +2175,24 @@ static int ofdpa_port_fwd_disable(struct ofdpa_port *ofdpa_port, int flags)
                return 0;
 
        /* port is not bridged, so simulate going to DISABLED state */
-       return ofdpa_port_stp_update(ofdpa_port, NULL, flags,
+       return ofdpa_port_stp_update(ofdpa_port, flags,
                                     BR_STATE_DISABLED);
 }
 
 static int ofdpa_port_vlan_add(struct ofdpa_port *ofdpa_port,
-                              struct switchdev_trans *trans,
                               u16 vid, u16 flags)
 {
        int err;
 
        /* XXX deal with flags for PVID and untagged */
 
-       err = ofdpa_port_vlan(ofdpa_port, trans, 0, vid);
+       err = ofdpa_port_vlan(ofdpa_port, 0, vid);
        if (err)
                return err;
 
-       err = ofdpa_port_router_mac(ofdpa_port, trans, 0, htons(vid));
+       err = ofdpa_port_router_mac(ofdpa_port, 0, htons(vid));
        if (err)
-               ofdpa_port_vlan(ofdpa_port, trans,
+               ofdpa_port_vlan(ofdpa_port,
                                OFDPA_OP_FLAG_REMOVE, vid);
 
        return err;
@@ -2324,13 +2203,13 @@ static int ofdpa_port_vlan_del(struct ofdpa_port *ofdpa_port,
 {
        int err;
 
-       err = ofdpa_port_router_mac(ofdpa_port, NULL,
-                                   OFDPA_OP_FLAG_REMOVE, htons(vid));
+       err = ofdpa_port_router_mac(ofdpa_port, OFDPA_OP_FLAG_REMOVE,
+                                   htons(vid));
        if (err)
                return err;
 
-       return ofdpa_port_vlan(ofdpa_port, NULL,
-                              OFDPA_OP_FLAG_REMOVE, vid);
+       return ofdpa_port_vlan(ofdpa_port, OFDPA_OP_FLAG_REMOVE,
+                              vid);
 }
 
 static struct ofdpa_internal_vlan_tbl_entry *
@@ -2389,10 +2268,9 @@ static __be16 ofdpa_port_internal_vlan_id_get(struct ofdpa_port *ofdpa_port,
        return found->vlan_id;
 }
 
-static int ofdpa_port_fib_ipv4(struct ofdpa_port *ofdpa_port,
-                              struct switchdev_trans *trans, __be32 dst,
-                              int dst_len, struct fib_info *fi,
-                              u32 tb_id, int flags)
+static int ofdpa_port_fib_ipv4(struct ofdpa_port *ofdpa_port,  __be32 dst,
+                              int dst_len, struct fib_info *fi, u32 tb_id,
+                              int flags)
 {
        const struct fib_nh *nh;
        __be16 eth_type = htons(ETH_P_IP);
@@ -2414,7 +2292,7 @@ static int ofdpa_port_fib_ipv4(struct ofdpa_port *ofdpa_port,
        has_gw = !!nh->nh_gw;
 
        if (has_gw && nh_on_port) {
-               err = ofdpa_port_ipv4_nh(ofdpa_port, trans, flags,
+               err = ofdpa_port_ipv4_nh(ofdpa_port, flags,
                                         nh->nh_gw, &index);
                if (err)
                        return err;
@@ -2425,7 +2303,7 @@ static int ofdpa_port_fib_ipv4(struct ofdpa_port *ofdpa_port,
                group_id = ROCKER_GROUP_L2_INTERFACE(internal_vlan_id, 0);
        }
 
-       err = ofdpa_flow_tbl_ucast4_routing(ofdpa_port, trans, eth_type, dst,
+       err = ofdpa_flow_tbl_ucast4_routing(ofdpa_port, eth_type, dst,
                                            dst_mask, priority, goto_tbl,
                                            group_id, fi, flags);
        if (err)
@@ -2550,7 +2428,7 @@ static int ofdpa_port_pre_init(struct rocker_port *rocker_port)
        ofdpa_port->rocker_port = rocker_port;
        ofdpa_port->dev = rocker_port->dev;
        ofdpa_port->pport = rocker_port->pport;
-       ofdpa_port->brport_flags = BR_LEARNING | BR_LEARNING_SYNC;
+       ofdpa_port->brport_flags = BR_LEARNING;
        ofdpa_port->ageing_time = BR_DEFAULT_AGEING_TIME;
        return 0;
 }
@@ -2563,7 +2441,7 @@ static int ofdpa_port_init(struct rocker_port *rocker_port)
        rocker_port_set_learning(rocker_port,
                                 !!(ofdpa_port->brport_flags & BR_LEARNING));
 
-       err = ofdpa_port_ig_tbl(ofdpa_port, NULL, 0);
+       err = ofdpa_port_ig_tbl(ofdpa_port, 0);
        if (err) {
                netdev_err(ofdpa_port->dev, "install ig port table failed\n");
                return err;
@@ -2573,7 +2451,7 @@ static int ofdpa_port_init(struct rocker_port *rocker_port)
                ofdpa_port_internal_vlan_id_get(ofdpa_port,
                                                ofdpa_port->dev->ifindex);
 
-       err = ofdpa_port_vlan_add(ofdpa_port, NULL, OFDPA_UNTAGGED_VID, 0);
+       err = ofdpa_port_vlan_add(ofdpa_port, OFDPA_UNTAGGED_VID, 0);
        if (err) {
                netdev_err(ofdpa_port->dev, "install untagged VLAN failed\n");
                goto err_untagged_vlan;
@@ -2581,7 +2459,7 @@ static int ofdpa_port_init(struct rocker_port *rocker_port)
        return 0;
 
 err_untagged_vlan:
-       ofdpa_port_ig_tbl(ofdpa_port, NULL, OFDPA_OP_FLAG_REMOVE);
+       ofdpa_port_ig_tbl(ofdpa_port, OFDPA_OP_FLAG_REMOVE);
        return err;
 }
 
@@ -2589,7 +2467,7 @@ static void ofdpa_port_fini(struct rocker_port *rocker_port)
 {
        struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
 
-       ofdpa_port_ig_tbl(ofdpa_port, NULL, OFDPA_OP_FLAG_REMOVE);
+       ofdpa_port_ig_tbl(ofdpa_port, OFDPA_OP_FLAG_REMOVE);
 }
 
 static int ofdpa_port_open(struct rocker_port *rocker_port)
@@ -2607,12 +2485,11 @@ static void ofdpa_port_stop(struct rocker_port *rocker_port)
 }
 
 static int ofdpa_port_attr_stp_state_set(struct rocker_port *rocker_port,
-                                        u8 state,
-                                        struct switchdev_trans *trans)
+                                        u8 state)
 {
        struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
 
-       return ofdpa_port_stp_update(ofdpa_port, trans, 0, state);
+       return ofdpa_port_stp_update(ofdpa_port, 0, state);
 }
 
 static int ofdpa_port_attr_bridge_flags_set(struct rocker_port *rocker_port,
@@ -2646,6 +2523,16 @@ ofdpa_port_attr_bridge_flags_get(const struct rocker_port *rocker_port,
        return 0;
 }
 
+static int
+ofdpa_port_attr_bridge_flags_support_get(const struct rocker_port *
+                                        rocker_port,
+                                        unsigned long *
+                                        p_brport_flags_support)
+{
+       *p_brport_flags_support = BR_LEARNING;
+       return 0;
+}
+
 static int
 ofdpa_port_attr_bridge_ageing_time_set(struct rocker_port *rocker_port,
                                       u32 ageing_time,
@@ -2665,15 +2552,14 @@ ofdpa_port_attr_bridge_ageing_time_set(struct rocker_port *rocker_port,
 }
 
 static int ofdpa_port_obj_vlan_add(struct rocker_port *rocker_port,
-                                  const struct switchdev_obj_port_vlan *vlan,
-                                  struct switchdev_trans *trans)
+                                  const struct switchdev_obj_port_vlan *vlan)
 {
        struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
        u16 vid;
        int err;
 
        for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
-               err = ofdpa_port_vlan_add(ofdpa_port, trans, vid, vlan->flags);
+               err = ofdpa_port_vlan_add(ofdpa_port, vid, vlan->flags);
                if (err)
                        return err;
        }
@@ -2697,82 +2583,29 @@ static int ofdpa_port_obj_vlan_del(struct rocker_port *rocker_port,
        return 0;
 }
 
-static int ofdpa_port_obj_vlan_dump(const struct rocker_port *rocker_port,
-                                   struct switchdev_obj_port_vlan *vlan,
-                                   switchdev_obj_dump_cb_t *cb)
-{
-       const struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
-       u16 vid;
-       int err = 0;
-
-       for (vid = 1; vid < VLAN_N_VID; vid++) {
-               if (!test_bit(vid, ofdpa_port->vlan_bitmap))
-                       continue;
-               vlan->flags = 0;
-               if (ofdpa_vlan_id_is_internal(htons(vid)))
-                       vlan->flags |= BRIDGE_VLAN_INFO_PVID;
-               vlan->vid_begin = vlan->vid_end = vid;
-               err = cb(&vlan->obj);
-               if (err)
-                       break;
-       }
-
-       return err;
-}
-
 static int ofdpa_port_obj_fdb_add(struct rocker_port *rocker_port,
-                                 const struct switchdev_obj_port_fdb *fdb,
-                                 struct switchdev_trans *trans)
+                                 u16 vid, const unsigned char *addr)
 {
        struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
-       __be16 vlan_id = ofdpa_port_vid_to_vlan(ofdpa_port, fdb->vid, NULL);
+       __be16 vlan_id = ofdpa_port_vid_to_vlan(ofdpa_port, vid, NULL);
 
        if (!ofdpa_port_is_bridged(ofdpa_port))
                return -EINVAL;
 
-       return ofdpa_port_fdb(ofdpa_port, trans, fdb->addr, vlan_id, 0);
+       return ofdpa_port_fdb(ofdpa_port, addr, vlan_id, 0);
 }
 
 static int ofdpa_port_obj_fdb_del(struct rocker_port *rocker_port,
-                                 const struct switchdev_obj_port_fdb *fdb)
+                                 u16 vid, const unsigned char *addr)
 {
        struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
-       __be16 vlan_id = ofdpa_port_vid_to_vlan(ofdpa_port, fdb->vid, NULL);
+       __be16 vlan_id = ofdpa_port_vid_to_vlan(ofdpa_port, vid, NULL);
        int flags = OFDPA_OP_FLAG_REMOVE;
 
        if (!ofdpa_port_is_bridged(ofdpa_port))
                return -EINVAL;
 
-       return ofdpa_port_fdb(ofdpa_port, NULL, fdb->addr, vlan_id, flags);
-}
-
-static int ofdpa_port_obj_fdb_dump(const struct rocker_port *rocker_port,
-                                  struct switchdev_obj_port_fdb *fdb,
-                                  switchdev_obj_dump_cb_t *cb)
-{
-       const struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
-       struct ofdpa *ofdpa = ofdpa_port->ofdpa;
-       struct ofdpa_fdb_tbl_entry *found;
-       struct hlist_node *tmp;
-       unsigned long lock_flags;
-       int bkt;
-       int err = 0;
-
-       spin_lock_irqsave(&ofdpa->fdb_tbl_lock, lock_flags);
-       hash_for_each_safe(ofdpa->fdb_tbl, bkt, tmp, found, entry) {
-               if (found->key.ofdpa_port != ofdpa_port)
-                       continue;
-               ether_addr_copy(fdb->addr, found->key.addr);
-               fdb->ndm_state = NUD_REACHABLE;
-               fdb->vid = ofdpa_port_vlan_to_vid(ofdpa_port,
-                                                 found->key.vlan_id);
-               err = cb(&fdb->obj);
-               if (err)
-                       break;
-       }
-       spin_unlock_irqrestore(&ofdpa->fdb_tbl_lock, lock_flags);
-
-       return err;
+       return ofdpa_port_fdb(ofdpa_port, addr, vlan_id, flags);
 }
 
 static int ofdpa_port_bridge_join(struct ofdpa_port *ofdpa_port,
@@ -2797,7 +2630,7 @@ static int ofdpa_port_bridge_join(struct ofdpa_port *ofdpa_port,
 
        ofdpa_port->bridge_dev = bridge;
 
-       return ofdpa_port_vlan_add(ofdpa_port, NULL, OFDPA_UNTAGGED_VID, 0);
+       return ofdpa_port_vlan_add(ofdpa_port, OFDPA_UNTAGGED_VID, 0);
 }
 
 static int ofdpa_port_bridge_leave(struct ofdpa_port *ofdpa_port)
@@ -2816,7 +2649,7 @@ static int ofdpa_port_bridge_leave(struct ofdpa_port *ofdpa_port)
 
        ofdpa_port->bridge_dev = NULL;
 
-       err = ofdpa_port_vlan_add(ofdpa_port, NULL, OFDPA_UNTAGGED_VID, 0);
+       err = ofdpa_port_vlan_add(ofdpa_port, OFDPA_UNTAGGED_VID, 0);
        if (err)
                return err;
 
@@ -2875,7 +2708,7 @@ static int ofdpa_port_neigh_update(struct rocker_port *rocker_port,
                                                    OFDPA_OP_FLAG_NOWAIT;
        __be32 ip_addr = *(__be32 *) n->primary_key;
 
-       return ofdpa_port_ipv4_neigh(ofdpa_port, NULL, flags, ip_addr, n->ha);
+       return ofdpa_port_ipv4_neigh(ofdpa_port, flags, ip_addr, n->ha);
 }
 
 static int ofdpa_port_neigh_destroy(struct rocker_port *rocker_port,
@@ -2885,7 +2718,7 @@ static int ofdpa_port_neigh_destroy(struct rocker_port *rocker_port,
        int flags = OFDPA_OP_FLAG_REMOVE | OFDPA_OP_FLAG_NOWAIT;
        __be32 ip_addr = *(__be32 *) n->primary_key;
 
-       return ofdpa_port_ipv4_neigh(ofdpa_port, NULL, flags, ip_addr, n->ha);
+       return ofdpa_port_ipv4_neigh(ofdpa_port, flags, ip_addr, n->ha);
 }
 
 static int ofdpa_port_ev_mac_vlan_seen(struct rocker_port *rocker_port,
@@ -2899,7 +2732,7 @@ static int ofdpa_port_ev_mac_vlan_seen(struct rocker_port *rocker_port,
            ofdpa_port->stp_state != BR_STATE_FORWARDING)
                return 0;
 
-       return ofdpa_port_fdb(ofdpa_port, NULL, addr, vlan_id, flags);
+       return ofdpa_port_fdb(ofdpa_port, addr, vlan_id, flags);
 }
 
 static struct ofdpa_port *ofdpa_port_dev_lower_find(struct net_device *dev,
@@ -2923,7 +2756,7 @@ static int ofdpa_fib4_add(struct rocker *rocker,
        ofdpa_port = ofdpa_port_dev_lower_find(fen_info->fi->fib_dev, rocker);
        if (!ofdpa_port)
                return 0;
-       err = ofdpa_port_fib_ipv4(ofdpa_port, NULL, htonl(fen_info->dst),
+       err = ofdpa_port_fib_ipv4(ofdpa_port, htonl(fen_info->dst),
                                  fen_info->dst_len, fen_info->fi,
                                  fen_info->tb_id, 0);
        if (err)
@@ -2944,7 +2777,7 @@ static int ofdpa_fib4_del(struct rocker *rocker,
        if (!ofdpa_port)
                return 0;
        fib_info_offload_dec(fen_info->fi);
-       return ofdpa_port_fib_ipv4(ofdpa_port, NULL, htonl(fen_info->dst),
+       return ofdpa_port_fib_ipv4(ofdpa_port, htonl(fen_info->dst),
                                   fen_info->dst_len, fen_info->fi,
                                   fen_info->tb_id, OFDPA_OP_FLAG_REMOVE);
 }
@@ -2971,7 +2804,7 @@ static void ofdpa_fib4_abort(struct rocker *rocker)
                if (!ofdpa_port)
                        continue;
                fib_info_offload_dec(flow_entry->fi);
-               ofdpa_flow_tbl_del(ofdpa_port, NULL, OFDPA_OP_FLAG_REMOVE,
+               ofdpa_flow_tbl_del(ofdpa_port, OFDPA_OP_FLAG_REMOVE,
                                   flow_entry);
        }
        spin_unlock_irqrestore(&ofdpa->flow_tbl_lock, flags);
@@ -2993,13 +2826,12 @@ struct rocker_world_ops rocker_ofdpa_ops = {
        .port_attr_stp_state_set = ofdpa_port_attr_stp_state_set,
        .port_attr_bridge_flags_set = ofdpa_port_attr_bridge_flags_set,
        .port_attr_bridge_flags_get = ofdpa_port_attr_bridge_flags_get,
+       .port_attr_bridge_flags_support_get = ofdpa_port_attr_bridge_flags_support_get,
        .port_attr_bridge_ageing_time_set = ofdpa_port_attr_bridge_ageing_time_set,
        .port_obj_vlan_add = ofdpa_port_obj_vlan_add,
        .port_obj_vlan_del = ofdpa_port_obj_vlan_del,
-       .port_obj_vlan_dump = ofdpa_port_obj_vlan_dump,
        .port_obj_fdb_add = ofdpa_port_obj_fdb_add,
        .port_obj_fdb_del = ofdpa_port_obj_fdb_del,
-       .port_obj_fdb_dump = ofdpa_port_obj_fdb_dump,
        .port_master_linked = ofdpa_port_master_linked,
        .port_master_unlinked = ofdpa_port_master_unlinked,
        .port_neigh_update = ofdpa_port_neigh_update,
index a0c52e3281024b566dfe4b58e3014f26aadb0eaf..fcea9371ab7f636b885babfdc3ded58a6a941eec 100644 (file)
@@ -32,8 +32,8 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
                                struct net_device *net_dev);
 netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
 void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
-int efx_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
-                struct tc_to_netdev *tc);
+int efx_setup_tc(struct net_device *net_dev, u32 handle, u32 chain_index,
+                __be16 proto, struct tc_to_netdev *tc);
 unsigned int efx_tx_max_skb_descs(struct efx_nic *efx);
 extern unsigned int efx_piobuf_size;
 extern bool efx_separate_tx_channels;
index c89456fa148c797757411b34acca918aba2584b7..e5a7a40cc8b68ee092dddc2068760cb1d716383a 100644 (file)
@@ -32,8 +32,8 @@ netdev_tx_t ef4_hard_start_xmit(struct sk_buff *skb,
                                struct net_device *net_dev);
 netdev_tx_t ef4_enqueue_skb(struct ef4_tx_queue *tx_queue, struct sk_buff *skb);
 void ef4_xmit_done(struct ef4_tx_queue *tx_queue, unsigned int index);
-int ef4_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
-                struct tc_to_netdev *tc);
+int ef4_setup_tc(struct net_device *net_dev, u32 handle, u32 chain_index,
+                __be16 proto, struct tc_to_netdev *tc);
 unsigned int ef4_tx_max_skb_descs(struct ef4_nic *efx);
 extern bool ef4_separate_tx_channels;
 
index f6daf09b86272397d35bc72d59c5269b4644db1c..f1520a404ac619851d1f6ed5622828b6c7fbe44c 100644 (file)
@@ -425,8 +425,8 @@ void ef4_init_tx_queue_core_txq(struct ef4_tx_queue *tx_queue)
                                     efx->n_tx_channels : 0));
 }
 
-int ef4_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
-                struct tc_to_netdev *ntc)
+int ef4_setup_tc(struct net_device *net_dev, u32 handle, u32 chain_index,
+                __be16 proto, struct tc_to_netdev *ntc)
 {
        struct ef4_nic *efx = netdev_priv(net_dev);
        struct ef4_channel *channel;
index 3bdf87f310877a31fee219afa3de3dea91e40521..02d41eb4a8e9ae2cdabae7f1400d8506ce0abc85 100644 (file)
@@ -653,8 +653,8 @@ void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue)
                                     efx->n_tx_channels : 0));
 }
 
-int efx_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
-                struct tc_to_netdev *ntc)
+int efx_setup_tc(struct net_device *net_dev, u32 handle, u32 chain_index,
+                __be16 proto, struct tc_to_netdev *ntc)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
        struct efx_channel *channel;
index 16808e48ca1cf7bbd4237967ce0497caffc52808..743170d57f62258f68faf4706d04113faea2fc70 100644 (file)
@@ -273,7 +273,6 @@ static int stmmac_ethtool_get_link_ksettings(struct net_device *dev,
 {
        struct stmmac_priv *priv = netdev_priv(dev);
        struct phy_device *phy = dev->phydev;
-       int rc;
 
        if (priv->hw->pcs & STMMAC_PCS_RGMII ||
            priv->hw->pcs & STMMAC_PCS_SGMII) {
@@ -364,8 +363,8 @@ static int stmmac_ethtool_get_link_ksettings(struct net_device *dev,
                "link speed / duplex setting\n", dev->name);
                return -EBUSY;
        }
-       rc = phy_ethtool_ksettings_get(phy, cmd);
-       return rc;
+       phy_ethtool_ksettings_get(phy, cmd);
+       return 0;
 }
 
 static int
index 37fc16521143ed8391d81103e621e7e723ab7919..b7a0f5eeab620b30c5abcf8798f2bd3fdb2fb401 100644 (file)
@@ -1731,11 +1731,14 @@ static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
                cpts_rx_enable(cpts, 0);
                break;
        case HWTSTAMP_FILTER_ALL:
+       case HWTSTAMP_FILTER_NTP_ALL:
+               return -ERANGE;
        case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
        case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
        case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
-       case HWTSTAMP_FILTER_NTP_ALL:
-               return -ERANGE;
+               cpts_rx_enable(cpts, HWTSTAMP_FILTER_PTP_V1_L4_EVENT);
+               cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
+               break;
        case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
        case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
        case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
@@ -1745,7 +1748,7 @@ static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
        case HWTSTAMP_FILTER_PTP_V2_EVENT:
        case HWTSTAMP_FILTER_PTP_V2_SYNC:
        case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
-               cpts_rx_enable(cpts, 1);
+               cpts_rx_enable(cpts, HWTSTAMP_FILTER_PTP_V2_EVENT);
                cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
                break;
        default:
@@ -1784,7 +1787,7 @@ static int cpsw_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
        cfg.tx_type = cpts_is_tx_enabled(cpts) ?
                      HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
        cfg.rx_filter = (cpts_is_rx_enabled(cpts) ?
-                        HWTSTAMP_FILTER_PTP_V2_EVENT : HWTSTAMP_FILTER_NONE);
+                        cpts->rx_enable : HWTSTAMP_FILTER_NONE);
 
        return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
 }
@@ -2141,6 +2144,7 @@ static int cpsw_get_ts_info(struct net_device *ndev,
                (1 << HWTSTAMP_TX_ON);
        info->rx_filters =
                (1 << HWTSTAMP_FILTER_NONE) |
+               (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
                (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
        return 0;
 }
@@ -2166,11 +2170,11 @@ static int cpsw_get_link_ksettings(struct net_device *ndev,
        struct cpsw_common *cpsw = priv->cpsw;
        int slave_no = cpsw_slave_index(cpsw, priv);
 
-       if (cpsw->slaves[slave_no].phy)
-               return phy_ethtool_ksettings_get(cpsw->slaves[slave_no].phy,
-                                                ecmd);
-       else
+       if (!cpsw->slaves[slave_no].phy)
                return -EOPNOTSUPP;
+
+       phy_ethtool_ksettings_get(cpsw->slaves[slave_no].phy, ecmd);
+       return 0;
 }
 
 static int cpsw_set_link_ksettings(struct net_device *ndev,
index 7ecc6b70e7e898a5b0bd052cf60423d942905131..e4d6edf387b34571242b720306602528ddf94fe3 100644 (file)
@@ -645,7 +645,7 @@ EXPORT_SYMBOL_GPL(cpdma_ctlr_destroy);
 int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
 {
        unsigned long flags;
-       int i, reg;
+       int i;
 
        spin_lock_irqsave(&ctlr->lock, flags);
        if (ctlr->state != CPDMA_STATE_ACTIVE) {
@@ -653,9 +653,6 @@ int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
                return -EINVAL;
        }
 
-       reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR;
-       dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR);
-
        for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
                if (ctlr->channels[i])
                        cpdma_chan_int_ctrl(ctlr->channels[i], enable);
index e6222e535019a076ea0d4cd4c902f12332f079b2..9d52c3a78621b27b355c07bff905a6df3ad5c86b 100644 (file)
@@ -1877,8 +1877,8 @@ static u16 netcp_select_queue(struct net_device *dev, struct sk_buff *skb,
        return 0;
 }
 
-static int netcp_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-                         struct tc_to_netdev *tc)
+static int netcp_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+                         __be16 proto, struct tc_to_netdev *tc)
 {
        u8 num_tc;
        int i;
index dd92950a4615c3aab559c6dc383a4e90ee539160..0847a8f48cfe1d11d5001c1da2e0a33200a05116 100644 (file)
@@ -1927,7 +1927,6 @@ static int keystone_get_link_ksettings(struct net_device *ndev,
        struct netcp_intf *netcp = netdev_priv(ndev);
        struct phy_device *phy = ndev->phydev;
        struct gbe_intf *gbe_intf;
-       int ret;
 
        if (!phy)
                return -EINVAL;
@@ -1939,11 +1938,10 @@ static int keystone_get_link_ksettings(struct net_device *ndev,
        if (!gbe_intf->slave)
                return -EINVAL;
 
-       ret = phy_ethtool_ksettings_get(phy, cmd);
-       if (!ret)
-               cmd->base.port = gbe_intf->slave->phy_port_t;
+       phy_ethtool_ksettings_get(phy, cmd);
+       cmd->base.port = gbe_intf->slave->phy_port_t;
 
-       return ret;
+       return 0;
 }
 
 static int keystone_set_link_ksettings(struct net_device *ndev,
index 6ebb0f559a427fdb4d27d9b668b46d7151650043..ff626dbde23fface3e916555abeb76ed4f4ced3a 100644 (file)
@@ -212,6 +212,7 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
        struct genevehdr *gnvh = geneve_hdr(skb);
        struct metadata_dst *tun_dst = NULL;
        struct pcpu_sw_netstats *stats;
+       unsigned int len;
        int err = 0;
        void *oiph;
 
@@ -225,8 +226,10 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
                tun_dst = udp_tun_rx_dst(skb, geneve_get_sk_family(gs), flags,
                                         vni_to_tunnel_id(gnvh->vni),
                                         gnvh->opt_len * 4);
-               if (!tun_dst)
+               if (!tun_dst) {
+                       geneve->dev->stats.rx_dropped++;
                        goto drop;
+               }
                /* Update tunnel dst according to Geneve options. */
                ip_tunnel_info_opts_set(&tun_dst->u.tun_info,
                                        gnvh->options, gnvh->opt_len * 4);
@@ -234,8 +237,11 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
                /* Drop packets w/ critical options,
                 * since we don't support any...
                 */
-               if (gnvh->critical)
+               if (gnvh->critical) {
+                       geneve->dev->stats.rx_frame_errors++;
+                       geneve->dev->stats.rx_errors++;
                        goto drop;
+               }
        }
 
        skb_reset_mac_header(skb);
@@ -246,8 +252,10 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
                skb_dst_set(skb, &tun_dst->dst);
 
        /* Ignore packet loops (and multicast echo) */
-       if (ether_addr_equal(eth_hdr(skb)->h_source, geneve->dev->dev_addr))
+       if (ether_addr_equal(eth_hdr(skb)->h_source, geneve->dev->dev_addr)) {
+               geneve->dev->stats.rx_errors++;
                goto drop;
+       }
 
        oiph = skb_network_header(skb);
        skb_reset_network_header(skb);
@@ -279,13 +287,15 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
                }
        }
 
-       stats = this_cpu_ptr(geneve->dev->tstats);
-       u64_stats_update_begin(&stats->syncp);
-       stats->rx_packets++;
-       stats->rx_bytes += skb->len;
-       u64_stats_update_end(&stats->syncp);
-
-       gro_cells_receive(&geneve->gro_cells, skb);
+       len = skb->len;
+       err = gro_cells_receive(&geneve->gro_cells, skb);
+       if (likely(err == NET_RX_SUCCESS)) {
+               stats = this_cpu_ptr(geneve->dev->tstats);
+               u64_stats_update_begin(&stats->syncp);
+               stats->rx_packets++;
+               stats->rx_bytes += len;
+               u64_stats_update_end(&stats->syncp);
+       }
        return;
 drop:
        /* Consume bad packet */
@@ -334,7 +344,7 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
        struct geneve_sock *gs;
        int opts_len;
 
-       /* Need Geneve and inner Ethernet header to be present */
+       /* Need UDP and Geneve header to be present */
        if (unlikely(!pskb_may_pull(skb, GENEVE_BASE_HLEN)))
                goto drop;
 
@@ -357,8 +367,10 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
        opts_len = geneveh->opt_len * 4;
        if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len,
                                 htons(ETH_P_TEB),
-                                !net_eq(geneve->net, dev_net(geneve->dev))))
+                                !net_eq(geneve->net, dev_net(geneve->dev)))) {
+               geneve->dev->stats.rx_dropped++;
                goto drop;
+       }
 
        geneve_rx(geneve, gs, skb);
        return 0;
index 262b2ea576a38e4bb7d1c442f2dfcbc2c40fa302..f82d54e0208c32bd31ce9dfd0ddd0f99129c625d 100644 (file)
@@ -763,8 +763,7 @@ struct netvsc_device {
 
        refcount_t sc_offered;
 
-       /* Holds rndis device info */
-       void *extension;
+       struct rndis_device *extension;
 
        int ring_size;
 
index 652453d9fb088fd5103665e12884d87ff08465c3..7c5ed8fe7a4fad77f0f34e40274adf45bc2cb568 100644 (file)
@@ -97,16 +97,6 @@ static void free_netvsc_device_rcu(struct netvsc_device *nvdev)
        call_rcu(&nvdev->rcu, free_netvsc_device);
 }
 
-static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
-{
-       struct netvsc_device *net_device = hv_device_to_netvsc_device(device);
-
-       if (net_device && net_device->destroy)
-               net_device = NULL;
-
-       return net_device;
-}
-
 static void netvsc_destroy_buf(struct hv_device *device)
 {
        struct nvsp_message *revoke_packet;
@@ -243,18 +233,15 @@ static void netvsc_destroy_buf(struct hv_device *device)
        kfree(net_device->send_section_map);
 }
 
-static int netvsc_init_buf(struct hv_device *device)
+static int netvsc_init_buf(struct hv_device *device,
+                          struct netvsc_device *net_device)
 {
        int ret = 0;
-       struct netvsc_device *net_device;
        struct nvsp_message *init_packet;
        struct net_device *ndev;
        size_t map_words;
        int node;
 
-       net_device = get_outbound_net_device(device);
-       if (!net_device)
-               return -ENODEV;
        ndev = hv_get_drvdata(device);
 
        node = cpu_to_node(device->channel->target_cpu);
@@ -285,9 +272,7 @@ static int netvsc_init_buf(struct hv_device *device)
 
        /* Notify the NetVsp of the gpadl handle */
        init_packet = &net_device->channel_init_pkt;
-
        memset(init_packet, 0, sizeof(struct nvsp_message));
-
        init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_RECV_BUF;
        init_packet->msg.v1_msg.send_recv_buf.
                gpadl_handle = net_device->recv_buf_gpadl_handle;
@@ -486,20 +471,15 @@ static int negotiate_nvsp_ver(struct hv_device *device,
        return ret;
 }
 
-static int netvsc_connect_vsp(struct hv_device *device)
+static int netvsc_connect_vsp(struct hv_device *device,
+                             struct netvsc_device *net_device)
 {
-       int ret;
-       struct netvsc_device *net_device;
-       struct nvsp_message *init_packet;
-       int ndis_version;
        const u32 ver_list[] = {
                NVSP_PROTOCOL_VERSION_1, NVSP_PROTOCOL_VERSION_2,
-               NVSP_PROTOCOL_VERSION_4, NVSP_PROTOCOL_VERSION_5 };
-       int i;
-
-       net_device = get_outbound_net_device(device);
-       if (!net_device)
-               return -ENODEV;
+               NVSP_PROTOCOL_VERSION_4, NVSP_PROTOCOL_VERSION_5
+       };
+       struct nvsp_message *init_packet;
+       int ndis_version, i, ret;
 
        init_packet = &net_device->channel_init_pkt;
 
@@ -549,7 +529,7 @@ static int netvsc_connect_vsp(struct hv_device *device)
                net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
        net_device->send_buf_size = NETVSC_SEND_BUFFER_SIZE;
 
-       ret = netvsc_init_buf(device);
+       ret = netvsc_init_buf(device, net_device);
 
 cleanup:
        return ret;
@@ -843,7 +823,7 @@ int netvsc_send(struct hv_device *device,
                struct hv_page_buffer **pb,
                struct sk_buff *skb)
 {
-       struct netvsc_device *net_device;
+       struct netvsc_device *net_device = hv_device_to_netvsc_device(device);
        int ret = 0;
        struct netvsc_channel *nvchan;
        u32 pktlen = packet->total_data_buflen, msd_len = 0;
@@ -854,15 +834,15 @@ int netvsc_send(struct hv_device *device,
        bool try_batch;
        bool xmit_more = (skb != NULL) ? skb->xmit_more : false;
 
-       net_device = get_outbound_net_device(device);
-       if (!net_device)
+       /* If device is rescinded, return error and packet will get dropped. */
+       if (unlikely(net_device->destroy))
                return -ENODEV;
 
        /* We may race with netvsc_connect_vsp()/netvsc_init_buf() and get
         * here before the negotiation with the host is finished and
         * send_section_map may not be allocated yet.
         */
-       if (!net_device->send_section_map)
+       if (unlikely(!net_device->send_section_map))
                return -EAGAIN;
 
        nvchan = &net_device->chan_table[packet->q_idx];
@@ -1349,7 +1329,7 @@ int netvsc_device_add(struct hv_device *device,
        rcu_assign_pointer(net_device_ctx->nvdev, net_device);
 
        /* Connect with the NetVsp */
-       ret = netvsc_connect_vsp(device);
+       ret = netvsc_connect_vsp(device, net_device);
        if (ret != 0) {
                netdev_err(ndev,
                        "unable to connect to NetVSP - %d\n", ret);
@@ -1368,4 +1348,5 @@ int netvsc_device_add(struct hv_device *device,
        free_netvsc_device(&net_device->rcu);
 
        return ret;
+
 }
index 2564ac83eb64f70f6d7da6c8d666ea8cb3cbed2b..436a3ad55cfd04e6b245135d4c01ce543dd2e133 100644 (file)
@@ -120,7 +120,7 @@ static int netvsc_close(struct net_device *net)
        struct net_device_context *net_device_ctx = netdev_priv(net);
        struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
        int ret;
-       u32 aread, awrite, i, msec = 10, retry = 0, retry_max = 20;
+       u32 aread, i, msec = 10, retry = 0, retry_max = 20;
        struct vmbus_channel *chn;
 
        netif_tx_disable(net);
@@ -141,15 +141,11 @@ static int netvsc_close(struct net_device *net)
                        if (!chn)
                                continue;
 
-                       hv_get_ringbuffer_availbytes(&chn->inbound, &aread,
-                                                    &awrite);
-
+                       aread = hv_get_bytes_to_read(&chn->inbound);
                        if (aread)
                                break;
 
-                       hv_get_ringbuffer_availbytes(&chn->outbound, &aread,
-                                                    &awrite);
-
+                       aread = hv_get_bytes_to_read(&chn->outbound);
                        if (aread)
                                break;
                }
@@ -345,34 +341,14 @@ static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb,
        return slots_used;
 }
 
-static int count_skb_frag_slots(struct sk_buff *skb)
-{
-       int i, frags = skb_shinfo(skb)->nr_frags;
-       int pages = 0;
-
-       for (i = 0; i < frags; i++) {
-               skb_frag_t *frag = skb_shinfo(skb)->frags + i;
-               unsigned long size = skb_frag_size(frag);
-               unsigned long offset = frag->page_offset;
-
-               /* Skip unused frames from start of page */
-               offset &= ~PAGE_MASK;
-               pages += PFN_UP(offset + size);
-       }
-       return pages;
-}
-
-static int netvsc_get_slots(struct sk_buff *skb)
+/* Estimate number of page buffers neede to transmit
+ * Need at most 2 for RNDIS header plus skb body and fragments.
+ */
+static unsigned int netvsc_get_slots(const struct sk_buff *skb)
 {
-       char *data = skb->data;
-       unsigned int offset = offset_in_page(data);
-       unsigned int len = skb_headlen(skb);
-       int slots;
-       int frag_slots;
-
-       slots = DIV_ROUND_UP(offset + len, PAGE_SIZE);
-       frag_slots = count_skb_frag_slots(skb);
-       return slots + frag_slots;
+       return PFN_UP(offset_in_page(skb->data) + skb_headlen(skb))
+               + skb_shinfo(skb)->nr_frags
+               + 2;
 }
 
 static u32 net_checksum_info(struct sk_buff *skb)
@@ -410,21 +386,18 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
        struct hv_page_buffer page_buf[MAX_PAGE_BUFFER_COUNT];
        struct hv_page_buffer *pb = page_buf;
 
-       /* We will atmost need two pages to describe the rndis
-        * header. We can only transmit MAX_PAGE_BUFFER_COUNT number
+       /* We can only transmit MAX_PAGE_BUFFER_COUNT number
         * of pages in a single packet. If skb is scattered around
         * more pages we try linearizing it.
         */
-
-       num_data_pgs = netvsc_get_slots(skb) + 2;
-
+       num_data_pgs = netvsc_get_slots(skb);
        if (unlikely(num_data_pgs > MAX_PAGE_BUFFER_COUNT)) {
                ++net_device_ctx->eth_stats.tx_scattered;
 
                if (skb_linearize(skb))
                        goto no_memory;
 
-               num_data_pgs = netvsc_get_slots(skb) + 2;
+               num_data_pgs = netvsc_get_slots(skb);
                if (num_data_pgs > MAX_PAGE_BUFFER_COUNT) {
                        ++net_device_ctx->eth_stats.tx_too_big;
                        goto drop;
index 618ed88fad0fc1d4e227f0e84fde74462b2bc496..e4141d62b5c34b0104c7d205c4038230766b6f5e 100644 (file)
@@ -824,6 +824,33 @@ static int ipvlan_addr6_event(struct notifier_block *unused,
        return NOTIFY_OK;
 }
 
+static int ipvlan_addr6_validator_event(struct notifier_block *unused,
+                                       unsigned long event, void *ptr)
+{
+       struct in6_validator_info *i6vi = (struct in6_validator_info *)ptr;
+       struct net_device *dev = (struct net_device *)i6vi->i6vi_dev->dev;
+       struct ipvl_dev *ipvlan = netdev_priv(dev);
+
+       /* FIXME IPv6 autoconf calls us from bh without RTNL */
+       if (in_softirq())
+               return NOTIFY_DONE;
+
+       if (!netif_is_ipvlan(dev))
+               return NOTIFY_DONE;
+
+       if (!ipvlan || !ipvlan->port)
+               return NOTIFY_DONE;
+
+       switch (event) {
+       case NETDEV_UP:
+               if (ipvlan_addr_busy(ipvlan->port, &i6vi->i6vi_addr, true))
+                       return notifier_from_errno(-EADDRINUSE);
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
 static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr)
 {
        if (ipvlan_addr_busy(ipvlan->port, ip4_addr, false)) {
@@ -871,10 +898,37 @@ static int ipvlan_addr4_event(struct notifier_block *unused,
        return NOTIFY_OK;
 }
 
+static int ipvlan_addr4_validator_event(struct notifier_block *unused,
+                                       unsigned long event, void *ptr)
+{
+       struct in_validator_info *ivi = (struct in_validator_info *)ptr;
+       struct net_device *dev = (struct net_device *)ivi->ivi_dev->dev;
+       struct ipvl_dev *ipvlan = netdev_priv(dev);
+
+       if (!netif_is_ipvlan(dev))
+               return NOTIFY_DONE;
+
+       if (!ipvlan || !ipvlan->port)
+               return NOTIFY_DONE;
+
+       switch (event) {
+       case NETDEV_UP:
+               if (ipvlan_addr_busy(ipvlan->port, &ivi->ivi_addr, false))
+                       return notifier_from_errno(-EADDRINUSE);
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
 static struct notifier_block ipvlan_addr4_notifier_block __read_mostly = {
        .notifier_call = ipvlan_addr4_event,
 };
 
+static struct notifier_block ipvlan_addr4_vtor_notifier_block __read_mostly = {
+       .notifier_call = ipvlan_addr4_validator_event,
+};
+
 static struct notifier_block ipvlan_notifier_block __read_mostly = {
        .notifier_call = ipvlan_device_event,
 };
@@ -883,6 +937,10 @@ static struct notifier_block ipvlan_addr6_notifier_block __read_mostly = {
        .notifier_call = ipvlan_addr6_event,
 };
 
+static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = {
+       .notifier_call = ipvlan_addr6_validator_event,
+};
+
 static void ipvlan_ns_exit(struct net *net)
 {
        struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
@@ -907,7 +965,10 @@ static int __init ipvlan_init_module(void)
        ipvlan_init_secret();
        register_netdevice_notifier(&ipvlan_notifier_block);
        register_inet6addr_notifier(&ipvlan_addr6_notifier_block);
+       register_inet6addr_validator_notifier(
+           &ipvlan_addr6_vtor_notifier_block);
        register_inetaddr_notifier(&ipvlan_addr4_notifier_block);
+       register_inetaddr_validator_notifier(&ipvlan_addr4_vtor_notifier_block);
 
        err = register_pernet_subsys(&ipvlan_net_ops);
        if (err < 0)
@@ -922,7 +983,11 @@ static int __init ipvlan_init_module(void)
        return 0;
 error:
        unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
+       unregister_inetaddr_validator_notifier(
+           &ipvlan_addr4_vtor_notifier_block);
        unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block);
+       unregister_inet6addr_validator_notifier(
+           &ipvlan_addr6_vtor_notifier_block);
        unregister_netdevice_notifier(&ipvlan_notifier_block);
        return err;
 }
@@ -933,7 +998,11 @@ static void __exit ipvlan_cleanup_module(void)
        unregister_pernet_subsys(&ipvlan_net_ops);
        unregister_netdevice_notifier(&ipvlan_notifier_block);
        unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
+       unregister_inetaddr_validator_notifier(
+           &ipvlan_addr4_vtor_notifier_block);
        unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block);
+       unregister_inet6addr_validator_notifier(
+           &ipvlan_addr6_vtor_notifier_block);
 }
 
 module_init(ipvlan_init_module);
index 4c5246fed69be1093814e512ba52487456f986c0..8400403b3f622ec148e36193ce191d63b8dfae30 100644 (file)
@@ -1139,7 +1139,6 @@ static int marvell_read_status_page_an(struct phy_device *phydev,
        int status;
        int lpa;
        int lpagb;
-       int adv;
 
        status = phy_read(phydev, MII_M1011_PHY_STATUS);
        if (status < 0)
@@ -1153,12 +1152,6 @@ static int marvell_read_status_page_an(struct phy_device *phydev,
        if (lpagb < 0)
                return lpagb;
 
-       adv = phy_read(phydev, MII_ADVERTISE);
-       if (adv < 0)
-               return adv;
-
-       lpa &= adv;
-
        if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
                phydev->duplex = DUPLEX_FULL;
        else
index 4c169dbf9138b39c6b3d5e9eb30b9fb03c79c016..2df7b62c1a36811e97087ae641a89d06641cef4e 100644 (file)
@@ -353,33 +353,18 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
 
        mutex_init(&bus->mdio_lock);
 
-       /* de-assert bus level PHY GPIO resets */
-       if (bus->num_reset_gpios > 0) {
-               bus->reset_gpiod = devm_kcalloc(&bus->dev,
-                                                bus->num_reset_gpios,
-                                                sizeof(struct gpio_desc *),
-                                                GFP_KERNEL);
-               if (!bus->reset_gpiod)
-                       return -ENOMEM;
-       }
-
-       for (i = 0; i < bus->num_reset_gpios; i++) {
-               gpiod = devm_gpiod_get_index(&bus->dev, "reset", i,
-                                            GPIOD_OUT_LOW);
-               if (IS_ERR(gpiod)) {
-                       err = PTR_ERR(gpiod);
-                       if (err != -ENOENT) {
-                               dev_err(&bus->dev,
-                                       "mii_bus %s couldn't get reset GPIO\n",
-                                       bus->id);
-                               return err;
-                       }
-               } else {
-                       bus->reset_gpiod[i] = gpiod;
-                       gpiod_set_value_cansleep(gpiod, 1);
-                       udelay(bus->reset_delay_us);
-                       gpiod_set_value_cansleep(gpiod, 0);
-               }
+       /* de-assert bus level PHY GPIO reset */
+       gpiod = devm_gpiod_get_optional(&bus->dev, "reset", GPIOD_OUT_LOW);
+       if (IS_ERR(gpiod)) {
+               dev_err(&bus->dev, "mii_bus %s couldn't get reset GPIO\n",
+                       bus->id);
+               return PTR_ERR(gpiod);
+       } else  if (gpiod) {
+               bus->reset_gpiod = gpiod;
+
+               gpiod_set_value_cansleep(gpiod, 1);
+               udelay(bus->reset_delay_us);
+               gpiod_set_value_cansleep(gpiod, 0);
        }
 
        if (bus->reset)
@@ -414,10 +399,8 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
        }
 
        /* Put PHYs in RESET to save power */
-       for (i = 0; i < bus->num_reset_gpios; i++) {
-               if (bus->reset_gpiod[i])
-                       gpiod_set_value_cansleep(bus->reset_gpiod[i], 1);
-       }
+       if (bus->reset_gpiod)
+               gpiod_set_value_cansleep(bus->reset_gpiod, 1);
 
        device_del(&bus->dev);
        return err;
@@ -442,10 +425,8 @@ void mdiobus_unregister(struct mii_bus *bus)
        }
 
        /* Put PHYs in RESET to save power */
-       for (i = 0; i < bus->num_reset_gpios; i++) {
-               if (bus->reset_gpiod[i])
-                       gpiod_set_value_cansleep(bus->reset_gpiod[i], 1);
-       }
+       if (bus->reset_gpiod)
+               gpiod_set_value_cansleep(bus->reset_gpiod, 1);
 
        device_del(&bus->dev);
 }
index 14fc5bc75cd1136dd0330f0dc546912db668bcbc..edcdf0d872ed18fe309f4e393491a210b7fba74d 100644 (file)
@@ -509,8 +509,8 @@ int phy_ethtool_ksettings_set(struct phy_device *phydev,
 }
 EXPORT_SYMBOL(phy_ethtool_ksettings_set);
 
-int phy_ethtool_ksettings_get(struct phy_device *phydev,
-                             struct ethtool_link_ksettings *cmd)
+void phy_ethtool_ksettings_get(struct phy_device *phydev,
+                              struct ethtool_link_ksettings *cmd)
 {
        ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
                                                phydev->supported);
@@ -532,8 +532,6 @@ int phy_ethtool_ksettings_get(struct phy_device *phydev,
        cmd->base.autoneg = phydev->autoneg;
        cmd->base.eth_tp_mdix_ctrl = phydev->mdix_ctrl;
        cmd->base.eth_tp_mdix = phydev->mdix;
-
-       return 0;
 }
 EXPORT_SYMBOL(phy_ethtool_ksettings_get);
 
@@ -1449,7 +1447,9 @@ int phy_ethtool_get_link_ksettings(struct net_device *ndev,
        if (!phydev)
                return -ENODEV;
 
-       return phy_ethtool_ksettings_get(phydev, cmd);
+       phy_ethtool_ksettings_get(phydev, cmd);
+
+       return 0;
 }
 EXPORT_SYMBOL(phy_ethtool_get_link_ksettings);
 
index 92578d72e4ee51ce26d3e23d4b86099a0097801d..63a8ff816e5917983d7c095696492175d7160a77 100644 (file)
@@ -886,7 +886,7 @@ static int marvell_read_link(struct mii_phy *phy)
         SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
 
 /* Broadcom BCM 5201 */
-static struct mii_phy_ops bcm5201_phy_ops = {
+static const struct mii_phy_ops bcm5201_phy_ops = {
        .init           = bcm5201_init,
        .suspend        = bcm5201_suspend,
        .setup_aneg     = genmii_setup_aneg,
@@ -905,7 +905,7 @@ static struct mii_phy_def bcm5201_phy_def = {
 };
 
 /* Broadcom BCM 5221 */
-static struct mii_phy_ops bcm5221_phy_ops = {
+static const struct mii_phy_ops bcm5221_phy_ops = {
        .suspend        = bcm5221_suspend,
        .init           = bcm5221_init,
        .setup_aneg     = genmii_setup_aneg,
@@ -924,7 +924,7 @@ static struct mii_phy_def bcm5221_phy_def = {
 };
 
 /* Broadcom BCM 5241 */
-static struct mii_phy_ops bcm5241_phy_ops = {
+static const struct mii_phy_ops bcm5241_phy_ops = {
        .suspend        = bcm5241_suspend,
        .init           = bcm5241_init,
        .setup_aneg     = genmii_setup_aneg,
@@ -942,7 +942,7 @@ static struct mii_phy_def bcm5241_phy_def = {
 };
 
 /* Broadcom BCM 5400 */
-static struct mii_phy_ops bcm5400_phy_ops = {
+static const struct mii_phy_ops bcm5400_phy_ops = {
        .init           = bcm5400_init,
        .suspend        = bcm5400_suspend,
        .setup_aneg     = bcm54xx_setup_aneg,
@@ -961,7 +961,7 @@ static struct mii_phy_def bcm5400_phy_def = {
 };
 
 /* Broadcom BCM 5401 */
-static struct mii_phy_ops bcm5401_phy_ops = {
+static const struct mii_phy_ops bcm5401_phy_ops = {
        .init           = bcm5401_init,
        .suspend        = bcm5401_suspend,
        .setup_aneg     = bcm54xx_setup_aneg,
@@ -980,7 +980,7 @@ static struct mii_phy_def bcm5401_phy_def = {
 };
 
 /* Broadcom BCM 5411 */
-static struct mii_phy_ops bcm5411_phy_ops = {
+static const struct mii_phy_ops bcm5411_phy_ops = {
        .init           = bcm5411_init,
        .suspend        = generic_suspend,
        .setup_aneg     = bcm54xx_setup_aneg,
@@ -999,7 +999,7 @@ static struct mii_phy_def bcm5411_phy_def = {
 };
 
 /* Broadcom BCM 5421 */
-static struct mii_phy_ops bcm5421_phy_ops = {
+static const struct mii_phy_ops bcm5421_phy_ops = {
        .init           = bcm5421_init,
        .suspend        = generic_suspend,
        .setup_aneg     = bcm54xx_setup_aneg,
@@ -1019,7 +1019,7 @@ static struct mii_phy_def bcm5421_phy_def = {
 };
 
 /* Broadcom BCM 5421 built-in K2 */
-static struct mii_phy_ops bcm5421k2_phy_ops = {
+static const struct mii_phy_ops bcm5421k2_phy_ops = {
        .init           = bcm5421_init,
        .suspend        = generic_suspend,
        .setup_aneg     = bcm54xx_setup_aneg,
@@ -1037,7 +1037,7 @@ static struct mii_phy_def bcm5421k2_phy_def = {
        .ops            = &bcm5421k2_phy_ops
 };
 
-static struct mii_phy_ops bcm5461_phy_ops = {
+static const struct mii_phy_ops bcm5461_phy_ops = {
        .init           = bcm5421_init,
        .suspend        = generic_suspend,
        .setup_aneg     = bcm54xx_setup_aneg,
@@ -1057,7 +1057,7 @@ static struct mii_phy_def bcm5461_phy_def = {
 };
 
 /* Broadcom BCM 5462 built-in Vesta */
-static struct mii_phy_ops bcm5462V_phy_ops = {
+static const struct mii_phy_ops bcm5462V_phy_ops = {
        .init           = bcm5421_init,
        .suspend        = generic_suspend,
        .setup_aneg     = bcm54xx_setup_aneg,
@@ -1076,7 +1076,7 @@ static struct mii_phy_def bcm5462V_phy_def = {
 };
 
 /* Marvell 88E1101 amd 88E1111 */
-static struct mii_phy_ops marvell88e1101_phy_ops = {
+static const struct mii_phy_ops marvell88e1101_phy_ops = {
        .suspend        = generic_suspend,
        .setup_aneg     = marvell_setup_aneg,
        .setup_forced   = marvell_setup_forced,
@@ -1084,7 +1084,7 @@ static struct mii_phy_ops marvell88e1101_phy_ops = {
        .read_link      = marvell_read_link
 };
 
-static struct mii_phy_ops marvell88e1111_phy_ops = {
+static const struct mii_phy_ops marvell88e1111_phy_ops = {
        .init           = marvell88e1111_init,
        .suspend        = generic_suspend,
        .setup_aneg     = marvell_setup_aneg,
@@ -1122,7 +1122,7 @@ static struct mii_phy_def marvell88e1111_phy_def = {
 };
 
 /* Generic implementation for most 10/100 PHYs */
-static struct mii_phy_ops generic_phy_ops = {
+static const struct mii_phy_ops generic_phy_ops = {
        .setup_aneg     = genmii_setup_aneg,
        .setup_forced   = genmii_setup_forced,
        .poll_link      = genmii_poll_link,
index 6c5d5ef46f75aa9a9089ac80bbee30a7f579b016..a3ec1892a2862d9df9ab7d906f6c47931944fecc 100644 (file)
@@ -2005,12 +2005,6 @@ static const struct net_device_ops team_netdev_ops = {
        .ndo_del_slave          = team_del_slave,
        .ndo_fix_features       = team_fix_features,
        .ndo_change_carrier     = team_change_carrier,
-       .ndo_bridge_setlink     = switchdev_port_bridge_setlink,
-       .ndo_bridge_getlink     = switchdev_port_bridge_getlink,
-       .ndo_bridge_dellink     = switchdev_port_bridge_dellink,
-       .ndo_fdb_add            = switchdev_port_fdb_add,
-       .ndo_fdb_del            = switchdev_port_fdb_del,
-       .ndo_fdb_dump           = switchdev_port_fdb_dump,
        .ndo_features_check     = passthru_features_check,
 };
 
index 9eff97a650ae5e3056f20e8c0f1bb717df4773ab..5833f7e2a127811aa2298ded2bc62b1d06ae1e9d 100644 (file)
@@ -1490,7 +1490,7 @@ static int lan78xx_get_link_ksettings(struct net_device *net,
        if (ret < 0)
                return ret;
 
-       ret = phy_ethtool_ksettings_get(phydev, cmd);
+       phy_ethtool_ksettings_get(phydev, cmd);
 
        usb_autopm_put_interface(dev->intf);
 
index fd31fab2a9daebb842784220a3a1950221e1e759..5a02053181d10d726869d013b35109c823a2b5e5 100644 (file)
 
 /* OCP_PHY_STATUS */
 #define PHY_STAT_MASK          0x0007
+#define PHY_STAT_EXT_INIT      2
 #define PHY_STAT_LAN_ON                3
 #define PHY_STAT_PWRDN         5
 
@@ -1812,6 +1813,10 @@ static int rx_bottom(struct r8152 *tp, int budget)
                        unsigned int pkt_len;
                        struct sk_buff *skb;
 
+                       /* limite the skb numbers for rx_queue */
+                       if (unlikely(skb_queue_len(&tp->rx_queue) >= 1000))
+                               break;
+
                        pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
                        if (pkt_len < ETH_ZLEN)
                                break;
@@ -1933,7 +1938,8 @@ static int r8152_poll(struct napi_struct *napi, int budget)
        bottom_half(tp);
 
        if (work_done < budget) {
-               napi_complete(napi);
+               if (!napi_complete_done(napi, work_done))
+                       goto out;
                if (!list_empty(&tp->rx_done))
                        napi_schedule(napi);
                else if (!skb_queue_empty(&tp->tx_queue) &&
@@ -1941,6 +1947,7 @@ static int r8152_poll(struct napi_struct *napi, int budget)
                        napi_schedule(napi);
        }
 
+out:
        return work_done;
 }
 
@@ -2262,7 +2269,6 @@ static int rtl8153_enable(struct r8152 *tp)
        if (test_bit(RTL8152_UNPLUG, &tp->flags))
                return -ENODEV;
 
-       usb_disable_lpm(tp->udev);
        set_tx_qlen(tp);
        rtl_set_eee_plus(tp);
        r8153_set_rx_early_timeout(tp);
@@ -2428,6 +2434,29 @@ static void __rtl_set_wol(struct r8152 *tp, u32 wolopts)
                device_set_wakeup_enable(&tp->udev->dev, false);
 }
 
+static void r8153_mac_clk_spd(struct r8152 *tp, bool enable)
+{
+       /* MAC clock speed down */
+       if (enable) {
+               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL,
+                              ALDPS_SPDWN_RATIO);
+               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2,
+                              EEE_SPDWN_RATIO);
+               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,
+                              PKT_AVAIL_SPDWN_EN | SUSPEND_SPDWN_EN |
+                              U1U2_SPDWN_EN | L1_SPDWN_EN);
+               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
+                              PWRSAVE_SPDWN_EN | RXDV_SPDWN_EN | TX10MIDLE_EN |
+                              TP100_SPDWN_EN | TP500_SPDWN_EN | EEE_SPDWN_EN |
+                              TP1000_SPDWN_EN);
+       } else {
+               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0);
+               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0);
+               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0);
+               ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0);
+       }
+}
+
 static void r8153_u1u2en(struct r8152 *tp, bool enable)
 {
        u8 u1u2[8];
@@ -2445,13 +2474,35 @@ static void r8153_u2p3en(struct r8152 *tp, bool enable)
        u32 ocp_data;
 
        ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL);
-       if (enable && tp->version != RTL_VER_03 && tp->version != RTL_VER_04)
+       if (enable)
                ocp_data |= U2P3_ENABLE;
        else
                ocp_data &= ~U2P3_ENABLE;
        ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data);
 }
 
+static u16 r8153_phy_status(struct r8152 *tp, u16 desired)
+{
+       u16 data;
+       int i;
+
+       for (i = 0; i < 500; i++) {
+               data = ocp_reg_read(tp, OCP_PHY_STATUS);
+               data &= PHY_STAT_MASK;
+               if (desired) {
+                       if (data == desired)
+                               break;
+               } else if (data == PHY_STAT_LAN_ON || data == PHY_STAT_PWRDN ||
+                          data == PHY_STAT_EXT_INIT) {
+                       break;
+               }
+
+               msleep(20);
+       }
+
+       return data;
+}
+
 static void r8153_power_cut_en(struct r8152 *tp, bool enable)
 {
        u32 ocp_data;
@@ -2506,13 +2557,26 @@ static void rtl_runtime_suspend_enable(struct r8152 *tp, bool enable)
 
 static void rtl8153_runtime_enable(struct r8152 *tp, bool enable)
 {
-       rtl_runtime_suspend_enable(tp, enable);
-
        if (enable) {
                r8153_u1u2en(tp, false);
                r8153_u2p3en(tp, false);
+               r8153_mac_clk_spd(tp, true);
+               rtl_runtime_suspend_enable(tp, true);
        } else {
-               r8153_u2p3en(tp, true);
+               rtl_runtime_suspend_enable(tp, false);
+               r8153_mac_clk_spd(tp, false);
+
+               switch (tp->version) {
+               case RTL_VER_03:
+               case RTL_VER_04:
+                       break;
+               case RTL_VER_05:
+               case RTL_VER_06:
+               default:
+                       r8153_u2p3en(tp, true);
+                       break;
+               }
+
                r8153_u1u2en(tp, true);
        }
 }
@@ -2778,9 +2842,15 @@ static void r8153_aldps_en(struct r8152 *tp, bool enable)
                data |= EN_ALDPS;
                ocp_reg_write(tp, OCP_POWER_CFG, data);
        } else {
+               int i;
+
                data &= ~EN_ALDPS;
                ocp_reg_write(tp, OCP_POWER_CFG, data);
-               msleep(20);
+               for (i = 0; i < 20; i++) {
+                       usleep_range(1000, 2000);
+                       if (ocp_read_word(tp, MCU_TYPE_PLA, 0xe000) & 0x0100)
+                               break;
+               }
        }
 }
 
@@ -2851,6 +2921,17 @@ static void r8153_hw_phy_cfg(struct r8152 *tp)
        r8153_aldps_en(tp, true);
        r8152b_enable_fc(tp);
 
+       switch (tp->version) {
+       case RTL_VER_03:
+       case RTL_VER_04:
+               break;
+       case RTL_VER_05:
+       case RTL_VER_06:
+       default:
+               r8153_u2p3en(tp, true);
+               break;
+       }
+
        set_bit(PHY_RESET, &tp->flags);
 }
 
@@ -2859,6 +2940,7 @@ static void r8153_first_init(struct r8152 *tp)
        u32 ocp_data;
        int i;
 
+       r8153_mac_clk_spd(tp, false);
        rxdy_gated_en(tp, true);
        r8153_teredo_off(tp);
 
@@ -2913,11 +2995,6 @@ static void r8153_first_init(struct r8152 *tp)
        ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_NORMAL);
        /* TX share fifo free credit full threshold */
        ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL2);
-
-       /* rx aggregation */
-       ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
-       ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
-       ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
 }
 
 static void r8153_enter_oob(struct r8152 *tp)
@@ -2925,6 +3002,8 @@ static void r8153_enter_oob(struct r8152 *tp)
        u32 ocp_data;
        int i;
 
+       r8153_mac_clk_spd(tp, true);
+
        ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
        ocp_data &= ~NOW_IS_OOB;
        ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
@@ -2980,7 +3059,6 @@ static void rtl8153_disable(struct r8152 *tp)
        rtl_disable(tp);
        rtl_reset_bmu(tp);
        r8153_aldps_en(tp, true);
-       usb_enable_lpm(tp->udev);
 }
 
 static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
@@ -3099,12 +3177,23 @@ static void rtl8153_up(struct r8152 *tp)
                return;
 
        r8153_u1u2en(tp, false);
+       r8153_u2p3en(tp, false);
        r8153_aldps_en(tp, false);
        r8153_first_init(tp);
        r8153_aldps_en(tp, true);
-       r8153_u2p3en(tp, true);
+
+       switch (tp->version) {
+       case RTL_VER_03:
+       case RTL_VER_04:
+               break;
+       case RTL_VER_05:
+       case RTL_VER_06:
+       default:
+               r8153_u2p3en(tp, true);
+               break;
+       }
+
        r8153_u1u2en(tp, true);
-       usb_enable_lpm(tp->udev);
 }
 
 static void rtl8153_down(struct r8152 *tp)
@@ -3420,12 +3509,7 @@ static void r8153_init(struct r8152 *tp)
                msleep(20);
        }
 
-       for (i = 0; i < 500; i++) {
-               ocp_data = ocp_reg_read(tp, OCP_PHY_STATUS) & PHY_STAT_MASK;
-               if (ocp_data == PHY_STAT_LAN_ON || ocp_data == PHY_STAT_PWRDN)
-                       break;
-               msleep(20);
-       }
+       data = r8153_phy_status(tp, 0);
 
        if (tp->version == RTL_VER_03 || tp->version == RTL_VER_04 ||
            tp->version == RTL_VER_05)
@@ -3437,14 +3521,8 @@ static void r8153_init(struct r8152 *tp)
                r8152_mdio_write(tp, MII_BMCR, data);
        }
 
-       for (i = 0; i < 500; i++) {
-               ocp_data = ocp_reg_read(tp, OCP_PHY_STATUS) & PHY_STAT_MASK;
-               if (ocp_data == PHY_STAT_LAN_ON)
-                       break;
-               msleep(20);
-       }
+       data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
 
-       usb_disable_lpm(tp->udev);
        r8153_u2p3en(tp, false);
 
        if (tp->version == RTL_VER_04) {
@@ -3504,15 +3582,28 @@ static void r8153_init(struct r8152 *tp)
 
        r8153_power_cut_en(tp, false);
        r8153_u1u2en(tp, true);
+       r8153_mac_clk_spd(tp, false);
+       usb_enable_lpm(tp->udev);
 
-       /* MAC clock speed down */
-       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0);
-       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0);
-       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0);
-       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0);
+       /* rx aggregation */
+       ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
+       ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
+       ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
 
        rtl_tally_reset(tp);
-       r8153_u2p3en(tp, true);
+
+       switch (tp->udev->speed) {
+       case USB_SPEED_SUPER:
+       case USB_SPEED_SUPER_PLUS:
+               tp->coalesce = COALESCE_SUPER;
+               break;
+       case USB_SPEED_HIGH:
+               tp->coalesce = COALESCE_HIGH;
+               break;
+       default:
+               tp->coalesce = COALESCE_SLOW;
+               break;
+       }
 }
 
 static int rtl8152_pre_reset(struct usb_interface *intf)
@@ -3697,11 +3788,8 @@ static int rtl8152_resume(struct usb_interface *intf)
 
        mutex_lock(&tp->control);
 
-       if (!test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
-               tp->rtl_ops.init(tp);
-               queue_delayed_work(system_long_wq, &tp->hw_phy_work, 0);
+       if (!test_bit(SELECTIVE_SUSPEND, &tp->flags))
                netif_device_attach(netdev);
-       }
 
        if (netif_running(netdev) && netdev->flags & IFF_UP) {
                if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
@@ -3747,6 +3835,10 @@ static int rtl8152_reset_resume(struct usb_interface *intf)
        struct r8152 *tp = usb_get_intfdata(intf);
 
        clear_bit(SELECTIVE_SUSPEND, &tp->flags);
+       mutex_lock(&tp->control);
+       tp->rtl_ops.init(tp);
+       queue_delayed_work(system_long_wq, &tp->hw_phy_work, 0);
+       mutex_unlock(&tp->control);
        return rtl8152_resume(intf);
 }
 
@@ -4458,19 +4550,6 @@ static int rtl8152_probe(struct usb_interface *intf,
        tp->mii.reg_num_mask = 0x1f;
        tp->mii.phy_id = R8152_PHY_ID;
 
-       switch (udev->speed) {
-       case USB_SPEED_SUPER:
-       case USB_SPEED_SUPER_PLUS:
-               tp->coalesce = COALESCE_SUPER;
-               break;
-       case USB_SPEED_HIGH:
-               tp->coalesce = COALESCE_HIGH;
-               break;
-       default:
-               tp->coalesce = COALESCE_SLOW;
-               break;
-       }
-
        tp->autoneg = AUTONEG_ENABLE;
        tp->speed = tp->mii.supports_gmii ? SPEED_1000 : SPEED_100;
        tp->duplex = DUPLEX_FULL;
index 7cb21a088bbc4c317be5b00d130bbe12189ce3e1..e045c34ffbeb6a018efe2a9dd9951c2e52cc79fd 100644 (file)
@@ -970,7 +970,7 @@ static bool vxlan_snoop(struct net_device *dev,
                        return false;
 
                /* Don't migrate static entries, drop packets */
-               if (f->state & NUD_NOARP)
+               if (f->state & (NUD_PERMANENT | NUD_NOARP))
                        return true;
 
                if (net_ratelimit())
index 8f5a3f4a43f2d0d215ea116f89417cf21b5c9d51..166920ae23f8d0716c61cc4773bac691293622f9 100644 (file)
@@ -45,6 +45,7 @@ source "drivers/net/wireless/rsi/Kconfig"
 source "drivers/net/wireless/st/Kconfig"
 source "drivers/net/wireless/ti/Kconfig"
 source "drivers/net/wireless/zydas/Kconfig"
+source "drivers/net/wireless/quantenna/Kconfig"
 
 config PCMCIA_RAYCS
        tristate "Aviator/Raytheon 2.4GHz wireless support"
index f00d42953fb8e6adca934544a6fe79188b3b678a..54b41ac5f9c88288460c10e929c1c72250a0c15e 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_WLAN_VENDOR_RSI) += rsi/
 obj-$(CONFIG_WLAN_VENDOR_ST) += st/
 obj-$(CONFIG_WLAN_VENDOR_TI) += ti/
 obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/
+obj-$(CONFIG_WLAN_VENDOR_QUANTENNA) += quantenna/
 
 # 16-bit wireless PCMCIA client drivers
 obj-$(CONFIG_PCMCIA_RAYCS)     += ray_cs.o
index b4241cf9b7ed41cad7094af9c1b56c772e66b63e..412eb1380dcc24bec00a2049c8265d4e33913b09 100644 (file)
@@ -22,6 +22,13 @@ config ATH10K_AHB
        ---help---
          This module adds support for AHB bus
 
+config ATH10K_SDIO
+       tristate "Atheros ath10k SDIO support (EXPERIMENTAL)"
+       depends on ATH10K && MMC
+       ---help---
+         This module adds experimental support for SDIO/MMC bus. Currently
+         work in progress and will not fully work.
+
 config ATH10K_DEBUG
        bool "Atheros ath10k debugging"
        depends on ATH10K
index 930fadd940d86ad05e5dc473b30aee410789114b..b0b19a7eb98b7709759685d26b0c2bd1f4e56569 100644 (file)
@@ -27,5 +27,8 @@ ath10k_pci-y += pci.o \
 
 ath10k_pci-$(CONFIG_ATH10K_AHB) += ahb.o
 
+obj-$(CONFIG_ATH10K_SDIO) += ath10k_sdio.o
+ath10k_sdio-y += sdio.o
+
 # for tracing framework to find trace.h
 CFLAGS_trace.o := -I$(src)
index abeee200310babce7b0d8cbd4da14765d15edbfa..2d3a2f31123d3cc8b7f8f227c4e491fbdc51f0e0 100644 (file)
@@ -97,6 +97,77 @@ int ath10k_bmi_get_target_info(struct ath10k *ar,
        return 0;
 }
 
+#define TARGET_VERSION_SENTINAL 0xffffffffu
+
+int ath10k_bmi_get_target_info_sdio(struct ath10k *ar,
+                                   struct bmi_target_info *target_info)
+{
+       struct bmi_cmd cmd;
+       union bmi_resp resp;
+       u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.get_target_info);
+       u32 resplen, ver_len;
+       __le32 tmp;
+       int ret;
+
+       ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi get target info SDIO\n");
+
+       if (ar->bmi.done_sent) {
+               ath10k_warn(ar, "BMI Get Target Info Command disallowed\n");
+               return -EBUSY;
+       }
+
+       cmd.id = __cpu_to_le32(BMI_GET_TARGET_INFO);
+
+       /* Step 1: Read 4 bytes of the target info and check if it is
+        * the special sentinal version word or the first word in the
+        * version response.
+        */
+       resplen = sizeof(u32);
+       ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &tmp, &resplen);
+       if (ret) {
+               ath10k_warn(ar, "unable to read from device\n");
+               return ret;
+       }
+
+       /* Some SDIO boards have a special sentinal byte before the real
+        * version response.
+        */
+       if (__le32_to_cpu(tmp) == TARGET_VERSION_SENTINAL) {
+               /* Step 1b: Read the version length */
+               resplen = sizeof(u32);
+               ret = ath10k_hif_exchange_bmi_msg(ar, NULL, 0, &tmp,
+                                                 &resplen);
+               if (ret) {
+                       ath10k_warn(ar, "unable to read from device\n");
+                       return ret;
+               }
+       }
+
+       ver_len = __le32_to_cpu(tmp);
+
+       /* Step 2: Check the target info length */
+       if (ver_len != sizeof(resp.get_target_info)) {
+               ath10k_warn(ar, "Unexpected target info len: %u. Expected: %zu\n",
+                           ver_len, sizeof(resp.get_target_info));
+               return -EINVAL;
+       }
+
+       /* Step 3: Read the rest of the version response */
+       resplen = sizeof(resp.get_target_info) - sizeof(u32);
+       ret = ath10k_hif_exchange_bmi_msg(ar, NULL, 0,
+                                         &resp.get_target_info.version,
+                                         &resplen);
+       if (ret) {
+               ath10k_warn(ar, "unable to read from device\n");
+               return ret;
+       }
+
+       target_info->version = __le32_to_cpu(resp.get_target_info.version);
+       target_info->type    = __le32_to_cpu(resp.get_target_info.type);
+
+       return 0;
+}
+
 int ath10k_bmi_read_memory(struct ath10k *ar,
                           u32 address, void *buffer, u32 length)
 {
index cc45b63ade15e2bbd062bef4a0eef3530c5b0e80..0342073ed397bc96786d08d7eb26fc9dcb53d814 100644 (file)
@@ -198,6 +198,8 @@ void ath10k_bmi_start(struct ath10k *ar);
 int ath10k_bmi_done(struct ath10k *ar);
 int ath10k_bmi_get_target_info(struct ath10k *ar,
                               struct bmi_target_info *target_info);
+int ath10k_bmi_get_target_info_sdio(struct ath10k *ar,
+                                   struct bmi_target_info *target_info);
 int ath10k_bmi_read_memory(struct ath10k *ar, u32 address,
                           void *buffer, u32 length);
 int ath10k_bmi_write_memory(struct ath10k *ar, u32 address,
index 5a0638915874451201fadfd8ea450504a792a627..eea111d704c5dbd6f3c0b18fa18bce03b0d69334 100644 (file)
@@ -389,6 +389,21 @@ static void ath10k_send_suspend_complete(struct ath10k *ar)
        complete(&ar->target_suspend);
 }
 
+static void ath10k_init_sdio(struct ath10k *ar)
+{
+       u32 param = 0;
+
+       ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256);
+       ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);
+       ath10k_bmi_read32(ar, hi_acs_flags, &param);
+
+       param |= (HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET |
+                 HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET |
+                 HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE);
+
+       ath10k_bmi_write32(ar, hi_acs_flags, param);
+}
+
 static int ath10k_init_configure_target(struct ath10k *ar)
 {
        u32 param_host;
@@ -1395,7 +1410,18 @@ int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
 static void ath10k_core_get_fw_name(struct ath10k *ar, char *fw_name,
                                    size_t fw_name_len, int fw_api)
 {
-       scnprintf(fw_name, fw_name_len, "%s-%d.bin", ATH10K_FW_FILE_BASE, fw_api);
+       switch (ar->hif.bus) {
+       case ATH10K_BUS_SDIO:
+               scnprintf(fw_name, fw_name_len, "%s-%s-%d.bin",
+                         ATH10K_FW_FILE_BASE, ath10k_bus_str(ar->hif.bus),
+                         fw_api);
+               break;
+       case ATH10K_BUS_PCI:
+       case ATH10K_BUS_AHB:
+               scnprintf(fw_name, fw_name_len, "%s-%d.bin",
+                         ATH10K_FW_FILE_BASE, fw_api);
+               break;
+       }
 }
 
 static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
@@ -1953,6 +1979,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
        if (status)
                goto err;
 
+       if (ar->hif.bus == ATH10K_BUS_SDIO)
+               ath10k_init_sdio(ar);
+
        ar->htc.htc_ops.target_send_suspend_complete =
                ath10k_send_suspend_complete;
 
@@ -2200,7 +2229,10 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
        }
 
        memset(&target_info, 0, sizeof(target_info));
-       ret = ath10k_bmi_get_target_info(ar, &target_info);
+       if (ar->hif.bus == ATH10K_BUS_SDIO)
+               ret = ath10k_bmi_get_target_info_sdio(ar, &target_info);
+       else
+               ret = ath10k_bmi_get_target_info(ar, &target_info);
        if (ret) {
                ath10k_err(ar, "could not get target info (%d)\n", ret);
                goto err_power_down;
index bf091514ecc6bd220af20c68eaab00528ae2ef4c..8fc08a5043db204b722f75707c24af313e4251ea 100644 (file)
@@ -91,6 +91,7 @@ struct ath10k;
 enum ath10k_bus {
        ATH10K_BUS_PCI,
        ATH10K_BUS_AHB,
+       ATH10K_BUS_SDIO,
 };
 
 static inline const char *ath10k_bus_str(enum ath10k_bus bus)
@@ -100,6 +101,8 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus)
                return "pci";
        case ATH10K_BUS_AHB:
                return "ahb";
+       case ATH10K_BUS_SDIO:
+               return "sdio";
        }
 
        return "unknown";
index 4cd2a0fd49d6e53c08c7d2af5b1d1542f811affd..389fcb7a9fd0fdf7313f0acc2dc8e5b436644153 100644 (file)
@@ -625,17 +625,21 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
                                              size_t count, loff_t *ppos)
 {
        struct ath10k *ar = file->private_data;
-       char buf[32];
+       char buf[32] = {0};
+       ssize_t rc;
        int ret;
 
-       simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+       /* filter partial writes and invalid commands */
+       if (*ppos != 0 || count >= sizeof(buf) || count == 0)
+               return -EINVAL;
 
-       /* make sure that buf is null terminated */
-       buf[sizeof(buf) - 1] = 0;
+       rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+       if (rc < 0)
+               return rc;
 
        /* drop the possible '\n' from the end */
-       if (buf[count - 1] == '\n')
-               buf[count - 1] = 0;
+       if (buf[*ppos - 1] == '\n')
+               buf[*ppos - 1] = '\0';
 
        mutex_lock(&ar->conf_mutex);
 
index 2368f47314ae81994d337f948a685c55477c2b85..257d10985c6e21ae5a27d7408666f783576e8235 100644 (file)
@@ -38,6 +38,8 @@ enum ath10k_debug_mask {
        ATH10K_DBG_WMI_PRINT    = 0x00002000,
        ATH10K_DBG_PCI_PS       = 0x00004000,
        ATH10K_DBG_AHB          = 0x00008000,
+       ATH10K_DBG_SDIO         = 0x00010000,
+       ATH10K_DBG_SDIO_DUMP    = 0x00020000,
        ATH10K_DBG_ANY          = 0xffffffff,
 };
 
index b7669b2e94aaec8f86683cbc4e084cca122f6625..e5c80f582ff51692233b0775f6ee4f0e0624f1f1 100644 (file)
@@ -57,8 +57,8 @@ static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc,
        skb_pull(skb, sizeof(struct ath10k_htc_hdr));
 }
 
-static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
-                                           struct sk_buff *skb)
+void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
+                                    struct sk_buff *skb)
 {
        struct ath10k *ar = ep->htc->ar;
 
@@ -75,6 +75,7 @@ static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
 
        ep->ep_ops.ep_tx_complete(ep->htc->ar, skb);
 }
+EXPORT_SYMBOL(ath10k_htc_notify_tx_completion);
 
 static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
                                      struct sk_buff *skb)
@@ -230,12 +231,79 @@ ath10k_htc_process_credit_report(struct ath10k_htc *htc,
        spin_unlock_bh(&htc->tx_lock);
 }
 
-static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
-                                     u8 *buffer,
-                                     int length,
-                                     enum ath10k_htc_ep_id src_eid)
+static int
+ath10k_htc_process_lookahead(struct ath10k_htc *htc,
+                            const struct ath10k_htc_lookahead_report *report,
+                            int len,
+                            enum ath10k_htc_ep_id eid,
+                            void *next_lookaheads,
+                            int *next_lookaheads_len)
 {
        struct ath10k *ar = htc->ar;
+
+       /* Invalid lookahead flags are actually transmitted by
+        * the target in the HTC control message.
+        * Since this will happen at every boot we silently ignore
+        * the lookahead in this case
+        */
+       if (report->pre_valid != ((~report->post_valid) & 0xFF))
+               return 0;
+
+       if (next_lookaheads && next_lookaheads_len) {
+               ath10k_dbg(ar, ATH10K_DBG_HTC,
+                          "htc rx lookahead found pre_valid 0x%x post_valid 0x%x\n",
+                          report->pre_valid, report->post_valid);
+
+               /* look ahead bytes are valid, copy them over */
+               memcpy((u8 *)next_lookaheads, report->lookahead, 4);
+
+               *next_lookaheads_len = 1;
+       }
+
+       return 0;
+}
+
+static int
+ath10k_htc_process_lookahead_bundle(struct ath10k_htc *htc,
+                                   const struct ath10k_htc_lookahead_bundle *report,
+                                   int len,
+                                   enum ath10k_htc_ep_id eid,
+                                   void *next_lookaheads,
+                                   int *next_lookaheads_len)
+{
+       struct ath10k *ar = htc->ar;
+       int bundle_cnt = len / sizeof(*report);
+
+       if (!bundle_cnt || (bundle_cnt > HTC_HOST_MAX_MSG_PER_BUNDLE)) {
+               ath10k_warn(ar, "Invalid lookahead bundle count: %d\n",
+                           bundle_cnt);
+               return -EINVAL;
+       }
+
+       if (next_lookaheads && next_lookaheads_len) {
+               int i;
+
+               for (i = 0; i < bundle_cnt; i++) {
+                       memcpy(((u8 *)next_lookaheads) + 4 * i,
+                              report->lookahead, 4);
+                       report++;
+               }
+
+               *next_lookaheads_len = bundle_cnt;
+       }
+
+       return 0;
+}
+
+int ath10k_htc_process_trailer(struct ath10k_htc *htc,
+                              u8 *buffer,
+                              int length,
+                              enum ath10k_htc_ep_id src_eid,
+                              void *next_lookaheads,
+                              int *next_lookaheads_len)
+{
+       struct ath10k_htc_lookahead_bundle *bundle;
+       struct ath10k *ar = htc->ar;
        int status = 0;
        struct ath10k_htc_record *record;
        u8 *orig_buffer;
@@ -274,6 +342,29 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
                                                         record->hdr.len,
                                                         src_eid);
                        break;
+               case ATH10K_HTC_RECORD_LOOKAHEAD:
+                       len = sizeof(struct ath10k_htc_lookahead_report);
+                       if (record->hdr.len < len) {
+                               ath10k_warn(ar, "Lookahead report too long\n");
+                               status = -EINVAL;
+                               break;
+                       }
+                       status = ath10k_htc_process_lookahead(htc,
+                                                             record->lookahead_report,
+                                                             record->hdr.len,
+                                                             src_eid,
+                                                             next_lookaheads,
+                                                             next_lookaheads_len);
+                       break;
+               case ATH10K_HTC_RECORD_LOOKAHEAD_BUNDLE:
+                       bundle = record->lookahead_bundle;
+                       status = ath10k_htc_process_lookahead_bundle(htc,
+                                                                    bundle,
+                                                                    record->hdr.len,
+                                                                    src_eid,
+                                                                    next_lookaheads,
+                                                                    next_lookaheads_len);
+                       break;
                default:
                        ath10k_warn(ar, "Unhandled record: id:%d length:%d\n",
                                    record->hdr.id, record->hdr.len);
@@ -294,6 +385,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
 
        return status;
 }
+EXPORT_SYMBOL(ath10k_htc_process_trailer);
 
 void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
 {
@@ -360,7 +452,8 @@ void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
                trailer += payload_len;
                trailer -= trailer_len;
                status = ath10k_htc_process_trailer(htc, trailer,
-                                                   trailer_len, hdr->eid);
+                                                   trailer_len, hdr->eid,
+                                                   NULL, NULL);
                if (status)
                        goto out;
 
@@ -371,42 +464,6 @@ void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
                /* zero length packet with trailer data, just drop these */
                goto out;
 
-       if (eid == ATH10K_HTC_EP_0) {
-               struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data;
-
-               switch (__le16_to_cpu(msg->hdr.message_id)) {
-               case ATH10K_HTC_MSG_READY_ID:
-               case ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID:
-                       /* handle HTC control message */
-                       if (completion_done(&htc->ctl_resp)) {
-                               /*
-                                * this is a fatal error, target should not be
-                                * sending unsolicited messages on the ep 0
-                                */
-                               ath10k_warn(ar, "HTC rx ctrl still processing\n");
-                               complete(&htc->ctl_resp);
-                               goto out;
-                       }
-
-                       htc->control_resp_len =
-                               min_t(int, skb->len,
-                                     ATH10K_HTC_MAX_CTRL_MSG_LEN);
-
-                       memcpy(htc->control_resp_buffer, skb->data,
-                              htc->control_resp_len);
-
-                       complete(&htc->ctl_resp);
-                       break;
-               case ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE:
-                       htc->htc_ops.target_send_suspend_complete(ar);
-                       break;
-               default:
-                       ath10k_warn(ar, "ignoring unsolicited htc ep0 event\n");
-                       break;
-               }
-               goto out;
-       }
-
        ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %pK\n",
                   eid, skb);
        ep->ep_ops.ep_rx_complete(ar, skb);
@@ -421,10 +478,40 @@ EXPORT_SYMBOL(ath10k_htc_rx_completion_handler);
 static void ath10k_htc_control_rx_complete(struct ath10k *ar,
                                           struct sk_buff *skb)
 {
-       /* This is unexpected. FW is not supposed to send regular rx on this
-        * endpoint.
-        */
-       ath10k_warn(ar, "unexpected htc rx\n");
+       struct ath10k_htc *htc = &ar->htc;
+       struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data;
+
+       switch (__le16_to_cpu(msg->hdr.message_id)) {
+       case ATH10K_HTC_MSG_READY_ID:
+       case ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID:
+               /* handle HTC control message */
+               if (completion_done(&htc->ctl_resp)) {
+                       /* this is a fatal error, target should not be
+                        * sending unsolicited messages on the ep 0
+                        */
+                       ath10k_warn(ar, "HTC rx ctrl still processing\n");
+                       complete(&htc->ctl_resp);
+                       goto out;
+               }
+
+               htc->control_resp_len =
+                       min_t(int, skb->len,
+                             ATH10K_HTC_MAX_CTRL_MSG_LEN);
+
+               memcpy(htc->control_resp_buffer, skb->data,
+                      htc->control_resp_len);
+
+               complete(&htc->ctl_resp);
+               break;
+       case ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE:
+               htc->htc_ops.target_send_suspend_complete(ar);
+               break;
+       default:
+               ath10k_warn(ar, "ignoring unsolicited htc ep0 event\n");
+               break;
+       }
+
+out:
        kfree_skb(skb);
 }
 
@@ -497,12 +584,8 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
        struct ath10k *ar = htc->ar;
        int i, status = 0;
        unsigned long time_left;
-       struct ath10k_htc_svc_conn_req conn_req;
-       struct ath10k_htc_svc_conn_resp conn_resp;
        struct ath10k_htc_msg *msg;
        u16 message_id;
-       u16 credit_count;
-       u16 credit_size;
 
        time_left = wait_for_completion_timeout(&htc->ctl_resp,
                                                ATH10K_HTC_WAIT_TIMEOUT_HZ);
@@ -539,16 +622,14 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
 
        msg = (struct ath10k_htc_msg *)htc->control_resp_buffer;
        message_id   = __le16_to_cpu(msg->hdr.message_id);
-       credit_count = __le16_to_cpu(msg->ready.credit_count);
-       credit_size  = __le16_to_cpu(msg->ready.credit_size);
 
        if (message_id != ATH10K_HTC_MSG_READY_ID) {
                ath10k_err(ar, "Invalid HTC ready msg: 0x%x\n", message_id);
                return -ECOMM;
        }
 
-       htc->total_transmit_credits = credit_count;
-       htc->target_credit_size = credit_size;
+       htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count);
+       htc->target_credit_size = __le16_to_cpu(msg->ready.credit_size);
 
        ath10k_dbg(ar, ATH10K_DBG_HTC,
                   "Target ready! transmit resources: %d size:%d\n",
@@ -561,20 +642,17 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
                return -ECOMM;
        }
 
-       /* setup our pseudo HTC control endpoint connection */
-       memset(&conn_req, 0, sizeof(conn_req));
-       memset(&conn_resp, 0, sizeof(conn_resp));
-       conn_req.ep_ops.ep_tx_complete = ath10k_htc_control_tx_complete;
-       conn_req.ep_ops.ep_rx_complete = ath10k_htc_control_rx_complete;
-       conn_req.max_send_queue_depth = ATH10K_NUM_CONTROL_TX_BUFFERS;
-       conn_req.service_id = ATH10K_HTC_SVC_ID_RSVD_CTRL;
-
-       /* connect fake service */
-       status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp);
-       if (status) {
-               ath10k_err(ar, "could not connect to htc service (%d)\n",
-                          status);
-               return status;
+       /* The only way to determine if the ready message is an extended
+        * message is from the size.
+        */
+       if (htc->control_resp_len >=
+           sizeof(msg->hdr) + sizeof(msg->ready_ext)) {
+               htc->max_msgs_per_htc_bundle =
+                       min_t(u8, msg->ready_ext.max_msgs_per_htc_bundle,
+                             HTC_HOST_MAX_MSG_PER_BUNDLE);
+               ath10k_dbg(ar, ATH10K_DBG_HTC,
+                          "Extended ready message. RX bundle size: %d\n",
+                          htc->max_msgs_per_htc_bundle);
        }
 
        return 0;
@@ -772,6 +850,13 @@ int ath10k_htc_start(struct ath10k_htc *htc)
        msg->hdr.message_id =
                __cpu_to_le16(ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID);
 
+       if (ar->hif.bus == ATH10K_BUS_SDIO) {
+               /* Extra setup params used by SDIO */
+               msg->setup_complete_ext.flags =
+                       __cpu_to_le32(ATH10K_HTC_SETUP_COMPLETE_FLAGS_RX_BNDL_EN);
+               msg->setup_complete_ext.max_msgs_per_bundled_recv =
+                       htc->max_msgs_per_htc_bundle;
+       }
        ath10k_dbg(ar, ATH10K_DBG_HTC, "HTC is using TX credit flow control\n");
 
        status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb);
@@ -786,8 +871,10 @@ int ath10k_htc_start(struct ath10k_htc *htc)
 /* registered target arrival callback from the HIF layer */
 int ath10k_htc_init(struct ath10k *ar)
 {
-       struct ath10k_htc_ep *ep = NULL;
+       int status;
        struct ath10k_htc *htc = &ar->htc;
+       struct ath10k_htc_svc_conn_req conn_req;
+       struct ath10k_htc_svc_conn_resp conn_resp;
 
        spin_lock_init(&htc->tx_lock);
 
@@ -795,10 +882,21 @@ int ath10k_htc_init(struct ath10k *ar)
 
        htc->ar = ar;
 
-       /* Get HIF default pipe for HTC message exchange */
-       ep = &htc->endpoint[ATH10K_HTC_EP_0];
+       /* setup our pseudo HTC control endpoint connection */
+       memset(&conn_req, 0, sizeof(conn_req));
+       memset(&conn_resp, 0, sizeof(conn_resp));
+       conn_req.ep_ops.ep_tx_complete = ath10k_htc_control_tx_complete;
+       conn_req.ep_ops.ep_rx_complete = ath10k_htc_control_rx_complete;
+       conn_req.max_send_queue_depth = ATH10K_NUM_CONTROL_TX_BUFFERS;
+       conn_req.service_id = ATH10K_HTC_SVC_ID_RSVD_CTRL;
 
-       ath10k_hif_get_default_pipe(ar, &ep->ul_pipe_id, &ep->dl_pipe_id);
+       /* connect fake service */
+       status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp);
+       if (status) {
+               ath10k_err(ar, "could not connect to htc service (%d)\n",
+                          status);
+               return status;
+       }
 
        init_completion(&htc->ctl_resp);
 
index 6ababa345e2b94c169817f72cde649e235f1efc5..24663b07eeaca733b99cc324e78919c1de8f0875 100644 (file)
@@ -50,6 +50,8 @@ struct ath10k;
  * 4-byte aligned.
  */
 
+#define HTC_HOST_MAX_MSG_PER_BUNDLE        8
+
 enum ath10k_htc_tx_flags {
        ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01,
        ATH10K_HTC_FLAG_SEND_BUNDLE        = 0x02
@@ -110,6 +112,10 @@ enum ath10k_htc_conn_svc_status {
        ATH10K_HTC_CONN_SVC_STATUS_NO_MORE_EP   = 4
 };
 
+enum ath10k_htc_setup_complete_flags {
+       ATH10K_HTC_SETUP_COMPLETE_FLAGS_RX_BNDL_EN = 1
+};
+
 struct ath10k_ath10k_htc_msg_hdr {
        __le16 message_id; /* @enum htc_message_id */
 } __packed;
@@ -174,8 +180,10 @@ struct ath10k_htc_msg {
 } __packed __aligned(4);
 
 enum ath10k_ath10k_htc_record_id {
-       ATH10K_HTC_RECORD_NULL    = 0,
-       ATH10K_HTC_RECORD_CREDITS = 1
+       ATH10K_HTC_RECORD_NULL             = 0,
+       ATH10K_HTC_RECORD_CREDITS          = 1,
+       ATH10K_HTC_RECORD_LOOKAHEAD        = 2,
+       ATH10K_HTC_RECORD_LOOKAHEAD_BUNDLE = 3,
 };
 
 struct ath10k_ath10k_htc_record_hdr {
@@ -192,10 +200,28 @@ struct ath10k_htc_credit_report {
        u8 pad1;
 } __packed;
 
+struct ath10k_htc_lookahead_report {
+       u8 pre_valid;
+       u8 pad0;
+       u8 pad1;
+       u8 pad2;
+       u8 lookahead[4];
+       u8 post_valid;
+       u8 pad3;
+       u8 pad4;
+       u8 pad5;
+} __packed;
+
+struct ath10k_htc_lookahead_bundle {
+       u8 lookahead[4];
+} __packed;
+
 struct ath10k_htc_record {
        struct ath10k_ath10k_htc_record_hdr hdr;
        union {
                struct ath10k_htc_credit_report credit_report[0];
+               struct ath10k_htc_lookahead_report lookahead_report[0];
+               struct ath10k_htc_lookahead_bundle lookahead_bundle[0];
                u8 pauload[0];
        };
 } __packed __aligned(4);
@@ -338,6 +364,7 @@ struct ath10k_htc {
 
        int total_transmit_credits;
        int target_credit_size;
+       u8 max_msgs_per_htc_bundle;
 };
 
 int ath10k_htc_init(struct ath10k *ar);
@@ -351,5 +378,13 @@ int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
 struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size);
 void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
 void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
+void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
+                                    struct sk_buff *skb);
+int ath10k_htc_process_trailer(struct ath10k_htc *htc,
+                              u8 *buffer,
+                              int length,
+                              enum ath10k_htc_ep_id src_eid,
+                              void *next_lookaheads,
+                              int *next_lookaheads_len);
 
 #endif
index 5b1e90bb2a4db2ddeebbd1c3383f096889e1e9a3..d34272803fd71a5db2fb77e3af074ff1d18c3c42 100644 (file)
@@ -863,6 +863,59 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
 #define QCA9887_EEPROM_ADDR_LO_MASK            0x00ff0000
 #define QCA9887_EEPROM_ADDR_LO_LSB             16
 
+#define MBOX_RESET_CONTROL_ADDRESS             0x00000000
+#define MBOX_HOST_INT_STATUS_ADDRESS           0x00000800
+#define MBOX_HOST_INT_STATUS_ERROR_LSB         7
+#define MBOX_HOST_INT_STATUS_ERROR_MASK                0x00000080
+#define MBOX_HOST_INT_STATUS_CPU_LSB           6
+#define MBOX_HOST_INT_STATUS_CPU_MASK          0x00000040
+#define MBOX_HOST_INT_STATUS_COUNTER_LSB       4
+#define MBOX_HOST_INT_STATUS_COUNTER_MASK      0x00000010
+#define MBOX_CPU_INT_STATUS_ADDRESS            0x00000801
+#define MBOX_ERROR_INT_STATUS_ADDRESS          0x00000802
+#define MBOX_ERROR_INT_STATUS_WAKEUP_LSB       2
+#define MBOX_ERROR_INT_STATUS_WAKEUP_MASK      0x00000004
+#define MBOX_ERROR_INT_STATUS_RX_UNDERFLOW_LSB 1
+#define MBOX_ERROR_INT_STATUS_RX_UNDERFLOW_MASK        0x00000002
+#define MBOX_ERROR_INT_STATUS_TX_OVERFLOW_LSB  0
+#define MBOX_ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00000001
+#define MBOX_COUNTER_INT_STATUS_ADDRESS                0x00000803
+#define MBOX_COUNTER_INT_STATUS_COUNTER_LSB    0
+#define MBOX_COUNTER_INT_STATUS_COUNTER_MASK   0x000000ff
+#define MBOX_RX_LOOKAHEAD_VALID_ADDRESS                0x00000805
+#define MBOX_INT_STATUS_ENABLE_ADDRESS         0x00000828
+#define MBOX_INT_STATUS_ENABLE_ERROR_LSB       7
+#define MBOX_INT_STATUS_ENABLE_ERROR_MASK      0x00000080
+#define MBOX_INT_STATUS_ENABLE_CPU_LSB         6
+#define MBOX_INT_STATUS_ENABLE_CPU_MASK                0x00000040
+#define MBOX_INT_STATUS_ENABLE_INT_LSB         5
+#define MBOX_INT_STATUS_ENABLE_INT_MASK                0x00000020
+#define MBOX_INT_STATUS_ENABLE_COUNTER_LSB     4
+#define MBOX_INT_STATUS_ENABLE_COUNTER_MASK    0x00000010
+#define MBOX_INT_STATUS_ENABLE_MBOX_DATA_LSB   0
+#define MBOX_INT_STATUS_ENABLE_MBOX_DATA_MASK  0x0000000f
+#define MBOX_CPU_INT_STATUS_ENABLE_ADDRESS     0x00000819
+#define MBOX_CPU_INT_STATUS_ENABLE_BIT_LSB     0
+#define MBOX_CPU_INT_STATUS_ENABLE_BIT_MASK    0x000000ff
+#define MBOX_ERROR_STATUS_ENABLE_ADDRESS       0x0000081a
+#define MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB  1
+#define MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00000002
+#define MBOX_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB   0
+#define MBOX_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK  0x00000001
+#define MBOX_COUNTER_INT_STATUS_ENABLE_ADDRESS 0x0000081b
+#define MBOX_COUNTER_INT_STATUS_ENABLE_BIT_LSB 0
+#define MBOX_COUNTER_INT_STATUS_ENABLE_BIT_MASK        0x000000ff
+#define MBOX_COUNT_ADDRESS                     0x00000820
+#define MBOX_COUNT_DEC_ADDRESS                 0x00000840
+#define MBOX_WINDOW_DATA_ADDRESS               0x00000874
+#define MBOX_WINDOW_WRITE_ADDR_ADDRESS         0x00000878
+#define MBOX_WINDOW_READ_ADDR_ADDRESS          0x0000087c
+#define MBOX_CPU_DBG_SEL_ADDRESS               0x00000883
+#define MBOX_CPU_DBG_ADDRESS                   0x00000884
+#define MBOX_RTC_BASE_ADDRESS                  0x00000000
+#define MBOX_GPIO_BASE_ADDRESS                 0x00005000
+#define MBOX_MBOX_BASE_ADDRESS                 0x00008000
+
 #define RTC_STATE_V_GET(x) (((x) & RTC_STATE_V_MASK) >> RTC_STATE_V_LSB)
 
 /* Register definitions for first generation ath10k cards. These cards include
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
new file mode 100644 (file)
index 0000000..9e78fba
--- /dev/null
@@ -0,0 +1,2113 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sd.h>
+#include <linux/bitfield.h>
+#include "core.h"
+#include "bmi.h"
+#include "debug.h"
+#include "hif.h"
+#include "htc.h"
+#include "targaddrs.h"
+#include "trace.h"
+#include "sdio.h"
+
+/* inlined helper functions */
+
+static inline int ath10k_sdio_calc_txrx_padded_len(struct ath10k_sdio *ar_sdio,
+                                                  size_t len)
+{
+       return __ALIGN_MASK((len), ar_sdio->mbox_info.block_mask);
+}
+
+static inline enum ath10k_htc_ep_id pipe_id_to_eid(u8 pipe_id)
+{
+       return (enum ath10k_htc_ep_id)pipe_id;
+}
+
+static inline void ath10k_sdio_mbox_free_rx_pkt(struct ath10k_sdio_rx_data *pkt)
+{
+       dev_kfree_skb(pkt->skb);
+       pkt->skb = NULL;
+       pkt->alloc_len = 0;
+       pkt->act_len = 0;
+       pkt->trailer_only = false;
+}
+
+static inline int ath10k_sdio_mbox_alloc_rx_pkt(struct ath10k_sdio_rx_data *pkt,
+                                               size_t act_len, size_t full_len,
+                                               bool part_of_bundle,
+                                               bool last_in_bundle)
+{
+       pkt->skb = dev_alloc_skb(full_len);
+       if (!pkt->skb)
+               return -ENOMEM;
+
+       pkt->act_len = act_len;
+       pkt->alloc_len = full_len;
+       pkt->part_of_bundle = part_of_bundle;
+       pkt->last_in_bundle = last_in_bundle;
+       pkt->trailer_only = false;
+
+       return 0;
+}
+
+static inline bool is_trailer_only_msg(struct ath10k_sdio_rx_data *pkt)
+{
+       bool trailer_only = false;
+       struct ath10k_htc_hdr *htc_hdr =
+               (struct ath10k_htc_hdr *)pkt->skb->data;
+       u16 len = __le16_to_cpu(htc_hdr->len);
+
+       if (len == htc_hdr->trailer_len)
+               trailer_only = true;
+
+       return trailer_only;
+}
+
+/* sdio/mmc functions */
+
+static inline void ath10k_sdio_set_cmd52_arg(u32 *arg, u8 write, u8 raw,
+                                            unsigned int address,
+                                            unsigned char val)
+{
+       *arg = FIELD_PREP(BIT(31), write) |
+              FIELD_PREP(BIT(27), raw) |
+              FIELD_PREP(BIT(26), 1) |
+              FIELD_PREP(GENMASK(25, 9), address) |
+              FIELD_PREP(BIT(8), 1) |
+              FIELD_PREP(GENMASK(7, 0), val);
+}
+
+static int ath10k_sdio_func0_cmd52_wr_byte(struct mmc_card *card,
+                                          unsigned int address,
+                                          unsigned char byte)
+{
+       struct mmc_command io_cmd;
+
+       memset(&io_cmd, 0, sizeof(io_cmd));
+       ath10k_sdio_set_cmd52_arg(&io_cmd.arg, 1, 0, address, byte);
+       io_cmd.opcode = SD_IO_RW_DIRECT;
+       io_cmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
+
+       return mmc_wait_for_cmd(card->host, &io_cmd, 0);
+}
+
+static int ath10k_sdio_func0_cmd52_rd_byte(struct mmc_card *card,
+                                          unsigned int address,
+                                          unsigned char *byte)
+{
+       struct mmc_command io_cmd;
+       int ret;
+
+       memset(&io_cmd, 0, sizeof(io_cmd));
+       ath10k_sdio_set_cmd52_arg(&io_cmd.arg, 0, 0, address, 0);
+       io_cmd.opcode = SD_IO_RW_DIRECT;
+       io_cmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
+
+       ret = mmc_wait_for_cmd(card->host, &io_cmd, 0);
+       if (!ret)
+               *byte = io_cmd.resp[0];
+
+       return ret;
+}
+
+static int ath10k_sdio_config(struct ath10k *ar)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct sdio_func *func = ar_sdio->func;
+       unsigned char byte, asyncintdelay = 2;
+       int ret;
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio configuration\n");
+
+       sdio_claim_host(func);
+
+       byte = 0;
+       ret = ath10k_sdio_func0_cmd52_rd_byte(func->card,
+                                             SDIO_CCCR_DRIVE_STRENGTH,
+                                             &byte);
+
+       byte &= ~ATH10K_SDIO_DRIVE_DTSX_MASK;
+       byte |= FIELD_PREP(ATH10K_SDIO_DRIVE_DTSX_MASK,
+                          ATH10K_SDIO_DRIVE_DTSX_TYPE_D);
+
+       ret = ath10k_sdio_func0_cmd52_wr_byte(func->card,
+                                             SDIO_CCCR_DRIVE_STRENGTH,
+                                             byte);
+
+       byte = 0;
+       ret = ath10k_sdio_func0_cmd52_rd_byte(
+               func->card,
+               CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR,
+               &byte);
+
+       byte |= (CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A |
+                CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C |
+                CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D);
+
+       ret = ath10k_sdio_func0_cmd52_wr_byte(func->card,
+                                             CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR,
+                                             byte);
+       if (ret) {
+               ath10k_warn(ar, "failed to enable driver strength: %d\n", ret);
+               goto out;
+       }
+
+       byte = 0;
+       ret = ath10k_sdio_func0_cmd52_rd_byte(func->card,
+                                             CCCR_SDIO_IRQ_MODE_REG_SDIO3,
+                                             &byte);
+
+       byte |= SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_SDIO3;
+
+       ret = ath10k_sdio_func0_cmd52_wr_byte(func->card,
+                                             CCCR_SDIO_IRQ_MODE_REG_SDIO3,
+                                             byte);
+       if (ret) {
+               ath10k_warn(ar, "failed to enable 4-bit async irq mode: %d\n",
+                           ret);
+               goto out;
+       }
+
+       byte = 0;
+       ret = ath10k_sdio_func0_cmd52_rd_byte(func->card,
+                                             CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS,
+                                             &byte);
+
+       byte &= ~CCCR_SDIO_ASYNC_INT_DELAY_MASK;
+       byte |= FIELD_PREP(CCCR_SDIO_ASYNC_INT_DELAY_MASK, asyncintdelay);
+
+       ret = ath10k_sdio_func0_cmd52_wr_byte(func->card,
+                                             CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS,
+                                             byte);
+
+       /* give us some time to enable, in ms */
+       func->enable_timeout = 100;
+
+       ret = sdio_set_block_size(func, ar_sdio->mbox_info.block_size);
+       if (ret) {
+               ath10k_warn(ar, "failed to set sdio block size to %d: %d\n",
+                           ar_sdio->mbox_info.block_size, ret);
+               goto out;
+       }
+
+out:
+       sdio_release_host(func);
+       return ret;
+}
+
+static int ath10k_sdio_write32(struct ath10k *ar, u32 addr, u32 val)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct sdio_func *func = ar_sdio->func;
+       int ret;
+
+       sdio_claim_host(func);
+
+       sdio_writel(func, val, addr, &ret);
+       if (ret) {
+               ath10k_warn(ar, "failed to write 0x%x to address 0x%x: %d\n",
+                           val, addr, ret);
+               goto out;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio write32 addr 0x%x val 0x%x\n",
+                  addr, val);
+
+out:
+       sdio_release_host(func);
+
+       return ret;
+}
+
+static int ath10k_sdio_writesb32(struct ath10k *ar, u32 addr, u32 val)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct sdio_func *func = ar_sdio->func;
+       __le32 *buf;
+       int ret;
+
+       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       *buf = cpu_to_le32(val);
+
+       sdio_claim_host(func);
+
+       ret = sdio_writesb(func, addr, buf, sizeof(*buf));
+       if (ret) {
+               ath10k_warn(ar, "failed to write value 0x%x to fixed sb address 0x%x: %d\n",
+                           val, addr, ret);
+               goto out;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio writesb32 addr 0x%x val 0x%x\n",
+                  addr, val);
+
+out:
+       sdio_release_host(func);
+
+       kfree(buf);
+
+       return ret;
+}
+
+static int ath10k_sdio_read32(struct ath10k *ar, u32 addr, u32 *val)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct sdio_func *func = ar_sdio->func;
+       int ret;
+
+       sdio_claim_host(func);
+       *val = sdio_readl(func, addr, &ret);
+       if (ret) {
+               ath10k_warn(ar, "failed to read from address 0x%x: %d\n",
+                           addr, ret);
+               goto out;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio read32 addr 0x%x val 0x%x\n",
+                  addr, *val);
+
+out:
+       sdio_release_host(func);
+
+       return ret;
+}
+
+static int ath10k_sdio_read(struct ath10k *ar, u32 addr, void *buf, size_t len)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct sdio_func *func = ar_sdio->func;
+       int ret;
+
+       sdio_claim_host(func);
+
+       ret = sdio_memcpy_fromio(func, buf, addr, len);
+       if (ret) {
+               ath10k_warn(ar, "failed to read from address 0x%x: %d\n",
+                           addr, ret);
+               goto out;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio read addr 0x%x buf 0x%p len %zu\n",
+                  addr, buf, len);
+       ath10k_dbg_dump(ar, ATH10K_DBG_SDIO_DUMP, NULL, "sdio read ", buf, len);
+
+out:
+       sdio_release_host(func);
+
+       return ret;
+}
+
+static int ath10k_sdio_write(struct ath10k *ar, u32 addr, const void *buf, size_t len)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct sdio_func *func = ar_sdio->func;
+       int ret;
+
+       sdio_claim_host(func);
+
+       /* For some reason toio() doesn't have const for the buffer, need
+        * an ugly hack to workaround that.
+        */
+       ret = sdio_memcpy_toio(func, addr, (void *)buf, len);
+       if (ret) {
+               ath10k_warn(ar, "failed to write to address 0x%x: %d\n",
+                           addr, ret);
+               goto out;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio write addr 0x%x buf 0x%p len %zu\n",
+                  addr, buf, len);
+       ath10k_dbg_dump(ar, ATH10K_DBG_SDIO_DUMP, NULL, "sdio write ", buf, len);
+
+out:
+       sdio_release_host(func);
+
+       return ret;
+}
+
+static int ath10k_sdio_readsb(struct ath10k *ar, u32 addr, void *buf, size_t len)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct sdio_func *func = ar_sdio->func;
+       int ret;
+
+       sdio_claim_host(func);
+
+       len = round_down(len, ar_sdio->mbox_info.block_size);
+
+       ret = sdio_readsb(func, buf, addr, len);
+       if (ret) {
+               ath10k_warn(ar, "failed to read from fixed (sb) address 0x%x: %d\n",
+                           addr, ret);
+               goto out;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio readsb addr 0x%x buf 0x%p len %zu\n",
+                  addr, buf, len);
+       ath10k_dbg_dump(ar, ATH10K_DBG_SDIO_DUMP, NULL, "sdio readsb ", buf, len);
+
+out:
+       sdio_release_host(func);
+
+       return ret;
+}
+
+/* HIF mbox functions */
+
+static int ath10k_sdio_mbox_rx_process_packet(struct ath10k *ar,
+                                             struct ath10k_sdio_rx_data *pkt,
+                                             u32 *lookaheads,
+                                             int *n_lookaheads)
+{
+       struct ath10k_htc *htc = &ar->htc;
+       struct sk_buff *skb = pkt->skb;
+       struct ath10k_htc_hdr *htc_hdr = (struct ath10k_htc_hdr *)skb->data;
+       bool trailer_present = htc_hdr->flags & ATH10K_HTC_FLAG_TRAILER_PRESENT;
+       enum ath10k_htc_ep_id eid;
+       u16 payload_len;
+       u8 *trailer;
+       int ret;
+
+       payload_len = le16_to_cpu(htc_hdr->len);
+
+       if (trailer_present) {
+               trailer = skb->data + sizeof(*htc_hdr) +
+                         payload_len - htc_hdr->trailer_len;
+
+               eid = pipe_id_to_eid(htc_hdr->eid);
+
+               ret = ath10k_htc_process_trailer(htc,
+                                                trailer,
+                                                htc_hdr->trailer_len,
+                                                eid,
+                                                lookaheads,
+                                                n_lookaheads);
+               if (ret)
+                       return ret;
+
+               if (is_trailer_only_msg(pkt))
+                       pkt->trailer_only = true;
+
+               skb_trim(skb, skb->len - htc_hdr->trailer_len);
+       }
+
+       skb_pull(skb, sizeof(*htc_hdr));
+
+       return 0;
+}
+
+static int ath10k_sdio_mbox_rx_process_packets(struct ath10k *ar,
+                                              u32 lookaheads[],
+                                              int *n_lookahead)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct ath10k_htc *htc = &ar->htc;
+       struct ath10k_sdio_rx_data *pkt;
+       struct ath10k_htc_ep *ep;
+       enum ath10k_htc_ep_id id;
+       int ret, i, *n_lookahead_local;
+       u32 *lookaheads_local;
+
+       for (i = 0; i < ar_sdio->n_rx_pkts; i++) {
+               lookaheads_local = lookaheads;
+               n_lookahead_local = n_lookahead;
+
+               id = ((struct ath10k_htc_hdr *)&lookaheads[i])->eid;
+
+               if (id >= ATH10K_HTC_EP_COUNT) {
+                       ath10k_warn(ar, "invalid endpoint in look-ahead: %d\n",
+                                   id);
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               ep = &htc->endpoint[id];
+
+               if (ep->service_id == 0) {
+                       ath10k_warn(ar, "ep %d is not connected\n", id);
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               pkt = &ar_sdio->rx_pkts[i];
+
+               if (pkt->part_of_bundle && !pkt->last_in_bundle) {
+                       /* Only read lookahead's from RX trailers
+                        * for the last packet in a bundle.
+                        */
+                       lookaheads_local = NULL;
+                       n_lookahead_local = NULL;
+               }
+
+               ret = ath10k_sdio_mbox_rx_process_packet(ar,
+                                                        pkt,
+                                                        lookaheads_local,
+                                                        n_lookahead_local);
+               if (ret)
+                       goto out;
+
+               if (!pkt->trailer_only)
+                       ep->ep_ops.ep_rx_complete(ar_sdio->ar, pkt->skb);
+               else
+                       kfree_skb(pkt->skb);
+
+               /* The RX complete handler now owns the skb...*/
+               pkt->skb = NULL;
+               pkt->alloc_len = 0;
+       }
+
+       ret = 0;
+
+out:
+       /* Free all packets that was not passed on to the RX completion
+        * handler...
+        */
+       for (; i < ar_sdio->n_rx_pkts; i++)
+               ath10k_sdio_mbox_free_rx_pkt(&ar_sdio->rx_pkts[i]);
+
+       return ret;
+}
+
+static int ath10k_sdio_mbox_alloc_pkt_bundle(struct ath10k *ar,
+                                            struct ath10k_sdio_rx_data *rx_pkts,
+                                            struct ath10k_htc_hdr *htc_hdr,
+                                            size_t full_len, size_t act_len,
+                                            size_t *bndl_cnt)
+{
+       int ret, i;
+
+       *bndl_cnt = FIELD_GET(ATH10K_HTC_FLAG_BUNDLE_MASK, htc_hdr->flags);
+
+       if (*bndl_cnt > HTC_HOST_MAX_MSG_PER_BUNDLE) {
+               ath10k_warn(ar,
+                           "HTC bundle length %u exceeds maximum %u\n",
+                           le16_to_cpu(htc_hdr->len),
+                           HTC_HOST_MAX_MSG_PER_BUNDLE);
+               return -ENOMEM;
+       }
+
+       /* Allocate bndl_cnt extra skb's for the bundle.
+        * The package containing the
+        * ATH10K_HTC_FLAG_BUNDLE_MASK flag is not included
+        * in bndl_cnt. The skb for that packet will be
+        * allocated separately.
+        */
+       for (i = 0; i < *bndl_cnt; i++) {
+               ret = ath10k_sdio_mbox_alloc_rx_pkt(&rx_pkts[i],
+                                                   act_len,
+                                                   full_len,
+                                                   true,
+                                                   false);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
+                                    u32 lookaheads[], int n_lookaheads)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct ath10k_htc_hdr *htc_hdr;
+       size_t full_len, act_len;
+       bool last_in_bundle;
+       int ret, i;
+
+       if (n_lookaheads > ATH10K_SDIO_MAX_RX_MSGS) {
+               ath10k_warn(ar,
+                           "the total number of pkgs to be fetched (%u) exceeds maximum %u\n",
+                           n_lookaheads,
+                           ATH10K_SDIO_MAX_RX_MSGS);
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       for (i = 0; i < n_lookaheads; i++) {
+               htc_hdr = (struct ath10k_htc_hdr *)&lookaheads[i];
+               last_in_bundle = false;
+
+               if (le16_to_cpu(htc_hdr->len) >
+                   ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH) {
+                       ath10k_warn(ar,
+                                   "payload length %d exceeds max htc length: %zu\n",
+                                   le16_to_cpu(htc_hdr->len),
+                                   ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH);
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               act_len = le16_to_cpu(htc_hdr->len) + sizeof(*htc_hdr);
+               full_len = ath10k_sdio_calc_txrx_padded_len(ar_sdio, act_len);
+
+               if (full_len > ATH10K_SDIO_MAX_BUFFER_SIZE) {
+                       ath10k_warn(ar,
+                                   "rx buffer requested with invalid htc_hdr length (%d, 0x%x): %d\n",
+                                   htc_hdr->eid, htc_hdr->flags,
+                                   le16_to_cpu(htc_hdr->len));
+                       ret = -EINVAL;
+                       goto err;
+               }
+
+               if (htc_hdr->flags & ATH10K_HTC_FLAG_BUNDLE_MASK) {
+                       /* HTC header indicates that every packet to follow
+                        * has the same padded length so that it can be
+                        * optimally fetched as a full bundle.
+                        */
+                       size_t bndl_cnt;
+
+                       ret = ath10k_sdio_mbox_alloc_pkt_bundle(ar,
+                                                               &ar_sdio->rx_pkts[i],
+                                                               htc_hdr,
+                                                               full_len,
+                                                               act_len,
+                                                               &bndl_cnt);
+
+                       n_lookaheads += bndl_cnt;
+                       i += bndl_cnt;
+                       /*Next buffer will be the last in the bundle */
+                       last_in_bundle = true;
+               }
+
+               /* Allocate skb for packet. If the packet had the
+                * ATH10K_HTC_FLAG_BUNDLE_MASK flag set, all bundled
+                * packet skb's have been allocated in the previous step.
+                */
+               ret = ath10k_sdio_mbox_alloc_rx_pkt(&ar_sdio->rx_pkts[i],
+                                                   act_len,
+                                                   full_len,
+                                                   last_in_bundle,
+                                                   last_in_bundle);
+       }
+
+       ar_sdio->n_rx_pkts = i;
+
+       return 0;
+
+err:
+       for (i = 0; i < ATH10K_SDIO_MAX_RX_MSGS; i++) {
+               if (!ar_sdio->rx_pkts[i].alloc_len)
+                       break;
+               ath10k_sdio_mbox_free_rx_pkt(&ar_sdio->rx_pkts[i]);
+       }
+
+       return ret;
+}
+
+static int ath10k_sdio_mbox_rx_packet(struct ath10k *ar,
+                                     struct ath10k_sdio_rx_data *pkt)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct sk_buff *skb = pkt->skb;
+       int ret;
+
+       ret = ath10k_sdio_readsb(ar, ar_sdio->mbox_info.htc_addr,
+                                skb->data, pkt->alloc_len);
+       pkt->status = ret;
+       if (!ret)
+               skb_put(skb, pkt->act_len);
+
+       return ret;
+}
+
+static int ath10k_sdio_mbox_rx_fetch(struct ath10k *ar)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       int ret, i;
+
+       for (i = 0; i < ar_sdio->n_rx_pkts; i++) {
+               ret = ath10k_sdio_mbox_rx_packet(ar,
+                                                &ar_sdio->rx_pkts[i]);
+               if (ret)
+                       goto err;
+       }
+
+       return 0;
+
+err:
+       /* Free all packets that was not successfully fetched. */
+       for (; i < ar_sdio->n_rx_pkts; i++)
+               ath10k_sdio_mbox_free_rx_pkt(&ar_sdio->rx_pkts[i]);
+
+       return ret;
+}
+
+/* This is the timeout for mailbox processing done in the sdio irq
+ * handler. The timeout is deliberately set quite high since SDIO dump logs
+ * over serial port can/will add a substantial overhead to the processing
+ * (if enabled).
+ */
+#define SDIO_MBOX_PROCESSING_TIMEOUT_HZ (20 * HZ)
+
+static int ath10k_sdio_mbox_rxmsg_pending_handler(struct ath10k *ar,
+                                                 u32 msg_lookahead, bool *done)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       u32 lookaheads[ATH10K_SDIO_MAX_RX_MSGS];
+       int n_lookaheads = 1;
+       unsigned long timeout;
+       int ret;
+
+       *done = true;
+
+       /* Copy the lookahead obtained from the HTC register table into our
+        * temp array as a start value.
+        */
+       lookaheads[0] = msg_lookahead;
+
+       timeout = jiffies + SDIO_MBOX_PROCESSING_TIMEOUT_HZ;
+       while (time_before(jiffies, timeout)) {
+               /* Try to allocate as many HTC RX packets indicated by
+                * n_lookaheads.
+                */
+               ret = ath10k_sdio_mbox_rx_alloc(ar, lookaheads,
+                                               n_lookaheads);
+               if (ret)
+                       break;
+
+               if (ar_sdio->n_rx_pkts >= 2)
+                       /* A recv bundle was detected, force IRQ status
+                        * re-check again.
+                        */
+                       *done = false;
+
+               ret = ath10k_sdio_mbox_rx_fetch(ar);
+
+               /* Process fetched packets. This will potentially update
+                * n_lookaheads depending on if the packets contain lookahead
+                * reports.
+                */
+               n_lookaheads = 0;
+               ret = ath10k_sdio_mbox_rx_process_packets(ar,
+                                                         lookaheads,
+                                                         &n_lookaheads);
+
+               if (!n_lookaheads || ret)
+                       break;
+
+               /* For SYNCH processing, if we get here, we are running
+                * through the loop again due to updated lookaheads. Set
+                * flag that we should re-check IRQ status registers again
+                * before leaving IRQ processing, this can net better
+                * performance in high throughput situations.
+                */
+               *done = false;
+       }
+
+       if (ret && (ret != -ECANCELED))
+               ath10k_warn(ar, "failed to get pending recv messages: %d\n",
+                           ret);
+
+       return ret;
+}
+
+static int ath10k_sdio_mbox_proc_dbg_intr(struct ath10k *ar)
+{
+       u32 val;
+       int ret;
+
+       /* TODO: Add firmware crash handling */
+       ath10k_warn(ar, "firmware crashed\n");
+
+       /* read counter to clear the interrupt, the debug error interrupt is
+        * counter 0.
+        */
+       ret = ath10k_sdio_read32(ar, MBOX_COUNT_DEC_ADDRESS, &val);
+       if (ret)
+               ath10k_warn(ar, "failed to clear debug interrupt: %d\n", ret);
+
+       return ret;
+}
+
+static int ath10k_sdio_mbox_proc_counter_intr(struct ath10k *ar)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+       u8 counter_int_status;
+       int ret;
+
+       mutex_lock(&irq_data->mtx);
+       counter_int_status = irq_data->irq_proc_reg->counter_int_status &
+                            irq_data->irq_en_reg->cntr_int_status_en;
+
+       /* NOTE: other modules like GMBOX may use the counter interrupt for
+        * credit flow control on other counters, we only need to check for
+        * the debug assertion counter interrupt.
+        */
+       if (counter_int_status & ATH10K_SDIO_TARGET_DEBUG_INTR_MASK)
+               ret = ath10k_sdio_mbox_proc_dbg_intr(ar);
+       else
+               ret = 0;
+
+       mutex_unlock(&irq_data->mtx);
+
+       return ret;
+}
+
+static int ath10k_sdio_mbox_proc_err_intr(struct ath10k *ar)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+       u8 error_int_status;
+       int ret;
+
+       ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio error interrupt\n");
+
+       error_int_status = irq_data->irq_proc_reg->error_int_status & 0x0F;
+       if (!error_int_status) {
+               ath10k_warn(ar, "invalid error interrupt status: 0x%x\n",
+                           error_int_status);
+               return -EIO;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_SDIO,
+                  "sdio error_int_status 0x%x\n", error_int_status);
+
+       if (FIELD_GET(MBOX_ERROR_INT_STATUS_WAKEUP_MASK,
+                     error_int_status))
+               ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio interrupt error wakeup\n");
+
+       if (FIELD_GET(MBOX_ERROR_INT_STATUS_RX_UNDERFLOW_MASK,
+                     error_int_status))
+               ath10k_warn(ar, "rx underflow interrupt error\n");
+
+       if (FIELD_GET(MBOX_ERROR_INT_STATUS_TX_OVERFLOW_MASK,
+                     error_int_status))
+               ath10k_warn(ar, "tx overflow interrupt error\n");
+
+       /* Clear the interrupt */
+       irq_data->irq_proc_reg->error_int_status &= ~error_int_status;
+
+       /* set W1C value to clear the interrupt, this hits the register first */
+       ret = ath10k_sdio_writesb32(ar, MBOX_ERROR_INT_STATUS_ADDRESS,
+                                   error_int_status);
+       if (ret) {
+               ath10k_warn(ar, "unable to write to error int status address: %d\n",
+                           ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int ath10k_sdio_mbox_proc_cpu_intr(struct ath10k *ar)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+       u8 cpu_int_status;
+       int ret;
+
+       mutex_lock(&irq_data->mtx);
+       cpu_int_status = irq_data->irq_proc_reg->cpu_int_status &
+                        irq_data->irq_en_reg->cpu_int_status_en;
+       if (!cpu_int_status) {
+               ath10k_warn(ar, "CPU interrupt status is zero\n");
+               ret = -EIO;
+               goto out;
+       }
+
+       /* Clear the interrupt */
+       irq_data->irq_proc_reg->cpu_int_status &= ~cpu_int_status;
+
+       /* Set up the register transfer buffer to hit the register 4 times,
+        * this is done to make the access 4-byte aligned to mitigate issues
+        * with host bus interconnects that restrict bus transfer lengths to
+        * be a multiple of 4-bytes.
+        *
+        * Set W1C value to clear the interrupt, this hits the register first.
+        */
+       ret = ath10k_sdio_writesb32(ar, MBOX_CPU_INT_STATUS_ADDRESS,
+                                   cpu_int_status);
+       if (ret) {
+               ath10k_warn(ar, "unable to write to cpu interrupt status address: %d\n",
+                           ret);
+               goto out;
+       }
+
+out:
+       mutex_unlock(&irq_data->mtx);
+       return ret;
+}
+
+static int ath10k_sdio_mbox_read_int_status(struct ath10k *ar,
+                                           u8 *host_int_status,
+                                           u32 *lookahead)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+       struct ath10k_sdio_irq_proc_regs *irq_proc_reg = irq_data->irq_proc_reg;
+       struct ath10k_sdio_irq_enable_regs *irq_en_reg = irq_data->irq_en_reg;
+       u8 htc_mbox = FIELD_PREP(ATH10K_HTC_MAILBOX_MASK, 1);
+       int ret;
+
+       mutex_lock(&irq_data->mtx);
+
+       *lookahead = 0;
+       *host_int_status = 0;
+
+       /* int_status_en is supposed to be non zero, otherwise interrupts
+        * shouldn't be enabled. There is however a short time frame during
+        * initialization between the irq register and int_status_en init
+        * where this can happen.
+        * We silently ignore this condition.
+        */
+       if (!irq_en_reg->int_status_en) {
+               ret = 0;
+               goto out;
+       }
+
+       /* Read the first sizeof(struct ath10k_irq_proc_registers)
+        * bytes of the HTC register table. This
+        * will yield us the value of different int status
+        * registers and the lookahead registers.
+        */
+       ret = ath10k_sdio_read(ar, MBOX_HOST_INT_STATUS_ADDRESS,
+                              irq_proc_reg, sizeof(*irq_proc_reg));
+       if (ret)
+               goto out;
+
+       /* Update only those registers that are enabled */
+       *host_int_status = irq_proc_reg->host_int_status &
+                          irq_en_reg->int_status_en;
+
+       /* Look at mbox status */
+       if (!(*host_int_status & htc_mbox)) {
+               *lookahead = 0;
+               ret = 0;
+               goto out;
+       }
+
+       /* Mask out pending mbox value, we use look ahead as
+        * the real flag for mbox processing.
+        */
+       *host_int_status &= ~htc_mbox;
+       if (irq_proc_reg->rx_lookahead_valid & htc_mbox) {
+               *lookahead = le32_to_cpu(
+                       irq_proc_reg->rx_lookahead[ATH10K_HTC_MAILBOX]);
+               if (!*lookahead)
+                       ath10k_warn(ar, "sdio mbox lookahead is zero\n");
+       }
+
+out:
+       mutex_unlock(&irq_data->mtx);
+       return ret;
+}
+
+static int ath10k_sdio_mbox_proc_pending_irqs(struct ath10k *ar,
+                                             bool *done)
+{
+       u8 host_int_status;
+       u32 lookahead;
+       int ret;
+
+       /* NOTE: HIF implementation guarantees that the context of this
+        * call allows us to perform SYNCHRONOUS I/O, that is we can block,
+        * sleep or call any API that can block or switch thread/task
+        * contexts. This is a fully schedulable context.
+        */
+
+       ret = ath10k_sdio_mbox_read_int_status(ar,
+                                              &host_int_status,
+                                              &lookahead);
+       if (ret) {
+               *done = true;
+               goto out;
+       }
+
+       if (!host_int_status && !lookahead) {
+               ret = 0;
+               *done = true;
+               goto out;
+       }
+
+       if (lookahead) {
+               ath10k_dbg(ar, ATH10K_DBG_SDIO,
+                          "sdio pending mailbox msg lookahead 0x%08x\n",
+                          lookahead);
+
+               ret = ath10k_sdio_mbox_rxmsg_pending_handler(ar,
+                                                            lookahead,
+                                                            done);
+               if (ret)
+                       goto out;
+       }
+
+       /* now, handle the rest of the interrupts */
+       ath10k_dbg(ar, ATH10K_DBG_SDIO,
+                  "sdio host_int_status 0x%x\n", host_int_status);
+
+       if (FIELD_GET(MBOX_HOST_INT_STATUS_CPU_MASK, host_int_status)) {
+               /* CPU Interrupt */
+               ret = ath10k_sdio_mbox_proc_cpu_intr(ar);
+               if (ret)
+                       goto out;
+       }
+
+       if (FIELD_GET(MBOX_HOST_INT_STATUS_ERROR_MASK, host_int_status)) {
+               /* Error Interrupt */
+               ret = ath10k_sdio_mbox_proc_err_intr(ar);
+               if (ret)
+                       goto out;
+       }
+
+       if (FIELD_GET(MBOX_HOST_INT_STATUS_COUNTER_MASK, host_int_status))
+               /* Counter Interrupt */
+               ret = ath10k_sdio_mbox_proc_counter_intr(ar);
+
+       ret = 0;
+
+out:
+       /* An optimization to bypass reading the IRQ status registers
+        * unecessarily which can re-wake the target, if upper layers
+        * determine that we are in a low-throughput mode, we can rely on
+        * taking another interrupt rather than re-checking the status
+        * registers which can re-wake the target.
+        *
+        * NOTE : for host interfaces that makes use of detecting pending
+        * mbox messages at hif can not use this optimization due to
+        * possible side effects, SPI requires the host to drain all
+        * messages from the mailbox before exiting the ISR routine.
+        */
+
+       ath10k_dbg(ar, ATH10K_DBG_SDIO,
+                  "sdio pending irqs done %d status %d",
+                  *done, ret);
+
+       return ret;
+}
+
+static void ath10k_sdio_set_mbox_info(struct ath10k *ar)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct ath10k_mbox_info *mbox_info = &ar_sdio->mbox_info;
+       u16 device = ar_sdio->func->device, dev_id_base, dev_id_chiprev;
+
+       mbox_info->htc_addr = ATH10K_HIF_MBOX_BASE_ADDR;
+       mbox_info->block_size = ATH10K_HIF_MBOX_BLOCK_SIZE;
+       mbox_info->block_mask = ATH10K_HIF_MBOX_BLOCK_SIZE - 1;
+       mbox_info->gmbox_addr = ATH10K_HIF_GMBOX_BASE_ADDR;
+       mbox_info->gmbox_sz = ATH10K_HIF_GMBOX_WIDTH;
+
+       mbox_info->ext_info[0].htc_ext_addr = ATH10K_HIF_MBOX0_EXT_BASE_ADDR;
+
+       dev_id_base = FIELD_GET(QCA_MANUFACTURER_ID_BASE, device);
+       dev_id_chiprev = FIELD_GET(QCA_MANUFACTURER_ID_REV_MASK, device);
+       switch (dev_id_base) {
+       case QCA_MANUFACTURER_ID_AR6005_BASE:
+               if (dev_id_chiprev < 4)
+                       mbox_info->ext_info[0].htc_ext_sz =
+                               ATH10K_HIF_MBOX0_EXT_WIDTH;
+               else
+                       /* from QCA6174 2.0(0x504), the width has been extended
+                        * to 56K
+                        */
+                       mbox_info->ext_info[0].htc_ext_sz =
+                               ATH10K_HIF_MBOX0_EXT_WIDTH_ROME_2_0;
+               break;
+       case QCA_MANUFACTURER_ID_QCA9377_BASE:
+               mbox_info->ext_info[0].htc_ext_sz =
+                       ATH10K_HIF_MBOX0_EXT_WIDTH_ROME_2_0;
+               break;
+       default:
+               mbox_info->ext_info[0].htc_ext_sz =
+                               ATH10K_HIF_MBOX0_EXT_WIDTH;
+       }
+
+       mbox_info->ext_info[1].htc_ext_addr =
+               mbox_info->ext_info[0].htc_ext_addr +
+               mbox_info->ext_info[0].htc_ext_sz +
+               ATH10K_HIF_MBOX_DUMMY_SPACE_SIZE;
+       mbox_info->ext_info[1].htc_ext_sz = ATH10K_HIF_MBOX1_EXT_WIDTH;
+}
+
+/* BMI functions */
+
+static int ath10k_sdio_bmi_credits(struct ath10k *ar)
+{
+       u32 addr, cmd_credits;
+       unsigned long timeout;
+       int ret;
+
+       /* Read the counter register to get the command credits */
+       addr = MBOX_COUNT_DEC_ADDRESS + ATH10K_HIF_MBOX_NUM_MAX * 4;
+       timeout = jiffies + BMI_COMMUNICATION_TIMEOUT_HZ;
+       cmd_credits = 0;
+
+       while (time_before(jiffies, timeout) && !cmd_credits) {
+               /* Hit the credit counter with a 4-byte access, the first byte
+                * read will hit the counter and cause a decrement, while the
+                * remaining 3 bytes has no effect. The rationale behind this
+                * is to make all HIF accesses 4-byte aligned.
+                */
+               ret = ath10k_sdio_read32(ar, addr, &cmd_credits);
+               if (ret) {
+                       ath10k_warn(ar,
+                                   "unable to decrement the command credit count register: %d\n",
+                                   ret);
+                       return ret;
+               }
+
+               /* The counter is only 8 bits.
+                * Ignore anything in the upper 3 bytes
+                */
+               cmd_credits &= 0xFF;
+       }
+
+       if (!cmd_credits) {
+               ath10k_warn(ar, "bmi communication timeout\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int ath10k_sdio_bmi_get_rx_lookahead(struct ath10k *ar)
+{
+       unsigned long timeout;
+       u32 rx_word;
+       int ret;
+
+       timeout = jiffies + BMI_COMMUNICATION_TIMEOUT_HZ;
+       rx_word = 0;
+
+       while ((time_before(jiffies, timeout)) && !rx_word) {
+               ret = ath10k_sdio_read32(ar,
+                                        MBOX_HOST_INT_STATUS_ADDRESS,
+                                        &rx_word);
+               if (ret) {
+                       ath10k_warn(ar, "unable to read RX_LOOKAHEAD_VALID: %d\n", ret);
+                       return ret;
+               }
+
+                /* all we really want is one bit */
+               rx_word &= 1;
+       }
+
+       if (!rx_word) {
+               ath10k_warn(ar, "bmi_recv_buf FIFO empty\n");
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+static int ath10k_sdio_bmi_exchange_msg(struct ath10k *ar,
+                                       void *req, u32 req_len,
+                                       void *resp, u32 *resp_len)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       u32 addr;
+       int ret;
+
+       if (req) {
+               ret = ath10k_sdio_bmi_credits(ar);
+               if (ret)
+                       return ret;
+
+               addr = ar_sdio->mbox_info.htc_addr;
+
+               memcpy(ar_sdio->bmi_buf, req, req_len);
+               ret = ath10k_sdio_write(ar, addr, ar_sdio->bmi_buf, req_len);
+               if (ret) {
+                       ath10k_warn(ar,
+                                   "unable to send the bmi data to the device: %d\n",
+                                   ret);
+                       return ret;
+               }
+       }
+
+       if (!resp || !resp_len)
+               /* No response expected */
+               return 0;
+
+       /* During normal bootup, small reads may be required.
+        * Rather than issue an HIF Read and then wait as the Target
+        * adds successive bytes to the FIFO, we wait here until
+        * we know that response data is available.
+        *
+        * This allows us to cleanly timeout on an unexpected
+        * Target failure rather than risk problems at the HIF level.
+        * In particular, this avoids SDIO timeouts and possibly garbage
+        * data on some host controllers.  And on an interconnect
+        * such as Compact Flash (as well as some SDIO masters) which
+        * does not provide any indication on data timeout, it avoids
+        * a potential hang or garbage response.
+        *
+        * Synchronization is more difficult for reads larger than the
+        * size of the MBOX FIFO (128B), because the Target is unable
+        * to push the 129th byte of data until AFTER the Host posts an
+        * HIF Read and removes some FIFO data.  So for large reads the
+        * Host proceeds to post an HIF Read BEFORE all the data is
+        * actually available to read.  Fortunately, large BMI reads do
+        * not occur in practice -- they're supported for debug/development.
+        *
+        * So Host/Target BMI synchronization is divided into these cases:
+        *  CASE 1: length < 4
+        *        Should not happen
+        *
+        *  CASE 2: 4 <= length <= 128
+        *        Wait for first 4 bytes to be in FIFO
+        *        If CONSERVATIVE_BMI_READ is enabled, also wait for
+        *        a BMI command credit, which indicates that the ENTIRE
+        *        response is available in the the FIFO
+        *
+        *  CASE 3: length > 128
+        *        Wait for the first 4 bytes to be in FIFO
+        *
+        * For most uses, a small timeout should be sufficient and we will
+        * usually see a response quickly; but there may be some unusual
+        * (debug) cases of BMI_EXECUTE where we want an larger timeout.
+        * For now, we use an unbounded busy loop while waiting for
+        * BMI_EXECUTE.
+        *
+        * If BMI_EXECUTE ever needs to support longer-latency execution,
+        * especially in production, this code needs to be enhanced to sleep
+        * and yield.  Also note that BMI_COMMUNICATION_TIMEOUT is currently
+        * a function of Host processor speed.
+        */
+       ret = ath10k_sdio_bmi_get_rx_lookahead(ar);
+       if (ret)
+               return ret;
+
+       /* We always read from the start of the mbox address */
+       addr = ar_sdio->mbox_info.htc_addr;
+       ret = ath10k_sdio_read(ar, addr, ar_sdio->bmi_buf, *resp_len);
+       if (ret) {
+               ath10k_warn(ar,
+                           "unable to read the bmi data from the device: %d\n",
+                           ret);
+               return ret;
+       }
+
+       memcpy(resp, ar_sdio->bmi_buf, *resp_len);
+
+       return 0;
+}
+
+/* sdio async handling functions */
+
+static struct ath10k_sdio_bus_request
+*ath10k_sdio_alloc_busreq(struct ath10k *ar)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct ath10k_sdio_bus_request *bus_req;
+
+       spin_lock_bh(&ar_sdio->lock);
+
+       if (list_empty(&ar_sdio->bus_req_freeq)) {
+               bus_req = NULL;
+               goto out;
+       }
+
+       bus_req = list_first_entry(&ar_sdio->bus_req_freeq,
+                                  struct ath10k_sdio_bus_request, list);
+       list_del(&bus_req->list);
+
+out:
+       spin_unlock_bh(&ar_sdio->lock);
+       return bus_req;
+}
+
+static void ath10k_sdio_free_bus_req(struct ath10k *ar,
+                                    struct ath10k_sdio_bus_request *bus_req)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+
+       memset(bus_req, 0, sizeof(*bus_req));
+
+       spin_lock_bh(&ar_sdio->lock);
+       list_add_tail(&bus_req->list, &ar_sdio->bus_req_freeq);
+       spin_unlock_bh(&ar_sdio->lock);
+}
+
+static void __ath10k_sdio_write_async(struct ath10k *ar,
+                                     struct ath10k_sdio_bus_request *req)
+{
+       struct ath10k_htc_ep *ep;
+       struct sk_buff *skb;
+       int ret;
+
+       skb = req->skb;
+       ret = ath10k_sdio_write(ar, req->address, skb->data, skb->len);
+       if (ret)
+               ath10k_warn(ar, "failed to write skb to 0x%x asynchronously: %d",
+                           req->address, ret);
+
+       if (req->htc_msg) {
+               ep = &ar->htc.endpoint[req->eid];
+               ath10k_htc_notify_tx_completion(ep, skb);
+       } else if (req->comp) {
+               complete(req->comp);
+       }
+
+       ath10k_sdio_free_bus_req(ar, req);
+}
+
+static void ath10k_sdio_write_async_work(struct work_struct *work)
+{
+       struct ath10k_sdio *ar_sdio = container_of(work, struct ath10k_sdio,
+                                                  wr_async_work);
+       struct ath10k *ar = ar_sdio->ar;
+       struct ath10k_sdio_bus_request *req, *tmp_req;
+
+       spin_lock_bh(&ar_sdio->wr_async_lock);
+
+       list_for_each_entry_safe(req, tmp_req, &ar_sdio->wr_asyncq, list) {
+               list_del(&req->list);
+               spin_unlock_bh(&ar_sdio->wr_async_lock);
+               __ath10k_sdio_write_async(ar, req);
+               spin_lock_bh(&ar_sdio->wr_async_lock);
+       }
+
+       spin_unlock_bh(&ar_sdio->wr_async_lock);
+}
+
+static int ath10k_sdio_prep_async_req(struct ath10k *ar, u32 addr,
+                                     struct sk_buff *skb,
+                                     struct completion *comp,
+                                     bool htc_msg, enum ath10k_htc_ep_id eid)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct ath10k_sdio_bus_request *bus_req;
+
+       /* Allocate a bus request for the message and queue it on the
+        * SDIO workqueue.
+        */
+       bus_req = ath10k_sdio_alloc_busreq(ar);
+       if (!bus_req) {
+               ath10k_warn(ar,
+                           "unable to allocate bus request for async request\n");
+               return -ENOMEM;
+       }
+
+       bus_req->skb = skb;
+       bus_req->eid = eid;
+       bus_req->address = addr;
+       bus_req->htc_msg = htc_msg;
+       bus_req->comp = comp;
+
+       spin_lock_bh(&ar_sdio->wr_async_lock);
+       list_add_tail(&bus_req->list, &ar_sdio->wr_asyncq);
+       spin_unlock_bh(&ar_sdio->wr_async_lock);
+
+       return 0;
+}
+
+/* IRQ handler */
+
+static void ath10k_sdio_irq_handler(struct sdio_func *func)
+{
+       struct ath10k_sdio *ar_sdio = sdio_get_drvdata(func);
+       struct ath10k *ar = ar_sdio->ar;
+       unsigned long timeout;
+       bool done = false;
+       int ret;
+
+       /* Release the host during interrupts so we can pick it back up when
+        * we process commands.
+        */
+       sdio_release_host(ar_sdio->func);
+
+       timeout = jiffies + ATH10K_SDIO_HIF_COMMUNICATION_TIMEOUT_HZ;
+       while (time_before(jiffies, timeout) && !done) {
+               ret = ath10k_sdio_mbox_proc_pending_irqs(ar, &done);
+               if (ret)
+                       break;
+       }
+
+       sdio_claim_host(ar_sdio->func);
+
+       wake_up(&ar_sdio->irq_wq);
+
+       if (ret && ret != -ECANCELED)
+               ath10k_warn(ar, "failed to process pending SDIO interrupts: %d\n",
+                           ret);
+}
+
+/* sdio HIF functions */
+
+static int ath10k_sdio_hif_disable_intrs(struct ath10k *ar)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+       struct ath10k_sdio_irq_enable_regs *regs = irq_data->irq_en_reg;
+       int ret;
+
+       mutex_lock(&irq_data->mtx);
+
+       memset(regs, 0, sizeof(*regs));
+       ret = ath10k_sdio_write(ar, MBOX_INT_STATUS_ENABLE_ADDRESS,
+                               &regs->int_status_en, sizeof(*regs));
+       if (ret)
+               ath10k_warn(ar, "unable to disable sdio interrupts: %d\n", ret);
+
+       mutex_unlock(&irq_data->mtx);
+
+       return ret;
+}
+
+static int ath10k_sdio_hif_power_up(struct ath10k *ar)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct sdio_func *func = ar_sdio->func;
+       int ret;
+
+       if (!ar_sdio->is_disabled)
+               return 0;
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio power on\n");
+
+       sdio_claim_host(func);
+
+       ret = sdio_enable_func(func);
+       if (ret) {
+               ath10k_warn(ar, "unable to enable sdio function: %d)\n", ret);
+               sdio_release_host(func);
+               return ret;
+       }
+
+       sdio_release_host(func);
+
+       /* Wait for hardware to initialise. It should take a lot less than
+        * 20 ms but let's be conservative here.
+        */
+       msleep(20);
+
+       ar_sdio->is_disabled = false;
+
+       ret = ath10k_sdio_hif_disable_intrs(ar);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static void ath10k_sdio_hif_power_down(struct ath10k *ar)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       int ret;
+
+       if (ar_sdio->is_disabled)
+               return;
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio power off\n");
+
+       /* Disable the card */
+       sdio_claim_host(ar_sdio->func);
+       ret = sdio_disable_func(ar_sdio->func);
+       sdio_release_host(ar_sdio->func);
+
+       if (ret)
+               ath10k_warn(ar, "unable to disable sdio function: %d\n", ret);
+
+       ar_sdio->is_disabled = true;
+}
+
+static int ath10k_sdio_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
+                                struct ath10k_hif_sg_item *items, int n_items)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       enum ath10k_htc_ep_id eid;
+       struct sk_buff *skb;
+       int ret, i;
+
+       eid = pipe_id_to_eid(pipe_id);
+
+       for (i = 0; i < n_items; i++) {
+               size_t padded_len;
+               u32 address;
+
+               skb = items[i].transfer_context;
+               padded_len = ath10k_sdio_calc_txrx_padded_len(ar_sdio,
+                                                             skb->len);
+               skb_trim(skb, padded_len);
+
+               /* Write TX data to the end of the mbox address space */
+               address = ar_sdio->mbox_addr[eid] + ar_sdio->mbox_size[eid] -
+                         skb->len;
+               ret = ath10k_sdio_prep_async_req(ar, address, skb,
+                                                NULL, true, eid);
+               if (ret)
+                       return ret;
+       }
+
+       queue_work(ar_sdio->workqueue, &ar_sdio->wr_async_work);
+
+       return 0;
+}
+
+static int ath10k_sdio_hif_enable_intrs(struct ath10k *ar)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+       struct ath10k_sdio_irq_enable_regs *regs = irq_data->irq_en_reg;
+       int ret;
+
+       mutex_lock(&irq_data->mtx);
+
+       /* Enable all but CPU interrupts */
+       regs->int_status_en = FIELD_PREP(MBOX_INT_STATUS_ENABLE_ERROR_MASK, 1) |
+                             FIELD_PREP(MBOX_INT_STATUS_ENABLE_CPU_MASK, 1) |
+                             FIELD_PREP(MBOX_INT_STATUS_ENABLE_COUNTER_MASK, 1);
+
+       /* NOTE: There are some cases where HIF can do detection of
+        * pending mbox messages which is disabled now.
+        */
+       regs->int_status_en |=
+               FIELD_PREP(MBOX_INT_STATUS_ENABLE_MBOX_DATA_MASK, 1);
+
+       /* Set up the CPU Interrupt status Register */
+       regs->cpu_int_status_en = 0;
+
+       /* Set up the Error Interrupt status Register */
+       regs->err_int_status_en =
+               FIELD_PREP(MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, 1) |
+               FIELD_PREP(MBOX_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, 1);
+
+       /* Enable Counter interrupt status register to get fatal errors for
+        * debugging.
+        */
+       regs->cntr_int_status_en =
+               FIELD_PREP(MBOX_COUNTER_INT_STATUS_ENABLE_BIT_MASK,
+                          ATH10K_SDIO_TARGET_DEBUG_INTR_MASK);
+
+       ret = ath10k_sdio_write(ar, MBOX_INT_STATUS_ENABLE_ADDRESS,
+                               &regs->int_status_en, sizeof(*regs));
+       if (ret)
+               ath10k_warn(ar,
+                           "failed to update mbox interrupt status register : %d\n",
+                           ret);
+
+       mutex_unlock(&irq_data->mtx);
+       return ret;
+}
+
+static int ath10k_sdio_hif_set_mbox_sleep(struct ath10k *ar, bool enable_sleep)
+{
+       u32 val;
+       int ret;
+
+       ret = ath10k_sdio_read32(ar, ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL, &val);
+       if (ret) {
+               ath10k_warn(ar, "failed to read fifo/chip control register: %d\n",
+                           ret);
+               return ret;
+       }
+
+       if (enable_sleep)
+               val &= ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF;
+       else
+               val |= ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON;
+
+       ret = ath10k_sdio_write32(ar, ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL, val);
+       if (ret) {
+               ath10k_warn(ar, "failed to write to FIFO_TIMEOUT_AND_CHIP_CONTROL: %d",
+                           ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+/* HIF diagnostics */
+
+static int ath10k_sdio_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
+                                    size_t buf_len)
+{
+       int ret;
+
+       /* set window register to start read cycle */
+       ret = ath10k_sdio_write32(ar, MBOX_WINDOW_READ_ADDR_ADDRESS, address);
+       if (ret) {
+               ath10k_warn(ar, "failed to set mbox window read address: %d", ret);
+               return ret;
+       }
+
+       /* read the data */
+       ret = ath10k_sdio_read(ar, MBOX_WINDOW_DATA_ADDRESS, buf, buf_len);
+       if (ret) {
+               ath10k_warn(ar, "failed to read from mbox window data addrress: %d\n",
+                           ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int ath10k_sdio_hif_diag_read32(struct ath10k *ar, u32 address,
+                                      u32 *value)
+{
+       __le32 *val;
+       int ret;
+
+       val = kzalloc(sizeof(*val), GFP_KERNEL);
+       if (!val)
+               return -ENOMEM;
+
+       ret = ath10k_sdio_hif_diag_read(ar, address, val, sizeof(*val));
+       if (ret)
+               goto out;
+
+       *value = __le32_to_cpu(*val);
+
+out:
+       kfree(val);
+
+       return ret;
+}
+
+static int ath10k_sdio_hif_diag_write_mem(struct ath10k *ar, u32 address,
+                                         const void *data, int nbytes)
+{
+       int ret;
+
+       /* set write data */
+       ret = ath10k_sdio_write(ar, MBOX_WINDOW_DATA_ADDRESS, data, nbytes);
+       if (ret) {
+               ath10k_warn(ar,
+                           "failed to write 0x%p to mbox window data addrress: %d\n",
+                           data, ret);
+               return ret;
+       }
+
+       /* set window register, which starts the write cycle */
+       ret = ath10k_sdio_write32(ar, MBOX_WINDOW_WRITE_ADDR_ADDRESS, address);
+       if (ret) {
+               ath10k_warn(ar, "failed to set mbox window write address: %d", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+/* HIF start/stop */
+
+static int ath10k_sdio_hif_start(struct ath10k *ar)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       u32 addr, val;
+       int ret;
+
+       /* Sleep 20 ms before HIF interrupts are disabled.
+        * This will give target plenty of time to process the BMI done
+        * request before interrupts are disabled.
+        */
+       msleep(20);
+       ret = ath10k_sdio_hif_disable_intrs(ar);
+       if (ret)
+               return ret;
+
+       /* eid 0 always uses the lower part of the extended mailbox address
+        * space (ext_info[0].htc_ext_addr).
+        */
+       ar_sdio->mbox_addr[0] = ar_sdio->mbox_info.ext_info[0].htc_ext_addr;
+       ar_sdio->mbox_size[0] = ar_sdio->mbox_info.ext_info[0].htc_ext_sz;
+
+       sdio_claim_host(ar_sdio->func);
+
+       /* Register the isr */
+       ret =  sdio_claim_irq(ar_sdio->func, ath10k_sdio_irq_handler);
+       if (ret) {
+               ath10k_warn(ar, "failed to claim sdio interrupt: %d\n", ret);
+               sdio_release_host(ar_sdio->func);
+               return ret;
+       }
+
+       sdio_release_host(ar_sdio->func);
+
+       ret = ath10k_sdio_hif_enable_intrs(ar);
+       if (ret)
+               ath10k_warn(ar, "failed to enable sdio interrupts: %d\n", ret);
+
+       addr = host_interest_item_address(HI_ITEM(hi_acs_flags));
+
+       ret = ath10k_sdio_hif_diag_read32(ar, addr, &val);
+       if (ret) {
+               ath10k_warn(ar, "unable to read hi_acs_flags address: %d\n", ret);
+               return ret;
+       }
+
+       if (val & HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_FW_ACK) {
+               ath10k_dbg(ar, ATH10K_DBG_SDIO,
+                          "sdio mailbox swap service enabled\n");
+               ar_sdio->swap_mbox = true;
+       }
+
+       /* Enable sleep and then disable it again */
+       ret = ath10k_sdio_hif_set_mbox_sleep(ar, true);
+       if (ret)
+               return ret;
+
+       /* Wait for 20ms for the written value to take effect */
+       msleep(20);
+
+       ret = ath10k_sdio_hif_set_mbox_sleep(ar, false);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+#define SDIO_IRQ_DISABLE_TIMEOUT_HZ (3 * HZ)
+
+static void ath10k_sdio_irq_disable(struct ath10k *ar)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct ath10k_sdio_irq_data *irq_data = &ar_sdio->irq_data;
+       struct ath10k_sdio_irq_enable_regs *regs = irq_data->irq_en_reg;
+       struct sk_buff *skb;
+       struct completion irqs_disabled_comp;
+       int ret;
+
+       skb = dev_alloc_skb(sizeof(*regs));
+       if (!skb)
+               return;
+
+       mutex_lock(&irq_data->mtx);
+
+       memset(regs, 0, sizeof(*regs)); /* disable all interrupts */
+       memcpy(skb->data, regs, sizeof(*regs));
+       skb_put(skb, sizeof(*regs));
+
+       mutex_unlock(&irq_data->mtx);
+
+       init_completion(&irqs_disabled_comp);
+       ret = ath10k_sdio_prep_async_req(ar, MBOX_INT_STATUS_ENABLE_ADDRESS,
+                                        skb, &irqs_disabled_comp, false, 0);
+       if (ret)
+               goto out;
+
+       queue_work(ar_sdio->workqueue, &ar_sdio->wr_async_work);
+
+       /* Wait for the completion of the IRQ disable request.
+        * If there is a timeout we will try to disable irq's anyway.
+        */
+       ret = wait_for_completion_timeout(&irqs_disabled_comp,
+                                         SDIO_IRQ_DISABLE_TIMEOUT_HZ);
+       if (!ret)
+               ath10k_warn(ar, "sdio irq disable request timed out\n");
+
+       sdio_claim_host(ar_sdio->func);
+
+       ret = sdio_release_irq(ar_sdio->func);
+       if (ret)
+               ath10k_warn(ar, "failed to release sdio interrupt: %d\n", ret);
+
+       sdio_release_host(ar_sdio->func);
+
+out:
+       kfree_skb(skb);
+}
+
+static void ath10k_sdio_hif_stop(struct ath10k *ar)
+{
+       struct ath10k_sdio_bus_request *req, *tmp_req;
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+
+       ath10k_sdio_irq_disable(ar);
+
+       cancel_work_sync(&ar_sdio->wr_async_work);
+
+       spin_lock_bh(&ar_sdio->wr_async_lock);
+
+       /* Free all bus requests that have not been handled */
+       list_for_each_entry_safe(req, tmp_req, &ar_sdio->wr_asyncq, list) {
+               struct ath10k_htc_ep *ep;
+
+               list_del(&req->list);
+
+               if (req->htc_msg) {
+                       ep = &ar->htc.endpoint[req->eid];
+                       ath10k_htc_notify_tx_completion(ep, req->skb);
+               } else if (req->skb) {
+                       kfree_skb(req->skb);
+               }
+               ath10k_sdio_free_bus_req(ar, req);
+       }
+
+       spin_unlock_bh(&ar_sdio->wr_async_lock);
+}
+
+#ifdef CONFIG_PM
+
+static int ath10k_sdio_hif_suspend(struct ath10k *ar)
+{
+       return -EOPNOTSUPP;
+}
+
+static int ath10k_sdio_hif_resume(struct ath10k *ar)
+{
+       switch (ar->state) {
+       case ATH10K_STATE_OFF:
+               ath10k_dbg(ar, ATH10K_DBG_SDIO,
+                          "sdio resume configuring sdio\n");
+
+               /* need to set sdio settings after power is cut from sdio */
+               ath10k_sdio_config(ar);
+               break;
+
+       case ATH10K_STATE_ON:
+       default:
+               break;
+       }
+
+       return 0;
+}
+#endif
+
+static int ath10k_sdio_hif_map_service_to_pipe(struct ath10k *ar,
+                                              u16 service_id,
+                                              u8 *ul_pipe, u8 *dl_pipe)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       struct ath10k_htc *htc = &ar->htc;
+       u32 htt_addr, wmi_addr, htt_mbox_size, wmi_mbox_size;
+       enum ath10k_htc_ep_id eid;
+       bool ep_found = false;
+       int i;
+
+       /* For sdio, we are interested in the mapping between eid
+        * and pipeid rather than service_id to pipe_id.
+        * First we find out which eid has been allocated to the
+        * service...
+        */
+       for (i = 0; i < ATH10K_HTC_EP_COUNT; i++) {
+               if (htc->endpoint[i].service_id == service_id) {
+                       eid = htc->endpoint[i].eid;
+                       ep_found = true;
+                       break;
+               }
+       }
+
+       if (!ep_found)
+               return -EINVAL;
+
+       /* Then we create the simplest mapping possible between pipeid
+        * and eid
+        */
+       *ul_pipe = *dl_pipe = (u8)eid;
+
+       /* Normally, HTT will use the upper part of the extended
+        * mailbox address space (ext_info[1].htc_ext_addr) and WMI ctrl
+        * the lower part (ext_info[0].htc_ext_addr).
+        * If fw wants swapping of mailbox addresses, the opposite is true.
+        */
+       if (ar_sdio->swap_mbox) {
+               htt_addr = ar_sdio->mbox_info.ext_info[0].htc_ext_addr;
+               wmi_addr = ar_sdio->mbox_info.ext_info[1].htc_ext_addr;
+               htt_mbox_size = ar_sdio->mbox_info.ext_info[0].htc_ext_sz;
+               wmi_mbox_size = ar_sdio->mbox_info.ext_info[1].htc_ext_sz;
+       } else {
+               htt_addr = ar_sdio->mbox_info.ext_info[1].htc_ext_addr;
+               wmi_addr = ar_sdio->mbox_info.ext_info[0].htc_ext_addr;
+               htt_mbox_size = ar_sdio->mbox_info.ext_info[1].htc_ext_sz;
+               wmi_mbox_size = ar_sdio->mbox_info.ext_info[0].htc_ext_sz;
+       }
+
+       switch (service_id) {
+       case ATH10K_HTC_SVC_ID_RSVD_CTRL:
+               /* HTC ctrl ep mbox address has already been setup in
+                * ath10k_sdio_hif_start
+                */
+               break;
+       case ATH10K_HTC_SVC_ID_WMI_CONTROL:
+               ar_sdio->mbox_addr[eid] = wmi_addr;
+               ar_sdio->mbox_size[eid] = wmi_mbox_size;
+               ath10k_dbg(ar, ATH10K_DBG_SDIO,
+                          "sdio wmi ctrl mbox_addr 0x%x mbox_size %d\n",
+                          ar_sdio->mbox_addr[eid], ar_sdio->mbox_size[eid]);
+               break;
+       case ATH10K_HTC_SVC_ID_HTT_DATA_MSG:
+               ar_sdio->mbox_addr[eid] = htt_addr;
+               ar_sdio->mbox_size[eid] = htt_mbox_size;
+               ath10k_dbg(ar, ATH10K_DBG_SDIO,
+                          "sdio htt data mbox_addr 0x%x mbox_size %d\n",
+                          ar_sdio->mbox_addr[eid], ar_sdio->mbox_size[eid]);
+               break;
+       default:
+               ath10k_warn(ar, "unsupported HTC service id: %d\n",
+                           service_id);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void ath10k_sdio_hif_get_default_pipe(struct ath10k *ar,
+                                            u8 *ul_pipe, u8 *dl_pipe)
+{
+       ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio hif get default pipe\n");
+
+       /* HTC ctrl ep (SVC id 1) always has eid (and pipe_id in our
+        * case) == 0
+        */
+       *ul_pipe = 0;
+       *dl_pipe = 0;
+}
+
+/* This op is currently only used by htc_wait_target if the HTC ready
+ * message times out. It is not applicable for SDIO since there is nothing
+ * we can do if the HTC ready message does not arrive in time.
+ * TODO: Make this op non mandatory by introducing a NULL check in the
+ * hif op wrapper.
+ */
+static void ath10k_sdio_hif_send_complete_check(struct ath10k *ar,
+                                               u8 pipe, int force)
+{
+}
+
+static const struct ath10k_hif_ops ath10k_sdio_hif_ops = {
+       .tx_sg                  = ath10k_sdio_hif_tx_sg,
+       .diag_read              = ath10k_sdio_hif_diag_read,
+       .diag_write             = ath10k_sdio_hif_diag_write_mem,
+       .exchange_bmi_msg       = ath10k_sdio_bmi_exchange_msg,
+       .start                  = ath10k_sdio_hif_start,
+       .stop                   = ath10k_sdio_hif_stop,
+       .map_service_to_pipe    = ath10k_sdio_hif_map_service_to_pipe,
+       .get_default_pipe       = ath10k_sdio_hif_get_default_pipe,
+       .send_complete_check    = ath10k_sdio_hif_send_complete_check,
+       .power_up               = ath10k_sdio_hif_power_up,
+       .power_down             = ath10k_sdio_hif_power_down,
+#ifdef CONFIG_PM
+       .suspend                = ath10k_sdio_hif_suspend,
+       .resume                 = ath10k_sdio_hif_resume,
+#endif
+};
+
+#ifdef CONFIG_PM_SLEEP
+
+/* Empty handlers so that mmc subsystem doesn't remove us entirely during
+ * suspend. We instead follow cfg80211 suspend/resume handlers.
+ */
+static int ath10k_sdio_pm_suspend(struct device *device)
+{
+       return 0;
+}
+
+static int ath10k_sdio_pm_resume(struct device *device)
+{
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(ath10k_sdio_pm_ops, ath10k_sdio_pm_suspend,
+                        ath10k_sdio_pm_resume);
+
+#define ATH10K_SDIO_PM_OPS (&ath10k_sdio_pm_ops)
+
+#else
+
+#define ATH10K_SDIO_PM_OPS NULL
+
+#endif /* CONFIG_PM_SLEEP */
+
+static int ath10k_sdio_probe(struct sdio_func *func,
+                            const struct sdio_device_id *id)
+{
+       struct ath10k_sdio *ar_sdio;
+       struct ath10k *ar;
+       enum ath10k_hw_rev hw_rev;
+       u32 chip_id, dev_id_base;
+       int ret, i;
+
+       /* Assumption: All SDIO based chipsets (so far) are QCA6174 based.
+        * If there will be newer chipsets that does not use the hw reg
+        * setup as defined in qca6174_regs and qca6174_values, this
+        * assumption is no longer valid and hw_rev must be setup differently
+        * depending on chipset.
+        */
+       hw_rev = ATH10K_HW_QCA6174;
+
+       ar = ath10k_core_create(sizeof(*ar_sdio), &func->dev, ATH10K_BUS_SDIO,
+                               hw_rev, &ath10k_sdio_hif_ops);
+       if (!ar) {
+               dev_err(&func->dev, "failed to allocate core\n");
+               return -ENOMEM;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                  "sdio new func %d vendor 0x%x device 0x%x block 0x%x/0x%x\n",
+                  func->num, func->vendor, func->device,
+                  func->max_blksize, func->cur_blksize);
+
+       ar_sdio = ath10k_sdio_priv(ar);
+
+       ar_sdio->irq_data.irq_proc_reg =
+               kzalloc(sizeof(struct ath10k_sdio_irq_proc_regs),
+                       GFP_KERNEL);
+       if (!ar_sdio->irq_data.irq_proc_reg) {
+               ret = -ENOMEM;
+               goto err_core_destroy;
+       }
+
+       ar_sdio->irq_data.irq_en_reg =
+               kzalloc(sizeof(struct ath10k_sdio_irq_enable_regs),
+                       GFP_KERNEL);
+       if (!ar_sdio->irq_data.irq_en_reg) {
+               ret = -ENOMEM;
+               goto err_free_proc_reg;
+       }
+
+       ar_sdio->bmi_buf = kzalloc(BMI_MAX_CMDBUF_SIZE, GFP_KERNEL);
+       if (!ar_sdio->bmi_buf) {
+               ret = -ENOMEM;
+               goto err_free_en_reg;
+       }
+
+       ar_sdio->func = func;
+       sdio_set_drvdata(func, ar_sdio);
+
+       ar_sdio->is_disabled = true;
+       ar_sdio->ar = ar;
+
+       spin_lock_init(&ar_sdio->lock);
+       spin_lock_init(&ar_sdio->wr_async_lock);
+       mutex_init(&ar_sdio->irq_data.mtx);
+
+       INIT_LIST_HEAD(&ar_sdio->bus_req_freeq);
+       INIT_LIST_HEAD(&ar_sdio->wr_asyncq);
+
+       INIT_WORK(&ar_sdio->wr_async_work, ath10k_sdio_write_async_work);
+       ar_sdio->workqueue = create_singlethread_workqueue("ath10k_sdio_wq");
+       if (!ar_sdio->workqueue) {
+               ret = -ENOMEM;
+               goto err_free_bmi_buf;
+       }
+
+       init_waitqueue_head(&ar_sdio->irq_wq);
+
+       for (i = 0; i < ATH10K_SDIO_BUS_REQUEST_MAX_NUM; i++)
+               ath10k_sdio_free_bus_req(ar, &ar_sdio->bus_req[i]);
+
+       dev_id_base = FIELD_GET(QCA_MANUFACTURER_ID_BASE, id->device);
+       switch (dev_id_base) {
+       case QCA_MANUFACTURER_ID_AR6005_BASE:
+       case QCA_MANUFACTURER_ID_QCA9377_BASE:
+               ar->dev_id = QCA9377_1_0_DEVICE_ID;
+               break;
+       default:
+               ret = -ENODEV;
+               ath10k_err(ar, "unsupported device id %u (0x%x)\n",
+                          dev_id_base, id->device);
+               goto err_free_bmi_buf;
+       }
+
+       ar->id.vendor = id->vendor;
+       ar->id.device = id->device;
+
+       ath10k_sdio_set_mbox_info(ar);
+
+       ret = ath10k_sdio_config(ar);
+       if (ret) {
+               ath10k_err(ar, "failed to config sdio: %d\n", ret);
+               goto err_free_wq;
+       }
+
+       /* TODO: don't know yet how to get chip_id with SDIO */
+       chip_id = 0;
+       ret = ath10k_core_register(ar, chip_id);
+       if (ret) {
+               ath10k_err(ar, "failed to register driver core: %d\n", ret);
+               goto err_free_wq;
+       }
+
+       /* TODO: remove this once SDIO support is fully implemented */
+       ath10k_warn(ar, "WARNING: ath10k SDIO support is incomplete, don't expect anything to work!\n");
+
+       return 0;
+
+err_free_wq:
+       destroy_workqueue(ar_sdio->workqueue);
+err_free_bmi_buf:
+       kfree(ar_sdio->bmi_buf);
+err_free_en_reg:
+       kfree(ar_sdio->irq_data.irq_en_reg);
+err_free_proc_reg:
+       kfree(ar_sdio->irq_data.irq_proc_reg);
+err_core_destroy:
+       ath10k_core_destroy(ar);
+
+       return ret;
+}
+
+static void ath10k_sdio_remove(struct sdio_func *func)
+{
+       struct ath10k_sdio *ar_sdio = sdio_get_drvdata(func);
+       struct ath10k *ar = ar_sdio->ar;
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                  "sdio removed func %d vendor 0x%x device 0x%x\n",
+                  func->num, func->vendor, func->device);
+
+       (void)ath10k_sdio_hif_disable_intrs(ar);
+       cancel_work_sync(&ar_sdio->wr_async_work);
+       ath10k_core_unregister(ar);
+       ath10k_core_destroy(ar);
+}
+
+static const struct sdio_device_id ath10k_sdio_devices[] = {
+       {SDIO_DEVICE(QCA_MANUFACTURER_CODE,
+                    (QCA_SDIO_ID_AR6005_BASE | 0xA))},
+       {SDIO_DEVICE(QCA_MANUFACTURER_CODE,
+                    (QCA_SDIO_ID_QCA9377_BASE | 0x1))},
+       {},
+};
+
+MODULE_DEVICE_TABLE(sdio, ath10k_sdio_devices);
+
+static struct sdio_driver ath10k_sdio_driver = {
+       .name = "ath10k_sdio",
+       .id_table = ath10k_sdio_devices,
+       .probe = ath10k_sdio_probe,
+       .remove = ath10k_sdio_remove,
+       .drv.pm = ATH10K_SDIO_PM_OPS,
+};
+
+static int __init ath10k_sdio_init(void)
+{
+       int ret;
+
+       ret = sdio_register_driver(&ath10k_sdio_driver);
+       if (ret)
+               pr_err("sdio driver registration failed: %d\n", ret);
+
+       return ret;
+}
+
+static void __exit ath10k_sdio_exit(void)
+{
+       sdio_unregister_driver(&ath10k_sdio_driver);
+}
+
+module_init(ath10k_sdio_init);
+module_exit(ath10k_sdio_exit);
+
+MODULE_AUTHOR("Qualcomm Atheros");
+MODULE_DESCRIPTION("Driver support for Qualcomm Atheros 802.11ac WLAN SDIO devices");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/ath/ath10k/sdio.h b/drivers/net/wireless/ath/ath10k/sdio.h
new file mode 100644 (file)
index 0000000..3f61c67
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
+ * Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SDIO_H_
+#define _SDIO_H_
+
+#define ATH10K_HIF_MBOX_BLOCK_SIZE              256
+
+#define QCA_MANUFACTURER_ID_BASE                GENMASK(11, 8)
+#define QCA_MANUFACTURER_ID_AR6005_BASE         0x5
+#define QCA_MANUFACTURER_ID_QCA9377_BASE        0x7
+#define QCA_SDIO_ID_AR6005_BASE                 0x500
+#define QCA_SDIO_ID_QCA9377_BASE                0x700
+#define QCA_MANUFACTURER_ID_REV_MASK            0x00FF
+#define QCA_MANUFACTURER_CODE                   0x271 /* Qualcomm/Atheros */
+
+#define ATH10K_SDIO_MAX_BUFFER_SIZE             4096 /*Unsure of this constant*/
+
+/* Mailbox address in SDIO address space */
+#define ATH10K_HIF_MBOX_BASE_ADDR               0x1000
+#define ATH10K_HIF_MBOX_WIDTH                   0x800
+
+#define ATH10K_HIF_MBOX_TOT_WIDTH \
+       (ATH10K_HIF_MBOX_NUM_MAX * ATH10K_HIF_MBOX_WIDTH)
+
+#define ATH10K_HIF_MBOX0_EXT_BASE_ADDR          0x5000
+#define ATH10K_HIF_MBOX0_EXT_WIDTH              (36 * 1024)
+#define ATH10K_HIF_MBOX0_EXT_WIDTH_ROME_2_0     (56 * 1024)
+#define ATH10K_HIF_MBOX1_EXT_WIDTH              (36 * 1024)
+#define ATH10K_HIF_MBOX_DUMMY_SPACE_SIZE        (2 * 1024)
+
+#define ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH \
+       (ATH10K_SDIO_MAX_BUFFER_SIZE - sizeof(struct ath10k_htc_hdr))
+
+#define ATH10K_HIF_MBOX_NUM_MAX                 4
+#define ATH10K_SDIO_BUS_REQUEST_MAX_NUM         64
+
+#define ATH10K_SDIO_HIF_COMMUNICATION_TIMEOUT_HZ (100 * HZ)
+
+/* HTC runs over mailbox 0 */
+#define ATH10K_HTC_MAILBOX                      0
+#define ATH10K_HTC_MAILBOX_MASK                 BIT(ATH10K_HTC_MAILBOX)
+
+/* GMBOX addresses */
+#define ATH10K_HIF_GMBOX_BASE_ADDR              0x7000
+#define ATH10K_HIF_GMBOX_WIDTH                  0x4000
+
+/* Modified versions of the sdio.h macros.
+ * The macros in sdio.h can't be used easily with the FIELD_{PREP|GET}
+ * macros in bitfield.h, so we define our own macros here.
+ */
+#define ATH10K_SDIO_DRIVE_DTSX_MASK \
+       (SDIO_DRIVE_DTSx_MASK << SDIO_DRIVE_DTSx_SHIFT)
+
+#define ATH10K_SDIO_DRIVE_DTSX_TYPE_B           0
+#define ATH10K_SDIO_DRIVE_DTSX_TYPE_A           1
+#define ATH10K_SDIO_DRIVE_DTSX_TYPE_C           2
+#define ATH10K_SDIO_DRIVE_DTSX_TYPE_D           3
+
+/* SDIO CCCR register definitions */
+#define CCCR_SDIO_IRQ_MODE_REG                  0xF0
+#define CCCR_SDIO_IRQ_MODE_REG_SDIO3            0x16
+
+#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR   0xF2
+
+#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A      0x02
+#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C      0x04
+#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D      0x08
+
+#define CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS       0xF0
+#define CCCR_SDIO_ASYNC_INT_DELAY_MASK          0xC0
+
+/* mode to enable special 4-bit interrupt assertion without clock */
+#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ            BIT(0)
+#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_SDIO3      BIT(1)
+
+#define ATH10K_SDIO_TARGET_DEBUG_INTR_MASK      0x01
+
+/* The theoretical maximum number of RX messages that can be fetched
+ * from the mbox interrupt handler in one loop is derived in the following
+ * way:
+ *
+ * Let's assume that each packet in a bundle of the maximum bundle size
+ * (HTC_HOST_MAX_MSG_PER_BUNDLE) has the HTC header bundle count set
+ * to the maximum value (HTC_HOST_MAX_MSG_PER_BUNDLE).
+ *
+ * in this case the driver must allocate
+ * (HTC_HOST_MAX_MSG_PER_BUNDLE * HTC_HOST_MAX_MSG_PER_BUNDLE) skb's.
+ */
+#define ATH10K_SDIO_MAX_RX_MSGS \
+       (HTC_HOST_MAX_MSG_PER_BUNDLE * HTC_HOST_MAX_MSG_PER_BUNDLE)
+
+#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL   0x00000868u
+#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF 0xFFFEFFFF
+#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON 0x10000
+
+struct ath10k_sdio_bus_request {
+       struct list_head list;
+
+       /* sdio address */
+       u32 address;
+
+       struct sk_buff *skb;
+       enum ath10k_htc_ep_id eid;
+       int status;
+       /* Specifies if the current request is an HTC message.
+        * If not, the eid is not applicable an the TX completion handler
+        * associated with the endpoint will not be invoked.
+        */
+       bool htc_msg;
+       /* Completion that (if set) will be invoked for non HTC requests
+        * (htc_msg == false) when the request has been processed.
+        */
+       struct completion *comp;
+};
+
+struct ath10k_sdio_rx_data {
+       struct sk_buff *skb;
+       size_t alloc_len;
+       size_t act_len;
+       enum ath10k_htc_ep_id eid;
+       bool part_of_bundle;
+       bool last_in_bundle;
+       bool trailer_only;
+       int status;
+};
+
+struct ath10k_sdio_irq_proc_regs {
+       u8 host_int_status;
+       u8 cpu_int_status;
+       u8 error_int_status;
+       u8 counter_int_status;
+       u8 mbox_frame;
+       u8 rx_lookahead_valid;
+       u8 host_int_status2;
+       u8 gmbox_rx_avail;
+       __le32 rx_lookahead[2];
+       __le32 rx_gmbox_lookahead_alias[2];
+};
+
+struct ath10k_sdio_irq_enable_regs {
+       u8 int_status_en;
+       u8 cpu_int_status_en;
+       u8 err_int_status_en;
+       u8 cntr_int_status_en;
+};
+
+struct ath10k_sdio_irq_data {
+       /* protects irq_proc_reg and irq_en_reg below.
+        * We use a mutex here and not a spinlock since we will have the
+        * mutex locked while calling the sdio_memcpy_ functions.
+        * These function require non atomic context, and hence, spinlocks
+        * can be held while calling these functions.
+        */
+       struct mutex mtx;
+       struct ath10k_sdio_irq_proc_regs *irq_proc_reg;
+       struct ath10k_sdio_irq_enable_regs *irq_en_reg;
+};
+
+struct ath10k_mbox_ext_info {
+       u32 htc_ext_addr;
+       u32 htc_ext_sz;
+};
+
+struct ath10k_mbox_info {
+       u32 htc_addr;
+       struct ath10k_mbox_ext_info ext_info[2];
+       u32 block_size;
+       u32 block_mask;
+       u32 gmbox_addr;
+       u32 gmbox_sz;
+};
+
+struct ath10k_sdio {
+       struct sdio_func *func;
+
+       struct ath10k_mbox_info mbox_info;
+       bool swap_mbox;
+       u32 mbox_addr[ATH10K_HTC_EP_COUNT];
+       u32 mbox_size[ATH10K_HTC_EP_COUNT];
+
+       /* available bus requests */
+       struct ath10k_sdio_bus_request bus_req[ATH10K_SDIO_BUS_REQUEST_MAX_NUM];
+       /* free list of bus requests */
+       struct list_head bus_req_freeq;
+       /* protects access to bus_req_freeq */
+       spinlock_t lock;
+
+       struct ath10k_sdio_rx_data rx_pkts[ATH10K_SDIO_MAX_RX_MSGS];
+       size_t n_rx_pkts;
+
+       struct ath10k *ar;
+       struct ath10k_sdio_irq_data irq_data;
+
+       /* temporary buffer for BMI requests */
+       u8 *bmi_buf;
+
+       wait_queue_head_t irq_wq;
+
+       bool is_disabled;
+
+       struct workqueue_struct *workqueue;
+       struct work_struct wr_async_work;
+       struct list_head wr_asyncq;
+       /* protects access to wr_asyncq */
+       spinlock_t wr_async_lock;
+};
+
+static inline struct ath10k_sdio *ath10k_sdio_priv(struct ath10k *ar)
+{
+       return (struct ath10k_sdio *)ar->drv_priv;
+}
+
+#endif
index cbac9e4252d6fdd60c8c6750fdaeaafeaa98e9e7..8bded5da9d0d72be1fb2c93f11bbe49a59572ca3 100644 (file)
@@ -205,6 +205,24 @@ struct host_interest {
         */
        /* Bit 1 - unused */
        u32 hi_fw_swap;                                 /* 0x104 */
+
+       /* global arenas pointer address, used by host driver debug */
+       u32 hi_dynamic_mem_arenas_addr;                 /* 0x108 */
+
+       /* allocated bytes of DRAM use by allocated */
+       u32 hi_dynamic_mem_allocated;                   /* 0x10C */
+
+       /* remaining bytes of DRAM */
+       u32 hi_dynamic_mem_remaining;                   /* 0x110 */
+
+       /* memory track count, configured by host */
+       u32 hi_dynamic_mem_track_max;                   /* 0x114 */
+
+       /* minidump buffer */
+       u32 hi_minidump;                                /* 0x118 */
+
+       /* bdata's sig and key addr */
+       u32 hi_bd_sig_key;                              /* 0x11c */
 } __packed;
 
 #define HI_ITEM(item)  offsetof(struct host_interest, item)
@@ -319,6 +337,12 @@ struct host_interest {
 #define HI_ACS_FLAGS_USE_WWAN       (1 << 1)
 /* Use test VAP */
 #define HI_ACS_FLAGS_TEST_VAP       (1 << 2)
+/* SDIO/mailbox ACS flag definitions */
+#define HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET       (1 << 0)
+#define HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET    (1 << 1)
+#define HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE        (1 << 2)
+#define HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_FW_ACK    (1 << 16)
+#define HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_FW_ACK (1 << 17)
 
 /*
  * CONSOLE FLAGS
index d8564624415c9f23a8fb21ea6efda6b9fc5c6fd1..9d3eb258ac2fdd2cd5e456dcba717234319476f3 100644 (file)
@@ -137,6 +137,13 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
                return ret;
        }
 
+       ret = nla_put_u32(skb, ATH10K_TM_ATTR_WMI_OP_VERSION,
+                         ar->normal_mode_fw.fw_file.wmi_op_version);
+       if (ret) {
+               kfree_skb(skb);
+               return ret;
+       }
+
        return cfg80211_testmode_reply(skb);
 }
 
index ba81bf66ce85aade4b60fe7ac90ac8c3b96dea40..191a8f34c8ea0831ca6105e87379a73b7303fdbc 100644 (file)
@@ -33,6 +33,7 @@ enum ath10k_tm_attr {
        ATH10K_TM_ATTR_WMI_CMDID        = 3,
        ATH10K_TM_ATTR_VERSION_MAJOR    = 4,
        ATH10K_TM_ATTR_VERSION_MINOR    = 5,
+       ATH10K_TM_ATTR_WMI_OP_VERSION   = 6,
 
        /* keep last */
        __ATH10K_TM_ATTR_AFTER_LAST,
index d068df520e7adf0ac0c7abe06fd3d40079656098..bd7f6d7b199e1816900f64c1158720626f6a70e3 100644 (file)
@@ -938,7 +938,10 @@ static int open_file_eeprom(struct inode *inode, struct file *file)
        }
 
        for (i = 0; i < eesize; ++i) {
-               AR5K_EEPROM_READ(i, val);
+               if (!ath5k_hw_nvram_read(ah, i, &val)) {
+                       ret = -EIO;
+                       goto freebuf;
+               }
                buf[i] = val;
        }
 
index a531e0c5c1e28514c0a8bb32f18c4f0808ec6f18..e6b2517e633498a26e82bf0982049c083e703268 100644 (file)
@@ -399,15 +399,10 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
                        csum_dest = skb->csum_offset + csum_start;
                }
 
-               if (skb_headroom(skb) < dev->needed_headroom) {
-                       struct sk_buff *tmp_skb = skb;
-
-                       skb = skb_realloc_headroom(skb, dev->needed_headroom);
-                       kfree_skb(tmp_skb);
-                       if (skb == NULL) {
-                               dev->stats.tx_dropped++;
-                               return 0;
-                       }
+               if (skb_cow_head(skb, dev->needed_headroom)) {
+                       dev->stats.tx_dropped++;
+                       kfree_skb(skb);
+                       return 0;
                }
 
                if (ath6kl_wmi_dix_2_dot3(ar->wmi, skb)) {
index c67d0e08bd4c2bbeed447976ff05dbaf66547b54..099f3d45c594d7bbe7c56aad7503627bd37d20d1 100644 (file)
@@ -369,7 +369,7 @@ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
 {
        struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
 
-       if (reg->power_limit != new_txpow)
+       if (ah->curchan && reg->power_limit != new_txpow)
                ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
 
        /* read back in case value is clamped */
index 6ccf248145141db26f931d83b1a8327d656b516f..6fbd5559c0c09a79c2e6bdbba4dbdfe0976269f9 100644 (file)
@@ -143,7 +143,7 @@ bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
 
        if (ah->eeprom_blob)
                ret = ath9k_hw_nvram_read_firmware(ah->eeprom_blob, off, data);
-       else if (pdata && !pdata->use_eeprom && pdata->eeprom_data)
+       else if (pdata && !pdata->use_eeprom)
                ret = ath9k_hw_nvram_read_pdata(pdata, off, data);
        else
                ret = common->bus_ops->eeprom_read(common, off, data);
index 16aca9e28b77396889fa9cc477b37c9a75cbb311..a866cbda0799fc1fdf4de944bac9b18ae9db6673 100644 (file)
@@ -153,7 +153,7 @@ static int ath9k_tx99_init(struct ath_softc *sc)
                sc->tx99_power,
                sc->tx99_power / 2);
 
-       /* We leave the harware awake as it will be chugging on */
+       /* We leave the hardware awake as it will be chugging on */
 
        return 0;
 }
index 5648ebbd0e1663720c2fd398d7e29fc623f9832b..5b0f9fc66bb60a85e285f54a30f24b8a502813ad 100644 (file)
@@ -795,15 +795,11 @@ static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf,
        struct wireless_dev *wdev = wil_to_wdev(wil);
        struct cfg80211_mgmt_tx_params params;
        int rc;
-       void *frame = kmalloc(len, GFP_KERNEL);
+       void *frame;
 
-       if (!frame)
-               return -ENOMEM;
-
-       if (copy_from_user(frame, buf, len)) {
-               kfree(frame);
-               return -EIO;
-       }
+       frame = memdup_user(buf, len);
+       if (IS_ERR(frame))
+               return PTR_ERR(frame);
 
        params.buf = frame;
        params.len = len;
index d23aac7503d332cfe741442fb66c9bc7e1373923..b37e7391f55defb4ded9635bdc15f55117789ba2 100644 (file)
@@ -71,8 +71,18 @@ MODULE_FIRMWARE("b43/ucode11.fw");
 MODULE_FIRMWARE("b43/ucode13.fw");
 MODULE_FIRMWARE("b43/ucode14.fw");
 MODULE_FIRMWARE("b43/ucode15.fw");
+MODULE_FIRMWARE("b43/ucode16_lp.fw");
 MODULE_FIRMWARE("b43/ucode16_mimo.fw");
+MODULE_FIRMWARE("b43/ucode24_lcn.fw");
+MODULE_FIRMWARE("b43/ucode25_lcn.fw");
+MODULE_FIRMWARE("b43/ucode25_mimo.fw");
+MODULE_FIRMWARE("b43/ucode26_mimo.fw");
+MODULE_FIRMWARE("b43/ucode29_mimo.fw");
+MODULE_FIRMWARE("b43/ucode33_lcn40.fw");
+MODULE_FIRMWARE("b43/ucode30_mimo.fw");
 MODULE_FIRMWARE("b43/ucode5.fw");
+MODULE_FIRMWARE("b43/ucode40.fw");
+MODULE_FIRMWARE("b43/ucode42.fw");
 MODULE_FIRMWARE("b43/ucode9.fw");
 
 static int modparam_bad_frames_preempt;
index 14a70d4b4e860aeded1cfa6d77b4bed6feb8578a..3559fb5b8fb03a964461be8815f12a4dad3cba3a 100644 (file)
@@ -380,9 +380,7 @@ int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg)
        /* Set up timer for BT  */
        btci->timer_on = false;
        btci->timeout = BRCMF_BTCOEX_OPPR_WIN_TIME;
-       init_timer(&btci->timer);
-       btci->timer.data = (ulong)btci;
-       btci->timer.function = brcmf_btcoex_timerfunc;
+       setup_timer(&btci->timer, brcmf_btcoex_timerfunc, (ulong)btci);
        btci->cfg = cfg;
        btci->saved_regs_part1 = false;
        btci->saved_regs_part2 = false;
index cd1d6730eab73d514db5a1b88d442607c7834e3d..a2bf11fc8ecce3d9748334f9be7e47d7842e6006 100644 (file)
@@ -4674,9 +4674,6 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
                if (err < 0)
                        brcmf_err("setting AP mode failed %d\n", err);
-               err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0);
-               if (err < 0)
-                       brcmf_err("setting INFRA mode failed %d\n", err);
                if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS))
                        brcmf_fil_iovar_int_set(ifp, "mbss", 0);
                brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
@@ -6378,16 +6375,6 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
        return -ENOMEM;
 }
 
-static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
-{
-       /* scheduled scan settings */
-       wiphy->max_sched_scan_reqs = 1;
-       wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
-       wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
-       wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
-       wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD;
-}
-
 #ifdef CONFIG_PM
 static const struct wiphy_wowlan_support brcmf_wowlan_support = {
        .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
@@ -6434,6 +6421,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
        const struct ieee80211_iface_combination *combo;
        struct ieee80211_supported_band *band;
        u16 max_interfaces = 0;
+       bool gscan;
        __le32 bandlist[3];
        u32 n_bands;
        int err, i;
@@ -6483,9 +6471,10 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
                wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
        wiphy->mgmt_stypes = brcmf_txrx_stypes;
        wiphy->max_remain_on_channel_duration = 5000;
-       if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO))
-               brcmf_wiphy_pno_params(wiphy);
-
+       if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {
+               gscan = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_GSCAN);
+               brcmf_pno_wiphy_params(wiphy, gscan);
+       }
        /* vendor commands/events support */
        wiphy->vendor_commands = brcmf_vendor_cmds;
        wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1;
index 8f19d95d4175da0742fbecb17c3fd6fc19453dff..a1c2e0af1774e5b43d6d330ccefa4601b99f9f1f 100644 (file)
@@ -24,6 +24,8 @@
 #include "fwil_types.h"
 #include "p2p.h"
 
+#define BRCMF_SCAN_IE_LEN_MAX          2048
+
 #define WL_NUM_SCAN_MAX                        10
 #define WL_TLV_INFO_MAX                        1024
 #define WL_BSS_INFO_MAX                        2048
index 62985f2c08538c1cbccb0a128df425c4b9eb20e5..8c7ef59944f08eabbd43c42682afa4828df23816 100644 (file)
@@ -27,6 +27,7 @@
 #include "feature.h"
 #include "common.h"
 
+#define BRCMF_FW_UNSUPPORTED   23
 
 /*
  * expand feature list to array of feature strings.
@@ -113,6 +114,22 @@ static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp,
        }
 }
 
+static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp,
+                                     enum brcmf_feat_id id, char *name,
+                                     const void *data, size_t len)
+{
+       int err;
+
+       err = brcmf_fil_iovar_data_set(ifp, name, data, len);
+       if (err != -BRCMF_FW_UNSUPPORTED) {
+               brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
+               ifp->drvr->feat_flags |= BIT(id);
+       } else {
+               brcmf_dbg(TRACE, "%s feature check failed: %d\n",
+                         brcmf_feat_names[id], err);
+       }
+}
+
 static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp)
 {
        char caps[256];
@@ -136,11 +153,14 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
 {
        struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
        struct brcmf_pno_macaddr_le pfn_mac;
+       struct brcmf_gscan_config gscan_cfg;
        u32 wowl_cap;
        s32 err;
 
        brcmf_feat_firmware_capabilities(ifp);
-
+       memset(&gscan_cfg, 0, sizeof(gscan_cfg));
+       brcmf_feat_iovar_data_set(ifp, BRCMF_FEAT_GSCAN, "pfn_gscan_cfg",
+                                 &gscan_cfg, sizeof(gscan_cfg));
        brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
        if (drvr->bus_if->wowl_supported)
                brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
index db4733a95e28fe99217b50b88de8b9b986446bfa..c1dbd17506aa1a2f65c2d2b5d3c8821a75f3de18 100644 (file)
@@ -31,6 +31,7 @@
  * WOWL_GTK: (WOWL) GTK rekeying offload
  * WOWL_ARP_ND: ARP and Neighbor Discovery offload support during WOWL.
  * MFP: 802.11w Management Frame Protection.
+ * GSCAN: enhanced scan offload feature.
  */
 #define BRCMF_FEAT_LIST \
        BRCMF_FEAT_DEF(MBSS) \
@@ -44,7 +45,8 @@
        BRCMF_FEAT_DEF(WOWL_ND) \
        BRCMF_FEAT_DEF(WOWL_GTK) \
        BRCMF_FEAT_DEF(WOWL_ARP_ND) \
-       BRCMF_FEAT_DEF(MFP)
+       BRCMF_FEAT_DEF(MFP) \
+       BRCMF_FEAT_DEF(GSCAN)
 
 /*
  * Quirks:
index 9a1eb5ab6c4b11c4ef822ea65fe1a4db4fe473f3..8c18fad3edc98fd8098673d5803227e6a9c5b0aa 100644 (file)
@@ -835,4 +835,63 @@ struct brcmf_gtk_keyinfo_le {
        u8 replay_counter[BRCMF_RSN_REPLAY_LEN];
 };
 
+/**
+ * struct brcmf_gscan_bucket_config - configuration data for channel bucket.
+ *
+ * @bucket_end_index: !unknown!
+ * @bucket_freq_multiple: !unknown!
+ * @flag: !unknown!
+ * @reserved: !unknown!
+ * @repeat: !unknown!
+ * @max_freq_multiple: !unknown!
+ */
+struct brcmf_gscan_bucket_config {
+       u8 bucket_end_index;
+       u8 bucket_freq_multiple;
+       u8 flag;
+       u8 reserved;
+       __le16 repeat;
+       __le16 max_freq_multiple;
+};
+
+/* version supported which must match firmware */
+#define BRCMF_GSCAN_CFG_VERSION                     1
+
+/**
+ * enum brcmf_gscan_cfg_flags - bit values for gscan flags.
+ *
+ * @BRCMF_GSCAN_CFG_FLAGS_ALL_RESULTS: send probe responses/beacons to host.
+ * @BRCMF_GSCAN_CFG_FLAGS_CHANGE_ONLY: indicated only flags member is changed.
+ */
+enum brcmf_gscan_cfg_flags {
+       BRCMF_GSCAN_CFG_FLAGS_ALL_RESULTS = BIT(0),
+       BRCMF_GSCAN_CFG_FLAGS_CHANGE_ONLY = BIT(7),
+};
+
+/**
+ * struct brcmf_gscan_config - configuration data for gscan.
+ *
+ * @version: version of the api to match firmware.
+ * @flags: flags according %enum brcmf_gscan_cfg_flags.
+ * @buffer_threshold: percentage threshold of buffer to generate an event.
+ * @swc_nbssid_threshold: number of BSSIDs with significant change that
+ *     will generate an event.
+ * @swc_rssi_window_size: size of rssi cache buffer (max=8).
+ * @count_of_channel_buckets: number of array members in @bucket.
+ * @retry_threshold: !unknown!
+ * @lost_ap_window: !unknown!
+ * @bucket: array of channel buckets.
+ */
+struct brcmf_gscan_config {
+       __le16 version;
+       u8  flags;
+       u8   buffer_threshold;
+       u8   swc_nbssid_threshold;
+       u8  swc_rssi_window_size;
+       u8  count_of_channel_buckets;
+       u8  retry_threshold;
+       __le16  lost_ap_window;
+       struct brcmf_gscan_bucket_config bucket[1];
+};
+
 #endif /* FWIL_TYPES_H_ */
index 6c3bde83d07085e46a5418673f09df5a5790a1aa..a473445ed7c4709e85c691a8551d6a72c465353d 100644 (file)
@@ -239,3 +239,13 @@ int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
        return ret;
 }
 
+void brcmf_pno_wiphy_params(struct wiphy *wiphy, bool gscan)
+{
+       /* scheduled scan settings */
+       wiphy->max_sched_scan_reqs = gscan ? 2 : 1;
+       wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
+       wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
+       wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
+       wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD;
+}
+
index bae55b2af78c027b975c20e5e486ea6047511ab1..07ec51f6bec131d55e185fe225fe84bcd04b34e6 100644 (file)
@@ -37,4 +37,12 @@ int brcmf_pno_clean(struct brcmf_if *ifp);
 int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
                               struct cfg80211_sched_scan_request *req);
 
+/**
+ * brcmf_pno_wiphy_params - fill scheduled scan parameters in wiphy instance.
+ *
+ * @wiphy: wiphy instance to be used.
+ * @gscan: indicates whether the device has support for g-scan feature.
+ */
+void brcmf_pno_wiphy_params(struct wiphy *wiphy, bool gscan);
+
 #endif /* _BRCMF_PNO_H */
index 140b6ea8f7cc48c9e3ea3908a3c274359ac9eaba..8d5acda92a9b819eb00e159790f796bbcbe1cf27 100644 (file)
@@ -5147,6 +5147,8 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed)
 
        if (changed & (IEEE80211_CONF_CHANGE_PS | IEEE80211_CONF_CHANGE_IDLE)) {
                il->power_data.ps_disabled = !(conf->flags & IEEE80211_CONF_PS);
+               if (!il->power_data.ps_disabled)
+                       IL_WARN_ONCE("Enabling power save might cause firmware crashes\n");
                ret = il_power_update_mode(il, false);
                if (ret)
                        D_MAC80211("Error setting sleep level\n");
index 3bba521d2cd90649befb9b270c70f90699a8fb04..18c60c92e3a35c79338d55bf1dfeb8d9fcb7a2ff 100644 (file)
@@ -45,6 +45,7 @@ struct il_tx_queue;
 
 #define IL_ERR(f, a...) dev_err(&il->pci_dev->dev, f, ## a)
 #define IL_WARN(f, a...) dev_warn(&il->pci_dev->dev, f, ## a)
+#define IL_WARN_ONCE(f, a...) dev_warn_once(&il->pci_dev->dev, f, ## a)
 #define IL_INFO(f, a...) dev_info(&il->pci_dev->dev, f, ## a)
 
 #define RX_QUEUE_SIZE                         256
index 04dfd040a6502a2d351d3a94e922469582497397..d4f0b730796e2839f13e4e9fdb1a74b458c43e43 100644 (file)
@@ -190,7 +190,7 @@ static inline void __hostap_cmd_queue_free(local_info_t *local,
                }
        }
 
-       if (atomic_dec_and_test(&entry->usecnt) && entry->del_req)
+       if (refcount_dec_and_test(&entry->usecnt) && entry->del_req)
                kfree(entry);
 }
 
@@ -228,7 +228,7 @@ static void prism2_clear_cmd_queue(local_info_t *local)
        spin_lock_irqsave(&local->cmdlock, flags);
        list_for_each_safe(ptr, n, &local->cmd_queue) {
                entry = list_entry(ptr, struct hostap_cmd_queue, list);
-               atomic_inc(&entry->usecnt);
+               refcount_inc(&entry->usecnt);
                printk(KERN_DEBUG "%s: removed pending cmd_queue entry "
                       "(type=%d, cmd=0x%04x, param0=0x%04x)\n",
                       local->dev->name, entry->type, entry->cmd,
@@ -350,7 +350,7 @@ static int hfa384x_cmd(struct net_device *dev, u16 cmd, u16 param0,
        if (entry == NULL)
                return -ENOMEM;
 
-       atomic_set(&entry->usecnt, 1);
+       refcount_set(&entry->usecnt, 1);
        entry->type = CMD_SLEEP;
        entry->cmd = cmd;
        entry->param0 = param0;
@@ -516,7 +516,7 @@ static int hfa384x_cmd_callback(struct net_device *dev, u16 cmd, u16 param0,
        if (entry == NULL)
                return -ENOMEM;
 
-       atomic_set(&entry->usecnt, 1);
+       refcount_set(&entry->usecnt, 1);
        entry->type = CMD_CALLBACK;
        entry->cmd = cmd;
        entry->param0 = param0;
@@ -666,7 +666,7 @@ static void prism2_cmd_ev(struct net_device *dev)
        if (!list_empty(&local->cmd_queue)) {
                entry = list_entry(local->cmd_queue.next,
                                   struct hostap_cmd_queue, list);
-               atomic_inc(&entry->usecnt);
+               refcount_inc(&entry->usecnt);
                list_del_init(&entry->list);
                local->cmd_queue_len--;
 
@@ -718,7 +718,7 @@ static void prism2_cmd_ev(struct net_device *dev)
                        entry = NULL;
                }
                if (entry)
-                       atomic_inc(&entry->usecnt);
+                       refcount_inc(&entry->usecnt);
        }
        spin_unlock(&local->cmdlock);
 
index ca25283e1c9201b566b09fcbe02a8aaa6c9c1811..5352adb94d5026d10c7fc5f2535c7418a3add721 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/mutex.h>
+#include <linux/refcount.h>
 #include <net/iw_handler.h>
 #include <net/ieee80211_radiotap.h>
 #include <net/lib80211.h>
@@ -557,7 +558,7 @@ struct hostap_cmd_queue {
        u16 resp0, res;
        volatile int issued, issuing;
 
-       atomic_t usecnt;
+       refcount_t usecnt;
        int del_req;
 };
 
index 132f5fbda58ba1517ed924e16e78dbf34ac17b14..c84fd8490601ec7db603dc49b39e0ca20d59dbd3 100644 (file)
@@ -64,6 +64,7 @@
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
 #include <linux/firmware.h>
+#include <linux/refcount.h>
 
 #include "mic.h"
 #include "orinoco.h"
@@ -268,7 +269,7 @@ enum ezusb_state {
 
 struct request_context {
        struct list_head list;
-       atomic_t refcount;
+       refcount_t refcount;
        struct completion done; /* Signals that CTX is dead */
        int killed;
        struct urb *outurb;     /* OUT for req pkt */
@@ -298,7 +299,7 @@ static inline u8 ezusb_reply_inc(u8 count)
 
 static void ezusb_request_context_put(struct request_context *ctx)
 {
-       if (!atomic_dec_and_test(&ctx->refcount))
+       if (!refcount_dec_and_test(&ctx->refcount))
                return;
 
        WARN_ON(!ctx->done.done);
@@ -328,7 +329,7 @@ static void ezusb_request_timerfn(u_long _ctx)
        } else {
                ctx->state = EZUSB_CTX_RESP_TIMEOUT;
                dev_dbg(&ctx->outurb->dev->dev, "couldn't unlink\n");
-               atomic_inc(&ctx->refcount);
+               refcount_inc(&ctx->refcount);
                ctx->killed = 1;
                ezusb_ctx_complete(ctx);
                ezusb_request_context_put(ctx);
@@ -361,7 +362,7 @@ static struct request_context *ezusb_alloc_ctx(struct ezusb_priv *upriv,
        ctx->out_rid = out_rid;
        ctx->in_rid = in_rid;
 
-       atomic_set(&ctx->refcount, 1);
+       refcount_set(&ctx->refcount, 1);
        init_completion(&ctx->done);
 
        setup_timer(&ctx->timer, ezusb_request_timerfn, (u_long)ctx);
@@ -469,7 +470,7 @@ static void ezusb_req_queue_run(struct ezusb_priv *upriv)
        list_move_tail(&ctx->list, &upriv->req_active);
 
        if (ctx->state == EZUSB_CTX_QUEUED) {
-               atomic_inc(&ctx->refcount);
+               refcount_inc(&ctx->refcount);
                result = usb_submit_urb(ctx->outurb, GFP_ATOMIC);
                if (result) {
                        ctx->state = EZUSB_CTX_REQSUBMIT_FAIL;
@@ -507,7 +508,7 @@ static void ezusb_req_enqueue_run(struct ezusb_priv *upriv,
                spin_unlock_irqrestore(&upriv->req_lock, flags);
                goto done;
        }
-       atomic_inc(&ctx->refcount);
+       refcount_inc(&ctx->refcount);
        list_add_tail(&ctx->list, &upriv->req_pending);
        spin_unlock_irqrestore(&upriv->req_lock, flags);
 
@@ -1477,7 +1478,7 @@ static inline void ezusb_delete(struct ezusb_priv *upriv)
                int err;
 
                ctx = list_entry(item, struct request_context, list);
-               atomic_inc(&ctx->refcount);
+               refcount_inc(&ctx->refcount);
 
                ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK;
                err = usb_unlink_urb(ctx->outurb);
index 4ac6764f4897f52f71ab12c4a10b1cc86067449e..3076f646c8293ca9ab7e80d50ece1b342a7e842d 100644 (file)
@@ -176,8 +176,9 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
                 * keeping a extra list for uploaded keys.
                 */
 
-               priv->used_rxkeys = kzalloc(BITS_TO_LONGS(
-                       priv->rx_keycache_size), GFP_KERNEL);
+               priv->used_rxkeys = kcalloc(BITS_TO_LONGS(priv->rx_keycache_size),
+                                           sizeof(long),
+                                           GFP_KERNEL);
 
                if (!priv->used_rxkeys)
                        return -ENOMEM;
index a0463fef79b016635b8cbd59978fe4c94b10a735..71ba2c8d09b50b834837cb606024927dd221f8e1 100644 (file)
@@ -443,17 +443,12 @@ static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy,
        struct lbs_private *priv = wiphy_priv(wiphy);
        int ret = -ENOTSUPP;
 
-       lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d",
-                          chandef->chan->center_freq,
-                          cfg80211_get_chandef_type(chandef));
-
        if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT)
                goto out;
 
        ret = lbs_set_channel(priv, chandef->chan->hw_value);
 
  out:
-       lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
        return ret;
 }
 
@@ -464,16 +459,12 @@ static int lbs_cfg_set_mesh_channel(struct wiphy *wiphy,
        struct lbs_private *priv = wiphy_priv(wiphy);
        int ret = -ENOTSUPP;
 
-       lbs_deb_enter_args(LBS_DEB_CFG80211, "iface %s freq %d",
-                          netdev_name(netdev), channel->center_freq);
-
        if (netdev != priv->mesh_dev)
                goto out;
 
        ret = lbs_mesh_set_channel(priv, channel->hw_value);
 
  out:
-       lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
        return ret;
 }
 
@@ -512,8 +503,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
        int i;
        int ret = -EILSEQ;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        bsssize = get_unaligned_le16(&scanresp->bssdescriptsize);
 
        lbs_deb_scan("scan response: %d BSSs (%d bytes); resp size %d bytes\n",
@@ -665,7 +654,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
        ret = 0;
 
  done:
-       lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
        return ret;
 }
 
@@ -693,11 +681,9 @@ static void lbs_scan_worker(struct work_struct *work)
        int last_channel;
        int running, carrier;
 
-       lbs_deb_enter(LBS_DEB_SCAN);
-
        scan_cmd = kzalloc(LBS_SCAN_MAX_CMD_SIZE, GFP_KERNEL);
        if (scan_cmd == NULL)
-               goto out_no_scan_cmd;
+               return;
 
        /* prepare fixed part of scan command */
        scan_cmd->bsstype = CMD_BSS_TYPE_ANY;
@@ -766,16 +752,11 @@ static void lbs_scan_worker(struct work_struct *work)
                lbs_deb_scan("scan: waking up waiters\n");
                wake_up_all(&priv->scan_q);
        }
-
- out_no_scan_cmd:
-       lbs_deb_leave(LBS_DEB_SCAN);
 }
 
 static void _internal_start_scan(struct lbs_private *priv, bool internal,
        struct cfg80211_scan_request *request)
 {
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        lbs_deb_scan("scan: ssids %d, channels %d, ie_len %zd\n",
                request->n_ssids, request->n_channels, request->ie_len);
 
@@ -785,8 +766,6 @@ static void _internal_start_scan(struct lbs_private *priv, bool internal,
 
        queue_delayed_work(priv->work_thread, &priv->scan_work,
                msecs_to_jiffies(50));
-
-       lbs_deb_leave(LBS_DEB_CFG80211);
 }
 
 /*
@@ -815,8 +794,6 @@ static int lbs_cfg_scan(struct wiphy *wiphy,
        struct lbs_private *priv = wiphy_priv(wiphy);
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        if (priv->scan_req || delayed_work_pending(&priv->scan_work)) {
                /* old scan request not yet processed */
                ret = -EAGAIN;
@@ -829,7 +806,6 @@ static int lbs_cfg_scan(struct wiphy *wiphy,
                ret = -EIO;
 
  out:
-       lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
        return ret;
 }
 
@@ -843,18 +819,12 @@ static int lbs_cfg_scan(struct wiphy *wiphy,
 void lbs_send_disconnect_notification(struct lbs_private *priv,
                                      bool locally_generated)
 {
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        cfg80211_disconnected(priv->dev, 0, NULL, 0, locally_generated,
                              GFP_KERNEL);
-
-       lbs_deb_leave(LBS_DEB_CFG80211);
 }
 
 void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event)
 {
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        cfg80211_michael_mic_failure(priv->dev,
                priv->assoc_bss,
                event == MACREG_INT_CODE_MIC_ERR_MULTICAST ?
@@ -863,8 +833,6 @@ void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event)
                -1,
                NULL,
                GFP_KERNEL);
-
-       lbs_deb_leave(LBS_DEB_CFG80211);
 }
 
 
@@ -883,8 +851,6 @@ static int lbs_remove_wep_keys(struct lbs_private *priv)
        struct cmd_ds_802_11_set_wep cmd;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        memset(&cmd, 0, sizeof(cmd));
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        cmd.keyindex = cpu_to_le16(priv->wep_tx_key);
@@ -892,7 +858,6 @@ static int lbs_remove_wep_keys(struct lbs_private *priv)
 
        ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
 
-       lbs_deb_leave(LBS_DEB_CFG80211);
        return ret;
 }
 
@@ -905,8 +870,6 @@ static int lbs_set_wep_keys(struct lbs_private *priv)
        int i;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        /*
         * command         13 00
         * size            50 00
@@ -956,7 +919,6 @@ static int lbs_set_wep_keys(struct lbs_private *priv)
                ret = lbs_remove_wep_keys(priv);
        }
 
-       lbs_deb_leave(LBS_DEB_CFG80211);
        return ret;
 }
 
@@ -969,8 +931,6 @@ static int lbs_enable_rsn(struct lbs_private *priv, int enable)
        struct cmd_ds_802_11_enable_rsn cmd;
        int ret;
 
-       lbs_deb_enter_args(LBS_DEB_CFG80211, "%d", enable);
-
        /*
         * cmd       2f 00
         * size      0c 00
@@ -986,7 +946,6 @@ static int lbs_enable_rsn(struct lbs_private *priv, int enable)
 
        ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
 
-       lbs_deb_leave(LBS_DEB_CFG80211);
        return ret;
 }
 
@@ -1014,8 +973,6 @@ static int lbs_set_key_material(struct lbs_private *priv,
        struct cmd_key_material cmd;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        /*
         * Example for WPA (TKIP):
         *
@@ -1044,7 +1001,6 @@ static int lbs_set_key_material(struct lbs_private *priv,
 
        ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
 
-       lbs_deb_leave(LBS_DEB_CFG80211);
        return ret;
 }
 
@@ -1061,8 +1017,6 @@ static int lbs_set_authtype(struct lbs_private *priv,
        struct cmd_ds_802_11_authenticate cmd;
        int ret;
 
-       lbs_deb_enter_args(LBS_DEB_CFG80211, "%d", sme->auth_type);
-
        /*
         * cmd        11 00
         * size       19 00
@@ -1085,7 +1039,6 @@ static int lbs_set_authtype(struct lbs_private *priv,
        ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd);
 
  done:
-       lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
        return ret;
 }
 
@@ -1116,8 +1069,6 @@ static int lbs_associate(struct lbs_private *priv,
        u8 *pos;
        u8 *tmp;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        if (!cmd) {
                ret = -ENOMEM;
                goto done;
@@ -1262,7 +1213,6 @@ static int lbs_associate(struct lbs_private *priv,
 
        kfree(cmd);
 done:
-       lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
        return ret;
 }
 
@@ -1329,8 +1279,6 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
        if (dev == priv->mesh_dev)
                return -EOPNOTSUPP;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        if (!sme->bssid) {
                struct cfg80211_scan_request *creq;
 
@@ -1442,7 +1390,6 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
  done:
        if (bss)
                cfg80211_put_bss(wiphy, bss);
-       lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
        return ret;
 }
 
@@ -1478,8 +1425,6 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
        if (dev == priv->mesh_dev)
                return -EOPNOTSUPP;
 
-       lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);
-
        /* store for lbs_cfg_ret_disconnect() */
        priv->disassoc_reason = reason_code;
 
@@ -1496,8 +1441,6 @@ static int lbs_cfg_set_default_key(struct wiphy *wiphy,
        if (netdev == priv->mesh_dev)
                return -EOPNOTSUPP;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        if (key_index != priv->wep_tx_key) {
                lbs_deb_assoc("set_default_key: to %d\n", key_index);
                priv->wep_tx_key = key_index;
@@ -1520,8 +1463,6 @@ static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
        if (netdev == priv->mesh_dev)
                return -EOPNOTSUPP;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        lbs_deb_assoc("add_key: cipher 0x%x, mac_addr %pM\n",
                      params->cipher, mac_addr);
        lbs_deb_assoc("add_key: key index %d, key len %d\n",
@@ -1575,8 +1516,6 @@ static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev,
                           u8 key_index, bool pairwise, const u8 *mac_addr)
 {
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        lbs_deb_assoc("del_key: key_idx %d, mac_addr %pM\n",
                      key_index, mac_addr);
 
@@ -1619,8 +1558,6 @@ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
        int ret;
        size_t i;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES) |
                         BIT(NL80211_STA_INFO_TX_PACKETS) |
                         BIT(NL80211_STA_INFO_RX_BYTES) |
@@ -1675,15 +1612,12 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev,
                return -EOPNOTSUPP;
        }
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        if (priv->iface_running)
                ret = lbs_set_iface_type(priv, type);
 
        if (!ret)
                priv->wdev->iftype = type;
 
-       lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
        return ret;
 }
 
@@ -1713,8 +1647,6 @@ static void lbs_join_post(struct lbs_private *priv,
        u8 *fake = fake_ie;
        struct cfg80211_bss *bss;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        /*
         * For cfg80211_inform_bss, we'll need a fake IE, as we can't get
         * the real IE from the firmware. So we fabricate a fake IE based on
@@ -1777,8 +1709,6 @@ static void lbs_join_post(struct lbs_private *priv,
        netif_carrier_on(priv->dev);
        if (!priv->tx_pending_len)
                netif_wake_queue(priv->dev);
-
-       lbs_deb_leave(LBS_DEB_CFG80211);
 }
 
 static int lbs_ibss_join_existing(struct lbs_private *priv,
@@ -1790,8 +1720,6 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
        u8 preamble = RADIO_PREAMBLE_SHORT;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        /* TODO: set preamble based on scan result */
        ret = lbs_set_radio(priv, preamble, 1);
        if (ret)
@@ -1888,7 +1816,6 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
        lbs_join_post(priv, params, bss->bssid, bss->capability);
 
  out:
-       lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
        return ret;
 }
 
@@ -1904,8 +1831,6 @@ static int lbs_ibss_start_new(struct lbs_private *priv,
        int ret = 0;
        u16 capability;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        ret = lbs_set_radio(priv, preamble, 1);
        if (ret)
                goto out;
@@ -1975,7 +1900,6 @@ static int lbs_ibss_start_new(struct lbs_private *priv,
        lbs_join_post(priv, params, resp->bssid, capability);
 
  out:
-       lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
        return ret;
 }
 
@@ -1990,8 +1914,6 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
        if (dev == priv->mesh_dev)
                return -EOPNOTSUPP;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        if (!params->chandef.chan) {
                ret = -ENOTSUPP;
                goto out;
@@ -2015,7 +1937,6 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 
 
  out:
-       lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
        return ret;
 }
 
@@ -2029,8 +1950,6 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
        if (dev == priv->mesh_dev)
                return -EOPNOTSUPP;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        memset(&cmd, 0, sizeof(cmd));
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd);
@@ -2038,7 +1957,6 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
        /* TODO: consider doing this at MACREG_INT_CODE_ADHOC_BCN_LOST time */
        lbs_mac_event_disconnected(priv, true);
 
-       lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
        return ret;
 }
 
@@ -2114,8 +2032,6 @@ struct wireless_dev *lbs_cfg_alloc(struct device *dev)
        int ret = 0;
        struct wireless_dev *wdev;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
        if (!wdev)
                return ERR_PTR(-ENOMEM);
@@ -2127,12 +2043,10 @@ struct wireless_dev *lbs_cfg_alloc(struct device *dev)
                goto err_wiphy_new;
        }
 
-       lbs_deb_leave(LBS_DEB_CFG80211);
        return wdev;
 
  err_wiphy_new:
        kfree(wdev);
-       lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
        return ERR_PTR(ret);
 }
 
@@ -2155,15 +2069,11 @@ static void lbs_cfg_set_regulatory_hint(struct lbs_private *priv)
        };
        size_t i;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        for (i = 0; i < ARRAY_SIZE(regmap); i++)
                if (regmap[i].code == priv->regioncode) {
                        regulatory_hint(priv->wdev->wiphy, regmap[i].cn);
                        break;
                }
-
-       lbs_deb_leave(LBS_DEB_CFG80211);
 }
 
 static void lbs_reg_notifier(struct wiphy *wiphy,
@@ -2171,15 +2081,9 @@ static void lbs_reg_notifier(struct wiphy *wiphy,
 {
        struct lbs_private *priv = wiphy_priv(wiphy);
 
-       lbs_deb_enter_args(LBS_DEB_CFG80211, "cfg80211 regulatory domain "
-                       "callback for domain %c%c\n", request->alpha2[0],
-                       request->alpha2[1]);
-
        memcpy(priv->country_code, request->alpha2, sizeof(request->alpha2));
        if (lbs_iface_active(priv))
                lbs_set_11d_domain_info(priv);
-
-       lbs_deb_leave(LBS_DEB_CFG80211);
 }
 
 /*
@@ -2192,8 +2096,6 @@ int lbs_cfg_register(struct lbs_private *priv)
        struct wireless_dev *wdev = priv->wdev;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        wdev->wiphy->max_scan_ssids = 1;
        wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
 
@@ -2229,13 +2131,11 @@ int lbs_cfg_register(struct lbs_private *priv)
 
        lbs_cfg_set_regulatory_hint(priv);
 
-       lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
        return ret;
 }
 
 void lbs_scan_deinit(struct lbs_private *priv)
 {
-       lbs_deb_enter(LBS_DEB_CFG80211);
        cancel_delayed_work_sync(&priv->scan_work);
 }
 
@@ -2244,8 +2144,6 @@ void lbs_cfg_free(struct lbs_private *priv)
 {
        struct wireless_dev *wdev = priv->wdev;
 
-       lbs_deb_enter(LBS_DEB_CFG80211);
-
        if (!wdev)
                return;
 
index 033ff881c7518109cf0278552af223ea24307f79..c1f42291873783cb8968a6075c158f348bd97b04 100644 (file)
@@ -91,8 +91,6 @@ int lbs_update_hw_spec(struct lbs_private *priv)
        int ret = -1;
        u32 i;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        memset(&cmd, 0, sizeof(cmd));
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
@@ -159,14 +157,12 @@ int lbs_update_hw_spec(struct lbs_private *priv)
        }
 
 out:
-       lbs_deb_leave(LBS_DEB_CMD);
        return ret;
 }
 
 static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy,
                        struct cmd_header *resp)
 {
-       lbs_deb_enter(LBS_DEB_CMD);
        if (priv->is_host_sleep_activated) {
                priv->is_host_sleep_configured = 0;
                if (priv->psstate == PS_STATE_FULL_POWER) {
@@ -176,7 +172,7 @@ static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy,
        } else {
                priv->is_host_sleep_configured = 1;
        }
-       lbs_deb_leave(LBS_DEB_CMD);
+
        return 0;
 }
 
@@ -236,8 +232,6 @@ int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block)
        struct cmd_ds_802_11_ps_mode cmd;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        memset(&cmd, 0, sizeof(cmd));
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        cmd.action = cpu_to_le16(cmd_action);
@@ -262,7 +256,6 @@ int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block)
                lbs_cmd_async(priv, CMD_802_11_PS_MODE, &cmd.hdr, sizeof (cmd));
 
 out:
-       lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
        return ret;
 }
 
@@ -272,8 +265,6 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
        struct cmd_ds_802_11_sleep_params cmd;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        if (cmd_action == CMD_ACT_GET) {
                memset(&cmd, 0, sizeof(cmd));
        } else {
@@ -304,7 +295,6 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
                sp->sp_reserved = le16_to_cpu(cmd.reserved);
        }
 
-       lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
        return ret;
 }
 
@@ -312,8 +302,6 @@ static int lbs_wait_for_ds_awake(struct lbs_private *priv)
 {
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        if (priv->is_deep_sleep) {
                if (!wait_event_interruptible_timeout(priv->ds_awake_q,
                                        !priv->is_deep_sleep, (10 * HZ))) {
@@ -322,7 +310,6 @@ static int lbs_wait_for_ds_awake(struct lbs_private *priv)
                }
        }
 
-       lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
        return ret;
 }
 
@@ -330,8 +317,6 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
 {
        int ret =  0;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        if (deep_sleep) {
                if (priv->is_deep_sleep != 1) {
                        lbs_deb_cmd("deep sleep: sleep\n");
@@ -358,7 +343,6 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
                }
        }
 
-       lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
        return ret;
 }
 
@@ -366,10 +350,9 @@ static int lbs_ret_host_sleep_activate(struct lbs_private *priv,
                unsigned long dummy,
                struct cmd_header *cmd)
 {
-       lbs_deb_enter(LBS_DEB_FW);
        priv->is_host_sleep_activated = 1;
        wake_up_interruptible(&priv->host_sleep_q);
-       lbs_deb_leave(LBS_DEB_FW);
+
        return 0;
 }
 
@@ -379,8 +362,6 @@ int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep)
        int ret = 0;
        uint32_t criteria = EHS_REMOVE_WAKEUP;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        if (host_sleep) {
                if (priv->is_host_sleep_activated != 1) {
                        memset(&cmd, 0, sizeof(cmd));
@@ -438,8 +419,6 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
        struct cmd_ds_802_11_snmp_mib cmd;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        memset(&cmd, 0, sizeof (cmd));
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        cmd.action = cpu_to_le16(CMD_ACT_SET);
@@ -470,7 +449,6 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
        ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
 
 out:
-       lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
        return ret;
 }
 
@@ -488,8 +466,6 @@ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
        struct cmd_ds_802_11_snmp_mib cmd;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        memset(&cmd, 0, sizeof (cmd));
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        cmd.action = cpu_to_le16(CMD_ACT_GET);
@@ -513,7 +489,6 @@ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
        }
 
 out:
-       lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
        return ret;
 }
 
@@ -533,8 +508,6 @@ int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
        struct cmd_ds_802_11_rf_tx_power cmd;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        memset(&cmd, 0, sizeof(cmd));
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        cmd.action = cpu_to_le16(CMD_ACT_GET);
@@ -548,7 +521,6 @@ int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
                        *maxlevel = cmd.maxlevel;
        }
 
-       lbs_deb_leave(LBS_DEB_CMD);
        return ret;
 }
 
@@ -565,8 +537,6 @@ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
        struct cmd_ds_802_11_rf_tx_power cmd;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        memset(&cmd, 0, sizeof(cmd));
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        cmd.action = cpu_to_le16(CMD_ACT_SET);
@@ -576,7 +546,6 @@ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
 
        ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
 
-       lbs_deb_leave(LBS_DEB_CMD);
        return ret;
 }
 
@@ -608,7 +577,6 @@ int lbs_set_monitor_mode(struct lbs_private *priv, int enable)
                                                ARPHRD_ETHER;
        }
 
-       lbs_deb_leave(LBS_DEB_CMD);
        return ret;
 }
 
@@ -624,8 +592,6 @@ static int lbs_get_channel(struct lbs_private *priv)
        struct cmd_ds_802_11_rf_channel cmd;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        memset(&cmd, 0, sizeof(cmd));
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
@@ -638,7 +604,6 @@ static int lbs_get_channel(struct lbs_private *priv)
        lbs_deb_cmd("current radio channel is %d\n", ret);
 
 out:
-       lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
        return ret;
 }
 
@@ -647,14 +612,12 @@ int lbs_update_channel(struct lbs_private *priv)
        int ret;
 
        /* the channel in f/w could be out of sync; get the current channel */
-       lbs_deb_enter(LBS_DEB_ASSOC);
-
        ret = lbs_get_channel(priv);
        if (ret > 0) {
                priv->channel = ret;
                ret = 0;
        }
-       lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+
        return ret;
 }
 
@@ -674,8 +637,6 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel)
 #endif
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        memset(&cmd, 0, sizeof(cmd));
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
@@ -690,7 +651,6 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel)
                priv->channel);
 
 out:
-       lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
        return ret;
 }
 
@@ -708,8 +668,6 @@ int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf)
        struct cmd_ds_802_11_rssi cmd;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        BUG_ON(rssi == NULL);
        BUG_ON(nf == NULL);
 
@@ -724,7 +682,6 @@ int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf)
                *rssi = CAL_RSSI(le16_to_cpu(cmd.n_or_snr), le16_to_cpu(cmd.nf));
        }
 
-       lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
        return ret;
 }
 
@@ -752,7 +709,6 @@ int lbs_set_11d_domain_info(struct lbs_private *priv)
        size_t triplet_size;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_11D);
        if (!priv->country_code[0])
                goto out;
 
@@ -849,7 +805,6 @@ int lbs_set_11d_domain_info(struct lbs_private *priv)
        ret = lbs_cmd_with_response(priv, CMD_802_11D_DOMAIN_INFO, &cmd);
 
 out:
-       lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
        return ret;
 }
 
@@ -869,8 +824,6 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
        struct cmd_ds_reg_access cmd;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        BUG_ON(value == NULL);
 
        memset(&cmd, 0, sizeof(cmd));
@@ -894,7 +847,6 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
        }
 
 out:
-       lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
        return ret;
 }
 
@@ -914,8 +866,6 @@ int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)
        struct cmd_ds_reg_access cmd;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        memset(&cmd, 0, sizeof(cmd));
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        cmd.action = cpu_to_le16(CMD_ACT_SET);
@@ -933,7 +883,6 @@ int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)
        ret = lbs_cmd_with_response(priv, reg, &cmd);
 
 out:
-       lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
        return ret;
 }
 
@@ -943,15 +892,13 @@ static void lbs_queue_cmd(struct lbs_private *priv,
        unsigned long flags;
        int addtail = 1;
 
-       lbs_deb_enter(LBS_DEB_HOST);
-
        if (!cmdnode) {
                lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
-               goto done;
+               return;
        }
        if (!cmdnode->cmdbuf->size) {
                lbs_deb_host("DNLD_CMD: cmd size is zero\n");
-               goto done;
+               return;
        }
        cmdnode->result = 0;
 
@@ -979,9 +926,6 @@ static void lbs_queue_cmd(struct lbs_private *priv,
 
        lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
                     le16_to_cpu(cmdnode->cmdbuf->command));
-
-done:
-       lbs_deb_leave(LBS_DEB_HOST);
 }
 
 static void lbs_submit_command(struct lbs_private *priv,
@@ -994,8 +938,6 @@ static void lbs_submit_command(struct lbs_private *priv,
        int timeo = 3 * HZ;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_HOST);
-
        cmd = cmdnode->cmdbuf;
 
        spin_lock_irqsave(&priv->driver_lock, flags);
@@ -1036,8 +978,6 @@ static void lbs_submit_command(struct lbs_private *priv,
                /* Setup the timer after transmit command */
                mod_timer(&priv->command_timer, jiffies + timeo);
        }
-
-       lbs_deb_leave(LBS_DEB_HOST);
 }
 
 /*
@@ -1047,10 +987,8 @@ static void lbs_submit_command(struct lbs_private *priv,
 static void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
                                         struct cmd_ctrl_node *cmdnode)
 {
-       lbs_deb_enter(LBS_DEB_HOST);
-
        if (!cmdnode)
-               goto out;
+               return;
 
        cmdnode->callback = NULL;
        cmdnode->callback_arg = 0;
@@ -1058,8 +996,6 @@ static void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
        memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
 
        list_add_tail(&cmdnode->list, &priv->cmdfreeq);
- out:
-       lbs_deb_leave(LBS_DEB_HOST);
 }
 
 static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
@@ -1107,8 +1043,6 @@ int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
        struct cmd_ds_802_11_radio_control cmd;
        int ret = -EINVAL;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        cmd.action = cpu_to_le16(CMD_ACT_SET);
        cmd.control = 0;
@@ -1141,7 +1075,6 @@ int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
        ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
 
 out:
-       lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
        return ret;
 }
 
@@ -1149,15 +1082,11 @@ void lbs_set_mac_control(struct lbs_private *priv)
 {
        struct cmd_ds_mac_control cmd;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        cmd.action = cpu_to_le16(priv->mac_control);
        cmd.reserved = 0;
 
        lbs_cmd_async(priv, CMD_MAC_CONTROL, &cmd.hdr, sizeof(cmd));
-
-       lbs_deb_leave(LBS_DEB_CMD);
 }
 
 int lbs_set_mac_control_sync(struct lbs_private *priv)
@@ -1165,14 +1094,11 @@ int lbs_set_mac_control_sync(struct lbs_private *priv)
        struct cmd_ds_mac_control cmd;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        cmd.hdr.size = cpu_to_le16(sizeof(cmd));
        cmd.action = cpu_to_le16(priv->mac_control);
        cmd.reserved = 0;
        ret = lbs_cmd_with_response(priv, CMD_MAC_CONTROL, &cmd);
 
-       lbs_deb_leave(LBS_DEB_CMD);
        return ret;
 }
 
@@ -1191,8 +1117,6 @@ int lbs_allocate_cmd_buffer(struct lbs_private *priv)
        u32 i;
        struct cmd_ctrl_node *cmdarray;
 
-       lbs_deb_enter(LBS_DEB_HOST);
-
        /* Allocate and initialize the command array */
        bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
        if (!(cmdarray = kzalloc(bufsize, GFP_KERNEL))) {
@@ -1219,7 +1143,6 @@ int lbs_allocate_cmd_buffer(struct lbs_private *priv)
        ret = 0;
 
 done:
-       lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
        return ret;
 }
 
@@ -1235,8 +1158,6 @@ int lbs_free_cmd_buffer(struct lbs_private *priv)
        struct cmd_ctrl_node *cmdarray;
        unsigned int i;
 
-       lbs_deb_enter(LBS_DEB_HOST);
-
        /* need to check if cmd array is allocated or not */
        if (priv->cmd_array == NULL) {
                lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
@@ -1260,7 +1181,6 @@ int lbs_free_cmd_buffer(struct lbs_private *priv)
        }
 
 done:
-       lbs_deb_leave(LBS_DEB_HOST);
        return 0;
 }
 
@@ -1278,8 +1198,6 @@ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)
        struct cmd_ctrl_node *tempnode;
        unsigned long flags;
 
-       lbs_deb_enter(LBS_DEB_HOST);
-
        if (!priv)
                return NULL;
 
@@ -1296,7 +1214,6 @@ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)
 
        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
-       lbs_deb_leave(LBS_DEB_HOST);
        return tempnode;
 }
 
@@ -1318,8 +1235,6 @@ int lbs_execute_next_command(struct lbs_private *priv)
        /* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
         * only caller to us is lbs_thread() and we get even when a
         * data packet is received */
-       lbs_deb_enter(LBS_DEB_THREAD);
-
        spin_lock_irqsave(&priv->driver_lock, flags);
 
        if (priv->cur_cmd) {
@@ -1440,7 +1355,6 @@ int lbs_execute_next_command(struct lbs_private *priv)
 
        ret = 0;
 done:
-       lbs_deb_leave(LBS_DEB_THREAD);
        return ret;
 }
 
@@ -1449,7 +1363,6 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)
        unsigned long flags;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_HOST);
        lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep,
                sizeof(confirm_sleep));
 
@@ -1457,7 +1370,7 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)
                sizeof(confirm_sleep));
        if (ret) {
                netdev_alert(priv->dev, "confirm_sleep failed\n");
-               goto out;
+               return;
        }
 
        spin_lock_irqsave(&priv->driver_lock, flags);
@@ -1475,9 +1388,6 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)
                priv->psstate = PS_STATE_SLEEP;
 
        spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-out:
-       lbs_deb_leave(LBS_DEB_HOST);
 }
 
 /**
@@ -1493,8 +1403,6 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv)
        unsigned long flags =0;
        int allowed = 1;
 
-       lbs_deb_enter(LBS_DEB_HOST);
-
        spin_lock_irqsave(&priv->driver_lock, flags);
        if (priv->dnld_sent) {
                allowed = 0;
@@ -1520,8 +1428,6 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv)
        } else {
                lbs_deb_host("sleep confirm has been delayed\n");
        }
-
-       lbs_deb_leave(LBS_DEB_HOST);
 }
 
 
@@ -1596,8 +1502,6 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
 {
        struct cmd_ctrl_node *cmdnode;
 
-       lbs_deb_enter(LBS_DEB_HOST);
-
        if (priv->surpriseremoved) {
                lbs_deb_host("PREP_CMD: card removed\n");
                cmdnode = ERR_PTR(-ENOENT);
@@ -1643,17 +1547,14 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
        wake_up(&priv->waitq);
 
  done:
-       lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode);
        return cmdnode;
 }
 
 void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
        struct cmd_header *in_cmd, int in_cmd_size)
 {
-       lbs_deb_enter(LBS_DEB_CMD);
        __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
                lbs_cmd_async_callback, 0);
-       lbs_deb_leave(LBS_DEB_CMD);
 }
 
 int __lbs_cmd(struct lbs_private *priv, uint16_t command,
@@ -1665,8 +1566,6 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
        unsigned long flags;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_HOST);
-
        cmdnode = __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
                                  callback, callback_arg);
        if (IS_ERR(cmdnode)) {
@@ -1693,7 +1592,6 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
 done:
-       lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
        return ret;
 }
 EXPORT_SYMBOL_GPL(__lbs_cmd);
index c753e36c2c0e191f7990268caf801122287796c7..aaf01619de59e2033cc7d3428807f4ece87f413a 100644 (file)
@@ -32,8 +32,6 @@ void lbs_mac_event_disconnected(struct lbs_private *priv,
        if (priv->connect_status != LBS_CONNECTED)
                return;
 
-       lbs_deb_enter(LBS_DEB_ASSOC);
-
        /*
         * Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
         * It causes problem in the Supplicant
@@ -61,7 +59,6 @@ void lbs_mac_event_disconnected(struct lbs_private *priv,
                lbs_deb_cmd("disconnected, so exit PS mode\n");
                lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
        }
-       lbs_deb_leave(LBS_DEB_ASSOC);
 }
 
 int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
@@ -72,8 +69,6 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
        unsigned long flags;
        uint16_t result;
 
-       lbs_deb_enter(LBS_DEB_HOST);
-
        mutex_lock(&priv->lock);
        spin_lock_irqsave(&priv->driver_lock, flags);
 
@@ -221,7 +216,6 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
 
 done:
        mutex_unlock(&priv->lock);
-       lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
        return ret;
 }
 
@@ -230,8 +224,6 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
        int ret = 0;
        struct cmd_header cmd;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        switch (event) {
        case MACREG_INT_CODE_LINK_SENSED:
                lbs_deb_cmd("EVENT: link sensed\n");
@@ -359,6 +351,5 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
                break;
        }
 
-       lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
        return ret;
 }
index 407784aca627bcd69b8a8632b45be53390a17481..d3221444e51c3f8dda0132a52235717968a5e630 100644 (file)
@@ -55,15 +55,6 @@ do { if ((lbs_debug & (grp)) == (grp)) \
 #define LBS_DEB_LL(grp, grpnam, fmt, args...) do {} while (0)
 #endif
 
-#define lbs_deb_enter(grp) \
-  LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s()\n", __func__);
-#define lbs_deb_enter_args(grp, fmt, args...) \
-  LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args);
-#define lbs_deb_leave(grp) \
-  LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s()\n", __func__);
-#define lbs_deb_leave_args(grp, fmt, args...) \
-  LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s(), " fmt "\n", \
-  __func__, ##args);
 #define lbs_deb_main(fmt, args...)      LBS_DEB_LL(LBS_DEB_MAIN, " main", fmt, ##args)
 #define lbs_deb_net(fmt, args...)       LBS_DEB_LL(LBS_DEB_NET, " net", fmt, ##args)
 #define lbs_deb_mesh(fmt, args...)      LBS_DEB_LL(LBS_DEB_MESH, " mesh", fmt, ##args)
index f955b2d66ed6e7609836e919678fc8c79d479b4b..693868f16921da0c0fd7421e63e4d7f4bf39fb18 100644 (file)
@@ -41,8 +41,6 @@ static int lbs_ethtool_get_eeprom(struct net_device *dev,
        struct cmd_ds_802_11_eeprom_access cmd;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_ETHTOOL);
-
        if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN ||
            eeprom->len > LBS_EEPROM_READ_LEN) {
                ret = -EINVAL;
@@ -59,7 +57,6 @@ static int lbs_ethtool_get_eeprom(struct net_device *dev,
                memcpy(bytes, cmd.value, eeprom->len);
 
 out:
-       lbs_deb_leave_args(LBS_DEB_ETHTOOL, "ret %d", ret);
         return ret;
 }
 
index f499efc6abcf8bed36c46c7aaa342c8b8be3c878..7d88223f890baf6020cdbf2a2417babd2f8c7e8c 100644 (file)
@@ -336,13 +336,11 @@ static inline u32 get_model(u16 manf_id, u16 card_id)
 
 static inline void if_cs_enable_ints(struct if_cs_card *card)
 {
-       lbs_deb_enter(LBS_DEB_CS);
        if_cs_write16(card, IF_CS_HOST_INT_MASK, 0);
 }
 
 static inline void if_cs_disable_ints(struct if_cs_card *card)
 {
-       lbs_deb_enter(LBS_DEB_CS);
        if_cs_write16(card, IF_CS_HOST_INT_MASK, IF_CS_BIT_MASK);
 }
 
@@ -355,7 +353,6 @@ static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb)
        int ret = -1;
        int loops = 0;
 
-       lbs_deb_enter(LBS_DEB_CS);
        if_cs_disable_ints(card);
 
        /* Is hardware ready? */
@@ -388,7 +385,6 @@ static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb)
 
 done:
        if_cs_enable_ints(card);
-       lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
        return ret;
 }
 
@@ -400,7 +396,6 @@ static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb)
        struct if_cs_card *card = (struct if_cs_card *)priv->card;
        u16 status;
 
-       lbs_deb_enter(LBS_DEB_CS);
        if_cs_disable_ints(card);
 
        status = if_cs_read16(card, IF_CS_CARD_STATUS);
@@ -416,8 +411,6 @@ static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb)
        if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_TX);
        if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_TX);
        if_cs_enable_ints(card);
-
-       lbs_deb_leave(LBS_DEB_CS);
 }
 
 /*
@@ -429,8 +422,6 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
        int ret = -1;
        u16 status;
 
-       lbs_deb_enter(LBS_DEB_CS);
-
        /* is hardware ready? */
        status = if_cs_read16(priv->card, IF_CS_CARD_STATUS);
        if ((status & IF_CS_BIT_RESP) == 0) {
@@ -463,7 +454,6 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
        spin_unlock_irqrestore(&priv->driver_lock, flags);
 
 out:
-       lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len);
        return ret;
 }
 
@@ -473,8 +463,6 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv)
        u16 len;
        u8 *data;
 
-       lbs_deb_enter(LBS_DEB_CS);
-
        len = if_cs_read16(priv->card, IF_CS_READ_LEN);
        if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
                netdev_err(priv->dev,
@@ -501,7 +489,6 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv)
        if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_RX);
 
 out:
-       lbs_deb_leave_args(LBS_DEB_CS, "ret %p", skb);
        return skb;
 }
 
@@ -511,8 +498,6 @@ static irqreturn_t if_cs_interrupt(int irq, void *data)
        struct lbs_private *priv = card->priv;
        u16 cause;
 
-       lbs_deb_enter(LBS_DEB_CS);
-
        /* Ask card interrupt cause register if there is something for us */
        cause = if_cs_read16(card, IF_CS_CARD_INT_CAUSE);
        lbs_deb_cs("cause 0x%04x\n", cause);
@@ -569,7 +554,6 @@ static irqreturn_t if_cs_interrupt(int irq, void *data)
        /* Clear interrupt cause */
        if_cs_write16(card, IF_CS_CARD_INT_CAUSE, cause & IF_CS_BIT_MASK);
 
-       lbs_deb_leave(LBS_DEB_CS);
        return IRQ_HANDLED;
 }
 
@@ -591,8 +575,6 @@ static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw)
        int sent = 0;
        u8  scratch;
 
-       lbs_deb_enter(LBS_DEB_CS);
-
        /*
         * This is the only place where an unaligned register access happens on
         * the CF8305 card, therefore for the sake of speed of the driver, we do
@@ -671,7 +653,6 @@ static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw)
        }
 
 done:
-       lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
        return ret;
 }
 
@@ -683,8 +664,6 @@ static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw)
        int len = 0;
        int sent;
 
-       lbs_deb_enter(LBS_DEB_CS);
-
        lbs_deb_cs("fw size %td\n", fw->size);
 
        ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW,
@@ -734,7 +713,6 @@ static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw)
                pr_err("firmware download failed\n");
 
 done:
-       lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
        return ret;
 }
 
@@ -792,8 +770,6 @@ static int if_cs_host_to_card(struct lbs_private *priv,
 {
        int ret = -1;
 
-       lbs_deb_enter_args(LBS_DEB_CS, "type %d, bytes %d", type, nb);
-
        switch (type) {
        case MVMS_DAT:
                priv->dnld_sent = DNLD_DATA_SENT;
@@ -809,7 +785,6 @@ static int if_cs_host_to_card(struct lbs_private *priv,
                           __func__, type);
        }
 
-       lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
        return ret;
 }
 
@@ -818,14 +793,10 @@ static void if_cs_release(struct pcmcia_device *p_dev)
 {
        struct if_cs_card *card = p_dev->priv;
 
-       lbs_deb_enter(LBS_DEB_CS);
-
        free_irq(p_dev->irq, card);
        pcmcia_disable_device(p_dev);
        if (card->iobase)
                ioport_unmap(card->iobase);
-
-       lbs_deb_leave(LBS_DEB_CS);
 }
 
 
@@ -850,8 +821,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
        struct lbs_private *priv;
        struct if_cs_card *card;
 
-       lbs_deb_enter(LBS_DEB_CS);
-
        card = kzalloc(sizeof(struct if_cs_card), GFP_KERNEL);
        if (!card)
                goto out;
@@ -961,7 +930,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
 out1:
        pcmcia_disable_device(p_dev);
 out:
-       lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
        return ret;
 }
 
@@ -970,15 +938,11 @@ static void if_cs_detach(struct pcmcia_device *p_dev)
 {
        struct if_cs_card *card = p_dev->priv;
 
-       lbs_deb_enter(LBS_DEB_CS);
-
        lbs_stop_card(card->priv);
        lbs_remove_card(card->priv);
        if_cs_disable_ints(card);
        if_cs_release(p_dev);
        kfree(card);
-
-       lbs_deb_leave(LBS_DEB_CS);
 }
 
 
index 47f4a14c84fedb037bbbe12479e43f915829afaa..e0196208ab0d57bb0b2cfecf38382bfba0ec2838 100644 (file)
@@ -211,8 +211,6 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card,
        unsigned long flags;
        u8 i;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        if (size > LBS_CMD_BUFFER_SIZE) {
                lbs_deb_sdio("response packet too large (%d bytes)\n",
                        (int)size);
@@ -233,7 +231,6 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card,
        ret = 0;
 
 out:
-       lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
        return ret;
 }
 
@@ -244,8 +241,6 @@ static int if_sdio_handle_data(struct if_sdio_card *card,
        struct sk_buff *skb;
        char *data;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        if (size > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
                lbs_deb_sdio("response packet too large (%d bytes)\n",
                        (int)size);
@@ -270,8 +265,6 @@ static int if_sdio_handle_data(struct if_sdio_card *card,
        ret = 0;
 
 out:
-       lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
        return ret;
 }
 
@@ -281,8 +274,6 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
        int ret;
        u32 event;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        if (card->model == MODEL_8385) {
                event = sdio_readb(card->func, IF_SDIO_EVENT, &ret);
                if (ret)
@@ -307,8 +298,6 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
        ret = 0;
 
 out:
-       lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
        return ret;
 }
 
@@ -337,8 +326,6 @@ static int if_sdio_card_to_host(struct if_sdio_card *card)
        int ret;
        u16 size, type, chunk;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        size = if_sdio_read_rx_len(card, &ret);
        if (ret)
                goto out;
@@ -410,8 +397,6 @@ static int if_sdio_card_to_host(struct if_sdio_card *card)
        if (ret)
                pr_err("problem fetching packet from firmware\n");
 
-       lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
        return ret;
 }
 
@@ -422,8 +407,6 @@ static void if_sdio_host_to_card_worker(struct work_struct *work)
        int ret;
        unsigned long flags;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        card = container_of(work, struct if_sdio_card, packet_worker);
 
        while (1) {
@@ -451,8 +434,6 @@ static void if_sdio_host_to_card_worker(struct work_struct *work)
 
                kfree(packet);
        }
-
-       lbs_deb_leave(LBS_DEB_SDIO);
 }
 
 /********************************************************************/
@@ -471,8 +452,6 @@ static int if_sdio_prog_helper(struct if_sdio_card *card,
        const u8 *firmware;
        size_t size;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        chunk_buffer = kzalloc(64, GFP_KERNEL);
        if (!chunk_buffer) {
                ret = -ENOMEM;
@@ -556,7 +535,6 @@ static int if_sdio_prog_helper(struct if_sdio_card *card,
        if (ret)
                pr_err("failed to load helper firmware\n");
 
-       lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
        return ret;
 }
 
@@ -570,8 +548,6 @@ static int if_sdio_prog_real(struct if_sdio_card *card,
        const u8 *firmware;
        size_t size, req_size;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        chunk_buffer = kzalloc(512, GFP_KERNEL);
        if (!chunk_buffer) {
                ret = -ENOMEM;
@@ -691,7 +667,6 @@ static int if_sdio_prog_real(struct if_sdio_card *card,
        if (ret)
                pr_err("failed to load firmware\n");
 
-       lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
        return ret;
 }
 
@@ -725,8 +700,6 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
        int ret;
        u16 scratch;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        /*
         * Disable interrupts
         */
@@ -769,7 +742,6 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
                                     fw_table, if_sdio_do_prog_firmware);
 
 out:
-       lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
        return ret;
 }
 
@@ -948,8 +920,6 @@ static int if_sdio_host_to_card(struct lbs_private *priv,
        u16 size;
        unsigned long flags;
 
-       lbs_deb_enter_args(LBS_DEB_SDIO, "type %d, bytes %d", type, nb);
-
        card = priv->card;
 
        if (nb > (65536 - sizeof(struct if_sdio_packet) - 4)) {
@@ -1013,8 +983,6 @@ static int if_sdio_host_to_card(struct lbs_private *priv,
        ret = 0;
 
 out:
-       lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
        return ret;
 }
 
@@ -1040,7 +1008,6 @@ static int if_sdio_exit_deep_sleep(struct lbs_private *priv)
        struct if_sdio_card *card = priv->card;
        int ret = -1;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
        sdio_claim_host(card->func);
 
        sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
@@ -1048,7 +1015,7 @@ static int if_sdio_exit_deep_sleep(struct lbs_private *priv)
                netdev_err(priv->dev, "sdio_writeb failed!\n");
 
        sdio_release_host(card->func);
-       lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
        return ret;
 }
 
@@ -1057,7 +1024,6 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
        struct if_sdio_card *card = priv->card;
        int ret = -1;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
        sdio_claim_host(card->func);
 
        sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret);
@@ -1065,7 +1031,7 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
                netdev_err(priv->dev, "sdio_writeb failed!\n");
 
        sdio_release_host(card->func);
-       lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+
        return ret;
 
 }
@@ -1143,19 +1109,17 @@ static void if_sdio_interrupt(struct sdio_func *func)
        struct if_sdio_card *card;
        u8 cause;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        card = sdio_get_drvdata(func);
 
        cause = sdio_readb(card->func, IF_SDIO_H_INT_STATUS, &ret);
        if (ret || !cause)
-               goto out;
+               return;
 
        lbs_deb_sdio("interrupt: 0x%X\n", (unsigned)cause);
 
        sdio_writeb(card->func, ~cause, IF_SDIO_H_INT_STATUS, &ret);
        if (ret)
-               goto out;
+               return;
 
        /*
         * Ignore the define name, this really means the card has
@@ -1169,13 +1133,8 @@ static void if_sdio_interrupt(struct sdio_func *func)
        if (cause & IF_SDIO_H_INT_UPLD) {
                ret = if_sdio_card_to_host(card);
                if (ret)
-                       goto out;
+                       return;
        }
-
-       ret = 0;
-
-out:
-       lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
 }
 
 static int if_sdio_probe(struct sdio_func *func,
@@ -1187,8 +1146,6 @@ static int if_sdio_probe(struct sdio_func *func,
        unsigned int model;
        struct if_sdio_packet *packet;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        for (i = 0;i < func->card->num_info;i++) {
                if (sscanf(func->card->info[i],
                                "802.11 SDIO ID: %x", &model) == 1)
@@ -1273,8 +1230,6 @@ static int if_sdio_probe(struct sdio_func *func,
                goto err_activate_card;
 
 out:
-       lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
        return ret;
 
 err_activate_card:
@@ -1298,8 +1253,6 @@ static void if_sdio_remove(struct sdio_func *func)
        struct if_sdio_card *card;
        struct if_sdio_packet *packet;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        card = sdio_get_drvdata(func);
 
        /* Undo decrement done above in if_sdio_probe */
@@ -1335,7 +1288,6 @@ static void if_sdio_remove(struct sdio_func *func)
        }
 
        kfree(card);
-       lbs_deb_leave(LBS_DEB_SDIO);
 }
 
 static int if_sdio_suspend(struct device *dev)
@@ -1415,8 +1367,6 @@ static int __init if_sdio_init_module(void)
 {
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        printk(KERN_INFO "libertas_sdio: Libertas SDIO driver\n");
        printk(KERN_INFO "libertas_sdio: Copyright Pierre Ossman\n");
 
@@ -1425,23 +1375,17 @@ static int __init if_sdio_init_module(void)
        /* Clear the flag in case user removes the card. */
        user_rmmod = 0;
 
-       lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
        return ret;
 }
 
 static void __exit if_sdio_exit_module(void)
 {
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        /* Set the flag as user is removing this module. */
        user_rmmod = 1;
 
        cancel_work_sync(&card_reset_work);
 
        sdio_unregister_driver(&if_sdio_driver);
-
-       lbs_deb_leave(LBS_DEB_SDIO);
 }
 
 module_init(if_sdio_init_module);
index 7b4955cc38db3d9b19376d0fde19c1ada14139f9..e9aec6cb110546521e46836085114f07605e7cfe 100644 (file)
@@ -466,8 +466,6 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,
        const u8 *fw;
        u8 temp[HELPER_FW_LOAD_CHUNK_SZ];
 
-       lbs_deb_enter(LBS_DEB_SPI);
-
        err = spu_set_interrupt_mode(card, 1, 0);
        if (err)
                goto out;
@@ -533,7 +531,7 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,
 out:
        if (err)
                pr_err("failed to load helper firmware (err=%d)\n", err);
-       lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
+
        return err;
 }
 
@@ -588,8 +586,6 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card,
        const u8 *fw;
        u16 num_crc_errs;
 
-       lbs_deb_enter(LBS_DEB_SPI);
-
        err = spu_set_interrupt_mode(card, 1, 0);
        if (err)
                goto out;
@@ -666,7 +662,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card,
 out:
        if (err)
                pr_err("failed to load firmware (err=%d)\n", err);
-       lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
+
        return err;
 }
 
@@ -699,8 +695,6 @@ static int if_spi_c2h_cmd(struct if_spi_card *card)
         */
        BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0);
 
-       lbs_deb_enter(LBS_DEB_SPI);
-
        /* How many bytes are there to read? */
        err = spu_read_u16(card, IF_SPI_SCRATCH_2_REG, &len);
        if (err)
@@ -735,7 +729,7 @@ static int if_spi_c2h_cmd(struct if_spi_card *card)
 out:
        if (err)
                netdev_err(priv->dev, "%s: err=%d\n", __func__, err);
-       lbs_deb_leave(LBS_DEB_SPI);
+
        return err;
 }
 
@@ -748,8 +742,6 @@ static int if_spi_c2h_data(struct if_spi_card *card)
        u16 len;
        int err = 0;
 
-       lbs_deb_enter(LBS_DEB_SPI);
-
        /* How many bytes are there to read? */
        err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len);
        if (err)
@@ -794,7 +786,7 @@ static int if_spi_c2h_data(struct if_spi_card *card)
 out:
        if (err)
                netdev_err(priv->dev, "%s: err=%d\n", __func__, err);
-       lbs_deb_leave(LBS_DEB_SPI);
+
        return err;
 }
 
@@ -870,8 +862,6 @@ static void if_spi_host_to_card_worker(struct work_struct *work)
        card = container_of(work, struct if_spi_card, packet_work);
        priv = card->priv;
 
-       lbs_deb_enter(LBS_DEB_SPI);
-
        /*
         * Read the host interrupt status register to see what we
         * can do.
@@ -943,8 +933,6 @@ static void if_spi_host_to_card_worker(struct work_struct *work)
 err:
        if (err)
                netdev_err(priv->dev, "%s: got error %d\n", __func__, err);
-
-       lbs_deb_leave(LBS_DEB_SPI);
 }
 
 /*
@@ -962,8 +950,6 @@ static int if_spi_host_to_card(struct lbs_private *priv,
        struct if_spi_packet *packet;
        u16 blen;
 
-       lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
-
        if (nb == 0) {
                netdev_err(priv->dev, "%s: invalid size requested: %d\n",
                           __func__, nb);
@@ -1004,7 +990,6 @@ static int if_spi_host_to_card(struct lbs_private *priv,
        /* Queue spi xfer work */
        queue_work(card->workqueue, &card->packet_work);
 out:
-       lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err);
        return err;
 }
 
@@ -1035,8 +1020,6 @@ static int if_spi_init_card(struct if_spi_card *card)
        const struct firmware *helper = NULL;
        const struct firmware *mainfw = NULL;
 
-       lbs_deb_enter(LBS_DEB_SPI);
-
        err = spu_init(card, card->pdata->use_dummy_writes);
        if (err)
                goto out;
@@ -1093,7 +1076,6 @@ static int if_spi_init_card(struct if_spi_card *card)
                goto out;
 
 out:
-       lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
        return err;
 }
 
@@ -1126,8 +1108,6 @@ static int if_spi_probe(struct spi_device *spi)
        struct libertas_spi_platform_data *pdata = dev_get_platdata(&spi->dev);
        int err = 0;
 
-       lbs_deb_enter(LBS_DEB_SPI);
-
        if (!pdata) {
                err = -EINVAL;
                goto out;
@@ -1221,7 +1201,6 @@ static int if_spi_probe(struct spi_device *spi)
        if (pdata->teardown)
                pdata->teardown(spi);
 out:
-       lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
        return err;
 }
 
@@ -1231,7 +1210,6 @@ static int libertas_spi_remove(struct spi_device *spi)
        struct lbs_private *priv = card->priv;
 
        lbs_deb_spi("libertas_spi_remove\n");
-       lbs_deb_enter(LBS_DEB_SPI);
 
        cancel_work_sync(&card->resume_work);
 
@@ -1243,7 +1221,7 @@ static int libertas_spi_remove(struct spi_device *spi)
        if (card->pdata->teardown)
                card->pdata->teardown(spi);
        free_if_spi_card(card);
-       lbs_deb_leave(LBS_DEB_SPI);
+
        return 0;
 }
 
@@ -1297,18 +1275,16 @@ static struct spi_driver libertas_spi_driver = {
 static int __init if_spi_init_module(void)
 {
        int ret = 0;
-       lbs_deb_enter(LBS_DEB_SPI);
+
        printk(KERN_INFO "libertas_spi: Libertas SPI driver\n");
        ret = spi_register_driver(&libertas_spi_driver);
-       lbs_deb_leave(LBS_DEB_SPI);
+
        return ret;
 }
 
 static void __exit if_spi_exit_module(void)
 {
-       lbs_deb_enter(LBS_DEB_SPI);
        spi_unregister_driver(&libertas_spi_driver);
-       lbs_deb_leave(LBS_DEB_SPI);
 }
 
 module_init(if_spi_init_module);
index aba0c9995b14b143f716d4a83c0a695f0cc628eb..e53025ea6689c77af8f95b5454533f6819901172 100644 (file)
@@ -111,8 +111,6 @@ static void if_usb_write_bulk_callback(struct urb *urb)
  */
 static void if_usb_free(struct if_usb_card *cardp)
 {
-       lbs_deb_enter(LBS_DEB_USB);
-
        /* Unlink tx & rx urb */
        usb_kill_urb(cardp->tx_urb);
        usb_kill_urb(cardp->rx_urb);
@@ -125,8 +123,6 @@ static void if_usb_free(struct if_usb_card *cardp)
 
        kfree(cardp->ep_out_buf);
        cardp->ep_out_buf = NULL;
-
-       lbs_deb_leave(LBS_DEB_USB);
 }
 
 static void if_usb_setup_firmware(struct lbs_private *priv)
@@ -306,8 +302,6 @@ static void if_usb_disconnect(struct usb_interface *intf)
        struct if_usb_card *cardp = usb_get_intfdata(intf);
        struct lbs_private *priv = cardp->priv;
 
-       lbs_deb_enter(LBS_DEB_MAIN);
-
        cardp->surprise_removed = 1;
 
        if (priv) {
@@ -320,8 +314,6 @@ static void if_usb_disconnect(struct usb_interface *intf)
 
        usb_set_intfdata(intf, NULL);
        usb_put_dev(interface_to_usbdev(intf));
-
-       lbs_deb_leave(LBS_DEB_MAIN);
 }
 
 /**
@@ -388,8 +380,6 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
        struct cmd_header *cmd = cardp->ep_out_buf + 4;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_USB);
-
        *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
 
        cmd->command = cpu_to_le16(CMD_802_11_RESET);
@@ -407,8 +397,6 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
                if_usb_reset_olpc_card(NULL);
 #endif
 
-       lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
-
        return ret;
 }
 
@@ -671,8 +659,6 @@ static void if_usb_receive(struct urb *urb)
        __le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET);
        uint32_t event;
 
-       lbs_deb_enter(LBS_DEB_USB);
-
        if (recvlength) {
                if (urb->status) {
                        lbs_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n",
@@ -688,7 +674,7 @@ static void if_usb_receive(struct urb *urb)
                            recvlength, recvtype);
        } else if (urb->status) {
                kfree_skb(skb);
-               goto rx_exit;
+               return;
        }
 
        switch (recvtype) {
@@ -724,8 +710,6 @@ static void if_usb_receive(struct urb *urb)
 
 setup_for_next:
        if_usb_submit_rx_urb(cardp);
-rx_exit:
-       lbs_deb_leave(LBS_DEB_USB);
 }
 
 /**
@@ -835,8 +819,6 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
        int i = 0;
        static int reset_count = 10;
 
-       lbs_deb_enter(LBS_DEB_USB);
-
        if (ret) {
                pr_err("failed to find firmware (%d)\n", ret);
                goto done;
@@ -942,7 +924,6 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
 
  done:
        cardp->fw = NULL;
-       lbs_deb_leave(LBS_DEB_USB);
 }
 
 
@@ -953,8 +934,6 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
        struct lbs_private *priv = cardp->priv;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_USB);
-
        if (priv->psstate != PS_STATE_FULL_POWER) {
                ret = -1;
                goto out;
@@ -978,7 +957,6 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
        usb_kill_urb(cardp->rx_urb);
 
  out:
-       lbs_deb_leave(LBS_DEB_USB);
        return ret;
 }
 
@@ -987,13 +965,10 @@ static int if_usb_resume(struct usb_interface *intf)
        struct if_usb_card *cardp = usb_get_intfdata(intf);
        struct lbs_private *priv = cardp->priv;
 
-       lbs_deb_enter(LBS_DEB_USB);
-
        if_usb_submit_rx_urb(cardp);
 
        lbs_resume(priv);
 
-       lbs_deb_leave(LBS_DEB_USB);
        return 0;
 }
 #else
index e3500203715cf6d1f42a7243460ad1878ca10c1d..55f8c997e5cbbff495889d8ff59c0abd0c92d1d0 100644 (file)
@@ -180,7 +180,6 @@ static int lbs_dev_open(struct net_device *dev)
        struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_NET);
        if (!priv->iface_running) {
                ret = lbs_start_iface(priv);
                if (ret)
@@ -197,7 +196,6 @@ static int lbs_dev_open(struct net_device *dev)
        spin_unlock_irq(&priv->driver_lock);
 
 out:
-       lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
        return ret;
 }
 
@@ -216,8 +214,6 @@ int lbs_stop_iface(struct lbs_private *priv)
        unsigned long flags;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_MAIN);
-
        spin_lock_irqsave(&priv->driver_lock, flags);
        priv->iface_running = false;
        kfree_skb(priv->currenttxskb);
@@ -236,7 +232,6 @@ int lbs_stop_iface(struct lbs_private *priv)
        if (priv->power_save)
                ret = priv->power_save(priv);
 
-       lbs_deb_leave(LBS_DEB_MAIN);
        return ret;
 }
 
@@ -250,8 +245,6 @@ static int lbs_eth_stop(struct net_device *dev)
 {
        struct lbs_private *priv = dev->ml_priv;
 
-       lbs_deb_enter(LBS_DEB_NET);
-
        if (priv->connect_status == LBS_CONNECTED)
                lbs_disconnect(priv, WLAN_REASON_DEAUTH_LEAVING);
 
@@ -269,7 +262,6 @@ static int lbs_eth_stop(struct net_device *dev)
        if (!lbs_iface_active(priv))
                lbs_stop_iface(priv);
 
-       lbs_deb_leave(LBS_DEB_NET);
        return 0;
 }
 
@@ -277,8 +269,6 @@ void lbs_host_to_card_done(struct lbs_private *priv)
 {
        unsigned long flags;
 
-       lbs_deb_enter(LBS_DEB_THREAD);
-
        spin_lock_irqsave(&priv->driver_lock, flags);
        del_timer(&priv->tx_lockup_timer);
 
@@ -291,7 +281,6 @@ void lbs_host_to_card_done(struct lbs_private *priv)
        }
 
        spin_unlock_irqrestore(&priv->driver_lock, flags);
-       lbs_deb_leave(LBS_DEB_THREAD);
 }
 EXPORT_SYMBOL_GPL(lbs_host_to_card_done);
 
@@ -301,8 +290,6 @@ int lbs_set_mac_address(struct net_device *dev, void *addr)
        struct lbs_private *priv = dev->ml_priv;
        struct sockaddr *phwaddr = addr;
 
-       lbs_deb_enter(LBS_DEB_NET);
-
        /*
         * Can only set MAC address when all interfaces are down, to be written
         * to the hardware when one of them is brought up.
@@ -318,7 +305,6 @@ int lbs_set_mac_address(struct net_device *dev, void *addr)
        if (priv->mesh_dev)
                memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
 
-       lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
        return ret;
 }
 
@@ -378,8 +364,6 @@ void lbs_update_mcast(struct lbs_private *priv)
        int nr_addrs;
        int old_mac_control = priv->mac_control;
 
-       lbs_deb_enter(LBS_DEB_NET);
-
        if (netif_running(priv->dev))
                dev_flags |= priv->dev->flags;
        if (priv->mesh_dev && netif_running(priv->mesh_dev))
@@ -424,8 +408,6 @@ void lbs_update_mcast(struct lbs_private *priv)
  out_set_mac_control:
        if (priv->mac_control != old_mac_control)
                lbs_set_mac_control(priv);
-
-       lbs_deb_leave(LBS_DEB_NET);
 }
 
 static void lbs_set_mcast_worker(struct work_struct *work)
@@ -455,8 +437,6 @@ static int lbs_thread(void *data)
        struct lbs_private *priv = dev->ml_priv;
        wait_queue_t wait;
 
-       lbs_deb_enter(LBS_DEB_THREAD);
-
        init_waitqueue_entry(&wait, current);
 
        for (;;) {
@@ -648,7 +628,6 @@ static int lbs_thread(void *data)
        del_timer(&priv->tx_lockup_timer);
        del_timer(&priv->auto_deepsleep_timer);
 
-       lbs_deb_leave(LBS_DEB_THREAD);
        return 0;
 }
 
@@ -664,8 +643,6 @@ static int lbs_setup_firmware(struct lbs_private *priv)
        int ret = -1;
        s16 curlevel = 0, minlevel = 0, maxlevel = 0;
 
-       lbs_deb_enter(LBS_DEB_FW);
-
        /* Read MAC address from firmware */
        eth_broadcast_addr(priv->current_addr);
        ret = lbs_update_hw_spec(priv);
@@ -687,7 +664,6 @@ static int lbs_setup_firmware(struct lbs_private *priv)
 
        ret = lbs_set_mac_control_sync(priv);
 done:
-       lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
        return ret;
 }
 
@@ -695,8 +671,6 @@ int lbs_suspend(struct lbs_private *priv)
 {
        int ret;
 
-       lbs_deb_enter(LBS_DEB_FW);
-
        if (priv->is_deep_sleep) {
                ret = lbs_set_deep_sleep(priv, 0);
                if (ret) {
@@ -713,7 +687,6 @@ int lbs_suspend(struct lbs_private *priv)
        if (priv->mesh_dev)
                netif_device_detach(priv->mesh_dev);
 
-       lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
        return ret;
 }
 EXPORT_SYMBOL_GPL(lbs_suspend);
@@ -722,8 +695,6 @@ int lbs_resume(struct lbs_private *priv)
 {
        int ret;
 
-       lbs_deb_enter(LBS_DEB_FW);
-
        ret = lbs_set_host_sleep(priv, 0);
 
        netif_device_attach(priv->dev);
@@ -741,7 +712,6 @@ int lbs_resume(struct lbs_private *priv)
        if (priv->setup_fw_on_resume)
                ret = lbs_setup_firmware(priv);
 
-       lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
        return ret;
 }
 EXPORT_SYMBOL_GPL(lbs_resume);
@@ -757,7 +727,6 @@ static void lbs_cmd_timeout_handler(unsigned long data)
        struct lbs_private *priv = (struct lbs_private *)data;
        unsigned long flags;
 
-       lbs_deb_enter(LBS_DEB_CMD);
        spin_lock_irqsave(&priv->driver_lock, flags);
 
        if (!priv->cur_cmd)
@@ -778,7 +747,6 @@ static void lbs_cmd_timeout_handler(unsigned long data)
        wake_up(&priv->waitq);
 out:
        spin_unlock_irqrestore(&priv->driver_lock, flags);
-       lbs_deb_leave(LBS_DEB_CMD);
 }
 
 /**
@@ -793,7 +761,6 @@ static void lbs_tx_lockup_handler(unsigned long data)
        struct lbs_private *priv = (struct lbs_private *)data;
        unsigned long flags;
 
-       lbs_deb_enter(LBS_DEB_TX);
        spin_lock_irqsave(&priv->driver_lock, flags);
 
        netdev_info(priv->dev, "TX lockup detected\n");
@@ -804,7 +771,6 @@ static void lbs_tx_lockup_handler(unsigned long data)
        wake_up_interruptible(&priv->waitq);
 
        spin_unlock_irqrestore(&priv->driver_lock, flags);
-       lbs_deb_leave(LBS_DEB_TX);
 }
 
 /**
@@ -817,8 +783,6 @@ static void auto_deepsleep_timer_fn(unsigned long data)
 {
        struct lbs_private *priv = (struct lbs_private *)data;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        if (priv->is_activity_detected) {
                priv->is_activity_detected = 0;
        } else {
@@ -836,32 +800,25 @@ static void auto_deepsleep_timer_fn(unsigned long data)
        }
        mod_timer(&priv->auto_deepsleep_timer , jiffies +
                                (priv->auto_deep_sleep_timeout * HZ)/1000);
-       lbs_deb_leave(LBS_DEB_CMD);
 }
 
 int lbs_enter_auto_deep_sleep(struct lbs_private *priv)
 {
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        priv->is_auto_deep_sleep_enabled = 1;
        if (priv->is_deep_sleep)
                priv->wakeup_dev_required = 1;
        mod_timer(&priv->auto_deepsleep_timer ,
                        jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000);
 
-       lbs_deb_leave(LBS_DEB_SDIO);
        return 0;
 }
 
 int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
 {
-       lbs_deb_enter(LBS_DEB_SDIO);
-
        priv->is_auto_deep_sleep_enabled = 0;
        priv->auto_deep_sleep_timeout = 0;
        del_timer(&priv->auto_deepsleep_timer);
 
-       lbs_deb_leave(LBS_DEB_SDIO);
        return 0;
 }
 
@@ -869,8 +826,6 @@ static int lbs_init_adapter(struct lbs_private *priv)
 {
        int ret;
 
-       lbs_deb_enter(LBS_DEB_MAIN);
-
        eth_broadcast_addr(priv->current_addr);
 
        priv->connect_status = LBS_DISCONNECTED;
@@ -921,22 +876,16 @@ static int lbs_init_adapter(struct lbs_private *priv)
        }
 
 out:
-       lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
-
        return ret;
 }
 
 static void lbs_free_adapter(struct lbs_private *priv)
 {
-       lbs_deb_enter(LBS_DEB_MAIN);
-
        lbs_free_cmd_buffer(priv);
        kfifo_free(&priv->event_fifo);
        del_timer(&priv->command_timer);
        del_timer(&priv->tx_lockup_timer);
        del_timer(&priv->auto_deepsleep_timer);
-
-       lbs_deb_leave(LBS_DEB_MAIN);
 }
 
 static const struct net_device_ops lbs_netdev_ops = {
@@ -962,8 +911,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
        struct wireless_dev *wdev;
        struct lbs_private *priv = NULL;
 
-       lbs_deb_enter(LBS_DEB_MAIN);
-
        /* Allocate an Ethernet device and register it */
        wdev = lbs_cfg_alloc(dmdev);
        if (IS_ERR(wdev)) {
@@ -1031,7 +978,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
        priv = NULL;
 
 done:
-       lbs_deb_leave_args(LBS_DEB_MAIN, "priv %p", priv);
        return priv;
 }
 EXPORT_SYMBOL_GPL(lbs_add_card);
@@ -1041,8 +987,6 @@ void lbs_remove_card(struct lbs_private *priv)
 {
        struct net_device *dev = priv->dev;
 
-       lbs_deb_enter(LBS_DEB_MAIN);
-
        lbs_remove_mesh(priv);
 
        if (priv->wiphy_registered)
@@ -1083,8 +1027,6 @@ void lbs_remove_card(struct lbs_private *priv)
        lbs_free_adapter(priv);
        lbs_cfg_free(priv);
        free_netdev(dev);
-
-       lbs_deb_leave(LBS_DEB_MAIN);
 }
 EXPORT_SYMBOL_GPL(lbs_remove_card);
 
@@ -1105,8 +1047,6 @@ int lbs_start_card(struct lbs_private *priv)
        struct net_device *dev = priv->dev;
        int ret = -1;
 
-       lbs_deb_enter(LBS_DEB_MAIN);
-
        /* poke the firmware */
        ret = lbs_setup_firmware(priv);
        if (ret)
@@ -1133,7 +1073,6 @@ int lbs_start_card(struct lbs_private *priv)
        ret = 0;
 
 done:
-       lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
        return ret;
 }
 EXPORT_SYMBOL_GPL(lbs_start_card);
@@ -1143,16 +1082,14 @@ void lbs_stop_card(struct lbs_private *priv)
 {
        struct net_device *dev;
 
-       lbs_deb_enter(LBS_DEB_MAIN);
-
        if (!priv)
-               goto out;
+               return;
        dev = priv->dev;
 
        /* If the netdev isn't registered, it means that lbs_start_card() was
         * never called so we have nothing to do here. */
        if (dev->reg_state != NETREG_REGISTERED)
-               goto out;
+               return;
 
        netif_stop_queue(dev);
        netif_carrier_off(dev);
@@ -1160,9 +1097,6 @@ void lbs_stop_card(struct lbs_private *priv)
        lbs_debugfs_remove_one(priv);
        lbs_deinit_mesh(priv);
        unregister_netdev(dev);
-
-out:
-       lbs_deb_leave(LBS_DEB_MAIN);
 }
 EXPORT_SYMBOL_GPL(lbs_stop_card);
 
@@ -1171,7 +1105,6 @@ void lbs_queue_event(struct lbs_private *priv, u32 event)
 {
        unsigned long flags;
 
-       lbs_deb_enter(LBS_DEB_THREAD);
        spin_lock_irqsave(&priv->driver_lock, flags);
 
        if (priv->psstate == PS_STATE_SLEEP)
@@ -1182,14 +1115,11 @@ void lbs_queue_event(struct lbs_private *priv, u32 event)
        wake_up(&priv->waitq);
 
        spin_unlock_irqrestore(&priv->driver_lock, flags);
-       lbs_deb_leave(LBS_DEB_THREAD);
 }
 EXPORT_SYMBOL_GPL(lbs_queue_event);
 
 void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
 {
-       lbs_deb_enter(LBS_DEB_THREAD);
-
        if (priv->psstate == PS_STATE_SLEEP)
                priv->psstate = PS_STATE_AWAKE;
 
@@ -1198,28 +1128,23 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
        priv->resp_idx = resp_idx;
 
        wake_up(&priv->waitq);
-
-       lbs_deb_leave(LBS_DEB_THREAD);
 }
 EXPORT_SYMBOL_GPL(lbs_notify_command_response);
 
 static int __init lbs_init_module(void)
 {
-       lbs_deb_enter(LBS_DEB_MAIN);
        memset(&confirm_sleep, 0, sizeof(confirm_sleep));
        confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE);
        confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep));
        confirm_sleep.action = cpu_to_le16(PS_MODE_ACTION_SLEEP_CONFIRMED);
        lbs_debugfs_init();
-       lbs_deb_leave(LBS_DEB_MAIN);
+
        return 0;
 }
 
 static void __exit lbs_exit_module(void)
 {
-       lbs_deb_enter(LBS_DEB_MAIN);
        lbs_debugfs_remove();
-       lbs_deb_leave(LBS_DEB_MAIN);
 }
 
 module_init(lbs_init_module);
index d0c881dd584677f18c551657d351b6bee435da5f..eeeb892219aa4c50fb154207d2b8d773b085fd77 100644 (file)
@@ -26,8 +26,6 @@ static int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
 {
        int ret;
 
-       lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
        cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
        cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
        cmd->hdr.result = 0;
@@ -36,7 +34,6 @@ static int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
 
        ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
 
-       lbs_deb_leave(LBS_DEB_CMD);
        return ret;
 }
 
@@ -47,8 +44,6 @@ static int __lbs_mesh_config_send(struct lbs_private *priv,
        int ret;
        u16 command = CMD_MESH_CONFIG_OLD;
 
-       lbs_deb_enter(LBS_DEB_CMD);
-
        /*
         * Command id is 0xac for v10 FW along with mesh interface
         * id in bits 14-13-12.
@@ -66,7 +61,6 @@ static int __lbs_mesh_config_send(struct lbs_private *priv,
 
        ret = lbs_cmd_with_response(priv, command, cmd);
 
-       lbs_deb_leave(LBS_DEB_CMD);
        return ret;
 }
 
@@ -823,8 +817,6 @@ int lbs_init_mesh(struct lbs_private *priv)
 {
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_MESH);
-
        /* Determine mesh_fw_ver from fwrelease and fwcapinfo */
        /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
        /* 5.110.22 have mesh command with 0xa3 command id */
@@ -870,7 +862,6 @@ int lbs_init_mesh(struct lbs_private *priv)
                ret = 1;
        }
 
-       lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
        return ret;
 }
 
@@ -887,14 +878,11 @@ int lbs_deinit_mesh(struct lbs_private *priv)
        struct net_device *dev = priv->dev;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_MESH);
-
        if (priv->mesh_tlv) {
                device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
                ret = 1;
        }
 
-       lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
        return ret;
 }
 
@@ -909,7 +897,6 @@ static int lbs_mesh_stop(struct net_device *dev)
 {
        struct lbs_private *priv = dev->ml_priv;
 
-       lbs_deb_enter(LBS_DEB_MESH);
        lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP,
                lbs_mesh_get_channel(priv));
 
@@ -924,7 +911,6 @@ static int lbs_mesh_stop(struct net_device *dev)
        if (!lbs_iface_active(priv))
                lbs_stop_iface(priv);
 
-       lbs_deb_leave(LBS_DEB_MESH);
        return 0;
 }
 
@@ -939,7 +925,6 @@ static int lbs_mesh_dev_open(struct net_device *dev)
        struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_NET);
        if (!priv->iface_running) {
                ret = lbs_start_iface(priv);
                if (ret)
@@ -965,7 +950,6 @@ static int lbs_mesh_dev_open(struct net_device *dev)
                lbs_mesh_get_channel(priv));
 
 out:
-       lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
        return ret;
 }
 
@@ -989,8 +973,6 @@ static int lbs_add_mesh(struct lbs_private *priv)
        struct wireless_dev *mesh_wdev;
        int ret = 0;
 
-       lbs_deb_enter(LBS_DEB_MESH);
-
        /* Allocate a virtual mesh device */
        mesh_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
        if (!mesh_wdev) {
@@ -1048,7 +1030,6 @@ static int lbs_add_mesh(struct lbs_private *priv)
        kfree(mesh_wdev);
 
 done:
-       lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
        return ret;
 }
 
@@ -1060,7 +1041,6 @@ void lbs_remove_mesh(struct lbs_private *priv)
        if (!mesh_dev)
                return;
 
-       lbs_deb_enter(LBS_DEB_MESH);
        netif_stop_queue(mesh_dev);
        netif_carrier_off(mesh_dev);
        sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
@@ -1069,7 +1049,6 @@ void lbs_remove_mesh(struct lbs_private *priv)
        priv->mesh_dev = NULL;
        kfree(mesh_dev->ieee80211_ptr);
        free_netdev(mesh_dev);
-       lbs_deb_leave(LBS_DEB_MESH);
 }
 
 
@@ -1108,15 +1087,15 @@ void lbs_mesh_set_txpd(struct lbs_private *priv,
  * Ethtool related
  */
 
-static const char * const mesh_stat_strings[] = {
-                       "drop_duplicate_bcast",
-                       "drop_ttl_zero",
-                       "drop_no_fwd_route",
-                       "drop_no_buffers",
-                       "fwded_unicast_cnt",
-                       "fwded_bcast_cnt",
-                       "drop_blind_table",
-                       "tx_failed_cnt"
+static const char mesh_stat_strings[MESH_STATS_NUM][ETH_GSTRING_LEN] = {
+       "drop_duplicate_bcast",
+       "drop_ttl_zero",
+       "drop_no_fwd_route",
+       "drop_no_buffers",
+       "fwded_unicast_cnt",
+       "fwded_bcast_cnt",
+       "drop_blind_table",
+       "tx_failed_cnt"
 };
 
 void lbs_mesh_ethtool_get_stats(struct net_device *dev,
@@ -1126,8 +1105,6 @@ void lbs_mesh_ethtool_get_stats(struct net_device *dev,
        struct cmd_ds_mesh_access mesh_access;
        int ret;
 
-       lbs_deb_enter(LBS_DEB_ETHTOOL);
-
        /* Get Mesh Statistics */
        ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access);
 
@@ -1153,8 +1130,6 @@ void lbs_mesh_ethtool_get_stats(struct net_device *dev,
        data[5] = priv->mstats.fwd_bcast_cnt;
        data[6] = priv->mstats.drop_blind;
        data[7] = priv->mstats.tx_failed_cnt;
-
-       lbs_deb_enter(LBS_DEB_ETHTOOL);
 }
 
 int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset)
@@ -1170,18 +1145,9 @@ int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset)
 void lbs_mesh_ethtool_get_strings(struct net_device *dev,
        uint32_t stringset, uint8_t *s)
 {
-       int i;
-
-       lbs_deb_enter(LBS_DEB_ETHTOOL);
-
        switch (stringset) {
        case ETH_SS_STATS:
-               for (i = 0; i < MESH_STATS_NUM; i++) {
-                       memcpy(s + i * ETH_GSTRING_LEN,
-                                       mesh_stat_strings[i],
-                                       ETH_GSTRING_LEN);
-               }
+               memcpy(s, mesh_stat_strings, sizeof(mesh_stat_strings));
                break;
        }
-       lbs_deb_enter(LBS_DEB_ETHTOOL);
 }
index e446fed7b3459b854b05ab7728c0c15c3ac51e7e..a18bb7a9889ce7989d7a8d80de13cd425b345b8b 100644 (file)
@@ -65,8 +65,6 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
                0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
        };
 
-       lbs_deb_enter(LBS_DEB_RX);
-
        BUG_ON(!skb);
 
        skb->ip_summed = CHECKSUM_NONE;
@@ -158,7 +156,6 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
 
        ret = 0;
 done:
-       lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
        return ret;
 }
 EXPORT_SYMBOL_GPL(lbs_process_rxed_packet);
@@ -221,8 +218,6 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
        struct rx_radiotap_hdr radiotap_hdr;
        struct rx_radiotap_hdr *pradiotap_hdr;
 
-       lbs_deb_enter(LBS_DEB_RX);
-
        p_rx_pkt = (struct rx80211packethdr *) skb->data;
        prxpd = &p_rx_pkt->rx_pd;
 
@@ -281,6 +276,5 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
        ret = 0;
 
 done:
-       lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
        return ret;
 }
index c025f9c1828234ebbac20396c76ae69c05af05da..723ba5fd0bfe2be2c7635fbe19c08a8359571330 100644 (file)
@@ -70,8 +70,6 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        uint16_t pkt_len;
        netdev_tx_t ret = NETDEV_TX_OK;
 
-       lbs_deb_enter(LBS_DEB_TX);
-
        /* We need to protect against the queues being restarted before
           we get round to stopping them */
        spin_lock_irqsave(&priv->driver_lock, flags);
@@ -166,7 +164,6 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        spin_unlock_irqrestore(&priv->driver_lock, flags);
        wake_up(&priv->waitq);
 
-       lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret);
        return ret;
 }
 
index 366eb4991a7d88ffbd2965a43449f74e1ab7e551..238accfe4f41deb9e6505deb2e92d946f2e51cc6 100644 (file)
@@ -128,9 +128,6 @@ void mwifiex_dfs_cac_work_queue(struct work_struct *work)
                        container_of(delayed_work, struct mwifiex_private,
                                     dfs_cac_work);
 
-       if (WARN_ON(!priv))
-               return;
-
        chandef = priv->dfs_chandef;
        if (priv->wdev.cac_started) {
                mwifiex_dbg(priv->adapter, MSG,
@@ -289,9 +286,6 @@ void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
                        container_of(delayed_work, struct mwifiex_private,
                                     dfs_chan_sw_work);
 
-       if (WARN_ON(!priv))
-               return;
-
        bss_cfg = &priv->bss_cfg;
        if (!bss_cfg->beacon_period) {
                mwifiex_dbg(priv->adapter, ERROR,
index c174e79e6df2b656757b37e49d77e9bc446aa093..16c77c27f1b6022cc4e34d23704e421b1e64f77f 100644 (file)
@@ -653,11 +653,13 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
 void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
 {
        struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
+       unsigned long flags;
 
+       spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
        if (list_empty(&priv->rx_reorder_tbl_ptr)) {
                dev_dbg(priv->adapter->dev,
                        "mwifiex_11n_delba: rx_reorder_tbl_ptr empty\n");
-               return;
+               goto exit;
        }
 
        list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) {
@@ -666,9 +668,11 @@ void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
                                "Send delba to tid=%d, %pM\n",
                                tid, rx_reor_tbl_ptr->ta);
                        mwifiex_send_delba(priv, tid, rx_reor_tbl_ptr->ta, 0);
-                       return;
+                       goto exit;
                }
        }
+exit:
+       spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
 }
 
 /*
@@ -764,14 +768,9 @@ void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra)
                return;
 
        spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
-       list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list) {
-               if (!memcmp(tbl->ra, ra, ETH_ALEN)) {
-                       spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
-                                              flags);
+       list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list)
+               if (!memcmp(tbl->ra, ra, ETH_ALEN))
                        mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, tbl);
-                       spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
-               }
-       }
        spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
 
        return;
index a75013ac84d7ccdd147f68bc9b10cba667cfeb7f..53e67526f40d5dd524736b06f5ffdf6e0b767525 100644 (file)
@@ -164,7 +164,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
        int pad = 0, aggr_num = 0, ret;
        struct mwifiex_tx_param tx_param;
        struct txpd *ptx_pd = NULL;
-       int headroom = adapter->iface_type == MWIFIEX_USB ? 0 : INTF_HEADER_LEN;
+       int headroom = adapter->intf_hdr_len;
 
        skb_src = skb_peek(&pra_list->skb_head);
        if (!skb_src) {
@@ -250,15 +250,15 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
                return 0;
        }
 
+       if (skb_src)
+               tx_param.next_pkt_len = skb_src->len + sizeof(struct txpd);
+       else
+               tx_param.next_pkt_len = 0;
+
        if (adapter->iface_type == MWIFIEX_USB) {
                ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
-                                                  skb_aggr, NULL);
+                                                  skb_aggr, &tx_param);
        } else {
-               if (skb_src)
-                       tx_param.next_pkt_len =
-                                       skb_src->len + sizeof(struct txpd);
-               else
-                       tx_param.next_pkt_len = 0;
 
                ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
                                                   skb_aggr, &tx_param);
index 7ec06bf13413bfaf6fb1153cc9a2a34a14e51c1f..025bc06a19d66ef03101e8e8d2079d1ede2da8b9 100644 (file)
@@ -2964,10 +2964,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
        if (!dev) {
                mwifiex_dbg(adapter, ERROR,
                            "no memory available for netdevice\n");
-               memset(&priv->wdev, 0, sizeof(priv->wdev));
-               priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-               priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-               return ERR_PTR(-ENOMEM);
+               ret = -ENOMEM;
+               goto err_alloc_netdev;
        }
 
        mwifiex_init_priv_params(priv, dev);
@@ -2976,11 +2974,11 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
        ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
                               HostCmd_ACT_GEN_SET, 0, NULL, true);
        if (ret)
-               return ERR_PTR(ret);
+               goto err_set_bss_mode;
 
        ret = mwifiex_sta_init_cmd(priv, false, false);
        if (ret)
-               return ERR_PTR(ret);
+               goto err_sta_init;
 
        mwifiex_setup_ht_caps(&wiphy->bands[NL80211_BAND_2GHZ]->ht_cap, priv);
        if (adapter->is_hw_11ac_capable)
@@ -3011,31 +3009,14 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 
        SET_NETDEV_DEV(dev, adapter->dev);
 
-       /* Register network device */
-       if (register_netdevice(dev)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cannot register virtual network device\n");
-               free_netdev(dev);
-               priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-               priv->netdev = NULL;
-               memset(&priv->wdev, 0, sizeof(priv->wdev));
-               priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-               return ERR_PTR(-EFAULT);
-       }
-
        priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",
                                                  WQ_HIGHPRI |
                                                  WQ_MEM_RECLAIM |
                                                  WQ_UNBOUND, 1, name);
        if (!priv->dfs_cac_workqueue) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cannot register virtual network device\n");
-               free_netdev(dev);
-               priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-               priv->netdev = NULL;
-               memset(&priv->wdev, 0, sizeof(priv->wdev));
-               priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-               return ERR_PTR(-ENOMEM);
+               mwifiex_dbg(adapter, ERROR, "cannot alloc DFS CAC queue\n");
+               ret = -ENOMEM;
+               goto err_alloc_cac;
        }
 
        INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);
@@ -3044,16 +3025,9 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
                                                      WQ_HIGHPRI | WQ_UNBOUND |
                                                      WQ_MEM_RECLAIM, 1, name);
        if (!priv->dfs_chan_sw_workqueue) {
-               mwifiex_dbg(adapter, ERROR,
-                           "cannot register virtual network device\n");
-               free_netdev(dev);
-               priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-               priv->netdev = NULL;
-               memset(&priv->wdev, 0, sizeof(priv->wdev));
-               priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-               destroy_workqueue(priv->dfs_cac_workqueue);
-               priv->dfs_cac_workqueue = NULL;
-               return ERR_PTR(-ENOMEM);
+               mwifiex_dbg(adapter, ERROR, "cannot alloc DFS channel sw queue\n");
+               ret = -ENOMEM;
+               goto err_alloc_chsw;
        }
 
        INIT_DELAYED_WORK(&priv->dfs_chan_sw_work,
@@ -3061,6 +3035,13 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 
        sema_init(&priv->async_sem, 1);
 
+       /* Register network device */
+       if (register_netdevice(dev)) {
+               mwifiex_dbg(adapter, ERROR, "cannot register network device\n");
+               ret = -EFAULT;
+               goto err_reg_netdev;
+       }
+
        mwifiex_dbg(adapter, INFO,
                    "info: %s: Marvell 802.11 Adapter\n", dev->name);
 
@@ -3081,11 +3062,29 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
                adapter->curr_iface_comb.p2p_intf++;
                break;
        default:
+               /* This should be dead code; checked above */
                mwifiex_dbg(adapter, ERROR, "type not supported\n");
                return ERR_PTR(-EINVAL);
        }
 
        return &priv->wdev;
+
+err_reg_netdev:
+       destroy_workqueue(priv->dfs_chan_sw_workqueue);
+       priv->dfs_chan_sw_workqueue = NULL;
+err_alloc_chsw:
+       destroy_workqueue(priv->dfs_cac_workqueue);
+       priv->dfs_cac_workqueue = NULL;
+err_alloc_cac:
+       free_netdev(dev);
+       priv->netdev = NULL;
+err_sta_init:
+err_set_bss_mode:
+err_alloc_netdev:
+       memset(&priv->wdev, 0, sizeof(priv->wdev));
+       priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+       priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+       return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
 
index 0c3b217247b145a9f823f9f73d1233070e87f542..40c3fe5ab8ca35d3fa5726a851569ac3841eaaae 100644 (file)
@@ -258,10 +258,10 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
                if (ret == -EBUSY)
                        cmd_node->cmd_skb = NULL;
        } else {
-               skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN);
+               skb_push(cmd_node->cmd_skb, adapter->intf_hdr_len);
                ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
                                                   cmd_node->cmd_skb, NULL);
-               skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN);
+               skb_pull(cmd_node->cmd_skb, adapter->intf_hdr_len);
        }
 
        if (ret == -1) {
@@ -351,10 +351,10 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
                if (ret != -EBUSY)
                        dev_kfree_skb_any(sleep_cfm_tmp);
        } else {
-               skb_push(adapter->sleep_cfm, INTF_HEADER_LEN);
+               skb_push(adapter->sleep_cfm, adapter->intf_hdr_len);
                ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
                                                   adapter->sleep_cfm, NULL);
-               skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN);
+               skb_pull(adapter->sleep_cfm, adapter->intf_hdr_len);
        }
 
        if (ret == -1) {
@@ -761,8 +761,6 @@ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
        }
        cmd_node = list_first_entry(&adapter->cmd_pending_q,
                                    struct cmd_ctrl_node, list);
-       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
-                              cmd_pending_q_flags);
 
        host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
        priv = cmd_node->priv;
@@ -771,11 +769,12 @@ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
                mwifiex_dbg(adapter, ERROR,
                            "%s: cannot send cmd in sleep state,\t"
                            "this should not happen\n", __func__);
+               spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
+                                      cmd_pending_q_flags);
                spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
                return ret;
        }
 
-       spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags);
        list_del(&cmd_node->list);
        spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
                               cmd_pending_q_flags);
@@ -1056,12 +1055,10 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
        list_for_each_entry_safe(cmd_node, tmp_node,
                                 &adapter->cmd_pending_q, list) {
                list_del(&cmd_node->list);
-               spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
 
                if (cmd_node->wait_q_enabled)
                        adapter->cmd_wait_q.status = -1;
                mwifiex_recycle_cmd_node(adapter, cmd_node);
-               spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
        }
        spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
        spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
index 6cf9ab9133ea37145c7ccb59d527b1e41b5cf2ea..b4d915b9232c9c207b64958d0c684636adbd4e0d 100644 (file)
@@ -405,6 +405,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define HostCmd_CMD_TDLS_OPER                         0x0122
 #define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG               0x0223
 #define HostCmd_CMD_CHAN_REGION_CFG                  0x0242
+#define HostCmd_CMD_PACKET_AGGR_CTRL                 0x0251
 
 #define PROTOCOL_NO_SECURITY        0x01
 #define PROTOCOL_STATIC_WEP         0x02
@@ -2268,6 +2269,14 @@ struct host_cmd_ds_chan_region_cfg {
        __le16 action;
 } __packed;
 
+struct host_cmd_ds_pkt_aggr_ctrl {
+       __le16 action;
+       __le16 enable;
+       __le16 tx_aggr_max_size;
+       __le16 tx_aggr_max_num;
+       __le16 tx_aggr_align;
+} __packed;
+
 struct host_cmd_ds_command {
        __le16 command;
        __le16 size;
@@ -2343,6 +2352,7 @@ struct host_cmd_ds_command {
                struct host_cmd_ds_wakeup_reason hs_wakeup_reason;
                struct host_cmd_ds_gtk_rekey_params rekey;
                struct host_cmd_ds_chan_region_cfg reg_cfg;
+               struct host_cmd_ds_pkt_aggr_ctrl pkt_aggr_ctrl;
        } params;
 } __packed;
 
index 756948385b60166cc02f9cd66aeb0584513e67ee..3ecb59f7405b1fae27846ec0e52ffaa548a49bab 100644 (file)
@@ -217,6 +217,11 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
        else
                adapter->data_sent = false;
 
+       if (adapter->iface_type == MWIFIEX_USB)
+               adapter->intf_hdr_len = 0;
+       else
+               adapter->intf_hdr_len = INTF_HEADER_LEN;
+
        adapter->cmd_resp_received = false;
        adapter->event_received = false;
        adapter->data_received = false;
@@ -409,11 +414,6 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
 static void
 mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
 {
-       if (!adapter) {
-               pr_err("%s: adapter is NULL\n", __func__);
-               return;
-       }
-
        del_timer(&adapter->wakeup_timer);
        mwifiex_cancel_all_pending_cmd(adapter);
        wake_up_interruptible(&adapter->cmd_wait_q.wait);
@@ -439,7 +439,6 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
        struct mwifiex_private *priv;
        s32 i, j;
 
-       spin_lock_init(&adapter->mwifiex_lock);
        spin_lock_init(&adapter->int_lock);
        spin_lock_init(&adapter->main_proc_lock);
        spin_lock_init(&adapter->mwifiex_cmd_lock);
@@ -670,8 +669,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
 
                        mwifiex_clean_auto_tdls(priv);
                        mwifiex_abort_cac(priv);
-                       mwifiex_clean_txrx(priv);
-                       mwifiex_delete_bss_prio_tbl(priv);
+                       mwifiex_free_priv(priv);
                }
        }
 
@@ -694,11 +692,8 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
 
        spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
 
-       spin_lock(&adapter->mwifiex_lock);
-
        mwifiex_adapter_cleanup(adapter);
 
-       spin_unlock(&adapter->mwifiex_lock);
        adapter->hw_status = MWIFIEX_HW_STATUS_NOT_READY;
 }
 
index dd87b9ff64c371911a74308be55e93e3a46cdd43..2c42191293c3f70d711a62b429896f670dba49b3 100644 (file)
@@ -44,6 +44,10 @@ bool mfg_mode;
 module_param(mfg_mode, bool, 0);
 MODULE_PARM_DESC(mfg_mode, "manufacturing mode enable:1, disable:0");
 
+bool aggr_ctrl;
+module_param(aggr_ctrl, bool, 0000);
+MODULE_PARM_DESC(aggr_ctrl, "usb tx aggreataon enable:1, disable:0");
+
 /*
  * This function registers the device and performs all the necessary
  * initializations.
index bb2a467d8b133dd21dbe7fd918a77e82bac46992..c37fb260650260387554108fd90607c0f083ffee 100644 (file)
@@ -60,6 +60,7 @@
 
 extern const char driver_version[];
 extern bool mfg_mode;
+extern bool aggr_ctrl;
 
 struct mwifiex_adapter;
 struct mwifiex_private;
@@ -798,6 +799,18 @@ struct mwifiex_auto_tdls_peer {
        u8 do_setup;
 };
 
+#define MWIFIEX_TYPE_AGGR_DATA_V2 11
+#define MWIFIEX_BUS_AGGR_MODE_LEN_V2 (2)
+#define MWIFIEX_BUS_AGGR_MAX_LEN 16000
+#define MWIFIEX_BUS_AGGR_MAX_NUM 10
+struct bus_aggr_params {
+       u16 enable;
+       u16 mode;
+       u16 tx_aggr_max_size;
+       u16 tx_aggr_max_num;
+       u16 tx_aggr_align;
+};
+
 struct mwifiex_if_ops {
        int (*init_if) (struct mwifiex_adapter *);
        void (*cleanup_if) (struct mwifiex_adapter *);
@@ -849,6 +862,7 @@ struct mwifiex_adapter {
        u8 perm_addr[ETH_ALEN];
        bool surprise_removed;
        u32 fw_release_number;
+       u8 intf_hdr_len;
        u16 init_wait_q_woken;
        wait_queue_head_t init_wait_q;
        void *card;
@@ -870,8 +884,6 @@ struct mwifiex_adapter {
        bool rx_locked;
        bool main_locked;
        struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM];
-       /* spin lock for init/shutdown */
-       spinlock_t mwifiex_lock;
        /* spin lock for main process */
        spinlock_t main_proc_lock;
        u32 mwifiex_processing;
@@ -1017,6 +1029,8 @@ struct mwifiex_adapter {
        /* Wake-on-WLAN (WoWLAN) */
        int irq_wakeup;
        bool wake_by_wifi;
+       /* Aggregation parameters*/
+       struct bus_aggr_params bus_aggr;
 };
 
 void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1235,7 +1249,8 @@ mwifiex_queuing_ra_based(struct mwifiex_private *priv)
         * Currently we assume if we are in Infra, then DA=RA. This might not be
         * true in the future
         */
-       if ((priv->bss_mode == NL80211_IFTYPE_STATION) &&
+       if ((priv->bss_mode == NL80211_IFTYPE_STATION ||
+            priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) &&
            (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA))
                return false;
 
index ac62bce50e964b900135cdc600dcdb9032928a3f..b53ecf1edddae1f1c7966f23cd2d2d2aa5ba9335 100644 (file)
@@ -370,7 +370,6 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
                 * PCIe and HW.
                 */
                mwifiex_shutdown_sw(adapter);
-               adapter->surprise_removed = true;
                clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
                clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
        } else {
@@ -378,7 +377,6 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
                 * after performing FLR respectively. Reconfigure the software
                 * and firmware including firmware redownload
                 */
-               adapter->surprise_removed = false;
                ret = mwifiex_reinit_sw(adapter);
                if (ret) {
                        dev_err(&pdev->dev, "reinit failed: %d\n", ret);
@@ -1391,7 +1389,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
                 * first 2 bytes for len, next 2 bytes is for type
                 */
                rx_len = get_unaligned_le16(skb_data->data);
-               if (WARN_ON(rx_len <= INTF_HEADER_LEN ||
+               if (WARN_ON(rx_len <= adapter->intf_hdr_len ||
                            rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) {
                        mwifiex_dbg(adapter, ERROR,
                                    "Invalid RX len %d, Rd=%#x, Wr=%#x\n",
@@ -1402,7 +1400,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
                        mwifiex_dbg(adapter, DATA,
                                    "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
                                    card->rxbd_rdptr, wrptr, rx_len);
-                       skb_pull(skb_data, INTF_HEADER_LEN);
+                       skb_pull(skb_data, adapter->intf_hdr_len);
                        if (adapter->rx_work_enabled) {
                                skb_queue_tail(&adapter->rx_data_q, skb_data);
                                adapter->data_received = true;
@@ -1736,7 +1734,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
                                                       MWIFIEX_MAX_DELAY_COUNT);
                        mwifiex_unmap_pci_memory(adapter, skb,
                                                 PCI_DMA_FROMDEVICE);
-                       skb_pull(skb, INTF_HEADER_LEN);
+                       skb_pull(skb, adapter->intf_hdr_len);
                        while (reg->sleep_cookie && (count++ < 10) &&
                               mwifiex_pcie_ok_to_access_hw(adapter))
                                usleep_range(50, 60);
@@ -1749,12 +1747,12 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
                }
                memcpy(adapter->upld_buf, skb->data,
                       min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
-               skb_push(skb, INTF_HEADER_LEN);
+               skb_push(skb, adapter->intf_hdr_len);
                if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
                                           PCI_DMA_FROMDEVICE))
                        return -1;
        } else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
-               skb_pull(skb, INTF_HEADER_LEN);
+               skb_pull(skb, adapter->intf_hdr_len);
                adapter->curr_cmd->resp_skb = skb;
                adapter->cmd_resp_received = true;
                /* Take the pointer and set it to CMD node and will
@@ -1791,7 +1789,7 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
 
        if (skb) {
                card->cmdrsp_buf = skb;
-               skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
+               skb_push(card->cmdrsp_buf, adapter->intf_hdr_len);
                if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
                                           PCI_DMA_FROMDEVICE))
                        return -1;
@@ -1856,14 +1854,15 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
                desc = card->evtbd_ring[rdptr];
                memset(desc, 0, sizeof(*desc));
 
-               event = get_unaligned_le32(&skb_cmd->data[INTF_HEADER_LEN]);
+               event = get_unaligned_le32(
+                       &skb_cmd->data[adapter->intf_hdr_len]);
                adapter->event_cause = event;
                /* The first 4bytes will be the event transfer header
                   len is 2 bytes followed by type which is 2 bytes */
                memcpy(&data_len, skb_cmd->data, sizeof(__le16));
                evt_len = le16_to_cpu(data_len);
                skb_trim(skb_cmd, evt_len);
-               skb_pull(skb_cmd, INTF_HEADER_LEN);
+               skb_pull(skb_cmd, adapter->intf_hdr_len);
                mwifiex_dbg(adapter, EVENT,
                            "info: Event length: %d\n", evt_len);
 
@@ -1922,7 +1921,7 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
        }
 
        if (!card->evt_buf_list[rdptr]) {
-               skb_push(skb, INTF_HEADER_LEN);
+               skb_push(skb, adapter->intf_hdr_len);
                skb_put(skb, MAX_EVENT_SIZE - skb->len);
                if (mwifiex_map_pci_memory(adapter, skb,
                                           MAX_EVENT_SIZE,
@@ -2380,11 +2379,6 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
        struct pcie_service_card *card;
        struct mwifiex_adapter *adapter;
 
-       if (!pdev) {
-               pr_err("info: %s: pdev is NULL\n", __func__);
-               goto exit;
-       }
-
        card = pci_get_drvdata(pdev);
 
        if (!card->adapter) {
@@ -2822,6 +2816,13 @@ static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
        mwifiex_upload_device_dump(adapter, drv_info, drv_info_size);
 }
 
+static void mwifiex_pcie_card_reset_work(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+
+       pci_reset_function(card->dev);
+}
+
 static void mwifiex_pcie_work(struct work_struct *work)
 {
        struct pcie_service_card *card =
@@ -2830,6 +2831,9 @@ static void mwifiex_pcie_work(struct work_struct *work)
        if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
                               &card->work_flags))
                mwifiex_pcie_device_dump_work(card->adapter);
+       if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET,
+                              &card->work_flags))
+               mwifiex_pcie_card_reset_work(card->adapter);
 }
 
 /* This function dumps FW information */
@@ -2837,12 +2841,72 @@ static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
 {
        struct pcie_service_card *card = adapter->card;
 
-       if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags))
-               return;
+       if (!test_and_set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
+                             &card->work_flags))
+               schedule_work(&card->work);
+}
+
+static void mwifiex_pcie_card_reset(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+
+       if (!test_and_set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags))
+               schedule_work(&card->work);
+}
+
+static int mwifiex_pcie_alloc_buffers(struct mwifiex_adapter *adapter)
+{
+       struct pcie_service_card *card = adapter->card;
+       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       int ret;
+
+       card->cmdrsp_buf = NULL;
+       ret = mwifiex_pcie_create_txbd_ring(adapter);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR, "Failed to create txbd ring\n");
+               goto err_cre_txbd;
+       }
+
+       ret = mwifiex_pcie_create_rxbd_ring(adapter);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR, "Failed to create rxbd ring\n");
+               goto err_cre_rxbd;
+       }
+
+       ret = mwifiex_pcie_create_evtbd_ring(adapter);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR, "Failed to create evtbd ring\n");
+               goto err_cre_evtbd;
+       }
 
-       set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
+       ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR, "Failed to allocate cmdbuf buffer\n");
+               goto err_alloc_cmdbuf;
+       }
 
-       schedule_work(&card->work);
+       if (reg->sleep_cookie) {
+               ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
+               if (ret) {
+                       mwifiex_dbg(adapter, ERROR, "Failed to allocate sleep_cookie buffer\n");
+                       goto err_alloc_cookie;
+               }
+       } else {
+               card->sleep_cookie_vbase = NULL;
+       }
+
+       return 0;
+
+err_alloc_cookie:
+       mwifiex_pcie_delete_cmdrsp_buf(adapter);
+err_alloc_cmdbuf:
+       mwifiex_pcie_delete_evtbd_ring(adapter);
+err_cre_evtbd:
+       mwifiex_pcie_delete_rxbd_ring(adapter);
+err_cre_rxbd:
+       mwifiex_pcie_delete_txbd_ring(adapter);
+err_cre_txbd:
+       return ret;
 }
 
 static void mwifiex_pcie_free_buffers(struct mwifiex_adapter *adapter)
@@ -2862,20 +2926,12 @@ static void mwifiex_pcie_free_buffers(struct mwifiex_adapter *adapter)
 
 /*
  * This function initializes the PCI-E host memory space, WCB rings, etc.
- *
- * The following initializations steps are followed -
- *      - Allocate TXBD ring buffers
- *      - Allocate RXBD ring buffers
- *      - Allocate event BD ring buffers
- *      - Allocate command response ring buffer
- *      - Allocate sleep cookie buffer
  */
 static int mwifiex_init_pcie(struct mwifiex_adapter *adapter)
 {
        struct pcie_service_card *card = adapter->card;
        int ret;
        struct pci_dev *pdev = card->dev;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 
        pci_set_drvdata(pdev, card);
 
@@ -2924,37 +2980,13 @@ static int mwifiex_init_pcie(struct mwifiex_adapter *adapter)
        pr_notice("PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
                  card->pci_mmap, card->pci_mmap1);
 
-       card->cmdrsp_buf = NULL;
-       ret = mwifiex_pcie_create_txbd_ring(adapter);
-       if (ret)
-               goto err_cre_txbd;
-       ret = mwifiex_pcie_create_rxbd_ring(adapter);
+       ret = mwifiex_pcie_alloc_buffers(adapter);
        if (ret)
-               goto err_cre_rxbd;
-       ret = mwifiex_pcie_create_evtbd_ring(adapter);
-       if (ret)
-               goto err_cre_evtbd;
-       ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
-       if (ret)
-               goto err_alloc_cmdbuf;
-       if (reg->sleep_cookie) {
-               ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
-               if (ret)
-                       goto err_alloc_cookie;
-       } else {
-               card->sleep_cookie_vbase = NULL;
-       }
-       return ret;
+               goto err_alloc_buffers;
 
-err_alloc_cookie:
-       mwifiex_pcie_delete_cmdrsp_buf(adapter);
-err_alloc_cmdbuf:
-       mwifiex_pcie_delete_evtbd_ring(adapter);
-err_cre_evtbd:
-       mwifiex_pcie_delete_rxbd_ring(adapter);
-err_cre_rxbd:
-       mwifiex_pcie_delete_txbd_ring(adapter);
-err_cre_txbd:
+       return 0;
+
+err_alloc_buffers:
        pci_iounmap(pdev, card->pci_mmap1);
 err_iomap2:
        pci_release_region(pdev, 2);
@@ -3168,73 +3200,25 @@ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
        card->adapter = NULL;
 }
 
-/* This function initializes the PCI-E host memory space, WCB rings, etc.
- *
- * The following initializations steps are followed -
- *      - Allocate TXBD ring buffers
- *      - Allocate RXBD ring buffers
- *      - Allocate event BD ring buffers
- *      - Allocate command response ring buffer
- *      - Allocate sleep cookie buffer
- * Part of mwifiex_init_pcie(), not reset the PCIE registers
+/*
+ * This function initializes the PCI-E host memory space, WCB rings, etc.,
+ * similar to mwifiex_init_pcie(), but without resetting PCI-E state.
  */
 static void mwifiex_pcie_up_dev(struct mwifiex_adapter *adapter)
 {
        struct pcie_service_card *card = adapter->card;
        int ret;
        struct pci_dev *pdev = card->dev;
-       const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 
        /* tx_buf_size might be changed to 3584 by firmware during
         * data transfer, we should reset it to default size.
         */
        adapter->tx_buf_size = card->pcie.tx_buf_size;
 
-       card->cmdrsp_buf = NULL;
-       ret = mwifiex_pcie_create_txbd_ring(adapter);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR, "Failed to create txbd ring\n");
-               goto err_cre_txbd;
-       }
-
-       ret = mwifiex_pcie_create_rxbd_ring(adapter);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR, "Failed to create rxbd ring\n");
-               goto err_cre_rxbd;
-       }
-
-       ret = mwifiex_pcie_create_evtbd_ring(adapter);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR, "Failed to create evtbd ring\n");
-               goto err_cre_evtbd;
-       }
-
-       ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
-       if (ret) {
-               mwifiex_dbg(adapter, ERROR, "Failed to allocate cmdbuf buffer\n");
-               goto err_alloc_cmdbuf;
-       }
-
-       if (reg->sleep_cookie) {
-               ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
-               if (ret) {
-                       mwifiex_dbg(adapter, ERROR, "Failed to allocate sleep_cookie buffer\n");
-                       goto err_alloc_cookie;
-               }
-       } else {
-               card->sleep_cookie_vbase = NULL;
-       }
-       return;
+       ret = mwifiex_pcie_alloc_buffers(adapter);
+       if (!ret)
+               return;
 
-err_alloc_cookie:
-       mwifiex_pcie_delete_cmdrsp_buf(adapter);
-err_alloc_cmdbuf:
-       mwifiex_pcie_delete_evtbd_ring(adapter);
-err_cre_evtbd:
-       mwifiex_pcie_delete_rxbd_ring(adapter);
-err_cre_rxbd:
-       mwifiex_pcie_delete_txbd_ring(adapter);
-err_cre_txbd:
        pci_iounmap(pdev, card->pci_mmap1);
 }
 
@@ -3274,6 +3258,7 @@ static struct mwifiex_if_ops pcie_ops = {
        .cleanup_mpa_buf =              NULL,
        .init_fw_port =                 mwifiex_pcie_init_fw_port,
        .clean_pcie_ring =              mwifiex_clean_pcie_ring_buf,
+       .card_reset =                   mwifiex_pcie_card_reset,
        .reg_dump =                     mwifiex_pcie_reg_dump,
        .device_dump =                  mwifiex_pcie_device_dump,
        .down_dev =                     mwifiex_pcie_down_dev,
index 0af1c6733c9257e64fbecd81e11fb76ec871452a..f81a006668f3d63ba3e1c7a81e49656b9c43db12 100644 (file)
@@ -1125,7 +1125,7 @@ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
        data = skb->data;
        total_pkt_len = skb->len;
 
-       while (total_pkt_len >= (SDIO_HEADER_OFFSET + INTF_HEADER_LEN)) {
+       while (total_pkt_len >= (SDIO_HEADER_OFFSET + adapter->intf_hdr_len)) {
                if (total_pkt_len < adapter->sdio_rx_block_size)
                        break;
                blk_num = *(data + BLOCK_NUMBER_OFFSET);
@@ -1152,7 +1152,7 @@ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
                        break;
                skb_put(skb_deaggr, pkt_len);
                memcpy(skb_deaggr->data, data + SDIO_HEADER_OFFSET, pkt_len);
-               skb_pull(skb_deaggr, INTF_HEADER_LEN);
+               skb_pull(skb_deaggr, adapter->intf_hdr_len);
 
                mwifiex_handle_rx_packet(adapter, skb_deaggr);
                data += blk_size;
@@ -1178,7 +1178,7 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
 
        if (upld_typ != MWIFIEX_TYPE_AGGR_DATA) {
                skb_trim(skb, pkt_len);
-               skb_pull(skb, INTF_HEADER_LEN);
+               skb_pull(skb, adapter->intf_hdr_len);
        }
 
        switch (upld_typ) {
@@ -1537,7 +1537,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                rx_len = card->mp_regs[reg->cmd_rd_len_1] << 8;
                rx_len |= (u16)card->mp_regs[reg->cmd_rd_len_0];
                rx_blocks = DIV_ROUND_UP(rx_len, MWIFIEX_SDIO_BLOCK_SIZE);
-               if (rx_len <= INTF_HEADER_LEN ||
+               if (rx_len <= adapter->intf_hdr_len ||
                    (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
                     MWIFIEX_RX_DATA_BUF_SIZE)
                        return -1;
@@ -1635,7 +1635,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                        rx_blocks =
                                (rx_len + MWIFIEX_SDIO_BLOCK_SIZE -
                                 1) / MWIFIEX_SDIO_BLOCK_SIZE;
-                       if (rx_len <= INTF_HEADER_LEN ||
+                       if (rx_len <= adapter->intf_hdr_len ||
                            (card->mpa_rx.enabled &&
                             ((rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
                              card->mpa_rx.buf_size))) {
@@ -1896,7 +1896,7 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
                adapter->cmd_sent = true;
                /* Type must be MWIFIEX_TYPE_CMD */
 
-               if (pkt_len <= INTF_HEADER_LEN ||
+               if (pkt_len <= adapter->intf_hdr_len ||
                    pkt_len > MWIFIEX_UPLD_SIZE)
                        mwifiex_dbg(adapter, ERROR,
                                    "%s: payload=%p, nb=%d\n",
@@ -2533,12 +2533,8 @@ static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter)
 {
        struct sdio_mmc_card *card = adapter->card;
 
-       if (test_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags))
-               return;
-
-       set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
-
-       schedule_work(&card->work);
+       if (!test_and_set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags))
+               schedule_work(&card->work);
 }
 
 /* This function dumps FW information */
@@ -2546,11 +2542,9 @@ static void mwifiex_sdio_device_dump(struct mwifiex_adapter *adapter)
 {
        struct sdio_mmc_card *card = adapter->card;
 
-       if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags))
-               return;
-
-       set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
-       schedule_work(&card->work);
+       if (!test_and_set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
+                             &card->work_flags))
+               schedule_work(&card->work);
 }
 
 /* Function to dump SDIO function registers and SDIO scratch registers in case
index 83916c1439af767ca4d03c2fab046170e44492d0..534d94a206a5d23dc0a1edceda7788041b892b9d 100644 (file)
@@ -2064,6 +2064,15 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
        case HostCmd_CMD_11AC_CFG:
                ret = mwifiex_cmd_11ac_cfg(priv, cmd_ptr, cmd_action, data_buf);
                break;
+       case HostCmd_CMD_PACKET_AGGR_CTRL:
+               cmd_ptr->command = cpu_to_le16(cmd_no);
+               cmd_ptr->params.pkt_aggr_ctrl.action = cpu_to_le16(cmd_action);
+               cmd_ptr->params.pkt_aggr_ctrl.enable =
+                                               cpu_to_le16(*(u16 *)data_buf);
+               cmd_ptr->size =
+                       cpu_to_le16(sizeof(struct host_cmd_ds_pkt_aggr_ctrl) +
+                                   S_DS_GEN);
+               break;
        case HostCmd_CMD_P2P_MODE_CFG:
                cmd_ptr->command = cpu_to_le16(cmd_no);
                cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action);
@@ -2241,6 +2250,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
        enum state_11d_t state_11d;
        struct mwifiex_ds_11n_tx_cfg tx_cfg;
        u8 sdio_sp_rx_aggr_enable;
+       u16 packet_aggr_enable;
        int data;
 
        if (first_sta) {
@@ -2387,6 +2397,14 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
                                    "11D: failed to enable 11D\n");
        }
 
+       /* Pacekt aggregation handshake with firmware */
+       if (aggr_ctrl) {
+               packet_aggr_enable = true;
+               mwifiex_send_cmd(priv, HostCmd_CMD_PACKET_AGGR_CTRL,
+                                HostCmd_ACT_GEN_SET, 0,
+                                &packet_aggr_enable, true);
+       }
+
        /* Send cmd to FW to configure 11n specific configuration
         * (Short GI, Channel BW, Green field support etc.) for transmit
         */
index f1d1f56fc23ff739c3766e38bc723337a581ccb6..3348fb3a7514c31c585484089aa2eaf167fadff3 100644 (file)
@@ -1154,6 +1154,27 @@ static int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv,
        return 0;
 }
 
+int mwifiex_ret_pkt_aggr_ctrl(struct mwifiex_private *priv,
+                             struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_pkt_aggr_ctrl *pkt_aggr_ctrl =
+                                       &resp->params.pkt_aggr_ctrl;
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       adapter->bus_aggr.enable = le16_to_cpu(pkt_aggr_ctrl->enable);
+       if (adapter->bus_aggr.enable)
+               adapter->intf_hdr_len = INTF_HEADER_LEN;
+       adapter->bus_aggr.mode = MWIFIEX_BUS_AGGR_MODE_LEN_V2;
+       adapter->bus_aggr.tx_aggr_max_size =
+                               le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_size);
+       adapter->bus_aggr.tx_aggr_max_num =
+                               le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_num);
+       adapter->bus_aggr.tx_aggr_align =
+                               le16_to_cpu(pkt_aggr_ctrl->tx_aggr_align);
+
+       return 0;
+}
+
 /*
  * This function handles the command responses.
  *
@@ -1255,6 +1276,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
                break;
        case HostCmd_CMD_11AC_CFG:
                break;
+       case HostCmd_CMD_PACKET_AGGR_CTRL:
+               ret = mwifiex_ret_pkt_aggr_ctrl(priv, resp);
+               break;
        case HostCmd_CMD_P2P_MODE_CFG:
                ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
                break;
index f6683ea6bd5ddfb64a64c0168ea26db346c45281..620f8650a74200290a7fd98561b3f0b6ec5afc4a 100644 (file)
@@ -49,8 +49,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
        struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
        unsigned int pad;
        u16 pkt_type, pkt_offset;
-       int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 :
-                      INTF_HEADER_LEN;
+       int hroom = adapter->intf_hdr_len;
 
        if (!skb->len) {
                mwifiex_dbg(adapter, ERROR,
@@ -116,7 +115,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
 
        local_tx_pd->tx_pkt_offset = cpu_to_le16(pkt_offset);
 
-       /* make space for INTF_HEADER_LEN */
+       /* make space for adapter->intf_hdr_len */
        skb_push(skb, hroom);
 
        if (!local_tx_pd->tx_control)
@@ -165,8 +164,9 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
        memset(tx_info, 0, sizeof(*tx_info));
        tx_info->bss_num = priv->bss_num;
        tx_info->bss_type = priv->bss_type;
-       tx_info->pkt_len = data_len - (sizeof(struct txpd) + INTF_HEADER_LEN);
-       skb_reserve(skb, sizeof(struct txpd) + INTF_HEADER_LEN);
+       tx_info->pkt_len = data_len -
+                       (sizeof(struct txpd) + adapter->intf_hdr_len);
+       skb_reserve(skb, sizeof(struct txpd) + adapter->intf_hdr_len);
        skb_push(skb, sizeof(struct txpd));
 
        local_tx_pd = (struct txpd *) skb->data;
@@ -177,11 +177,11 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
        local_tx_pd->bss_num = priv->bss_num;
        local_tx_pd->bss_type = priv->bss_type;
 
+       skb_push(skb, adapter->intf_hdr_len);
        if (adapter->iface_type == MWIFIEX_USB) {
                ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
                                                   skb, NULL);
        } else {
-               skb_push(skb, INTF_HEADER_LEN);
                tx_param.next_pkt_len = 0;
                ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
                                                   skb, &tx_param);
index 7d0d3ff3dd4cc02e7a1729a67a743f132c36c2a6..d76ce8797de1740648f25f3591cbbd26ef139f15 100644 (file)
@@ -55,11 +55,8 @@ static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
                        tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
                } else {
                        tid_list = &priv->wmm.tid_tbl_ptr[tid_down].ra_list;
-                       if (!list_empty(tid_list))
-                               ra_list = list_first_entry(tid_list,
-                                             struct mwifiex_ra_list_tbl, list);
-                       else
-                               ra_list = NULL;
+                       ra_list = list_first_entry_or_null(tid_list,
+                                       struct mwifiex_ra_list_tbl, list);
                        tx_info->flags &= ~MWIFIEX_BUF_FLAG_TDLS_PKT;
                }
 
index fac28bd8fbee49bac450a7af32b7c6c71b4e95b6..d848933466d9b45801ecaf08b9dc67f8acc8a399 100644 (file)
@@ -91,7 +91,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
        struct mwifiex_sta_node *dest_node;
        struct ethhdr *hdr = (void *)skb->data;
 
-       hroom = (adapter->iface_type == MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;
+       hroom = adapter->intf_hdr_len;
 
        if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
                dest_node = mwifiex_get_sta_entry(priv, hdr->h_dest);
@@ -117,7 +117,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
                if (adapter->iface_type == MWIFIEX_USB) {
                        ret = adapter->if_ops.host_to_card(adapter,
                                                           priv->usb_port,
-                                                          skb, NULL);
+                                                          skb, tx_param);
                } else {
                        ret = adapter->if_ops.host_to_card(adapter,
                                                           MWIFIEX_TYPE_DATA,
@@ -179,18 +179,13 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
                mwifiex_write_data_complete(adapter, skb, 0, 0);
                return ret;
        }
-       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
-               if (adapter->iface_type == MWIFIEX_USB)
-                       local_tx_pd = (struct txpd *)head_ptr;
-               else
-                       local_tx_pd = (struct txpd *) (head_ptr +
-                               INTF_HEADER_LEN);
-       }
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
+               local_tx_pd = (struct txpd *)(head_ptr + adapter->intf_hdr_len);
 
        if (adapter->iface_type == MWIFIEX_USB) {
                ret = adapter->if_ops.host_to_card(adapter,
                                                   priv->usb_port,
-                                                  skb, NULL);
+                                                  skb, tx_param);
        } else {
                ret = adapter->if_ops.host_to_card(adapter,
                                                   MWIFIEX_TYPE_DATA,
index e10b2a52e78fe7c04b24a62d63af1e6b7bcec682..e8c8728db15aa37cf62a63abef0264edb3894ba1 100644 (file)
@@ -312,6 +312,17 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                                            adapter->event_skb->len -
                                            sizeof(eventcause));
                break;
+
+       case EVENT_REMAIN_ON_CHAN_EXPIRED:
+               mwifiex_dbg(adapter, EVENT,
+                           "event: uap: Remain on channel expired\n");
+               cfg80211_remain_on_channel_expired(&priv->wdev,
+                                                  priv->roc_cfg.cookie,
+                                                  &priv->roc_cfg.chan,
+                                                  GFP_ATOMIC);
+               memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg));
+               break;
+
        default:
                mwifiex_dbg(adapter, EVENT,
                            "event: unknown event id: %#x\n", eventcause);
index bf5660eb27d370d23f7bbcead25cb56b0fef78a8..1e6a62c69ac52bfb285a400d883287ca422f1998 100644 (file)
@@ -468,8 +468,7 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv,
        struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
        int pad;
        u16 pkt_type, pkt_offset;
-       int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 :
-                      INTF_HEADER_LEN;
+       int hroom = adapter->intf_hdr_len;
 
        if (!skb->len) {
                mwifiex_dbg(adapter, ERROR,
@@ -521,7 +520,7 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv,
 
        txpd->tx_pkt_offset = cpu_to_le16(pkt_offset);
 
-       /* make space for INTF_HEADER_LEN */
+       /* make space for adapter->intf_hdr_len */
        skb_push(skb, hroom);
 
        if (!txpd->tx_control)
index 2f7705c50161404825695846bd94e8c95bfd5a7c..cb1753e43ef4a0734dc79b6d4b15e64fff5b0c23 100644 (file)
@@ -363,6 +363,7 @@ static void mwifiex_usb_free(struct usb_card_rec *card)
        for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
                port = &card->port[i];
                for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
+                       usb_kill_urb(port->tx_data_list[j].urb);
                        usb_free_urb(port->tx_data_list[j].urb);
                        port->tx_data_list[j].urb = NULL;
                }
@@ -424,7 +425,8 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
        card->intf = intf;
 
        pr_debug("info: bcdUSB=%#x Device Class=%#x SubClass=%#x Protocol=%#x\n",
-                udev->descriptor.bcdUSB, udev->descriptor.bDeviceClass,
+                le16_to_cpu(udev->descriptor.bcdUSB),
+                udev->descriptor.bDeviceClass,
                 udev->descriptor.bDeviceSubClass,
                 udev->descriptor.bDeviceProtocol);
 
@@ -661,75 +663,6 @@ static struct usb_driver mwifiex_usb_driver = {
        .soft_unbind = 1,
 };
 
-static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
-{
-       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
-       struct usb_tx_data_port *port;
-       int i, j;
-
-       card->tx_cmd.adapter = adapter;
-       card->tx_cmd.ep = card->tx_cmd_ep;
-
-       card->tx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!card->tx_cmd.urb)
-               return -ENOMEM;
-
-       for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
-               port = &card->port[i];
-               if (!port->tx_data_ep)
-                       continue;
-               port->tx_data_ix = 0;
-               if (port->tx_data_ep == MWIFIEX_USB_EP_DATA)
-                       port->block_status = false;
-               else
-                       port->block_status = true;
-               for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
-                       port->tx_data_list[j].adapter = adapter;
-                       port->tx_data_list[j].ep = port->tx_data_ep;
-                       port->tx_data_list[j].urb =
-                                       usb_alloc_urb(0, GFP_KERNEL);
-                       if (!port->tx_data_list[j].urb)
-                               return -ENOMEM;
-               }
-       }
-
-       return 0;
-}
-
-static int mwifiex_usb_rx_init(struct mwifiex_adapter *adapter)
-{
-       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
-       int i;
-
-       card->rx_cmd.adapter = adapter;
-       card->rx_cmd.ep = card->rx_cmd_ep;
-
-       card->rx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!card->rx_cmd.urb)
-               return -ENOMEM;
-
-       card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE);
-       if (!card->rx_cmd.skb)
-               return -ENOMEM;
-
-       if (mwifiex_usb_submit_rx_urb(&card->rx_cmd, MWIFIEX_RX_CMD_BUF_SIZE))
-               return -1;
-
-       for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
-               card->rx_data_list[i].adapter = adapter;
-               card->rx_data_list[i].ep = card->rx_data_ep;
-
-               card->rx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!card->rx_data_list[i].urb)
-                       return -1;
-               if (mwifiex_usb_submit_rx_urb(&card->rx_data_list[i],
-                                             MWIFIEX_RX_DATA_BUF_SIZE))
-                       return -1;
-       }
-
-       return 0;
-}
-
 static int mwifiex_write_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf,
                                   u32 *len, u8 ep, u32 timeout)
 {
@@ -845,6 +778,364 @@ static inline u8 mwifiex_usb_data_sent(struct mwifiex_adapter *adapter)
        return true;
 }
 
+static int mwifiex_usb_construct_send_urb(struct mwifiex_adapter *adapter,
+                                         struct usb_tx_data_port *port, u8 ep,
+                                         struct urb_context *context,
+                                         struct sk_buff *skb_send)
+{
+       struct usb_card_rec *card = adapter->card;
+       int ret = -EINPROGRESS;
+       struct urb *tx_urb;
+
+       context->adapter = adapter;
+       context->ep = ep;
+       context->skb = skb_send;
+       tx_urb = context->urb;
+
+       if (ep == card->tx_cmd_ep &&
+           card->tx_cmd_ep_type == USB_ENDPOINT_XFER_INT)
+               usb_fill_int_urb(tx_urb, card->udev,
+                                usb_sndintpipe(card->udev, ep), skb_send->data,
+                                skb_send->len, mwifiex_usb_tx_complete,
+                                (void *)context, card->tx_cmd_interval);
+       else
+               usb_fill_bulk_urb(tx_urb, card->udev,
+                                 usb_sndbulkpipe(card->udev, ep),
+                                 skb_send->data, skb_send->len,
+                                 mwifiex_usb_tx_complete, (void *)context);
+
+       tx_urb->transfer_flags |= URB_ZERO_PACKET;
+
+       if (ep == card->tx_cmd_ep)
+               atomic_inc(&card->tx_cmd_urb_pending);
+       else
+               atomic_inc(&port->tx_data_urb_pending);
+
+       if (ep != card->tx_cmd_ep &&
+           atomic_read(&port->tx_data_urb_pending) ==
+                                       MWIFIEX_TX_DATA_URB) {
+               port->block_status = true;
+               adapter->data_sent = mwifiex_usb_data_sent(adapter);
+               ret = -ENOSR;
+       }
+
+       if (usb_submit_urb(tx_urb, GFP_ATOMIC)) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: usb_submit_urb failed\n", __func__);
+               if (ep == card->tx_cmd_ep) {
+                       atomic_dec(&card->tx_cmd_urb_pending);
+               } else {
+                       atomic_dec(&port->tx_data_urb_pending);
+                       port->block_status = false;
+                       adapter->data_sent = false;
+                       if (port->tx_data_ix)
+                               port->tx_data_ix--;
+                       else
+                               port->tx_data_ix = MWIFIEX_TX_DATA_URB;
+               }
+               ret = -1;
+       }
+
+       return ret;
+}
+
+static int mwifiex_usb_prepare_tx_aggr_skb(struct mwifiex_adapter *adapter,
+                                          struct usb_tx_data_port *port,
+                                          struct sk_buff **skb_send)
+{
+       struct sk_buff *skb_aggr, *skb_tmp;
+       u8 *payload, pad;
+       u16 align = adapter->bus_aggr.tx_aggr_align;
+       struct mwifiex_txinfo *tx_info = NULL;
+       bool is_txinfo_set = false;
+
+       /* Packets in aggr_list will be send in either skb_aggr or
+        * write complete, delete the tx_aggr timer
+        */
+       if (port->tx_aggr.timer_cnxt.is_hold_timer_set) {
+               del_timer(&port->tx_aggr.timer_cnxt.hold_timer);
+               port->tx_aggr.timer_cnxt.is_hold_timer_set = false;
+               port->tx_aggr.timer_cnxt.hold_tmo_msecs = 0;
+       }
+
+       skb_aggr = mwifiex_alloc_dma_align_buf(port->tx_aggr.aggr_len,
+                                              GFP_ATOMIC);
+       if (!skb_aggr) {
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: alloc skb_aggr failed\n", __func__);
+
+               while ((skb_tmp = skb_dequeue(&port->tx_aggr.aggr_list)))
+                       mwifiex_write_data_complete(adapter, skb_tmp, 0, -1);
+
+               port->tx_aggr.aggr_num = 0;
+               port->tx_aggr.aggr_len = 0;
+               return -EBUSY;
+       }
+
+       tx_info = MWIFIEX_SKB_TXCB(skb_aggr);
+       memset(tx_info, 0, sizeof(*tx_info));
+
+       while ((skb_tmp = skb_dequeue(&port->tx_aggr.aggr_list))) {
+               /* padding for aligning next packet header*/
+               pad = (align - (skb_tmp->len & (align - 1))) % align;
+               payload = skb_put(skb_aggr, skb_tmp->len + pad);
+               memcpy(payload, skb_tmp->data, skb_tmp->len);
+               if (skb_queue_empty(&port->tx_aggr.aggr_list)) {
+                       /* do not padding for last packet*/
+                       *(u16 *)payload = cpu_to_le16(skb_tmp->len);
+                       *(u16 *)&payload[2] =
+                               cpu_to_le16(MWIFIEX_TYPE_AGGR_DATA_V2 | 0x80);
+                       skb_trim(skb_aggr, skb_aggr->len - pad);
+               } else {
+                       /* add aggregation interface header */
+                       *(u16 *)payload = cpu_to_le16(skb_tmp->len + pad);
+                       *(u16 *)&payload[2] =
+                               cpu_to_le16(MWIFIEX_TYPE_AGGR_DATA_V2);
+               }
+
+               if (!is_txinfo_set) {
+                       tx_info->bss_num = MWIFIEX_SKB_TXCB(skb_tmp)->bss_num;
+                       tx_info->bss_type = MWIFIEX_SKB_TXCB(skb_tmp)->bss_type;
+                       is_txinfo_set = true;
+               }
+
+               port->tx_aggr.aggr_num--;
+               port->tx_aggr.aggr_len -= (skb_tmp->len + pad);
+               mwifiex_write_data_complete(adapter, skb_tmp, 0, 0);
+       }
+
+       tx_info->pkt_len = skb_aggr->len -
+                       (sizeof(struct txpd) + adapter->intf_hdr_len);
+       tx_info->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT;
+
+       port->tx_aggr.aggr_num = 0;
+       port->tx_aggr.aggr_len = 0;
+       *skb_send = skb_aggr;
+
+       return 0;
+}
+
+/* This function prepare data packet to be send under usb tx aggregation
+ * protocol, check current usb aggregation status, link packet to aggrgation
+ * list if possible, work flow as below:
+ * (1) if only 1 packet available, add usb tx aggregation header and send.
+ * (2) if packet is able to aggregated, link it to current aggregation list.
+ * (3) if packet is not able to aggregated, aggregate and send exist packets
+ *     in aggrgation list. Then, link packet in the list if there is more
+ *     packet in transmit queue, otherwise try to transmit single packet.
+ */
+static int mwifiex_usb_aggr_tx_data(struct mwifiex_adapter *adapter, u8 ep,
+                                   struct sk_buff *skb,
+                                   struct mwifiex_tx_param *tx_param,
+                                   struct usb_tx_data_port *port)
+{
+       u8 *payload, pad;
+       u16 align = adapter->bus_aggr.tx_aggr_align;
+       struct sk_buff *skb_send = NULL;
+       struct urb_context *context = NULL;
+       struct txpd *local_tx_pd =
+               (struct txpd *)((u8 *)skb->data + adapter->intf_hdr_len);
+       u8 f_send_aggr_buf = 0;
+       u8 f_send_cur_buf = 0;
+       u8 f_precopy_cur_buf = 0;
+       u8 f_postcopy_cur_buf = 0;
+       u32 timeout;
+       int ret;
+
+       /* padding to ensure each packet alginment */
+       pad = (align - (skb->len & (align - 1))) % align;
+
+       if (tx_param && tx_param->next_pkt_len) {
+               /* next packet available in tx queue*/
+               if (port->tx_aggr.aggr_len + skb->len + pad >
+                   adapter->bus_aggr.tx_aggr_max_size) {
+                       f_send_aggr_buf = 1;
+                       f_postcopy_cur_buf = 1;
+               } else {
+                       /* current packet could be aggregated*/
+                       f_precopy_cur_buf = 1;
+
+                       if (port->tx_aggr.aggr_len + skb->len + pad +
+                           tx_param->next_pkt_len >
+                           adapter->bus_aggr.tx_aggr_max_size ||
+                           port->tx_aggr.aggr_num + 2 >
+                           adapter->bus_aggr.tx_aggr_max_num) {
+                           /* next packet could not be aggregated
+                            * send current aggregation buffer
+                            */
+                               f_send_aggr_buf = 1;
+                       }
+               }
+       } else {
+               /* last packet in tx queue */
+               if (port->tx_aggr.aggr_num > 0) {
+                       /* pending packets in aggregation buffer*/
+                       if (port->tx_aggr.aggr_len + skb->len + pad >
+                           adapter->bus_aggr.tx_aggr_max_size) {
+                               /* current packet not be able to aggregated,
+                                * send aggr buffer first, then send packet.
+                                */
+                               f_send_cur_buf = 1;
+                       } else {
+                               /* last packet, Aggregation and send */
+                               f_precopy_cur_buf = 1;
+                       }
+
+                       f_send_aggr_buf = 1;
+               } else {
+                       /* no pending packets in aggregation buffer,
+                        * send current packet immediately
+                        */
+                        f_send_cur_buf = 1;
+               }
+       }
+
+       if (local_tx_pd->flags & MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET) {
+               /* Send NULL packet immediately*/
+               if (f_precopy_cur_buf) {
+                       if (skb_queue_empty(&port->tx_aggr.aggr_list)) {
+                               f_precopy_cur_buf = 0;
+                               f_send_aggr_buf = 0;
+                               f_send_cur_buf = 1;
+                       } else {
+                               f_send_aggr_buf = 1;
+                       }
+               } else if (f_postcopy_cur_buf) {
+                       f_send_cur_buf = 1;
+                       f_postcopy_cur_buf = 0;
+               }
+       }
+
+       if (f_precopy_cur_buf) {
+               skb_queue_tail(&port->tx_aggr.aggr_list, skb);
+               port->tx_aggr.aggr_len += (skb->len + pad);
+               port->tx_aggr.aggr_num++;
+               if (f_send_aggr_buf)
+                       goto send_aggr_buf;
+
+               /* packet will not been send immediately,
+                * set a timer to make sure it will be sent under
+                * strict time limit. Dynamically fit the timeout
+                * value, according to packets number in aggr_list
+                */
+               if (!port->tx_aggr.timer_cnxt.is_hold_timer_set) {
+                       port->tx_aggr.timer_cnxt.hold_tmo_msecs =
+                                       MWIFIEX_USB_TX_AGGR_TMO_MIN;
+                       timeout =
+                               port->tx_aggr.timer_cnxt.hold_tmo_msecs;
+                       mod_timer(&port->tx_aggr.timer_cnxt.hold_timer,
+                                 jiffies + msecs_to_jiffies(timeout));
+                       port->tx_aggr.timer_cnxt.is_hold_timer_set = true;
+               } else {
+                       if (port->tx_aggr.timer_cnxt.hold_tmo_msecs <
+                           MWIFIEX_USB_TX_AGGR_TMO_MAX) {
+                               /* Dyanmic fit timeout */
+                               timeout =
+                               ++port->tx_aggr.timer_cnxt.hold_tmo_msecs;
+                               mod_timer(&port->tx_aggr.timer_cnxt.hold_timer,
+                                         jiffies + msecs_to_jiffies(timeout));
+                       }
+               }
+       }
+
+send_aggr_buf:
+       if (f_send_aggr_buf) {
+               ret = mwifiex_usb_prepare_tx_aggr_skb(adapter, port, &skb_send);
+               if (!ret) {
+                       context = &port->tx_data_list[port->tx_data_ix++];
+                       ret = mwifiex_usb_construct_send_urb(adapter, port, ep,
+                                                            context, skb_send);
+                       if (ret == -1)
+                               mwifiex_write_data_complete(adapter, skb_send,
+                                                           0, -1);
+               }
+       }
+
+       if (f_send_cur_buf) {
+               if (f_send_aggr_buf) {
+                       if (atomic_read(&port->tx_data_urb_pending) >=
+                           MWIFIEX_TX_DATA_URB) {
+                               port->block_status = true;
+                               adapter->data_sent =
+                                       mwifiex_usb_data_sent(adapter);
+                               /* no available urb, postcopy packet*/
+                               f_postcopy_cur_buf = 1;
+                               goto postcopy_cur_buf;
+                       }
+
+                       if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
+                               port->tx_data_ix = 0;
+               }
+
+               payload = skb->data;
+               *(u16 *)&payload[2] =
+                       cpu_to_le16(MWIFIEX_TYPE_AGGR_DATA_V2 | 0x80);
+               *(u16 *)payload = cpu_to_le16(skb->len);
+               skb_send = skb;
+               context = &port->tx_data_list[port->tx_data_ix++];
+               return mwifiex_usb_construct_send_urb(adapter, port, ep,
+                                                     context, skb_send);
+       }
+
+postcopy_cur_buf:
+       if (f_postcopy_cur_buf) {
+               skb_queue_tail(&port->tx_aggr.aggr_list, skb);
+               port->tx_aggr.aggr_len += (skb->len + pad);
+               port->tx_aggr.aggr_num++;
+               /* New aggregation begin, start timer */
+               if (!port->tx_aggr.timer_cnxt.is_hold_timer_set) {
+                       port->tx_aggr.timer_cnxt.hold_tmo_msecs =
+                                       MWIFIEX_USB_TX_AGGR_TMO_MIN;
+                       timeout = port->tx_aggr.timer_cnxt.hold_tmo_msecs;
+                       mod_timer(&port->tx_aggr.timer_cnxt.hold_timer,
+                                 jiffies + msecs_to_jiffies(timeout));
+                       port->tx_aggr.timer_cnxt.is_hold_timer_set = true;
+               }
+       }
+
+       return -EINPROGRESS;
+}
+
+static void mwifiex_usb_tx_aggr_tmo(unsigned long context)
+{
+       struct urb_context *urb_cnxt = NULL;
+       struct sk_buff *skb_send = NULL;
+       struct tx_aggr_tmr_cnxt *timer_context =
+               (struct tx_aggr_tmr_cnxt *)context;
+       struct mwifiex_adapter *adapter = timer_context->adapter;
+       struct usb_tx_data_port *port = timer_context->port;
+       unsigned long flags;
+       int err = 0;
+
+       spin_lock_irqsave(&port->tx_aggr_lock, flags);
+       err = mwifiex_usb_prepare_tx_aggr_skb(adapter, port, &skb_send);
+       if (err) {
+               mwifiex_dbg(adapter, ERROR,
+                           "prepare tx aggr skb failed, err=%d\n", err);
+               return;
+       }
+
+       if (atomic_read(&port->tx_data_urb_pending) >=
+           MWIFIEX_TX_DATA_URB) {
+               port->block_status = true;
+               adapter->data_sent =
+                       mwifiex_usb_data_sent(adapter);
+               err = -1;
+               goto done;
+       }
+
+       if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
+               port->tx_data_ix = 0;
+
+       urb_cnxt = &port->tx_data_list[port->tx_data_ix++];
+       err = mwifiex_usb_construct_send_urb(adapter, port, port->tx_data_ep,
+                                            urb_cnxt, skb_send);
+done:
+       if (err == -1)
+               mwifiex_write_data_complete(adapter, skb_send, 0, -1);
+       spin_unlock_irqrestore(&port->tx_aggr_lock, flags);
+}
+
 /* This function write a command/data packet to card. */
 static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
                                    struct sk_buff *skb,
@@ -853,9 +1144,8 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
        struct usb_card_rec *card = adapter->card;
        struct urb_context *context = NULL;
        struct usb_tx_data_port *port = NULL;
-       u8 *data = (u8 *)skb->data;
-       struct urb *tx_urb;
-       int idx, ret = -EINPROGRESS;
+       unsigned long flags;
+       int idx, ret;
 
        if (adapter->is_suspended) {
                mwifiex_dbg(adapter, ERROR,
@@ -873,6 +1163,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
        if (ep == card->tx_cmd_ep) {
                context = &card->tx_cmd;
        } else {
+               /* get the data port structure for endpoint */
                for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
                        if (ep == card->port[idx].tx_data_ep) {
                                port = &card->port[idx];
@@ -885,67 +1176,105 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep,
                                }
                                if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB)
                                        port->tx_data_ix = 0;
-                               context =
-                                       &port->tx_data_list[port->tx_data_ix++];
                                break;
                        }
                }
+
                if (!port) {
                        mwifiex_dbg(adapter, ERROR, "Wrong usb tx data port\n");
                        return -1;
                }
-       }
 
-       context->adapter = adapter;
-       context->ep = ep;
-       context->skb = skb;
-       tx_urb = context->urb;
+               if (adapter->bus_aggr.enable) {
+                       spin_lock_irqsave(&port->tx_aggr_lock, flags);
+                       ret =  mwifiex_usb_aggr_tx_data(adapter, ep, skb,
+                                                       tx_param, port);
+                       spin_unlock_irqrestore(&port->tx_aggr_lock, flags);
+                       return ret;
+               }
 
-       if (ep == card->tx_cmd_ep &&
-           card->tx_cmd_ep_type == USB_ENDPOINT_XFER_INT)
-               usb_fill_int_urb(tx_urb, card->udev,
-                                usb_sndintpipe(card->udev, ep), data,
-                                skb->len, mwifiex_usb_tx_complete,
-                                (void *)context, card->tx_cmd_interval);
-       else
-               usb_fill_bulk_urb(tx_urb, card->udev,
-                                 usb_sndbulkpipe(card->udev, ep), data,
-                                 skb->len, mwifiex_usb_tx_complete,
-                                 (void *)context);
+               context = &port->tx_data_list[port->tx_data_ix++];
+       }
 
-       tx_urb->transfer_flags |= URB_ZERO_PACKET;
+       return mwifiex_usb_construct_send_urb(adapter, port, ep, context, skb);
+}
 
-       if (ep == card->tx_cmd_ep)
-               atomic_inc(&card->tx_cmd_urb_pending);
-       else
-               atomic_inc(&port->tx_data_urb_pending);
+static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
+{
+       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+       struct usb_tx_data_port *port;
+       int i, j;
 
-       if (ep != card->tx_cmd_ep &&
-           atomic_read(&port->tx_data_urb_pending) ==
-                                       MWIFIEX_TX_DATA_URB) {
-               port->block_status = true;
-               adapter->data_sent = mwifiex_usb_data_sent(adapter);
-               ret = -ENOSR;
-       }
+       card->tx_cmd.adapter = adapter;
+       card->tx_cmd.ep = card->tx_cmd_ep;
 
-       if (usb_submit_urb(tx_urb, GFP_ATOMIC)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "%s: usb_submit_urb failed\n", __func__);
-               if (ep == card->tx_cmd_ep) {
-                       atomic_dec(&card->tx_cmd_urb_pending);
-               } else {
-                       atomic_dec(&port->tx_data_urb_pending);
+       card->tx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!card->tx_cmd.urb)
+               return -ENOMEM;
+
+       for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) {
+               port = &card->port[i];
+               if (!port->tx_data_ep)
+                       continue;
+               port->tx_data_ix = 0;
+               skb_queue_head_init(&port->tx_aggr.aggr_list);
+               if (port->tx_data_ep == MWIFIEX_USB_EP_DATA)
                        port->block_status = false;
-                       adapter->data_sent = false;
-                       if (port->tx_data_ix)
-                               port->tx_data_ix--;
-                       else
-                               port->tx_data_ix = MWIFIEX_TX_DATA_URB;
+               else
+                       port->block_status = true;
+               for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) {
+                       port->tx_data_list[j].adapter = adapter;
+                       port->tx_data_list[j].ep = port->tx_data_ep;
+                       port->tx_data_list[j].urb =
+                                       usb_alloc_urb(0, GFP_KERNEL);
+                       if (!port->tx_data_list[j].urb)
+                               return -ENOMEM;
                }
-               ret = -1;
+
+               port->tx_aggr.timer_cnxt.adapter = adapter;
+               port->tx_aggr.timer_cnxt.port = port;
+               port->tx_aggr.timer_cnxt.is_hold_timer_set = false;
+               port->tx_aggr.timer_cnxt.hold_tmo_msecs = 0;
+               setup_timer(&port->tx_aggr.timer_cnxt.hold_timer,
+                           mwifiex_usb_tx_aggr_tmo,
+                           (unsigned long)&port->tx_aggr.timer_cnxt);
        }
 
-       return ret;
+       return 0;
+}
+
+static int mwifiex_usb_rx_init(struct mwifiex_adapter *adapter)
+{
+       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+       int i;
+
+       card->rx_cmd.adapter = adapter;
+       card->rx_cmd.ep = card->rx_cmd_ep;
+
+       card->rx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!card->rx_cmd.urb)
+               return -ENOMEM;
+
+       card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE);
+       if (!card->rx_cmd.skb)
+               return -ENOMEM;
+
+       if (mwifiex_usb_submit_rx_urb(&card->rx_cmd, MWIFIEX_RX_CMD_BUF_SIZE))
+               return -1;
+
+       for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
+               card->rx_data_list[i].adapter = adapter;
+               card->rx_data_list[i].ep = card->rx_data_ep;
+
+               card->rx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!card->rx_data_list[i].urb)
+                       return -1;
+               if (mwifiex_usb_submit_rx_urb(&card->rx_data_list[i],
+                                             MWIFIEX_RX_DATA_BUF_SIZE))
+                       return -1;
+       }
+
+       return 0;
 }
 
 /* This function register usb device and initialize parameter. */
@@ -988,10 +1317,32 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
        return 0;
 }
 
+static void mwifiex_usb_cleanup_tx_aggr(struct mwifiex_adapter *adapter)
+{
+       struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
+       struct usb_tx_data_port *port;
+       struct sk_buff *skb_tmp;
+       int idx;
+
+       for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) {
+               port = &card->port[idx];
+               if (adapter->bus_aggr.enable)
+                       while ((skb_tmp =
+                               skb_dequeue(&port->tx_aggr.aggr_list)))
+                               mwifiex_write_data_complete(adapter, skb_tmp,
+                                                           0, -1);
+               del_timer_sync(&port->tx_aggr.timer_cnxt.hold_timer);
+               port->tx_aggr.timer_cnxt.is_hold_timer_set = false;
+               port->tx_aggr.timer_cnxt.hold_tmo_msecs = 0;
+       }
+}
+
 static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
 {
        struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
 
+       mwifiex_usb_cleanup_tx_aggr(adapter);
+
        card->adapter = NULL;
 }
 
index e36bd63172ff9606ee61979fdb51a96330b996ef..37abd228a84fab0b68a34915ac168fb0f857de19 100644 (file)
@@ -64,12 +64,35 @@ struct urb_context {
        u8 ep;
 };
 
+#define MWIFIEX_USB_TX_AGGR_TMO_MIN    1
+#define MWIFIEX_USB_TX_AGGR_TMO_MAX    4
+
+struct tx_aggr_tmr_cnxt {
+       struct mwifiex_adapter *adapter;
+       struct usb_tx_data_port *port;
+       struct timer_list hold_timer;
+       bool is_hold_timer_set;
+       u32 hold_tmo_msecs;
+};
+
+struct usb_tx_aggr {
+       struct sk_buff_head aggr_list;
+       int aggr_len;
+       int aggr_num;
+       struct tx_aggr_tmr_cnxt timer_cnxt;
+};
+
 struct usb_tx_data_port {
        u8 tx_data_ep;
        u8 block_status;
        atomic_t tx_data_urb_pending;
        int tx_data_ix;
        struct urb_context tx_data_list[MWIFIEX_TX_DATA_URB];
+       /* usb tx aggregation*/
+       struct usb_tx_aggr tx_aggr;
+       struct sk_buff *skb_aggr[MWIFIEX_TX_DATA_URB];
+       /* lock for protect tx aggregation data path*/
+       spinlock_t tx_aggr_lock;
 };
 
 struct usb_card_rec {
index e4ff3b9738505f2077452cf65790cd68bee3652e..0edd26881321e50335b92d54469b8b7d7357c1ba 100644 (file)
@@ -868,12 +868,8 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
                        return;
                default:
                        list_head = priv->wmm.tid_tbl_ptr[tid_down].ra_list;
-                       if (!list_empty(&list_head))
-                               ra_list = list_first_entry(
-                                       &list_head, struct mwifiex_ra_list_tbl,
-                                       list);
-                       else
-                               ra_list = NULL;
+                       ra_list = list_first_entry_or_null(&list_head,
+                                       struct mwifiex_ra_list_tbl, list);
                        break;
                }
        } else {
@@ -1363,13 +1359,13 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
 
        spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
 
+       tx_param.next_pkt_len =
+               ((skb_next) ? skb_next->len +
+                sizeof(struct txpd) : 0);
        if (adapter->iface_type == MWIFIEX_USB) {
                ret = adapter->if_ops.host_to_card(adapter, priv->usb_port,
-                                                  skb, NULL);
+                                                  skb, &tx_param);
        } else {
-               tx_param.next_pkt_len =
-                       ((skb_next) ? skb_next->len +
-                        sizeof(struct txpd) : 0);
                ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
                                                   skb, &tx_param);
        }
diff --git a/drivers/net/wireless/quantenna/Kconfig b/drivers/net/wireless/quantenna/Kconfig
new file mode 100644 (file)
index 0000000..3094365
--- /dev/null
@@ -0,0 +1,16 @@
+config WLAN_VENDOR_QUANTENNA
+       bool "Quantenna wireless cards support"
+       default y
+       ---help---
+         If you have a wireless card belonging to this class, say Y.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about  cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if WLAN_VENDOR_QUANTENNA
+
+source "drivers/net/wireless/quantenna/qtnfmac/Kconfig"
+
+endif # WLAN_VENDOR_QUANTENNA
diff --git a/drivers/net/wireless/quantenna/Makefile b/drivers/net/wireless/quantenna/Makefile
new file mode 100644 (file)
index 0000000..baebfbd
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Copyright (c) 2015-2016 Quantenna Communications, Inc.
+# All rights reserved.
+#
+
+obj-$(CONFIG_QTNFMAC)  += qtnfmac/
diff --git a/drivers/net/wireless/quantenna/qtnfmac/Kconfig b/drivers/net/wireless/quantenna/qtnfmac/Kconfig
new file mode 100644 (file)
index 0000000..025fa60
--- /dev/null
@@ -0,0 +1,19 @@
+config QTNFMAC
+       tristate
+       depends on QTNFMAC_PEARL_PCIE
+       default m if QTNFMAC_PEARL_PCIE=m
+       default y if QTNFMAC_PEARL_PCIE=y
+
+config QTNFMAC_PEARL_PCIE
+       tristate "Quantenna QSR10g PCIe support"
+       default n
+       depends on HAS_DMA && PCI && CFG80211
+       select QTNFMAC
+       select FW_LOADER
+       select CRC32
+       ---help---
+         This option adds support for wireless adapters based on Quantenna
+         802.11ac QSR10g (aka Pearl) FullMAC chipset running over PCIe.
+
+         If you choose to build it as a module, two modules will be built:
+         qtnfmac.ko and qtnfmac_pearl_pcie.ko.
diff --git a/drivers/net/wireless/quantenna/qtnfmac/Makefile b/drivers/net/wireless/quantenna/qtnfmac/Makefile
new file mode 100644 (file)
index 0000000..0d618e5
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2015-2016 Quantenna Communications, Inc.
+# All rights reserved.
+#
+
+ccflags-y += \
+       -Idrivers/net/wireless/quantenna/qtnfmac
+
+obj-$(CONFIG_QTNFMAC) += qtnfmac.o
+qtnfmac-objs += \
+       core.o \
+       commands.o \
+       trans.o \
+       cfg80211.o \
+       event.o \
+       util.o \
+       qlink_util.o
+
+#
+
+obj-$(CONFIG_QTNFMAC_PEARL_PCIE) += qtnfmac_pearl_pcie.o
+
+qtnfmac_pearl_pcie-objs += \
+       shm_ipc.o \
+       pearl/pcie.o
+
+qtnfmac_pearl_pcie-$(CONFIG_DEBUG_FS) += debug.o
+
+#
+
+ccflags-y += -D__CHECK_ENDIAN
diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h b/drivers/net/wireless/quantenna/qtnfmac/bus.h
new file mode 100644 (file)
index 0000000..dda0500
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2015 Quantenna Communications
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef QTNFMAC_BUS_H
+#define QTNFMAC_BUS_H
+
+#include <linux/netdevice.h>
+#include <linux/workqueue.h>
+
+#define QTNF_MAX_MAC           3
+
+enum qtnf_fw_state {
+       QTNF_FW_STATE_RESET,
+       QTNF_FW_STATE_FW_DNLD_DONE,
+       QTNF_FW_STATE_BOOT_DONE,
+       QTNF_FW_STATE_ACTIVE,
+       QTNF_FW_STATE_DEAD,
+};
+
+struct qtnf_bus;
+
+struct qtnf_bus_ops {
+       /* mgmt methods */
+       int (*preinit)(struct qtnf_bus *);
+       void (*stop)(struct qtnf_bus *);
+
+       /* control path methods */
+       int (*control_tx)(struct qtnf_bus *, struct sk_buff *);
+
+       /* data xfer methods */
+       int (*data_tx)(struct qtnf_bus *, struct sk_buff *);
+       void (*data_tx_timeout)(struct qtnf_bus *, struct net_device *);
+       void (*data_rx_start)(struct qtnf_bus *);
+       void (*data_rx_stop)(struct qtnf_bus *);
+};
+
+struct qtnf_bus {
+       struct device *dev;
+       enum qtnf_fw_state fw_state;
+       u32 chip;
+       u32 chiprev;
+       const struct qtnf_bus_ops *bus_ops;
+       struct qtnf_wmac *mac[QTNF_MAX_MAC];
+       struct qtnf_qlink_transport trans;
+       struct qtnf_hw_info hw_info;
+       char fwname[32];
+       struct napi_struct mux_napi;
+       struct net_device mux_dev;
+       struct completion request_firmware_complete;
+       struct workqueue_struct *workqueue;
+       struct work_struct event_work;
+       struct mutex bus_lock; /* lock during command/event processing */
+       struct dentry *dbg_dir;
+       /* bus private data */
+       char bus_priv[0] __aligned(sizeof(void *));
+};
+
+static inline void *get_bus_priv(struct qtnf_bus *bus)
+{
+       if (WARN(!bus, "qtnfmac: invalid bus pointer"))
+               return NULL;
+
+       return &bus->bus_priv;
+}
+
+/* callback wrappers */
+
+static inline int qtnf_bus_preinit(struct qtnf_bus *bus)
+{
+       if (!bus->bus_ops->preinit)
+               return 0;
+       return bus->bus_ops->preinit(bus);
+}
+
+static inline void qtnf_bus_stop(struct qtnf_bus *bus)
+{
+       if (!bus->bus_ops->stop)
+               return;
+       bus->bus_ops->stop(bus);
+}
+
+static inline int qtnf_bus_data_tx(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+       return bus->bus_ops->data_tx(bus, skb);
+}
+
+static inline void
+qtnf_bus_data_tx_timeout(struct qtnf_bus *bus, struct net_device *ndev)
+{
+       return bus->bus_ops->data_tx_timeout(bus, ndev);
+}
+
+static inline int qtnf_bus_control_tx(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+       return bus->bus_ops->control_tx(bus, skb);
+}
+
+static inline void qtnf_bus_data_rx_start(struct qtnf_bus *bus)
+{
+       return bus->bus_ops->data_rx_start(bus);
+}
+
+static inline void qtnf_bus_data_rx_stop(struct qtnf_bus *bus)
+{
+       return bus->bus_ops->data_rx_stop(bus);
+}
+
+static __always_inline void qtnf_bus_lock(struct qtnf_bus *bus)
+{
+       mutex_lock(&bus->bus_lock);
+}
+
+static __always_inline void qtnf_bus_unlock(struct qtnf_bus *bus)
+{
+       mutex_unlock(&bus->bus_lock);
+}
+
+/* interface functions from common layer */
+
+void qtnf_rx_frame(struct device *dev, struct sk_buff *rxp);
+int qtnf_core_attach(struct qtnf_bus *bus);
+void qtnf_core_detach(struct qtnf_bus *bus);
+void qtnf_txflowblock(struct device *dev, bool state);
+void qtnf_txcomplete(struct device *dev, struct sk_buff *txp, bool success);
+
+#endif /* QTNFMAC_BUS_H */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
new file mode 100644 (file)
index 0000000..e3c0900
--- /dev/null
@@ -0,0 +1,995 @@
+/*
+ * Copyright (c) 2012-2012 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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/kernel.h>
+#include <linux/etherdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include <net/netlink.h>
+
+#include "cfg80211.h"
+#include "commands.h"
+#include "core.h"
+#include "util.h"
+#include "bus.h"
+
+/* Supported rates to be advertised to the cfg80211 */
+static struct ieee80211_rate qtnf_rates_2g[] = {
+       {.bitrate = 10, .hw_value = 2, },
+       {.bitrate = 20, .hw_value = 4, },
+       {.bitrate = 55, .hw_value = 11, },
+       {.bitrate = 110, .hw_value = 22, },
+       {.bitrate = 60, .hw_value = 12, },
+       {.bitrate = 90, .hw_value = 18, },
+       {.bitrate = 120, .hw_value = 24, },
+       {.bitrate = 180, .hw_value = 36, },
+       {.bitrate = 240, .hw_value = 48, },
+       {.bitrate = 360, .hw_value = 72, },
+       {.bitrate = 480, .hw_value = 96, },
+       {.bitrate = 540, .hw_value = 108, },
+};
+
+/* Supported rates to be advertised to the cfg80211 */
+static struct ieee80211_rate qtnf_rates_5g[] = {
+       {.bitrate = 60, .hw_value = 12, },
+       {.bitrate = 90, .hw_value = 18, },
+       {.bitrate = 120, .hw_value = 24, },
+       {.bitrate = 180, .hw_value = 36, },
+       {.bitrate = 240, .hw_value = 48, },
+       {.bitrate = 360, .hw_value = 72, },
+       {.bitrate = 480, .hw_value = 96, },
+       {.bitrate = 540, .hw_value = 108, },
+};
+
+/* Supported crypto cipher suits to be advertised to cfg80211 */
+static const u32 qtnf_cipher_suites[] = {
+       WLAN_CIPHER_SUITE_TKIP,
+       WLAN_CIPHER_SUITE_CCMP,
+       WLAN_CIPHER_SUITE_AES_CMAC,
+};
+
+/* Supported mgmt frame types to be advertised to cfg80211 */
+static const struct ieee80211_txrx_stypes
+qtnf_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+       [NL80211_IFTYPE_STATION] = {
+               .tx = BIT(IEEE80211_STYPE_ACTION >> 4),
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+                     BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+       },
+       [NL80211_IFTYPE_AP] = {
+               .tx = BIT(IEEE80211_STYPE_ACTION >> 4),
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+                     BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+       },
+};
+
+static int
+qtnf_change_virtual_intf(struct wiphy *wiphy,
+                        struct net_device *dev,
+                        enum nl80211_iftype type,
+                        struct vif_params *params)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+       u8 *mac_addr;
+       int ret;
+
+       if (params)
+               mac_addr = params->macaddr;
+       else
+               mac_addr = NULL;
+
+       qtnf_scan_done(vif->mac, true);
+
+       ret = qtnf_cmd_send_change_intf_type(vif, type, mac_addr);
+       if (ret) {
+               pr_err("VIF%u.%u: failed to change VIF type: %d\n",
+                      vif->mac->macid, vif->vifid, ret);
+               return ret;
+       }
+
+       vif->wdev.iftype = type;
+       return 0;
+}
+
+int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+       struct net_device *netdev =  wdev->netdev;
+       struct qtnf_vif *vif;
+
+       if (WARN_ON(!netdev))
+               return -EFAULT;
+
+       vif = qtnf_netdev_get_priv(wdev->netdev);
+
+       if (qtnf_cmd_send_del_intf(vif))
+               pr_err("VIF%u.%u: failed to delete VIF\n", vif->mac->macid,
+                      vif->vifid);
+
+       /* Stop data */
+       netif_tx_stop_all_queues(netdev);
+       if (netif_carrier_ok(netdev))
+               netif_carrier_off(netdev);
+
+       if (netdev->reg_state == NETREG_REGISTERED)
+               unregister_netdevice(netdev);
+
+       vif->netdev->ieee80211_ptr = NULL;
+       vif->netdev = NULL;
+       vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+       eth_zero_addr(vif->mac_addr);
+
+       return 0;
+}
+
+static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy,
+                                                 const char *name,
+                                                 unsigned char name_assign_t,
+                                                 enum nl80211_iftype type,
+                                                 struct vif_params *params)
+{
+       struct qtnf_wmac *mac;
+       struct qtnf_vif *vif;
+       u8 *mac_addr = NULL;
+
+       mac = wiphy_priv(wiphy);
+
+       if (!mac)
+               return ERR_PTR(-EFAULT);
+
+       switch (type) {
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_AP:
+               vif = qtnf_mac_get_free_vif(mac);
+               if (!vif) {
+                       pr_err("MAC%u: no free VIF available\n", mac->macid);
+                       return ERR_PTR(-EFAULT);
+               }
+
+               eth_zero_addr(vif->mac_addr);
+               vif->bss_priority = QTNF_DEF_BSS_PRIORITY;
+               vif->wdev.wiphy = wiphy;
+               vif->wdev.iftype = type;
+               vif->sta_state = QTNF_STA_DISCONNECTED;
+               break;
+       default:
+               pr_err("MAC%u: unsupported IF type %d\n", mac->macid, type);
+               return ERR_PTR(-ENOTSUPP);
+       }
+
+       if (params)
+               mac_addr = params->macaddr;
+
+       if (qtnf_cmd_send_add_intf(vif, type, mac_addr)) {
+               pr_err("VIF%u.%u: failed to add VIF\n", mac->macid, vif->vifid);
+               goto err_cmd;
+       }
+
+       if (!is_valid_ether_addr(vif->mac_addr)) {
+               pr_err("VIF%u.%u: FW reported bad MAC: %pM\n",
+                      mac->macid, vif->vifid, vif->mac_addr);
+               goto err_mac;
+       }
+
+       if (qtnf_core_net_attach(mac, vif, name, name_assign_t, type)) {
+               pr_err("VIF%u.%u: failed to attach netdev\n", mac->macid,
+                      vif->vifid);
+               goto err_net;
+       }
+
+       vif->wdev.netdev = vif->netdev;
+       return &vif->wdev;
+
+err_net:
+       vif->netdev = NULL;
+err_mac:
+       qtnf_cmd_send_del_intf(vif);
+err_cmd:
+       vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+
+       return ERR_PTR(-EFAULT);
+}
+
+static int qtnf_mgmt_set_appie(struct qtnf_vif *vif,
+                              const struct cfg80211_beacon_data *info)
+{
+       int ret = 0;
+
+       if (!info->beacon_ies || !info->beacon_ies_len) {
+               ret = qtnf_cmd_send_mgmt_set_appie(vif, QLINK_MGMT_FRAME_BEACON,
+                                                  NULL, 0);
+       } else {
+               ret = qtnf_cmd_send_mgmt_set_appie(vif, QLINK_MGMT_FRAME_BEACON,
+                                                  info->beacon_ies,
+                                                  info->beacon_ies_len);
+       }
+
+       if (ret)
+               goto out;
+
+       if (!info->proberesp_ies || !info->proberesp_ies_len) {
+               ret = qtnf_cmd_send_mgmt_set_appie(vif,
+                                                  QLINK_MGMT_FRAME_PROBE_RESP,
+                                                  NULL, 0);
+       } else {
+               ret = qtnf_cmd_send_mgmt_set_appie(vif,
+                                                  QLINK_MGMT_FRAME_PROBE_RESP,
+                                                  info->proberesp_ies,
+                                                  info->proberesp_ies_len);
+       }
+
+       if (ret)
+               goto out;
+
+       if (!info->assocresp_ies || !info->assocresp_ies_len) {
+               ret = qtnf_cmd_send_mgmt_set_appie(vif,
+                                                  QLINK_MGMT_FRAME_ASSOC_RESP,
+                                                  NULL, 0);
+       } else {
+               ret = qtnf_cmd_send_mgmt_set_appie(vif,
+                                                  QLINK_MGMT_FRAME_ASSOC_RESP,
+                                                  info->assocresp_ies,
+                                                  info->assocresp_ies_len);
+       }
+
+out:
+       return ret;
+}
+
+static int qtnf_change_beacon(struct wiphy *wiphy, struct net_device *dev,
+                             struct cfg80211_beacon_data *info)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+
+       if (!(vif->bss_status & QTNF_STATE_AP_START)) {
+               pr_err("VIF%u.%u: not started\n", vif->mac->macid, vif->vifid);
+               return -EFAULT;
+       }
+
+       return qtnf_mgmt_set_appie(vif, info);
+}
+
+static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev,
+                        struct cfg80211_ap_settings *settings)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+       struct qtnf_bss_config *bss_cfg;
+       int ret;
+
+       bss_cfg = &vif->bss_cfg;
+
+       memset(bss_cfg, 0, sizeof(*bss_cfg));
+
+       bss_cfg->bcn_period = settings->beacon_interval;
+       bss_cfg->dtim = settings->dtim_period;
+       bss_cfg->auth_type = settings->auth_type;
+       bss_cfg->privacy = settings->privacy;
+
+       bss_cfg->ssid_len = settings->ssid_len;
+       memcpy(&bss_cfg->ssid, settings->ssid, bss_cfg->ssid_len);
+
+       memcpy(&bss_cfg->chandef, &settings->chandef,
+              sizeof(struct cfg80211_chan_def));
+       memcpy(&bss_cfg->crypto, &settings->crypto,
+              sizeof(struct cfg80211_crypto_settings));
+
+       ret = qtnf_cmd_send_config_ap(vif);
+       if (ret) {
+               pr_err("VIF%u.%u: failed to push config to FW\n",
+                      vif->mac->macid, vif->vifid);
+               goto out;
+       }
+
+       if (!(vif->bss_status & QTNF_STATE_AP_CONFIG)) {
+               pr_err("VIF%u.%u: AP config failed in FW\n", vif->mac->macid,
+                      vif->vifid);
+               ret = -EFAULT;
+               goto out;
+       }
+
+       ret = qtnf_mgmt_set_appie(vif, &settings->beacon);
+       if (ret) {
+               pr_err("VIF%u.%u: failed to add IEs to beacon\n",
+                      vif->mac->macid, vif->vifid);
+               goto out;
+       }
+
+       ret = qtnf_cmd_send_start_ap(vif);
+       if (ret) {
+               pr_err("VIF%u.%u: failed to start AP\n", vif->mac->macid,
+                      vif->vifid);
+               goto out;
+       }
+
+       if (!(vif->bss_status & QTNF_STATE_AP_START)) {
+               pr_err("VIF%u.%u: FW failed to start AP operation\n",
+                      vif->mac->macid, vif->vifid);
+               ret = -EFAULT;
+       }
+
+out:
+       return ret;
+}
+
+static int qtnf_stop_ap(struct wiphy *wiphy, struct net_device *dev)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+       int ret;
+
+       ret = qtnf_cmd_send_stop_ap(vif);
+       if (ret) {
+               pr_err("VIF%u.%u: failed to stop AP operation in FW\n",
+                      vif->mac->macid, vif->vifid);
+               vif->bss_status &= ~QTNF_STATE_AP_START;
+               vif->bss_status &= ~QTNF_STATE_AP_CONFIG;
+
+               netif_carrier_off(vif->netdev);
+       }
+
+       return ret;
+}
+
+static int qtnf_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+       struct qtnf_wmac *mac = wiphy_priv(wiphy);
+       struct qtnf_vif *vif;
+       int ret;
+
+       vif = qtnf_mac_get_base_vif(mac);
+       if (!vif) {
+               pr_err("MAC%u: primary VIF is not configured\n", mac->macid);
+               return -EFAULT;
+       }
+
+       if (changed & (WIPHY_PARAM_RETRY_LONG | WIPHY_PARAM_RETRY_SHORT)) {
+               pr_err("MAC%u: can't modify retry params\n", mac->macid);
+               return -EOPNOTSUPP;
+       }
+
+       ret = qtnf_cmd_send_update_phy_params(mac, changed);
+       if (ret)
+               pr_err("MAC%u: failed to update PHY params\n", mac->macid);
+
+       return ret;
+}
+
+static void
+qtnf_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
+                        u16 frame_type, bool reg)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(wdev->netdev);
+       u16 mgmt_type;
+       u16 new_mask;
+       u16 qlink_frame_type = 0;
+
+       mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
+
+       if (reg)
+               new_mask = vif->mgmt_frames_bitmask | BIT(mgmt_type);
+       else
+               new_mask = vif->mgmt_frames_bitmask & ~BIT(mgmt_type);
+
+       if (new_mask == vif->mgmt_frames_bitmask)
+               return;
+
+       switch (frame_type & IEEE80211_FCTL_STYPE) {
+       case IEEE80211_STYPE_PROBE_REQ:
+               qlink_frame_type = QLINK_MGMT_FRAME_PROBE_REQ;
+               break;
+       case IEEE80211_STYPE_ACTION:
+               qlink_frame_type = QLINK_MGMT_FRAME_ACTION;
+               break;
+       default:
+               pr_warn("VIF%u.%u: unsupported frame type: %X\n",
+                       vif->mac->macid, vif->vifid,
+                       (frame_type & IEEE80211_FCTL_STYPE) >> 4);
+               return;
+       }
+
+       if (qtnf_cmd_send_register_mgmt(vif, qlink_frame_type, reg)) {
+               pr_warn("VIF%u.%u: failed to %sregister mgmt frame type 0x%x\n",
+                       vif->mac->macid, vif->vifid, reg ? "" : "un",
+                       frame_type);
+               return;
+       }
+
+       vif->mgmt_frames_bitmask = new_mask;
+       pr_debug("VIF%u.%u: %sregistered mgmt frame type 0x%x\n",
+                vif->mac->macid, vif->vifid, reg ? "" : "un", frame_type);
+}
+
+static int
+qtnf_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
+            struct cfg80211_mgmt_tx_params *params, u64 *cookie)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(wdev->netdev);
+       const struct ieee80211_mgmt *mgmt_frame = (void *)params->buf;
+       u32 short_cookie = prandom_u32();
+       u16 flags = 0;
+
+       *cookie = short_cookie;
+
+       if (params->offchan)
+               flags |= QLINK_MGMT_FRAME_TX_FLAG_OFFCHAN;
+
+       if (params->no_cck)
+               flags |= QLINK_MGMT_FRAME_TX_FLAG_NO_CCK;
+
+       if (params->dont_wait_for_ack)
+               flags |= QLINK_MGMT_FRAME_TX_FLAG_ACK_NOWAIT;
+
+       pr_debug("%s freq:%u; FC:%.4X; DA:%pM; len:%zu; C:%.8X; FL:%.4X\n",
+                wdev->netdev->name, params->chan->center_freq,
+                le16_to_cpu(mgmt_frame->frame_control), mgmt_frame->da,
+                params->len, short_cookie, flags);
+
+       return qtnf_cmd_send_mgmt_frame(vif, short_cookie, flags,
+                                       params->chan->center_freq,
+                                       params->buf, params->len);
+}
+
+static int
+qtnf_get_station(struct wiphy *wiphy, struct net_device *dev,
+                const u8 *mac, struct station_info *sinfo)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+
+       return qtnf_cmd_get_sta_info(vif, mac, sinfo);
+}
+
+static int
+qtnf_dump_station(struct wiphy *wiphy, struct net_device *dev,
+                 int idx, u8 *mac, struct station_info *sinfo)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+       const struct qtnf_sta_node *sta_node;
+       int ret;
+
+       sta_node = qtnf_sta_list_lookup_index(&vif->sta_list, idx);
+
+       if (unlikely(!sta_node))
+               return -ENOENT;
+
+       ether_addr_copy(mac, sta_node->mac_addr);
+
+       ret = qtnf_cmd_get_sta_info(vif, sta_node->mac_addr, sinfo);
+
+       if (unlikely(ret == -ENOENT)) {
+               qtnf_sta_list_del(&vif->sta_list, mac);
+               cfg80211_del_sta(vif->netdev, mac, GFP_KERNEL);
+               sinfo->filled = 0;
+       }
+
+       return ret;
+}
+
+static int qtnf_add_key(struct wiphy *wiphy, struct net_device *dev,
+                       u8 key_index, bool pairwise, const u8 *mac_addr,
+                       struct key_params *params)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+       int ret;
+
+       ret = qtnf_cmd_send_add_key(vif, key_index, pairwise, mac_addr, params);
+       if (ret)
+               pr_err("VIF%u.%u: failed to add key: cipher=%x idx=%u pw=%u\n",
+                      vif->mac->macid, vif->vifid, params->cipher, key_index,
+                      pairwise);
+
+       return ret;
+}
+
+static int qtnf_del_key(struct wiphy *wiphy, struct net_device *dev,
+                       u8 key_index, bool pairwise, const u8 *mac_addr)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+       int ret;
+
+       ret = qtnf_cmd_send_del_key(vif, key_index, pairwise, mac_addr);
+       if (ret)
+               pr_err("VIF%u.%u: failed to delete key: idx=%u pw=%u\n",
+                      vif->mac->macid, vif->vifid, key_index, pairwise);
+
+       return ret;
+}
+
+static int qtnf_set_default_key(struct wiphy *wiphy, struct net_device *dev,
+                               u8 key_index, bool unicast, bool multicast)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+       int ret;
+
+       ret = qtnf_cmd_send_set_default_key(vif, key_index, unicast, multicast);
+       if (ret)
+               pr_err("VIF%u.%u: failed to set dflt key: idx=%u uc=%u mc=%u\n",
+                      vif->mac->macid, vif->vifid, key_index, unicast,
+                      multicast);
+
+       return ret;
+}
+
+static int
+qtnf_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *dev,
+                         u8 key_index)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+       int ret;
+
+       ret = qtnf_cmd_send_set_default_mgmt_key(vif, key_index);
+       if (ret)
+               pr_err("VIF%u.%u: failed to set default MGMT key: idx=%u\n",
+                      vif->mac->macid, vif->vifid, key_index);
+
+       return ret;
+}
+
+static int
+qtnf_change_station(struct wiphy *wiphy, struct net_device *dev,
+                   const u8 *mac, struct station_parameters *params)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+       int ret;
+
+       ret = qtnf_cmd_send_change_sta(vif, mac, params);
+       if (ret)
+               pr_err("VIF%u.%u: failed to change STA %pM\n",
+                      vif->mac->macid, vif->vifid, mac);
+
+       return ret;
+}
+
+static int
+qtnf_del_station(struct wiphy *wiphy, struct net_device *dev,
+                struct station_del_parameters *params)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+       int ret;
+
+       if (params->mac &&
+           (vif->wdev.iftype == NL80211_IFTYPE_AP) &&
+           !is_broadcast_ether_addr(params->mac) &&
+           !qtnf_sta_list_lookup(&vif->sta_list, params->mac))
+               return 0;
+
+       qtnf_scan_done(vif->mac, true);
+
+       ret = qtnf_cmd_send_del_sta(vif, params);
+       if (ret)
+               pr_err("VIF%u.%u: failed to delete STA %pM\n",
+                      vif->mac->macid, vif->vifid, params->mac);
+       return ret;
+}
+
+static int
+qtnf_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
+{
+       struct qtnf_wmac *mac = wiphy_priv(wiphy);
+       int ret;
+
+       mac->scan_req = request;
+
+       ret = qtnf_cmd_send_scan(mac);
+       if (ret)
+               pr_err("MAC%u: failed to start scan\n", mac->macid);
+
+       return ret;
+}
+
+static int
+qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
+            struct cfg80211_connect_params *sme)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
+       struct qtnf_bss_config *bss_cfg;
+       int ret;
+
+       if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
+               return -EOPNOTSUPP;
+
+       if (vif->sta_state != QTNF_STA_DISCONNECTED)
+               return -EBUSY;
+
+       bss_cfg = &vif->bss_cfg;
+       memset(bss_cfg, 0, sizeof(*bss_cfg));
+
+       bss_cfg->ssid_len = sme->ssid_len;
+       memcpy(&bss_cfg->ssid, sme->ssid, bss_cfg->ssid_len);
+       bss_cfg->chandef.chan = sme->channel;
+       bss_cfg->auth_type = sme->auth_type;
+       bss_cfg->privacy = sme->privacy;
+       bss_cfg->mfp = sme->mfp;
+
+       if ((sme->bg_scan_period > 0) &&
+           (sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD))
+               bss_cfg->bg_scan_period = sme->bg_scan_period;
+       else if (sme->bg_scan_period == -1)
+               bss_cfg->bg_scan_period = QTNF_DEFAULT_BG_SCAN_PERIOD;
+       else
+               bss_cfg->bg_scan_period = 0; /* disabled */
+
+       bss_cfg->connect_flags = 0;
+
+       if (sme->flags & ASSOC_REQ_DISABLE_HT)
+               bss_cfg->connect_flags |= QLINK_STA_CONNECT_DISABLE_HT;
+       if (sme->flags & ASSOC_REQ_DISABLE_VHT)
+               bss_cfg->connect_flags |= QLINK_STA_CONNECT_DISABLE_VHT;
+       if (sme->flags & ASSOC_REQ_USE_RRM)
+               bss_cfg->connect_flags |= QLINK_STA_CONNECT_USE_RRM;
+
+       memcpy(&bss_cfg->crypto, &sme->crypto, sizeof(bss_cfg->crypto));
+       if (sme->bssid)
+               ether_addr_copy(bss_cfg->bssid, sme->bssid);
+       else
+               eth_zero_addr(bss_cfg->bssid);
+
+       ret = qtnf_cmd_send_connect(vif, sme);
+       if (ret) {
+               pr_err("VIF%u.%u: failed to connect\n", vif->mac->macid,
+                      vif->vifid);
+               return ret;
+       }
+
+       vif->sta_state = QTNF_STA_CONNECTING;
+       return 0;
+}
+
+static int
+qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
+               u16 reason_code)
+{
+       struct qtnf_wmac *mac = wiphy_priv(wiphy);
+       struct qtnf_vif *vif;
+       int ret;
+
+       vif = qtnf_mac_get_base_vif(mac);
+       if (!vif) {
+               pr_err("MAC%u: primary VIF is not configured\n", mac->macid);
+               return -EFAULT;
+       }
+
+       if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
+               return -EOPNOTSUPP;
+
+       if (vif->sta_state == QTNF_STA_DISCONNECTED)
+               return 0;
+
+       ret = qtnf_cmd_send_disconnect(vif, reason_code);
+       if (ret) {
+               pr_err("VIF%u.%u: failed to disconnect\n", mac->macid,
+                      vif->vifid);
+               return ret;
+       }
+
+       vif->sta_state = QTNF_STA_DISCONNECTED;
+       return 0;
+}
+
+static struct cfg80211_ops qtn_cfg80211_ops = {
+       .add_virtual_intf       = qtnf_add_virtual_intf,
+       .change_virtual_intf    = qtnf_change_virtual_intf,
+       .del_virtual_intf       = qtnf_del_virtual_intf,
+       .start_ap               = qtnf_start_ap,
+       .change_beacon          = qtnf_change_beacon,
+       .stop_ap                = qtnf_stop_ap,
+       .set_wiphy_params       = qtnf_set_wiphy_params,
+       .mgmt_frame_register    = qtnf_mgmt_frame_register,
+       .mgmt_tx                = qtnf_mgmt_tx,
+       .change_station         = qtnf_change_station,
+       .del_station            = qtnf_del_station,
+       .get_station            = qtnf_get_station,
+       .dump_station           = qtnf_dump_station,
+       .add_key                = qtnf_add_key,
+       .del_key                = qtnf_del_key,
+       .set_default_key        = qtnf_set_default_key,
+       .set_default_mgmt_key   = qtnf_set_default_mgmt_key,
+       .scan                   = qtnf_scan,
+       .connect                = qtnf_connect,
+       .disconnect             = qtnf_disconnect
+};
+
+static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy,
+                                      struct regulatory_request *req)
+{
+       struct qtnf_wmac *mac = wiphy_priv(wiphy);
+       struct qtnf_bus *bus;
+       struct qtnf_vif *vif;
+       struct qtnf_wmac *chan_mac;
+       int i;
+       enum nl80211_band band;
+
+       bus = mac->bus;
+
+       pr_debug("MAC%u: initiator=%d alpha=%c%c\n", mac->macid, req->initiator,
+                req->alpha2[0], req->alpha2[1]);
+
+       vif = qtnf_mac_get_base_vif(mac);
+       if (!vif) {
+               pr_err("MAC%u: primary VIF is not configured\n", mac->macid);
+               return;
+       }
+
+       /* ignore non-ISO3166 country codes */
+       for (i = 0; i < sizeof(req->alpha2); i++) {
+               if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
+                       pr_err("MAC%u: not an ISO3166 code\n", mac->macid);
+                       return;
+               }
+       }
+       if (!strncasecmp(req->alpha2, bus->hw_info.alpha2_code,
+                        sizeof(req->alpha2))) {
+               pr_warn("MAC%u: unchanged country code\n", mac->macid);
+               return;
+       }
+
+       if (qtnf_cmd_send_regulatory_config(mac, req->alpha2)) {
+               pr_err("MAC%u: failed to configure regulatory\n", mac->macid);
+               return;
+       }
+
+       for (i = 0; i < bus->hw_info.num_mac; i++) {
+               chan_mac = bus->mac[i];
+
+               if (!chan_mac)
+                       continue;
+
+               if (!(bus->hw_info.mac_bitmap & BIT(i)))
+                       continue;
+
+               for (band = 0; band < NUM_NL80211_BANDS; ++band) {
+                       if (!wiphy->bands[band])
+                               continue;
+
+                       if (qtnf_cmd_get_mac_chan_info(chan_mac,
+                                                      wiphy->bands[band])) {
+                               pr_err("MAC%u: can't get channel info\n",
+                                      chan_mac->macid);
+                               qtnf_core_detach(bus);
+
+                               return;
+                       }
+               }
+       }
+}
+
+void qtnf_band_setup_htvht_caps(struct qtnf_mac_info *macinfo,
+                               struct ieee80211_supported_band *band)
+{
+       struct ieee80211_sta_ht_cap *ht_cap;
+       struct ieee80211_sta_vht_cap *vht_cap;
+
+       ht_cap = &band->ht_cap;
+       ht_cap->ht_supported = true;
+       memcpy(&ht_cap->cap, &macinfo->ht_cap.cap_info,
+              sizeof(u16));
+       ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+       ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
+       memcpy(&ht_cap->mcs, &macinfo->ht_cap.mcs,
+              sizeof(ht_cap->mcs));
+
+       if (macinfo->phymode_cap & QLINK_PHYMODE_AC) {
+               vht_cap = &band->vht_cap;
+               vht_cap->vht_supported = true;
+               memcpy(&vht_cap->cap,
+                      &macinfo->vht_cap.vht_cap_info, sizeof(u32));
+               /* Update MCS support for VHT */
+               memcpy(&vht_cap->vht_mcs,
+                      &macinfo->vht_cap.supp_mcs,
+                      sizeof(struct ieee80211_vht_mcs_info));
+       }
+}
+
+struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus)
+{
+       struct wiphy *wiphy;
+
+       wiphy = wiphy_new(&qtn_cfg80211_ops, sizeof(struct qtnf_wmac));
+       if (!wiphy)
+               return NULL;
+
+       set_wiphy_dev(wiphy, bus->dev);
+
+       return wiphy;
+}
+
+static int qtnf_wiphy_setup_if_comb(struct wiphy *wiphy,
+                                   struct ieee80211_iface_combination *if_comb,
+                                   const struct qtnf_mac_info *mac_info)
+{
+       size_t max_interfaces = 0;
+       u16 interface_modes = 0;
+       size_t i;
+
+       if (unlikely(!mac_info->limits || !mac_info->n_limits))
+               return -ENOENT;
+
+       if_comb->limits = mac_info->limits;
+       if_comb->n_limits = mac_info->n_limits;
+
+       for (i = 0; i < mac_info->n_limits; i++) {
+               max_interfaces += mac_info->limits[i].max;
+               interface_modes |= mac_info->limits[i].types;
+       }
+
+       if_comb->num_different_channels = 1;
+       if_comb->beacon_int_infra_match = true;
+       if_comb->max_interfaces = max_interfaces;
+       if_comb->radar_detect_widths = mac_info->radar_detect_widths;
+       wiphy->interface_modes = interface_modes;
+
+       return 0;
+}
+
+int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
+{
+       struct wiphy *wiphy = priv_to_wiphy(mac);
+       struct ieee80211_iface_combination *iface_comb = NULL;
+       int ret;
+
+       if (!wiphy) {
+               pr_err("invalid wiphy pointer\n");
+               return -EFAULT;
+       }
+
+       iface_comb = kzalloc(sizeof(*iface_comb), GFP_KERNEL);
+       if (!iface_comb) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = qtnf_wiphy_setup_if_comb(wiphy, iface_comb, &mac->macinfo);
+       if (ret)
+               goto out;
+
+       pr_info("MAC%u: phymode=%#x radar=%#x\n", mac->macid,
+               mac->macinfo.phymode_cap, mac->macinfo.radar_detect_widths);
+
+       wiphy->frag_threshold = mac->macinfo.frag_thr;
+       wiphy->rts_threshold = mac->macinfo.rts_thr;
+       wiphy->retry_short = mac->macinfo.sretry_limit;
+       wiphy->retry_long = mac->macinfo.lretry_limit;
+       wiphy->coverage_class = mac->macinfo.coverage_class;
+
+       wiphy->max_scan_ssids = QTNF_MAX_SSID_LIST_LENGTH;
+       wiphy->max_scan_ie_len = QTNF_MAX_VSIE_LEN;
+       wiphy->mgmt_stypes = qtnf_mgmt_stypes;
+       wiphy->max_remain_on_channel_duration = 5000;
+
+       wiphy->iface_combinations = iface_comb;
+       wiphy->n_iface_combinations = 1;
+
+       /* Initialize cipher suits */
+       wiphy->cipher_suites = qtnf_cipher_suites;
+       wiphy->n_cipher_suites = ARRAY_SIZE(qtnf_cipher_suites);
+       wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+       wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
+                       WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
+                       WIPHY_FLAG_AP_UAPSD;
+
+       wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
+                                   NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2;
+
+       wiphy->available_antennas_tx = mac->macinfo.num_tx_chain;
+       wiphy->available_antennas_rx = mac->macinfo.num_rx_chain;
+
+       wiphy->max_ap_assoc_sta = mac->macinfo.max_ap_assoc_sta;
+
+       ether_addr_copy(wiphy->perm_addr, mac->macaddr);
+
+       if (hw_info->hw_capab & QLINK_HW_SUPPORTS_REG_UPDATE) {
+               pr_debug("device supports REG_UPDATE\n");
+               wiphy->reg_notifier = qtnf_cfg80211_reg_notifier;
+               pr_debug("hint regulatory about EP region: %c%c\n",
+                        hw_info->alpha2_code[0],
+                        hw_info->alpha2_code[1]);
+               regulatory_hint(wiphy, hw_info->alpha2_code);
+       } else {
+               pr_debug("device doesn't support REG_UPDATE\n");
+               wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
+       }
+
+       ret = wiphy_register(wiphy);
+
+out:
+       if (ret < 0) {
+               kfree(iface_comb);
+               return ret;
+       }
+
+       return 0;
+}
+
+void qtnf_netdev_updown(struct net_device *ndev, bool up)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
+
+       if (qtnf_cmd_send_updown_intf(vif, up))
+               pr_err("failed to send up/down command to FW\n");
+}
+
+void qtnf_virtual_intf_cleanup(struct net_device *ndev)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
+       struct qtnf_wmac *mac = wiphy_priv(vif->wdev.wiphy);
+
+       if (vif->wdev.iftype == NL80211_IFTYPE_STATION) {
+               switch (vif->sta_state) {
+               case QTNF_STA_DISCONNECTED:
+                       break;
+               case QTNF_STA_CONNECTING:
+                       cfg80211_connect_result(vif->netdev,
+                                               vif->bss_cfg.bssid, NULL, 0,
+                                               NULL, 0,
+                                               WLAN_STATUS_UNSPECIFIED_FAILURE,
+                                               GFP_KERNEL);
+                       qtnf_disconnect(vif->wdev.wiphy, ndev,
+                                       WLAN_REASON_DEAUTH_LEAVING);
+                       break;
+               case QTNF_STA_CONNECTED:
+                       cfg80211_disconnected(vif->netdev,
+                                             WLAN_REASON_DEAUTH_LEAVING,
+                                             NULL, 0, 1, GFP_KERNEL);
+                       qtnf_disconnect(vif->wdev.wiphy, ndev,
+                                       WLAN_REASON_DEAUTH_LEAVING);
+                       break;
+               }
+
+               vif->sta_state = QTNF_STA_DISCONNECTED;
+               qtnf_scan_done(mac, true);
+       }
+}
+
+void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif)
+{
+       if (vif->wdev.iftype == NL80211_IFTYPE_STATION) {
+               switch (vif->sta_state) {
+               case QTNF_STA_CONNECTING:
+                       cfg80211_connect_result(vif->netdev,
+                                               vif->bss_cfg.bssid, NULL, 0,
+                                               NULL, 0,
+                                               WLAN_STATUS_UNSPECIFIED_FAILURE,
+                                               GFP_KERNEL);
+                       break;
+               case QTNF_STA_CONNECTED:
+                       cfg80211_disconnected(vif->netdev,
+                                             WLAN_REASON_DEAUTH_LEAVING,
+                                             NULL, 0, 1, GFP_KERNEL);
+                       break;
+               case QTNF_STA_DISCONNECTED:
+                       break;
+               }
+       }
+
+       cfg80211_shutdown_all_interfaces(vif->wdev.wiphy);
+       vif->sta_state = QTNF_STA_DISCONNECTED;
+}
+
+void qtnf_band_init_rates(struct ieee80211_supported_band *band)
+{
+       switch (band->band) {
+       case NL80211_BAND_2GHZ:
+               band->bitrates = qtnf_rates_2g;
+               band->n_bitrates = ARRAY_SIZE(qtnf_rates_2g);
+               break;
+       case NL80211_BAND_5GHZ:
+               band->bitrates = qtnf_rates_5g;
+               band->n_bitrates = ARRAY_SIZE(qtnf_rates_5g);
+               break;
+       default:
+               band->bitrates = NULL;
+               band->n_bitrates = 0;
+               break;
+       }
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
new file mode 100644 (file)
index 0000000..5bd3312
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 _QTN_FMAC_CFG80211_H_
+#define _QTN_FMAC_CFG80211_H_
+
+#include <net/cfg80211.h>
+
+#include "core.h"
+
+int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac);
+int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev);
+void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif);
+void qtnf_band_init_rates(struct ieee80211_supported_band *band);
+void qtnf_band_setup_htvht_caps(struct qtnf_mac_info *macinfo,
+                               struct ieee80211_supported_band *band);
+
+static inline void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted)
+{
+       struct cfg80211_scan_info info = {
+               .aborted = aborted,
+       };
+
+       if (mac->scan_req) {
+               cfg80211_scan_done(mac->scan_req, &info);
+               mac->scan_req = NULL;
+       }
+}
+
+#endif /* _QTN_FMAC_CFG80211_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
new file mode 100644 (file)
index 0000000..f0a0cfa
--- /dev/null
@@ -0,0 +1,1982 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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/types.h>
+#include <linux/skbuff.h>
+
+#include "cfg80211.h"
+#include "core.h"
+#include "qlink.h"
+#include "qlink_util.h"
+#include "bus.h"
+#include "commands.h"
+
+static int qtnf_cmd_check_reply_header(const struct qlink_resp *resp,
+                                      u16 cmd_id, u8 mac_id, u8 vif_id,
+                                      size_t resp_size)
+{
+       if (unlikely(le16_to_cpu(resp->cmd_id) != cmd_id)) {
+               pr_warn("VIF%u.%u CMD%x: bad cmd_id in response: 0x%.4X\n",
+                       mac_id, vif_id, cmd_id, le16_to_cpu(resp->cmd_id));
+               return -EINVAL;
+       }
+
+       if (unlikely(resp->macid != mac_id)) {
+               pr_warn("VIF%u.%u CMD%x: bad MAC in response: %u\n",
+                       mac_id, vif_id, cmd_id, resp->macid);
+               return -EINVAL;
+       }
+
+       if (unlikely(resp->vifid != vif_id)) {
+               pr_warn("VIF%u.%u CMD%x: bad VIF in response: %u\n",
+                       mac_id, vif_id, cmd_id, resp->vifid);
+               return -EINVAL;
+       }
+
+       if (unlikely(le16_to_cpu(resp->mhdr.len) < resp_size)) {
+               pr_warn("VIF%u.%u CMD%x: bad response size %u < %zu\n",
+                       mac_id, vif_id, cmd_id,
+                       le16_to_cpu(resp->mhdr.len), resp_size);
+               return -ENOSPC;
+       }
+
+       return 0;
+}
+
+static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus,
+                                   struct sk_buff *cmd_skb,
+                                   struct sk_buff **response_skb,
+                                   u16 *result_code,
+                                   size_t const_resp_size,
+                                   size_t *var_resp_size)
+{
+       struct qlink_cmd *cmd;
+       const struct qlink_resp *resp;
+       struct sk_buff *resp_skb = NULL;
+       u16 cmd_id;
+       u8 mac_id, vif_id;
+       int ret;
+
+       cmd = (struct qlink_cmd *)cmd_skb->data;
+       cmd_id = le16_to_cpu(cmd->cmd_id);
+       mac_id = cmd->macid;
+       vif_id = cmd->vifid;
+       cmd->mhdr.len = cpu_to_le16(cmd_skb->len);
+
+       if (unlikely(bus->fw_state != QTNF_FW_STATE_ACTIVE &&
+                    le16_to_cpu(cmd->cmd_id) != QLINK_CMD_FW_INIT)) {
+               pr_warn("VIF%u.%u: drop cmd 0x%.4X in fw state %d\n",
+                       mac_id, vif_id, le16_to_cpu(cmd->cmd_id),
+                       bus->fw_state);
+               return -ENODEV;
+       }
+
+       pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id,
+                le16_to_cpu(cmd->cmd_id));
+
+       ret = qtnf_trans_send_cmd_with_resp(bus, cmd_skb, &resp_skb);
+
+       if (unlikely(ret))
+               goto out;
+
+       resp = (const struct qlink_resp *)resp_skb->data;
+       ret = qtnf_cmd_check_reply_header(resp, cmd_id, mac_id, vif_id,
+                                         const_resp_size);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (likely(result_code))
+               *result_code = le16_to_cpu(resp->result);
+
+       /* Return length of variable part of response */
+       if (response_skb && var_resp_size)
+               *var_resp_size = le16_to_cpu(resp->mhdr.len) - const_resp_size;
+
+out:
+       if (response_skb)
+               *response_skb = resp_skb;
+       else
+               consume_skb(resp_skb);
+
+       return ret;
+}
+
+static inline int qtnf_cmd_send(struct qtnf_bus *bus,
+                               struct sk_buff *cmd_skb,
+                               u16 *result_code)
+{
+       return qtnf_cmd_send_with_reply(bus, cmd_skb, NULL, result_code,
+                                       sizeof(struct qlink_resp), NULL);
+}
+
+static struct sk_buff *qtnf_cmd_alloc_new_cmdskb(u8 macid, u8 vifid, u16 cmd_no,
+                                                size_t cmd_size)
+{
+       struct qlink_cmd *cmd;
+       struct sk_buff *cmd_skb;
+
+       cmd_skb = __dev_alloc_skb(sizeof(*cmd) +
+                                 QTNF_MAX_CMD_BUF_SIZE, GFP_KERNEL);
+       if (unlikely(!cmd_skb)) {
+               pr_err("VIF%u.%u CMD %u: alloc failed\n", macid, vifid, cmd_no);
+               return NULL;
+       }
+
+       memset(skb_put(cmd_skb, cmd_size), 0, cmd_size);
+
+       cmd = (struct qlink_cmd *)cmd_skb->data;
+       cmd->mhdr.len = cpu_to_le16(cmd_skb->len);
+       cmd->mhdr.type = cpu_to_le16(QLINK_MSG_TYPE_CMD);
+       cmd->cmd_id = cpu_to_le16(cmd_no);
+       cmd->macid = macid;
+       cmd->vifid = vifid;
+
+       return cmd_skb;
+}
+
+int qtnf_cmd_send_start_ap(struct qtnf_vif *vif)
+{
+       struct sk_buff *cmd_skb;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_START_AP,
+                                           sizeof(struct qlink_cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+       vif->bss_status |= QTNF_STATE_AP_START;
+       netif_carrier_on(vif->netdev);
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_regulatory_config(struct qtnf_wmac *mac, const char *alpha2)
+{
+       struct sk_buff *cmd_skb;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
+                                           QLINK_CMD_REG_REGION,
+                                           sizeof(struct qlink_cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_COUNTRY, alpha2,
+                                QTNF_MAX_ALPHA_LEN);
+
+       ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+       memcpy(mac->bus->hw_info.alpha2_code, alpha2,
+              sizeof(mac->bus->hw_info.alpha2_code));
+out:
+       return ret;
+}
+
+int qtnf_cmd_send_config_ap(struct qtnf_vif *vif)
+{
+       struct sk_buff *cmd_skb;
+       struct qtnf_bss_config *bss_cfg = &vif->bss_cfg;
+       struct cfg80211_chan_def *chandef = &bss_cfg->chandef;
+       struct qlink_tlv_channel *qchan;
+       struct qlink_auth_encr aen;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret;
+       int i;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_CONFIG_AP,
+                                           sizeof(struct qlink_cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, bss_cfg->ssid,
+                                bss_cfg->ssid_len);
+       qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_BCN_PERIOD,
+                                bss_cfg->bcn_period);
+       qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_DTIM, bss_cfg->dtim);
+
+       qchan = (struct qlink_tlv_channel *)skb_put(cmd_skb, sizeof(*qchan));
+
+       memset(qchan, 0, sizeof(*qchan));
+       qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
+       qchan->hdr.len = cpu_to_le16(sizeof(*qchan) -
+                       sizeof(struct qlink_tlv_hdr));
+       qchan->hw_value = cpu_to_le16(
+               ieee80211_frequency_to_channel(chandef->chan->center_freq));
+
+       memset(&aen, 0, sizeof(aen));
+       aen.auth_type = bss_cfg->auth_type;
+       aen.privacy = !!bss_cfg->privacy;
+       aen.mfp = bss_cfg->mfp;
+       aen.wpa_versions = cpu_to_le32(bss_cfg->crypto.wpa_versions);
+       aen.cipher_group = cpu_to_le32(bss_cfg->crypto.cipher_group);
+       aen.n_ciphers_pairwise = cpu_to_le32(
+                                       bss_cfg->crypto.n_ciphers_pairwise);
+       for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
+               aen.ciphers_pairwise[i] = cpu_to_le32(
+                                       bss_cfg->crypto.ciphers_pairwise[i]);
+       aen.n_akm_suites = cpu_to_le32(
+                                       bss_cfg->crypto.n_akm_suites);
+       for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
+               aen.akm_suites[i] = cpu_to_le32(
+                                       bss_cfg->crypto.akm_suites[i]);
+       aen.control_port = bss_cfg->crypto.control_port;
+       aen.control_port_no_encrypt =
+                       bss_cfg->crypto.control_port_no_encrypt;
+       aen.control_port_ethertype = cpu_to_le16(be16_to_cpu(
+                               bss_cfg->crypto.control_port_ethertype));
+
+       qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_CRYPTO, (u8 *)&aen,
+                                sizeof(aen));
+
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+       vif->bss_status |= QTNF_STATE_AP_CONFIG;
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif)
+{
+       struct sk_buff *cmd_skb;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_STOP_AP,
+                                           sizeof(struct qlink_cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+       vif->bss_status &= ~QTNF_STATE_AP_START;
+       vif->bss_status &= ~QTNF_STATE_AP_CONFIG;
+
+       netif_carrier_off(vif->netdev);
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg)
+{
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_mgmt_frame_register *cmd;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_REGISTER_MGMT,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_mgmt_frame_register *)cmd_skb->data;
+       cmd->frame_type = cpu_to_le16(frame_type);
+       cmd->do_register = reg;
+
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
+                            u16 freq, const u8 *buf, size_t len)
+{
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_mgmt_frame_tx *cmd;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret;
+
+       if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) {
+               pr_warn("VIF%u.%u: frame is too big: %zu\n", vif->mac->macid,
+                       vif->vifid, len);
+               return -E2BIG;
+       }
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_SEND_MGMT_FRAME,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_mgmt_frame_tx *)cmd_skb->data;
+       cmd->cookie = cpu_to_le32(cookie);
+       cmd->freq = cpu_to_le16(freq);
+       cmd->flags = cpu_to_le16(flags);
+
+       if (len && buf)
+               qtnf_cmd_skb_put_buffer(cmd_skb, buf, len);
+
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
+                                const u8 *buf, size_t len)
+{
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_mgmt_append_ie *cmd;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret;
+
+       if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) {
+               pr_warn("VIF%u.%u: %u frame is too big: %zu\n", vif->mac->macid,
+                       vif->vifid, frame_type, len);
+               return -E2BIG;
+       }
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_MGMT_SET_APPIE,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_mgmt_append_ie *)cmd_skb->data;
+       cmd->type = frame_type;
+       cmd->flags = 0;
+
+       /* If len == 0 then IE buf for specified frame type
+        * should be cleared on EP.
+        */
+       if (len && buf)
+               qtnf_cmd_skb_put_buffer(cmd_skb, buf, len);
+
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u frame %u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, frame_type, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+static void
+qtnf_sta_info_parse_basic_counters(struct station_info *sinfo,
+               const struct qlink_sta_stat_basic_counters *counters)
+{
+       sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES) |
+                        BIT(NL80211_STA_INFO_TX_BYTES);
+       sinfo->rx_bytes = get_unaligned_le64(&counters->rx_bytes);
+       sinfo->tx_bytes = get_unaligned_le64(&counters->tx_bytes);
+
+       sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS) |
+                        BIT(NL80211_STA_INFO_TX_PACKETS) |
+                        BIT(NL80211_STA_INFO_BEACON_RX);
+       sinfo->rx_packets = get_unaligned_le32(&counters->rx_packets);
+       sinfo->tx_packets = get_unaligned_le32(&counters->tx_packets);
+       sinfo->rx_beacon = get_unaligned_le64(&counters->rx_beacons);
+
+       sinfo->filled |= BIT(NL80211_STA_INFO_RX_DROP_MISC) |
+                        BIT(NL80211_STA_INFO_TX_FAILED);
+       sinfo->rx_dropped_misc = get_unaligned_le32(&counters->rx_dropped);
+       sinfo->tx_failed = get_unaligned_le32(&counters->tx_failed);
+}
+
+static void
+qtnf_sta_info_parse_rate(struct rate_info *rate_dst,
+                        const struct  qlink_sta_info_rate *rate_src)
+{
+       rate_dst->legacy = get_unaligned_le16(&rate_src->rate) * 10;
+
+       rate_dst->mcs = rate_src->mcs;
+       rate_dst->nss = rate_src->nss;
+       rate_dst->flags = 0;
+
+       switch (rate_src->bw) {
+       case QLINK_STA_INFO_RATE_BW_5:
+               rate_dst->bw = RATE_INFO_BW_5;
+               break;
+       case QLINK_STA_INFO_RATE_BW_10:
+               rate_dst->bw = RATE_INFO_BW_10;
+               break;
+       case QLINK_STA_INFO_RATE_BW_20:
+               rate_dst->bw = RATE_INFO_BW_20;
+               break;
+       case QLINK_STA_INFO_RATE_BW_40:
+               rate_dst->bw = RATE_INFO_BW_40;
+               break;
+       case QLINK_STA_INFO_RATE_BW_80:
+               rate_dst->bw = RATE_INFO_BW_80;
+               break;
+       case QLINK_STA_INFO_RATE_BW_160:
+               rate_dst->bw = RATE_INFO_BW_160;
+               break;
+       default:
+               rate_dst->bw = 0;
+               break;
+       }
+
+       if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_HT_MCS)
+               rate_dst->flags |= RATE_INFO_FLAGS_MCS;
+       else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_VHT_MCS)
+               rate_dst->flags |= RATE_INFO_FLAGS_VHT_MCS;
+}
+
+static void
+qtnf_sta_info_parse_flags(struct nl80211_sta_flag_update *dst,
+                         const struct qlink_sta_info_state *src)
+{
+       u32 mask, value;
+
+       dst->mask = 0;
+       dst->set = 0;
+
+       mask = le32_to_cpu(src->mask);
+       value = le32_to_cpu(src->value);
+
+       if (mask & QLINK_STA_FLAG_AUTHORIZED) {
+               dst->mask |= BIT(NL80211_STA_FLAG_AUTHORIZED);
+               if (value & QLINK_STA_FLAG_AUTHORIZED)
+                       dst->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
+       }
+
+       if (mask & QLINK_STA_FLAG_SHORT_PREAMBLE) {
+               dst->mask |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
+               if (value & QLINK_STA_FLAG_SHORT_PREAMBLE)
+                       dst->set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
+       }
+
+       if (mask & QLINK_STA_FLAG_WME) {
+               dst->mask |= BIT(NL80211_STA_FLAG_WME);
+               if (value & QLINK_STA_FLAG_WME)
+                       dst->set |= BIT(NL80211_STA_FLAG_WME);
+       }
+
+       if (mask & QLINK_STA_FLAG_MFP) {
+               dst->mask |= BIT(NL80211_STA_FLAG_MFP);
+               if (value & QLINK_STA_FLAG_MFP)
+                       dst->set |= BIT(NL80211_STA_FLAG_MFP);
+       }
+
+       if (mask & QLINK_STA_FLAG_AUTHENTICATED) {
+               dst->mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
+               if (value & QLINK_STA_FLAG_AUTHENTICATED)
+                       dst->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
+       }
+
+       if (mask & QLINK_STA_FLAG_TDLS_PEER) {
+               dst->mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);
+               if (value & QLINK_STA_FLAG_TDLS_PEER)
+                       dst->set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
+       }
+
+       if (mask & QLINK_STA_FLAG_ASSOCIATED) {
+               dst->mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);
+               if (value & QLINK_STA_FLAG_ASSOCIATED)
+                       dst->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
+       }
+}
+
+static void
+qtnf_sta_info_parse_generic_info(struct station_info *sinfo,
+                                const struct qlink_sta_info_generic *info)
+{
+       sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME) |
+                        BIT(NL80211_STA_INFO_INACTIVE_TIME);
+       sinfo->connected_time = get_unaligned_le32(&info->connected_time);
+       sinfo->inactive_time = get_unaligned_le32(&info->inactive_time);
+
+       sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) |
+                        BIT(NL80211_STA_INFO_SIGNAL_AVG);
+       sinfo->signal = info->rssi - 120;
+       sinfo->signal_avg = info->rssi_avg - QLINK_RSSI_OFFSET;
+
+       if (info->rx_rate.rate) {
+               sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
+               qtnf_sta_info_parse_rate(&sinfo->rxrate, &info->rx_rate);
+       }
+
+       if (info->tx_rate.rate) {
+               sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
+               qtnf_sta_info_parse_rate(&sinfo->txrate, &info->tx_rate);
+       }
+
+       sinfo->filled |= BIT(NL80211_STA_INFO_STA_FLAGS);
+       qtnf_sta_info_parse_flags(&sinfo->sta_flags, &info->state);
+}
+
+static int qtnf_cmd_sta_info_parse(struct station_info *sinfo,
+                                  const u8 *payload, size_t payload_size)
+{
+       const struct qlink_sta_stat_basic_counters *counters;
+       const struct qlink_sta_info_generic *sta_info;
+       u16 tlv_type;
+       u16 tlv_value_len;
+       size_t tlv_full_len;
+       const struct qlink_tlv_hdr *tlv;
+
+       sinfo->filled = 0;
+
+       tlv = (const struct qlink_tlv_hdr *)payload;
+       while (payload_size >= sizeof(struct qlink_tlv_hdr)) {
+               tlv_type = le16_to_cpu(tlv->type);
+               tlv_value_len = le16_to_cpu(tlv->len);
+               tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
+               if (tlv_full_len > payload_size) {
+                       pr_warn("malformed TLV 0x%.2X; LEN: %u\n",
+                               tlv_type, tlv_value_len);
+                       return -EINVAL;
+               }
+               switch (tlv_type) {
+               case QTN_TLV_ID_STA_BASIC_COUNTERS:
+                       if (unlikely(tlv_value_len < sizeof(*counters))) {
+                               pr_err("invalid TLV size %.4X: %u\n",
+                                      tlv_type, tlv_value_len);
+                               break;
+                       }
+
+                       counters = (void *)tlv->val;
+                       qtnf_sta_info_parse_basic_counters(sinfo, counters);
+                       break;
+               case QTN_TLV_ID_STA_GENERIC_INFO:
+                       if (unlikely(tlv_value_len < sizeof(*sta_info)))
+                               break;
+
+                       sta_info = (void *)tlv->val;
+                       qtnf_sta_info_parse_generic_info(sinfo, sta_info);
+                       break;
+               default:
+                       pr_warn("unexpected TLV type: %.4X\n", tlv_type);
+                       break;
+               }
+               payload_size -= tlv_full_len;
+               tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
+       }
+
+       if (payload_size) {
+               pr_warn("malformed TLV buf; bytes left: %zu\n", payload_size);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac,
+                         struct station_info *sinfo)
+{
+       struct sk_buff *cmd_skb, *resp_skb = NULL;
+       struct qlink_cmd_get_sta_info *cmd;
+       const struct qlink_resp_get_sta_info *resp;
+       size_t var_resp_len;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_GET_STA_INFO,
+                                           sizeof(*cmd));
+
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_get_sta_info *)cmd_skb->data;
+       ether_addr_copy(cmd->sta_addr, sta_mac);
+
+       ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb,
+                                      &res_code, sizeof(*resp),
+                                      &var_resp_len);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               switch (res_code) {
+               case QLINK_CMD_RESULT_ENOTFOUND:
+                       pr_warn("VIF%u.%u: %pM STA not found\n",
+                               vif->mac->macid, vif->vifid, sta_mac);
+                       ret = -ENOENT;
+                       break;
+               default:
+                       pr_err("VIF%u.%u: can't get info for %pM: %u\n",
+                              vif->mac->macid, vif->vifid, sta_mac, res_code);
+                       ret = -EFAULT;
+                       break;
+               }
+               goto out;
+       }
+
+       resp = (const struct qlink_resp_get_sta_info *)resp_skb->data;
+
+       if (unlikely(!ether_addr_equal(sta_mac, resp->sta_addr))) {
+               pr_err("VIF%u.%u: wrong mac in reply: %pM != %pM\n",
+                      vif->mac->macid, vif->vifid, resp->sta_addr, sta_mac);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = qtnf_cmd_sta_info_parse(sinfo, resp->info, var_resp_len);
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       consume_skb(resp_skb);
+
+       return ret;
+}
+
+static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif,
+                                        enum nl80211_iftype iftype,
+                                        u8 *mac_addr,
+                                        enum qlink_cmd_type cmd_type)
+{
+       struct sk_buff *cmd_skb, *resp_skb = NULL;
+       struct qlink_cmd_manage_intf *cmd;
+       const struct qlink_resp_manage_intf *resp;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           cmd_type,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data;
+
+       switch (iftype) {
+       case NL80211_IFTYPE_AP:
+               cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_AP);
+               break;
+       case NL80211_IFTYPE_STATION:
+               cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
+               break;
+       default:
+               pr_err("VIF%u.%u: unsupported type %d\n", vif->mac->macid,
+                      vif->vifid, iftype);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (mac_addr)
+               ether_addr_copy(cmd->intf_info.mac_addr, mac_addr);
+       else
+               eth_zero_addr(cmd->intf_info.mac_addr);
+
+       ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb,
+                                      &res_code, sizeof(*resp), NULL);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD %d failed: %u\n", vif->mac->macid,
+                      vif->vifid, cmd_type, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+       resp = (const struct qlink_resp_manage_intf *)resp_skb->data;
+       ether_addr_copy(vif->mac_addr, resp->intf_info.mac_addr);
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       consume_skb(resp_skb);
+
+       return ret;
+}
+
+int qtnf_cmd_send_add_intf(struct qtnf_vif *vif,
+                          enum nl80211_iftype iftype, u8 *mac_addr)
+{
+       return qtnf_cmd_send_add_change_intf(vif, iftype, mac_addr,
+                       QLINK_CMD_ADD_INTF);
+}
+
+int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif,
+                                  enum nl80211_iftype iftype, u8 *mac_addr)
+{
+       return qtnf_cmd_send_add_change_intf(vif, iftype, mac_addr,
+                                            QLINK_CMD_CHANGE_INTF);
+}
+
+int qtnf_cmd_send_del_intf(struct qtnf_vif *vif)
+{
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_manage_intf *cmd;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_DEL_INTF,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data;
+
+       switch (vif->wdev.iftype) {
+       case NL80211_IFTYPE_AP:
+               cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_AP);
+               break;
+       case NL80211_IFTYPE_STATION:
+               cmd->intf_info.if_type = cpu_to_le16(QLINK_IFTYPE_STATION);
+               break;
+       default:
+               pr_warn("VIF%u.%u: unsupported iftype %d\n", vif->mac->macid,
+                       vif->vifid, vif->wdev.iftype);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       eth_zero_addr(cmd->intf_info.mac_addr);
+
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+static int
+qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
+                          const struct qlink_resp_get_hw_info *resp)
+{
+       struct qtnf_hw_info *hwinfo = &bus->hw_info;
+
+       hwinfo->num_mac = resp->num_mac;
+       hwinfo->mac_bitmap = resp->mac_bitmap;
+       hwinfo->fw_ver = le32_to_cpu(resp->fw_ver);
+       hwinfo->ql_proto_ver = le16_to_cpu(resp->ql_proto_ver);
+       memcpy(hwinfo->alpha2_code, resp->alpha2_code,
+              sizeof(hwinfo->alpha2_code));
+       hwinfo->total_tx_chain = resp->total_tx_chain;
+       hwinfo->total_rx_chain = resp->total_rx_chain;
+       hwinfo->hw_capab = le32_to_cpu(resp->hw_capab);
+
+       pr_info("fw_version=%d, MACs map %#x, alpha2=\"%c%c\", chains Tx=%u Rx=%u\n",
+               hwinfo->fw_ver, hwinfo->mac_bitmap,
+               hwinfo->alpha2_code[0], hwinfo->alpha2_code[1],
+               hwinfo->total_tx_chain, hwinfo->total_rx_chain);
+
+       return 0;
+}
+
+static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
+                                       const u8 *tlv_buf, size_t tlv_buf_size)
+{
+       struct ieee80211_iface_limit *limits = NULL;
+       const struct qlink_iface_limit *limit_record;
+       size_t record_count = 0, rec = 0;
+       u16 tlv_type, tlv_value_len, mask;
+       struct qlink_iface_comb_num *comb;
+       size_t tlv_full_len;
+       const struct qlink_tlv_hdr *tlv;
+
+       mac->macinfo.n_limits = 0;
+
+       tlv = (const struct qlink_tlv_hdr *)tlv_buf;
+       while (tlv_buf_size >= sizeof(struct qlink_tlv_hdr)) {
+               tlv_type = le16_to_cpu(tlv->type);
+               tlv_value_len = le16_to_cpu(tlv->len);
+               tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
+               if (tlv_full_len > tlv_buf_size) {
+                       pr_warn("MAC%u: malformed TLV 0x%.2X; LEN: %u\n",
+                               mac->macid, tlv_type, tlv_value_len);
+                       return -EINVAL;
+               }
+
+               switch (tlv_type) {
+               case QTN_TLV_ID_NUM_IFACE_COMB:
+                       if (unlikely(tlv_value_len != sizeof(*comb)))
+                               return -EINVAL;
+
+                       comb = (void *)tlv->val;
+                       record_count = le16_to_cpu(comb->iface_comb_num);
+
+                       mac->macinfo.n_limits = record_count;
+                       /* free earlier iface limits memory */
+                       kfree(mac->macinfo.limits);
+                       mac->macinfo.limits =
+                               kzalloc(sizeof(*mac->macinfo.limits) *
+                                       record_count, GFP_KERNEL);
+
+                       if (unlikely(!mac->macinfo.limits))
+                               return -ENOMEM;
+
+                       limits = mac->macinfo.limits;
+                       break;
+               case QTN_TLV_ID_IFACE_LIMIT:
+                       if (unlikely(!limits)) {
+                               pr_warn("MAC%u: limits are not inited\n",
+                                       mac->macid);
+                               return -EINVAL;
+                       }
+
+                       if (unlikely(tlv_value_len != sizeof(*limit_record))) {
+                               pr_warn("MAC%u: record size mismatch\n",
+                                       mac->macid);
+                               return -EINVAL;
+                       }
+
+                       limit_record = (void *)tlv->val;
+                       limits[rec].max = le16_to_cpu(limit_record->max_num);
+                       mask = le16_to_cpu(limit_record->type_mask);
+                       limits[rec].types = qlink_iface_type_mask_to_nl(mask);
+                       /* only AP and STA modes are supported */
+                       limits[rec].types &= BIT(NL80211_IFTYPE_AP) |
+                                            BIT(NL80211_IFTYPE_STATION);
+
+                       pr_debug("MAC%u: MAX: %u; TYPES: %.4X\n", mac->macid,
+                                limits[rec].max, limits[rec].types);
+
+                       if (limits[rec].types)
+                               rec++;
+                       break;
+               default:
+                       break;
+               }
+               tlv_buf_size -= tlv_full_len;
+               tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
+       }
+
+       if (tlv_buf_size) {
+               pr_warn("MAC%u: malformed TLV buf; bytes left: %zu\n",
+                       mac->macid, tlv_buf_size);
+               return -EINVAL;
+       }
+
+       if (mac->macinfo.n_limits != rec) {
+               pr_err("MAC%u: combination mismatch: reported=%zu parsed=%zu\n",
+                      mac->macid, mac->macinfo.n_limits, rec);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void
+qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac,
+                           const struct qlink_resp_get_mac_info *resp_info)
+{
+       struct qtnf_mac_info *mac_info;
+       struct qtnf_vif *vif;
+
+       mac_info = &mac->macinfo;
+
+       mac_info->bands_cap = resp_info->bands_cap;
+       mac_info->phymode_cap = resp_info->phymode_cap;
+       memcpy(&mac_info->dev_mac, &resp_info->dev_mac,
+              sizeof(mac_info->dev_mac));
+
+       ether_addr_copy(mac->macaddr, mac_info->dev_mac);
+
+       vif = qtnf_mac_get_base_vif(mac);
+       if (vif)
+               ether_addr_copy(vif->mac_addr, mac->macaddr);
+       else
+               pr_err("could not get valid base vif\n");
+
+       mac_info->num_tx_chain = resp_info->num_tx_chain;
+       mac_info->num_rx_chain = resp_info->num_rx_chain;
+
+       mac_info->max_ap_assoc_sta = le16_to_cpu(resp_info->max_ap_assoc_sta);
+       mac_info->radar_detect_widths =
+                       qlink_chan_width_mask_to_nl(le16_to_cpu(
+                                       resp_info->radar_detect_widths));
+
+       memcpy(&mac_info->ht_cap, &resp_info->ht_cap, sizeof(mac_info->ht_cap));
+       memcpy(&mac_info->vht_cap, &resp_info->vht_cap,
+              sizeof(mac_info->vht_cap));
+}
+
+static int
+qtnf_cmd_resp_fill_channels_info(struct ieee80211_supported_band *band,
+                                struct qlink_resp_get_chan_info *resp,
+                                size_t payload_len)
+{
+       u16 tlv_type;
+       size_t tlv_len;
+       const struct qlink_tlv_hdr *tlv;
+       const struct qlink_tlv_channel *qchan;
+       struct ieee80211_channel *chan;
+       unsigned int chidx = 0;
+       u32 qflags;
+
+       kfree(band->channels);
+       band->channels = NULL;
+
+       band->n_channels = resp->num_chans;
+       if (band->n_channels == 0)
+               return 0;
+
+       band->channels = kcalloc(band->n_channels, sizeof(*chan), GFP_KERNEL);
+       if (!band->channels) {
+               band->n_channels = 0;
+               return -ENOMEM;
+       }
+
+       tlv = (struct qlink_tlv_hdr *)resp->info;
+
+       while (payload_len >= sizeof(*tlv)) {
+               tlv_type = le16_to_cpu(tlv->type);
+               tlv_len = le16_to_cpu(tlv->len) + sizeof(*tlv);
+
+               if (tlv_len > payload_len) {
+                       pr_warn("malformed TLV 0x%.2X; LEN: %zu\n",
+                               tlv_type, tlv_len);
+                       goto error_ret;
+               }
+
+               switch (tlv_type) {
+               case QTN_TLV_ID_CHANNEL:
+                       if (unlikely(tlv_len != sizeof(*qchan))) {
+                               pr_err("invalid channel TLV len %zu\n",
+                                      tlv_len);
+                               goto error_ret;
+                       }
+
+                       if (chidx == band->n_channels) {
+                               pr_err("too many channel TLVs\n");
+                               goto error_ret;
+                       }
+
+                       qchan = (const struct qlink_tlv_channel *)tlv;
+                       chan = &band->channels[chidx++];
+                       qflags = le32_to_cpu(qchan->flags);
+
+                       chan->hw_value = le16_to_cpu(qchan->hw_value);
+                       chan->band = band->band;
+                       chan->center_freq = le16_to_cpu(qchan->center_freq);
+                       chan->max_antenna_gain = (int)qchan->max_antenna_gain;
+                       chan->max_power = (int)qchan->max_power;
+                       chan->max_reg_power = (int)qchan->max_reg_power;
+                       chan->beacon_found = qchan->beacon_found;
+                       chan->dfs_cac_ms = le32_to_cpu(qchan->dfs_cac_ms);
+                       chan->flags = 0;
+
+                       if (qflags & QLINK_CHAN_DISABLED)
+                               chan->flags |= IEEE80211_CHAN_DISABLED;
+
+                       if (qflags & QLINK_CHAN_NO_IR)
+                               chan->flags |= IEEE80211_CHAN_NO_IR;
+
+                       if (qflags & QLINK_CHAN_NO_HT40PLUS)
+                               chan->flags |= IEEE80211_CHAN_NO_HT40PLUS;
+
+                       if (qflags & QLINK_CHAN_NO_HT40MINUS)
+                               chan->flags |= IEEE80211_CHAN_NO_HT40MINUS;
+
+                       if (qflags & QLINK_CHAN_NO_OFDM)
+                               chan->flags |= IEEE80211_CHAN_NO_OFDM;
+
+                       if (qflags & QLINK_CHAN_NO_80MHZ)
+                               chan->flags |= IEEE80211_CHAN_NO_80MHZ;
+
+                       if (qflags & QLINK_CHAN_NO_160MHZ)
+                               chan->flags |= IEEE80211_CHAN_NO_160MHZ;
+
+                       if (qflags & QLINK_CHAN_INDOOR_ONLY)
+                               chan->flags |= IEEE80211_CHAN_INDOOR_ONLY;
+
+                       if (qflags & QLINK_CHAN_IR_CONCURRENT)
+                               chan->flags |= IEEE80211_CHAN_IR_CONCURRENT;
+
+                       if (qflags & QLINK_CHAN_NO_20MHZ)
+                               chan->flags |= IEEE80211_CHAN_NO_20MHZ;
+
+                       if (qflags & QLINK_CHAN_NO_10MHZ)
+                               chan->flags |= IEEE80211_CHAN_NO_10MHZ;
+
+                       if (qflags & QLINK_CHAN_RADAR) {
+                               chan->flags |= IEEE80211_CHAN_RADAR;
+                               chan->dfs_state_entered = jiffies;
+
+                               if (qchan->dfs_state == QLINK_DFS_USABLE)
+                                       chan->dfs_state = NL80211_DFS_USABLE;
+                               else if (qchan->dfs_state ==
+                                       QLINK_DFS_AVAILABLE)
+                                       chan->dfs_state = NL80211_DFS_AVAILABLE;
+                               else
+                                       chan->dfs_state =
+                                               NL80211_DFS_UNAVAILABLE;
+                       }
+
+                       pr_debug("chan=%d flags=%#x max_pow=%d max_reg_pow=%d\n",
+                                chan->hw_value, chan->flags, chan->max_power,
+                                chan->max_reg_power);
+                       break;
+               default:
+                       pr_warn("unknown TLV type: %#x\n", tlv_type);
+                       break;
+               }
+
+               payload_len -= tlv_len;
+               tlv = (struct qlink_tlv_hdr *)((u8 *)tlv + tlv_len);
+       }
+
+       if (payload_len) {
+               pr_err("malformed TLV buf; bytes left: %zu\n", payload_len);
+               goto error_ret;
+       }
+
+       if (band->n_channels != chidx) {
+               pr_err("channel count mismatch: reported=%d, parsed=%d\n",
+                      band->n_channels, chidx);
+               goto error_ret;
+       }
+
+       return 0;
+
+error_ret:
+       kfree(band->channels);
+       band->channels = NULL;
+       band->n_channels = 0;
+
+       return -EINVAL;
+}
+
+static int qtnf_cmd_resp_proc_phy_params(struct qtnf_wmac *mac,
+                                        const u8 *payload, size_t payload_len)
+{
+       struct qtnf_mac_info *mac_info;
+       struct qlink_tlv_frag_rts_thr *phy_thr;
+       struct qlink_tlv_rlimit *limit;
+       struct qlink_tlv_cclass *class;
+       u16 tlv_type;
+       u16 tlv_value_len;
+       size_t tlv_full_len;
+       const struct qlink_tlv_hdr *tlv;
+
+       mac_info = &mac->macinfo;
+
+       tlv = (struct qlink_tlv_hdr *)payload;
+       while (payload_len >= sizeof(struct qlink_tlv_hdr)) {
+               tlv_type = le16_to_cpu(tlv->type);
+               tlv_value_len = le16_to_cpu(tlv->len);
+               tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
+
+               if (tlv_full_len > payload_len) {
+                       pr_warn("MAC%u: malformed TLV 0x%.2X; LEN: %u\n",
+                               mac->macid, tlv_type, tlv_value_len);
+                       return -EINVAL;
+               }
+
+               switch (tlv_type) {
+               case QTN_TLV_ID_FRAG_THRESH:
+                       phy_thr = (void *)tlv;
+                       mac_info->frag_thr = (u32)le16_to_cpu(phy_thr->thr);
+                       break;
+               case QTN_TLV_ID_RTS_THRESH:
+                       phy_thr = (void *)tlv;
+                       mac_info->rts_thr = (u32)le16_to_cpu(phy_thr->thr);
+                       break;
+               case QTN_TLV_ID_SRETRY_LIMIT:
+                       limit = (void *)tlv;
+                       mac_info->sretry_limit = limit->rlimit;
+                       break;
+               case QTN_TLV_ID_LRETRY_LIMIT:
+                       limit = (void *)tlv;
+                       mac_info->lretry_limit = limit->rlimit;
+                       break;
+               case QTN_TLV_ID_COVERAGE_CLASS:
+                       class = (void *)tlv;
+                       mac_info->coverage_class = class->cclass;
+                       break;
+               default:
+                       pr_err("MAC%u: Unknown TLV type: %#x\n", mac->macid,
+                              le16_to_cpu(tlv->type));
+                       break;
+               }
+
+               payload_len -= tlv_full_len;
+               tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
+       }
+
+       if (payload_len) {
+               pr_warn("MAC%u: malformed TLV buf; bytes left: %zu\n",
+                       mac->macid, payload_len);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac)
+{
+       struct sk_buff *cmd_skb, *resp_skb = NULL;
+       const struct qlink_resp_get_mac_info *resp;
+       size_t var_data_len;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
+                                           QLINK_CMD_MAC_INFO,
+                                           sizeof(struct qlink_cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(mac->bus);
+
+       ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code,
+                                      sizeof(*resp), &var_data_len);
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+       resp = (const struct qlink_resp_get_mac_info *)resp_skb->data;
+       qtnf_cmd_resp_proc_mac_info(mac, resp);
+       ret = qtnf_parse_variable_mac_info(mac, resp->var_info, var_data_len);
+
+out:
+       qtnf_bus_unlock(mac->bus);
+       consume_skb(resp_skb);
+
+       return ret;
+}
+
+int qtnf_cmd_get_hw_info(struct qtnf_bus *bus)
+{
+       struct sk_buff *cmd_skb, *resp_skb = NULL;
+       const struct qlink_resp_get_hw_info *resp;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
+                                           QLINK_CMD_GET_HW_INFO,
+                                           sizeof(struct qlink_cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(bus);
+
+       ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, &res_code,
+                                      sizeof(*resp), NULL);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("cmd exec failed: 0x%.4X\n", res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+       resp = (const struct qlink_resp_get_hw_info *)resp_skb->data;
+       ret = qtnf_cmd_resp_proc_hw_info(bus, resp);
+
+out:
+       qtnf_bus_unlock(bus);
+       consume_skb(resp_skb);
+
+       return ret;
+}
+
+int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
+                              struct ieee80211_supported_band *band)
+{
+       struct sk_buff *cmd_skb, *resp_skb = NULL;
+       size_t info_len;
+       struct qlink_cmd_chans_info_get *cmd;
+       struct qlink_resp_get_chan_info *resp;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+       u8 qband;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
+                                           QLINK_CMD_CHANS_INFO_GET,
+                                           sizeof(*cmd));
+       if (!cmd_skb)
+               return -ENOMEM;
+
+       switch (band->band) {
+       case NL80211_BAND_2GHZ:
+               qband = QLINK_BAND_2GHZ;
+               break;
+       case NL80211_BAND_5GHZ:
+               qband = QLINK_BAND_5GHZ;
+               break;
+       case NL80211_BAND_60GHZ:
+               qband = QLINK_BAND_60GHZ;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       cmd = (struct qlink_cmd_chans_info_get *)cmd_skb->data;
+       cmd->band = qband;
+       ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code,
+                                      sizeof(*resp), &info_len);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+       resp = (struct qlink_resp_get_chan_info *)resp_skb->data;
+       if (resp->band != qband) {
+               pr_err("MAC%u: reply band %u != cmd band %u\n", mac->macid,
+                      resp->band, qband);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = qtnf_cmd_resp_fill_channels_info(band, resp, info_len);
+
+out:
+       consume_skb(resp_skb);
+
+       return ret;
+}
+
+int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac)
+{
+       struct sk_buff *cmd_skb, *resp_skb = NULL;
+       size_t response_size;
+       struct qlink_resp_phy_params *resp;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
+                                           QLINK_CMD_PHY_PARAMS_GET,
+                                           sizeof(struct qlink_cmd));
+       if (!cmd_skb)
+               return -ENOMEM;
+
+       qtnf_bus_lock(mac->bus);
+
+       ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code,
+                                      sizeof(*resp), &response_size);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+       resp = (struct qlink_resp_phy_params *)resp_skb->data;
+       ret = qtnf_cmd_resp_proc_phy_params(mac, resp->info, response_size);
+
+out:
+       qtnf_bus_unlock(mac->bus);
+       consume_skb(resp_skb);
+
+       return ret;
+}
+
+int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed)
+{
+       struct wiphy *wiphy = priv_to_wiphy(mac);
+       struct sk_buff *cmd_skb;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
+                                           QLINK_CMD_PHY_PARAMS_SET,
+                                           sizeof(struct qlink_cmd));
+       if (!cmd_skb)
+               return -ENOMEM;
+
+       qtnf_bus_lock(mac->bus);
+
+       if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
+               qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_FRAG_THRESH,
+                                        wiphy->frag_threshold);
+       if (changed & WIPHY_PARAM_RTS_THRESHOLD)
+               qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_RTS_THRESH,
+                                        wiphy->rts_threshold);
+       if (changed & WIPHY_PARAM_COVERAGE_CLASS)
+               qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS,
+                                       wiphy->coverage_class);
+
+       ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+out:
+       qtnf_bus_unlock(mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_init_fw(struct qtnf_bus *bus)
+{
+       struct sk_buff *cmd_skb;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
+                                           QLINK_CMD_FW_INIT,
+                                           sizeof(struct qlink_cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(bus);
+
+       ret = qtnf_cmd_send(bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("cmd exec failed: 0x%.4X\n", res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+out:
+       qtnf_bus_unlock(bus);
+       return ret;
+}
+
+void qtnf_cmd_send_deinit_fw(struct qtnf_bus *bus)
+{
+       struct sk_buff *cmd_skb;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
+                                           QLINK_CMD_FW_DEINIT,
+                                           sizeof(struct qlink_cmd));
+       if (!cmd_skb)
+               return;
+
+       qtnf_bus_lock(bus);
+
+       qtnf_cmd_send(bus, cmd_skb, NULL);
+
+       qtnf_bus_unlock(bus);
+}
+
+int qtnf_cmd_send_add_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
+                         const u8 *mac_addr, struct key_params *params)
+{
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_add_key *cmd;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_ADD_KEY,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_add_key *)cmd_skb->data;
+
+       if (mac_addr)
+               ether_addr_copy(cmd->addr, mac_addr);
+       else
+               eth_broadcast_addr(cmd->addr);
+
+       cmd->cipher = cpu_to_le32(params->cipher);
+       cmd->key_index = key_index;
+       cmd->pairwise = pairwise;
+
+       if (params->key && params->key_len > 0)
+               qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_KEY,
+                                        params->key,
+                                        params->key_len);
+
+       if (params->seq && params->seq_len > 0)
+               qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_SEQ,
+                                        params->seq,
+                                        params->seq_len);
+
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n",
+                      vif->mac->macid, vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_del_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
+                         const u8 *mac_addr)
+{
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_del_key *cmd;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_DEL_KEY,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_del_key *)cmd_skb->data;
+
+       if (mac_addr)
+               ether_addr_copy(cmd->addr, mac_addr);
+       else
+               eth_broadcast_addr(cmd->addr);
+
+       cmd->key_index = key_index;
+       cmd->pairwise = pairwise;
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n",
+                      vif->mac->macid, vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_set_default_key(struct qtnf_vif *vif, u8 key_index,
+                                 bool unicast, bool multicast)
+{
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_set_def_key *cmd;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_SET_DEFAULT_KEY,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_set_def_key *)cmd_skb->data;
+       cmd->key_index = key_index;
+       cmd->unicast = unicast;
+       cmd->multicast = multicast;
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif *vif, u8 key_index)
+{
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_set_def_mgmt_key *cmd;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_SET_DEFAULT_MGMT_KEY,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_set_def_mgmt_key *)cmd_skb->data;
+       cmd->key_index = key_index;
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+static u32 qtnf_encode_sta_flags(u32 flags)
+{
+       u32 code = 0;
+
+       if (flags & BIT(NL80211_STA_FLAG_AUTHORIZED))
+               code |= QLINK_STA_FLAG_AUTHORIZED;
+       if (flags & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
+               code |= QLINK_STA_FLAG_SHORT_PREAMBLE;
+       if (flags & BIT(NL80211_STA_FLAG_WME))
+               code |= QLINK_STA_FLAG_WME;
+       if (flags & BIT(NL80211_STA_FLAG_MFP))
+               code |= QLINK_STA_FLAG_MFP;
+       if (flags & BIT(NL80211_STA_FLAG_AUTHENTICATED))
+               code |= QLINK_STA_FLAG_AUTHENTICATED;
+       if (flags & BIT(NL80211_STA_FLAG_TDLS_PEER))
+               code |= QLINK_STA_FLAG_TDLS_PEER;
+       if (flags & BIT(NL80211_STA_FLAG_ASSOCIATED))
+               code |= QLINK_STA_FLAG_ASSOCIATED;
+       return code;
+}
+
+int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac,
+                            struct station_parameters *params)
+{
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_change_sta *cmd;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_CHANGE_STA,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_change_sta *)cmd_skb->data;
+       ether_addr_copy(cmd->sta_addr, mac);
+       cmd->sta_flags_mask = cpu_to_le32(qtnf_encode_sta_flags(
+                                         params->sta_flags_mask));
+       cmd->sta_flags_set = cpu_to_le32(qtnf_encode_sta_flags(
+                                        params->sta_flags_set));
+
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
+                         struct station_del_parameters *params)
+{
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_del_sta *cmd;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret = 0;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_DEL_STA,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_del_sta *)cmd_skb->data;
+
+       if (params->mac)
+               ether_addr_copy(cmd->sta_addr, params->mac);
+       else
+               eth_broadcast_addr(cmd->sta_addr);      /* flush all stations */
+
+       cmd->subtype = params->subtype;
+       cmd->reason_code = cpu_to_le16(params->reason_code);
+
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
+{
+       struct sk_buff *cmd_skb;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       struct ieee80211_channel *sc;
+       struct cfg80211_scan_request *scan_req = mac->scan_req;
+       struct qlink_tlv_channel *qchan;
+       int n_channels;
+       int count = 0;
+       int ret;
+       u32 flags;
+
+       if (scan_req->n_ssids > QTNF_MAX_SSID_LIST_LENGTH) {
+               pr_err("MAC%u: too many SSIDs in scan request\n", mac->macid);
+               return -EINVAL;
+       }
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
+                                           QLINK_CMD_SCAN,
+                                           sizeof(struct qlink_cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(mac->bus);
+
+       if (scan_req->n_ssids != 0) {
+               while (count < scan_req->n_ssids) {
+                       qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID,
+                               scan_req->ssids[count].ssid,
+                               scan_req->ssids[count].ssid_len);
+                       count++;
+               }
+       }
+
+       if (scan_req->ie_len != 0)
+               qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET,
+                                        scan_req->ie,
+                                        scan_req->ie_len);
+
+       if (scan_req->n_channels) {
+               n_channels = scan_req->n_channels;
+               count = 0;
+
+               while (n_channels != 0) {
+                       sc = scan_req->channels[count];
+                       if (sc->flags & IEEE80211_CHAN_DISABLED) {
+                               n_channels--;
+                               continue;
+                       }
+
+                       pr_debug("MAC%u: scan chan=%d, freq=%d, flags=%#x\n",
+                                mac->macid, sc->hw_value, sc->center_freq,
+                                sc->flags);
+                       qchan = (struct qlink_tlv_channel *)
+                                       skb_put(cmd_skb, sizeof(*qchan));
+                       memset(qchan, 0, sizeof(*qchan));
+                       flags = 0;
+
+                       qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
+                       qchan->hdr.len = cpu_to_le16(sizeof(*qchan) -
+                                       sizeof(struct qlink_tlv_hdr));
+                       qchan->center_freq = cpu_to_le16(sc->center_freq);
+                       qchan->hw_value = cpu_to_le16(sc->hw_value);
+
+                       if (sc->flags & IEEE80211_CHAN_NO_IR)
+                               flags |= QLINK_CHAN_NO_IR;
+
+                       if (sc->flags & IEEE80211_CHAN_RADAR)
+                               flags |= QLINK_CHAN_RADAR;
+
+                       qchan->flags = cpu_to_le32(flags);
+                       n_channels--;
+                       count++;
+               }
+       }
+
+       ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       pr_debug("MAC%u: scan started\n", mac->macid);
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+out:
+       qtnf_bus_unlock(mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_connect(struct qtnf_vif *vif,
+                         struct cfg80211_connect_params *sme)
+{
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_connect *cmd;
+       struct qtnf_bss_config *bss_cfg = &vif->bss_cfg;
+       struct qlink_auth_encr aen;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret;
+       int i;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_CONNECT,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_connect *)cmd_skb->data;
+
+       ether_addr_copy(cmd->bssid, bss_cfg->bssid);
+
+       if (bss_cfg->chandef.chan)
+               cmd->freq = cpu_to_le16(bss_cfg->chandef.chan->center_freq);
+
+       cmd->bg_scan_period = cpu_to_le16(bss_cfg->bg_scan_period);
+
+       memset(&aen, 0, sizeof(aen));
+       aen.auth_type = bss_cfg->auth_type;
+       aen.privacy = !!bss_cfg->privacy;
+       aen.mfp = bss_cfg->mfp;
+       aen.wpa_versions = cpu_to_le32(bss_cfg->crypto.wpa_versions);
+       aen.cipher_group = cpu_to_le32(bss_cfg->crypto.cipher_group);
+       aen.n_ciphers_pairwise = cpu_to_le32(
+                                       bss_cfg->crypto.n_ciphers_pairwise);
+
+       for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
+               aen.ciphers_pairwise[i] = cpu_to_le32(
+                                       bss_cfg->crypto.ciphers_pairwise[i]);
+
+       aen.n_akm_suites = cpu_to_le32(bss_cfg->crypto.n_akm_suites);
+
+       for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
+               aen.akm_suites[i] = cpu_to_le32(
+                                       bss_cfg->crypto.akm_suites[i]);
+
+       aen.control_port = bss_cfg->crypto.control_port;
+       aen.control_port_no_encrypt =
+                       bss_cfg->crypto.control_port_no_encrypt;
+       aen.control_port_ethertype = cpu_to_le16(be16_to_cpu(
+                               bss_cfg->crypto.control_port_ethertype));
+
+       qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, bss_cfg->ssid,
+                                bss_cfg->ssid_len);
+       qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_CRYPTO, (u8 *)&aen,
+                                sizeof(aen));
+
+       if (sme->ie_len != 0)
+               qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET,
+                                        sme->ie,
+                                        sme->ie_len);
+
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code)
+{
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_disconnect *cmd;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_DISCONNECT,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       cmd = (struct qlink_cmd_disconnect *)cmd_skb->data;
+       cmd->reason = cpu_to_le16(reason_code);
+
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
+
+int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up)
+{
+       struct sk_buff *cmd_skb;
+       struct qlink_cmd_updown *cmd;
+       u16 res_code = QLINK_CMD_RESULT_OK;
+       int ret;
+
+       cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
+                                           QLINK_CMD_UPDOWN_INTF,
+                                           sizeof(*cmd));
+       if (unlikely(!cmd_skb))
+               return -ENOMEM;
+
+       cmd = (struct qlink_cmd_updown *)cmd_skb->data;
+       cmd->if_up = !!up;
+
+       qtnf_bus_lock(vif->mac->bus);
+
+       ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
+
+       if (unlikely(ret))
+               goto out;
+
+       if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
+               pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid,
+                      vif->vifid, res_code);
+               ret = -EFAULT;
+               goto out;
+       }
+out:
+       qtnf_bus_unlock(vif->mac->bus);
+       return ret;
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h
new file mode 100644 (file)
index 0000000..6c51854
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016 Quantenna Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 QLINK_COMMANDS_H_
+#define QLINK_COMMANDS_H_
+
+#include <linux/nl80211.h>
+
+#include "core.h"
+#include "bus.h"
+
+int qtnf_cmd_send_init_fw(struct qtnf_bus *bus);
+void qtnf_cmd_send_deinit_fw(struct qtnf_bus *bus);
+int qtnf_cmd_get_hw_info(struct qtnf_bus *bus);
+int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac);
+int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype,
+                          u8 *mac_addr);
+int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif,
+                                  enum nl80211_iftype iftype, u8 *mac_addr);
+int qtnf_cmd_send_del_intf(struct qtnf_vif *vif);
+int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
+                              struct ieee80211_supported_band *band);
+int qtnf_cmd_send_regulatory_config(struct qtnf_wmac *mac, const char *alpha2);
+int qtnf_cmd_send_config_ap(struct qtnf_vif *vif);
+int qtnf_cmd_send_start_ap(struct qtnf_vif *vif);
+int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif);
+int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg);
+int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
+                            u16 freq, const u8 *buf, size_t len);
+int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
+                                const u8 *buf, size_t len);
+int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac,
+                         struct station_info *sinfo);
+int qtnf_cmd_send_phy_params(struct qtnf_wmac *mac, u16 cmd_action,
+                            void *data_buf);
+int qtnf_cmd_send_add_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
+                         const u8 *mac_addr, struct key_params *params);
+int qtnf_cmd_send_del_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
+                         const u8 *mac_addr);
+int qtnf_cmd_send_set_default_key(struct qtnf_vif *vif, u8 key_index,
+                                 bool unicast, bool multicast);
+int qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif *vif, u8 key_index);
+int qtnf_cmd_send_add_sta(struct qtnf_vif *vif, const u8 *mac,
+                         struct station_parameters *params);
+int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac,
+                            struct station_parameters *params);
+int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
+                         struct station_del_parameters *params);
+
+int qtnf_cmd_resp_parse(struct qtnf_bus *bus, struct sk_buff *resp_skb);
+int qtnf_cmd_resp_check(const struct qtnf_vif *vif,
+                       const struct sk_buff *resp_skb, u16 cmd_id,
+                       u16 *result, const u8 **payload, size_t *payload_size);
+int qtnf_cmd_send_scan(struct qtnf_wmac *mac);
+int qtnf_cmd_send_connect(struct qtnf_vif *vif,
+                         struct cfg80211_connect_params *sme);
+int qtnf_cmd_send_disconnect(struct qtnf_vif *vif,
+                            u16 reason_code);
+int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif,
+                             bool up);
+
+#endif /* QLINK_COMMANDS_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c
new file mode 100644 (file)
index 0000000..c5ac252
--- /dev/null
@@ -0,0 +1,618 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/if_ether.h>
+
+#include "core.h"
+#include "bus.h"
+#include "trans.h"
+#include "commands.h"
+#include "cfg80211.h"
+#include "event.h"
+#include "util.h"
+
+#define QTNF_DMP_MAX_LEN 48
+#define QTNF_PRIMARY_VIF_IDX   0
+
+struct qtnf_frame_meta_info {
+       u8 magic_s;
+       u8 ifidx;
+       u8 macid;
+       u8 magic_e;
+} __packed;
+
+struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid)
+{
+       struct qtnf_wmac *mac = NULL;
+
+       if (unlikely(macid >= QTNF_MAX_MAC)) {
+               pr_err("invalid MAC index %u\n", macid);
+               return NULL;
+       }
+
+       mac = bus->mac[macid];
+
+       if (unlikely(!mac)) {
+               pr_err("MAC%u: not initialized\n", macid);
+               return NULL;
+       }
+
+       return mac;
+}
+
+/* Netdev handler for open.
+ */
+static int qtnf_netdev_open(struct net_device *ndev)
+{
+       netif_carrier_off(ndev);
+       qtnf_netdev_updown(ndev, 1);
+       return 0;
+}
+
+/* Netdev handler for close.
+ */
+static int qtnf_netdev_close(struct net_device *ndev)
+{
+       netif_carrier_off(ndev);
+       qtnf_virtual_intf_cleanup(ndev);
+       qtnf_netdev_updown(ndev, 0);
+       return 0;
+}
+
+/* Netdev handler for data transmission.
+ */
+static int
+qtnf_netdev_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+       struct qtnf_vif *vif;
+       struct qtnf_wmac *mac;
+
+       vif = qtnf_netdev_get_priv(ndev);
+
+       if (unlikely(skb->dev != ndev)) {
+               pr_err_ratelimited("invalid skb->dev");
+               dev_kfree_skb_any(skb);
+               return 0;
+       }
+
+       if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)) {
+               pr_err_ratelimited("%s: VIF not initialized\n", ndev->name);
+               dev_kfree_skb_any(skb);
+               return 0;
+       }
+
+       mac = vif->mac;
+       if (unlikely(!mac)) {
+               pr_err_ratelimited("%s: NULL mac pointer", ndev->name);
+               dev_kfree_skb_any(skb);
+               return 0;
+       }
+
+       if (!skb->len || (skb->len > ETH_FRAME_LEN)) {
+               pr_err_ratelimited("%s: invalid skb len %d\n", ndev->name,
+                                  skb->len);
+               dev_kfree_skb_any(skb);
+               ndev->stats.tx_dropped++;
+               return 0;
+       }
+
+       /* tx path is enabled: reset vif timeout */
+       vif->cons_tx_timeout_cnt = 0;
+
+       return qtnf_bus_data_tx(mac->bus, skb);
+}
+
+/* Netdev handler for getting stats.
+ */
+static struct net_device_stats *qtnf_netdev_get_stats(struct net_device *dev)
+{
+       return &dev->stats;
+}
+
+/* Netdev handler for transmission timeout.
+ */
+static void qtnf_netdev_tx_timeout(struct net_device *ndev)
+{
+       struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
+       struct qtnf_wmac *mac;
+       struct qtnf_bus *bus;
+
+       if (unlikely(!vif || !vif->mac || !vif->mac->bus))
+               return;
+
+       mac = vif->mac;
+       bus = mac->bus;
+
+       pr_warn("VIF%u.%u: Tx timeout- %lu\n", mac->macid, vif->vifid, jiffies);
+
+       qtnf_bus_data_tx_timeout(bus, ndev);
+       ndev->stats.tx_errors++;
+
+       if (++vif->cons_tx_timeout_cnt > QTNF_TX_TIMEOUT_TRSHLD) {
+               pr_err("Tx timeout threshold exceeded !\n");
+               pr_err("schedule interface %s reset !\n", netdev_name(ndev));
+               queue_work(bus->workqueue, &vif->reset_work);
+       }
+}
+
+/* Network device ops handlers */
+const struct net_device_ops qtnf_netdev_ops = {
+       .ndo_open = qtnf_netdev_open,
+       .ndo_stop = qtnf_netdev_close,
+       .ndo_start_xmit = qtnf_netdev_hard_start_xmit,
+       .ndo_tx_timeout = qtnf_netdev_tx_timeout,
+       .ndo_get_stats = qtnf_netdev_get_stats,
+};
+
+static int qtnf_mac_init_single_band(struct wiphy *wiphy,
+                                    struct qtnf_wmac *mac,
+                                    enum nl80211_band band)
+{
+       int ret;
+
+       wiphy->bands[band] = kzalloc(sizeof(*wiphy->bands[band]), GFP_KERNEL);
+       if (!wiphy->bands[band])
+               return -ENOMEM;
+
+       wiphy->bands[band]->band = band;
+
+       ret = qtnf_cmd_get_mac_chan_info(mac, wiphy->bands[band]);
+       if (ret) {
+               pr_err("MAC%u: band %u: failed to get chans info: %d\n",
+                      mac->macid, band, ret);
+               return ret;
+       }
+
+       qtnf_band_init_rates(wiphy->bands[band]);
+       qtnf_band_setup_htvht_caps(&mac->macinfo, wiphy->bands[band]);
+
+       return 0;
+}
+
+static int qtnf_mac_init_bands(struct qtnf_wmac *mac)
+{
+       struct wiphy *wiphy = priv_to_wiphy(mac);
+       int ret = 0;
+
+       if (mac->macinfo.bands_cap & QLINK_BAND_2GHZ) {
+               ret = qtnf_mac_init_single_band(wiphy, mac, NL80211_BAND_2GHZ);
+               if (ret)
+                       goto out;
+       }
+
+       if (mac->macinfo.bands_cap & QLINK_BAND_5GHZ) {
+               ret = qtnf_mac_init_single_band(wiphy, mac, NL80211_BAND_5GHZ);
+               if (ret)
+                       goto out;
+       }
+
+       if (mac->macinfo.bands_cap & QLINK_BAND_60GHZ)
+               ret = qtnf_mac_init_single_band(wiphy, mac, NL80211_BAND_60GHZ);
+
+out:
+       return ret;
+}
+
+struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac)
+{
+       struct qtnf_vif *vif;
+       int i;
+
+       for (i = 0; i < QTNF_MAX_INTF; i++) {
+               vif = &mac->iflist[i];
+               if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)
+                       return vif;
+       }
+
+       return NULL;
+}
+
+struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac)
+{
+       struct qtnf_vif *vif;
+
+       vif = &mac->iflist[QTNF_PRIMARY_VIF_IDX];
+
+       if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)
+               return NULL;
+
+       return vif;
+}
+
+static void qtnf_vif_reset_handler(struct work_struct *work)
+{
+       struct qtnf_vif *vif = container_of(work, struct qtnf_vif, reset_work);
+
+       rtnl_lock();
+
+       if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) {
+               rtnl_unlock();
+               return;
+       }
+
+       /* stop tx completely */
+       netif_tx_stop_all_queues(vif->netdev);
+       if (netif_carrier_ok(vif->netdev))
+               netif_carrier_off(vif->netdev);
+
+       qtnf_cfg80211_vif_reset(vif);
+
+       rtnl_unlock();
+}
+
+static void qtnf_mac_init_primary_intf(struct qtnf_wmac *mac)
+{
+       struct qtnf_vif *vif = &mac->iflist[QTNF_PRIMARY_VIF_IDX];
+
+       vif->wdev.iftype = NL80211_IFTYPE_AP;
+       vif->bss_priority = QTNF_DEF_BSS_PRIORITY;
+       vif->wdev.wiphy = priv_to_wiphy(mac);
+       INIT_WORK(&vif->reset_work, qtnf_vif_reset_handler);
+       vif->cons_tx_timeout_cnt = 0;
+}
+
+static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
+                                            unsigned int macid)
+{
+       struct wiphy *wiphy;
+       struct qtnf_wmac *mac;
+       unsigned int i;
+
+       wiphy = qtnf_wiphy_allocate(bus);
+       if (!wiphy)
+               return ERR_PTR(-ENOMEM);
+
+       mac = wiphy_priv(wiphy);
+
+       mac->macid = macid;
+       mac->bus = bus;
+
+       for (i = 0; i < QTNF_MAX_INTF; i++) {
+               memset(&mac->iflist[i], 0, sizeof(struct qtnf_vif));
+               mac->iflist[i].wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+               mac->iflist[i].mac = mac;
+               mac->iflist[i].vifid = i;
+               qtnf_sta_list_init(&mac->iflist[i].sta_list);
+       }
+
+       qtnf_mac_init_primary_intf(mac);
+       bus->mac[macid] = mac;
+
+       return mac;
+}
+
+int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif,
+                        const char *name, unsigned char name_assign_type,
+                        enum nl80211_iftype iftype)
+{
+       struct wiphy *wiphy = priv_to_wiphy(mac);
+       struct net_device *dev;
+       void *qdev_vif;
+       int ret;
+
+       dev = alloc_netdev_mqs(sizeof(struct qtnf_vif *), name,
+                              name_assign_type, ether_setup, 1, 1);
+       if (!dev) {
+               memset(&vif->wdev, 0, sizeof(vif->wdev));
+               vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+               return -ENOMEM;
+       }
+
+       vif->netdev = dev;
+
+       dev->netdev_ops = &qtnf_netdev_ops;
+       dev->destructor = free_netdev;
+       dev_net_set(dev, wiphy_net(wiphy));
+       dev->ieee80211_ptr = &vif->wdev;
+       dev->ieee80211_ptr->iftype = iftype;
+       ether_addr_copy(dev->dev_addr, vif->mac_addr);
+       SET_NETDEV_DEV(dev, wiphy_dev(wiphy));
+       dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+       dev->watchdog_timeo = QTNF_DEF_WDOG_TIMEOUT;
+       dev->tx_queue_len = 100;
+
+       qdev_vif = netdev_priv(dev);
+       *((void **)qdev_vif) = vif;
+
+       SET_NETDEV_DEV(dev, mac->bus->dev);
+
+       ret = register_netdevice(dev);
+       if (ret) {
+               free_netdev(dev);
+               vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+       }
+
+       return ret;
+}
+
+static void qtnf_core_mac_detach(struct qtnf_bus *bus, unsigned int macid)
+{
+       struct qtnf_wmac *mac;
+       struct wiphy *wiphy;
+       struct qtnf_vif *vif;
+       unsigned int i;
+       enum nl80211_band band;
+
+       mac = bus->mac[macid];
+
+       if (!mac)
+               return;
+
+       wiphy = priv_to_wiphy(mac);
+
+       for (i = 0; i < QTNF_MAX_INTF; i++) {
+               vif = &mac->iflist[i];
+               rtnl_lock();
+               if (vif->netdev &&
+                   vif->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED) {
+                       qtnf_virtual_intf_cleanup(vif->netdev);
+                       qtnf_del_virtual_intf(wiphy, &vif->wdev);
+               }
+               rtnl_unlock();
+               qtnf_sta_list_free(&vif->sta_list);
+       }
+
+       if (mac->wiphy_registered)
+               wiphy_unregister(wiphy);
+
+       for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; ++band) {
+               if (!wiphy->bands[band])
+                       continue;
+
+               kfree(wiphy->bands[band]->channels);
+               wiphy->bands[band]->n_channels = 0;
+
+               kfree(wiphy->bands[band]);
+               wiphy->bands[band] = NULL;
+       }
+
+       kfree(mac->macinfo.limits);
+       kfree(wiphy->iface_combinations);
+       wiphy_free(wiphy);
+       bus->mac[macid] = NULL;
+}
+
+static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid)
+{
+       struct qtnf_wmac *mac;
+       struct qtnf_vif *vif;
+       int ret;
+
+       if (!(bus->hw_info.mac_bitmap & BIT(macid))) {
+               pr_info("MAC%u is not active in FW\n", macid);
+               return 0;
+       }
+
+       mac = qtnf_core_mac_alloc(bus, macid);
+       if (IS_ERR(mac)) {
+               pr_err("MAC%u allocation failed\n", macid);
+               return PTR_ERR(mac);
+       }
+
+       ret = qtnf_cmd_get_mac_info(mac);
+       if (ret) {
+               pr_err("MAC%u: failed to get info\n", macid);
+               goto error;
+       }
+
+       vif = qtnf_mac_get_base_vif(mac);
+       if (!vif) {
+               pr_err("MAC%u: primary VIF is not ready\n", macid);
+               ret = -EFAULT;
+               goto error;
+       }
+
+       ret = qtnf_cmd_send_add_intf(vif, NL80211_IFTYPE_AP, vif->mac_addr);
+       if (ret) {
+               pr_err("MAC%u: failed to add VIF\n", macid);
+               goto error;
+       }
+
+       ret = qtnf_cmd_send_get_phy_params(mac);
+       if (ret) {
+               pr_err("MAC%u: failed to get PHY settings\n", macid);
+               goto error;
+       }
+
+       ret = qtnf_mac_init_bands(mac);
+       if (ret) {
+               pr_err("MAC%u: failed to init bands\n", macid);
+               goto error;
+       }
+
+       ret = qtnf_wiphy_register(&bus->hw_info, mac);
+       if (ret) {
+               pr_err("MAC%u: wiphy registration failed\n", macid);
+               goto error;
+       }
+
+       mac->wiphy_registered = 1;
+
+       rtnl_lock();
+
+       ret = qtnf_core_net_attach(mac, vif, "wlan%d", NET_NAME_ENUM,
+                                  NL80211_IFTYPE_AP);
+       rtnl_unlock();
+
+       if (ret) {
+               pr_err("MAC%u: failed to attach netdev\n", macid);
+               vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+               vif->netdev = NULL;
+               goto error;
+       }
+
+       pr_debug("MAC%u initialized\n", macid);
+
+       return 0;
+
+error:
+       qtnf_core_mac_detach(bus, macid);
+       return ret;
+}
+
+int qtnf_core_attach(struct qtnf_bus *bus)
+{
+       unsigned int i;
+       int ret;
+
+       qtnf_trans_init(bus);
+
+       bus->fw_state = QTNF_FW_STATE_BOOT_DONE;
+       qtnf_bus_data_rx_start(bus);
+
+       bus->workqueue = alloc_ordered_workqueue("QTNF_BUS", 0);
+       if (!bus->workqueue) {
+               pr_err("failed to alloc main workqueue\n");
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       INIT_WORK(&bus->event_work, qtnf_event_work_handler);
+
+       ret = qtnf_cmd_send_init_fw(bus);
+       if (ret) {
+               pr_err("failed to init FW: %d\n", ret);
+               goto error;
+       }
+
+       bus->fw_state = QTNF_FW_STATE_ACTIVE;
+
+       ret = qtnf_cmd_get_hw_info(bus);
+       if (ret) {
+               pr_err("failed to get HW info: %d\n", ret);
+               goto error;
+       }
+
+       if (bus->hw_info.ql_proto_ver != QLINK_PROTO_VER) {
+               pr_err("qlink version mismatch %u != %u\n",
+                      QLINK_PROTO_VER, bus->hw_info.ql_proto_ver);
+               ret = -EPROTONOSUPPORT;
+               goto error;
+       }
+
+       if (bus->hw_info.num_mac > QTNF_MAX_MAC) {
+               pr_err("no support for number of MACs=%u\n",
+                      bus->hw_info.num_mac);
+               ret = -ERANGE;
+               goto error;
+       }
+
+       for (i = 0; i < bus->hw_info.num_mac; i++) {
+               ret = qtnf_core_mac_attach(bus, i);
+
+               if (ret) {
+                       pr_err("MAC%u: attach failed: %d\n", i, ret);
+                       goto error;
+               }
+       }
+
+       return 0;
+
+error:
+       qtnf_core_detach(bus);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(qtnf_core_attach);
+
+void qtnf_core_detach(struct qtnf_bus *bus)
+{
+       unsigned int macid;
+
+       qtnf_bus_data_rx_stop(bus);
+
+       for (macid = 0; macid < QTNF_MAX_MAC; macid++)
+               qtnf_core_mac_detach(bus, macid);
+
+       if (bus->fw_state == QTNF_FW_STATE_ACTIVE)
+               qtnf_cmd_send_deinit_fw(bus);
+
+       bus->fw_state = QTNF_FW_STATE_DEAD;
+
+       if (bus->workqueue) {
+               flush_workqueue(bus->workqueue);
+               destroy_workqueue(bus->workqueue);
+       }
+
+       qtnf_trans_free(bus);
+}
+EXPORT_SYMBOL_GPL(qtnf_core_detach);
+
+static inline int qtnf_is_frame_meta_magic_valid(struct qtnf_frame_meta_info *m)
+{
+       return m->magic_s == 0xAB && m->magic_e == 0xBA;
+}
+
+struct net_device *qtnf_classify_skb(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+       struct qtnf_frame_meta_info *meta;
+       struct net_device *ndev = NULL;
+       struct qtnf_wmac *mac;
+       struct qtnf_vif *vif;
+
+       meta = (struct qtnf_frame_meta_info *)
+               (skb_tail_pointer(skb) - sizeof(*meta));
+
+       if (unlikely(!qtnf_is_frame_meta_magic_valid(meta))) {
+               pr_err_ratelimited("invalid magic 0x%x:0x%x\n",
+                                  meta->magic_s, meta->magic_e);
+               goto out;
+       }
+
+       if (unlikely(meta->macid >= QTNF_MAX_MAC)) {
+               pr_err_ratelimited("invalid mac(%u)\n", meta->macid);
+               goto out;
+       }
+
+       if (unlikely(meta->ifidx >= QTNF_MAX_INTF)) {
+               pr_err_ratelimited("invalid vif(%u)\n", meta->ifidx);
+               goto out;
+       }
+
+       mac = bus->mac[meta->macid];
+
+       if (unlikely(!mac)) {
+               pr_err_ratelimited("mac(%d) does not exist\n", meta->macid);
+               goto out;
+       }
+
+       vif = &mac->iflist[meta->ifidx];
+
+       if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)) {
+               pr_err_ratelimited("vif(%u) does not exists\n", meta->ifidx);
+               goto out;
+       }
+
+       ndev = vif->netdev;
+
+       if (unlikely(!ndev)) {
+               pr_err_ratelimited("netdev for wlan%u.%u does not exists\n",
+                                  meta->macid, meta->ifidx);
+               goto out;
+       }
+
+       __skb_trim(skb, skb->len - sizeof(*meta));
+
+out:
+       return ndev;
+}
+EXPORT_SYMBOL_GPL(qtnf_classify_skb);
+
+MODULE_AUTHOR("Quantenna Communications");
+MODULE_DESCRIPTION("Quantenna 802.11 wireless LAN FullMAC driver.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
new file mode 100644 (file)
index 0000000..a616434
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 _QTN_FMAC_CORE_H_
+#define _QTN_FMAC_CORE_H_
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/semaphore.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <net/sock.h>
+#include <net/lib80211.h>
+#include <net/cfg80211.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <linux/ctype.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+
+#include "qlink.h"
+#include "trans.h"
+
+#undef pr_fmt
+#define pr_fmt(fmt)    KBUILD_MODNAME ": %s: " fmt, __func__
+
+#define QTNF_MAX_SSID_LIST_LENGTH      2
+#define QTNF_MAX_VSIE_LEN              255
+#define QTNF_MAX_ALPHA_LEN             2
+#define QTNF_MAX_INTF                  8
+#define QTNF_MAX_EVENT_QUEUE_LEN       255
+#define QTNF_DEFAULT_BG_SCAN_PERIOD    300
+#define QTNF_MAX_BG_SCAN_PERIOD                0xffff
+
+#define QTNF_DEF_BSS_PRIORITY          0
+#define QTNF_DEF_WDOG_TIMEOUT          5
+#define QTNF_TX_TIMEOUT_TRSHLD         100
+
+#define QTNF_STATE_AP_CONFIG           BIT(2)
+#define QTNF_STATE_AP_START            BIT(1)
+
+extern const struct net_device_ops qtnf_netdev_ops;
+struct qtnf_bus;
+struct qtnf_vif;
+
+struct qtnf_bss_config {
+       u8 ssid[IEEE80211_MAX_SSID_LEN];
+       u8 bssid[ETH_ALEN];
+       size_t ssid_len;
+       u8 dtim;
+       u16 bcn_period;
+       u16 auth_type;
+       bool privacy;
+       enum nl80211_mfp mfp;
+       struct cfg80211_chan_def chandef;
+       struct cfg80211_crypto_settings crypto;
+       u16 bg_scan_period;
+       u32 connect_flags;
+};
+
+struct qtnf_sta_node {
+       struct list_head list;
+       u8 mac_addr[ETH_ALEN];
+};
+
+struct qtnf_sta_list {
+       struct list_head head;
+       atomic_t size;
+};
+
+enum qtnf_sta_state {
+       QTNF_STA_DISCONNECTED,
+       QTNF_STA_CONNECTING,
+       QTNF_STA_CONNECTED
+};
+
+struct qtnf_vif {
+       struct wireless_dev wdev;
+       u8 vifid;
+       u8 bss_priority;
+       u8 bss_status;
+       enum qtnf_sta_state sta_state;
+       u16 mgmt_frames_bitmask;
+       struct net_device *netdev;
+       struct qtnf_wmac *mac;
+       u8 mac_addr[ETH_ALEN];
+       struct work_struct reset_work;
+       struct qtnf_bss_config bss_cfg;
+       struct qtnf_sta_list sta_list;
+       unsigned long cons_tx_timeout_cnt;
+};
+
+struct qtnf_mac_info {
+       u8 bands_cap;
+       u8 phymode_cap;
+       u8 dev_mac[ETH_ALEN];
+       u8 num_tx_chain;
+       u8 num_rx_chain;
+       u16 max_ap_assoc_sta;
+       u32 frag_thr;
+       u32 rts_thr;
+       u8 lretry_limit;
+       u8 sretry_limit;
+       u8 coverage_class;
+       u8 radar_detect_widths;
+       struct ieee80211_ht_cap ht_cap;
+       struct ieee80211_vht_cap vht_cap;
+       struct ieee80211_iface_limit *limits;
+       size_t n_limits;
+};
+
+struct qtnf_wmac {
+       u8 macid;
+       u8 wiphy_registered;
+       u8 macaddr[ETH_ALEN];
+       struct qtnf_bus *bus;
+       struct qtnf_mac_info macinfo;
+       struct qtnf_vif iflist[QTNF_MAX_INTF];
+       struct cfg80211_scan_request *scan_req;
+};
+
+struct qtnf_hw_info {
+       u8 num_mac;
+       u8 mac_bitmap;
+       u8 alpha2_code[QTNF_MAX_ALPHA_LEN];
+       u32 fw_ver;
+       u16 ql_proto_ver;
+       u8 total_tx_chain;
+       u8 total_rx_chain;
+       u32 hw_capab;
+};
+
+struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac);
+struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac);
+struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus);
+int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *priv,
+                        const char *name, unsigned char name_assign_type,
+                        enum nl80211_iftype iftype);
+void qtnf_main_work_queue(struct work_struct *work);
+int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed);
+int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac);
+
+struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid);
+struct net_device *qtnf_classify_skb(struct qtnf_bus *bus, struct sk_buff *skb);
+struct net_device *qtnf_classify_skb_no_mbss(struct qtnf_bus *bus,
+                                            struct sk_buff *skb);
+
+void qtnf_virtual_intf_cleanup(struct net_device *ndev);
+
+void qtnf_netdev_updown(struct net_device *ndev, bool up);
+
+static inline struct qtnf_vif *qtnf_netdev_get_priv(struct net_device *dev)
+{
+       return *((void **)netdev_priv(dev));
+}
+
+#endif /* _QTN_FMAC_CORE_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/debug.c b/drivers/net/wireless/quantenna/qtnfmac/debug.c
new file mode 100644 (file)
index 0000000..9f826b9
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 "debug.h"
+
+#undef pr_fmt
+#define pr_fmt(fmt)    "qtnfmac dbg: %s: " fmt, __func__
+
+void qtnf_debugfs_init(struct qtnf_bus *bus, const char *name)
+{
+       bus->dbg_dir = debugfs_create_dir(name, NULL);
+
+       if (IS_ERR_OR_NULL(bus->dbg_dir)) {
+               pr_warn("failed to create debugfs root dir\n");
+               bus->dbg_dir = NULL;
+       }
+}
+
+void qtnf_debugfs_remove(struct qtnf_bus *bus)
+{
+       debugfs_remove_recursive(bus->dbg_dir);
+       bus->dbg_dir = NULL;
+}
+
+void qtnf_debugfs_add_entry(struct qtnf_bus *bus, const char *name,
+                           int (*fn)(struct seq_file *seq, void *data))
+{
+       struct dentry *entry;
+
+       entry = debugfs_create_devm_seqfile(bus->dev, name, bus->dbg_dir, fn);
+       if (IS_ERR_OR_NULL(entry))
+               pr_warn("failed to add entry (%s)\n", name);
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/debug.h b/drivers/net/wireless/quantenna/qtnfmac/debug.h
new file mode 100644 (file)
index 0000000..d6dd12b
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 _QTN_FMAC_DEBUG_H_
+#define _QTN_FMAC_DEBUG_H_
+
+#include <linux/debugfs.h>
+
+#include "core.h"
+#include "bus.h"
+
+#ifdef CONFIG_DEBUG_FS
+
+void qtnf_debugfs_init(struct qtnf_bus *bus, const char *name);
+void qtnf_debugfs_remove(struct qtnf_bus *bus);
+void qtnf_debugfs_add_entry(struct qtnf_bus *bus, const char *name,
+                           int (*fn)(struct seq_file *seq, void *data));
+
+#else
+
+static inline void qtnf_debugfs_init(struct qtnf_bus *bus, const char *name)
+{
+}
+
+static inline void qtnf_debugfs_remove(struct qtnf_bus *bus)
+{
+}
+
+static inline void
+qtnf_debugfs_add_entry(struct qtnf_bus *bus, const char *name,
+                      int (*fn)(struct seq_file *seq, void *data))
+{
+}
+
+#endif /* CONFIG_DEBUG_FS */
+
+#endif /* _QTN_FMAC_DEBUG_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
new file mode 100644 (file)
index 0000000..9b61e9a
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "cfg80211.h"
+#include "core.h"
+#include "qlink.h"
+#include "bus.h"
+#include "trans.h"
+#include "util.h"
+#include "event.h"
+
+static int
+qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
+                           const struct qlink_event_sta_assoc *sta_assoc,
+                           u16 len)
+{
+       const u8 *sta_addr;
+       u16 frame_control;
+       struct station_info sinfo = { 0 };
+       size_t payload_len;
+       u16 tlv_type;
+       u16 tlv_value_len;
+       size_t tlv_full_len;
+       const struct qlink_tlv_hdr *tlv;
+
+       if (unlikely(len < sizeof(*sta_assoc))) {
+               pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
+                      mac->macid, vif->vifid, len, sizeof(*sta_assoc));
+               return -EINVAL;
+       }
+
+       if (vif->wdev.iftype != NL80211_IFTYPE_AP) {
+               pr_err("VIF%u.%u: STA_ASSOC event when not in AP mode\n",
+                      mac->macid, vif->vifid);
+               return -EPROTO;
+       }
+
+       if (!(vif->bss_status & QTNF_STATE_AP_START)) {
+               pr_err("VIF%u.%u: STA_ASSOC event when AP is not started\n",
+                      mac->macid, vif->vifid);
+               return -EPROTO;
+       }
+
+       sta_addr = sta_assoc->sta_addr;
+       frame_control = le16_to_cpu(sta_assoc->frame_control);
+
+       pr_debug("VIF%u.%u: MAC:%pM FC:%x\n", mac->macid, vif->vifid, sta_addr,
+                frame_control);
+
+       qtnf_sta_list_add(&vif->sta_list, sta_addr);
+
+       sinfo.assoc_req_ies = NULL;
+       sinfo.assoc_req_ies_len = 0;
+
+       payload_len = len - sizeof(*sta_assoc);
+       tlv = (struct qlink_tlv_hdr *)sta_assoc->ies;
+
+       while (payload_len >= sizeof(struct qlink_tlv_hdr)) {
+               tlv_type = le16_to_cpu(tlv->type);
+               tlv_value_len = le16_to_cpu(tlv->len);
+               tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
+
+               if (tlv_full_len > payload_len) {
+                       pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n",
+                               mac->macid, vif->vifid, tlv_type,
+                               tlv_value_len);
+                       return -EINVAL;
+               }
+
+               if (tlv_type == QTN_TLV_ID_IE_SET) {
+                       sinfo.assoc_req_ies = tlv->val;
+                       sinfo.assoc_req_ies_len = tlv_value_len;
+               }
+
+               payload_len -= tlv_full_len;
+               tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
+       }
+
+       if (payload_len) {
+               pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n",
+                       mac->macid, vif->vifid, payload_len);
+               return -EINVAL;
+       }
+
+       cfg80211_new_sta(vif->netdev, sta_assoc->sta_addr, &sinfo,
+                        GFP_KERNEL);
+
+       return 0;
+}
+
+static int
+qtnf_event_handle_sta_deauth(struct qtnf_wmac *mac, struct qtnf_vif *vif,
+                            const struct qlink_event_sta_deauth *sta_deauth,
+                            u16 len)
+{
+       const u8 *sta_addr;
+       u16 reason;
+
+       if (unlikely(len < sizeof(*sta_deauth))) {
+               pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
+                      mac->macid, vif->vifid, len,
+                      sizeof(struct qlink_event_sta_deauth));
+               return -EINVAL;
+       }
+
+       if (vif->wdev.iftype != NL80211_IFTYPE_AP) {
+               pr_err("VIF%u.%u: STA_DEAUTH event when not in AP mode\n",
+                      mac->macid, vif->vifid);
+               return -EPROTO;
+       }
+
+       if (!(vif->bss_status & QTNF_STATE_AP_START)) {
+               pr_err("VIF%u.%u: STA_DEAUTH event when AP is not started\n",
+                      mac->macid, vif->vifid);
+               return -EPROTO;
+       }
+
+       sta_addr = sta_deauth->sta_addr;
+       reason = le16_to_cpu(sta_deauth->reason);
+
+       pr_debug("VIF%u.%u: MAC:%pM reason:%x\n", mac->macid, vif->vifid,
+                sta_addr, reason);
+
+       if (qtnf_sta_list_del(&vif->sta_list, sta_addr))
+               cfg80211_del_sta(vif->netdev, sta_deauth->sta_addr,
+                                GFP_KERNEL);
+
+       return 0;
+}
+
+static int
+qtnf_event_handle_bss_join(struct qtnf_vif *vif,
+                          const struct qlink_event_bss_join *join_info,
+                          u16 len)
+{
+       if (unlikely(len < sizeof(*join_info))) {
+               pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
+                      vif->mac->macid, vif->vifid, len,
+                      sizeof(struct qlink_event_bss_join));
+               return -EINVAL;
+       }
+
+       if (vif->wdev.iftype != NL80211_IFTYPE_STATION) {
+               pr_err("VIF%u.%u: BSS_JOIN event when not in STA mode\n",
+                      vif->mac->macid, vif->vifid);
+               return -EPROTO;
+       }
+
+       if (vif->sta_state != QTNF_STA_CONNECTING) {
+               pr_err("VIF%u.%u: BSS_JOIN event when STA is not connecting\n",
+                      vif->mac->macid, vif->vifid);
+               return -EPROTO;
+       }
+
+       pr_debug("VIF%u.%u: BSSID:%pM\n", vif->mac->macid, vif->vifid,
+                join_info->bssid);
+
+       cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL,
+                               0, le16_to_cpu(join_info->status), GFP_KERNEL);
+
+       if (le16_to_cpu(join_info->status) == WLAN_STATUS_SUCCESS) {
+               vif->sta_state = QTNF_STA_CONNECTED;
+               netif_carrier_on(vif->netdev);
+       } else {
+               vif->sta_state = QTNF_STA_DISCONNECTED;
+       }
+
+       return 0;
+}
+
+static int
+qtnf_event_handle_bss_leave(struct qtnf_vif *vif,
+                           const struct qlink_event_bss_leave *leave_info,
+                           u16 len)
+{
+       if (unlikely(len < sizeof(*leave_info))) {
+               pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
+                      vif->mac->macid, vif->vifid, len,
+                      sizeof(struct qlink_event_bss_leave));
+               return -EINVAL;
+       }
+
+       if (vif->wdev.iftype != NL80211_IFTYPE_STATION) {
+               pr_err("VIF%u.%u: BSS_LEAVE event when not in STA mode\n",
+                      vif->mac->macid, vif->vifid);
+               return -EPROTO;
+       }
+
+       if (vif->sta_state != QTNF_STA_CONNECTED) {
+               pr_err("VIF%u.%u: BSS_LEAVE event when STA is not connected\n",
+                      vif->mac->macid, vif->vifid);
+               return -EPROTO;
+       }
+
+       pr_debug("VIF%u.%u: disconnected\n", vif->mac->macid, vif->vifid);
+
+       cfg80211_disconnected(vif->netdev, leave_info->reason, NULL, 0, 0,
+                             GFP_KERNEL);
+
+       vif->sta_state = QTNF_STA_DISCONNECTED;
+       netif_carrier_off(vif->netdev);
+
+       return 0;
+}
+
+static int
+qtnf_event_handle_mgmt_received(struct qtnf_vif *vif,
+                               const struct qlink_event_rxmgmt *rxmgmt,
+                               u16 len)
+{
+       const size_t min_len = sizeof(*rxmgmt) +
+                              sizeof(struct ieee80211_hdr_3addr);
+       const struct ieee80211_hdr_3addr *frame = (void *)rxmgmt->frame_data;
+       const u16 frame_len = len - sizeof(*rxmgmt);
+       enum nl80211_rxmgmt_flags flags = 0;
+
+       if (unlikely(len < min_len)) {
+               pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
+                      vif->mac->macid, vif->vifid, len, min_len);
+               return -EINVAL;
+       }
+
+       if (le32_to_cpu(rxmgmt->flags) & QLINK_RXMGMT_FLAG_ANSWERED)
+               flags |= NL80211_RXMGMT_FLAG_ANSWERED;
+
+       pr_debug("%s LEN:%u FC:%.4X SA:%pM\n", vif->netdev->name, frame_len,
+                le16_to_cpu(frame->frame_control), frame->addr2);
+
+       cfg80211_rx_mgmt(&vif->wdev, le32_to_cpu(rxmgmt->freq),
+                        le32_to_cpu(rxmgmt->sig_dbm), rxmgmt->frame_data,
+                        frame_len, flags);
+
+       return 0;
+}
+
+static int
+qtnf_event_handle_scan_results(struct qtnf_vif *vif,
+                              const struct qlink_event_scan_result *sr,
+                              u16 len)
+{
+       struct cfg80211_bss *bss;
+       struct ieee80211_channel *channel;
+       struct wiphy *wiphy = priv_to_wiphy(vif->mac);
+       enum cfg80211_bss_frame_type frame_type;
+       size_t payload_len;
+       u16 tlv_type;
+       u16 tlv_value_len;
+       size_t tlv_full_len;
+       const struct qlink_tlv_hdr *tlv;
+
+       const u8 *ies = NULL;
+       size_t ies_len = 0;
+
+       if (len < sizeof(*sr)) {
+               pr_err("VIF%u.%u: payload is too short\n", vif->mac->macid,
+                      vif->vifid);
+               return -EINVAL;
+       }
+
+       channel = ieee80211_get_channel(wiphy, le16_to_cpu(sr->freq));
+       if (!channel) {
+               pr_err("VIF%u.%u: channel at %u MHz not found\n",
+                      vif->mac->macid, vif->vifid, le16_to_cpu(sr->freq));
+               return -EINVAL;
+       }
+
+       switch (sr->frame_type) {
+       case QLINK_BSS_FTYPE_BEACON:
+               frame_type = CFG80211_BSS_FTYPE_BEACON;
+               break;
+       case QLINK_BSS_FTYPE_PRESP:
+               frame_type = CFG80211_BSS_FTYPE_PRESP;
+               break;
+       default:
+               frame_type = CFG80211_BSS_FTYPE_UNKNOWN;
+       }
+
+       payload_len = len - sizeof(*sr);
+       tlv = (struct qlink_tlv_hdr *)sr->payload;
+
+       while (payload_len >= sizeof(struct qlink_tlv_hdr)) {
+               tlv_type = le16_to_cpu(tlv->type);
+               tlv_value_len = le16_to_cpu(tlv->len);
+               tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
+
+               if (tlv_full_len > payload_len) {
+                       pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n",
+                               vif->mac->macid, vif->vifid, tlv_type,
+                               tlv_value_len);
+                       return -EINVAL;
+               }
+
+               if (tlv_type == QTN_TLV_ID_IE_SET) {
+                       ies = tlv->val;
+                       ies_len = tlv_value_len;
+               }
+
+               payload_len -= tlv_full_len;
+               tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
+       }
+
+       if (payload_len) {
+               pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n",
+                       vif->mac->macid, vif->vifid, payload_len);
+               return -EINVAL;
+       }
+
+       bss = cfg80211_inform_bss(wiphy, channel, frame_type,
+                                 sr->bssid, get_unaligned_le64(&sr->tsf),
+                                 le16_to_cpu(sr->capab),
+                                 le16_to_cpu(sr->bintval), ies, ies_len,
+                                 sr->signal, GFP_KERNEL);
+       if (!bss)
+               return -ENOMEM;
+
+       cfg80211_put_bss(wiphy, bss);
+
+       return 0;
+}
+
+static int
+qtnf_event_handle_scan_complete(struct qtnf_wmac *mac,
+                               const struct qlink_event_scan_complete *status,
+                               u16 len)
+{
+       if (len < sizeof(*status)) {
+               pr_err("MAC%u: payload is too short\n", mac->macid);
+               return -EINVAL;
+       }
+
+       qtnf_scan_done(mac, le32_to_cpu(status->flags) & QLINK_SCAN_ABORTED);
+
+       return 0;
+}
+
+static int qtnf_event_parse(struct qtnf_wmac *mac,
+                           const struct sk_buff *event_skb)
+{
+       const struct qlink_event *event;
+       struct qtnf_vif *vif = NULL;
+       int ret = -1;
+       u16 event_id;
+       u16 event_len;
+
+       event = (const struct qlink_event *)event_skb->data;
+       event_id = le16_to_cpu(event->event_id);
+       event_len = le16_to_cpu(event->mhdr.len);
+
+       if (likely(event->vifid < QTNF_MAX_INTF)) {
+               vif = &mac->iflist[event->vifid];
+       } else {
+               pr_err("invalid vif(%u)\n", event->vifid);
+               return -EINVAL;
+       }
+
+       switch (event_id) {
+       case QLINK_EVENT_STA_ASSOCIATED:
+               ret = qtnf_event_handle_sta_assoc(mac, vif, (const void *)event,
+                                                 event_len);
+               break;
+       case QLINK_EVENT_STA_DEAUTH:
+               ret = qtnf_event_handle_sta_deauth(mac, vif,
+                                                  (const void *)event,
+                                                  event_len);
+               break;
+       case QLINK_EVENT_MGMT_RECEIVED:
+               ret = qtnf_event_handle_mgmt_received(vif, (const void *)event,
+                                                     event_len);
+               break;
+       case QLINK_EVENT_SCAN_RESULTS:
+               ret = qtnf_event_handle_scan_results(vif, (const void *)event,
+                                                    event_len);
+               break;
+       case QLINK_EVENT_SCAN_COMPLETE:
+               ret = qtnf_event_handle_scan_complete(mac, (const void *)event,
+                                                     event_len);
+               break;
+       case QLINK_EVENT_BSS_JOIN:
+               ret = qtnf_event_handle_bss_join(vif, (const void *)event,
+                                                event_len);
+               break;
+       case QLINK_EVENT_BSS_LEAVE:
+               ret = qtnf_event_handle_bss_leave(vif, (const void *)event,
+                                                 event_len);
+               break;
+       default:
+               pr_warn("unknown event type: %x\n", event_id);
+               break;
+       }
+
+       return ret;
+}
+
+static int qtnf_event_process_skb(struct qtnf_bus *bus,
+                                 const struct sk_buff *skb)
+{
+       const struct qlink_event *event;
+       struct qtnf_wmac *mac;
+       int res;
+
+       if (unlikely(!skb || skb->len < sizeof(*event))) {
+               pr_err("invalid event buffer\n");
+               return -EINVAL;
+       }
+
+       event = (struct qlink_event *)skb->data;
+
+       mac = qtnf_core_get_mac(bus, event->macid);
+
+       pr_debug("new event id:%x len:%u mac:%u vif:%u\n",
+                le16_to_cpu(event->event_id), le16_to_cpu(event->mhdr.len),
+                event->macid, event->vifid);
+
+       if (unlikely(!mac))
+               return -ENXIO;
+
+       qtnf_bus_lock(bus);
+       res = qtnf_event_parse(mac, skb);
+       qtnf_bus_unlock(bus);
+
+       return res;
+}
+
+void qtnf_event_work_handler(struct work_struct *work)
+{
+       struct qtnf_bus *bus = container_of(work, struct qtnf_bus, event_work);
+       struct sk_buff_head *event_queue = &bus->trans.event_queue;
+       struct sk_buff *current_event_skb = skb_dequeue(event_queue);
+
+       while (current_event_skb) {
+               qtnf_event_process_skb(bus, current_event_skb);
+               dev_kfree_skb_any(current_event_skb);
+               current_event_skb = skb_dequeue(event_queue);
+       }
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.h b/drivers/net/wireless/quantenna/qtnfmac/event.h
new file mode 100644 (file)
index 0000000..ae759b6
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 _QTN_FMAC_EVENT_H_
+#define _QTN_FMAC_EVENT_H_
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "qlink.h"
+
+void qtnf_event_work_handler(struct work_struct *work);
+
+#endif /* _QTN_FMAC_EVENT_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
new file mode 100644 (file)
index 0000000..4814d90
--- /dev/null
@@ -0,0 +1,1378 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/crc32.h>
+#include <linux/spinlock.h>
+
+#include "qtn_hw_ids.h"
+#include "pcie_bus_priv.h"
+#include "core.h"
+#include "bus.h"
+#include "debug.h"
+
+static bool use_msi = true;
+module_param(use_msi, bool, 0644);
+MODULE_PARM_DESC(use_msi, "set 0 to use legacy interrupt");
+
+static unsigned int tx_bd_size_param = 256;
+module_param(tx_bd_size_param, uint, 0644);
+MODULE_PARM_DESC(tx_bd_size_param, "Tx descriptors queue size");
+
+static unsigned int rx_bd_size_param = 256;
+module_param(rx_bd_size_param, uint, 0644);
+MODULE_PARM_DESC(rx_bd_size_param, "Rx descriptors queue size");
+
+static unsigned int rx_bd_reserved_param = 16;
+module_param(rx_bd_reserved_param, uint, 0644);
+MODULE_PARM_DESC(rx_bd_reserved_param, "Reserved RX descriptors");
+
+static u8 flashboot = 1;
+module_param(flashboot, byte, 0644);
+MODULE_PARM_DESC(flashboot, "set to 0 to use FW binary file on FS");
+
+#define DRV_NAME       "qtnfmac_pearl_pcie"
+
+static inline void qtnf_non_posted_write(u32 val, void __iomem *basereg)
+{
+       writel(val, basereg);
+
+       /* flush posted write */
+       readl(basereg);
+}
+
+static inline void qtnf_init_hdp_irqs(struct qtnf_pcie_bus_priv *priv)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->irq_lock, flags);
+       priv->pcie_irq_mask = (PCIE_HDP_INT_RX_BITS | PCIE_HDP_INT_TX_BITS);
+       spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static inline void qtnf_enable_hdp_irqs(struct qtnf_pcie_bus_priv *priv)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->irq_lock, flags);
+       writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base));
+       spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static inline void qtnf_disable_hdp_irqs(struct qtnf_pcie_bus_priv *priv)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->irq_lock, flags);
+       writel(0x0, PCIE_HDP_INT_EN(priv->pcie_reg_base));
+       spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static inline void qtnf_en_rxdone_irq(struct qtnf_pcie_bus_priv *priv)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->irq_lock, flags);
+       priv->pcie_irq_mask |= PCIE_HDP_INT_RX_BITS;
+       writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base));
+       spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static inline void qtnf_dis_rxdone_irq(struct qtnf_pcie_bus_priv *priv)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->irq_lock, flags);
+       priv->pcie_irq_mask &= ~PCIE_HDP_INT_RX_BITS;
+       writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base));
+       spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static inline void qtnf_en_txdone_irq(struct qtnf_pcie_bus_priv *priv)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->irq_lock, flags);
+       priv->pcie_irq_mask |= PCIE_HDP_INT_TX_BITS;
+       writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base));
+       spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static inline void qtnf_dis_txdone_irq(struct qtnf_pcie_bus_priv *priv)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->irq_lock, flags);
+       priv->pcie_irq_mask &= ~PCIE_HDP_INT_TX_BITS;
+       writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base));
+       spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static int qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv *priv)
+{
+       struct pci_dev *pdev = priv->pdev;
+
+       /* fall back to legacy INTx interrupts by default */
+       priv->msi_enabled = 0;
+
+       /* check if MSI capability is available */
+       if (use_msi) {
+               if (!pci_enable_msi(pdev)) {
+                       pr_debug("MSI interrupt enabled\n");
+                       priv->msi_enabled = 1;
+               } else {
+                       pr_warn("failed to enable MSI interrupts");
+               }
+       }
+
+       if (!priv->msi_enabled) {
+               pr_warn("legacy PCIE interrupts enabled\n");
+               pci_intx(pdev, 1);
+       }
+
+       return 0;
+}
+
+static void qtnf_deassert_intx(struct qtnf_pcie_bus_priv *priv)
+{
+       void __iomem *reg = priv->sysctl_bar + PEARL_PCIE_CFG0_OFFSET;
+       u32 cfg;
+
+       cfg = readl(reg);
+       cfg &= ~PEARL_ASSERT_INTX;
+       qtnf_non_posted_write(cfg, reg);
+}
+
+static void qtnf_ipc_gen_ep_int(void *arg)
+{
+       const struct qtnf_pcie_bus_priv *priv = arg;
+       const u32 data = QTN_PEARL_IPC_IRQ_WORD(QTN_PEARL_LHOST_IPC_IRQ);
+       void __iomem *reg = priv->sysctl_bar +
+                           QTN_PEARL_SYSCTL_LHOST_IRQ_OFFSET;
+
+       qtnf_non_posted_write(data, reg);
+}
+
+static void __iomem *qtnf_map_bar(struct qtnf_pcie_bus_priv *priv, u8 index)
+{
+       void __iomem *vaddr;
+       dma_addr_t busaddr;
+       size_t len;
+       int ret;
+
+       ret = pcim_iomap_regions(priv->pdev, 1 << index, DRV_NAME);
+       if (ret)
+               return IOMEM_ERR_PTR(ret);
+
+       busaddr = pci_resource_start(priv->pdev, index);
+       vaddr = pcim_iomap_table(priv->pdev)[index];
+       len = pci_resource_len(priv->pdev, index);
+
+       pr_debug("BAR%u vaddr=0x%p busaddr=%pad len=%u\n",
+                index, vaddr, &busaddr, (int)len);
+
+       return vaddr;
+}
+
+static void qtnf_pcie_control_rx_callback(void *arg, const u8 *buf, size_t len)
+{
+       struct qtnf_pcie_bus_priv *priv = arg;
+       struct qtnf_bus *bus = pci_get_drvdata(priv->pdev);
+       struct sk_buff *skb;
+
+       if (unlikely(len == 0)) {
+               pr_warn("zero length packet received\n");
+               return;
+       }
+
+       skb = __dev_alloc_skb(len, GFP_KERNEL);
+
+       if (unlikely(!skb)) {
+               pr_err("failed to allocate skb\n");
+               return;
+       }
+
+       memcpy(skb_put(skb, len), buf, len);
+
+       qtnf_trans_handle_rx_ctl_packet(bus, skb);
+}
+
+static int qtnf_pcie_init_shm_ipc(struct qtnf_pcie_bus_priv *priv)
+{
+       struct qtnf_shm_ipc_region __iomem *ipc_tx_reg;
+       struct qtnf_shm_ipc_region __iomem *ipc_rx_reg;
+       const struct qtnf_shm_ipc_int ipc_int = { qtnf_ipc_gen_ep_int, priv };
+       const struct qtnf_shm_ipc_rx_callback rx_callback = {
+                                       qtnf_pcie_control_rx_callback, priv };
+
+       ipc_tx_reg = &priv->bda->bda_shm_reg1;
+       ipc_rx_reg = &priv->bda->bda_shm_reg2;
+
+       qtnf_shm_ipc_init(&priv->shm_ipc_ep_in, QTNF_SHM_IPC_OUTBOUND,
+                         ipc_tx_reg, priv->workqueue,
+                         &ipc_int, &rx_callback);
+       qtnf_shm_ipc_init(&priv->shm_ipc_ep_out, QTNF_SHM_IPC_INBOUND,
+                         ipc_rx_reg, priv->workqueue,
+                         &ipc_int, &rx_callback);
+
+       return 0;
+}
+
+static void qtnf_pcie_free_shm_ipc(struct qtnf_pcie_bus_priv *priv)
+{
+       qtnf_shm_ipc_free(&priv->shm_ipc_ep_in);
+       qtnf_shm_ipc_free(&priv->shm_ipc_ep_out);
+}
+
+static int qtnf_pcie_init_memory(struct qtnf_pcie_bus_priv *priv)
+{
+       int ret;
+
+       priv->sysctl_bar = qtnf_map_bar(priv, QTN_SYSCTL_BAR);
+       if (IS_ERR_OR_NULL(priv->sysctl_bar)) {
+               pr_err("failed to map BAR%u\n", QTN_SYSCTL_BAR);
+               return ret;
+       }
+
+       priv->dmareg_bar = qtnf_map_bar(priv, QTN_DMA_BAR);
+       if (IS_ERR_OR_NULL(priv->dmareg_bar)) {
+               pr_err("failed to map BAR%u\n", QTN_DMA_BAR);
+               return ret;
+       }
+
+       priv->epmem_bar = qtnf_map_bar(priv, QTN_SHMEM_BAR);
+       if (IS_ERR_OR_NULL(priv->epmem_bar)) {
+               pr_err("failed to map BAR%u\n", QTN_SHMEM_BAR);
+               return ret;
+       }
+
+       priv->pcie_reg_base = priv->dmareg_bar;
+       priv->bda = priv->epmem_bar;
+       writel(priv->msi_enabled, &priv->bda->bda_rc_msi_enabled);
+
+       return 0;
+}
+
+static int
+qtnf_pcie_init_dma_mask(struct qtnf_pcie_bus_priv *priv, u64 dma_mask)
+{
+       int ret;
+
+       ret = dma_supported(&priv->pdev->dev, dma_mask);
+       if (!ret) {
+               pr_err("DMA mask %llu not supported\n", dma_mask);
+               return ret;
+       }
+
+       ret = pci_set_dma_mask(priv->pdev, dma_mask);
+       if (ret) {
+               pr_err("failed to set DMA mask %llu\n", dma_mask);
+               return ret;
+       }
+
+       ret = pci_set_consistent_dma_mask(priv->pdev, dma_mask);
+       if (ret) {
+               pr_err("failed to set consistent DMA mask %llu\n", dma_mask);
+               return ret;
+       }
+
+       return ret;
+}
+
+static void qtnf_tune_pcie_mps(struct qtnf_pcie_bus_priv *priv)
+{
+       struct pci_dev *pdev = priv->pdev;
+       struct pci_dev *parent;
+       int mps_p, mps_o, mps_m, mps;
+       int ret;
+
+       /* current mps */
+       mps_o = pcie_get_mps(pdev);
+
+       /* maximum supported mps */
+       mps_m = 128 << pdev->pcie_mpss;
+
+       /* suggested new mps value */
+       mps = mps_m;
+
+       if (pdev->bus && pdev->bus->self) {
+               /* parent (bus) mps */
+               parent = pdev->bus->self;
+
+               if (pci_is_pcie(parent)) {
+                       mps_p = pcie_get_mps(parent);
+                       mps = min(mps_m, mps_p);
+               }
+       }
+
+       ret = pcie_set_mps(pdev, mps);
+       if (ret) {
+               pr_err("failed to set mps to %d, keep using current %d\n",
+                      mps, mps_o);
+               priv->mps = mps_o;
+               return;
+       }
+
+       pr_debug("set mps to %d (was %d, max %d)\n", mps, mps_o, mps_m);
+       priv->mps = mps;
+}
+
+static int qtnf_is_state(__le32 __iomem *reg, u32 state)
+{
+       u32 s = readl(reg);
+
+       return s & state;
+}
+
+static void qtnf_set_state(__le32 __iomem *reg, u32 state)
+{
+       u32 s = readl(reg);
+
+       qtnf_non_posted_write(state | s, reg);
+}
+
+static void qtnf_clear_state(__le32 __iomem *reg, u32 state)
+{
+       u32 s = readl(reg);
+
+       qtnf_non_posted_write(s & ~state, reg);
+}
+
+static int qtnf_poll_state(__le32 __iomem *reg, u32 state, u32 delay_in_ms)
+{
+       u32 timeout = 0;
+
+       while ((qtnf_is_state(reg, state) == 0)) {
+               usleep_range(1000, 1200);
+               if (++timeout > delay_in_ms)
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int alloc_skb_array(struct qtnf_pcie_bus_priv *priv)
+{
+       struct sk_buff **vaddr;
+       int len;
+
+       len = priv->tx_bd_num * sizeof(*priv->tx_skb) +
+               priv->rx_bd_num * sizeof(*priv->rx_skb);
+       vaddr = devm_kzalloc(&priv->pdev->dev, len, GFP_KERNEL);
+
+       if (!vaddr)
+               return -ENOMEM;
+
+       priv->tx_skb = vaddr;
+
+       vaddr += priv->tx_bd_num;
+       priv->rx_skb = vaddr;
+
+       return 0;
+}
+
+static int alloc_bd_table(struct qtnf_pcie_bus_priv *priv)
+{
+       dma_addr_t paddr;
+       void *vaddr;
+       int len;
+
+       len = priv->tx_bd_num * sizeof(struct qtnf_tx_bd) +
+               priv->rx_bd_num * sizeof(struct qtnf_rx_bd);
+
+       vaddr = dmam_alloc_coherent(&priv->pdev->dev, len, &paddr, GFP_KERNEL);
+       if (!vaddr)
+               return -ENOMEM;
+
+       /* tx bd */
+
+       memset(vaddr, 0, len);
+
+       priv->bd_table_vaddr = vaddr;
+       priv->bd_table_paddr = paddr;
+       priv->bd_table_len = len;
+
+       priv->tx_bd_vbase = vaddr;
+       priv->tx_bd_pbase = paddr;
+
+       pr_debug("TX descriptor table: vaddr=0x%p paddr=%pad\n", vaddr, &paddr);
+
+       priv->tx_bd_reclaim_start = 0;
+       priv->tx_bd_index = 0;
+       priv->tx_queue_len = 0;
+
+       /* rx bd */
+
+       vaddr = ((struct qtnf_tx_bd *)vaddr) + priv->tx_bd_num;
+       paddr += priv->tx_bd_num * sizeof(struct qtnf_tx_bd);
+
+       priv->rx_bd_vbase = vaddr;
+       priv->rx_bd_pbase = paddr;
+
+       writel(QTN_HOST_LO32(paddr),
+              PCIE_HDP_TX_HOST_Q_BASE_L(priv->pcie_reg_base));
+       writel(QTN_HOST_HI32(paddr),
+              PCIE_HDP_TX_HOST_Q_BASE_H(priv->pcie_reg_base));
+       writel(priv->rx_bd_num | (sizeof(struct qtnf_rx_bd)) << 16,
+              PCIE_HDP_TX_HOST_Q_SZ_CTRL(priv->pcie_reg_base));
+
+       priv->hw_txproc_wr_ptr = priv->rx_bd_num - rx_bd_reserved_param;
+
+       writel(priv->hw_txproc_wr_ptr,
+              PCIE_HDP_TX_HOST_Q_WR_PTR(priv->pcie_reg_base));
+
+       pr_debug("RX descriptor table: vaddr=0x%p paddr=%pad\n", vaddr, &paddr);
+
+       priv->rx_bd_index = 0;
+
+       return 0;
+}
+
+static int skb2rbd_attach(struct qtnf_pcie_bus_priv *priv, u16 rx_bd_index)
+{
+       struct qtnf_rx_bd *rxbd;
+       struct sk_buff *skb;
+       dma_addr_t paddr;
+
+       skb = __dev_alloc_skb(SKB_BUF_SIZE + NET_IP_ALIGN,
+                             GFP_ATOMIC);
+       if (!skb) {
+               priv->rx_skb[rx_bd_index] = NULL;
+               return -ENOMEM;
+       }
+
+       priv->rx_skb[rx_bd_index] = skb;
+
+       skb_reserve(skb, NET_IP_ALIGN);
+
+       rxbd = &priv->rx_bd_vbase[rx_bd_index];
+
+       paddr = pci_map_single(priv->pdev, skb->data,
+                              SKB_BUF_SIZE, PCI_DMA_FROMDEVICE);
+       if (pci_dma_mapping_error(priv->pdev, paddr)) {
+               pr_err("skb DMA mapping error: %pad\n", &paddr);
+               return -ENOMEM;
+       }
+
+       writel(QTN_HOST_LO32(paddr),
+              PCIE_HDP_HHBM_BUF_PTR(priv->pcie_reg_base));
+       writel(QTN_HOST_HI32(paddr),
+              PCIE_HDP_HHBM_BUF_PTR_H(priv->pcie_reg_base));
+
+       /* keep rx skb paddrs in rx buffer descriptors for cleanup purposes */
+       rxbd->addr = cpu_to_le32(QTN_HOST_LO32(paddr));
+       rxbd->addr_h = cpu_to_le32(QTN_HOST_HI32(paddr));
+
+       rxbd->info = 0x0;
+
+       return 0;
+}
+
+static int alloc_rx_buffers(struct qtnf_pcie_bus_priv *priv)
+{
+       u16 i;
+       int ret = 0;
+
+       memset(priv->rx_bd_vbase, 0x0,
+              priv->rx_bd_num * sizeof(struct qtnf_rx_bd));
+
+       for (i = 0; i < priv->rx_bd_num; i++) {
+               ret = skb2rbd_attach(priv, i);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
+
+/* all rx/tx activity should have ceased before calling this function */
+static void free_xfer_buffers(void *data)
+{
+       struct qtnf_pcie_bus_priv *priv = (struct qtnf_pcie_bus_priv *)data;
+       struct qtnf_rx_bd *rxbd;
+       dma_addr_t paddr;
+       int i;
+
+       /* free rx buffers */
+       for (i = 0; i < priv->rx_bd_num; i++) {
+               if (priv->rx_skb[i]) {
+                       rxbd = &priv->rx_bd_vbase[i];
+                       paddr = QTN_HOST_ADDR(le32_to_cpu(rxbd->addr_h),
+                                             le32_to_cpu(rxbd->addr));
+                       pci_unmap_single(priv->pdev, paddr, SKB_BUF_SIZE,
+                                        PCI_DMA_FROMDEVICE);
+
+                       dev_kfree_skb_any(priv->rx_skb[i]);
+               }
+       }
+
+       /* free tx buffers */
+       for (i = 0; i < priv->tx_bd_num; i++) {
+               if (priv->tx_skb[i]) {
+                       dev_kfree_skb_any(priv->tx_skb[i]);
+                       priv->tx_skb[i] = NULL;
+               }
+       }
+}
+
+static int qtnf_pcie_init_xfer(struct qtnf_pcie_bus_priv *priv)
+{
+       int ret;
+
+       priv->tx_bd_num = tx_bd_size_param;
+       priv->rx_bd_num = rx_bd_size_param;
+
+       ret = alloc_skb_array(priv);
+       if (ret) {
+               pr_err("failed to allocate skb array\n");
+               return ret;
+       }
+
+       ret = alloc_bd_table(priv);
+       if (ret) {
+               pr_err("failed to allocate bd table\n");
+               return ret;
+       }
+
+       ret = alloc_rx_buffers(priv);
+       if (ret) {
+               pr_err("failed to allocate rx buffers\n");
+               return ret;
+       }
+
+       return ret;
+}
+
+static int qtnf_pcie_data_tx_reclaim(struct qtnf_pcie_bus_priv *priv)
+{
+       struct qtnf_tx_bd *txbd;
+       struct sk_buff *skb;
+       dma_addr_t paddr;
+       int last_sent;
+       int count;
+       int i;
+
+       last_sent = readl(PCIE_HDP_RX0DMA_CNT(priv->pcie_reg_base))
+                       % priv->tx_bd_num;
+       i = priv->tx_bd_reclaim_start;
+       count = 0;
+
+       while (i != last_sent) {
+               skb = priv->tx_skb[i];
+               if (!skb)
+                       break;
+
+               txbd = &priv->tx_bd_vbase[i];
+               paddr = QTN_HOST_ADDR(le32_to_cpu(txbd->addr_h),
+                                     le32_to_cpu(txbd->addr));
+               pci_unmap_single(priv->pdev, paddr, skb->len, PCI_DMA_TODEVICE);
+
+               if (skb->dev) {
+                       skb->dev->stats.tx_packets++;
+                       skb->dev->stats.tx_bytes += skb->len;
+
+                       if (netif_queue_stopped(skb->dev))
+                               netif_wake_queue(skb->dev);
+               }
+
+               dev_kfree_skb_any(skb);
+               priv->tx_skb[i] = NULL;
+               priv->tx_queue_len--;
+               count++;
+
+               if (++i >= priv->tx_bd_num)
+                       i = 0;
+       }
+
+       priv->tx_bd_reclaim_start = i;
+       priv->tx_reclaim_done += count;
+       priv->tx_reclaim_req++;
+
+       return count;
+}
+
+static bool qtnf_tx_queue_ready(struct qtnf_pcie_bus_priv *priv)
+{
+       if (priv->tx_queue_len >= priv->tx_bd_num - 1) {
+               pr_err_ratelimited("reclaim full Tx queue\n");
+               qtnf_pcie_data_tx_reclaim(priv);
+
+               if (priv->tx_queue_len >= priv->tx_bd_num - 1) {
+                       priv->tx_full_count++;
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+       struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+       dma_addr_t txbd_paddr, skb_paddr;
+       struct qtnf_tx_bd *txbd;
+       unsigned long flags;
+       int len, i;
+       u32 info;
+       int ret = 0;
+
+       spin_lock_irqsave(&priv->tx_lock, flags);
+
+       priv->tx_done_count++;
+
+       if (!qtnf_tx_queue_ready(priv)) {
+               if (skb->dev)
+                       netif_stop_queue(skb->dev);
+
+               spin_unlock_irqrestore(&priv->tx_lock, flags);
+               return NETDEV_TX_BUSY;
+       }
+
+       i = priv->tx_bd_index;
+       priv->tx_skb[i] = skb;
+       len = skb->len;
+
+       skb_paddr = pci_map_single(priv->pdev, skb->data,
+                                  skb->len, PCI_DMA_TODEVICE);
+       if (pci_dma_mapping_error(priv->pdev, skb_paddr)) {
+               pr_err("skb DMA mapping error: %pad\n", &skb_paddr);
+               ret = -ENOMEM;
+               goto tx_done;
+       }
+
+       txbd = &priv->tx_bd_vbase[i];
+       txbd->addr = cpu_to_le32(QTN_HOST_LO32(skb_paddr));
+       txbd->addr_h = cpu_to_le32(QTN_HOST_HI32(skb_paddr));
+
+       info = (len & QTN_PCIE_TX_DESC_LEN_MASK) << QTN_PCIE_TX_DESC_LEN_SHIFT;
+       txbd->info = cpu_to_le32(info);
+
+       /* sync up all descriptor updates before passing them to EP */
+       dma_wmb();
+
+       /* write new TX descriptor to PCIE_RX_FIFO on EP */
+       txbd_paddr = priv->tx_bd_pbase + i * sizeof(struct qtnf_tx_bd);
+       writel(QTN_HOST_LO32(txbd_paddr),
+              PCIE_HDP_HOST_WR_DESC0(priv->pcie_reg_base));
+       writel(QTN_HOST_HI32(txbd_paddr),
+              PCIE_HDP_HOST_WR_DESC0_H(priv->pcie_reg_base));
+
+       if (++i >= priv->tx_bd_num)
+               i = 0;
+
+       priv->tx_bd_index = i;
+       priv->tx_queue_len++;
+
+tx_done:
+       if (ret && skb) {
+               pr_err_ratelimited("drop skb\n");
+               if (skb->dev)
+                       skb->dev->stats.tx_dropped++;
+               dev_kfree_skb_any(skb);
+       }
+
+       spin_unlock_irqrestore(&priv->tx_lock, flags);
+
+       return NETDEV_TX_OK;
+}
+
+static int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+       struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+
+       return qtnf_shm_ipc_send(&priv->shm_ipc_ep_in, skb->data, skb->len);
+}
+
+static irqreturn_t qtnf_interrupt(int irq, void *data)
+{
+       struct qtnf_bus *bus = (struct qtnf_bus *)data;
+       struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+       u32 status;
+
+       priv->pcie_irq_count++;
+       status = readl(PCIE_HDP_INT_STATUS(priv->pcie_reg_base));
+
+       qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_in);
+       qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_out);
+
+       if (!(status & priv->pcie_irq_mask))
+               goto irq_done;
+
+       if (status & PCIE_HDP_INT_RX_BITS) {
+               priv->pcie_irq_rx_count++;
+               qtnf_dis_rxdone_irq(priv);
+               napi_schedule(&bus->mux_napi);
+       }
+
+       if (status & PCIE_HDP_INT_TX_BITS) {
+               priv->pcie_irq_tx_count++;
+               qtnf_dis_txdone_irq(priv);
+               tasklet_hi_schedule(&priv->reclaim_tq);
+       }
+
+irq_done:
+       /* H/W workaround: clean all bits, not only enabled */
+       qtnf_non_posted_write(~0U, PCIE_HDP_INT_STATUS(priv->pcie_reg_base));
+
+       if (!priv->msi_enabled)
+               qtnf_deassert_intx(priv);
+
+       return IRQ_HANDLED;
+}
+
+static inline void hw_txproc_wr_ptr_inc(struct qtnf_pcie_bus_priv *priv)
+{
+       u32 index;
+
+       index = priv->hw_txproc_wr_ptr;
+
+       if (++index >= priv->rx_bd_num)
+               index = 0;
+
+       priv->hw_txproc_wr_ptr = index;
+}
+
+static int qtnf_rx_poll(struct napi_struct *napi, int budget)
+{
+       struct qtnf_bus *bus = container_of(napi, struct qtnf_bus, mux_napi);
+       struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+       struct net_device *ndev = NULL;
+       struct sk_buff *skb = NULL;
+       int processed = 0;
+       struct qtnf_rx_bd *rxbd;
+       dma_addr_t skb_paddr;
+       u32 descw;
+       u16 index;
+       int ret;
+
+       index = priv->rx_bd_index;
+       rxbd = &priv->rx_bd_vbase[index];
+
+       descw = le32_to_cpu(rxbd->info);
+
+       while ((descw & QTN_TXDONE_MASK) && (processed < budget)) {
+               skb = priv->rx_skb[index];
+
+               if (likely(skb)) {
+                       skb_put(skb, QTN_GET_LEN(descw));
+
+                       skb_paddr = QTN_HOST_ADDR(le32_to_cpu(rxbd->addr_h),
+                                                 le32_to_cpu(rxbd->addr));
+                       pci_unmap_single(priv->pdev, skb_paddr, SKB_BUF_SIZE,
+                                        PCI_DMA_FROMDEVICE);
+
+                       ndev = qtnf_classify_skb(bus, skb);
+                       if (likely(ndev)) {
+                               ndev->stats.rx_packets++;
+                               ndev->stats.rx_bytes += skb->len;
+
+                               skb->protocol = eth_type_trans(skb, ndev);
+                               netif_receive_skb(skb);
+                       } else {
+                               pr_debug("drop untagged skb\n");
+                               bus->mux_dev.stats.rx_dropped++;
+                               dev_kfree_skb_any(skb);
+                       }
+
+                       processed++;
+               } else {
+                       pr_err("missing rx_skb[%d]\n", index);
+               }
+
+               /* attached rx buffer is passed upstream: map a new one */
+               ret = skb2rbd_attach(priv, index);
+               if (likely(!ret)) {
+                       if (++index >= priv->rx_bd_num)
+                               index = 0;
+
+                       priv->rx_bd_index = index;
+                       hw_txproc_wr_ptr_inc(priv);
+
+                       rxbd = &priv->rx_bd_vbase[index];
+                       descw = le32_to_cpu(rxbd->info);
+               } else {
+                       pr_err("failed to allocate new rx_skb[%d]\n", index);
+                       break;
+               }
+
+               writel(priv->hw_txproc_wr_ptr,
+                      PCIE_HDP_TX_HOST_Q_WR_PTR(priv->pcie_reg_base));
+       }
+
+       if (processed < budget) {
+               napi_complete(napi);
+               qtnf_en_rxdone_irq(priv);
+       }
+
+       return processed;
+}
+
+static void
+qtnf_pcie_data_tx_timeout(struct qtnf_bus *bus, struct net_device *ndev)
+{
+       struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+
+       tasklet_hi_schedule(&priv->reclaim_tq);
+}
+
+static void qtnf_pcie_data_rx_start(struct qtnf_bus *bus)
+{
+       struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+
+       qtnf_enable_hdp_irqs(priv);
+       napi_enable(&bus->mux_napi);
+}
+
+static void qtnf_pcie_data_rx_stop(struct qtnf_bus *bus)
+{
+       struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+
+       napi_disable(&bus->mux_napi);
+       qtnf_disable_hdp_irqs(priv);
+}
+
+static const struct qtnf_bus_ops qtnf_pcie_bus_ops = {
+       /* control path methods */
+       .control_tx     = qtnf_pcie_control_tx,
+
+       /* data path methods */
+       .data_tx                = qtnf_pcie_data_tx,
+       .data_tx_timeout        = qtnf_pcie_data_tx_timeout,
+       .data_rx_start          = qtnf_pcie_data_rx_start,
+       .data_rx_stop           = qtnf_pcie_data_rx_stop,
+};
+
+static int qtnf_ep_fw_send(struct qtnf_pcie_bus_priv *priv, uint32_t size,
+                          int blk, const u8 *pblk, const u8 *fw)
+{
+       struct pci_dev *pdev = priv->pdev;
+       struct qtnf_bus *bus = pci_get_drvdata(pdev);
+
+       struct qtnf_pcie_fw_hdr *hdr;
+       u8 *pdata;
+
+       int hds = sizeof(*hdr);
+       struct sk_buff *skb = NULL;
+       int len = 0;
+       int ret;
+
+       skb = __dev_alloc_skb(QTN_PCIE_FW_BUFSZ, GFP_KERNEL);
+       if (!skb)
+               return -ENOMEM;
+
+       skb->len = QTN_PCIE_FW_BUFSZ;
+       skb->dev = NULL;
+
+       hdr = (struct qtnf_pcie_fw_hdr *)skb->data;
+       memcpy(hdr->boardflg, QTN_PCIE_BOARDFLG, strlen(QTN_PCIE_BOARDFLG));
+       hdr->fwsize = cpu_to_le32(size);
+       hdr->seqnum = cpu_to_le32(blk);
+
+       if (blk)
+               hdr->type = cpu_to_le32(QTN_FW_DSUB);
+       else
+               hdr->type = cpu_to_le32(QTN_FW_DBEGIN);
+
+       pdata = skb->data + hds;
+
+       len = QTN_PCIE_FW_BUFSZ - hds;
+       if (pblk >= (fw + size - len)) {
+               len = fw + size - pblk;
+               hdr->type = cpu_to_le32(QTN_FW_DEND);
+       }
+
+       hdr->pktlen = cpu_to_le32(len);
+       memcpy(pdata, pblk, len);
+       hdr->crc = cpu_to_le32(~crc32(0, pdata, len));
+
+       ret = qtnf_pcie_data_tx(bus, skb);
+
+       return (ret == NETDEV_TX_OK) ? len : 0;
+}
+
+static int
+qtnf_ep_fw_load(struct qtnf_pcie_bus_priv *priv, const u8 *fw, u32 fw_size)
+{
+       int blk_size = QTN_PCIE_FW_BUFSZ - sizeof(struct qtnf_pcie_fw_hdr);
+       int blk_count = fw_size / blk_size + ((fw_size % blk_size) ? 1 : 0);
+       const u8 *pblk = fw;
+       int threshold = 0;
+       int blk = 0;
+       int len;
+
+       pr_debug("FW upload started: fw_addr=0x%p size=%d\n", fw, fw_size);
+
+       while (blk < blk_count) {
+               if (++threshold > 10000) {
+                       pr_err("FW upload failed: too many retries\n");
+                       return -ETIMEDOUT;
+               }
+
+               len = qtnf_ep_fw_send(priv, fw_size, blk, pblk, fw);
+               if (len <= 0)
+                       continue;
+
+               if (!((blk + 1) & QTN_PCIE_FW_DLMASK) ||
+                   (blk == (blk_count - 1))) {
+                       qtnf_set_state(&priv->bda->bda_rc_state,
+                                      QTN_RC_FW_SYNC);
+                       if (qtnf_poll_state(&priv->bda->bda_ep_state,
+                                           QTN_EP_FW_SYNC,
+                                           QTN_FW_DL_TIMEOUT_MS)) {
+                               pr_err("FW upload failed: SYNC timed out\n");
+                               return -ETIMEDOUT;
+                       }
+
+                       qtnf_clear_state(&priv->bda->bda_ep_state,
+                                        QTN_EP_FW_SYNC);
+
+                       if (qtnf_is_state(&priv->bda->bda_ep_state,
+                                         QTN_EP_FW_RETRY)) {
+                               if (blk == (blk_count - 1)) {
+                                       int last_round =
+                                               blk_count & QTN_PCIE_FW_DLMASK;
+                                       blk -= last_round;
+                                       pblk -= ((last_round - 1) *
+                                               blk_size + len);
+                               } else {
+                                       blk -= QTN_PCIE_FW_DLMASK;
+                                       pblk -= QTN_PCIE_FW_DLMASK * blk_size;
+                               }
+
+                               qtnf_clear_state(&priv->bda->bda_ep_state,
+                                                QTN_EP_FW_RETRY);
+
+                               pr_warn("FW upload retry: block #%d\n", blk);
+                               continue;
+                       }
+
+                       qtnf_pcie_data_tx_reclaim(priv);
+               }
+
+               pblk += len;
+               blk++;
+       }
+
+       pr_debug("FW upload completed: totally sent %d blocks\n", blk);
+       return 0;
+}
+
+static void qtnf_firmware_load(const struct firmware *fw, void *context)
+{
+       struct qtnf_pcie_bus_priv *priv = (void *)context;
+       struct pci_dev *pdev = priv->pdev;
+       struct qtnf_bus *bus = pci_get_drvdata(pdev);
+       int ret;
+
+       if (!fw) {
+               pr_err("failed to get firmware %s\n", bus->fwname);
+               goto fw_load_err;
+       }
+
+       ret = qtnf_ep_fw_load(priv, fw->data, fw->size);
+       if (ret) {
+               pr_err("FW upload error\n");
+               goto fw_load_err;
+       }
+
+       if (qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_DONE,
+                           QTN_FW_DL_TIMEOUT_MS)) {
+               pr_err("FW bringup timed out\n");
+               goto fw_load_err;
+       }
+
+       bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE;
+       pr_info("firmware is up and running\n");
+
+fw_load_err:
+
+       if (fw)
+               release_firmware(fw);
+
+       complete(&bus->request_firmware_complete);
+}
+
+static int qtnf_bringup_fw(struct qtnf_bus *bus)
+{
+       struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
+       struct pci_dev *pdev = priv->pdev;
+       int ret;
+       u32 state = QTN_RC_FW_LOADRDY | QTN_RC_FW_QLINK;
+
+       if (flashboot)
+               state |= QTN_RC_FW_FLASHBOOT;
+
+       qtnf_set_state(&priv->bda->bda_rc_state, state);
+
+       if (qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_LOADRDY,
+                           QTN_FW_DL_TIMEOUT_MS)) {
+               pr_err("card is not ready\n");
+               return -ETIMEDOUT;
+       }
+
+       qtnf_clear_state(&priv->bda->bda_ep_state, QTN_EP_FW_LOADRDY);
+
+       if (flashboot) {
+               pr_info("Booting FW from flash\n");
+
+               if (!qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_DONE,
+                                    QTN_FW_DL_TIMEOUT_MS))
+                       bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE;
+
+               return 0;
+       }
+
+       pr_info("starting firmware upload: %s\n", bus->fwname);
+
+       ret = request_firmware_nowait(THIS_MODULE, 1, bus->fwname, &pdev->dev,
+                                     GFP_KERNEL, priv, qtnf_firmware_load);
+       if (ret < 0)
+               pr_err("request_firmware_nowait error %d\n", ret);
+       else
+               ret = 1;
+
+       return ret;
+}
+
+static void qtnf_reclaim_tasklet_fn(unsigned long data)
+{
+       struct qtnf_pcie_bus_priv *priv = (void *)data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->tx_lock, flags);
+       qtnf_pcie_data_tx_reclaim(priv);
+       spin_unlock_irqrestore(&priv->tx_lock, flags);
+       qtnf_en_txdone_irq(priv);
+}
+
+static int qtnf_dbg_mps_show(struct seq_file *s, void *data)
+{
+       struct qtnf_bus *bus = dev_get_drvdata(s->private);
+       struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+       seq_printf(s, "%d\n", priv->mps);
+
+       return 0;
+}
+
+static int qtnf_dbg_msi_show(struct seq_file *s, void *data)
+{
+       struct qtnf_bus *bus = dev_get_drvdata(s->private);
+       struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+       seq_printf(s, "%u\n", priv->msi_enabled);
+
+       return 0;
+}
+
+static int qtnf_dbg_irq_stats(struct seq_file *s, void *data)
+{
+       struct qtnf_bus *bus = dev_get_drvdata(s->private);
+       struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+       seq_printf(s, "pcie_irq_count(%u)\n", priv->pcie_irq_count);
+       seq_printf(s, "pcie_irq_tx_count(%u)\n", priv->pcie_irq_tx_count);
+       seq_printf(s, "pcie_irq_rx_count(%u)\n", priv->pcie_irq_rx_count);
+
+       return 0;
+}
+
+static int qtnf_dbg_hdp_stats(struct seq_file *s, void *data)
+{
+       struct qtnf_bus *bus = dev_get_drvdata(s->private);
+       struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+       seq_printf(s, "tx_full_count(%u)\n", priv->tx_full_count);
+       seq_printf(s, "tx_done_count(%u)\n", priv->tx_done_count);
+       seq_printf(s, "tx_reclaim_done(%u)\n", priv->tx_reclaim_done);
+       seq_printf(s, "tx_reclaim_req(%u)\n", priv->tx_reclaim_req);
+       seq_printf(s, "tx_bd_reclaim_start(%u)\n", priv->tx_bd_reclaim_start);
+       seq_printf(s, "tx_bd_index(%u)\n", priv->tx_bd_index);
+       seq_printf(s, "rx_bd_index(%u)\n", priv->rx_bd_index);
+       seq_printf(s, "tx_queue_len(%u)\n", priv->tx_queue_len);
+
+       return 0;
+}
+
+static int qtnf_dbg_shm_stats(struct seq_file *s, void *data)
+{
+       struct qtnf_bus *bus = dev_get_drvdata(s->private);
+       struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+
+       seq_printf(s, "shm_ipc_ep_in.tx_packet_count(%zu)\n",
+                  priv->shm_ipc_ep_in.tx_packet_count);
+       seq_printf(s, "shm_ipc_ep_in.rx_packet_count(%zu)\n",
+                  priv->shm_ipc_ep_in.rx_packet_count);
+       seq_printf(s, "shm_ipc_ep_out.tx_packet_count(%zu)\n",
+                  priv->shm_ipc_ep_out.tx_timeout_count);
+       seq_printf(s, "shm_ipc_ep_out.rx_packet_count(%zu)\n",
+                  priv->shm_ipc_ep_out.rx_packet_count);
+
+       return 0;
+}
+
+static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct qtnf_pcie_bus_priv *pcie_priv;
+       struct qtnf_bus *bus;
+       int ret;
+
+       bus = devm_kzalloc(&pdev->dev,
+                          sizeof(*bus) + sizeof(*pcie_priv), GFP_KERNEL);
+       if (!bus) {
+               ret = -ENOMEM;
+               goto err_init;
+       }
+
+       pcie_priv = get_bus_priv(bus);
+
+       pci_set_drvdata(pdev, bus);
+       bus->bus_ops = &qtnf_pcie_bus_ops;
+       bus->dev = &pdev->dev;
+       bus->fw_state = QTNF_FW_STATE_RESET;
+       pcie_priv->pdev = pdev;
+
+       strcpy(bus->fwname, QTN_PCI_PEARL_FW_NAME);
+       init_completion(&bus->request_firmware_complete);
+       mutex_init(&bus->bus_lock);
+       spin_lock_init(&pcie_priv->irq_lock);
+       spin_lock_init(&pcie_priv->tx_lock);
+
+       /* init stats */
+       pcie_priv->tx_full_count = 0;
+       pcie_priv->tx_done_count = 0;
+       pcie_priv->pcie_irq_count = 0;
+       pcie_priv->pcie_irq_rx_count = 0;
+       pcie_priv->pcie_irq_tx_count = 0;
+       pcie_priv->tx_reclaim_done = 0;
+       pcie_priv->tx_reclaim_req = 0;
+
+       pcie_priv->workqueue = create_singlethread_workqueue("QTNF_PEARL_PCIE");
+       if (!pcie_priv->workqueue) {
+               pr_err("failed to alloc bus workqueue\n");
+               ret = -ENODEV;
+               goto err_priv;
+       }
+
+       if (!pci_is_pcie(pdev)) {
+               pr_err("device %s is not PCI Express\n", pci_name(pdev));
+               ret = -EIO;
+               goto err_base;
+       }
+
+       qtnf_tune_pcie_mps(pcie_priv);
+
+       ret = pcim_enable_device(pdev);
+       if (ret) {
+               pr_err("failed to init PCI device %x\n", pdev->device);
+               goto err_base;
+       } else {
+               pr_debug("successful init of PCI device %x\n", pdev->device);
+       }
+
+       pcim_pin_device(pdev);
+       pci_set_master(pdev);
+
+       ret = qtnf_pcie_init_irq(pcie_priv);
+       if (ret < 0) {
+               pr_err("irq init failed\n");
+               goto err_base;
+       }
+
+       ret = qtnf_pcie_init_memory(pcie_priv);
+       if (ret < 0) {
+               pr_err("PCIE memory init failed\n");
+               goto err_base;
+       }
+
+       ret = qtnf_pcie_init_shm_ipc(pcie_priv);
+       if (ret < 0) {
+               pr_err("PCIE SHM IPC init failed\n");
+               goto err_base;
+       }
+
+       ret = qtnf_pcie_init_dma_mask(pcie_priv, DMA_BIT_MASK(32));
+       if (ret) {
+               pr_err("PCIE DMA mask init failed\n");
+               goto err_base;
+       }
+
+       ret = devm_add_action(&pdev->dev, free_xfer_buffers, (void *)pcie_priv);
+       if (ret) {
+               pr_err("custom release callback init failed\n");
+               goto err_base;
+       }
+
+       ret = qtnf_pcie_init_xfer(pcie_priv);
+       if (ret) {
+               pr_err("PCIE xfer init failed\n");
+               goto err_base;
+       }
+
+       /* init default irq settings */
+       qtnf_init_hdp_irqs(pcie_priv);
+
+       /* start with disabled irqs */
+       qtnf_disable_hdp_irqs(pcie_priv);
+
+       ret = devm_request_irq(&pdev->dev, pdev->irq, &qtnf_interrupt, 0,
+                              "qtnf_pcie_irq", (void *)bus);
+       if (ret) {
+               pr_err("failed to request pcie irq %d\n", pdev->irq);
+               goto err_base;
+       }
+
+       tasklet_init(&pcie_priv->reclaim_tq, qtnf_reclaim_tasklet_fn,
+                    (unsigned long)pcie_priv);
+       init_dummy_netdev(&bus->mux_dev);
+       netif_napi_add(&bus->mux_dev, &bus->mux_napi,
+                      qtnf_rx_poll, 10);
+
+       ret = qtnf_bringup_fw(bus);
+       if (ret < 0)
+               goto err_bringup_fw;
+       else if (ret)
+               wait_for_completion(&bus->request_firmware_complete);
+
+       if (bus->fw_state != QTNF_FW_STATE_FW_DNLD_DONE) {
+               pr_err("failed to start FW\n");
+               goto err_bringup_fw;
+       }
+
+       if (qtnf_poll_state(&pcie_priv->bda->bda_ep_state, QTN_EP_FW_QLINK_DONE,
+                           QTN_FW_QLINK_TIMEOUT_MS)) {
+               pr_err("FW runtime failure\n");
+               goto err_bringup_fw;
+       }
+
+       ret = qtnf_core_attach(bus);
+       if (ret) {
+               pr_err("failed to attach core\n");
+               goto err_bringup_fw;
+       }
+
+       qtnf_debugfs_init(bus, DRV_NAME);
+       qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show);
+       qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show);
+       qtnf_debugfs_add_entry(bus, "hdp_stats", qtnf_dbg_hdp_stats);
+       qtnf_debugfs_add_entry(bus, "irq_stats", qtnf_dbg_irq_stats);
+       qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats);
+
+       return 0;
+
+err_bringup_fw:
+       netif_napi_del(&bus->mux_napi);
+
+err_base:
+       flush_workqueue(pcie_priv->workqueue);
+       destroy_workqueue(pcie_priv->workqueue);
+
+err_priv:
+       pci_set_drvdata(pdev, NULL);
+
+err_init:
+       return ret;
+}
+
+static void qtnf_pcie_remove(struct pci_dev *pdev)
+{
+       struct qtnf_pcie_bus_priv *priv;
+       struct qtnf_bus *bus;
+
+       bus = pci_get_drvdata(pdev);
+       if (!bus)
+               return;
+
+       priv = get_bus_priv(bus);
+
+       qtnf_core_detach(bus);
+       netif_napi_del(&bus->mux_napi);
+
+       flush_workqueue(priv->workqueue);
+       destroy_workqueue(priv->workqueue);
+       tasklet_kill(&priv->reclaim_tq);
+
+       qtnf_debugfs_remove(bus);
+
+       qtnf_pcie_free_shm_ipc(priv);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int qtnf_pcie_suspend(struct device *dev)
+{
+       return -EOPNOTSUPP;
+}
+
+static int qtnf_pcie_resume(struct device *dev)
+{
+       return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM_SLEEP
+/* Power Management Hooks */
+static SIMPLE_DEV_PM_OPS(qtnf_pcie_pm_ops, qtnf_pcie_suspend,
+                        qtnf_pcie_resume);
+#endif
+
+static struct pci_device_id qtnf_pcie_devid_table[] = {
+       {
+               PCIE_VENDOR_ID_QUANTENNA, PCIE_DEVICE_ID_QTN_PEARL,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+       },
+       { },
+};
+
+MODULE_DEVICE_TABLE(pci, qtnf_pcie_devid_table);
+
+static struct pci_driver qtnf_pcie_drv_data = {
+       .name = DRV_NAME,
+       .id_table = qtnf_pcie_devid_table,
+       .probe = qtnf_pcie_probe,
+       .remove = qtnf_pcie_remove,
+#ifdef CONFIG_PM_SLEEP
+       .driver = {
+               .pm = &qtnf_pcie_pm_ops,
+       },
+#endif
+};
+
+static int __init qtnf_pcie_register(void)
+{
+       pr_info("register Quantenna QSR10g FullMAC PCIE driver\n");
+       return pci_register_driver(&qtnf_pcie_drv_data);
+}
+
+static void __exit qtnf_pcie_exit(void)
+{
+       pr_info("unregister Quantenna QSR10g FullMAC PCIE driver\n");
+       pci_unregister_driver(&qtnf_pcie_drv_data);
+}
+
+module_init(qtnf_pcie_register);
+module_exit(qtnf_pcie_exit);
+
+MODULE_AUTHOR("Quantenna Communications");
+MODULE_DESCRIPTION("Quantenna QSR10g PCIe bus driver for 802.11 wireless LAN.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h
new file mode 100644 (file)
index 0000000..2a897db
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 _QTN_FMAC_PCIE_H_
+#define _QTN_FMAC_PCIE_H_
+
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+
+#include "pcie_regs_pearl.h"
+#include "pcie_ipc.h"
+#include "shm_ipc.h"
+
+struct bus;
+
+struct qtnf_pcie_bus_priv {
+       struct pci_dev  *pdev;
+
+       /* lock for irq configuration changes */
+       spinlock_t irq_lock;
+
+       /* lock for tx operations */
+       spinlock_t tx_lock;
+       u8 msi_enabled;
+       int mps;
+
+       struct workqueue_struct *workqueue;
+       struct tasklet_struct reclaim_tq;
+
+       void __iomem *sysctl_bar;
+       void __iomem *epmem_bar;
+       void __iomem *dmareg_bar;
+
+       struct qtnf_shm_ipc shm_ipc_ep_in;
+       struct qtnf_shm_ipc shm_ipc_ep_out;
+
+       struct qtnf_pcie_bda __iomem *bda;
+       void __iomem *pcie_reg_base;
+
+       u16 tx_bd_num;
+       u16 rx_bd_num;
+
+       struct sk_buff **tx_skb;
+       struct sk_buff **rx_skb;
+
+       struct qtnf_tx_bd *tx_bd_vbase;
+       dma_addr_t tx_bd_pbase;
+
+       struct qtnf_rx_bd *rx_bd_vbase;
+       dma_addr_t rx_bd_pbase;
+
+       dma_addr_t bd_table_paddr;
+       void *bd_table_vaddr;
+       u32 bd_table_len;
+
+       u32 hw_txproc_wr_ptr;
+
+       u16 tx_bd_reclaim_start;
+       u16 tx_bd_index;
+       u32 tx_queue_len;
+
+       u16 rx_bd_index;
+
+       u32 pcie_irq_mask;
+
+       /* diagnostics stats */
+       u32 pcie_irq_count;
+       u32 pcie_irq_rx_count;
+       u32 pcie_irq_tx_count;
+       u32 tx_full_count;
+       u32 tx_done_count;
+       u32 tx_reclaim_done;
+       u32 tx_reclaim_req;
+};
+
+#endif /* _QTN_FMAC_PCIE_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_ipc.h b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_ipc.h
new file mode 100644 (file)
index 0000000..e00d508
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 _QTN_FMAC_PCIE_IPC_H_
+#define _QTN_FMAC_PCIE_IPC_H_
+
+#include <linux/types.h>
+
+#include "shm_ipc_defs.h"
+
+/* bitmap for EP status and flags: updated by EP, read by RC */
+#define QTN_EP_HAS_UBOOT       BIT(0)
+#define QTN_EP_HAS_FIRMWARE    BIT(1)
+#define QTN_EP_REQ_UBOOT       BIT(2)
+#define QTN_EP_REQ_FIRMWARE    BIT(3)
+#define QTN_EP_ERROR_UBOOT     BIT(4)
+#define QTN_EP_ERROR_FIRMWARE  BIT(5)
+
+#define QTN_EP_FW_LOADRDY      BIT(8)
+#define QTN_EP_FW_SYNC         BIT(9)
+#define QTN_EP_FW_RETRY                BIT(10)
+#define QTN_EP_FW_QLINK_DONE   BIT(15)
+#define QTN_EP_FW_DONE         BIT(16)
+
+/* bitmap for RC status and flags: updated by RC, read by EP */
+#define QTN_RC_PCIE_LINK       BIT(0)
+#define QTN_RC_NET_LINK                BIT(1)
+#define QTN_RC_FW_FLASHBOOT    BIT(5)
+#define QTN_RC_FW_QLINK                BIT(7)
+#define QTN_RC_FW_LOADRDY      BIT(8)
+#define QTN_RC_FW_SYNC         BIT(9)
+
+/* state transition timeouts */
+#define QTN_FW_DL_TIMEOUT_MS   3000
+#define QTN_FW_QLINK_TIMEOUT_MS        30000
+
+#define PCIE_HDP_INT_RX_BITS (0                \
+       | PCIE_HDP_INT_EP_TXDMA         \
+       | PCIE_HDP_INT_EP_TXEMPTY       \
+       )
+
+#define PCIE_HDP_INT_TX_BITS (0                \
+       | PCIE_HDP_INT_EP_RXDMA         \
+       )
+
+#if BITS_PER_LONG == 64
+#define QTN_HOST_HI32(a)       ((u32)(((u64)a) >> 32))
+#define QTN_HOST_LO32(a)       ((u32)(((u64)a) & 0xffffffffUL))
+#define QTN_HOST_ADDR(h, l)    ((((u64)h) << 32) | ((u64)l))
+#elif BITS_PER_LONG == 32
+#define QTN_HOST_HI32(a)       0
+#define QTN_HOST_LO32(a)       ((u32)(((u32)a) & 0xffffffffUL))
+#define QTN_HOST_ADDR(h, l)    ((u32)l)
+#else
+#error Unexpected BITS_PER_LONG value
+#endif
+
+#define QTN_SYSCTL_BAR 0
+#define QTN_SHMEM_BAR  2
+#define QTN_DMA_BAR    3
+
+#define QTN_PCIE_BDA_VERSION           0x1002
+
+#define PCIE_BDA_NAMELEN               32
+#define PCIE_HHBM_MAX_SIZE             512
+
+#define SKB_BUF_SIZE           2048
+
+#define QTN_PCIE_BOARDFLG      "PCIEQTN"
+#define QTN_PCIE_FW_DLMASK     0xF
+#define QTN_PCIE_FW_BUFSZ      2048
+
+#define QTN_ENET_ADDR_LENGTH   6
+
+#define QTN_TXDONE_MASK                ((u32)0x80000000)
+#define QTN_GET_LEN(x)         ((x) & 0xFFFF)
+
+#define QTN_PCIE_TX_DESC_LEN_MASK      0xFFFF
+#define QTN_PCIE_TX_DESC_LEN_SHIFT     0
+#define QTN_PCIE_TX_DESC_PORT_MASK     0xF
+#define QTN_PCIE_TX_DESC_PORT_SHIFT    16
+#define QTN_PCIE_TX_DESC_TQE_BIT       BIT(24)
+
+#define QTN_EP_LHOST_TQE_PORT  4
+
+enum qtnf_pcie_bda_ipc_flags {
+       QTN_PCIE_IPC_FLAG_HBM_MAGIC     = BIT(0),
+       QTN_PCIE_IPC_FLAG_SHM_PIO       = BIT(1),
+};
+
+struct qtnf_pcie_bda {
+       __le16 bda_len;
+       __le16 bda_version;
+       __le32 bda_pci_endian;
+       __le32 bda_ep_state;
+       __le32 bda_rc_state;
+       __le32 bda_dma_mask;
+       __le32 bda_msi_addr;
+       __le32 bda_flashsz;
+       u8 bda_boardname[PCIE_BDA_NAMELEN];
+       __le32 bda_rc_msi_enabled;
+       __le32 bda_hhbm_list[PCIE_HHBM_MAX_SIZE];
+       __le32 bda_dsbw_start_index;
+       __le32 bda_dsbw_end_index;
+       __le32 bda_dsbw_total_bytes;
+       __le32 bda_rc_tx_bd_base;
+       __le32 bda_rc_tx_bd_num;
+       u8 bda_pcie_mac[QTN_ENET_ADDR_LENGTH];
+       struct qtnf_shm_ipc_region bda_shm_reg1 __aligned(4096); /* host TX */
+       struct qtnf_shm_ipc_region bda_shm_reg2 __aligned(4096); /* host RX */
+} __packed;
+
+struct qtnf_tx_bd {
+       __le32 addr;
+       __le32 addr_h;
+       __le32 info;
+       __le32 info_h;
+} __packed;
+
+struct qtnf_rx_bd {
+       __le32 addr;
+       __le32 addr_h;
+       __le32 info;
+       __le32 info_h;
+       __le32 next_ptr;
+       __le32 next_ptr_h;
+} __packed;
+
+enum qtnf_fw_loadtype {
+       QTN_FW_DBEGIN,
+       QTN_FW_DSUB,
+       QTN_FW_DEND,
+       QTN_FW_CTRL
+};
+
+struct qtnf_pcie_fw_hdr {
+       u8 boardflg[8];
+       __le32 fwsize;
+       __le32 seqnum;
+       __le32 type;
+       __le32 pktlen;
+       __le32 crc;
+} __packed;
+
+#endif /* _QTN_FMAC_PCIE_IPC_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_regs_pearl.h b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_regs_pearl.h
new file mode 100644 (file)
index 0000000..78715b8
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2015 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 __PEARL_PCIE_H
+#define __PEARL_PCIE_H
+
+#define        PCIE_GEN2_BASE                          (0xe9000000)
+#define        PCIE_GEN3_BASE                          (0xe7000000)
+
+#define PEARL_CUR_PCIE_BASE                    (PCIE_GEN2_BASE)
+#define PCIE_HDP_OFFSET                                (0x2000)
+
+#define PCIE_HDP_CTRL(base)                    ((base) + 0x2c00)
+#define PCIE_HDP_AXI_CTRL(base)                        ((base) + 0x2c04)
+#define PCIE_HDP_HOST_WR_DESC0(base)           ((base) + 0x2c10)
+#define PCIE_HDP_HOST_WR_DESC0_H(base)         ((base) + 0x2c14)
+#define PCIE_HDP_HOST_WR_DESC1(base)           ((base) + 0x2c18)
+#define PCIE_HDP_HOST_WR_DESC1_H(base)         ((base) + 0x2c1c)
+#define PCIE_HDP_HOST_WR_DESC2(base)           ((base) + 0x2c20)
+#define PCIE_HDP_HOST_WR_DESC2_H(base)         ((base) + 0x2c24)
+#define PCIE_HDP_HOST_WR_DESC3(base)           ((base) + 0x2c28)
+#define PCIE_HDP_HOST_WR_DESC4_H(base)         ((base) + 0x2c2c)
+#define PCIE_HDP_RX_INT_CTRL(base)             ((base) + 0x2c30)
+#define PCIE_HDP_TX_INT_CTRL(base)             ((base) + 0x2c34)
+#define PCIE_HDP_INT_STATUS(base)              ((base) + 0x2c38)
+#define PCIE_HDP_INT_EN(base)                  ((base) + 0x2c3c)
+#define PCIE_HDP_RX_DESC0_PTR(base)            ((base) + 0x2c40)
+#define PCIE_HDP_RX_DESC0_NOE(base)            ((base) + 0x2c44)
+#define PCIE_HDP_RX_DESC1_PTR(base)            ((base) + 0x2c48)
+#define PCIE_HDP_RX_DESC1_NOE(base)            ((base) + 0x2c4c)
+#define PCIE_HDP_RX_DESC2_PTR(base)            ((base) + 0x2c50)
+#define PCIE_HDP_RX_DESC2_NOE(base)            ((base) + 0x2c54)
+#define PCIE_HDP_RX_DESC3_PTR(base)            ((base) + 0x2c58)
+#define PCIE_HDP_RX_DESC3_NOE(base)            ((base) + 0x2c5c)
+
+#define PCIE_HDP_TX0_BASE_ADDR(base)           ((base) + 0x2c60)
+#define PCIE_HDP_TX1_BASE_ADDR(base)           ((base) + 0x2c64)
+#define PCIE_HDP_TX0_Q_CTRL(base)              ((base) + 0x2c70)
+#define PCIE_HDP_TX1_Q_CTRL(base)              ((base) + 0x2c74)
+#define PCIE_HDP_CFG0(base)                    ((base) + 0x2c80)
+#define PCIE_HDP_CFG1(base)                    ((base) + 0x2c84)
+#define PCIE_HDP_CFG2(base)                    ((base) + 0x2c88)
+#define PCIE_HDP_CFG3(base)                    ((base) + 0x2c8c)
+#define PCIE_HDP_CFG4(base)                    ((base) + 0x2c90)
+#define PCIE_HDP_CFG5(base)                    ((base) + 0x2c94)
+#define PCIE_HDP_CFG6(base)                    ((base) + 0x2c98)
+#define PCIE_HDP_CFG7(base)                    ((base) + 0x2c9c)
+#define PCIE_HDP_CFG8(base)                    ((base) + 0x2ca0)
+#define PCIE_HDP_CFG9(base)                    ((base) + 0x2ca4)
+#define PCIE_HDP_CFG10(base)                   ((base) + 0x2ca8)
+#define PCIE_HDP_CFG11(base)                   ((base) + 0x2cac)
+#define PCIE_INT(base)                         ((base) + 0x2cb0)
+#define PCIE_INT_MASK(base)                    ((base) + 0x2cb4)
+#define PCIE_MSI_MASK(base)                    ((base) + 0x2cb8)
+#define PCIE_MSI_PNDG(base)                    ((base) + 0x2cbc)
+#define PCIE_PRI_CFG(base)                     ((base) + 0x2cc0)
+#define PCIE_PHY_CR(base)                      ((base) + 0x2cc4)
+#define PCIE_HDP_CTAG_CTRL(base)               ((base) + 0x2cf4)
+#define PCIE_HDP_HHBM_BUF_PTR(base)            ((base) + 0x2d00)
+#define PCIE_HDP_HHBM_BUF_PTR_H(base)          ((base) + 0x2d04)
+#define PCIE_HDP_HHBM_BUF_FIFO_NOE(base)       ((base) + 0x2d04)
+#define PCIE_HDP_RX0DMA_CNT(base)              ((base) + 0x2d10)
+#define PCIE_HDP_RX1DMA_CNT(base)              ((base) + 0x2d14)
+#define PCIE_HDP_RX2DMA_CNT(base)              ((base) + 0x2d18)
+#define PCIE_HDP_RX3DMA_CNT(base)              ((base) + 0x2d1c)
+#define PCIE_HDP_TX0DMA_CNT(base)              ((base) + 0x2d20)
+#define PCIE_HDP_TX1DMA_CNT(base)              ((base) + 0x2d24)
+#define PCIE_HDP_RXDMA_CTRL(base)              ((base) + 0x2d28)
+#define PCIE_HDP_TX_HOST_Q_SZ_CTRL(base)       ((base) + 0x2d2c)
+#define PCIE_HDP_TX_HOST_Q_BASE_L(base)                ((base) + 0x2d30)
+#define PCIE_HDP_TX_HOST_Q_BASE_H(base)                ((base) + 0x2d34)
+#define PCIE_HDP_TX_HOST_Q_WR_PTR(base)                ((base) + 0x2d38)
+#define PCIE_HDP_TX_HOST_Q_RD_PTR(base)                ((base) + 0x2d3c)
+#define PCIE_HDP_TX_HOST_Q_STS(base)           ((base) + 0x2d40)
+
+/* Host HBM pool registers */
+#define PCIE_HHBM_CSR_REG(base)                        ((base) + 0x2e00)
+#define PCIE_HHBM_Q_BASE_REG(base)             ((base) + 0x2e04)
+#define PCIE_HHBM_Q_LIMIT_REG(base)            ((base) + 0x2e08)
+#define PCIE_HHBM_Q_WR_REG(base)               ((base) + 0x2e0c)
+#define PCIE_HHBM_Q_RD_REG(base)               ((base) + 0x2e10)
+#define PCIE_HHBM_POOL_DATA_0_H(base)          ((base) + 0x2e90)
+#define PCIE_HHBM_CONFIG(base)                 ((base) + 0x2f9c)
+#define PCIE_HHBM_POOL_REQ_0(base)             ((base) + 0x2f10)
+#define PCIE_HHBM_POOL_DATA_0(base)            ((base) + 0x2f40)
+#define PCIE_HHBM_WATERMARK_MASKED_INT(base)   ((base) + 0x2f68)
+#define PCIE_HHBM_WATERMARK_INT(base)          ((base) + 0x2f6c)
+#define PCIE_HHBM_POOL_WATERMARK(base)         ((base) + 0x2f70)
+#define PCIE_HHBM_POOL_OVERFLOW_CNT(base)      ((base) + 0x2f90)
+#define PCIE_HHBM_POOL_UNDERFLOW_CNT(base)     ((base) + 0x2f94)
+#define HBM_INT_STATUS(base)                   ((base) + 0x2f9c)
+#define PCIE_HHBM_POOL_CNFIG(base)             ((base) + 0x2f9c)
+
+/* host HBM bit field definition */
+#define HHBM_CONFIG_SOFT_RESET                 (BIT(8))
+#define HHBM_WR_REQ                            (BIT(0))
+#define HHBM_RD_REQ                            (BIT(1))
+#define HHBM_DONE                              (BIT(31))
+
+/* offsets for dual PCIE */
+#define PCIE_PORT_LINK_CTL(base)               ((base) + 0x0710)
+#define PCIE_GEN2_CTL(base)                    ((base) + 0x080C)
+#define PCIE_GEN3_OFF(base)                    ((base) + 0x0890)
+#define PCIE_ATU_CTRL1(base)                   ((base) + 0x0904)
+#define PCIE_ATU_CTRL2(base)                   ((base) + 0x0908)
+#define PCIE_ATU_BASE_LOW(base)                        ((base) + 0x090C)
+#define PCIE_ATU_BASE_HIGH(base)               ((base) + 0x0910)
+#define PCIE_ATU_BASE_LIMIT(base)              ((base) + 0x0914)
+#define PCIE_ATU_TGT_LOW(base)                 ((base) + 0x0918)
+#define PCIE_ATU_TGT_HIGH(base)                        ((base) + 0x091C)
+#define PCIE_DMA_WR_ENABLE(base)               ((base) + 0x097C)
+#define PCIE_DMA_WR_CHWTLOW(base)              ((base) + 0x0988)
+#define PCIE_DMA_WR_CHWTHIG(base)              ((base) + 0x098C)
+#define PCIE_DMA_WR_INTSTS(base)               ((base) + 0x09BC)
+#define PCIE_DMA_WR_INTMASK(base)              ((base) + 0x09C4)
+#define PCIE_DMA_WR_INTCLER(base)              ((base) + 0x09C8)
+#define PCIE_DMA_WR_DONE_IMWR_ADDR_L(base)     ((base) + 0x09D0)
+#define PCIE_DMA_WR_DONE_IMWR_ADDR_H(base)     ((base) + 0x09D4)
+#define PCIE_DMA_WR_ABORT_IMWR_ADDR_L(base)    ((base) + 0x09D8)
+#define PCIE_DMA_WR_ABORT_IMWR_ADDR_H(base)    ((base) + 0x09DC)
+#define PCIE_DMA_WR_IMWR_DATA(base)            ((base) + 0x09E0)
+#define PCIE_DMA_WR_LL_ERR_EN(base)            ((base) + 0x0A00)
+#define PCIE_DMA_WR_DOORBELL(base)             ((base) + 0x0980)
+#define PCIE_DMA_RD_ENABLE(base)               ((base) + 0x099C)
+#define PCIE_DMA_RD_DOORBELL(base)             ((base) + 0x09A0)
+#define PCIE_DMA_RD_CHWTLOW(base)              ((base) + 0x09A8)
+#define PCIE_DMA_RD_CHWTHIG(base)              ((base) + 0x09AC)
+#define PCIE_DMA_RD_INTSTS(base)               ((base) + 0x0A10)
+#define PCIE_DMA_RD_INTMASK(base)              ((base) + 0x0A18)
+#define PCIE_DMA_RD_INTCLER(base)              ((base) + 0x0A1C)
+#define PCIE_DMA_RD_ERR_STS_L(base)            ((base) + 0x0A24)
+#define PCIE_DMA_RD_ERR_STS_H(base)            ((base) + 0x0A28)
+#define PCIE_DMA_RD_LL_ERR_EN(base)            ((base) + 0x0A34)
+#define PCIE_DMA_RD_DONE_IMWR_ADDR_L(base)     ((base) + 0x0A3C)
+#define PCIE_DMA_RD_DONE_IMWR_ADDR_H(base)     ((base) + 0x0A40)
+#define PCIE_DMA_RD_ABORT_IMWR_ADDR_L(base)    ((base) + 0x0A44)
+#define PCIE_DMA_RD_ABORT_IMWR_ADDR_H(base)    ((base) + 0x0A48)
+#define PCIE_DMA_RD_IMWR_DATA(base)            ((base) + 0x0A4C)
+#define PCIE_DMA_CHNL_CONTEXT(base)            ((base) + 0x0A6C)
+#define PCIE_DMA_CHNL_CNTRL(base)              ((base) + 0x0A70)
+#define PCIE_DMA_XFR_SIZE(base)                        ((base) + 0x0A78)
+#define PCIE_DMA_SAR_LOW(base)                 ((base) + 0x0A7C)
+#define PCIE_DMA_SAR_HIGH(base)                        ((base) + 0x0A80)
+#define PCIE_DMA_DAR_LOW(base)                 ((base) + 0x0A84)
+#define PCIE_DMA_DAR_HIGH(base)                        ((base) + 0x0A88)
+#define PCIE_DMA_LLPTR_LOW(base)               ((base) + 0x0A8C)
+#define PCIE_DMA_LLPTR_HIGH(base)              ((base) + 0x0A90)
+#define PCIE_DMA_WRLL_ERR_ENB(base)            ((base) + 0x0A00)
+#define PCIE_DMA_RDLL_ERR_ENB(base)            ((base) + 0x0A34)
+#define PCIE_DMABD_CHNL_CNTRL(base)            ((base) + 0x8000)
+#define PCIE_DMABD_XFR_SIZE(base)              ((base) + 0x8004)
+#define PCIE_DMABD_SAR_LOW(base)               ((base) + 0x8008)
+#define PCIE_DMABD_SAR_HIGH(base)              ((base) + 0x800c)
+#define PCIE_DMABD_DAR_LOW(base)               ((base) + 0x8010)
+#define PCIE_DMABD_DAR_HIGH(base)              ((base) + 0x8014)
+#define PCIE_DMABD_LLPTR_LOW(base)             ((base) + 0x8018)
+#define PCIE_DMABD_LLPTR_HIGH(base)            ((base) + 0x801c)
+#define PCIE_WRDMA0_CHNL_CNTRL(base)           ((base) + 0x8000)
+#define PCIE_WRDMA0_XFR_SIZE(base)             ((base) + 0x8004)
+#define PCIE_WRDMA0_SAR_LOW(base)              ((base) + 0x8008)
+#define PCIE_WRDMA0_SAR_HIGH(base)             ((base) + 0x800c)
+#define PCIE_WRDMA0_DAR_LOW(base)              ((base) + 0x8010)
+#define PCIE_WRDMA0_DAR_HIGH(base)             ((base) + 0x8014)
+#define PCIE_WRDMA0_LLPTR_LOW(base)            ((base) + 0x8018)
+#define PCIE_WRDMA0_LLPTR_HIGH(base)           ((base) + 0x801c)
+#define PCIE_WRDMA1_CHNL_CNTRL(base)           ((base) + 0x8020)
+#define PCIE_WRDMA1_XFR_SIZE(base)             ((base) + 0x8024)
+#define PCIE_WRDMA1_SAR_LOW(base)              ((base) + 0x8028)
+#define PCIE_WRDMA1_SAR_HIGH(base)             ((base) + 0x802c)
+#define PCIE_WRDMA1_DAR_LOW(base)              ((base) + 0x8030)
+#define PCIE_WRDMA1_DAR_HIGH(base)             ((base) + 0x8034)
+#define PCIE_WRDMA1_LLPTR_LOW(base)            ((base) + 0x8038)
+#define PCIE_WRDMA1_LLPTR_HIGH(base)           ((base) + 0x803c)
+#define PCIE_RDDMA0_CHNL_CNTRL(base)           ((base) + 0x8040)
+#define PCIE_RDDMA0_XFR_SIZE(base)             ((base) + 0x8044)
+#define PCIE_RDDMA0_SAR_LOW(base)              ((base) + 0x8048)
+#define PCIE_RDDMA0_SAR_HIGH(base)             ((base) + 0x804c)
+#define PCIE_RDDMA0_DAR_LOW(base)              ((base) + 0x8050)
+#define PCIE_RDDMA0_DAR_HIGH(base)             ((base) + 0x8054)
+#define PCIE_RDDMA0_LLPTR_LOW(base)            ((base) + 0x8058)
+#define PCIE_RDDMA0_LLPTR_HIGH(base)           ((base) + 0x805c)
+#define PCIE_RDDMA1_CHNL_CNTRL(base)           ((base) + 0x8060)
+#define PCIE_RDDMA1_XFR_SIZE(base)             ((base) + 0x8064)
+#define PCIE_RDDMA1_SAR_LOW(base)              ((base) + 0x8068)
+#define PCIE_RDDMA1_SAR_HIGH(base)             ((base) + 0x806c)
+#define PCIE_RDDMA1_DAR_LOW(base)              ((base) + 0x8070)
+#define PCIE_RDDMA1_DAR_HIGH(base)             ((base) + 0x8074)
+#define PCIE_RDDMA1_LLPTR_LOW(base)            ((base) + 0x8078)
+#define PCIE_RDDMA1_LLPTR_HIGH(base)           ((base) + 0x807c)
+
+#define PCIE_ID(base)                          ((base) + 0x0000)
+#define PCIE_CMD(base)                         ((base) + 0x0004)
+#define PCIE_BAR(base, n)                      ((base) + 0x0010 + ((n) << 2))
+#define PCIE_CAP_PTR(base)                     ((base) + 0x0034)
+#define PCIE_MSI_LBAR(base)                    ((base) + 0x0054)
+#define PCIE_MSI_CTRL(base)                    ((base) + 0x0050)
+#define PCIE_MSI_ADDR_L(base)                  ((base) + 0x0054)
+#define PCIE_MSI_ADDR_H(base)                  ((base) + 0x0058)
+#define PCIE_MSI_DATA(base)                    ((base) + 0x005C)
+#define PCIE_MSI_MASK_BIT(base)                        ((base) + 0x0060)
+#define PCIE_MSI_PEND_BIT(base)                        ((base) + 0x0064)
+#define PCIE_DEVCAP(base)                      ((base) + 0x0074)
+#define PCIE_DEVCTLSTS(base)                   ((base) + 0x0078)
+
+#define PCIE_CMDSTS(base)                      ((base) + 0x0004)
+#define PCIE_LINK_STAT(base)                   ((base) + 0x80)
+#define PCIE_LINK_CTL2(base)                   ((base) + 0xa0)
+#define PCIE_ASPM_L1_CTRL(base)                        ((base) + 0x70c)
+#define PCIE_ASPM_LINK_CTRL(base)              (PCIE_LINK_STAT)
+#define PCIE_ASPM_L1_SUBSTATE_TIMING(base)     ((base) + 0xB44)
+#define PCIE_L1SUB_CTRL1(base)                 ((base) + 0x150)
+#define PCIE_PMCSR(base)                       ((base) + 0x44)
+#define PCIE_CFG_SPACE_LIMIT(base)             ((base) + 0x100)
+
+/* PCIe link defines */
+#define PEARL_PCIE_LINKUP                      (0x7)
+#define PEARL_PCIE_DATA_LINK                   (BIT(0))
+#define PEARL_PCIE_PHY_LINK                    (BIT(1))
+#define PEARL_PCIE_LINK_RST                    (BIT(3))
+#define PEARL_PCIE_FATAL_ERR                   (BIT(5))
+#define PEARL_PCIE_NONFATAL_ERR                        (BIT(6))
+
+/* PCIe Lane defines */
+#define PCIE_G2_LANE_X1                                ((BIT(0)) << 16)
+#define PCIE_G2_LANE_X2                                ((BIT(0) | BIT(1)) << 16)
+
+/* PCIe DLL link enable */
+#define PCIE_DLL_LINK_EN                       ((BIT(0)) << 5)
+
+#define PCIE_LINK_GEN1                         (BIT(0))
+#define PCIE_LINK_GEN2                         (BIT(1))
+#define PCIE_LINK_GEN3                         (BIT(2))
+#define PCIE_LINK_MODE(x)                      (((x) >> 16) & 0x7)
+
+#define MSI_EN                                 (BIT(0))
+#define MSI_64_EN                              (BIT(7))
+#define PCIE_MSI_ADDR_OFFSET(a)                        ((a) & 0xFFFF)
+#define PCIE_MSI_ADDR_ALIGN(a)                 ((a) & (~0xFFFF))
+
+#define PCIE_BAR_MASK(base, n)                 ((base) + 0x1010 + ((n) << 2))
+#define PCIE_MAX_BAR                           (6)
+
+#define PCIE_ATU_VIEW(base)                    ((base) + 0x0900)
+#define PCIE_ATU_CTL1(base)                    ((base) + 0x0904)
+#define PCIE_ATU_CTL2(base)                    ((base) + 0x0908)
+#define PCIE_ATU_LBAR(base)                    ((base) + 0x090c)
+#define PCIE_ATU_UBAR(base)                    ((base) + 0x0910)
+#define PCIE_ATU_LAR(base)                     ((base) + 0x0914)
+#define PCIE_ATU_LTAR(base)                    ((base) + 0x0918)
+#define PCIE_ATU_UTAR(base)                    ((base) + 0x091c)
+
+#define PCIE_MSI_ADDR_LOWER(base)              ((base) + 0x0820)
+#define PCIE_MSI_ADDR_UPPER(base)              ((base) + 0x0824)
+#define PCIE_MSI_ENABLE(base)                  ((base) + 0x0828)
+#define PCIE_MSI_MASK_RC(base)                 ((base) + 0x082c)
+#define PCIE_MSI_STATUS(base)                  ((base) + 0x0830)
+#define PEARL_PCIE_MSI_REGION                  (0xce000000)
+#define PEARL_PCIE_MSI_DATA                    (0)
+#define PCIE_MSI_GPIO(base)                    ((base) + 0x0888)
+
+#define PCIE_HDP_HOST_QUEUE_FULL       (BIT(17))
+#define USE_BAR_MATCH_MODE
+#define PCIE_ATU_OB_REGION             (BIT(0))
+#define PCIE_ATU_EN_REGION             (BIT(31))
+#define PCIE_ATU_EN_MATCH              (BIT(30))
+#define PCIE_BASE_REGION               (0xb0000000)
+#define PCIE_MEM_MAP_SIZE              (512 * 1024)
+
+#define PCIE_OB_REG_REGION             (0xcf000000)
+#define PCIE_CONFIG_REGION             (0xcf000000)
+#define PCIE_CONFIG_SIZE               (4096)
+#define PCIE_CONFIG_CH                 (1)
+
+/* inbound mapping */
+#define PCIE_IB_BAR0                   (0x00000000)    /* ddr */
+#define PCIE_IB_BAR0_CH                        (0)
+#define PCIE_IB_BAR3                   (0xe0000000)    /* sys_reg */
+#define PCIE_IB_BAR3_CH                        (1)
+
+/* outbound mapping */
+#define PCIE_MEM_CH                    (0)
+#define PCIE_REG_CH                    (1)
+#define PCIE_MEM_REGION                        (0xc0000000)
+#define        PCIE_MEM_SIZE                   (0x000fffff)
+#define PCIE_MEM_TAR                   (0x80000000)
+
+#define PCIE_MSI_REGION                        (0xce000000)
+#define PCIE_MSI_SIZE                  (KBYTE(4) - 1)
+#define PCIE_MSI_CH                    (1)
+
+/* size of config region */
+#define PCIE_CFG_SIZE                  (0x0000ffff)
+
+#define PCIE_ATU_DIR_IB                        (BIT(31))
+#define PCIE_ATU_DIR_OB                        (0)
+#define PCIE_ATU_DIR_CFG               (2)
+#define PCIE_ATU_DIR_MATCH_IB          (BIT(31) | BIT(30))
+
+#define PCIE_DMA_WR_0                  (0)
+#define PCIE_DMA_WR_1                  (1)
+#define PCIE_DMA_RD_0                  (2)
+#define PCIE_DMA_RD_1                  (3)
+
+#define PCIE_DMA_CHNL_CNTRL_CB         (BIT(0))
+#define PCIE_DMA_CHNL_CNTRL_TCB                (BIT(1))
+#define PCIE_DMA_CHNL_CNTRL_LLP                (BIT(2))
+#define PCIE_DMA_CHNL_CNTRL_LIE                (BIT(3))
+#define PCIE_DMA_CHNL_CNTRL_RIE                (BIT(4))
+#define PCIE_DMA_CHNL_CNTRL_CSS                (BIT(8))
+#define PCIE_DMA_CHNL_CNTRL_LLE                (BIT(9))
+#define PCIE_DMA_CHNL_CNTRL_TLP                (BIT(26))
+
+#define PCIE_DMA_CHNL_CONTEXT_RD       (BIT(31))
+#define PCIE_DMA_CHNL_CONTEXT_WR       (0)
+#define PCIE_MAX_BAR                   (6)
+
+/* PCIe HDP interrupt status definition */
+#define PCIE_HDP_INT_EP_RXDMA          (BIT(0))
+#define PCIE_HDP_INT_HBM_UF            (BIT(1))
+#define PCIE_HDP_INT_RX_LEN_ERR                (BIT(2))
+#define PCIE_HDP_INT_RX_HDR_LEN_ERR    (BIT(3))
+#define PCIE_HDP_INT_EP_TXDMA          (BIT(12))
+#define PCIE_HDP_INT_EP_TXEMPTY                (BIT(15))
+#define PCIE_HDP_INT_IPC               (BIT(29))
+
+/* PCIe interrupt status definition */
+#define PCIE_INT_MSI                   (BIT(24))
+#define PCIE_INT_INTX                  (BIT(23))
+
+/* PCIe legacy INTx */
+#define PEARL_PCIE_CFG0_OFFSET         (0x6C)
+#define PEARL_ASSERT_INTX              (BIT(9))
+
+/* SYS CTL regs */
+#define QTN_PEARL_SYSCTL_LHOST_IRQ_OFFSET      (0x001C)
+
+#define QTN_PEARL_IPC_IRQ_WORD(irq)    (BIT(irq) | BIT(irq + 16))
+#define QTN_PEARL_LHOST_IPC_IRQ                (6)
+
+#endif /* __PEARL_PCIE_H */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
new file mode 100644 (file)
index 0000000..6eafc15
--- /dev/null
@@ -0,0 +1,901 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 _QTN_QLINK_H_
+#define _QTN_QLINK_H_
+
+#include <linux/ieee80211.h>
+
+#define QLINK_PROTO_VER                3
+
+#define QLINK_MACID_RSVD               0xFF
+#define QLINK_VIFID_RSVD               0xFF
+
+/* Common QLINK protocol messages definitions.
+ */
+
+/**
+ * enum qlink_msg_type - QLINK message types
+ *
+ * Used to distinguish between message types of QLINK protocol.
+ *
+ * @QLINK_MSG_TYPE_CMD: Message is carrying data of a command sent from
+ *     driver to wireless hardware.
+ * @QLINK_MSG_TYPE_CMDRSP: Message is carrying data of a response to a command.
+ *     Sent from wireless HW to driver in reply to previously issued command.
+ * @QLINK_MSG_TYPE_EVENT: Data for an event originated in wireless hardware and
+ *     sent asynchronously to driver.
+ */
+enum qlink_msg_type {
+       QLINK_MSG_TYPE_CMD      = 1,
+       QLINK_MSG_TYPE_CMDRSP   = 2,
+       QLINK_MSG_TYPE_EVENT    = 3
+};
+
+/**
+ * struct qlink_msg_header - common QLINK protocol message header
+ *
+ * Portion of QLINK protocol header common for all message types.
+ *
+ * @type: Message type, one of &enum qlink_msg_type.
+ * @len: Total length of message including all headers.
+ */
+struct qlink_msg_header {
+       __le16 type;
+       __le16 len;
+} __packed;
+
+/* Generic definitions of data and information carried in QLINK messages
+ */
+
+enum qlink_hw_capab {
+       QLINK_HW_SUPPORTS_REG_UPDATE    = BIT(0),
+};
+
+enum qlink_phy_mode {
+       QLINK_PHYMODE_BGN       = BIT(0),
+       QLINK_PHYMODE_AN        = BIT(1),
+       QLINK_PHYMODE_AC        = BIT(2),
+};
+
+enum qlink_iface_type {
+       QLINK_IFTYPE_AP         = 1,
+       QLINK_IFTYPE_STATION    = 2,
+       QLINK_IFTYPE_ADHOC      = 3,
+       QLINK_IFTYPE_MONITOR    = 4,
+       QLINK_IFTYPE_WDS        = 5,
+};
+
+/**
+ * struct qlink_intf_info - information on virtual interface.
+ *
+ * Data describing a single virtual interface.
+ *
+ * @if_type: Mode of interface operation, one of &enum qlink_iface_type
+ * @flags: interface flagsmap.
+ * @mac_addr: MAC address of virtual interface.
+ */
+struct qlink_intf_info {
+       __le16 if_type;
+       __le16 flags;
+       u8 mac_addr[ETH_ALEN];
+       u8 rsvd[2];
+} __packed;
+
+enum qlink_sta_flags {
+       QLINK_STA_FLAG_INVALID          = 0,
+       QLINK_STA_FLAG_AUTHORIZED               = BIT(0),
+       QLINK_STA_FLAG_SHORT_PREAMBLE   = BIT(1),
+       QLINK_STA_FLAG_WME                      = BIT(2),
+       QLINK_STA_FLAG_MFP                      = BIT(3),
+       QLINK_STA_FLAG_AUTHENTICATED            = BIT(4),
+       QLINK_STA_FLAG_TDLS_PEER                = BIT(5),
+       QLINK_STA_FLAG_ASSOCIATED               = BIT(6),
+};
+
+enum qlink_channel_width {
+       QLINK_CHAN_WIDTH_5              = BIT(0),
+       QLINK_CHAN_WIDTH_10             = BIT(1),
+       QLINK_CHAN_WIDTH_20_NOHT        = BIT(2),
+       QLINK_CHAN_WIDTH_20             = BIT(3),
+       QLINK_CHAN_WIDTH_40             = BIT(4),
+       QLINK_CHAN_WIDTH_80             = BIT(5),
+       QLINK_CHAN_WIDTH_80P80          = BIT(6),
+       QLINK_CHAN_WIDTH_160            = BIT(7),
+};
+
+/* QLINK Command messages related definitions
+ */
+
+/**
+ * enum qlink_cmd_type - list of supported commands
+ *
+ * Commands are QLINK messages of type @QLINK_MSG_TYPE_CMD, sent by driver to
+ * wireless network device for processing. Device is expected to send back a
+ * reply message of type &QLINK_MSG_TYPE_CMDRSP, containing at least command
+ * execution status (one of &enum qlink_cmd_result) at least. Reply message
+ * may also contain data payload specific to the command type.
+ *
+ * @QLINK_CMD_CHANS_INFO_GET: for the specified MAC and specified band, get
+ *     number of operational channels and information on each of the channel.
+ *     This command is generic to a specified MAC, interface index must be set
+ *     to QLINK_VIFID_RSVD in command header.
+ */
+enum qlink_cmd_type {
+       QLINK_CMD_FW_INIT               = 0x0001,
+       QLINK_CMD_FW_DEINIT             = 0x0002,
+       QLINK_CMD_REGISTER_MGMT         = 0x0003,
+       QLINK_CMD_SEND_MGMT_FRAME       = 0x0004,
+       QLINK_CMD_MGMT_SET_APPIE        = 0x0005,
+       QLINK_CMD_PHY_PARAMS_GET        = 0x0011,
+       QLINK_CMD_PHY_PARAMS_SET        = 0x0012,
+       QLINK_CMD_GET_HW_INFO           = 0x0013,
+       QLINK_CMD_MAC_INFO              = 0x0014,
+       QLINK_CMD_ADD_INTF              = 0x0015,
+       QLINK_CMD_DEL_INTF              = 0x0016,
+       QLINK_CMD_CHANGE_INTF           = 0x0017,
+       QLINK_CMD_UPDOWN_INTF           = 0x0018,
+       QLINK_CMD_REG_REGION            = 0x0019,
+       QLINK_CMD_CHANS_INFO_GET        = 0x001A,
+       QLINK_CMD_CONFIG_AP             = 0x0020,
+       QLINK_CMD_START_AP              = 0x0021,
+       QLINK_CMD_STOP_AP               = 0x0022,
+       QLINK_CMD_GET_STA_INFO          = 0x0030,
+       QLINK_CMD_ADD_KEY               = 0x0040,
+       QLINK_CMD_DEL_KEY               = 0x0041,
+       QLINK_CMD_SET_DEFAULT_KEY       = 0x0042,
+       QLINK_CMD_SET_DEFAULT_MGMT_KEY  = 0x0043,
+       QLINK_CMD_CHANGE_STA            = 0x0051,
+       QLINK_CMD_DEL_STA               = 0x0052,
+       QLINK_CMD_SCAN                  = 0x0053,
+       QLINK_CMD_CONNECT               = 0x0060,
+       QLINK_CMD_DISCONNECT            = 0x0061,
+};
+
+/**
+ * struct qlink_cmd - QLINK command message header
+ *
+ * Header used for QLINK messages of QLINK_MSG_TYPE_CMD type.
+ *
+ * @mhdr: Common QLINK message header.
+ * @cmd_id: command id, one of &enum qlink_cmd_type.
+ * @seq_num: sequence number of command message, used for matching with
+ *     response message.
+ * @macid: index of physical radio device the command is destined to or
+ *     QLINK_MACID_RSVD if not applicable.
+ * @vifid: index of virtual wireless interface on specified @macid the command
+ *     is destined to or QLINK_VIFID_RSVD if not applicable.
+ */
+struct qlink_cmd {
+       struct qlink_msg_header mhdr;
+       __le16 cmd_id;
+       __le16 seq_num;
+       u8 rsvd[2];
+       u8 macid;
+       u8 vifid;
+} __packed;
+
+/**
+ * struct qlink_cmd_manage_intf - interface management command
+ *
+ * Data for interface management commands QLINK_CMD_ADD_INTF, QLINK_CMD_DEL_INTF
+ * and QLINK_CMD_CHANGE_INTF.
+ *
+ * @intf_info: interface description.
+ */
+struct qlink_cmd_manage_intf {
+       struct qlink_cmd chdr;
+       struct qlink_intf_info intf_info;
+} __packed;
+
+enum qlink_mgmt_frame_type {
+       QLINK_MGMT_FRAME_ASSOC_REQ      = 0x00,
+       QLINK_MGMT_FRAME_ASSOC_RESP     = 0x01,
+       QLINK_MGMT_FRAME_REASSOC_REQ    = 0x02,
+       QLINK_MGMT_FRAME_REASSOC_RESP   = 0x03,
+       QLINK_MGMT_FRAME_PROBE_REQ      = 0x04,
+       QLINK_MGMT_FRAME_PROBE_RESP     = 0x05,
+       QLINK_MGMT_FRAME_BEACON         = 0x06,
+       QLINK_MGMT_FRAME_ATIM           = 0x07,
+       QLINK_MGMT_FRAME_DISASSOC       = 0x08,
+       QLINK_MGMT_FRAME_AUTH           = 0x09,
+       QLINK_MGMT_FRAME_DEAUTH         = 0x0A,
+       QLINK_MGMT_FRAME_ACTION         = 0x0B,
+
+       QLINK_MGMT_FRAME_TYPE_COUNT
+};
+
+/**
+ * struct qlink_cmd_mgmt_frame_register - data for QLINK_CMD_REGISTER_MGMT
+ *
+ * @frame_type: MGMT frame type the registration request describes, one of
+ *     &enum qlink_mgmt_frame_type.
+ * @do_register: 0 - unregister, otherwise register for reception of specified
+ *     MGMT frame type.
+ */
+struct qlink_cmd_mgmt_frame_register {
+       struct qlink_cmd chdr;
+       __le16 frame_type;
+       u8 do_register;
+} __packed;
+
+enum qlink_mgmt_frame_tx_flags {
+       QLINK_MGMT_FRAME_TX_FLAG_NONE           = 0,
+       QLINK_MGMT_FRAME_TX_FLAG_OFFCHAN        = BIT(0),
+       QLINK_MGMT_FRAME_TX_FLAG_NO_CCK         = BIT(1),
+       QLINK_MGMT_FRAME_TX_FLAG_ACK_NOWAIT     = BIT(2),
+};
+
+/**
+ * struct qlink_cmd_mgmt_frame_tx - data for QLINK_CMD_SEND_MGMT_FRAME command
+ *
+ * @cookie: opaque request identifier.
+ * @freq: Frequency to use for frame transmission.
+ * @flags: Transmission flags, one of &enum qlink_mgmt_frame_tx_flags.
+ * @frame_data: frame to transmit.
+ */
+struct qlink_cmd_mgmt_frame_tx {
+       struct qlink_cmd chdr;
+       __le32 cookie;
+       __le16 freq;
+       __le16 flags;
+       u8 frame_data[0];
+} __packed;
+
+/**
+ * struct qlink_cmd_mgmt_append_ie - data for QLINK_CMD_MGMT_SET_APPIE command
+ *
+ * @type: type of MGMT frame to appent requested IEs to, one of
+ *     &enum qlink_mgmt_frame_type.
+ * @flags: for future use.
+ * @ie_data: IEs data to append.
+ */
+struct qlink_cmd_mgmt_append_ie {
+       struct qlink_cmd chdr;
+       u8 type;
+       u8 flags;
+       u8 ie_data[0];
+} __packed;
+
+/**
+ * struct qlink_cmd_get_sta_info - data for QLINK_CMD_GET_STA_INFO command
+ *
+ * @sta_addr: MAC address of the STA statistics is requested for.
+ */
+struct qlink_cmd_get_sta_info {
+       struct qlink_cmd chdr;
+       u8 sta_addr[ETH_ALEN];
+} __packed;
+
+/**
+ * struct qlink_cmd_add_key - data for QLINK_CMD_ADD_KEY command.
+ *
+ * @key_index: index of the key being installed.
+ * @pairwise: whether to use pairwise key.
+ * @addr: MAC address of a STA key is being installed to.
+ * @cipher: cipher suite.
+ * @key_data: key data itself.
+ */
+struct qlink_cmd_add_key {
+       struct qlink_cmd chdr;
+       u8 key_index;
+       u8 pairwise;
+       u8 addr[ETH_ALEN];
+       __le32 cipher;
+       u8 key_data[0];
+} __packed;
+
+/**
+ * struct qlink_cmd_del_key_req - data for QLINK_CMD_DEL_KEY command
+ *
+ * @key_index: index of the key being removed.
+ * @pairwise: whether to use pairwise key.
+ * @addr: MAC address of a STA for which a key is removed.
+ */
+struct qlink_cmd_del_key {
+       struct qlink_cmd chdr;
+       u8 key_index;
+       u8 pairwise;
+       u8 addr[ETH_ALEN];
+} __packed;
+
+/**
+ * struct qlink_cmd_set_def_key - data for QLINK_CMD_SET_DEFAULT_KEY command
+ *
+ * @key_index: index of the key to be set as default one.
+ * @unicast: key is unicast.
+ * @multicast: key is multicast.
+ */
+struct qlink_cmd_set_def_key {
+       struct qlink_cmd chdr;
+       u8 key_index;
+       u8 unicast;
+       u8 multicast;
+} __packed;
+
+/**
+ * struct qlink_cmd_set_def_mgmt_key - data for QLINK_CMD_SET_DEFAULT_MGMT_KEY
+ *
+ * @key_index: index of the key to be set as default MGMT key.
+ */
+struct qlink_cmd_set_def_mgmt_key {
+       struct qlink_cmd chdr;
+       u8 key_index;
+} __packed;
+
+/**
+ * struct qlink_cmd_change_sta - data for QLINK_CMD_CHANGE_STA command
+ *
+ * @sta_flags_mask: STA flags mask, bitmap of &enum qlink_sta_flags
+ * @sta_flags_set: STA flags values, bitmap of &enum qlink_sta_flags
+ * @sta_addr: address of the STA for which parameters are set.
+ */
+struct qlink_cmd_change_sta {
+       struct qlink_cmd chdr;
+       __le32 sta_flags_mask;
+       __le32 sta_flags_set;
+       u8 sta_addr[ETH_ALEN];
+} __packed;
+
+/**
+ * struct qlink_cmd_del_sta - data for QLINK_CMD_DEL_STA command.
+ *
+ * See &struct station_del_parameters
+ */
+struct qlink_cmd_del_sta {
+       struct qlink_cmd chdr;
+       __le16 reason_code;
+       u8 subtype;
+       u8 sta_addr[ETH_ALEN];
+} __packed;
+
+enum qlink_sta_connect_flags {
+       QLINK_STA_CONNECT_DISABLE_HT    = BIT(0),
+       QLINK_STA_CONNECT_DISABLE_VHT   = BIT(1),
+       QLINK_STA_CONNECT_USE_RRM       = BIT(2),
+};
+
+/**
+ * struct qlink_cmd_connect - data for QLINK_CMD_CONNECT command
+ *
+ * @flags: for future use.
+ * @freq: center frequence of a channel which should be used to connect.
+ * @bg_scan_period: period of background scan.
+ * @bssid: BSSID of the BSS to connect to.
+ * @payload: variable portion of connection request.
+ */
+struct qlink_cmd_connect {
+       struct qlink_cmd chdr;
+       __le32 flags;
+       __le16 freq;
+       __le16 bg_scan_period;
+       u8 bssid[ETH_ALEN];
+       u8 payload[0];
+} __packed;
+
+/**
+ * struct qlink_cmd_disconnect - data for QLINK_CMD_DISCONNECT command
+ *
+ * @reason: code of the reason of disconnect, see &enum ieee80211_reasoncode.
+ */
+struct qlink_cmd_disconnect {
+       struct qlink_cmd chdr;
+       __le16 reason;
+} __packed;
+
+/**
+ * struct qlink_cmd_updown - data for QLINK_CMD_UPDOWN_INTF command
+ *
+ * @if_up: bring specified interface DOWN (if_up==0) or UP (otherwise).
+ *     Interface is specified in common command header @chdr.
+ */
+struct qlink_cmd_updown {
+       struct qlink_cmd chdr;
+       u8 if_up;
+} __packed;
+
+/**
+ * enum qlink_band - a list of frequency bands
+ *
+ * @QLINK_BAND_2GHZ: 2.4GHz band
+ * @QLINK_BAND_5GHZ: 5GHz band
+ * @QLINK_BAND_60GHZ: 60GHz band
+ */
+enum qlink_band {
+       QLINK_BAND_2GHZ = BIT(0),
+       QLINK_BAND_5GHZ = BIT(1),
+       QLINK_BAND_60GHZ = BIT(2),
+};
+
+/**
+ * struct qlink_cmd_chans_info_get - data for QLINK_CMD_CHANS_INFO_GET command
+ *
+ * @band: a PHY band for which channels info is needed, one of @enum qlink_band
+ */
+struct qlink_cmd_chans_info_get {
+       struct qlink_cmd chdr;
+       u8 band;
+} __packed;
+
+/* QLINK Command Responses messages related definitions
+ */
+
+enum qlink_cmd_result {
+       QLINK_CMD_RESULT_OK = 0,
+       QLINK_CMD_RESULT_INVALID,
+       QLINK_CMD_RESULT_ENOTSUPP,
+       QLINK_CMD_RESULT_ENOTFOUND,
+};
+
+/**
+ * struct qlink_resp - QLINK command response message header
+ *
+ * Header used for QLINK messages of QLINK_MSG_TYPE_CMDRSP type.
+ *
+ * @mhdr: see &struct qlink_msg_header.
+ * @cmd_id: command ID the response corresponds to, one of &enum qlink_cmd_type.
+ * @seq_num: sequence number of command message, used for matching with
+ *     response message.
+ * @result: result of the command execution, one of &enum qlink_cmd_result.
+ * @macid: index of physical radio device the response is sent from or
+ *     QLINK_MACID_RSVD if not applicable.
+ * @vifid: index of virtual wireless interface on specified @macid the response
+ *     is sent from or QLINK_VIFID_RSVD if not applicable.
+ */
+struct qlink_resp {
+       struct qlink_msg_header mhdr;
+       __le16 cmd_id;
+       __le16 seq_num;
+       __le16 result;
+       u8 macid;
+       u8 vifid;
+} __packed;
+
+/**
+ * struct qlink_resp_get_mac_info - response for QLINK_CMD_MAC_INFO command
+ *
+ * Data describing specific physical device providing wireless MAC
+ * functionality.
+ *
+ * @dev_mac: MAC address of physical WMAC device (used for first BSS on
+ *     specified WMAC).
+ * @num_tx_chain: Number of transmit chains used by WMAC.
+ * @num_rx_chain: Number of receive chains used by WMAC.
+ * @vht_cap: VHT capabilities.
+ * @ht_cap: HT capabilities.
+ * @bands_cap: wireless bands WMAC can operate in, bitmap of &enum qlink_band.
+ * @phymode_cap: PHY modes WMAC can operate in, bitmap of &enum qlink_phy_mode.
+ * @max_ap_assoc_sta: Maximum number of associations supported by WMAC.
+ * @radar_detect_widths: bitmask of channels BW for which WMAC can detect radar.
+ * @var_info: variable-length WMAC info data.
+ */
+struct qlink_resp_get_mac_info {
+       struct qlink_resp rhdr;
+       u8 dev_mac[ETH_ALEN];
+       u8 num_tx_chain;
+       u8 num_rx_chain;
+       struct ieee80211_vht_cap vht_cap;
+       struct ieee80211_ht_cap ht_cap;
+       u8 bands_cap;
+       u8 phymode_cap;
+       __le16 max_ap_assoc_sta;
+       __le16 radar_detect_widths;
+       u8 var_info[0];
+} __packed;
+
+/**
+ * struct qlink_resp_get_hw_info - response for QLINK_CMD_GET_HW_INFO command
+ *
+ * Description of wireless hardware capabilities and features.
+ *
+ * @fw_ver: wireless hardware firmware version.
+ * @hw_capab: Bitmap of capabilities supported by firmware.
+ * @ql_proto_ver: Version of QLINK protocol used by firmware.
+ * @country_code: country code ID firmware is configured to.
+ * @num_mac: Number of separate physical radio devices provided by hardware.
+ * @mac_bitmap: Bitmap of MAC IDs that are active and can be used in firmware.
+ * @total_tx_chains: total number of transmit chains used by device.
+ * @total_rx_chains: total number of receive chains.
+ */
+struct qlink_resp_get_hw_info {
+       struct qlink_resp rhdr;
+       __le32 fw_ver;
+       __le32 hw_capab;
+       __le16 ql_proto_ver;
+       u8 alpha2_code[2];
+       u8 num_mac;
+       u8 mac_bitmap;
+       u8 total_tx_chain;
+       u8 total_rx_chain;
+} __packed;
+
+/**
+ * struct qlink_resp_manage_intf - response for interface management commands
+ *
+ * Response data for QLINK_CMD_ADD_INTF and QLINK_CMD_CHANGE_INTF commands.
+ *
+ * @rhdr: Common Command Response message header.
+ * @intf_info: interface description.
+ */
+struct qlink_resp_manage_intf {
+       struct qlink_resp rhdr;
+       struct qlink_intf_info intf_info;
+} __packed;
+
+/**
+ * struct qlink_resp_get_sta_info - response for QLINK_CMD_GET_STA_INFO command
+ *
+ * Response data containing statistics for specified STA.
+ *
+ * @sta_addr: MAC address of STA the response carries statistic for.
+ * @info: statistics for specified STA.
+ */
+struct qlink_resp_get_sta_info {
+       struct qlink_resp rhdr;
+       u8 sta_addr[ETH_ALEN];
+       u8 info[0];
+} __packed;
+
+/**
+ * struct qlink_resp_get_chan_info - response for QLINK_CMD_CHANS_INFO_GET cmd
+ *
+ * @band: frequency band to which channels belong to, one of @enum qlink_band.
+ * @num_chans: total number of channels info data contained in reply data.
+ * @info: variable-length channels info.
+ */
+struct qlink_resp_get_chan_info {
+       struct qlink_resp rhdr;
+       u8 band;
+       u8 num_chans;
+       u8 rsvd[2];
+       u8 info[0];
+} __packed;
+
+/**
+ * struct qlink_resp_phy_params - response for QLINK_CMD_PHY_PARAMS_GET command
+ *
+ * @info: variable-length array of PHY params.
+ */
+struct qlink_resp_phy_params {
+       struct qlink_resp rhdr;
+       u8 info[0];
+} __packed;
+
+/* QLINK Events messages related definitions
+ */
+
+enum qlink_event_type {
+       QLINK_EVENT_STA_ASSOCIATED      = 0x0021,
+       QLINK_EVENT_STA_DEAUTH          = 0x0022,
+       QLINK_EVENT_MGMT_RECEIVED       = 0x0023,
+       QLINK_EVENT_SCAN_RESULTS        = 0x0024,
+       QLINK_EVENT_SCAN_COMPLETE       = 0x0025,
+       QLINK_EVENT_BSS_JOIN            = 0x0026,
+       QLINK_EVENT_BSS_LEAVE           = 0x0027,
+};
+
+/**
+ * struct qlink_event - QLINK event message header
+ *
+ * Header used for QLINK messages of QLINK_MSG_TYPE_EVENT type.
+ *
+ * @mhdr: Common QLINK message header.
+ * @event_id: Specifies specific event ID, one of &enum qlink_event_type.
+ * @macid: index of physical radio device the event was generated on or
+ *     QLINK_MACID_RSVD if not applicable.
+ * @vifid: index of virtual wireless interface on specified @macid the event
+ *     was generated on or QLINK_VIFID_RSVD if not applicable.
+ */
+struct qlink_event {
+       struct qlink_msg_header mhdr;
+       __le16 event_id;
+       u8 macid;
+       u8 vifid;
+} __packed;
+
+/**
+ * struct qlink_event_sta_assoc - data for QLINK_EVENT_STA_ASSOCIATED event
+ *
+ * @sta_addr: Address of a STA for which new association event was generated
+ * @frame_control: control bits from 802.11 ASSOC_REQUEST header.
+ * @payload: IEs from association request.
+ */
+struct qlink_event_sta_assoc {
+       struct qlink_event ehdr;
+       u8 sta_addr[ETH_ALEN];
+       __le16 frame_control;
+       u8 ies[0];
+} __packed;
+
+/**
+ * struct qlink_event_sta_deauth - data for QLINK_EVENT_STA_DEAUTH event
+ *
+ * @sta_addr: Address of a deauthenticated STA.
+ * @reason: reason for deauthentication.
+ */
+struct qlink_event_sta_deauth {
+       struct qlink_event ehdr;
+       u8 sta_addr[ETH_ALEN];
+       __le16 reason;
+} __packed;
+
+/**
+ * struct qlink_event_bss_join - data for QLINK_EVENT_BSS_JOIN event
+ *
+ * @bssid: BSSID of a BSS which interface tried to joined.
+ * @status: status of joining attempt, see &enum ieee80211_statuscode.
+ */
+struct qlink_event_bss_join {
+       struct qlink_event ehdr;
+       u8 bssid[ETH_ALEN];
+       __le16 status;
+} __packed;
+
+/**
+ * struct qlink_event_bss_leave - data for QLINK_EVENT_BSS_LEAVE event
+ *
+ * @reason: reason of disconnecting from BSS.
+ */
+struct qlink_event_bss_leave {
+       struct qlink_event ehdr;
+       u16 reason;
+} __packed;
+
+enum qlink_rxmgmt_flags {
+       QLINK_RXMGMT_FLAG_ANSWERED = 1 << 0,
+};
+
+/**
+ * struct qlink_event_rxmgmt - data for QLINK_EVENT_MGMT_RECEIVED event
+ *
+ * @freq: Frequency on which the frame was received in MHz.
+ * @sig_dbm: signal strength in dBm.
+ * @flags: bitmap of &enum qlink_rxmgmt_flags.
+ * @frame_data: data of Rx'd frame itself.
+ */
+struct qlink_event_rxmgmt {
+       struct qlink_event ehdr;
+       __le32 freq;
+       __le32 sig_dbm;
+       __le32 flags;
+       u8 frame_data[0];
+} __packed;
+
+enum qlink_frame_type {
+       QLINK_BSS_FTYPE_UNKNOWN,
+       QLINK_BSS_FTYPE_BEACON,
+       QLINK_BSS_FTYPE_PRESP,
+};
+
+/**
+ * struct qlink_event_scan_result - data for QLINK_EVENT_SCAN_RESULTS event
+ *
+ * @tsf: TSF timestamp indicating when scan results were generated.
+ * @freq: Center frequency of the channel where BSS for which the scan result
+ *     event was generated was discovered.
+ * @capab: capabilities field.
+ * @bintval: beacon interval announced by discovered BSS.
+ * @signal: signal strength.
+ * @frame_type: frame type used to get scan result, see &enum qlink_frame_type.
+ * @bssid: BSSID announced by discovered BSS.
+ * @ssid_len: length of SSID announced by BSS.
+ * @ssid: SSID announced by discovered BSS.
+ * @payload: IEs that are announced by discovered BSS in its MGMt frames.
+ */
+struct qlink_event_scan_result {
+       struct qlink_event ehdr;
+       __le64 tsf;
+       __le16 freq;
+       __le16 capab;
+       __le16 bintval;
+       s8 signal;
+       u8 frame_type;
+       u8 bssid[ETH_ALEN];
+       u8 ssid_len;
+       u8 ssid[IEEE80211_MAX_SSID_LEN];
+       u8 payload[0];
+} __packed;
+
+/**
+ * enum qlink_scan_complete_flags - indicates result of scan request.
+ *
+ * @QLINK_SCAN_NONE: Scan request was processed.
+ * @QLINK_SCAN_ABORTED: Scan was aborted.
+ */
+enum qlink_scan_complete_flags {
+       QLINK_SCAN_NONE         = 0,
+       QLINK_SCAN_ABORTED      = BIT(0),
+};
+
+/**
+ * struct qlink_event_scan_complete - data for QLINK_EVENT_SCAN_COMPLETE event
+ *
+ * @flags: flags indicating the status of pending scan request,
+ *     see &enum qlink_scan_complete_flags.
+ */
+struct qlink_event_scan_complete {
+       struct qlink_event ehdr;
+       __le32 flags;
+} __packed;
+
+/* QLINK TLVs (Type-Length Values) definitions
+ */
+
+enum qlink_tlv_id {
+       QTN_TLV_ID_FRAG_THRESH          = 0x0201,
+       QTN_TLV_ID_RTS_THRESH           = 0x0202,
+       QTN_TLV_ID_SRETRY_LIMIT         = 0x0203,
+       QTN_TLV_ID_LRETRY_LIMIT         = 0x0204,
+       QTN_TLV_ID_BCN_PERIOD           = 0x0205,
+       QTN_TLV_ID_DTIM                 = 0x0206,
+       QTN_TLV_ID_CHANNEL              = 0x020F,
+       QTN_TLV_ID_COVERAGE_CLASS       = 0x0213,
+       QTN_TLV_ID_IFACE_LIMIT          = 0x0214,
+       QTN_TLV_ID_NUM_IFACE_COMB       = 0x0215,
+       QTN_TLV_ID_STA_BASIC_COUNTERS   = 0x0300,
+       QTN_TLV_ID_STA_GENERIC_INFO     = 0x0301,
+       QTN_TLV_ID_KEY                  = 0x0302,
+       QTN_TLV_ID_SEQ                  = 0x0303,
+       QTN_TLV_ID_CRYPTO               = 0x0304,
+       QTN_TLV_ID_IE_SET               = 0x0305,
+};
+
+struct qlink_tlv_hdr {
+       __le16 type;
+       __le16 len;
+       u8 val[0];
+} __packed;
+
+struct qlink_iface_limit {
+       __le16 max_num;
+       __le16 type_mask;
+} __packed;
+
+struct qlink_iface_comb_num {
+       __le16 iface_comb_num;
+} __packed;
+
+struct qlink_sta_stat_basic_counters {
+       __le64 rx_bytes;
+       __le64 tx_bytes;
+       __le64 rx_beacons;
+       __le32 rx_packets;
+       __le32 tx_packets;
+       __le32 rx_dropped;
+       __le32 tx_failed;
+} __packed;
+
+enum qlink_sta_info_rate_flags {
+       QLINK_STA_INFO_RATE_FLAG_INVALID        = 0,
+       QLINK_STA_INFO_RATE_FLAG_HT_MCS         = BIT(0),
+       QLINK_STA_INFO_RATE_FLAG_VHT_MCS        = BIT(1),
+       QLINK_STA_INFO_RATE_FLAG_SHORT_GI       = BIT(2),
+       QLINK_STA_INFO_RATE_FLAG_60G            = BIT(3),
+};
+
+enum qlink_sta_info_rate_bw {
+       QLINK_STA_INFO_RATE_BW_5                = 0,
+       QLINK_STA_INFO_RATE_BW_10               = 1,
+       QLINK_STA_INFO_RATE_BW_20               = 2,
+       QLINK_STA_INFO_RATE_BW_40               = 3,
+       QLINK_STA_INFO_RATE_BW_80               = 4,
+       QLINK_STA_INFO_RATE_BW_160              = 5,
+};
+
+/**
+ * struct qlink_sta_info_rate - STA rate statistics
+ *
+ * @rate: data rate in Mbps.
+ * @flags: bitmap of &enum qlink_sta_flags.
+ * @mcs: 802.11-defined MCS index.
+ * nss: Number of Spatial Streams.
+ * @bw: bandwidth, one of &enum qlink_sta_info_rate_bw.
+ */
+struct qlink_sta_info_rate {
+       __le16 rate;
+       u8 flags;
+       u8 mcs;
+       u8 nss;
+       u8 bw;
+} __packed;
+
+struct qlink_sta_info_state {
+       __le32 mask;
+       __le32 value;
+} __packed;
+
+#define QLINK_RSSI_OFFSET      120
+
+struct qlink_sta_info_generic {
+       struct qlink_sta_info_state state;
+       __le32 connected_time;
+       __le32 inactive_time;
+       struct qlink_sta_info_rate rx_rate;
+       struct qlink_sta_info_rate tx_rate;
+       u8 rssi;
+       u8 rssi_avg;
+} __packed;
+
+struct qlink_tlv_frag_rts_thr {
+       struct qlink_tlv_hdr hdr;
+       __le16 thr;
+} __packed;
+
+struct qlink_tlv_rlimit {
+       struct qlink_tlv_hdr hdr;
+       u8 rlimit;
+} __packed;
+
+struct qlink_tlv_cclass {
+       struct qlink_tlv_hdr hdr;
+       u8 cclass;
+} __packed;
+
+enum qlink_dfs_state {
+       QLINK_DFS_USABLE,
+       QLINK_DFS_UNAVAILABLE,
+       QLINK_DFS_AVAILABLE,
+};
+
+enum qlink_channel_flags {
+       QLINK_CHAN_DISABLED             = BIT(0),
+       QLINK_CHAN_NO_IR                = BIT(1),
+       QLINK_CHAN_RADAR                = BIT(3),
+       QLINK_CHAN_NO_HT40PLUS          = BIT(4),
+       QLINK_CHAN_NO_HT40MINUS         = BIT(5),
+       QLINK_CHAN_NO_OFDM              = BIT(6),
+       QLINK_CHAN_NO_80MHZ             = BIT(7),
+       QLINK_CHAN_NO_160MHZ            = BIT(8),
+       QLINK_CHAN_INDOOR_ONLY          = BIT(9),
+       QLINK_CHAN_IR_CONCURRENT        = BIT(10),
+       QLINK_CHAN_NO_20MHZ             = BIT(11),
+       QLINK_CHAN_NO_10MHZ             = BIT(12),
+};
+
+struct qlink_tlv_channel {
+       struct qlink_tlv_hdr hdr;
+       __le16 hw_value;
+       __le16 center_freq;
+       __le32 flags;
+       u8 band;
+       u8 max_antenna_gain;
+       u8 max_power;
+       u8 max_reg_power;
+       __le32 dfs_cac_ms;
+       u8 dfs_state;
+       u8 beacon_found;
+       u8 rsvd[2];
+} __packed;
+
+#define QLINK_MAX_NR_CIPHER_SUITES            5
+#define QLINK_MAX_NR_AKM_SUITES               2
+
+struct qlink_auth_encr {
+       __le32 wpa_versions;
+       __le32 cipher_group;
+       __le32 n_ciphers_pairwise;
+       __le32 ciphers_pairwise[QLINK_MAX_NR_CIPHER_SUITES];
+       __le32 n_akm_suites;
+       __le32 akm_suites[QLINK_MAX_NR_AKM_SUITES];
+       __le16 control_port_ethertype;
+       u8 auth_type;
+       u8 privacy;
+       u8 mfp;
+       u8 control_port;
+       u8 control_port_no_encrypt;
+} __packed;
+
+#endif /* _QTN_QLINK_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c
new file mode 100644 (file)
index 0000000..49ae652
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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/nl80211.h>
+
+#include "qlink_util.h"
+
+u16 qlink_iface_type_mask_to_nl(u16 qlink_mask)
+{
+       u16 result = 0;
+
+       if (qlink_mask & QLINK_IFTYPE_AP)
+               result |= BIT(NL80211_IFTYPE_AP);
+
+       if (qlink_mask & QLINK_IFTYPE_STATION)
+               result |= BIT(NL80211_IFTYPE_STATION);
+
+       if (qlink_mask & QLINK_IFTYPE_ADHOC)
+               result |= BIT(NL80211_IFTYPE_ADHOC);
+
+       if (qlink_mask & QLINK_IFTYPE_MONITOR)
+               result |= BIT(NL80211_IFTYPE_MONITOR);
+
+       if (qlink_mask & QLINK_IFTYPE_WDS)
+               result |= BIT(NL80211_IFTYPE_WDS);
+
+       return result;
+}
+
+u8 qlink_chan_width_mask_to_nl(u16 qlink_mask)
+{
+       u8 result = 0;
+
+       if (qlink_mask & QLINK_CHAN_WIDTH_5)
+               result |= BIT(NL80211_CHAN_WIDTH_5);
+
+       if (qlink_mask & QLINK_CHAN_WIDTH_10)
+               result |= BIT(NL80211_CHAN_WIDTH_10);
+
+       if (qlink_mask & QLINK_CHAN_WIDTH_20_NOHT)
+               result |= BIT(NL80211_CHAN_WIDTH_20_NOHT);
+
+       if (qlink_mask & QLINK_CHAN_WIDTH_20)
+               result |= BIT(NL80211_CHAN_WIDTH_20);
+
+       if (qlink_mask & QLINK_CHAN_WIDTH_40)
+               result |= BIT(NL80211_CHAN_WIDTH_40);
+
+       if (qlink_mask & QLINK_CHAN_WIDTH_80)
+               result |= BIT(NL80211_CHAN_WIDTH_80);
+
+       if (qlink_mask & QLINK_CHAN_WIDTH_80P80)
+               result |= BIT(NL80211_CHAN_WIDTH_80P80);
+
+       if (qlink_mask & QLINK_CHAN_WIDTH_160)
+               result |= BIT(NL80211_CHAN_WIDTH_160);
+
+       return result;
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h
new file mode 100644 (file)
index 0000000..d8de484
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 _QTN_FMAC_QLINK_UTIL_H_
+#define _QTN_FMAC_QLINK_UTIL_H_
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+
+#include "qlink.h"
+
+static inline void qtnf_cmd_skb_put_action(struct sk_buff *skb, u16 action)
+{
+       __le16 *buf_ptr;
+
+       buf_ptr = (__le16 *)skb_put(skb, sizeof(action));
+       *buf_ptr = cpu_to_le16(action);
+}
+
+static inline void
+qtnf_cmd_skb_put_buffer(struct sk_buff *skb, const u8 *buf_src, size_t len)
+{
+       u8 *buf_dst;
+
+       buf_dst = skb_put(skb, len);
+       memcpy(buf_dst, buf_src, len);
+}
+
+static inline void qtnf_cmd_skb_put_tlv_arr(struct sk_buff *skb,
+                                           u16 tlv_id, const u8 arr[],
+                                           size_t arr_len)
+{
+       struct qlink_tlv_hdr *hdr =
+                       (void *)skb_put(skb, sizeof(*hdr) + arr_len);
+
+       hdr->type = cpu_to_le16(tlv_id);
+       hdr->len = cpu_to_le16(arr_len);
+       memcpy(hdr->val, arr, arr_len);
+}
+
+static inline void qtnf_cmd_skb_put_tlv_u8(struct sk_buff *skb, u16 tlv_id,
+                                          u8 value)
+{
+       struct qlink_tlv_hdr *hdr =
+                       (void *)skb_put(skb, sizeof(*hdr) + sizeof(value));
+
+       hdr->type = cpu_to_le16(tlv_id);
+       hdr->len = cpu_to_le16(sizeof(value));
+       *hdr->val = value;
+}
+
+static inline void qtnf_cmd_skb_put_tlv_u16(struct sk_buff *skb,
+                                           u16 tlv_id, u16 value)
+{
+       struct qlink_tlv_hdr *hdr =
+                       (void *)skb_put(skb, sizeof(*hdr) + sizeof(value));
+       __le16 tmp = cpu_to_le16(value);
+
+       hdr->type = cpu_to_le16(tlv_id);
+       hdr->len = cpu_to_le16(sizeof(value));
+       memcpy(hdr->val, &tmp, sizeof(tmp));
+}
+
+u16 qlink_iface_type_mask_to_nl(u16 qlink_mask);
+u8 qlink_chan_width_mask_to_nl(u16 qlink_mask);
+
+#endif /* _QTN_FMAC_QLINK_UTIL_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h b/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h
new file mode 100644 (file)
index 0000000..c4ad40d
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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        _QTN_HW_IDS_H_
+#define        _QTN_HW_IDS_H_
+
+#include <linux/pci_ids.h>
+
+#define PCIE_VENDOR_ID_QUANTENNA       (0x1bb5)
+
+/* PCIE Device IDs */
+
+#define        PCIE_DEVICE_ID_QTN_PEARL        (0x0008)
+
+/* FW names */
+
+#define QTN_PCI_PEARL_FW_NAME          "qtn/fmac_qsr10g.img"
+
+#endif /* _QTN_HW_IDS_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c
new file mode 100644 (file)
index 0000000..aa106dd
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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/types.h>
+#include <linux/io.h>
+
+#include "shm_ipc.h"
+
+#undef pr_fmt
+#define pr_fmt(fmt)    "qtnfmac shm_ipc: %s: " fmt, __func__
+
+static bool qtnf_shm_ipc_has_new_data(struct qtnf_shm_ipc *ipc)
+{
+       const u32 flags = readl(&ipc->shm_region->headroom.hdr.flags);
+
+       return (flags & QTNF_SHM_IPC_NEW_DATA);
+}
+
+static void qtnf_shm_handle_new_data(struct qtnf_shm_ipc *ipc)
+{
+       size_t size;
+       bool rx_buff_ok = true;
+       struct qtnf_shm_ipc_region_header __iomem *shm_reg_hdr;
+
+       shm_reg_hdr = &ipc->shm_region->headroom.hdr;
+
+       size = readw(&shm_reg_hdr->data_len);
+
+       if (unlikely(size == 0 || size > QTN_IPC_MAX_DATA_SZ)) {
+               pr_err("wrong rx packet size: %zu\n", size);
+               rx_buff_ok = false;
+       } else {
+               memcpy_fromio(ipc->rx_data, ipc->shm_region->data, size);
+       }
+
+       writel(QTNF_SHM_IPC_ACK, &shm_reg_hdr->flags);
+       readl(&shm_reg_hdr->flags); /* flush PCIe write */
+
+       ipc->interrupt.fn(ipc->interrupt.arg);
+
+       if (likely(rx_buff_ok)) {
+               ipc->rx_packet_count++;
+               ipc->rx_callback.fn(ipc->rx_callback.arg, ipc->rx_data, size);
+       }
+}
+
+static void qtnf_shm_ipc_irq_work(struct work_struct *work)
+{
+       struct qtnf_shm_ipc *ipc = container_of(work, struct qtnf_shm_ipc,
+                                               irq_work);
+
+       while (qtnf_shm_ipc_has_new_data(ipc))
+               qtnf_shm_handle_new_data(ipc);
+}
+
+static void qtnf_shm_ipc_irq_inbound_handler(struct qtnf_shm_ipc *ipc)
+{
+       u32 flags;
+
+       flags = readl(&ipc->shm_region->headroom.hdr.flags);
+
+       if (flags & QTNF_SHM_IPC_NEW_DATA)
+               queue_work(ipc->workqueue, &ipc->irq_work);
+}
+
+static void qtnf_shm_ipc_irq_outbound_handler(struct qtnf_shm_ipc *ipc)
+{
+       u32 flags;
+
+       if (!READ_ONCE(ipc->waiting_for_ack))
+               return;
+
+       flags = readl(&ipc->shm_region->headroom.hdr.flags);
+
+       if (flags & QTNF_SHM_IPC_ACK) {
+               WRITE_ONCE(ipc->waiting_for_ack, 0);
+               complete(&ipc->tx_completion);
+       }
+}
+
+int qtnf_shm_ipc_init(struct qtnf_shm_ipc *ipc,
+                     enum qtnf_shm_ipc_direction direction,
+                     struct qtnf_shm_ipc_region __iomem *shm_region,
+                     struct workqueue_struct *workqueue,
+                     const struct qtnf_shm_ipc_int *interrupt,
+                     const struct qtnf_shm_ipc_rx_callback *rx_callback)
+{
+       BUILD_BUG_ON(offsetof(struct qtnf_shm_ipc_region, data) !=
+                    QTN_IPC_REG_HDR_SZ);
+       BUILD_BUG_ON(sizeof(struct qtnf_shm_ipc_region) > QTN_IPC_REG_SZ);
+
+       ipc->shm_region = shm_region;
+       ipc->direction = direction;
+       ipc->interrupt = *interrupt;
+       ipc->rx_callback = *rx_callback;
+       ipc->tx_packet_count = 0;
+       ipc->rx_packet_count = 0;
+       ipc->workqueue = workqueue;
+       ipc->waiting_for_ack = 0;
+       ipc->tx_timeout_count = 0;
+
+       switch (direction) {
+       case QTNF_SHM_IPC_OUTBOUND:
+               ipc->irq_handler = qtnf_shm_ipc_irq_outbound_handler;
+               break;
+       case QTNF_SHM_IPC_INBOUND:
+               ipc->irq_handler = qtnf_shm_ipc_irq_inbound_handler;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       INIT_WORK(&ipc->irq_work, qtnf_shm_ipc_irq_work);
+       init_completion(&ipc->tx_completion);
+
+       return 0;
+}
+
+void qtnf_shm_ipc_free(struct qtnf_shm_ipc *ipc)
+{
+       complete_all(&ipc->tx_completion);
+}
+
+int qtnf_shm_ipc_send(struct qtnf_shm_ipc *ipc, const u8 *buf, size_t size)
+{
+       int ret = 0;
+       struct qtnf_shm_ipc_region_header __iomem *shm_reg_hdr;
+
+       shm_reg_hdr = &ipc->shm_region->headroom.hdr;
+
+       if (unlikely(size > QTN_IPC_MAX_DATA_SZ))
+               return -E2BIG;
+
+       ipc->tx_packet_count++;
+
+       writew(size, &shm_reg_hdr->data_len);
+       memcpy_toio(ipc->shm_region->data, buf, size);
+
+       /* sync previous writes before proceeding */
+       dma_wmb();
+
+       WRITE_ONCE(ipc->waiting_for_ack, 1);
+
+       /* sync previous memory write before announcing new data ready */
+       wmb();
+
+       writel(QTNF_SHM_IPC_NEW_DATA, &shm_reg_hdr->flags);
+       readl(&shm_reg_hdr->flags); /* flush PCIe write */
+
+       ipc->interrupt.fn(ipc->interrupt.arg);
+
+       if (!wait_for_completion_timeout(&ipc->tx_completion,
+                                        QTN_SHM_IPC_ACK_TIMEOUT)) {
+               ret = -ETIMEDOUT;
+               ipc->tx_timeout_count++;
+               pr_err("TX ACK timeout\n");
+       }
+
+       /* now we're not waiting for ACK even in case of timeout */
+       WRITE_ONCE(ipc->waiting_for_ack, 0);
+
+       return ret;
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h
new file mode 100644 (file)
index 0000000..453dd64
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 _QTN_FMAC_SHM_IPC_H_
+#define _QTN_FMAC_SHM_IPC_H_
+
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
+#include "shm_ipc_defs.h"
+
+#define QTN_SHM_IPC_ACK_TIMEOUT                (2 * HZ)
+
+struct qtnf_shm_ipc_int {
+       void (*fn)(void *arg);
+       void *arg;
+};
+
+struct qtnf_shm_ipc_rx_callback {
+       void (*fn)(void *arg, const u8 *buf, size_t len);
+       void *arg;
+};
+
+enum qtnf_shm_ipc_direction {
+       QTNF_SHM_IPC_OUTBOUND           = BIT(0),
+       QTNF_SHM_IPC_INBOUND            = BIT(1),
+};
+
+struct qtnf_shm_ipc {
+       struct qtnf_shm_ipc_region __iomem *shm_region;
+       enum qtnf_shm_ipc_direction direction;
+       size_t tx_packet_count;
+       size_t rx_packet_count;
+
+       size_t tx_timeout_count;
+
+       u8 waiting_for_ack;
+
+       u8 rx_data[QTN_IPC_MAX_DATA_SZ] __aligned(sizeof(u32));
+
+       struct qtnf_shm_ipc_int interrupt;
+       struct qtnf_shm_ipc_rx_callback rx_callback;
+
+       void (*irq_handler)(struct qtnf_shm_ipc *ipc);
+
+       struct workqueue_struct *workqueue;
+       struct work_struct irq_work;
+       struct completion tx_completion;
+};
+
+int qtnf_shm_ipc_init(struct qtnf_shm_ipc *ipc,
+                     enum qtnf_shm_ipc_direction direction,
+                     struct qtnf_shm_ipc_region __iomem *shm_region,
+                     struct workqueue_struct *workqueue,
+                     const struct qtnf_shm_ipc_int *interrupt,
+                     const struct qtnf_shm_ipc_rx_callback *rx_callback);
+void qtnf_shm_ipc_free(struct qtnf_shm_ipc *ipc);
+int qtnf_shm_ipc_send(struct qtnf_shm_ipc *ipc, const u8 *buf, size_t size);
+
+static inline void qtnf_shm_ipc_irq_handler(struct qtnf_shm_ipc *ipc)
+{
+       ipc->irq_handler(ipc);
+}
+
+#endif /* _QTN_FMAC_SHM_IPC_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h
new file mode 100644 (file)
index 0000000..95a5f89
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 _QTN_FMAC_SHM_IPC_DEFS_H_
+#define _QTN_FMAC_SHM_IPC_DEFS_H_
+
+#include <linux/types.h>
+
+#define QTN_IPC_REG_HDR_SZ     (32)
+#define QTN_IPC_REG_SZ         (4096)
+#define QTN_IPC_MAX_DATA_SZ    (QTN_IPC_REG_SZ - QTN_IPC_REG_HDR_SZ)
+
+enum qtnf_shm_ipc_region_flags {
+       QTNF_SHM_IPC_NEW_DATA           = BIT(0),
+       QTNF_SHM_IPC_ACK                = BIT(1),
+};
+
+struct qtnf_shm_ipc_region_header {
+       __le32 flags;
+       __le16 data_len;
+} __packed;
+
+union qtnf_shm_ipc_region_headroom {
+       struct qtnf_shm_ipc_region_header hdr;
+       u8 headroom[QTN_IPC_REG_HDR_SZ];
+} __packed;
+
+struct qtnf_shm_ipc_region {
+       union qtnf_shm_ipc_region_headroom headroom;
+       u8 data[QTN_IPC_MAX_DATA_SZ];
+} __packed;
+
+#endif /* _QTN_FMAC_SHM_IPC_DEFS_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/trans.c b/drivers/net/wireless/quantenna/qtnfmac/trans.c
new file mode 100644 (file)
index 0000000..ccddfeb
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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/types.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+
+#include "core.h"
+#include "commands.h"
+#include "event.h"
+#include "bus.h"
+
+#define QTNF_DEF_SYNC_CMD_TIMEOUT      (5 * HZ)
+
+int qtnf_trans_send_cmd_with_resp(struct qtnf_bus *bus, struct sk_buff *cmd_skb,
+                                 struct sk_buff **response_skb)
+{
+       struct qtnf_cmd_ctl_node *ctl_node = &bus->trans.curr_cmd;
+       struct qlink_cmd *cmd = (void *)cmd_skb->data;
+       int ret = 0;
+       long status;
+       bool resp_not_handled = true;
+       struct sk_buff *resp_skb = NULL;
+
+       if (unlikely(!response_skb))
+               return -EFAULT;
+
+       spin_lock(&ctl_node->resp_lock);
+       ctl_node->seq_num++;
+       cmd->seq_num = cpu_to_le16(ctl_node->seq_num);
+       WARN(ctl_node->resp_skb, "qtnfmac: response skb not empty\n");
+       ctl_node->waiting_for_resp = true;
+       spin_unlock(&ctl_node->resp_lock);
+
+       ret = qtnf_bus_control_tx(bus, cmd_skb);
+       dev_kfree_skb(cmd_skb);
+
+       if (unlikely(ret))
+               goto out;
+
+       status = wait_for_completion_interruptible_timeout(
+                                               &ctl_node->cmd_resp_completion,
+                                               QTNF_DEF_SYNC_CMD_TIMEOUT);
+
+       spin_lock(&ctl_node->resp_lock);
+       resp_not_handled = ctl_node->waiting_for_resp;
+       resp_skb = ctl_node->resp_skb;
+       ctl_node->resp_skb = NULL;
+       ctl_node->waiting_for_resp = false;
+       spin_unlock(&ctl_node->resp_lock);
+
+       if (unlikely(status <= 0)) {
+               if (status == 0) {
+                       ret = -ETIMEDOUT;
+                       pr_err("response timeout\n");
+               } else {
+                       ret = -EINTR;
+                       pr_debug("interrupted\n");
+               }
+       }
+
+       if (unlikely(!resp_skb || resp_not_handled)) {
+               if (!ret)
+                       ret = -EFAULT;
+
+               goto out;
+       }
+
+       ret = 0;
+       *response_skb = resp_skb;
+
+out:
+       if (unlikely(resp_skb && resp_not_handled))
+               dev_kfree_skb(resp_skb);
+
+       return ret;
+}
+
+static void qtnf_trans_signal_cmdresp(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+       struct qtnf_cmd_ctl_node *ctl_node = &bus->trans.curr_cmd;
+       const struct qlink_resp *resp = (const struct qlink_resp *)skb->data;
+       const u16 recvd_seq_num = le16_to_cpu(resp->seq_num);
+
+       spin_lock(&ctl_node->resp_lock);
+
+       if (unlikely(!ctl_node->waiting_for_resp)) {
+               pr_err("unexpected response\n");
+               goto out_err;
+       }
+
+       if (unlikely(recvd_seq_num != ctl_node->seq_num)) {
+               pr_err("seq num mismatch\n");
+               goto out_err;
+       }
+
+       ctl_node->resp_skb = skb;
+       ctl_node->waiting_for_resp = false;
+
+       spin_unlock(&ctl_node->resp_lock);
+
+       complete(&ctl_node->cmd_resp_completion);
+       return;
+
+out_err:
+       spin_unlock(&ctl_node->resp_lock);
+       dev_kfree_skb(skb);
+}
+
+static int qtnf_trans_event_enqueue(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+       struct qtnf_qlink_transport *trans = &bus->trans;
+
+       if (likely(skb_queue_len(&trans->event_queue) <
+                  trans->event_queue_max_len)) {
+               skb_queue_tail(&trans->event_queue, skb);
+               queue_work(bus->workqueue, &bus->event_work);
+       } else {
+               pr_warn("event dropped due to queue overflow\n");
+               dev_kfree_skb(skb);
+               return -1;
+       }
+
+       return 0;
+}
+
+void qtnf_trans_init(struct qtnf_bus *bus)
+{
+       struct qtnf_qlink_transport *trans = &bus->trans;
+
+       init_completion(&trans->curr_cmd.cmd_resp_completion);
+       spin_lock_init(&trans->curr_cmd.resp_lock);
+
+       spin_lock(&trans->curr_cmd.resp_lock);
+       trans->curr_cmd.seq_num = 0;
+       trans->curr_cmd.waiting_for_resp = false;
+       trans->curr_cmd.resp_skb = NULL;
+       spin_unlock(&trans->curr_cmd.resp_lock);
+
+       /* Init event handling related fields */
+       skb_queue_head_init(&trans->event_queue);
+       trans->event_queue_max_len = QTNF_MAX_EVENT_QUEUE_LEN;
+}
+
+static void qtnf_trans_free_events(struct qtnf_bus *bus)
+{
+       struct sk_buff_head *event_queue = &bus->trans.event_queue;
+       struct sk_buff *current_event_skb = skb_dequeue(event_queue);
+
+       while (current_event_skb) {
+               dev_kfree_skb_any(current_event_skb);
+               current_event_skb = skb_dequeue(event_queue);
+       }
+}
+
+void qtnf_trans_free(struct qtnf_bus *bus)
+{
+       if (!bus) {
+               pr_err("invalid bus pointer\n");
+               return;
+       }
+
+       qtnf_trans_free_events(bus);
+}
+
+int qtnf_trans_handle_rx_ctl_packet(struct qtnf_bus *bus, struct sk_buff *skb)
+{
+       const struct qlink_msg_header *header = (void *)skb->data;
+       int ret = -1;
+
+       if (unlikely(skb->len < sizeof(*header))) {
+               pr_warn("packet is too small: %u\n", skb->len);
+               dev_kfree_skb(skb);
+               return -EINVAL;
+       }
+
+       if (unlikely(skb->len != le16_to_cpu(header->len))) {
+               pr_warn("cmd reply length mismatch: %u != %u\n",
+                       skb->len, le16_to_cpu(header->len));
+               dev_kfree_skb(skb);
+               return -EFAULT;
+       }
+
+       switch (le16_to_cpu(header->type)) {
+       case QLINK_MSG_TYPE_CMDRSP:
+               if (unlikely(skb->len < sizeof(struct qlink_cmd))) {
+                       pr_warn("cmd reply too short: %u\n", skb->len);
+                       dev_kfree_skb(skb);
+                       break;
+               }
+
+               qtnf_trans_signal_cmdresp(bus, skb);
+               break;
+       case QLINK_MSG_TYPE_EVENT:
+               if (unlikely(skb->len < sizeof(struct qlink_event))) {
+                       pr_warn("event too short: %u\n", skb->len);
+                       dev_kfree_skb(skb);
+                       break;
+               }
+
+               ret = qtnf_trans_event_enqueue(bus, skb);
+               break;
+       default:
+               pr_warn("unknown packet type: %x\n", le16_to_cpu(header->type));
+               dev_kfree_skb(skb);
+               break;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(qtnf_trans_handle_rx_ctl_packet);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/trans.h b/drivers/net/wireless/quantenna/qtnfmac/trans.h
new file mode 100644 (file)
index 0000000..9a473e0
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 _QTN_FMAC_TRANS_H_
+#define _QTN_FMAC_TRANS_H_
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/mutex.h>
+
+#include "qlink.h"
+
+#define QTNF_CMD_FLAG_RESP_REQ         BIT(0)
+
+#define QTNF_MAX_CMD_BUF_SIZE  2048
+#define QTNF_DEF_CMD_HROOM     4
+
+struct qtnf_bus;
+
+struct qtnf_cmd_ctl_node {
+       struct completion cmd_resp_completion;
+       struct sk_buff *resp_skb;
+       u16 seq_num;
+       bool waiting_for_resp;
+       spinlock_t resp_lock; /* lock for resp_skb & waiting_for_resp changes */
+};
+
+struct qtnf_qlink_transport {
+       struct qtnf_cmd_ctl_node curr_cmd;
+       struct sk_buff_head event_queue;
+       size_t event_queue_max_len;
+};
+
+void qtnf_trans_init(struct qtnf_bus *bus);
+void qtnf_trans_free(struct qtnf_bus *bus);
+
+int qtnf_trans_send_next_cmd(struct qtnf_bus *bus);
+int qtnf_trans_handle_rx_ctl_packet(struct qtnf_bus *bus, struct sk_buff *skb);
+int qtnf_trans_send_cmd_with_resp(struct qtnf_bus *bus,
+                                 struct sk_buff *cmd_skb,
+                                 struct sk_buff **response_skb);
+
+#endif /* _QTN_FMAC_TRANS_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/util.c b/drivers/net/wireless/quantenna/qtnfmac/util.c
new file mode 100644 (file)
index 0000000..ed38e87
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015-2016 Quantenna Communications, Inc.
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 "util.h"
+
+void qtnf_sta_list_init(struct qtnf_sta_list *list)
+{
+       if (unlikely(!list))
+               return;
+
+       INIT_LIST_HEAD(&list->head);
+       atomic_set(&list->size, 0);
+}
+
+struct qtnf_sta_node *qtnf_sta_list_lookup(struct qtnf_sta_list *list,
+                                          const u8 *mac)
+{
+       struct qtnf_sta_node *node;
+
+       if (unlikely(!mac))
+               return NULL;
+
+       list_for_each_entry(node, &list->head, list) {
+               if (ether_addr_equal(node->mac_addr, mac))
+                       return node;
+       }
+
+       return NULL;
+}
+
+struct qtnf_sta_node *qtnf_sta_list_lookup_index(struct qtnf_sta_list *list,
+                                                size_t index)
+{
+       struct qtnf_sta_node *node;
+
+       if (qtnf_sta_list_size(list) <= index)
+               return NULL;
+
+       list_for_each_entry(node, &list->head, list) {
+               if (index-- == 0)
+                       return node;
+       }
+
+       return NULL;
+}
+
+struct qtnf_sta_node *qtnf_sta_list_add(struct qtnf_sta_list *list,
+                                       const u8 *mac)
+{
+       struct qtnf_sta_node *node;
+
+       if (unlikely(!mac))
+               return NULL;
+
+       node = qtnf_sta_list_lookup(list, mac);
+
+       if (node)
+               goto done;
+
+       node = kzalloc(sizeof(*node), GFP_KERNEL);
+       if (unlikely(!node))
+               goto done;
+
+       ether_addr_copy(node->mac_addr, mac);
+       list_add_tail(&node->list, &list->head);
+       atomic_inc(&list->size);
+
+done:
+       return node;
+}
+
+bool qtnf_sta_list_del(struct qtnf_sta_list *list, const u8 *mac)
+{
+       struct qtnf_sta_node *node;
+       bool ret = false;
+
+       node = qtnf_sta_list_lookup(list, mac);
+
+       if (node) {
+               list_del(&node->list);
+               atomic_dec(&list->size);
+               kfree(node);
+               ret = true;
+       }
+
+       return ret;
+}
+
+void qtnf_sta_list_free(struct qtnf_sta_list *list)
+{
+       struct qtnf_sta_node *node, *tmp;
+
+       atomic_set(&list->size, 0);
+
+       list_for_each_entry_safe(node, tmp, &list->head, list) {
+               list_del(&node->list);
+               kfree(node);
+       }
+
+       INIT_LIST_HEAD(&list->head);
+}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/util.h b/drivers/net/wireless/quantenna/qtnfmac/util.h
new file mode 100644 (file)
index 0000000..0359eae
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 Quantenna Communications
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef QTNFMAC_UTIL_H
+#define QTNFMAC_UTIL_H
+
+#include <linux/kernel.h>
+#include "core.h"
+
+void qtnf_sta_list_init(struct qtnf_sta_list *list);
+
+struct qtnf_sta_node *qtnf_sta_list_lookup(struct qtnf_sta_list *list,
+                                          const u8 *mac);
+struct qtnf_sta_node *qtnf_sta_list_lookup_index(struct qtnf_sta_list *list,
+                                                size_t index);
+struct qtnf_sta_node *qtnf_sta_list_add(struct qtnf_sta_list *list,
+                                       const u8 *mac);
+bool qtnf_sta_list_del(struct qtnf_sta_list *list, const u8 *mac);
+
+void qtnf_sta_list_free(struct qtnf_sta_list *list);
+
+static inline size_t qtnf_sta_list_size(const struct qtnf_sta_list *list)
+{
+       return atomic_read(&list->size);
+}
+
+static inline bool qtnf_sta_list_empty(const struct qtnf_sta_list *list)
+{
+       return list_empty(&list->head);
+}
+
+#endif /* QTNFMAC_UTIL_H */
index 19874439ac40fc6419ccee96e062846a972067c8..0bc8b0249c571cd04094c2344289e765cbaa4bfa 100644 (file)
@@ -77,10 +77,11 @@ static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
        mutex_unlock(&rt2x00dev->csr_mutex);
 }
 
-static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
-                              const unsigned int word, u8 *value)
+static u8 rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
+                            const unsigned int word)
 {
        u32 reg;
+       u8 value;
 
        mutex_lock(&rt2x00dev->csr_mutex);
 
@@ -103,9 +104,11 @@ static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
                WAIT_FOR_BBP(rt2x00dev, &reg);
        }
 
-       *value = rt2x00_get_field32(reg, BBPCSR_VALUE);
+       value = rt2x00_get_field32(reg, BBPCSR_VALUE);
 
        mutex_unlock(&rt2x00dev->csr_mutex);
+
+       return value;
 }
 
 static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -138,7 +141,7 @@ static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
        struct rt2x00_dev *rt2x00dev = eeprom->data;
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR21);
 
        eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
        eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
@@ -202,7 +205,7 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, GPIOCSR);
        return rt2x00_get_field32(reg, GPIOCSR_VAL0);
 }
 
@@ -215,7 +218,7 @@ static void rt2400pci_brightness_set(struct led_classdev *led_cdev,
        unsigned int enabled = brightness != LED_OFF;
        u32 reg;
 
-       rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
+       reg = rt2x00mmio_register_read(led->rt2x00dev, LEDCSR);
 
        if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
                rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
@@ -233,7 +236,7 @@ static int rt2400pci_blink_set(struct led_classdev *led_cdev,
            container_of(led_cdev, struct rt2x00_led, led_dev);
        u32 reg;
 
-       rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
+       reg = rt2x00mmio_register_read(led->rt2x00dev, LEDCSR);
        rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
        rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
        rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
@@ -266,7 +269,7 @@ static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
         * Note that the version error will always be dropped
         * since there is no filter for it at this time.
         */
-       rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0);
        rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
                           !(filter_flags & FIF_FCSFAIL));
        rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
@@ -295,14 +298,14 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
                 * Enable beacon config
                 */
                bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
-               rt2x00mmio_register_read(rt2x00dev, BCNCSR1, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, BCNCSR1);
                rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
                rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);
 
                /*
                 * Enable synchronisation.
                 */
-               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
                rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
                rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
        }
@@ -330,35 +333,35 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
        if (changed & BSS_CHANGED_ERP_PREAMBLE) {
                preamble_mask = erp->short_preamble << 3;
 
-               rt2x00mmio_register_read(rt2x00dev, TXCSR1, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXCSR1);
                rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x1ff);
                rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0x13a);
                rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
                rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
                rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, ARCSR2, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, ARCSR2);
                rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
                rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
                rt2x00_set_field32(&reg, ARCSR2_LENGTH,
                                   GET_DURATION(ACK_SIZE, 10));
                rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, ARCSR3, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, ARCSR3);
                rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
                rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
                rt2x00_set_field32(&reg, ARCSR2_LENGTH,
                                   GET_DURATION(ACK_SIZE, 20));
                rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, ARCSR4, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, ARCSR4);
                rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
                rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
                rt2x00_set_field32(&reg, ARCSR2_LENGTH,
                                   GET_DURATION(ACK_SIZE, 55));
                rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, ARCSR5, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, ARCSR5);
                rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
                rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
                rt2x00_set_field32(&reg, ARCSR2_LENGTH,
@@ -370,23 +373,23 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
                rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
 
        if (changed & BSS_CHANGED_ERP_SLOT) {
-               rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR11);
                rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
                rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, CSR18, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR18);
                rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
                rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
                rt2x00mmio_register_write(rt2x00dev, CSR18, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, CSR19, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR19);
                rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
                rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
                rt2x00mmio_register_write(rt2x00dev, CSR19, reg);
        }
 
        if (changed & BSS_CHANGED_BEACON_INT) {
-               rt2x00mmio_register_read(rt2x00dev, CSR12, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR12);
                rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
                                   erp->beacon_int * 16);
                rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
@@ -408,8 +411,8 @@ static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev,
        BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
               ant->tx == ANTENNA_SW_DIVERSITY);
 
-       rt2400pci_bbp_read(rt2x00dev, 4, &r4);
-       rt2400pci_bbp_read(rt2x00dev, 1, &r1);
+       r4 = rt2400pci_bbp_read(rt2x00dev, 4);
+       r1 = rt2400pci_bbp_read(rt2x00dev, 1);
 
        /*
         * Configure the TX antenna.
@@ -495,7 +498,7 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
        /*
         * Clear false CRC during channel switch.
         */
-       rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);
+       rf->rf1 = rt2x00mmio_register_read(rt2x00dev, CNT0);
 }
 
 static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
@@ -508,7 +511,7 @@ static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR11);
        rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
                           libconf->conf->long_frame_max_tx_count);
        rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
@@ -525,7 +528,7 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
        u32 reg;
 
        if (state == STATE_SLEEP) {
-               rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR20);
                rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
                                   (rt2x00dev->beacon_int - 20) * 16);
                rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
@@ -538,7 +541,7 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
                rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
        } else {
-               rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR20);
                rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
                rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
        }
@@ -566,7 +569,7 @@ static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR11);
        rt2x00_set_field32(&reg, CSR11_CWMIN, cw_min);
        rt2x00_set_field32(&reg, CSR11_CWMAX, cw_max);
        rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
@@ -584,13 +587,13 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
        /*
         * Update FCS error count from register.
         */
-       rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CNT0);
        qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
 
        /*
         * Update False CCA count from register.
         */
-       rt2400pci_bbp_read(rt2x00dev, 39, &bbp);
+       bbp = rt2400pci_bbp_read(rt2x00dev, 39);
        qual->false_cca = bbp;
 }
 
@@ -639,12 +642,12 @@ static void rt2400pci_start_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0);
                rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
                rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
                break;
        case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
                rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
                rt2x00_set_field32(&reg, CSR14_TBCN, 1);
                rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
@@ -662,17 +665,17 @@ static void rt2400pci_kick_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_AC_VO:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
                rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
                rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
                break;
        case QID_AC_VI:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
                rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
                rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
                break;
        case QID_ATIM:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
                rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
                rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
                break;
@@ -690,17 +693,17 @@ static void rt2400pci_stop_queue(struct data_queue *queue)
        case QID_AC_VO:
        case QID_AC_VI:
        case QID_ATIM:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
                rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
                rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
                break;
        case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0);
                rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
                rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
                break;
        case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
                rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
                rt2x00_set_field32(&reg, CSR14_TBCN, 0);
                rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
@@ -725,11 +728,11 @@ static bool rt2400pci_get_entry_state(struct queue_entry *entry)
        u32 word;
 
        if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
 
                return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
        } else {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
 
                return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
                        rt2x00_get_field32(word, TXD_W0_VALID));
@@ -743,19 +746,19 @@ static void rt2400pci_clear_entry(struct queue_entry *entry)
        u32 word;
 
        if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 2, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 2);
                rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len);
                rt2x00_desc_write(entry_priv->desc, 2, word);
 
-               rt2x00_desc_read(entry_priv->desc, 1, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 1);
                rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
                rt2x00_desc_write(entry_priv->desc, 1, word);
 
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
                rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
                rt2x00_desc_write(entry_priv->desc, 0, word);
        } else {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
                rt2x00_set_field32(&word, TXD_W0_VALID, 0);
                rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
                rt2x00_desc_write(entry_priv->desc, 0, word);
@@ -770,7 +773,7 @@ static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize registers.
         */
-       rt2x00mmio_register_read(rt2x00dev, TXCSR2, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXCSR2);
        rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
        rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
        rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
@@ -778,36 +781,36 @@ static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
        rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);
 
        entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR3, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXCSR3);
        rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);
 
        entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR5, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXCSR5);
        rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg);
 
        entry_priv = rt2x00dev->atim->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR4, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXCSR4);
        rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg);
 
        entry_priv = rt2x00dev->bcn->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR6, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXCSR6);
        rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, RXCSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RXCSR1);
        rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
        rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
        rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);
 
        entry_priv = rt2x00dev->rx->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, RXCSR2, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RXCSR2);
        rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);
@@ -824,18 +827,18 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00023f20);
        rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002);
 
-       rt2x00mmio_register_read(rt2x00dev, TIMECSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TIMECSR);
        rt2x00_set_field32(&reg, TIMECSR_US_COUNT, 33);
        rt2x00_set_field32(&reg, TIMECSR_US_64_COUNT, 63);
        rt2x00_set_field32(&reg, TIMECSR_BEACON_EXPECT, 0);
        rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR9, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR9);
        rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT,
                           (rt2x00dev->rx->data_size / 128));
        rt2x00mmio_register_write(rt2x00dev, CSR9, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
        rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
        rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
        rt2x00_set_field32(&reg, CSR14_TBCN, 0);
@@ -848,14 +851,14 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
 
        rt2x00mmio_register_write(rt2x00dev, CNT3, 0x3f080000);
 
-       rt2x00mmio_register_read(rt2x00dev, ARCSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, ARCSR0);
        rt2x00_set_field32(&reg, ARCSR0_AR_BBP_DATA0, 133);
        rt2x00_set_field32(&reg, ARCSR0_AR_BBP_ID0, 134);
        rt2x00_set_field32(&reg, ARCSR0_AR_BBP_DATA1, 136);
        rt2x00_set_field32(&reg, ARCSR0_AR_BBP_ID1, 135);
        rt2x00mmio_register_write(rt2x00dev, ARCSR0, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, RXCSR3, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RXCSR3);
        rt2x00_set_field32(&reg, RXCSR3_BBP_ID0, 3); /* Tx power.*/
        rt2x00_set_field32(&reg, RXCSR3_BBP_ID0_VALID, 1);
        rt2x00_set_field32(&reg, RXCSR3_BBP_ID1, 32); /* Signal */
@@ -872,24 +875,24 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00217223);
        rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518);
 
-       rt2x00mmio_register_read(rt2x00dev, MACCSR2, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MACCSR2);
        rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
        rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, RALINKCSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RALINKCSR);
        rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA0, 17);
        rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID0, 154);
        rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA1, 0);
        rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID1, 154);
        rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR1);
        rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
        rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
        rt2x00_set_field32(&reg, CSR1_HOST_READY, 0);
        rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR1);
        rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 0);
        rt2x00_set_field32(&reg, CSR1_HOST_READY, 1);
        rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
@@ -899,8 +902,8 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
         * These registers are cleared on read,
         * so we may pass a useless variable to store the value.
         */
-       rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
-       rt2x00mmio_register_read(rt2x00dev, CNT4, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CNT0);
+       reg = rt2x00mmio_register_read(rt2x00dev, CNT4);
 
        return 0;
 }
@@ -911,7 +914,7 @@ static int rt2400pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
        u8 value;
 
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2400pci_bbp_read(rt2x00dev, 0, &value);
+               value = rt2400pci_bbp_read(rt2x00dev, 0);
                if ((value != 0xff) && (value != 0x00))
                        return 0;
                udelay(REGISTER_BUSY_DELAY);
@@ -947,7 +950,7 @@ static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev)
        rt2400pci_bbp_write(rt2x00dev, 31, 0x00);
 
        for (i = 0; i < EEPROM_BBP_SIZE; i++) {
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+               eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i);
 
                if (eeprom != 0xffff && eeprom != 0x0000) {
                        reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
@@ -974,7 +977,7 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
         * should clear the register to assure a clean state.
         */
        if (state == STATE_RADIO_IRQ_ON) {
-               rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR7);
                rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
        }
 
@@ -984,7 +987,7 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
         */
        spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
        rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
        rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
        rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);
@@ -1037,7 +1040,7 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
 
        put_to_sleep = (state != STATE_AWAKE);
 
-       rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, PWRCSR1);
        rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
        rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);
        rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);
@@ -1050,7 +1053,7 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
         * device has entered the correct state.
         */
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg2);
+               reg2 = rt2x00mmio_register_read(rt2x00dev, PWRCSR1);
                bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
                rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
                if (bbp_state == state && rf_state == state)
@@ -1110,16 +1113,16 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,
        /*
         * Start writing the descriptor words.
         */
-       rt2x00_desc_read(txd, 1, &word);
+       word = rt2x00_desc_read(txd, 1);
        rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
        rt2x00_desc_write(txd, 1, word);
 
-       rt2x00_desc_read(txd, 2, &word);
+       word = rt2x00_desc_read(txd, 2);
        rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, txdesc->length);
        rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, txdesc->length);
        rt2x00_desc_write(txd, 2, word);
 
-       rt2x00_desc_read(txd, 3, &word);
+       word = rt2x00_desc_read(txd, 3);
        rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
        rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);
        rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1);
@@ -1128,7 +1131,7 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,
        rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);
        rt2x00_desc_write(txd, 3, word);
 
-       rt2x00_desc_read(txd, 4, &word);
+       word = rt2x00_desc_read(txd, 4);
        rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW,
                           txdesc->u.plcp.length_low);
        rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);
@@ -1144,7 +1147,7 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,
         * the device, whereby the device may take hold of the TXD before we
         * finished updating it.
         */
-       rt2x00_desc_read(txd, 0, &word);
+       word = rt2x00_desc_read(txd, 0);
        rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
        rt2x00_set_field32(&word, TXD_W0_VALID, 1);
        rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
@@ -1180,7 +1183,7 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
         * Disable beaconing while we are reloading the beacon data,
         * otherwise we might be sending out invalid data.
         */
-       rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
        rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
        rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
 
@@ -1225,10 +1228,10 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry,
        u32 rx_low;
        u32 rx_high;
 
-       rt2x00_desc_read(entry_priv->desc, 0, &word0);
-       rt2x00_desc_read(entry_priv->desc, 2, &word2);
-       rt2x00_desc_read(entry_priv->desc, 3, &word3);
-       rt2x00_desc_read(entry_priv->desc, 4, &word4);
+       word0 = rt2x00_desc_read(entry_priv->desc, 0);
+       word2 = rt2x00_desc_read(entry_priv->desc, 2);
+       word3 = rt2x00_desc_read(entry_priv->desc, 3);
+       word4 = rt2x00_desc_read(entry_priv->desc, 4);
 
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -1282,7 +1285,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
        while (!rt2x00queue_empty(queue)) {
                entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
                entry_priv = entry->priv_data;
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
 
                if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
                    !rt2x00_get_field32(word, TXD_W0_VALID))
@@ -1320,7 +1323,7 @@ static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
         */
        spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
        rt2x00_set_field32(&reg, irq_field, 0);
        rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
 
@@ -1345,7 +1348,7 @@ static void rt2400pci_txstatus_tasklet(unsigned long data)
        if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
                spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-               rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
                rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
                rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
                rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
@@ -1381,7 +1384,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
         * Get the interrupt sources & saved to local variable.
         * Write register value back to clear pending interrupts.
         */
-       rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR7);
        rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
 
        if (!reg)
@@ -1419,7 +1422,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
         */
        spin_lock(&rt2x00dev->irqmask_lock);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
        reg |= mask;
        rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
 
@@ -1440,7 +1443,7 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        u16 word;
        u8 *mac;
 
-       rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR21);
 
        eeprom.data = rt2x00dev;
        eeprom.register_read = rt2400pci_eepromregister_read;
@@ -1461,7 +1464,7 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
        rt2x00lib_set_mac_address(rt2x00dev, mac);
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
        if (word == 0xffff) {
                rt2x00_err(rt2x00dev, "Invalid EEPROM data detected\n");
                return -EINVAL;
@@ -1479,13 +1482,13 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Read EEPROM word for configuration.
         */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
 
        /*
         * Identify RF chipset.
         */
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-       rt2x00mmio_register_read(rt2x00dev, CSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR0);
        rt2x00_set_chip(rt2x00dev, RT2460, value,
                        rt2x00_get_field32(reg, CSR0_REVISION));
 
@@ -1630,7 +1633,7 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
         * Enable rfkill polling by setting GPIO direction of the
         * rfkill switch GPIO pin correctly.
         */
-       rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, GPIOCSR);
        rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
        rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg);
 
@@ -1692,9 +1695,9 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw,
        u64 tsf;
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, CSR17, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR17);
        tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32;
-       rt2x00mmio_register_read(rt2x00dev, CSR16, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR16);
        tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);
 
        return tsf;
@@ -1705,7 +1708,7 @@ static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
        struct rt2x00_dev *rt2x00dev = hw->priv;
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, CSR15, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR15);
        return rt2x00_get_field32(reg, CSR15_BEACON_SENT);
 }
 
index 791434de8052e7ecba344c9a5f379a7b78b1f35e..1ff5434798ecd5d196fd42142e97a0d45311ab77 100644 (file)
@@ -77,10 +77,11 @@ static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,
        mutex_unlock(&rt2x00dev->csr_mutex);
 }
 
-static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
-                              const unsigned int word, u8 *value)
+static u8 rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
+                            const unsigned int word)
 {
        u32 reg;
+       u8 value;
 
        mutex_lock(&rt2x00dev->csr_mutex);
 
@@ -103,9 +104,11 @@ static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
                WAIT_FOR_BBP(rt2x00dev, &reg);
        }
 
-       *value = rt2x00_get_field32(reg, BBPCSR_VALUE);
+       value = rt2x00_get_field32(reg, BBPCSR_VALUE);
 
        mutex_unlock(&rt2x00dev->csr_mutex);
+
+       return value;
 }
 
 static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -138,7 +141,7 @@ static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
        struct rt2x00_dev *rt2x00dev = eeprom->data;
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR21);
 
        eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
        eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
@@ -202,7 +205,7 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, GPIOCSR);
        return rt2x00_get_field32(reg, GPIOCSR_VAL0);
 }
 
@@ -215,7 +218,7 @@ static void rt2500pci_brightness_set(struct led_classdev *led_cdev,
        unsigned int enabled = brightness != LED_OFF;
        u32 reg;
 
-       rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
+       reg = rt2x00mmio_register_read(led->rt2x00dev, LEDCSR);
 
        if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
                rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
@@ -233,7 +236,7 @@ static int rt2500pci_blink_set(struct led_classdev *led_cdev,
            container_of(led_cdev, struct rt2x00_led, led_dev);
        u32 reg;
 
-       rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
+       reg = rt2x00mmio_register_read(led->rt2x00dev, LEDCSR);
        rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
        rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
        rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
@@ -267,7 +270,7 @@ static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,
         * and broadcast frames will always be accepted since
         * there is no filter for it at this time.
         */
-       rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0);
        rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
                           !(filter_flags & FIF_FCSFAIL));
        rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
@@ -300,7 +303,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
                 * Enable beacon config
                 */
                bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
-               rt2x00mmio_register_read(rt2x00dev, BCNCSR1, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, BCNCSR1);
                rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
                rt2x00_set_field32(&reg, BCNCSR1_BEACON_CWMIN, queue->cw_min);
                rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);
@@ -308,7 +311,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
                /*
                 * Enable synchronisation.
                 */
-               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
                rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
                rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
        }
@@ -335,35 +338,35 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
        if (changed & BSS_CHANGED_ERP_PREAMBLE) {
                preamble_mask = erp->short_preamble << 3;
 
-               rt2x00mmio_register_read(rt2x00dev, TXCSR1, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXCSR1);
                rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x162);
                rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0xa2);
                rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
                rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
                rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, ARCSR2, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, ARCSR2);
                rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
                rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
                rt2x00_set_field32(&reg, ARCSR2_LENGTH,
                                   GET_DURATION(ACK_SIZE, 10));
                rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, ARCSR3, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, ARCSR3);
                rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
                rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
                rt2x00_set_field32(&reg, ARCSR2_LENGTH,
                                   GET_DURATION(ACK_SIZE, 20));
                rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, ARCSR4, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, ARCSR4);
                rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
                rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
                rt2x00_set_field32(&reg, ARCSR2_LENGTH,
                                   GET_DURATION(ACK_SIZE, 55));
                rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, ARCSR5, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, ARCSR5);
                rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
                rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
                rt2x00_set_field32(&reg, ARCSR2_LENGTH,
@@ -375,23 +378,23 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
                rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
 
        if (changed & BSS_CHANGED_ERP_SLOT) {
-               rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR11);
                rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
                rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, CSR18, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR18);
                rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
                rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
                rt2x00mmio_register_write(rt2x00dev, CSR18, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, CSR19, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR19);
                rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
                rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
                rt2x00mmio_register_write(rt2x00dev, CSR19, reg);
        }
 
        if (changed & BSS_CHANGED_BEACON_INT) {
-               rt2x00mmio_register_read(rt2x00dev, CSR12, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR12);
                rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
                                   erp->beacon_int * 16);
                rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
@@ -415,9 +418,9 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
        BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
               ant->tx == ANTENNA_SW_DIVERSITY);
 
-       rt2x00mmio_register_read(rt2x00dev, BBPCSR1, &reg);
-       rt2500pci_bbp_read(rt2x00dev, 14, &r14);
-       rt2500pci_bbp_read(rt2x00dev, 2, &r2);
+       reg = rt2x00mmio_register_read(rt2x00dev, BBPCSR1);
+       r14 = rt2500pci_bbp_read(rt2x00dev, 14);
+       r2 = rt2500pci_bbp_read(rt2x00dev, 2);
 
        /*
         * Configure the TX antenna.
@@ -538,7 +541,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
        /*
         * Clear false CRC during channel switch.
         */
-       rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);
+       rf->rf1 = rt2x00mmio_register_read(rt2x00dev, CNT0);
 }
 
 static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev,
@@ -546,7 +549,7 @@ static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev,
 {
        u32 rf3;
 
-       rt2x00_rf_read(rt2x00dev, 3, &rf3);
+       rf3 = rt2x00_rf_read(rt2x00dev, 3);
        rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
        rt2500pci_rf_write(rt2x00dev, 3, rf3);
 }
@@ -556,7 +559,7 @@ static void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR11);
        rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
                           libconf->conf->long_frame_max_tx_count);
        rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
@@ -573,7 +576,7 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
        u32 reg;
 
        if (state == STATE_SLEEP) {
-               rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR20);
                rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
                                   (rt2x00dev->beacon_int - 20) * 16);
                rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
@@ -586,7 +589,7 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
                rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
        } else {
-               rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR20);
                rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
                rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
        }
@@ -622,13 +625,13 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev,
        /*
         * Update FCS error count from register.
         */
-       rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CNT0);
        qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
 
        /*
         * Update False CCA count from register.
         */
-       rt2x00mmio_register_read(rt2x00dev, CNT3, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CNT3);
        qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
 }
 
@@ -728,12 +731,12 @@ static void rt2500pci_start_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0);
                rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
                rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
                break;
        case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
                rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
                rt2x00_set_field32(&reg, CSR14_TBCN, 1);
                rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
@@ -751,17 +754,17 @@ static void rt2500pci_kick_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_AC_VO:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
                rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
                rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
                break;
        case QID_AC_VI:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
                rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
                rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
                break;
        case QID_ATIM:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
                rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
                rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
                break;
@@ -779,17 +782,17 @@ static void rt2500pci_stop_queue(struct data_queue *queue)
        case QID_AC_VO:
        case QID_AC_VI:
        case QID_ATIM:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXCSR0);
                rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
                rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
                break;
        case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, RXCSR0);
                rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
                rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
                break;
        case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
                rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
                rt2x00_set_field32(&reg, CSR14_TBCN, 0);
                rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
@@ -814,11 +817,11 @@ static bool rt2500pci_get_entry_state(struct queue_entry *entry)
        u32 word;
 
        if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
 
                return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
        } else {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
 
                return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
                        rt2x00_get_field32(word, TXD_W0_VALID));
@@ -832,15 +835,15 @@ static void rt2500pci_clear_entry(struct queue_entry *entry)
        u32 word;
 
        if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 1, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 1);
                rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
                rt2x00_desc_write(entry_priv->desc, 1, word);
 
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
                rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
                rt2x00_desc_write(entry_priv->desc, 0, word);
        } else {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
                rt2x00_set_field32(&word, TXD_W0_VALID, 0);
                rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
                rt2x00_desc_write(entry_priv->desc, 0, word);
@@ -855,7 +858,7 @@ static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize registers.
         */
-       rt2x00mmio_register_read(rt2x00dev, TXCSR2, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXCSR2);
        rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
        rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
        rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
@@ -863,36 +866,36 @@ static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
        rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);
 
        entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR3, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXCSR3);
        rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);
 
        entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR5, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXCSR5);
        rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg);
 
        entry_priv = rt2x00dev->atim->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR4, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXCSR4);
        rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg);
 
        entry_priv = rt2x00dev->bcn->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR6, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXCSR6);
        rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, RXCSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RXCSR1);
        rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
        rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
        rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);
 
        entry_priv = rt2x00dev->rx->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, RXCSR2, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RXCSR2);
        rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);
@@ -909,13 +912,13 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00020002);
        rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002);
 
-       rt2x00mmio_register_read(rt2x00dev, TIMECSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TIMECSR);
        rt2x00_set_field32(&reg, TIMECSR_US_COUNT, 33);
        rt2x00_set_field32(&reg, TIMECSR_US_64_COUNT, 63);
        rt2x00_set_field32(&reg, TIMECSR_BEACON_EXPECT, 0);
        rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR9, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR9);
        rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT,
                           rt2x00dev->rx->data_size / 128);
        rt2x00mmio_register_write(rt2x00dev, CSR9, reg);
@@ -923,11 +926,11 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
        /*
         * Always use CWmin and CWmax set in descriptor.
         */
-       rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR11);
        rt2x00_set_field32(&reg, CSR11_CW_SELECT, 0);
        rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
        rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
        rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
        rt2x00_set_field32(&reg, CSR14_TBCN, 0);
@@ -940,7 +943,7 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
 
        rt2x00mmio_register_write(rt2x00dev, CNT3, 0);
 
-       rt2x00mmio_register_read(rt2x00dev, TXCSR8, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXCSR8);
        rt2x00_set_field32(&reg, TXCSR8_BBP_ID0, 10);
        rt2x00_set_field32(&reg, TXCSR8_BBP_ID0_VALID, 1);
        rt2x00_set_field32(&reg, TXCSR8_BBP_ID1, 11);
@@ -951,28 +954,28 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, TXCSR8_BBP_ID3_VALID, 1);
        rt2x00mmio_register_write(rt2x00dev, TXCSR8, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, ARTCSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, ARTCSR0);
        rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_1MBS, 112);
        rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_2MBS, 56);
        rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_5_5MBS, 20);
        rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_11MBS, 10);
        rt2x00mmio_register_write(rt2x00dev, ARTCSR0, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, ARTCSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, ARTCSR1);
        rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_6MBS, 45);
        rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_9MBS, 37);
        rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_12MBS, 33);
        rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_18MBS, 29);
        rt2x00mmio_register_write(rt2x00dev, ARTCSR1, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, ARTCSR2, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, ARTCSR2);
        rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_24MBS, 29);
        rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_36MBS, 25);
        rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_48MBS, 25);
        rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_54MBS, 25);
        rt2x00mmio_register_write(rt2x00dev, ARTCSR2, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, RXCSR3, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RXCSR3);
        rt2x00_set_field32(&reg, RXCSR3_BBP_ID0, 47); /* CCK Signal */
        rt2x00_set_field32(&reg, RXCSR3_BBP_ID0_VALID, 1);
        rt2x00_set_field32(&reg, RXCSR3_BBP_ID1, 51); /* Rssi */
@@ -983,7 +986,7 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, RXCSR3_BBP_ID3_VALID, 1);
        rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, PCICSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, PCICSR);
        rt2x00_set_field32(&reg, PCICSR_BIG_ENDIAN, 0);
        rt2x00_set_field32(&reg, PCICSR_RX_TRESHOLD, 0);
        rt2x00_set_field32(&reg, PCICSR_TX_TRESHOLD, 3);
@@ -1004,11 +1007,11 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00213223);
        rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518);
 
-       rt2x00mmio_register_read(rt2x00dev, MACCSR2, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MACCSR2);
        rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
        rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, RALINKCSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RALINKCSR);
        rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA0, 17);
        rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID0, 26);
        rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_VALID0, 1);
@@ -1021,13 +1024,13 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
 
        rt2x00mmio_register_write(rt2x00dev, TXACKCSR0, 0x00000020);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR1);
        rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
        rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
        rt2x00_set_field32(&reg, CSR1_HOST_READY, 0);
        rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR1);
        rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 0);
        rt2x00_set_field32(&reg, CSR1_HOST_READY, 1);
        rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
@@ -1037,8 +1040,8 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
         * These registers are cleared on read,
         * so we may pass a useless variable to store the value.
         */
-       rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
-       rt2x00mmio_register_read(rt2x00dev, CNT4, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CNT0);
+       reg = rt2x00mmio_register_read(rt2x00dev, CNT4);
 
        return 0;
 }
@@ -1049,7 +1052,7 @@ static int rt2500pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
        u8 value;
 
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2500pci_bbp_read(rt2x00dev, 0, &value);
+               value = rt2500pci_bbp_read(rt2x00dev, 0);
                if ((value != 0xff) && (value != 0x00))
                        return 0;
                udelay(REGISTER_BUSY_DELAY);
@@ -1101,7 +1104,7 @@ static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev)
        rt2500pci_bbp_write(rt2x00dev, 62, 0x10);
 
        for (i = 0; i < EEPROM_BBP_SIZE; i++) {
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+               eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i);
 
                if (eeprom != 0xffff && eeprom != 0x0000) {
                        reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
@@ -1128,7 +1131,7 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
         * should clear the register to assure a clean state.
         */
        if (state == STATE_RADIO_IRQ_ON) {
-               rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR7);
                rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
        }
 
@@ -1138,7 +1141,7 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
         */
        spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
        rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
        rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
        rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);
@@ -1190,7 +1193,7 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
 
        put_to_sleep = (state != STATE_AWAKE);
 
-       rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, PWRCSR1);
        rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
        rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);
        rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);
@@ -1203,7 +1206,7 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
         * device has entered the correct state.
         */
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg2);
+               reg2 = rt2x00mmio_register_read(rt2x00dev, PWRCSR1);
                bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
                rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
                if (bbp_state == state && rf_state == state)
@@ -1263,18 +1266,18 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,
        /*
         * Start writing the descriptor words.
         */
-       rt2x00_desc_read(txd, 1, &word);
+       word = rt2x00_desc_read(txd, 1);
        rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
        rt2x00_desc_write(txd, 1, word);
 
-       rt2x00_desc_read(txd, 2, &word);
+       word = rt2x00_desc_read(txd, 2);
        rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
        rt2x00_set_field32(&word, TXD_W2_AIFS, entry->queue->aifs);
        rt2x00_set_field32(&word, TXD_W2_CWMIN, entry->queue->cw_min);
        rt2x00_set_field32(&word, TXD_W2_CWMAX, entry->queue->cw_max);
        rt2x00_desc_write(txd, 2, word);
 
-       rt2x00_desc_read(txd, 3, &word);
+       word = rt2x00_desc_read(txd, 3);
        rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
        rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service);
        rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW,
@@ -1283,7 +1286,7 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,
                           txdesc->u.plcp.length_high);
        rt2x00_desc_write(txd, 3, word);
 
-       rt2x00_desc_read(txd, 10, &word);
+       word = rt2x00_desc_read(txd, 10);
        rt2x00_set_field32(&word, TXD_W10_RTS,
                           test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
        rt2x00_desc_write(txd, 10, word);
@@ -1293,7 +1296,7 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,
         * the device, whereby the device may take hold of the TXD before we
         * finished updating it.
         */
-       rt2x00_desc_read(txd, 0, &word);
+       word = rt2x00_desc_read(txd, 0);
        rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
        rt2x00_set_field32(&word, TXD_W0_VALID, 1);
        rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
@@ -1332,7 +1335,7 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
         * Disable beaconing while we are reloading the beacon data,
         * otherwise we might be sending out invalid data.
         */
-       rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR14);
        rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
        rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
 
@@ -1368,8 +1371,8 @@ static void rt2500pci_fill_rxdone(struct queue_entry *entry,
        u32 word0;
        u32 word2;
 
-       rt2x00_desc_read(entry_priv->desc, 0, &word0);
-       rt2x00_desc_read(entry_priv->desc, 2, &word2);
+       word0 = rt2x00_desc_read(entry_priv->desc, 0);
+       word2 = rt2x00_desc_read(entry_priv->desc, 2);
 
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -1410,7 +1413,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
        while (!rt2x00queue_empty(queue)) {
                entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
                entry_priv = entry->priv_data;
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
 
                if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
                    !rt2x00_get_field32(word, TXD_W0_VALID))
@@ -1448,7 +1451,7 @@ static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
         */
        spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
        rt2x00_set_field32(&reg, irq_field, 0);
        rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
 
@@ -1473,7 +1476,7 @@ static void rt2500pci_txstatus_tasklet(unsigned long data)
        if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
                spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-               rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
                rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
                rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
                rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
@@ -1509,7 +1512,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
         * Get the interrupt sources & saved to local variable.
         * Write register value back to clear pending interrupts.
         */
-       rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR7);
        rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
 
        if (!reg)
@@ -1547,7 +1550,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
         */
        spin_lock(&rt2x00dev->irqmask_lock);
 
-       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR8);
        reg |= mask;
        rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
 
@@ -1566,7 +1569,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        u16 word;
        u8 *mac;
 
-       rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR21);
 
        eeprom.data = rt2x00dev;
        eeprom.register_read = rt2500pci_eepromregister_read;
@@ -1587,7 +1590,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
        rt2x00lib_set_mac_address(rt2x00dev, mac);
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
                rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
@@ -1603,7 +1606,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
                rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);
@@ -1612,7 +1615,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
                                   DEFAULT_RSSI_OFFSET);
@@ -1633,13 +1636,13 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Read EEPROM word for configuration.
         */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
 
        /*
         * Identify RF chipset.
         */
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-       rt2x00mmio_register_read(rt2x00dev, CSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR0);
        rt2x00_set_chip(rt2x00dev, RT2560, value,
                        rt2x00_get_field32(reg, CSR0_REVISION));
 
@@ -1689,14 +1692,14 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Check if the BBP tuning should be enabled.
         */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
        if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE))
                __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 
        /*
         * Read the RSSI <-> dBm offset information.
         */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET);
        rt2x00dev->rssi_offset =
            rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI);
 
@@ -1955,7 +1958,7 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
         * Enable rfkill polling by setting GPIO direction of the
         * rfkill switch GPIO pin correctly.
         */
-       rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, GPIOCSR);
        rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
        rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg);
 
@@ -1991,9 +1994,9 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw,
        u64 tsf;
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, CSR17, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR17);
        tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32;
-       rt2x00mmio_register_read(rt2x00dev, CSR16, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR16);
        tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);
 
        return tsf;
@@ -2004,7 +2007,7 @@ static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
        struct rt2x00_dev *rt2x00dev = hw->priv;
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, CSR15, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CSR15);
        return rt2x00_get_field32(reg, CSR15_BEACON_SENT);
 }
 
index 0d2670a56c4c5c116ac0c9108ace68bb1bfe261e..529e05999abbbb9307d6e08b90e6127bb1ff6965 100644 (file)
@@ -55,26 +55,24 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
  * If the csr_mutex is already held then the _lock variants must
  * be used instead.
  */
-static void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
-                                          const unsigned int offset,
-                                          u16 *value)
+static u16 rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
+                                  const unsigned int offset)
 {
        __le16 reg;
        rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
                                      USB_VENDOR_REQUEST_IN, offset,
                                      &reg, sizeof(reg));
-       *value = le16_to_cpu(reg);
+       return le16_to_cpu(reg);
 }
 
-static void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
-                                               const unsigned int offset,
-                                               u16 *value)
+static u16 rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
+                                       const unsigned int offset)
 {
        __le16 reg;
        rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
                                       USB_VENDOR_REQUEST_IN, offset,
                                       &reg, sizeof(reg), REGISTER_TIMEOUT);
-       *value = le16_to_cpu(reg);
+       return le16_to_cpu(reg);
 }
 
 static void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
@@ -114,7 +112,7 @@ static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
        unsigned int i;
 
        for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
-               rt2500usb_register_read_lock(rt2x00dev, offset, reg);
+               *reg = rt2500usb_register_read_lock(rt2x00dev, offset);
                if (!rt2x00_get_field16(*reg, field))
                        return 1;
                udelay(REGISTER_BUSY_DELAY);
@@ -155,10 +153,11 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
        mutex_unlock(&rt2x00dev->csr_mutex);
 }
 
-static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
-                              const unsigned int word, u8 *value)
+static u8 rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
+                            const unsigned int word)
 {
        u16 reg;
+       u8 value;
 
        mutex_lock(&rt2x00dev->csr_mutex);
 
@@ -178,12 +177,14 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
                rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
 
                if (WAIT_FOR_BBP(rt2x00dev, &reg))
-                       rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
+                       reg = rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7);
        }
 
-       *value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
+       value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
 
        mutex_unlock(&rt2x00dev->csr_mutex);
+
+       return value;
 }
 
 static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -216,14 +217,10 @@ static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
 }
 
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-static void _rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
-                                    const unsigned int offset,
-                                    u32 *value)
+static u32 _rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
+                                    const unsigned int offset)
 {
-       u16 tmp;
-
-       rt2500usb_register_read(rt2x00dev, offset, &tmp);
-       *value = tmp;
+       return rt2500usb_register_read(rt2x00dev, offset);
 }
 
 static void _rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
@@ -271,7 +268,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
 {
        u16 reg;
 
-       rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, MAC_CSR19);
        return rt2x00_get_field16(reg, MAC_CSR19_VAL7);
 }
 
@@ -284,7 +281,7 @@ static void rt2500usb_brightness_set(struct led_classdev *led_cdev,
        unsigned int enabled = brightness != LED_OFF;
        u16 reg;
 
-       rt2500usb_register_read(led->rt2x00dev, MAC_CSR20, &reg);
+       reg = rt2500usb_register_read(led->rt2x00dev, MAC_CSR20);
 
        if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
                rt2x00_set_field16(&reg, MAC_CSR20_LINK, enabled);
@@ -302,7 +299,7 @@ static int rt2500usb_blink_set(struct led_classdev *led_cdev,
            container_of(led_cdev, struct rt2x00_led, led_dev);
        u16 reg;
 
-       rt2500usb_register_read(led->rt2x00dev, MAC_CSR21, &reg);
+       reg = rt2500usb_register_read(led->rt2x00dev, MAC_CSR21);
        rt2x00_set_field16(&reg, MAC_CSR21_ON_PERIOD, *delay_on);
        rt2x00_set_field16(&reg, MAC_CSR21_OFF_PERIOD, *delay_off);
        rt2500usb_register_write(led->rt2x00dev, MAC_CSR21, reg);
@@ -356,7 +353,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
                 */
                mask = TXRX_CSR0_KEY_ID.bit_mask;
 
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+               reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR0);
                curr_cipher = rt2x00_get_field16(reg, TXRX_CSR0_ALGORITHM);
                reg &= mask;
 
@@ -395,7 +392,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
         * TXRX_CSR0_KEY_ID contains only single-bit fields to indicate
         * a particular key is valid.
         */
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR0);
        rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, crypto->cipher);
        rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
 
@@ -421,7 +418,7 @@ static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev,
         * and broadcast frames will always be accepted since
         * there is no filter for it at this time.
         */
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2);
        rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC,
                           !(filter_flags & FIF_FCSFAIL));
        rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL,
@@ -453,7 +450,7 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
                 * Enable beacon config
                 */
                bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
+               reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR20);
                rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET, bcn_preload >> 6);
                rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW,
                                   2 * (conf->type != NL80211_IFTYPE_STATION));
@@ -462,11 +459,11 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
                /*
                 * Enable synchronisation.
                 */
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
+               reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR18);
                rt2x00_set_field16(&reg, TXRX_CSR18_OFFSET, 0);
                rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
 
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+               reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
                rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, conf->sync);
                rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
        }
@@ -487,7 +484,7 @@ static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
        u16 reg;
 
        if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
+               reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR10);
                rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
                                   !!erp->short_preamble);
                rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
@@ -498,7 +495,7 @@ static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
                                         erp->basic_rates);
 
        if (changed & BSS_CHANGED_BEACON_INT) {
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
+               reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR18);
                rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
                                   erp->beacon_int * 4);
                rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
@@ -526,10 +523,10 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
        BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
               ant->tx == ANTENNA_SW_DIVERSITY);
 
-       rt2500usb_bbp_read(rt2x00dev, 2, &r2);
-       rt2500usb_bbp_read(rt2x00dev, 14, &r14);
-       rt2500usb_register_read(rt2x00dev, PHY_CSR5, &csr5);
-       rt2500usb_register_read(rt2x00dev, PHY_CSR6, &csr6);
+       r2 = rt2500usb_bbp_read(rt2x00dev, 2);
+       r14 = rt2500usb_bbp_read(rt2x00dev, 14);
+       csr5 = rt2500usb_register_read(rt2x00dev, PHY_CSR5);
+       csr6 = rt2500usb_register_read(rt2x00dev, PHY_CSR6);
 
        /*
         * Configure the TX antenna.
@@ -629,7 +626,7 @@ static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
 {
        u32 rf3;
 
-       rt2x00_rf_read(rt2x00dev, 3, &rf3);
+       rf3 = rt2x00_rf_read(rt2x00dev, 3);
        rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
        rt2500usb_rf_write(rt2x00dev, 3, rf3);
 }
@@ -643,7 +640,7 @@ static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev,
        u16 reg;
 
        if (state == STATE_SLEEP) {
-               rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
+               reg = rt2500usb_register_read(rt2x00dev, MAC_CSR18);
                rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON,
                                   rt2x00dev->beacon_int - 20);
                rt2x00_set_field16(&reg, MAC_CSR18_BEACONS_BEFORE_WAKEUP,
@@ -656,7 +653,7 @@ static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 1);
                rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
        } else {
-               rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
+               reg = rt2500usb_register_read(rt2x00dev, MAC_CSR18);
                rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 0);
                rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
        }
@@ -690,13 +687,13 @@ static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev,
        /*
         * Update FCS error count from register.
         */
-       rt2500usb_register_read(rt2x00dev, STA_CSR0, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, STA_CSR0);
        qual->rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR);
 
        /*
         * Update False CCA count from register.
         */
-       rt2500usb_register_read(rt2x00dev, STA_CSR3, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, STA_CSR3);
        qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR);
 }
 
@@ -706,19 +703,19 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
        u16 eeprom;
        u16 value;
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24);
        value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R24_LOW);
        rt2500usb_bbp_write(rt2x00dev, 24, value);
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25);
        value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R25_LOW);
        rt2500usb_bbp_write(rt2x00dev, 25, value);
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61);
        value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R61_LOW);
        rt2500usb_bbp_write(rt2x00dev, 61, value);
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC);
        value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER);
        rt2500usb_bbp_write(rt2x00dev, 17, value);
 
@@ -735,12 +732,12 @@ static void rt2500usb_start_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+               reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2);
                rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 0);
                rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
                break;
        case QID_BEACON:
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+               reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
                rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
                rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
                rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
@@ -758,12 +755,12 @@ static void rt2500usb_stop_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+               reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2);
                rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 1);
                rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
                break;
        case QID_BEACON:
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+               reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
                rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
                rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
                rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
@@ -786,54 +783,54 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00usb_vendor_request_sw(rt2x00dev, USB_SINGLE_WRITE, 0x0308,
                                    0x00f0, REGISTER_TIMEOUT);
 
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR2);
        rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 1);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
 
        rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x1111);
        rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x1e11);
 
-       rt2500usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, MAC_CSR1);
        rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 1);
        rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 1);
        rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 0);
        rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
 
-       rt2500usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, MAC_CSR1);
        rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 0);
        rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 0);
        rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 0);
        rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
 
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR5, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR5);
        rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID0, 13);
        rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID0_VALID, 1);
        rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID1, 12);
        rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID1_VALID, 1);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR5, reg);
 
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR6, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR6);
        rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID0, 10);
        rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID0_VALID, 1);
        rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID1, 11);
        rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID1_VALID, 1);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR6, reg);
 
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR7, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR7);
        rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID0, 7);
        rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID0_VALID, 1);
        rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID1, 6);
        rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID1_VALID, 1);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR7, reg);
 
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR8, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR8);
        rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID0, 5);
        rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID0_VALID, 1);
        rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID1, 0);
        rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID1_VALID, 0);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR8, reg);
 
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
        rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
        rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, 0);
        rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
@@ -846,14 +843,14 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
        if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
                return -EBUSY;
 
-       rt2500usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, MAC_CSR1);
        rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 0);
        rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 0);
        rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 1);
        rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
 
        if (rt2x00_rev(rt2x00dev) >= RT2570_VERSION_C) {
-               rt2500usb_register_read(rt2x00dev, PHY_CSR2, &reg);
+               reg = rt2500usb_register_read(rt2x00dev, PHY_CSR2);
                rt2x00_set_field16(&reg, PHY_CSR2_LNA, 0);
        } else {
                reg = 0;
@@ -867,26 +864,26 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2500usb_register_write(rt2x00dev, MAC_CSR15, 0x01ee);
        rt2500usb_register_write(rt2x00dev, MAC_CSR16, 0x0000);
 
-       rt2500usb_register_read(rt2x00dev, MAC_CSR8, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, MAC_CSR8);
        rt2x00_set_field16(&reg, MAC_CSR8_MAX_FRAME_UNIT,
                           rt2x00dev->rx->data_size);
        rt2500usb_register_write(rt2x00dev, MAC_CSR8, reg);
 
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR0);
        rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, CIPHER_NONE);
        rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
        rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, 0);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
 
-       rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, MAC_CSR18);
        rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON, 90);
        rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
 
-       rt2500usb_register_read(rt2x00dev, PHY_CSR4, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, PHY_CSR4);
        rt2x00_set_field16(&reg, PHY_CSR4_LOW_RF_LE, 1);
        rt2500usb_register_write(rt2x00dev, PHY_CSR4, reg);
 
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR1);
        rt2x00_set_field16(&reg, TXRX_CSR1_AUTO_SEQUENCE, 1);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg);
 
@@ -899,7 +896,7 @@ static int rt2500usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
        u8 value;
 
        for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
-               rt2500usb_bbp_read(rt2x00dev, 0, &value);
+               value = rt2500usb_bbp_read(rt2x00dev, 0);
                if ((value != 0xff) && (value != 0x00))
                        return 0;
                udelay(REGISTER_BUSY_DELAY);
@@ -952,7 +949,7 @@ static int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev)
        rt2500usb_bbp_write(rt2x00dev, 75, 0xff);
 
        for (i = 0; i < EEPROM_BBP_SIZE; i++) {
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+               eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i);
 
                if (eeprom != 0xffff && eeprom != 0x0000) {
                        reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
@@ -1018,7 +1015,7 @@ static int rt2500usb_set_state(struct rt2x00_dev *rt2x00dev,
         * device has entered the correct state.
         */
        for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
-               rt2500usb_register_read(rt2x00dev, MAC_CSR17, &reg2);
+               reg2 = rt2500usb_register_read(rt2x00dev, MAC_CSR17);
                bbp_state = rt2x00_get_field16(reg2, MAC_CSR17_BBP_CURR_STATE);
                rf_state = rt2x00_get_field16(reg2, MAC_CSR17_RF_CURR_STATE);
                if (bbp_state == state && rf_state == state)
@@ -1077,7 +1074,7 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry,
        /*
         * Start writing the descriptor words.
         */
-       rt2x00_desc_read(txd, 0, &word);
+       word = rt2x00_desc_read(txd, 0);
        rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit);
        rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
                           test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
@@ -1095,14 +1092,14 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry,
        rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
        rt2x00_desc_write(txd, 0, word);
 
-       rt2x00_desc_read(txd, 1, &word);
+       word = rt2x00_desc_read(txd, 1);
        rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
        rt2x00_set_field32(&word, TXD_W1_AIFS, entry->queue->aifs);
        rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
        rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
        rt2x00_desc_write(txd, 1, word);
 
-       rt2x00_desc_read(txd, 2, &word);
+       word = rt2x00_desc_read(txd, 2);
        rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
        rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
        rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
@@ -1143,7 +1140,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry,
         * Disable beaconing while we are reloading the beacon data,
         * otherwise we might be sending out invalid data.
         */
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, TXRX_CSR19);
        rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
 
@@ -1250,8 +1247,8 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,
        /*
         * It is now safe to read the descriptor on all architectures.
         */
-       rt2x00_desc_read(rxd, 0, &word0);
-       rt2x00_desc_read(rxd, 1, &word1);
+       word0 = rt2x00_desc_read(rxd, 0);
+       word1 = rt2x00_desc_read(rxd, 1);
 
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -1263,8 +1260,8 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,
                rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY;
 
        if (rxdesc->cipher != CIPHER_NONE) {
-               _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
-               _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]);
+               rxdesc->iv[0] = _rt2x00_desc_read(rxd, 2);
+               rxdesc->iv[1] = _rt2x00_desc_read(rxd, 3);
                rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
 
                /* ICV is located at the end of frame */
@@ -1342,7 +1339,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
        rt2x00lib_set_mac_address(rt2x00dev, mac);
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
                rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
@@ -1358,7 +1355,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
                rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);
@@ -1367,7 +1364,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
                                   DEFAULT_RSSI_OFFSET);
@@ -1376,7 +1373,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                                  word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_BBPTUNE_THRESHOLD, 45);
                rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE, word);
@@ -1387,10 +1384,10 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
         * Switch lower vgc bound to current BBP R17 value,
         * lower the value a bit for better quality.
         */
-       rt2500usb_bbp_read(rt2x00dev, 17, &bbp);
+       bbp = rt2500usb_bbp_read(rt2x00dev, 17);
        bbp -= 6;
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40);
                rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
@@ -1401,7 +1398,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_LOW, 0x48);
                rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);
@@ -1409,7 +1406,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_LOW, 0x40);
                rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_HIGH, 0x80);
@@ -1417,7 +1414,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r24: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_LOW, 0x40);
                rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_HIGH, 0x50);
@@ -1425,7 +1422,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r25: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_LOW, 0x60);
                rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_HIGH, 0x6d);
@@ -1445,13 +1442,13 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Read EEPROM word for configuration.
         */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
 
        /*
         * Identify RF chipset.
         */
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-       rt2500usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, MAC_CSR0);
        rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
 
        if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) {
@@ -1511,7 +1508,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Read the RSSI <-> dBm offset information.
         */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET);
        rt2x00dev->rssi_offset =
            rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI);
 
@@ -1776,7 +1773,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
         * Enable rfkill polling by setting GPIO direction of the
         * rfkill switch GPIO pin correctly.
         */
-       rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
+       reg = rt2500usb_register_read(rt2x00dev, MAC_CSR19);
        rt2x00_set_field16(&reg, MAC_CSR19_DIR0, 0);
        rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg);
 
index d11c7b210e8133174b59688994f0c1e9c22c09ad..6e2e760d98b1b94ce03c7bb74fd034e6e0c9b693 100644 (file)
@@ -110,10 +110,10 @@ static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
        mutex_unlock(&rt2x00dev->csr_mutex);
 }
 
-static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev,
-                           const unsigned int word, u8 *value)
+static u8 rt2800_bbp_read(struct rt2x00_dev *rt2x00dev, const unsigned int word)
 {
        u32 reg;
+       u8 value;
 
        mutex_lock(&rt2x00dev->csr_mutex);
 
@@ -137,9 +137,11 @@ static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev,
                WAIT_FOR_BBP(rt2x00dev, &reg);
        }
 
-       *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE);
+       value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE);
 
        mutex_unlock(&rt2x00dev->csr_mutex);
+
+       return value;
 }
 
 static void rt2800_rfcsr_write(struct rt2x00_dev *rt2x00dev,
@@ -203,10 +205,11 @@ static void rt2800_rfcsr_write_dccal(struct rt2x00_dev *rt2x00dev,
        rt2800_rfcsr_write_bank(rt2x00dev, 7, reg, value);
 }
 
-static void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,
-                             const unsigned int word, u8 *value)
+static u8 rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,
+                           const unsigned int word)
 {
        u32 reg;
+       u8 value;
 
        mutex_lock(&rt2x00dev->csr_mutex);
 
@@ -232,7 +235,7 @@ static void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,
                        WAIT_FOR_RFCSR_MT7620(rt2x00dev, &reg);
                }
 
-               *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA_MT7620);
+               value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA_MT7620);
                break;
 
        default:
@@ -247,17 +250,19 @@ static void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,
                        WAIT_FOR_RFCSR(rt2x00dev, &reg);
                }
 
-               *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);
+               value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);
                break;
        }
 
        mutex_unlock(&rt2x00dev->csr_mutex);
+
+       return value;
 }
 
-static void rt2800_rfcsr_read_bank(struct rt2x00_dev *rt2x00dev, const u8 bank,
-                                  const unsigned int reg, u8 *value)
+static u8 rt2800_rfcsr_read_bank(struct rt2x00_dev *rt2x00dev, const u8 bank,
+                                const unsigned int reg)
 {
-       rt2800_rfcsr_read(rt2x00dev, (reg | (bank << 6)), value);
+       return rt2800_rfcsr_read(rt2x00dev, (reg | (bank << 6)));
 }
 
 static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -405,13 +410,13 @@ static void *rt2800_eeprom_addr(struct rt2x00_dev *rt2x00dev,
        return rt2x00_eeprom_addr(rt2x00dev, index);
 }
 
-static void rt2800_eeprom_read(struct rt2x00_dev *rt2x00dev,
-                              const enum rt2800_eeprom_word word, u16 *data)
+static u16 rt2800_eeprom_read(struct rt2x00_dev *rt2x00dev,
+                             const enum rt2800_eeprom_word word)
 {
        unsigned int index;
 
        index = rt2800_eeprom_word_index(rt2x00dev, word);
-       rt2x00_eeprom_read(rt2x00dev, index, data);
+       return rt2x00_eeprom_read(rt2x00dev, index);
 }
 
 static void rt2800_eeprom_write(struct rt2x00_dev *rt2x00dev,
@@ -423,15 +428,14 @@ static void rt2800_eeprom_write(struct rt2x00_dev *rt2x00dev,
        rt2x00_eeprom_write(rt2x00dev, index, data);
 }
 
-static void rt2800_eeprom_read_from_array(struct rt2x00_dev *rt2x00dev,
-                                         const enum rt2800_eeprom_word array,
-                                         unsigned int offset,
-                                         u16 *data)
+static u16 rt2800_eeprom_read_from_array(struct rt2x00_dev *rt2x00dev,
+                                        const enum rt2800_eeprom_word array,
+                                        unsigned int offset)
 {
        unsigned int index;
 
        index = rt2800_eeprom_word_index(rt2x00dev, array);
-       rt2x00_eeprom_read(rt2x00dev, index + offset, data);
+       return rt2x00_eeprom_read(rt2x00dev, index + offset);
 }
 
 static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
@@ -439,7 +443,7 @@ static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
        u32 reg;
        int i, count;
 
-       rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+       reg = rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL);
        rt2x00_set_field32(&reg, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
        rt2x00_set_field32(&reg, FRC_WL_ANT_SET, 1);
        rt2x00_set_field32(&reg, WLAN_CLK_EN, 0);
@@ -454,7 +458,7 @@ static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
                 * Check PLL_LD & XTAL_RDY.
                 */
                for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-                       rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
+                       reg = rt2800_register_read(rt2x00dev, CMB_CTRL);
                        if (rt2x00_get_field32(reg, PLL_LD) &&
                            rt2x00_get_field32(reg, XTAL_RDY))
                                break;
@@ -477,7 +481,7 @@ static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
                        count = 0;
                }
 
-               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+               reg = rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL);
                rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 0);
                rt2x00_set_field32(&reg, WLAN_CLK_EN, 1);
                rt2x00_set_field32(&reg, WLAN_RESET, 1);
@@ -532,7 +536,7 @@ int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev)
        u32 reg;
 
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+               reg = rt2800_register_read(rt2x00dev, MAC_CSR0);
                if (reg && reg != ~0)
                        return 0;
                msleep(1);
@@ -553,7 +557,7 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
         * before timing out.
         */
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+               reg = rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG);
                if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
                    !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
                        return 0;
@@ -570,7 +574,7 @@ void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
 
-       rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG);
        rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
        rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
        rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
@@ -720,7 +724,7 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
                    rt2x00_rt(rt2x00dev, RT3572) ||
                    rt2x00_rt(rt2x00dev, RT5390) ||
                    rt2x00_rt(rt2x00dev, RT5392)) {
-                       rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
+                       reg = rt2800_register_read(rt2x00dev, AUX_CTRL);
                        rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
                        rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
                        rt2800_register_write(rt2x00dev, AUX_CTRL, reg);
@@ -739,7 +743,7 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
         * Wait for device to stabilize.
         */
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+               reg = rt2800_register_read(rt2x00dev, PBF_SYS_CTRL);
                if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
                        break;
                msleep(1);
@@ -781,7 +785,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
        /*
         * Initialize TX Info descriptor
         */
-       rt2x00_desc_read(txwi, 0, &word);
+       word = rt2x00_desc_read(txwi, 0);
        rt2x00_set_field32(&word, TXWI_W0_FRAG,
                           test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
        rt2x00_set_field32(&word, TXWI_W0_MIMO_PS,
@@ -803,7 +807,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
        rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);
        rt2x00_desc_write(txwi, 0, word);
 
-       rt2x00_desc_read(txwi, 1, &word);
+       word = rt2x00_desc_read(txwi, 1);
        rt2x00_set_field32(&word, TXWI_W1_ACK,
                           test_bit(ENTRY_TXD_ACK, &txdesc->flags));
        rt2x00_set_field32(&word, TXWI_W1_NSEQ,
@@ -843,16 +847,16 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
        u8 offset2;
 
        if (rt2x00dev->curr_band == NL80211_BAND_2GHZ) {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG);
                offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0);
                offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1);
-               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2);
                offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_OFFSET2);
        } else {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A);
                offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET0);
                offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET1);
-               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2);
                offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_OFFSET2);
        }
 
@@ -881,12 +885,12 @@ void rt2800_process_rxwi(struct queue_entry *entry,
        __le32 *rxwi = (__le32 *) entry->skb->data;
        u32 word;
 
-       rt2x00_desc_read(rxwi, 0, &word);
+       word = rt2x00_desc_read(rxwi, 0);
 
        rxdesc->cipher = rt2x00_get_field32(word, RXWI_W0_UDF);
        rxdesc->size = rt2x00_get_field32(word, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
 
-       rt2x00_desc_read(rxwi, 1, &word);
+       word = rt2x00_desc_read(rxwi, 1);
 
        if (rt2x00_get_field32(word, RXWI_W1_SHORT_GI))
                rxdesc->enc_flags |= RX_ENC_FLAG_SHORT_GI;
@@ -907,7 +911,7 @@ void rt2800_process_rxwi(struct queue_entry *entry,
        if (rxdesc->rate_mode == RATE_MODE_CCK)
                rxdesc->signal &= ~0x8;
 
-       rt2x00_desc_read(rxwi, 2, &word);
+       word = rt2x00_desc_read(rxwi, 2);
 
        /*
         * Convert descriptor AGC value to RSSI value.
@@ -968,7 +972,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
         * Obtain the status about this packet.
         */
        txdesc.flags = 0;
-       rt2x00_desc_read(txwi, 0, &word);
+       word = rt2x00_desc_read(txwi, 0);
 
        mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
        ampdu = rt2x00_get_field32(word, TXWI_W0_AMPDU);
@@ -1093,7 +1097,7 @@ static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev)
        /*
         * H/W sends up to MAC_BSSID_DW1_BSS_BCN_NUM + 1 consecutive beacons.
         */
-       rt2800_register_read(rt2x00dev, MAC_BSSID_DW1, &bssid_dw1);
+       bssid_dw1 = rt2800_register_read(rt2x00dev, MAC_BSSID_DW1);
        rt2x00_set_field32(&bssid_dw1, MAC_BSSID_DW1_BSS_BCN_NUM,
                           bcn_num > 0 ? bcn_num - 1 : 0);
        rt2800_register_write(rt2x00dev, MAC_BSSID_DW1, bssid_dw1);
@@ -1112,7 +1116,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
         * Disable beaconing while we are reloading the beacon data,
         * otherwise we might be sending out invalid data.
         */
-       rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, BCN_TIME_CFG);
        orig_reg = reg;
        rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
        rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
@@ -1202,7 +1206,7 @@ void rt2800_clear_beacon(struct queue_entry *entry)
         * Disable beaconing while we are reloading the beacon data,
         * otherwise we might be sending out invalid data.
         */
-       rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &orig_reg);
+       orig_reg = rt2800_register_read(rt2x00dev, BCN_TIME_CFG);
        reg = orig_reg;
        rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
        rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
@@ -1275,10 +1279,10 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
        u32 reg;
 
        if (rt2x00_rt(rt2x00dev, RT3290)) {
-               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+               reg = rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL);
                return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
        } else {
-               rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+               reg = rt2800_register_read(rt2x00dev, GPIO_CTRL);
                return rt2x00_get_field32(reg, GPIO_CTRL_VAL2);
        }
 }
@@ -1303,7 +1307,7 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev,
 
        /* Check for SoC (SOC devices don't support MCU requests) */
        if (rt2x00_is_soc(led->rt2x00dev)) {
-               rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
+               reg = rt2800_register_read(led->rt2x00dev, LED_CFG);
 
                /* Set LED Polarity */
                rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, polarity);
@@ -1392,7 +1396,7 @@ static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
         * The BSS Idx numbers is split in a main value of 3 bits,
         * and a extended field for adding one additional bit to the value.
         */
-       rt2800_register_read(rt2x00dev, offset, &reg);
+       reg = rt2800_register_read(rt2x00dev, offset);
        rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
        rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
                           (bssidx & 0x8) >> 3);
@@ -1410,7 +1414,7 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
        offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
 
        if (crypto->cmd == SET_KEY) {
-               rt2800_register_read(rt2x00dev, offset, &reg);
+               reg = rt2800_register_read(rt2x00dev, offset);
                rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
                                   !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));
                /*
@@ -1426,7 +1430,7 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
                rt2800_register_write(rt2x00dev, offset, reg);
        } else {
                /* Delete the cipher without touching the bssidx */
-               rt2800_register_read(rt2x00dev, offset, &reg);
+               reg = rt2800_register_read(rt2x00dev, offset);
                rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB, 0);
                rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER, 0);
                rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT, 0);
@@ -1482,7 +1486,7 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
 
        offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
 
-       rt2800_register_read(rt2x00dev, offset, &reg);
+       reg = rt2800_register_read(rt2x00dev, offset);
        rt2x00_set_field32(&reg, field,
                           (crypto->cmd == SET_KEY) * crypto->cipher);
        rt2800_register_write(rt2x00dev, offset, reg);
@@ -1548,7 +1552,7 @@ static void rt2800_set_max_psdu_len(struct rt2x00_dev *rt2x00dev)
 
        max_psdu = min(drv_data->max_psdu, i);
 
-       rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, MAX_LEN_CFG);
        rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, max_psdu);
        rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg);
 }
@@ -1640,7 +1644,7 @@ void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
         * and broadcast frames will always be accepted since
         * there is no filter for it at this time.
         */
-       rt2800_register_read(rt2x00dev, RX_FILTER_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, RX_FILTER_CFG);
        rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CRC_ERROR,
                           !(filter_flags & FIF_FCSFAIL));
        rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PHY_ERROR,
@@ -1684,7 +1688,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
                /*
                 * Enable synchronisation.
                 */
-               rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               reg = rt2800_register_read(rt2x00dev, BCN_TIME_CFG);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
                rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
@@ -1692,14 +1696,14 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
                        /*
                         * Tune beacon queue transmit parameters for AP mode
                         */
-                       rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+                       reg = rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG);
                        rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 0);
                        rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 1);
                        rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
                        rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 0);
                        rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
                } else {
-                       rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+                       reg = rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG);
                        rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 4);
                        rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 2);
                        rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
@@ -1818,22 +1822,22 @@ static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,
                gf20_mode = gf40_mode = 1;
 
        /* Update HT protection config */
-       rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, MM20_PROT_CFG);
        rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, mm20_rate);
        rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, mm20_mode);
        rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, MM40_PROT_CFG);
        rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, mm40_rate);
        rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, mm40_mode);
        rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, GF20_PROT_CFG);
        rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, gf20_rate);
        rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, gf20_mode);
        rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, GF40_PROT_CFG);
        rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, gf40_rate);
        rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, gf40_mode);
        rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
@@ -1845,14 +1849,14 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
        u32 reg;
 
        if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-               rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
+               reg = rt2800_register_read(rt2x00dev, AUTO_RSP_CFG);
                rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
                                   !!erp->short_preamble);
                rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
        }
 
        if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-               rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+               reg = rt2800_register_read(rt2x00dev, OFDM_PROT_CFG);
                rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL,
                                   erp->cts_protection ? 2 : 0);
                rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
@@ -1865,18 +1869,18 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
        }
 
        if (changed & BSS_CHANGED_ERP_SLOT) {
-               rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
+               reg = rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG);
                rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME,
                                   erp->slot_time);
                rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
 
-               rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
+               reg = rt2800_register_read(rt2x00dev, XIFS_TIME_CFG);
                rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
                rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
        }
 
        if (changed & BSS_CHANGED_BEACON_INT) {
-               rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               reg = rt2800_register_read(rt2x00dev, BCN_TIME_CFG);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
                                   erp->beacon_int * 16);
                rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
@@ -1893,7 +1897,7 @@ static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev)
        u16 eeprom;
        u8 led_ctrl, led_g_mode, led_r_mode;
 
-       rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+       reg = rt2800_register_read(rt2x00dev, GPIO_SWITCH);
        if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) {
                rt2x00_set_field32(&reg, GPIO_SWITCH_0, 1);
                rt2x00_set_field32(&reg, GPIO_SWITCH_1, 1);
@@ -1903,12 +1907,12 @@ static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev)
        }
        rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
 
-       rt2800_register_read(rt2x00dev, LED_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, LED_CFG);
        led_g_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 3 : 0;
        led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3;
        if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) ||
            led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ);
                led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE);
                if (led_ctrl == 0 || led_ctrl > 0x40) {
                        rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, led_g_mode);
@@ -1929,14 +1933,14 @@ static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,
        u8 gpio_bit3 = (ant == ANTENNA_A) ? 0 : 1;
 
        if (rt2x00_is_pci(rt2x00dev)) {
-               rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
+               reg = rt2800_register_read(rt2x00dev, E2PROM_CSR);
                rt2x00_set_field32(&reg, E2PROM_CSR_DATA_CLOCK, eesk_pin);
                rt2800_register_write(rt2x00dev, E2PROM_CSR, reg);
        } else if (rt2x00_is_usb(rt2x00dev))
                rt2800_mcu_request(rt2x00dev, MCU_ANT_SELECT, 0xff,
                                   eesk_pin, 0);
 
-       rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+       reg = rt2800_register_read(rt2x00dev, GPIO_CTRL);
        rt2x00_set_field32(&reg, GPIO_CTRL_DIR3, 0);
        rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, gpio_bit3);
        rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
@@ -1948,8 +1952,8 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
        u8 r3;
        u16 eeprom;
 
-       rt2800_bbp_read(rt2x00dev, 1, &r1);
-       rt2800_bbp_read(rt2x00dev, 3, &r3);
+       r1 = rt2800_bbp_read(rt2x00dev, 1);
+       r3 = rt2800_bbp_read(rt2x00dev, 3);
 
        if (rt2x00_rt(rt2x00dev, RT3572) &&
            rt2x00_has_cap_bt_coexist(rt2x00dev))
@@ -1983,8 +1987,8 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
                    rt2x00_rt(rt2x00dev, RT3090) ||
                    rt2x00_rt(rt2x00dev, RT3352) ||
                    rt2x00_rt(rt2x00dev, RT3390)) {
-                       rt2800_eeprom_read(rt2x00dev,
-                                          EEPROM_NIC_CONF1, &eeprom);
+                       eeprom = rt2800_eeprom_read(rt2x00dev,
+                                                   EEPROM_NIC_CONF1);
                        if (rt2x00_get_field16(eeprom,
                                                EEPROM_NIC_CONF1_ANT_DIVERSITY))
                                rt2800_set_ant_diversity(rt2x00dev,
@@ -2027,28 +2031,28 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,
        short lna_gain;
 
        if (libconf->rf.channel <= 14) {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_LNA);
                lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG);
        } else if (libconf->rf.channel <= 64) {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_LNA);
                lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
        } else if (libconf->rf.channel <= 128) {
                if (rt2x00_rt(rt2x00dev, RT3593)) {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
+                       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
                        lna_gain = rt2x00_get_field16(eeprom,
                                                      EEPROM_EXT_LNA2_A1);
                } else {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
+                       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2);
                        lna_gain = rt2x00_get_field16(eeprom,
                                                      EEPROM_RSSI_BG2_LNA_A1);
                }
        } else {
                if (rt2x00_rt(rt2x00dev, RT3593)) {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
+                       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
                        lna_gain = rt2x00_get_field16(eeprom,
                                                      EEPROM_EXT_LNA2_A2);
                } else {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
+                       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2);
                        lna_gain = rt2x00_get_field16(eeprom,
                                                      EEPROM_RSSI_A2_LNA_A2);
                }
@@ -2072,7 +2076,7 @@ static void rt2800_freq_cal_mode1(struct rt2x00_dev *rt2x00dev)
        freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE);
        freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND);
 
-       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 17);
        prev_rfcsr = rfcsr;
 
        rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset);
@@ -2174,23 +2178,23 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
 
        rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
 
-       rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
        rt2x00_set_field8(&rfcsr, RFCSR3_K, rf->rf3);
        rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
        rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);
        rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 12);
        rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->default_power1);
        rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 13);
        rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2);
        rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
        rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
        rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD,
                          rt2x00dev->default_ant.rx_chain_num <= 1);
@@ -2203,7 +2207,7 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
                          rt2x00dev->default_ant.tx_chain_num <= 2);
        rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 23);
        rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
        rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
 
@@ -2220,19 +2224,19 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
                }
        }
 
-       rt2800_rfcsr_read(rt2x00dev, 24, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 24);
        rt2x00_set_field8(&rfcsr, RFCSR24_TX_CALIB, calib_tx);
        rt2800_rfcsr_write(rt2x00dev, 24, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 31);
        rt2x00_set_field8(&rfcsr, RFCSR31_RX_CALIB, calib_rx);
        rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 7);
        rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
        rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
        rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
        rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
 
@@ -2262,7 +2266,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
        rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
        rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3);
 
-       rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
        rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);
        if (rf->channel <= 14)
                rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 2);
@@ -2270,14 +2274,14 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 1);
        rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 5, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 5);
        if (rf->channel <= 14)
                rt2x00_set_field8(&rfcsr, RFCSR5_R1, 1);
        else
                rt2x00_set_field8(&rfcsr, RFCSR5_R1, 2);
        rt2800_rfcsr_write(rt2x00dev, 5, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 12);
        if (rf->channel <= 14) {
                rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3);
                rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
@@ -2290,7 +2294,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
        }
        rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 13);
        if (rf->channel <= 14) {
                rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3);
                rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
@@ -2303,7 +2307,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
        }
        rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
        rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
        rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
        rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
@@ -2336,7 +2340,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
        }
        rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 23);
        rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
        rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
 
@@ -2366,7 +2370,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
                rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
                rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
        } else {
-               rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+               rfcsr = rt2800_rfcsr_read(rt2x00dev, 7);
                rt2x00_set_field8(&rfcsr, RFCSR7_BIT2, 1);
                rt2x00_set_field8(&rfcsr, RFCSR7_BIT3, 0);
                rt2x00_set_field8(&rfcsr, RFCSR7_BIT4, 1);
@@ -2399,7 +2403,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
                rt2800_rfcsr_write(rt2x00dev, 29, 0x9f);
        }
 
-       rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+       reg = rt2800_register_read(rt2x00dev, GPIO_CTRL);
        rt2x00_set_field32(&reg, GPIO_CTRL_DIR7, 0);
        if (rf->channel <= 14)
                rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 1);
@@ -2407,7 +2411,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 0);
        rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
 
-       rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 7);
        rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
        rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
 }
@@ -2425,12 +2429,12 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
        const bool txbf_enabled = false; /* TODO */
 
        /* TODO: use TX{0,1,2}FinePowerControl values from EEPROM */
-       rt2800_bbp_read(rt2x00dev, 109, &bbp);
+       bbp = rt2800_bbp_read(rt2x00dev, 109);
        rt2x00_set_field8(&bbp, BBP109_TX0_POWER, 0);
        rt2x00_set_field8(&bbp, BBP109_TX1_POWER, 0);
        rt2800_bbp_write(rt2x00dev, 109, bbp);
 
-       rt2800_bbp_read(rt2x00dev, 110, &bbp);
+       bbp = rt2800_bbp_read(rt2x00dev, 110);
        rt2x00_set_field8(&bbp, BBP110_TX2_POWER, 0);
        rt2800_bbp_write(rt2x00dev, 110, bbp);
 
@@ -2450,11 +2454,11 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
        rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
        rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3 & 0xf);
 
-       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 11);
        rt2x00_set_field8(&rfcsr, RFCSR11_R, (rf->rf2 & 0x3));
        rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 11);
        rt2x00_set_field8(&rfcsr, RFCSR11_PLL_IDOH, 1);
        if (rf->channel <= 14)
                rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 1);
@@ -2462,7 +2466,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 2);
        rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 53, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 53);
        if (rf->channel <= 14) {
                rfcsr = 0;
                rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER,
@@ -2477,7 +2481,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
        }
        rt2800_rfcsr_write(rt2x00dev, 53, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 55, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 55);
        if (rf->channel <= 14) {
                rfcsr = 0;
                rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER,
@@ -2492,7 +2496,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
        }
        rt2800_rfcsr_write(rt2x00dev, 55, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 54, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 54);
        if (rf->channel <= 14) {
                rfcsr = 0;
                rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER,
@@ -2507,7 +2511,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
        }
        rt2800_rfcsr_write(rt2x00dev, 54, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
        rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
        rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
        rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
@@ -2559,7 +2563,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
        /* NOTE: the reference driver does not writes the new value
         * back to RFCSR 32
         */
-       rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 32);
        rt2x00_set_field8(&rfcsr, RFCSR32_TX_AGC_FC, txrx_agc_fc);
 
        if (rf->channel <= 14)
@@ -2568,34 +2572,34 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
                rfcsr = 0x80;
        rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
        rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, txrx_h20m);
        rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, txrx_h20m);
        rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
 
        /* Band selection */
-       rt2800_rfcsr_read(rt2x00dev, 36, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 36);
        if (rf->channel <= 14)
                rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1);
        else
                rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0);
        rt2800_rfcsr_write(rt2x00dev, 36, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 34, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 34);
        if (rf->channel <= 14)
                rfcsr = 0x3c;
        else
                rfcsr = 0x20;
        rt2800_rfcsr_write(rt2x00dev, 34, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 12);
        if (rf->channel <= 14)
                rfcsr = 0x1a;
        else
                rfcsr = 0x12;
        rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
        if (rf->channel >= 1 && rf->channel <= 14)
                rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
        else if (rf->channel >= 36 && rf->channel <= 64)
@@ -2606,7 +2610,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
        rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
        rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
        rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
 
@@ -2620,11 +2624,11 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
                rt2800_rfcsr_write(rt2x00dev, 13, 0x23);
        }
 
-       rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 51);
        rt2x00_set_field8(&rfcsr, RFCSR51_BITS01, 1);
        rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 51);
        if (rf->channel <= 14) {
                rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 5);
                rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 3);
@@ -2634,7 +2638,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
        }
        rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 49);
        if (rf->channel <= 14)
                rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 3);
        else
@@ -2645,11 +2649,11 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
 
        rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 50);
        rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO1_EN, 0);
        rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 57);
        if (rf->channel <= 14)
                rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x1b);
        else
@@ -2665,7 +2669,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
        }
 
        /* Initiate VCO calibration */
-       rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
        if (rf->channel <= 14) {
                rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
        } else {
@@ -2721,11 +2725,11 @@ static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
 
        rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
        rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
-       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 11);
        rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
        rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 49);
        if (info->default_power1 > POWER_BOUND)
                rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);
        else
@@ -2775,7 +2779,7 @@ static void rt2800_config_channel_rf3322(struct rt2x00_dev *rt2x00dev,
 
        rt2800_freq_cal_mode1(rt2x00dev);
 
-       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
        rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
        rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
 
@@ -2806,11 +2810,11 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
 
        rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
        rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
-       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 11);
        rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
        rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 49);
        if (info->default_power1 > POWER_BOUND)
                rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);
        else
@@ -2818,7 +2822,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
        rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
 
        if (rt2x00_rt(rt2x00dev, RT5392)) {
-               rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+               rfcsr = rt2800_rfcsr_read(rt2x00dev, 50);
                if (info->default_power2 > POWER_BOUND)
                        rt2x00_set_field8(&rfcsr, RFCSR50_TX, POWER_BOUND);
                else
@@ -2827,7 +2831,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
                rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
        }
 
-       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
        if (rt2x00_rt(rt2x00dev, RT5392)) {
                rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
                rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
@@ -2911,7 +2915,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
        const bool is_11b = false;
        const bool is_type_ep = false;
 
-       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+       reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
        rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL,
                           (rf->channel > 14 || conf_is_ht40(conf)) ? 5 : 0);
        rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
@@ -2919,13 +2923,13 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
        /* Order of values on rf_channel entry: N, K, mod, R */
        rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1 & 0xff);
 
-       rt2800_rfcsr_read(rt2x00dev,  9, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev,  9);
        rt2x00_set_field8(&rfcsr, RFCSR9_K, rf->rf2 & 0xf);
        rt2x00_set_field8(&rfcsr, RFCSR9_N, (rf->rf1 & 0x100) >> 8);
        rt2x00_set_field8(&rfcsr, RFCSR9_MOD, ((rf->rf3 - 8) & 0x4) >> 2);
        rt2800_rfcsr_write(rt2x00dev, 9, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 11);
        rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf4 - 1);
        rt2x00_set_field8(&rfcsr, RFCSR11_MOD, (rf->rf3 - 8) & 0x3);
        rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
@@ -3093,7 +3097,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
                ep_reg = 0x3;
        }
 
-       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 49);
        if (info->default_power1 > power_bound)
                rt2x00_set_field8(&rfcsr, RFCSR49_TX, power_bound);
        else
@@ -3102,7 +3106,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field8(&rfcsr, RFCSR49_EP, ep_reg);
        rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 50);
        if (info->default_power2 > power_bound)
                rt2x00_set_field8(&rfcsr, RFCSR50_TX, power_bound);
        else
@@ -3111,7 +3115,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field8(&rfcsr, RFCSR50_EP, ep_reg);
        rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
        rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
        rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
 
@@ -3144,7 +3148,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
        rt2800_freq_cal_mode1(rt2x00dev);
 
        /* TODO merge with others */
-       rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
        rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
        rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
 
@@ -3186,7 +3190,7 @@ static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev,
        /* Rdiv setting (set 0x03 if Xtal==20)
         * R13[1:0]
         */
-       rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 13);
        rt2x00_set_field8(&rfcsr, RFCSR13_RDIV_MT7620,
                          rt2800_clk_is_20mhz(rt2x00dev) ? 3 : 0);
        rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
@@ -3195,25 +3199,25 @@ static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev,
         * R20[7:0] in rf->rf1
         * R21[0] always 0
         */
-       rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 20);
        rfcsr = (rf->rf1 & 0x00ff);
        rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 21);
        rt2x00_set_field8(&rfcsr, RFCSR21_BIT1, 0);
        rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
 
        /* K setting (always 0)
         * R16[3:0] (RF PLL freq selection)
         */
-       rt2800_rfcsr_read(rt2x00dev, 16, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 16);
        rt2x00_set_field8(&rfcsr, RFCSR16_RF_PLL_FREQ_SEL_MT7620, 0);
        rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);
 
        /* D setting (always 0)
         * R22[2:0] (D=15, R22[2:0]=<111>)
         */
-       rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 22);
        rt2x00_set_field8(&rfcsr, RFCSR22_FREQPLAN_D_MT7620, 0);
        rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
 
@@ -3222,40 +3226,40 @@ static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev,
         *      R18<7:0> in rf->rf3
         *      R19<1:0> in rf->rf4
         */
-       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 17);
        rfcsr = rf->rf2;
        rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 18);
        rfcsr = rf->rf3;
        rt2800_rfcsr_write(rt2x00dev, 18, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 19, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 19);
        rt2x00_set_field8(&rfcsr, RFCSR19_K, rf->rf4);
        rt2800_rfcsr_write(rt2x00dev, 19, rfcsr);
 
        /* Default: XO=20MHz , SDM mode */
-       rt2800_rfcsr_read(rt2x00dev, 16, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 16);
        rt2x00_set_field8(&rfcsr, RFCSR16_SDM_MODE_MT7620, 0x80);
        rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 21);
        rt2x00_set_field8(&rfcsr, RFCSR21_BIT8, 1);
        rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
        rt2x00_set_field8(&rfcsr, RFCSR1_TX2_EN_MT7620,
                          rt2x00dev->default_ant.tx_chain_num != 1);
        rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 2);
        rt2x00_set_field8(&rfcsr, RFCSR2_TX2_EN_MT7620,
                          rt2x00dev->default_ant.tx_chain_num != 1);
        rt2x00_set_field8(&rfcsr, RFCSR2_RX2_EN_MT7620,
                          rt2x00dev->default_ant.rx_chain_num != 1);
        rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 42, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 42);
        rt2x00_set_field8(&rfcsr, RFCSR42_TX2_EN_MT7620,
                          rt2x00dev->default_ant.tx_chain_num != 1);
        rt2800_rfcsr_write(rt2x00dev, 42, rfcsr);
@@ -3283,7 +3287,7 @@ static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev,
                rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x28);
        }
 
-       rt2800_rfcsr_read(rt2x00dev, 28, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 28);
        rt2x00_set_field8(&rfcsr, RFCSR28_CH11_HT40,
                          conf_is_ht40(conf) && (rf->channel == 11));
        rt2800_rfcsr_write(rt2x00dev, 28, rfcsr);
@@ -3296,36 +3300,36 @@ static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev,
                        rx_agc_fc = drv_data->rx_calibration_bw20;
                        tx_agc_fc = drv_data->tx_calibration_bw20;
                }
-               rt2800_rfcsr_read_bank(rt2x00dev, 5, 6, &rfcsr);
+               rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 5, 6);
                rfcsr &= (~0x3F);
                rfcsr |= rx_agc_fc;
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 6, rfcsr);
-               rt2800_rfcsr_read_bank(rt2x00dev, 5, 7, &rfcsr);
+               rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 5, 7);
                rfcsr &= (~0x3F);
                rfcsr |= rx_agc_fc;
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 7, rfcsr);
-               rt2800_rfcsr_read_bank(rt2x00dev, 7, 6, &rfcsr);
+               rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 7, 6);
                rfcsr &= (~0x3F);
                rfcsr |= rx_agc_fc;
                rt2800_rfcsr_write_bank(rt2x00dev, 7, 6, rfcsr);
-               rt2800_rfcsr_read_bank(rt2x00dev, 7, 7, &rfcsr);
+               rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 7, 7);
                rfcsr &= (~0x3F);
                rfcsr |= rx_agc_fc;
                rt2800_rfcsr_write_bank(rt2x00dev, 7, 7, rfcsr);
 
-               rt2800_rfcsr_read_bank(rt2x00dev, 5, 58, &rfcsr);
+               rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 5, 58);
                rfcsr &= (~0x3F);
                rfcsr |= tx_agc_fc;
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 58, rfcsr);
-               rt2800_rfcsr_read_bank(rt2x00dev, 5, 59, &rfcsr);
+               rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 5, 59);
                rfcsr &= (~0x3F);
                rfcsr |= tx_agc_fc;
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 59, rfcsr);
-               rt2800_rfcsr_read_bank(rt2x00dev, 7, 58, &rfcsr);
+               rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 7, 58);
                rfcsr &= (~0x3F);
                rfcsr |= tx_agc_fc;
                rt2800_rfcsr_write_bank(rt2x00dev, 7, 58, rfcsr);
-               rt2800_rfcsr_read_bank(rt2x00dev, 7, 59, &rfcsr);
+               rfcsr = rt2800_rfcsr_read_bank(rt2x00dev, 7, 59);
                rfcsr &= (~0x3F);
                rfcsr |= tx_agc_fc;
                rt2800_rfcsr_write_bank(rt2x00dev, 7, 59, rfcsr);
@@ -3350,34 +3354,33 @@ static void rt2800_config_alc(struct rt2x00_dev *rt2x00dev,
        if (max_power > 0x2f)
                max_power = 0x2f;
 
-       rt2800_register_read(rt2x00dev, TX_ALC_CFG_0, &reg);
+       reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_0);
        rt2x00_set_field32(&reg, TX_ALC_CFG_0_CH_INIT_0, power_level);
        rt2x00_set_field32(&reg, TX_ALC_CFG_0_CH_INIT_1, power_level);
        rt2x00_set_field32(&reg, TX_ALC_CFG_0_LIMIT_0, max_power);
        rt2x00_set_field32(&reg, TX_ALC_CFG_0_LIMIT_1, max_power);
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_INTERNAL_TX_ALC)) {
                /* init base power by eeprom target power */
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_INIT,
-                                  &target_power);
+               target_power = rt2800_eeprom_read(rt2x00dev,
+                                                 EEPROM_TXPOWER_INIT);
                rt2x00_set_field32(&reg, TX_ALC_CFG_0_CH_INIT_0, target_power);
                rt2x00_set_field32(&reg, TX_ALC_CFG_0_CH_INIT_1, target_power);
        }
        rt2800_register_write(rt2x00dev, TX_ALC_CFG_0, reg);
 
-       rt2800_register_read(rt2x00dev, TX_ALC_CFG_1, &reg);
+       reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_1);
        rt2x00_set_field32(&reg, TX_ALC_CFG_1_TX_TEMP_COMP, 0);
        rt2800_register_write(rt2x00dev, TX_ALC_CFG_1, reg);
 
        /* Save MAC SYS CTRL registers */
-       rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &mac_sys_ctrl);
+       mac_sys_ctrl = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
        /* Disable Tx/Rx */
        rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0);
        /* Check MAC Tx/Rx idle */
        for (i = 0; i < 10000; i++) {
-               rt2800_register_read(rt2x00dev, MAC_STATUS_CFG,
-                                    &mac_status);
+               mac_status = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG);
                if (mac_status & 0x3)
                        usleep_range(50, 200);
                else
@@ -3388,7 +3391,7 @@ static void rt2800_config_alc(struct rt2x00_dev *rt2x00dev,
                rt2x00_warn(rt2x00dev, "Wait MAC Status to MAX !!!\n");
 
        if (chan->center_freq > 2457) {
-               rt2800_bbp_read(rt2x00dev, 30, &bbp);
+               bbp = rt2800_bbp_read(rt2x00dev, 30);
                bbp = 0x40;
                rt2800_bbp_write(rt2x00dev, 30, bbp);
                rt2800_rfcsr_write(rt2x00dev, 39, 0);
@@ -3397,7 +3400,7 @@ static void rt2800_config_alc(struct rt2x00_dev *rt2x00dev,
                else
                        rt2800_rfcsr_write(rt2x00dev, 42, 0x7b);
        } else {
-               rt2800_bbp_read(rt2x00dev, 30, &bbp);
+               bbp = rt2800_bbp_read(rt2x00dev, 30);
                bbp = 0x1f;
                rt2800_bbp_write(rt2x00dev, 30, bbp);
                rt2800_rfcsr_write(rt2x00dev, 39, 0x80);
@@ -3418,7 +3421,7 @@ static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev,
        u8 chain, reg;
 
        for (chain = 0; chain < rt2x00dev->default_ant.rx_chain_num; chain++) {
-               rt2800_bbp_read(rt2x00dev, 27, &reg);
+               reg = rt2800_bbp_read(rt2x00dev, 27);
                rt2x00_set_field8(&reg,  BBP27_RX_CHAIN_SEL, chain);
                rt2800_bbp_write(rt2x00dev, 27, reg);
 
@@ -3597,7 +3600,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
            rt2x00_rf(rt2x00dev, RF5372) ||
            rt2x00_rf(rt2x00dev, RF5390) ||
            rt2x00_rf(rt2x00dev, RF5392)) {
-               rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+               rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
                if (rt2x00_rf(rt2x00dev, RF3322)) {
                        rt2x00_set_field8(&rfcsr, RF3322_RFCSR30_TX_H20M,
                                          conf_is_ht40(conf));
@@ -3611,7 +3614,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
                }
                rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
 
-               rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+               rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
                rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
                rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
        }
@@ -3690,7 +3693,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
                        rt2800_bbp_write(rt2x00dev, 75, 0x50);
        }
 
-       rt2800_register_read(rt2x00dev, TX_BAND_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, TX_BAND_CFG);
        rt2x00_set_field32(&reg, TX_BAND_CFG_HT40_MINUS, conf_is_ht40_minus(conf));
        rt2x00_set_field32(&reg, TX_BAND_CFG_A, rf->channel > 14);
        rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
@@ -3699,7 +3702,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
        if (rt2x00_rt(rt2x00dev, RT3572))
                rt2800_rfcsr_write(rt2x00dev, 8, 0);
 
-       rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);
+       tx_pin = rt2800_register_read(rt2x00dev, TX_PIN_CFG);
 
        switch (rt2x00dev->default_ant.tx_chain_num) {
        case 3:
@@ -3765,7 +3768,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
        }
 
        if (rt2x00_rt(rt2x00dev, RT3593)) {
-               rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+               reg = rt2800_register_read(rt2x00dev, GPIO_CTRL);
 
                /* Band selection */
                if (rt2x00_is_usb(rt2x00dev) ||
@@ -3832,11 +3835,11 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
                rt2800_iq_calibrate(rt2x00dev, rf->channel);
        }
 
-       rt2800_bbp_read(rt2x00dev, 4, &bbp);
+       bbp = rt2800_bbp_read(rt2x00dev, 4);
        rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
        rt2800_bbp_write(rt2x00dev, 4, bbp);
 
-       rt2800_bbp_read(rt2x00dev, 3, &bbp);
+       bbp = rt2800_bbp_read(rt2x00dev, 3);
        rt2x00_set_field8(&bbp, BBP3_HT40_MINUS, conf_is_ht40_minus(conf));
        rt2800_bbp_write(rt2x00dev, 3, bbp);
 
@@ -3857,16 +3860,16 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
        /*
         * Clear channel statistic counters
         */
-       rt2800_register_read(rt2x00dev, CH_IDLE_STA, &reg);
-       rt2800_register_read(rt2x00dev, CH_BUSY_STA, &reg);
-       rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &reg);
+       reg = rt2800_register_read(rt2x00dev, CH_IDLE_STA);
+       reg = rt2800_register_read(rt2x00dev, CH_BUSY_STA);
+       reg = rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC);
 
        /*
         * Clear update flag
         */
        if (rt2x00_rt(rt2x00dev, RT3352) ||
            rt2x00_rt(rt2x00dev, RT5350)) {
-               rt2800_bbp_read(rt2x00dev, 49, &bbp);
+               bbp = rt2800_bbp_read(rt2x00dev, 49);
                rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0);
                rt2800_bbp_write(rt2x00dev, 49, bbp);
        }
@@ -3883,7 +3886,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
        /*
         * First check if temperature compensation is supported.
         */
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
        if (!rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC))
                return 0;
 
@@ -3896,62 +3899,62 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
         * Example TSSI bounds  0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00
         */
        if (rt2x00dev->curr_band == NL80211_BAND_2GHZ) {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1);
                tssi_bounds[0] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_BG1_MINUS4);
                tssi_bounds[1] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_BG1_MINUS3);
 
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2);
                tssi_bounds[2] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_BG2_MINUS2);
                tssi_bounds[3] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_BG2_MINUS1);
 
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3);
                tssi_bounds[4] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_BG3_REF);
                tssi_bounds[5] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_BG3_PLUS1);
 
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4);
                tssi_bounds[6] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_BG4_PLUS2);
                tssi_bounds[7] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_BG4_PLUS3);
 
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5);
                tssi_bounds[8] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_BG5_PLUS4);
 
                step = rt2x00_get_field16(eeprom,
                                          EEPROM_TSSI_BOUND_BG5_AGC_STEP);
        } else {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1);
                tssi_bounds[0] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_A1_MINUS4);
                tssi_bounds[1] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_A1_MINUS3);
 
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2);
                tssi_bounds[2] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_A2_MINUS2);
                tssi_bounds[3] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_A2_MINUS1);
 
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3);
                tssi_bounds[4] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_A3_REF);
                tssi_bounds[5] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_A3_PLUS1);
 
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4);
                tssi_bounds[6] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_A4_PLUS2);
                tssi_bounds[7] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_A4_PLUS3);
 
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5);
                tssi_bounds[8] = rt2x00_get_field16(eeprom,
                                        EEPROM_TSSI_BOUND_A5_PLUS4);
 
@@ -3968,7 +3971,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
        /*
         * Read current TSSI (BBP 49).
         */
-       rt2800_bbp_read(rt2x00dev, 49, &current_tssi);
+       current_tssi = rt2800_bbp_read(rt2x00dev, 49);
 
        /*
         * Compare TSSI value (BBP49) with the compensation boundaries
@@ -3997,7 +4000,7 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
        u8 comp_type;
        int comp_value = 0;
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom);
+       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA);
 
        /*
         * HT40 compensation not required.
@@ -4075,13 +4078,13 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
                 * .11b data rate need add additional 4dbm
                 * when calculating eirp txpower.
                 */
-               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                             1, &eeprom);
+               eeprom = rt2800_eeprom_read_from_array(rt2x00dev,
+                                                      EEPROM_TXPOWER_BYRATE,
+                                                      1);
                criterion = rt2x00_get_field16(eeprom,
                                               EEPROM_TXPOWER_BYRATE_RATE0);
 
-               rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER,
-                                  &eeprom);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER);
 
                if (band == NL80211_BAND_2GHZ)
                        eirp_txpower_criterion = rt2x00_get_field16(eeprom,
@@ -4150,8 +4153,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
                offset += 8;
 
        /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset, &eeprom);
+       eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                              offset);
 
        /* CCK 1MBS,2MBS */
        txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4198,8 +4201,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
                           TX_PWR_CFG_0_EXT_OFDM12_CH2, txpower);
 
        /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 1, &eeprom);
+       eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                              offset + 1);
 
        /* OFDM 24MBS,36MBS */
        txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4235,8 +4238,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
                           TX_PWR_CFG_7_OFDM54_CH2, txpower);
 
        /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 2, &eeprom);
+       eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                              offset + 2);
 
        /* MCS 0,1 */
        txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4283,8 +4286,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
                           TX_PWR_CFG_2_EXT_MCS6_CH2, txpower);
 
        /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 3, &eeprom);
+       eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                              offset + 3);
 
        /* MCS 7 */
        txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4331,8 +4334,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
                           TX_PWR_CFG_3_EXT_MCS12_CH2, txpower);
 
        /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 4, &eeprom);
+       eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                              offset + 4);
 
        /* MCS 14 */
        txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4379,8 +4382,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
                           TX_PWR_CFG_5_MCS18_CH2, txpower);
 
        /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 5, &eeprom);
+       eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                              offset + 5);
 
        /* MCS 20,21 */
        txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4416,8 +4419,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
                           TX_PWR_CFG_8_MCS23_CH2, txpower);
 
        /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 6, &eeprom);
+       eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                              offset + 6);
 
        /* STBC, MCS 0,1 */
        txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4460,8 +4463,8 @@ static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
                           txpower);
 
        /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 7, &eeprom);
+       eeprom = rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                              offset + 7);
 
        /* STBC, MCS 7 */
        txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
@@ -4541,8 +4544,9 @@ static void rt2800_config_txpower_rt6352(struct rt2x00_dev *rt2x00dev,
         * board vendors expected when they populated the EEPROM...
         */
        for (i = 0; i < 5; i++) {
-               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                             i * 2, &eeprom);
+               eeprom = rt2800_eeprom_read_from_array(rt2x00dev,
+                                                      EEPROM_TXPOWER_BYRATE,
+                                                      i * 2);
 
                data = eeprom;
 
@@ -4558,8 +4562,9 @@ static void rt2800_config_txpower_rt6352(struct rt2x00_dev *rt2x00dev,
 
                gdata |= (t << 8);
 
-               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                             (i * 2) + 1, &eeprom);
+               eeprom = rt2800_eeprom_read_from_array(rt2x00dev,
+                                                      EEPROM_TXPOWER_BYRATE,
+                                                      (i * 2) + 1);
 
                t = eeprom & 0x3f;
                if (t == 32)
@@ -4601,26 +4606,26 @@ static void rt2800_config_txpower_rt6352(struct rt2x00_dev *rt2x00dev,
 
        /* For OFDM 54MBS use value from OFDM 48MBS */
        pwreg = 0;
-       rt2800_register_read(rt2x00dev, TX_PWR_CFG_1, &reg);
+       reg = rt2800_register_read(rt2x00dev, TX_PWR_CFG_1);
        t = rt2x00_get_field32(reg, TX_PWR_CFG_1B_48MBS);
        rt2x00_set_field32(&pwreg, TX_PWR_CFG_7B_54MBS, t);
 
        /* For MCS 7 use value from MCS 6 */
-       rt2800_register_read(rt2x00dev, TX_PWR_CFG_2, &reg);
+       reg = rt2800_register_read(rt2x00dev, TX_PWR_CFG_2);
        t = rt2x00_get_field32(reg, TX_PWR_CFG_2B_MCS6_MCS7);
        rt2x00_set_field32(&pwreg, TX_PWR_CFG_7B_MCS7, t);
        rt2800_register_write(rt2x00dev, TX_PWR_CFG_7, pwreg);
 
        /* For MCS 15 use value from MCS 14 */
        pwreg = 0;
-       rt2800_register_read(rt2x00dev, TX_PWR_CFG_3, &reg);
+       reg = rt2800_register_read(rt2x00dev, TX_PWR_CFG_3);
        t = rt2x00_get_field32(reg, TX_PWR_CFG_3B_MCS14);
        rt2x00_set_field32(&pwreg, TX_PWR_CFG_8B_MCS15, t);
        rt2800_register_write(rt2x00dev, TX_PWR_CFG_8, pwreg);
 
        /* For STBC MCS 7 use value from STBC MCS 6 */
        pwreg = 0;
-       rt2800_register_read(rt2x00dev, TX_PWR_CFG_4, &reg);
+       reg = rt2800_register_read(rt2x00dev, TX_PWR_CFG_4);
        t = rt2x00_get_field32(reg, TX_PWR_CFG_4B_STBC_MCS6);
        rt2x00_set_field32(&pwreg, TX_PWR_CFG_9B_STBC_MCS7, t);
        rt2800_register_write(rt2x00dev, TX_PWR_CFG_9, pwreg);
@@ -4702,7 +4707,7 @@ static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev,
        } else {
                power_ctrl = 0;
        }
-       rt2800_bbp_read(rt2x00dev, 1, &r1);
+       r1 = rt2800_bbp_read(rt2x00dev, 1);
        rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
        rt2800_bbp_write(rt2x00dev, 1, r1);
 
@@ -4713,11 +4718,12 @@ static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev,
                if (offset > TX_PWR_CFG_4)
                        break;
 
-               rt2800_register_read(rt2x00dev, offset, &reg);
+               reg = rt2800_register_read(rt2x00dev, offset);
 
                /* read the next four txpower values */
-               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                             i, &eeprom);
+               eeprom = rt2800_eeprom_read_from_array(rt2x00dev,
+                                                      EEPROM_TXPOWER_BYRATE,
+                                                      i);
 
                is_rate_b = i ? 0 : 1;
                /*
@@ -4765,8 +4771,9 @@ static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field32(&reg, TX_PWR_CFG_RATE3, txpower);
 
                /* read the next four txpower values */
-               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                             i + 1, &eeprom);
+               eeprom = rt2800_eeprom_read_from_array(rt2x00dev,
+                                                      EEPROM_TXPOWER_BYRATE,
+                                                      i + 1);
 
                is_rate_b = 0;
                /*
@@ -4853,7 +4860,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
         * periodically to adjust the frequency to be precision.
        */
 
-       rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);
+       tx_pin = rt2800_register_read(rt2x00dev, TX_PIN_CFG);
        tx_pin &= TX_PIN_CFG_PA_PE_DISABLE;
        rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
 
@@ -4864,7 +4871,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
        case RF3022:
        case RF3320:
        case RF3052:
-               rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+               rfcsr = rt2800_rfcsr_read(rt2x00dev, 7);
                rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
                rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
                break;
@@ -4879,7 +4886,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
        case RF5390:
        case RF5392:
        case RF5592:
-               rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+               rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
                rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
                rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
                min_sleep = 1000;
@@ -4887,7 +4894,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
        case RF7620:
                rt2800_rfcsr_write(rt2x00dev, 5, 0x40);
                rt2800_rfcsr_write(rt2x00dev, 4, 0x0C);
-               rt2800_rfcsr_read(rt2x00dev, 4, &rfcsr);
+               rfcsr = rt2800_rfcsr_read(rt2x00dev, 4);
                rt2x00_set_field8(&rfcsr, RFCSR4_VCOCAL_EN, 1);
                rt2800_rfcsr_write(rt2x00dev, 4, rfcsr);
                min_sleep = 2000;
@@ -4901,7 +4908,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
        if (min_sleep > 0)
                usleep_range(min_sleep, min_sleep * 2);
 
-       rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);
+       tx_pin = rt2800_register_read(rt2x00dev, TX_PIN_CFG);
        if (rt2x00dev->rf_channel <= 14) {
                switch (rt2x00dev->default_ant.tx_chain_num) {
                case 3:
@@ -4975,7 +4982,7 @@ static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
 
-       rt2800_register_read(rt2x00dev, TX_RTY_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, TX_RTY_CFG);
        rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT,
                           libconf->conf->short_frame_max_tx_count);
        rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT,
@@ -4994,7 +5001,7 @@ static void rt2800_config_ps(struct rt2x00_dev *rt2x00dev,
        if (state == STATE_SLEEP) {
                rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0);
 
-               rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
+               reg = rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG);
                rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5);
                rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE,
                                   libconf->conf->listen_interval - 1);
@@ -5003,7 +5010,7 @@ static void rt2800_config_ps(struct rt2x00_dev *rt2x00dev,
 
                rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
        } else {
-               rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
+               reg = rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG);
                rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
                rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
                rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
@@ -5046,7 +5053,7 @@ void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual)
        /*
         * Update FCS error count from register.
         */
-       rt2800_register_read(rt2x00dev, RX_STA_CNT0, &reg);
+       reg = rt2800_register_read(rt2x00dev, RX_STA_CNT0);
        qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR);
 }
 EXPORT_SYMBOL_GPL(rt2800_link_stats);
@@ -5175,7 +5182,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 
        rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
 
-       rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, BCN_TIME_CFG);
        rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL, 1600);
        rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
        rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, 0);
@@ -5186,43 +5193,43 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 
        rt2800_config_filter(rt2x00dev, FIF_ALLMULTI);
 
-       rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG);
        rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME, 9);
        rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
        rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
 
        if (rt2x00_rt(rt2x00dev, RT3290)) {
-               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+               reg = rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL);
                if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
                        rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
                        rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
                }
 
-               rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
+               reg = rt2800_register_read(rt2x00dev, CMB_CTRL);
                if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
                        rt2x00_set_field32(&reg, LDO0_EN, 1);
                        rt2x00_set_field32(&reg, LDO_BGSEL, 3);
                        rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
                }
 
-               rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
+               reg = rt2800_register_read(rt2x00dev, OSC_CTRL);
                rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
                rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
                rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
                rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
 
-               rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
+               reg = rt2800_register_read(rt2x00dev, COEX_CFG0);
                rt2x00_set_field32(&reg, COEX_CFG_ANT, 0x5e);
                rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
 
-               rt2800_register_read(rt2x00dev, COEX_CFG2, &reg);
+               reg = rt2800_register_read(rt2x00dev, COEX_CFG2);
                rt2x00_set_field32(&reg, BT_COEX_CFG1, 0x00);
                rt2x00_set_field32(&reg, BT_COEX_CFG0, 0x17);
                rt2x00_set_field32(&reg, WL_COEX_CFG1, 0x93);
                rt2x00_set_field32(&reg, WL_COEX_CFG0, 0x7f);
                rt2800_register_write(rt2x00dev, COEX_CFG2, reg);
 
-               rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
+               reg = rt2800_register_read(rt2x00dev, PLL_CTRL);
                rt2x00_set_field32(&reg, PLL_CONTROL, 1);
                rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
        }
@@ -5243,8 +5250,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
                if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
                    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
                    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
-                                          &eeprom);
+                       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
                        if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
                                rt2800_register_write(rt2x00dev, TX_SW_CFG2,
                                                      0x0000002c);
@@ -5279,8 +5285,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
                rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
                rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
                if (rt2x00_rt_rev_lt(rt2x00dev, RT3593, REV_RT3593E)) {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
-                                          &eeprom);
+                       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
                        if (rt2x00_get_field16(eeprom,
                                               EEPROM_NIC_CONF1_DAC_TEST))
                                rt2800_register_write(rt2x00dev, TX_SW_CFG2,
@@ -5319,7 +5324,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
                                      0x3630363A);
                rt2800_register_write(rt2x00dev, TX1_RF_GAIN_CORRECT,
                                      0x3630363A);
-               rt2800_register_read(rt2x00dev, TX_ALC_CFG_1, &reg);
+               reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_1);
                rt2x00_set_field32(&reg, TX_ALC_CFG_1_ROS_BUSY_EN, 0);
                rt2800_register_write(rt2x00dev, TX_ALC_CFG_1, reg);
        } else {
@@ -5327,7 +5332,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
                rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
        }
 
-       rt2800_register_read(rt2x00dev, TX_LINK_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, TX_LINK_CFG);
        rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32);
        rt2x00_set_field32(&reg, TX_LINK_CFG_MFB_ENABLE, 0);
        rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0);
@@ -5338,13 +5343,13 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFS, 0);
        rt2800_register_write(rt2x00dev, TX_LINK_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG);
        rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9);
        rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 32);
        rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10);
        rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, MAX_LEN_CFG);
        rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
        if (rt2x00_is_usb(rt2x00dev)) {
                drv_data->max_psdu = 3;
@@ -5360,7 +5365,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_MPDU, 10);
        rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, LED_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, LED_CFG);
        rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, 70);
        rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, 30);
        rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3);
@@ -5372,7 +5377,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 
        rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f);
 
-       rt2800_register_read(rt2x00dev, TX_RTY_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, TX_RTY_CFG);
        rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT, 2);
        rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT, 2);
        rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_THRE, 2000);
@@ -5381,7 +5386,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1);
        rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, AUTO_RSP_CFG);
        rt2x00_set_field32(&reg, AUTO_RSP_CFG_AUTORESPONDER, 1);
        rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY, 1);
        rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MMODE, 1);
@@ -5391,7 +5396,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0);
        rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, CCK_PROT_CFG);
        rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 3);
        rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_CTRL, 0);
        rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_NAV_SHORT, 1);
@@ -5404,7 +5409,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, 1);
        rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, OFDM_PROT_CFG);
        rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 3);
        rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL, 0);
        rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_NAV_SHORT, 1);
@@ -5417,7 +5422,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, 1);
        rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, MM20_PROT_CFG);
        rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, 0x4004);
        rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, 1);
        rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_NAV_SHORT, 1);
@@ -5430,7 +5435,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, 0);
        rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, MM40_PROT_CFG);
        rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
        rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 1);
        rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV_SHORT, 1);
@@ -5443,7 +5448,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, 0);
        rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, GF20_PROT_CFG);
        rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, 0x4004);
        rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, 1);
        rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_NAV_SHORT, 1);
@@ -5456,7 +5461,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, 0);
        rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, GF40_PROT_CFG);
        rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, 0x4084);
        rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, 1);
        rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_NAV_SHORT, 1);
@@ -5472,7 +5477,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        if (rt2x00_is_usb(rt2x00dev)) {
                rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
 
-               rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+               reg = rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG);
                rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
                rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
                rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
@@ -5489,7 +5494,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
         * The legacy driver also sets TXOP_CTRL_CFG_RESERVED_TRUN_EN to 1
         * although it is reserved.
         */
-       rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG);
        rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TIMEOUT_TRUN_EN, 1);
        rt2x00_set_field32(&reg, TXOP_CTRL_CFG_AC_TRUN_EN, 1);
        rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN, 1);
@@ -5505,7 +5510,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
        rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
 
-       rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, TX_RTS_CFG);
        rt2x00_set_field32(&reg, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 7);
        rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES,
                           IEEE80211_MAX_RTS_THRESHOLD);
@@ -5521,7 +5526,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
         * connection problems with 11g + CTS protection. Hence, use the same
         * defaults as the Ralink driver: 16 for both, CCK and OFDM SIFS.
         */
-       rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, XIFS_TIME_CFG);
        rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, 16);
        rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, 16);
        rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4);
@@ -5551,16 +5556,16 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
                rt2800_clear_beacon_register(rt2x00dev, i);
 
        if (rt2x00_is_usb(rt2x00dev)) {
-               rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
+               reg = rt2800_register_read(rt2x00dev, US_CYC_CNT);
                rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 30);
                rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
        } else if (rt2x00_is_pcie(rt2x00dev)) {
-               rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
+               reg = rt2800_register_read(rt2x00dev, US_CYC_CNT);
                rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 125);
                rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
        }
 
-       rt2800_register_read(rt2x00dev, HT_FBK_CFG0, &reg);
+       reg = rt2800_register_read(rt2x00dev, HT_FBK_CFG0);
        rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS0FBK, 0);
        rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS1FBK, 0);
        rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS2FBK, 1);
@@ -5571,7 +5576,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS7FBK, 6);
        rt2800_register_write(rt2x00dev, HT_FBK_CFG0, reg);
 
-       rt2800_register_read(rt2x00dev, HT_FBK_CFG1, &reg);
+       reg = rt2800_register_read(rt2x00dev, HT_FBK_CFG1);
        rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS8FBK, 8);
        rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS9FBK, 8);
        rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS10FBK, 9);
@@ -5582,7 +5587,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS15FBK, 14);
        rt2800_register_write(rt2x00dev, HT_FBK_CFG1, reg);
 
-       rt2800_register_read(rt2x00dev, LG_FBK_CFG0, &reg);
+       reg = rt2800_register_read(rt2x00dev, LG_FBK_CFG0);
        rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS0FBK, 8);
        rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS1FBK, 8);
        rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS2FBK, 9);
@@ -5593,7 +5598,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS7FBK, 14);
        rt2800_register_write(rt2x00dev, LG_FBK_CFG0, reg);
 
-       rt2800_register_read(rt2x00dev, LG_FBK_CFG1, &reg);
+       reg = rt2800_register_read(rt2x00dev, LG_FBK_CFG1);
        rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS0FBK, 0);
        rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS1FBK, 0);
        rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS2FBK, 1);
@@ -5603,7 +5608,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        /*
         * Do not force the BA window size, we use the TXWI to set it
         */
-       rt2800_register_read(rt2x00dev, AMPDU_BA_WINSIZE, &reg);
+       reg = rt2800_register_read(rt2x00dev, AMPDU_BA_WINSIZE);
        rt2x00_set_field32(&reg, AMPDU_BA_WINSIZE_FORCE_WINSIZE_ENABLE, 0);
        rt2x00_set_field32(&reg, AMPDU_BA_WINSIZE_FORCE_WINSIZE, 0);
        rt2800_register_write(rt2x00dev, AMPDU_BA_WINSIZE, reg);
@@ -5613,24 +5618,24 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
         * These registers are cleared on read,
         * so we may pass a useless variable to store the value.
         */
-       rt2800_register_read(rt2x00dev, RX_STA_CNT0, &reg);
-       rt2800_register_read(rt2x00dev, RX_STA_CNT1, &reg);
-       rt2800_register_read(rt2x00dev, RX_STA_CNT2, &reg);
-       rt2800_register_read(rt2x00dev, TX_STA_CNT0, &reg);
-       rt2800_register_read(rt2x00dev, TX_STA_CNT1, &reg);
-       rt2800_register_read(rt2x00dev, TX_STA_CNT2, &reg);
+       reg = rt2800_register_read(rt2x00dev, RX_STA_CNT0);
+       reg = rt2800_register_read(rt2x00dev, RX_STA_CNT1);
+       reg = rt2800_register_read(rt2x00dev, RX_STA_CNT2);
+       reg = rt2800_register_read(rt2x00dev, TX_STA_CNT0);
+       reg = rt2800_register_read(rt2x00dev, TX_STA_CNT1);
+       reg = rt2800_register_read(rt2x00dev, TX_STA_CNT2);
 
        /*
         * Setup leadtime for pre tbtt interrupt to 6ms
         */
-       rt2800_register_read(rt2x00dev, INT_TIMER_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, INT_TIMER_CFG);
        rt2x00_set_field32(&reg, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4);
        rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg);
 
        /*
         * Set up channel statistics timer
         */
-       rt2800_register_read(rt2x00dev, CH_TIME_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, CH_TIME_CFG);
        rt2x00_set_field32(&reg, CH_TIME_CFG_EIFS_BUSY, 1);
        rt2x00_set_field32(&reg, CH_TIME_CFG_NAV_BUSY, 1);
        rt2x00_set_field32(&reg, CH_TIME_CFG_RX_BUSY, 1);
@@ -5647,7 +5652,7 @@ static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)
        u32 reg;
 
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2800_register_read(rt2x00dev, MAC_STATUS_CFG, &reg);
+               reg = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG);
                if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY))
                        return 0;
 
@@ -5672,7 +5677,7 @@ static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
        msleep(1);
 
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2800_bbp_read(rt2x00dev, 0, &value);
+               value = rt2800_bbp_read(rt2x00dev, 0);
                if ((value != 0xff) && (value != 0x00))
                        return 0;
                udelay(REGISTER_BUSY_DELAY);
@@ -5686,7 +5691,7 @@ static void rt2800_bbp4_mac_if_ctrl(struct rt2x00_dev *rt2x00dev)
 {
        u8 value;
 
-       rt2800_bbp_read(rt2x00dev, 4, &value);
+       value = rt2800_bbp_read(rt2x00dev, 4);
        rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
        rt2800_bbp_write(rt2x00dev, 4, value);
 }
@@ -5743,8 +5748,8 @@ static void rt2800_disable_unused_dac_adc(struct rt2x00_dev *rt2x00dev)
        u16 eeprom;
        u8 value;
 
-       rt2800_bbp_read(rt2x00dev, 138, &value);
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+       value = rt2800_bbp_read(rt2x00dev, 138);
+       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0);
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
                value |= 0x20;
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
@@ -5927,12 +5932,12 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev)
        rt2800_bbp_write(rt2x00dev, 155, 0x3b);
        rt2800_bbp_write(rt2x00dev, 253, 0x04);
 
-       rt2800_bbp_read(rt2x00dev, 47, &value);
+       value = rt2800_bbp_read(rt2x00dev, 47);
        rt2x00_set_field8(&value, BBP47_TSSI_ADC6, 1);
        rt2800_bbp_write(rt2x00dev, 47, value);
 
        /* Use 5-bit ADC for Acquisition and 8-bit ADC for data */
-       rt2800_bbp_read(rt2x00dev, 3, &value);
+       value = rt2800_bbp_read(rt2x00dev, 3);
        rt2x00_set_field8(&value, BBP3_ADC_MODE_SWITCH, 1);
        rt2x00_set_field8(&value, BBP3_ADC_INIT_MODE, 1);
        rt2800_bbp_write(rt2x00dev, 3, value);
@@ -6191,7 +6196,7 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
 
        rt2800_disable_unused_dac_adc(rt2x00dev);
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
        div_mode = rt2x00_get_field16(eeprom,
                                      EEPROM_NIC_CONF1_ANT_DIVERSITY);
        ant = (div_mode == 3) ? 1 : 0;
@@ -6200,7 +6205,7 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
        if (rt2x00_has_cap_bt_coexist(rt2x00dev)) {
                u32 reg;
 
-               rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+               reg = rt2800_register_read(rt2x00dev, GPIO_CTRL);
                rt2x00_set_field32(&reg, GPIO_CTRL_DIR3, 0);
                rt2x00_set_field32(&reg, GPIO_CTRL_DIR6, 0);
                rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, 0);
@@ -6219,7 +6224,7 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
                rt2800_bbp_write(rt2x00dev, 154, 0); /* Clear previously selected antenna */
        }
 
-       rt2800_bbp_read(rt2x00dev, 152, &value);
+       value = rt2800_bbp_read(rt2x00dev, 152);
        if (ant == 0)
                rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1);
        else
@@ -6237,7 +6242,7 @@ static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev)
 
        rt2800_init_bbp_early(rt2x00dev);
 
-       rt2800_bbp_read(rt2x00dev, 105, &value);
+       value = rt2800_bbp_read(rt2x00dev, 105);
        rt2x00_set_field8(&value, BBP105_MLD,
                          rt2x00dev->default_ant.rx_chain_num == 2);
        rt2800_bbp_write(rt2x00dev, 105, value);
@@ -6277,10 +6282,10 @@ static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev)
 
        rt2800_bbp4_mac_if_ctrl(rt2x00dev);
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
        div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY);
        ant = (div_mode == 3) ? 1 : 0;
-       rt2800_bbp_read(rt2x00dev, 152, &value);
+       value = rt2800_bbp_read(rt2x00dev, 152);
        if (ant == 0) {
                /* Main antenna */
                rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1);
@@ -6291,7 +6296,7 @@ static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev)
        rt2800_bbp_write(rt2x00dev, 152, value);
 
        if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) {
-               rt2800_bbp_read(rt2x00dev, 254, &value);
+               value = rt2800_bbp_read(rt2x00dev, 254);
                rt2x00_set_field8(&value, BBP254_BIT7, 1);
                rt2800_bbp_write(rt2x00dev, 254, value);
        }
@@ -6317,11 +6322,10 @@ static void rt2800_bbp_dcoc_write(struct rt2x00_dev *rt2x00dev,
        rt2800_bbp_write(rt2x00dev, 159, value);
 }
 
-static void rt2800_bbp_dcoc_read(struct rt2x00_dev *rt2x00dev,
-                                const u8 reg, u8 *value)
+static u8 rt2800_bbp_dcoc_read(struct rt2x00_dev *rt2x00dev, const u8 reg)
 {
        rt2800_bbp_write(rt2x00dev, 158, reg);
-       rt2800_bbp_read(rt2x00dev, 159, value);
+       return rt2800_bbp_read(rt2x00dev, 159);
 }
 
 static void rt2800_init_bbp_6352(struct rt2x00_dev *rt2x00dev)
@@ -6329,7 +6333,7 @@ static void rt2800_init_bbp_6352(struct rt2x00_dev *rt2x00dev)
        u8 bbp;
 
        /* Apply Maximum Likelihood Detection (MLD) for 2 stream case */
-       rt2800_bbp_read(rt2x00dev, 105, &bbp);
+       bbp = rt2800_bbp_read(rt2x00dev, 105);
        rt2x00_set_field8(&bbp, BBP105_MLD,
                          rt2x00dev->default_ant.rx_chain_num == 2);
        rt2800_bbp_write(rt2x00dev, 105, bbp);
@@ -6338,7 +6342,7 @@ static void rt2800_init_bbp_6352(struct rt2x00_dev *rt2x00dev)
        rt2800_bbp4_mac_if_ctrl(rt2x00dev);
 
        /* Fix I/Q swap issue */
-       rt2800_bbp_read(rt2x00dev, 1, &bbp);
+       bbp = rt2800_bbp_read(rt2x00dev, 1);
        bbp |= 0x04;
        rt2800_bbp_write(rt2x00dev, 1, bbp);
 
@@ -6578,8 +6582,8 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
        }
 
        for (i = 0; i < EEPROM_BBP_SIZE; i++) {
-               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_BBP_START, i,
-                                             &eeprom);
+               eeprom = rt2800_eeprom_read_from_array(rt2x00dev,
+                                                      EEPROM_BBP_START, i);
 
                if (eeprom != 0xffff && eeprom != 0x0000) {
                        reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
@@ -6593,7 +6597,7 @@ static void rt2800_led_open_drain_enable(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
 
-       rt2800_register_read(rt2x00dev, OPT_14_CSR, &reg);
+       reg = rt2800_register_read(rt2x00dev, OPT_14_CSR);
        rt2x00_set_field32(&reg, OPT_14_CSR_BIT0, 1);
        rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);
 }
@@ -6611,15 +6615,15 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40,
 
        rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);
 
-       rt2800_bbp_read(rt2x00dev, 4, &bbp);
+       bbp = rt2800_bbp_read(rt2x00dev, 4);
        rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);
        rt2800_bbp_write(rt2x00dev, 4, bbp);
 
-       rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 31);
        rt2x00_set_field8(&rfcsr, RFCSR31_RX_H20M, bw40);
        rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 22);
        rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);
        rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
 
@@ -6632,7 +6636,7 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40,
                rt2800_bbp_write(rt2x00dev, 25, 0x90);
                msleep(1);
 
-               rt2800_bbp_read(rt2x00dev, 55, &passband);
+               passband = rt2800_bbp_read(rt2x00dev, 55);
                if (passband)
                        break;
        }
@@ -6646,7 +6650,7 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40,
                rt2800_bbp_write(rt2x00dev, 25, 0x90);
                msleep(1);
 
-               rt2800_bbp_read(rt2x00dev, 55, &stopband);
+               stopband = rt2800_bbp_read(rt2x00dev, 55);
 
                if ((passband - stopband) <= filter_target) {
                        rfcsr24++;
@@ -6668,7 +6672,7 @@ static void rt2800_rf_init_calibration(struct rt2x00_dev *rt2x00dev,
 {
        u8 rfcsr;
 
-       rt2800_rfcsr_read(rt2x00dev, rf_reg, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, rf_reg);
        rt2x00_set_field8(&rfcsr, FIELD8(0x80), 1);
        rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr);
        msleep(1);
@@ -6702,22 +6706,22 @@ static void rt2800_rx_filter_calibration(struct rt2x00_dev *rt2x00dev)
        /*
         * Save BBP 25 & 26 values for later use in channel switching (for 3052)
         */
-       rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25);
-       rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);
+       drv_data->bbp25 = rt2800_bbp_read(rt2x00dev, 25);
+       drv_data->bbp26 = rt2800_bbp_read(rt2x00dev, 26);
 
        /*
         * Set back to initial state
         */
        rt2800_bbp_write(rt2x00dev, 24, 0);
 
-       rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 22);
        rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
        rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
 
        /*
         * Set BBP back to BW20
         */
-       rt2800_bbp_read(rt2x00dev, 4, &bbp);
+       bbp = rt2800_bbp_read(rt2x00dev, 4);
        rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
        rt2800_bbp_write(rt2x00dev, 4, bbp);
 }
@@ -6728,7 +6732,7 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
        u8 min_gain, rfcsr, bbp;
        u16 eeprom;
 
-       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 17);
 
        rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
        if (rt2x00_rt(rt2x00dev, RT3070) ||
@@ -6749,8 +6753,8 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
 
        if (rt2x00_rt(rt2x00dev, RT3090)) {
                /*  Turn off unused DAC1 and ADC1 to reduce power consumption */
-               rt2800_bbp_read(rt2x00dev, 138, &bbp);
-               rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+               bbp = rt2800_bbp_read(rt2x00dev, 138);
+               eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0);
                if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
                        rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0);
                if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
@@ -6759,7 +6763,7 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
        }
 
        if (rt2x00_rt(rt2x00dev, RT3070)) {
-               rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr);
+               rfcsr = rt2800_rfcsr_read(rt2x00dev, 27);
                if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F))
                        rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3);
                else
@@ -6771,7 +6775,7 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
        } else if (rt2x00_rt(rt2x00dev, RT3071) ||
                   rt2x00_rt(rt2x00dev, RT3090) ||
                   rt2x00_rt(rt2x00dev, RT3390)) {
-               rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+               rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
                rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
                rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
                rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
@@ -6779,15 +6783,15 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
                rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
                rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
 
-               rt2800_rfcsr_read(rt2x00dev, 15, &rfcsr);
+               rfcsr = rt2800_rfcsr_read(rt2x00dev, 15);
                rt2x00_set_field8(&rfcsr, RFCSR15_TX_LO2_EN, 0);
                rt2800_rfcsr_write(rt2x00dev, 15, rfcsr);
 
-               rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
+               rfcsr = rt2800_rfcsr_read(rt2x00dev, 20);
                rt2x00_set_field8(&rfcsr, RFCSR20_RX_LO1_EN, 0);
                rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
 
-               rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
+               rfcsr = rt2800_rfcsr_read(rt2x00dev, 21);
                rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0);
                rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
        }
@@ -6799,30 +6803,30 @@ static void rt2800_normal_mode_setup_3593(struct rt2x00_dev *rt2x00dev)
        u8 rfcsr;
        u8 tx_gain;
 
-       rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 50);
        rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO2_EN, 0);
        rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 51);
        tx_gain = rt2x00_get_field8(drv_data->txmixer_gain_24g,
                                    RFCSR17_TXMIXER_GAIN);
        rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, tx_gain);
        rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 38);
        rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0);
        rt2800_rfcsr_write(rt2x00dev, 38, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 39, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 39);
        rt2x00_set_field8(&rfcsr, RFCSR39_RX_LO2_EN, 0);
        rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
        rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
        rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
        rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
 
-       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
        rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
        rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
 
@@ -6835,25 +6839,25 @@ static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev)
        u16 eeprom;
 
        /*  Turn off unused DAC1 and ADC1 to reduce power consumption */
-       rt2800_bbp_read(rt2x00dev, 138, &reg);
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+       reg = rt2800_bbp_read(rt2x00dev, 138);
+       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0);
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
                rt2x00_set_field8(&reg, BBP138_RX_ADC1, 0);
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
                rt2x00_set_field8(&reg, BBP138_TX_DAC1, 1);
        rt2800_bbp_write(rt2x00dev, 138, reg);
 
-       rt2800_rfcsr_read(rt2x00dev, 38, &reg);
+       reg = rt2800_rfcsr_read(rt2x00dev, 38);
        rt2x00_set_field8(&reg, RFCSR38_RX_LO1_EN, 0);
        rt2800_rfcsr_write(rt2x00dev, 38, reg);
 
-       rt2800_rfcsr_read(rt2x00dev, 39, &reg);
+       reg = rt2800_rfcsr_read(rt2x00dev, 39);
        rt2x00_set_field8(&reg, RFCSR39_RX_LO2_EN, 0);
        rt2800_rfcsr_write(rt2x00dev, 39, reg);
 
        rt2800_bbp4_mac_if_ctrl(rt2x00dev);
 
-       rt2800_rfcsr_read(rt2x00dev, 30, &reg);
+       reg = rt2800_rfcsr_read(rt2x00dev, 30);
        rt2x00_set_field8(&reg, RFCSR30_RX_VCM, 2);
        rt2800_rfcsr_write(rt2x00dev, 30, reg);
 }
@@ -6926,7 +6930,7 @@ static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
        rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
 
        if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
-               rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+               reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
                rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
                rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
                rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
@@ -6934,16 +6938,15 @@ static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
                   rt2x00_rt(rt2x00dev, RT3090)) {
                rt2800_rfcsr_write(rt2x00dev, 31, 0x14);
 
-               rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+               rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
                rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
                rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
 
-               rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+               reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
                rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
                if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
                    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
-                                          &eeprom);
+                       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
                        if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
                                rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
                        else
@@ -6951,7 +6954,7 @@ static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
                }
                rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
 
-               rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+               reg = rt2800_register_read(rt2x00dev, GPIO_SWITCH);
                rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
                rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
        }
@@ -7020,7 +7023,7 @@ static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev)
        rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
        rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
 
-       rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 29);
        rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3);
        rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
 
@@ -7166,7 +7169,7 @@ static void rt2800_init_rfcsr_3390(struct rt2x00_dev *rt2x00dev)
        rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
        rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
 
-       rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+       reg = rt2800_register_read(rt2x00dev, GPIO_SWITCH);
        rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
        rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
 
@@ -7218,16 +7221,16 @@ static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev)
        rt2800_rfcsr_write(rt2x00dev, 30, 0x09);
        rt2800_rfcsr_write(rt2x00dev, 31, 0x10);
 
-       rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
        rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
        rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
 
-       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+       reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
        rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
        rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
        rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
        msleep(1);
-       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+       reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
        rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
        rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
        rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
@@ -7242,7 +7245,7 @@ static void rt3593_post_bbp_init(struct rt2x00_dev *rt2x00dev)
        u8 bbp;
        bool txbf_enabled = false; /* FIXME */
 
-       rt2800_bbp_read(rt2x00dev, 105, &bbp);
+       bbp = rt2800_bbp_read(rt2x00dev, 105);
        if (rt2x00dev->default_ant.rx_chain_num == 1)
                rt2x00_set_field8(&bbp, BBP105_MLD, 0);
        else
@@ -7291,7 +7294,7 @@ static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev)
        u8 rfcsr;
 
        /* Disable GPIO #4 and #7 function for LAN PE control */
-       rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+       reg = rt2800_register_read(rt2x00dev, GPIO_SWITCH);
        rt2x00_set_field32(&reg, GPIO_SWITCH_4, 0);
        rt2x00_set_field32(&reg, GPIO_SWITCH_7, 0);
        rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
@@ -7332,22 +7335,22 @@ static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev)
 
        /* Initiate calibration */
        /* TODO: use rt2800_rf_init_calibration ? */
-       rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 2);
        rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
        rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
 
        rt2800_freq_cal_mode1(rt2x00dev);
 
-       rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr);
+       rfcsr = rt2800_rfcsr_read(rt2x00dev, 18);
        rt2x00_set_field8(&rfcsr, RFCSR18_XO_TUNE_BYPASS, 1);
        rt2800_rfcsr_write(rt2x00dev, 18, rfcsr);
 
-       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+       reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
        rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
        rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
        rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
        usleep_range(1000, 1500);
-       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+       reg = rt2800_register_read(rt2x00dev, LDO_CFG0);
        rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
        rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
 
@@ -7356,8 +7359,8 @@ static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev)
        drv_data->calibration_bw40 = 0x2f;
 
        /* Save BBP 25 & 26 values for later use in channel switching */
-       rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25);
-       rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);
+       drv_data->bbp25 = rt2800_bbp_read(rt2x00dev, 25);
+       drv_data->bbp26 = rt2800_bbp_read(rt2x00dev, 26);
 
        rt2800_led_open_drain_enable(rt2x00dev);
        rt2800_normal_mode_setup_3593(rt2x00dev);
@@ -7651,19 +7654,19 @@ static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev,
 {
        u8 bbp_val;
 
-       rt2800_bbp_read(rt2x00dev, 21, &bbp_val);
+       bbp_val = rt2800_bbp_read(rt2x00dev, 21);
        bbp_val |= 0x1;
        rt2800_bbp_write(rt2x00dev, 21, bbp_val);
        usleep_range(100, 200);
 
        if (set_bw) {
-               rt2800_bbp_read(rt2x00dev, 4, &bbp_val);
+               bbp_val = rt2800_bbp_read(rt2x00dev, 4);
                rt2x00_set_field8(&bbp_val, BBP4_BANDWIDTH, 2 * is_ht40);
                rt2800_bbp_write(rt2x00dev, 4, bbp_val);
                usleep_range(100, 200);
        }
 
-       rt2800_bbp_read(rt2x00dev, 21, &bbp_val);
+       bbp_val = rt2800_bbp_read(rt2x00dev, 21);
        bbp_val &= (~0x1);
        rt2800_bbp_write(rt2x00dev, 21, bbp_val);
        usleep_range(100, 200);
@@ -7680,7 +7683,7 @@ static int rt2800_rf_lp_config(struct rt2x00_dev *rt2x00dev, bool btxcal)
 
        rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x06);
 
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 17, &rf_val);
+       rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 17);
        rf_val |= 0x80;
        rt2800_rfcsr_write_bank(rt2x00dev, 5, 17, rf_val);
 
@@ -7688,11 +7691,11 @@ static int rt2800_rf_lp_config(struct rt2x00_dev *rt2x00dev, bool btxcal)
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, 0xC1);
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, 0x20);
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, 0x02);
-               rt2800_rfcsr_read_bank(rt2x00dev, 5, 3, &rf_val);
+               rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 3);
                rf_val &= (~0x3F);
                rf_val |= 0x3F;
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 3, rf_val);
-               rt2800_rfcsr_read_bank(rt2x00dev, 5, 4, &rf_val);
+               rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4);
                rf_val &= (~0x3F);
                rf_val |= 0x3F;
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, rf_val);
@@ -7701,11 +7704,11 @@ static int rt2800_rf_lp_config(struct rt2x00_dev *rt2x00dev, bool btxcal)
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, 0xF1);
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, 0x18);
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, 0x02);
-               rt2800_rfcsr_read_bank(rt2x00dev, 5, 3, &rf_val);
+               rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 3);
                rf_val &= (~0x3F);
                rf_val |= 0x34;
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 3, rf_val);
-               rt2800_rfcsr_read_bank(rt2x00dev, 5, 4, &rf_val);
+               rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4);
                rf_val &= (~0x3F);
                rf_val |= 0x34;
                rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, rf_val);
@@ -7725,14 +7728,14 @@ static char rt2800_lp_tx_filter_bw_cal(struct rt2x00_dev *rt2x00dev)
        cnt = 0;
        do {
                usleep_range(500, 2000);
-               rt2800_bbp_read(rt2x00dev, 159, &bbp_val);
+               bbp_val = rt2800_bbp_read(rt2x00dev, 159);
                if (bbp_val == 0x02 || cnt == 20)
                        break;
 
                cnt++;
        } while (cnt < 20);
 
-       rt2800_bbp_dcoc_read(rt2x00dev, 0x39, &bbp_val);
+       bbp_val = rt2800_bbp_dcoc_read(rt2x00dev, 0x39);
        cal_val = bbp_val & 0x7F;
        if (cal_val >= 0x40)
                cal_val -= 128;
@@ -7761,67 +7764,67 @@ static void rt2800_bw_filter_calibration(struct rt2x00_dev *rt2x00dev,
        u32 MAC_RF_CONTROL0, MAC_RF_BYPASS0;
 
        /* Save MAC registers */
-       rt2800_register_read(rt2x00dev, RF_CONTROL0, &MAC_RF_CONTROL0);
-       rt2800_register_read(rt2x00dev, RF_BYPASS0, &MAC_RF_BYPASS0);
+       MAC_RF_CONTROL0 = rt2800_register_read(rt2x00dev, RF_CONTROL0);
+       MAC_RF_BYPASS0 = rt2800_register_read(rt2x00dev, RF_BYPASS0);
 
        /* save BBP registers */
-       rt2800_bbp_read(rt2x00dev, 23, &savebbpr23);
+       savebbpr23 = rt2800_bbp_read(rt2x00dev, 23);
 
-       rt2800_bbp_dcoc_read(rt2x00dev, 0, &savebbp159r0);
-       rt2800_bbp_dcoc_read(rt2x00dev, 2, &savebbp159r2);
+       savebbp159r0 = rt2800_bbp_dcoc_read(rt2x00dev, 0);
+       savebbp159r2 = rt2800_bbp_dcoc_read(rt2x00dev, 2);
 
        /* Save RF registers */
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 0, &saverfb5r00);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 1, &saverfb5r01);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 3, &saverfb5r03);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 4, &saverfb5r04);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 5, &saverfb5r05);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 6, &saverfb5r06);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 7, &saverfb5r07);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 8, &saverfb5r08);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 17, &saverfb5r17);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 18, &saverfb5r18);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 19, &saverfb5r19);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 20, &saverfb5r20);
-
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 37, &saverfb5r37);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 38, &saverfb5r38);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 39, &saverfb5r39);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 40, &saverfb5r40);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 41, &saverfb5r41);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 42, &saverfb5r42);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 43, &saverfb5r43);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 44, &saverfb5r44);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 45, &saverfb5r45);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 46, &saverfb5r46);
-
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 58, &saverfb5r58);
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 59, &saverfb5r59);
-
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 0, &rf_val);
+       saverfb5r00 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 0);
+       saverfb5r01 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 1);
+       saverfb5r03 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 3);
+       saverfb5r04 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4);
+       saverfb5r05 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 5);
+       saverfb5r06 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 6);
+       saverfb5r07 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 7);
+       saverfb5r08 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 8);
+       saverfb5r17 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 17);
+       saverfb5r18 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 18);
+       saverfb5r19 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 19);
+       saverfb5r20 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 20);
+
+       saverfb5r37 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 37);
+       saverfb5r38 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 38);
+       saverfb5r39 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 39);
+       saverfb5r40 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 40);
+       saverfb5r41 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 41);
+       saverfb5r42 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 42);
+       saverfb5r43 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 43);
+       saverfb5r44 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 44);
+       saverfb5r45 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 45);
+       saverfb5r46 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 46);
+
+       saverfb5r58 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 58);
+       saverfb5r59 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 59);
+
+       rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 0);
        rf_val |= 0x3;
        rt2800_rfcsr_write_bank(rt2x00dev, 5, 0, rf_val);
 
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 1, &rf_val);
+       rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 1);
        rf_val |= 0x1;
        rt2800_rfcsr_write_bank(rt2x00dev, 5, 1, rf_val);
 
        cnt = 0;
        do {
                usleep_range(500, 2000);
-               rt2800_rfcsr_read_bank(rt2x00dev, 5, 1, &rf_val);
+               rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 1);
                if (((rf_val & 0x1) == 0x00) || (cnt == 40))
                        break;
                cnt++;
        } while (cnt < 40);
 
-       rt2800_rfcsr_read_bank(rt2x00dev, 5, 0, &rf_val);
+       rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 0);
        rf_val &= (~0x3);
        rf_val |= 0x1;
        rt2800_rfcsr_write_bank(rt2x00dev, 5, 0, rf_val);
 
        /* I-3 */
-       rt2800_bbp_read(rt2x00dev, 23, &bbp_val);
+       bbp_val = rt2800_bbp_read(rt2x00dev, 23);
        bbp_val &= (~0x1F);
        bbp_val |= 0x10;
        rt2800_bbp_write(rt2x00dev, 23, bbp_val);
@@ -7844,7 +7847,7 @@ static void rt2800_bw_filter_calibration(struct rt2x00_dev *rt2x00dev,
                                filter_target = rx_filter_target_40m;
                }
 
-               rt2800_rfcsr_read_bank(rt2x00dev, 5, 8, &rf_val);
+               rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 8);
                rf_val &= (~0x04);
                if (loop == 1)
                        rf_val |= 0x4;
@@ -7856,25 +7859,25 @@ static void rt2800_bw_filter_calibration(struct rt2x00_dev *rt2x00dev,
                rt2800_rf_lp_config(rt2x00dev, btxcal);
                if (btxcal) {
                        tx_agc_fc = 0;
-                       rt2800_rfcsr_read_bank(rt2x00dev, 5, 58, &rf_val);
+                       rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 58);
                        rf_val &= (~0x7F);
                        rt2800_rfcsr_write_bank(rt2x00dev, 5, 58, rf_val);
-                       rt2800_rfcsr_read_bank(rt2x00dev, 5, 59, &rf_val);
+                       rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 59);
                        rf_val &= (~0x7F);
                        rt2800_rfcsr_write_bank(rt2x00dev, 5, 59, rf_val);
                } else {
                        rx_agc_fc = 0;
-                       rt2800_rfcsr_read_bank(rt2x00dev, 5, 6, &rf_val);
+                       rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 6);
                        rf_val &= (~0x7F);
                        rt2800_rfcsr_write_bank(rt2x00dev, 5, 6, rf_val);
-                       rt2800_rfcsr_read_bank(rt2x00dev, 5, 7, &rf_val);
+                       rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 7);
                        rf_val &= (~0x7F);
                        rt2800_rfcsr_write_bank(rt2x00dev, 5, 7, rf_val);
                }
 
                usleep_range(1000, 2000);
 
-               rt2800_bbp_dcoc_read(rt2x00dev, 2, &bbp_val);
+               bbp_val = rt2800_bbp_dcoc_read(rt2x00dev, 2);
                bbp_val &= (~0x6);
                rt2800_bbp_dcoc_write(rt2x00dev, 2, bbp_val);
 
@@ -7882,25 +7885,25 @@ static void rt2800_bw_filter_calibration(struct rt2x00_dev *rt2x00dev,
 
                cal_r32_init = rt2800_lp_tx_filter_bw_cal(rt2x00dev);
 
-               rt2800_bbp_dcoc_read(rt2x00dev, 2, &bbp_val);
+               bbp_val = rt2800_bbp_dcoc_read(rt2x00dev, 2);
                bbp_val |= 0x6;
                rt2800_bbp_dcoc_write(rt2x00dev, 2, bbp_val);
 do_cal:
                if (btxcal) {
-                       rt2800_rfcsr_read_bank(rt2x00dev, 5, 58, &rf_val);
+                       rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 58);
                        rf_val &= (~0x7F);
                        rf_val |= tx_agc_fc;
                        rt2800_rfcsr_write_bank(rt2x00dev, 5, 58, rf_val);
-                       rt2800_rfcsr_read_bank(rt2x00dev, 5, 59, &rf_val);
+                       rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 59);
                        rf_val &= (~0x7F);
                        rf_val |= tx_agc_fc;
                        rt2800_rfcsr_write_bank(rt2x00dev, 5, 59, rf_val);
                } else {
-                       rt2800_rfcsr_read_bank(rt2x00dev, 5, 6, &rf_val);
+                       rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 6);
                        rf_val &= (~0x7F);
                        rf_val |= rx_agc_fc;
                        rt2800_rfcsr_write_bank(rt2x00dev, 5, 6, rf_val);
-                       rt2800_rfcsr_read_bank(rt2x00dev, 5, 7, &rf_val);
+                       rf_val = rt2800_rfcsr_read_bank(rt2x00dev, 5, 7);
                        rf_val &= (~0x7F);
                        rf_val |= rx_agc_fc;
                        rt2800_rfcsr_write_bank(rt2x00dev, 5, 7, rf_val);
@@ -7980,7 +7983,7 @@ static void rt2800_bw_filter_calibration(struct rt2x00_dev *rt2x00dev,
        rt2800_bbp_dcoc_write(rt2x00dev, 0, savebbp159r0);
        rt2800_bbp_dcoc_write(rt2x00dev, 2, savebbp159r2);
 
-       rt2800_bbp_read(rt2x00dev, 4, &bbp_val);
+       bbp_val = rt2800_bbp_read(rt2x00dev, 4);
        rt2x00_set_field8(&bbp_val, BBP4_BANDWIDTH,
                          2 * test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags));
        rt2800_bbp_write(rt2x00dev, 4, bbp_val);
@@ -8355,20 +8358,20 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
        /*
         * Enable RX.
         */
-       rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+       reg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
        rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
        rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
        rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 
        udelay(50);
 
-       rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG);
        rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
        rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
        rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
        rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+       reg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
        rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
        rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
        rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
@@ -8376,15 +8379,15 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize LED control
         */
-       rt2800_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word);
+       word = rt2800_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF);
        rt2800_mcu_request(rt2x00dev, MCU_LED_AG_CONF, 0xff,
                           word & 0xff, (word >> 8) & 0xff);
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word);
+       word = rt2800_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF);
        rt2800_mcu_request(rt2x00dev, MCU_LED_ACT_CONF, 0xff,
                           word & 0xff, (word >> 8) & 0xff);
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word);
+       word = rt2800_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY);
        rt2800_mcu_request(rt2x00dev, MCU_LED_LED_POLARITY, 0xff,
                           word & 0xff, (word >> 8) & 0xff);
 
@@ -8401,7 +8404,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)
        /* Wait for DMA, ignore error */
        rt2800_wait_wpdma_ready(rt2x00dev);
 
-       rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+       reg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL);
        rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 0);
        rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
        rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
@@ -8418,7 +8421,7 @@ int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
        else
                efuse_ctrl_reg = EFUSE_CTRL;
 
-       rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
+       reg = rt2800_register_read(rt2x00dev, efuse_ctrl_reg);
        return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
 }
 EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
@@ -8447,7 +8450,7 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
        }
        mutex_lock(&rt2x00dev->csr_mutex);
 
-       rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
+       reg = rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg);
        rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
        rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
        rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
@@ -8456,14 +8459,14 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
        /* Wait until the EEPROM has been loaded */
        rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
        /* Apparently the data is read from end to start */
-       rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
+       reg = rt2800_register_read_lock(rt2x00dev, efuse_data3_reg);
        /* The returned value is in CPU order, but eeprom is le */
        *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
-       rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
+       reg = rt2800_register_read_lock(rt2x00dev, efuse_data2_reg);
        *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
-       rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
+       reg = rt2800_register_read_lock(rt2x00dev, efuse_data1_reg);
        *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
-       rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
+       reg = rt2800_register_read_lock(rt2x00dev, efuse_data0_reg);
        *(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
 
        mutex_unlock(&rt2x00dev->csr_mutex);
@@ -8487,7 +8490,7 @@ static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev)
        if (rt2x00_rt(rt2x00dev, RT3593))
                return 0;
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
+       word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG);
        if ((word & 0x00ff) != 0x00ff)
                return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL);
 
@@ -8501,7 +8504,7 @@ static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev)
        if (rt2x00_rt(rt2x00dev, RT3593))
                return 0;
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);
+       word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A);
        if ((word & 0x00ff) != 0x00ff)
                return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL);
 
@@ -8529,7 +8532,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        mac = rt2800_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
        rt2x00lib_set_mac_address(rt2x00dev, mac);
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);
+       word = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2);
                rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1);
@@ -8546,7 +8549,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
        }
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word);
+       word = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_NIC_CONF1_HW_RADIO, 0);
                rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC, 0);
@@ -8567,7 +8570,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
        }
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
+       word = rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ);
        if ((word & 0x00ff) == 0x00ff) {
                rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
                rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
@@ -8589,10 +8592,10 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
         * lna0 as correct value. Note that EEPROM_LNA
         * is never validated.
         */
-       rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &word);
+       word = rt2800_eeprom_read(rt2x00dev, EEPROM_LNA);
        default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0);
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);
+       word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG);
        if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)
                rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);
        if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)
@@ -8601,7 +8604,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 
        drv_data->txmixer_gain_24g = rt2800_get_txmixer_gain_24g(rt2x00dev);
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
+       word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2);
        if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
                rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
        if (!rt2x00_rt(rt2x00dev, RT3593)) {
@@ -8614,14 +8617,14 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 
        drv_data->txmixer_gain_5g = rt2800_get_txmixer_gain_5g(rt2x00dev);
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
+       word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A);
        if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
                rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);
        if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)
                rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0);
        rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
+       word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2);
        if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
                rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
        if (!rt2x00_rt(rt2x00dev, RT3593)) {
@@ -8633,7 +8636,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
 
        if (rt2x00_rt(rt2x00dev, RT3593)) {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &word);
+               word = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
                if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 ||
                    rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff)
                        rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1,
@@ -8657,7 +8660,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Read EEPROM word for configuration.
         */
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0);
 
        /*
         * Identify RF chipset by EEPROM value
@@ -8668,7 +8671,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
            rt2x00_rt(rt2x00dev, RT5390) ||
            rt2x00_rt(rt2x00dev, RT5392) ||
            rt2x00_rt(rt2x00dev, RT6352))
-               rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+               rf = rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID);
        else if (rt2x00_rt(rt2x00dev, RT3352))
                rf = RF3322;
        else if (rt2x00_rt(rt2x00dev, RT5350))
@@ -8717,7 +8720,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2x00dev->default_ant.rx_chain_num =
            rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH);
 
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
 
        if (rt2x00_rt(rt2x00dev, RT3070) ||
            rt2x00_rt(rt2x00dev, RT3090) ||
@@ -8771,7 +8774,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Read frequency offset and RF programming sequence.
         */
-       rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ);
        rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
 
        /*
@@ -8788,7 +8791,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Check if support EIRP tx power limit feature.
         */
-       rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom);
+       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER);
 
        if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) <
                                        EIRP_MAX_TX_POWER_LIMIT)
@@ -8797,7 +8800,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Detect if device uses internal or external PA
         */
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+       eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
 
        if (rt2x00_rt(rt2x00dev, RT3352)) {
                if (rt2x00_get_field16(eeprom,
@@ -9239,7 +9242,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
                break;
 
        case RF5592:
-               rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, &reg);
+               reg = rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX);
                if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {
                        spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40);
                        spec->channels = rf_vals_5592_xtal40;
@@ -9378,9 +9381,9 @@ static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)
        u32 rev;
 
        if (rt2x00_rt(rt2x00dev, RT3290))
-               rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
+               reg = rt2800_register_read(rt2x00dev, MAC_CSR0_3290);
        else
-               rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+               reg = rt2800_register_read(rt2x00dev, MAC_CSR0);
 
        rt = rt2x00_get_field32(reg, MAC_CSR0_CHIPSET);
        rev = rt2x00_get_field32(reg, MAC_CSR0_REVISION);
@@ -9440,7 +9443,7 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
         * Enable rfkill polling by setting GPIO direction of the
         * rfkill switch GPIO pin correctly.
         */
-       rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+       reg = rt2800_register_read(rt2x00dev, GPIO_CTRL);
        rt2x00_set_field32(&reg, GPIO_CTRL_DIR2, 1);
        rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
 
@@ -9515,31 +9518,31 @@ int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
        u32 reg;
        bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD);
 
-       rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, TX_RTS_CFG);
        rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES, value);
        rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, CCK_PROT_CFG);
        rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, enabled);
        rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, OFDM_PROT_CFG);
        rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, enabled);
        rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, MM20_PROT_CFG);
        rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, enabled);
        rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, MM40_PROT_CFG);
        rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, enabled);
        rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, GF20_PROT_CFG);
        rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, enabled);
        rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, GF40_PROT_CFG);
        rt2x00_set_field32(&reg, GF40_PROT_CFG_RTS_TH_EN, enabled);
        rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
 
@@ -9582,7 +9585,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw,
        field.bit_offset = (queue_idx & 1) * 16;
        field.bit_mask = 0xffff << field.bit_offset;
 
-       rt2800_register_read(rt2x00dev, offset, &reg);
+       reg = rt2800_register_read(rt2x00dev, offset);
        rt2x00_set_field32(&reg, field, queue->txop);
        rt2800_register_write(rt2x00dev, offset, reg);
 
@@ -9590,22 +9593,22 @@ int rt2800_conf_tx(struct ieee80211_hw *hw,
        field.bit_offset = queue_idx * 4;
        field.bit_mask = 0xf << field.bit_offset;
 
-       rt2800_register_read(rt2x00dev, WMM_AIFSN_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, WMM_AIFSN_CFG);
        rt2x00_set_field32(&reg, field, queue->aifs);
        rt2800_register_write(rt2x00dev, WMM_AIFSN_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, WMM_CWMIN_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, WMM_CWMIN_CFG);
        rt2x00_set_field32(&reg, field, queue->cw_min);
        rt2800_register_write(rt2x00dev, WMM_CWMIN_CFG, reg);
 
-       rt2800_register_read(rt2x00dev, WMM_CWMAX_CFG, &reg);
+       reg = rt2800_register_read(rt2x00dev, WMM_CWMAX_CFG);
        rt2x00_set_field32(&reg, field, queue->cw_max);
        rt2800_register_write(rt2x00dev, WMM_CWMAX_CFG, reg);
 
        /* Update EDCA registers */
        offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx);
 
-       rt2800_register_read(rt2x00dev, offset, &reg);
+       reg = rt2800_register_read(rt2x00dev, offset);
        rt2x00_set_field32(&reg, EDCA_AC0_CFG_TX_OP, queue->txop);
        rt2x00_set_field32(&reg, EDCA_AC0_CFG_AIFSN, queue->aifs);
        rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMIN, queue->cw_min);
@@ -9622,9 +9625,9 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        u64 tsf;
        u32 reg;
 
-       rt2800_register_read(rt2x00dev, TSF_TIMER_DW1, &reg);
+       reg = rt2800_register_read(rt2x00dev, TSF_TIMER_DW1);
        tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32;
-       rt2800_register_read(rt2x00dev, TSF_TIMER_DW0, &reg);
+       reg = rt2800_register_read(rt2x00dev, TSF_TIMER_DW0);
        tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD);
 
        return tsf;
@@ -9691,9 +9694,9 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
 
        survey->channel = conf->chandef.chan;
 
-       rt2800_register_read(rt2x00dev, CH_IDLE_STA, &idle);
-       rt2800_register_read(rt2x00dev, CH_BUSY_STA, &busy);
-       rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &busy_ext);
+       idle = rt2800_register_read(rt2x00dev, CH_IDLE_STA);
+       busy = rt2800_register_read(rt2x00dev, CH_BUSY_STA);
+       busy_ext = rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC);
 
        if (idle || busy) {
                survey->filled = SURVEY_INFO_TIME |
index f357531d9488d99d97033ac049d4ebbe99b70be2..275e3969abddb3015e8d19b88d7b479469ee570b 100644 (file)
@@ -49,10 +49,10 @@ struct rt2800_drv_data {
 };
 
 struct rt2800_ops {
-       void (*register_read)(struct rt2x00_dev *rt2x00dev,
-                             const unsigned int offset, u32 *value);
-       void (*register_read_lock)(struct rt2x00_dev *rt2x00dev,
-                                  const unsigned int offset, u32 *value);
+       u32 (*register_read)(struct rt2x00_dev *rt2x00dev,
+                             const unsigned int offset);
+       u32 (*register_read_lock)(struct rt2x00_dev *rt2x00dev,
+                                  const unsigned int offset);
        void (*register_write)(struct rt2x00_dev *rt2x00dev,
                               const unsigned int offset, u32 value);
        void (*register_write_lock)(struct rt2x00_dev *rt2x00dev,
@@ -78,22 +78,20 @@ struct rt2800_ops {
        __le32 *(*drv_get_txwi)(struct queue_entry *entry);
 };
 
-static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
-                                       const unsigned int offset,
-                                       u32 *value)
+static inline u32 rt2800_register_read(struct rt2x00_dev *rt2x00dev,
+                                      const unsigned int offset)
 {
        const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 
-       rt2800ops->register_read(rt2x00dev, offset, value);
+       return rt2800ops->register_read(rt2x00dev, offset);
 }
 
-static inline void rt2800_register_read_lock(struct rt2x00_dev *rt2x00dev,
-                                            const unsigned int offset,
-                                            u32 *value)
+static inline u32 rt2800_register_read_lock(struct rt2x00_dev *rt2x00dev,
+                                           const unsigned int offset)
 {
        const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 
-       rt2800ops->register_read_lock(rt2x00dev, offset, value);
+       return rt2800ops->register_read_lock(rt2x00dev, offset);
 }
 
 static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev,
index 3ab3b53238974a72c5d2170215666e4890110d4e..ee5276e233fa6d926b4881ef487f1188fc0ffe0e 100644 (file)
@@ -109,7 +109,7 @@ void rt2800mmio_fill_rxdone(struct queue_entry *entry,
        __le32 *rxd = entry_priv->desc;
        u32 word;
 
-       rt2x00_desc_read(rxd, 3, &word);
+       word = rt2x00_desc_read(rxd, 3);
 
        if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -175,7 +175,7 @@ static bool rt2800mmio_txdone_entry_check(struct queue_entry *entry, u32 status)
        wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
 
        txwi = rt2800_drv_get_txwi(entry);
-       rt2x00_desc_read(txwi, 1, &word);
+       word = rt2x00_desc_read(txwi, 1);
        tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
 
        return (tx_wcid == wcid);
@@ -331,7 +331,7 @@ static inline void rt2800mmio_enable_interrupt(struct rt2x00_dev *rt2x00dev,
         * access needs locking.
         */
        spin_lock_irq(&rt2x00dev->irqmask_lock);
-       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR);
        rt2x00_set_field32(&reg, irq_field, 1);
        rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
        spin_unlock_irq(&rt2x00dev->irqmask_lock);
@@ -376,12 +376,12 @@ void rt2800mmio_tbtt_tasklet(unsigned long data)
                 * interval every 64 beacons by 64us to mitigate this effect.
                 */
                if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) {
-                       rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+                       reg = rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG);
                        rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
                                           (rt2x00dev->beacon_int * 16) - 1);
                        rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
                } else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) {
-                       rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+                       reg = rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG);
                        rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
                                           (rt2x00dev->beacon_int * 16));
                        rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
@@ -439,7 +439,7 @@ static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
         * need to lock the kfifo.
         */
        for (i = 0; i < rt2x00dev->tx->limit; i++) {
-               rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status);
+               status = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO);
 
                if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
                        break;
@@ -460,7 +460,7 @@ irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
        u32 reg, mask;
 
        /* Read status and ACK all interrupts */
-       rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR);
        rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
 
        if (!reg)
@@ -501,7 +501,7 @@ irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
         * the tasklet will reenable the appropriate interrupts.
         */
        spin_lock(&rt2x00dev->irqmask_lock);
-       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR);
        reg &= mask;
        rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
        spin_unlock(&rt2x00dev->irqmask_lock);
@@ -521,7 +521,7 @@ void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev,
         * should clear the register to assure a clean state.
         */
        if (state == STATE_RADIO_IRQ_ON) {
-               rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR);
                rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
        }
 
@@ -560,18 +560,18 @@ void rt2800mmio_start_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL);
                rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
                rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
                break;
        case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
                rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN);
                rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
                rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg);
                break;
@@ -613,18 +613,18 @@ void rt2800mmio_stop_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL);
                rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
                rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
                break;
        case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
                rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN);
                rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
                rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg);
 
@@ -696,11 +696,11 @@ bool rt2800mmio_get_entry_state(struct queue_entry *entry)
        u32 word;
 
        if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 1, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 1);
 
                return (!rt2x00_get_field32(word, RXD_W1_DMA_DONE));
        } else {
-               rt2x00_desc_read(entry_priv->desc, 1, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 1);
 
                return (!rt2x00_get_field32(word, TXD_W1_DMA_DONE));
        }
@@ -715,11 +715,11 @@ void rt2800mmio_clear_entry(struct queue_entry *entry)
        u32 word;
 
        if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
                rt2x00_set_field32(&word, RXD_W0_SDP0, skbdesc->skb_dma);
                rt2x00_desc_write(entry_priv->desc, 0, word);
 
-               rt2x00_desc_read(entry_priv->desc, 1, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 1);
                rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0);
                rt2x00_desc_write(entry_priv->desc, 1, word);
 
@@ -730,7 +730,7 @@ void rt2800mmio_clear_entry(struct queue_entry *entry)
                rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX,
                                          entry->entry_idx);
        } else {
-               rt2x00_desc_read(entry_priv->desc, 1, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 1);
                rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
                rt2x00_desc_write(entry_priv->desc, 1, word);
        }
@@ -810,7 +810,7 @@ int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev)
        /*
         * Reset DMA indexes
         */
-       rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX);
        rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
        rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
        rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
@@ -831,7 +831,7 @@ int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev)
             rt2x00_rt(rt2x00dev, RT5390) ||
             rt2x00_rt(rt2x00dev, RT5392) ||
             rt2x00_rt(rt2x00dev, RT5592))) {
-               rt2x00mmio_register_read(rt2x00dev, AUX_CTRL, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, AUX_CTRL);
                rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
                rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
                rt2x00mmio_register_write(rt2x00dev, AUX_CTRL, reg);
index 0af22573a2eb5daa478ffbe0dadcca7feb2eb104..5cf655ff143024dd5f9e18c1c22e0fb54deb1492 100644 (file)
@@ -69,7 +69,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
                return;
 
        for (i = 0; i < 200; i++) {
-               rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID);
 
                if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
                    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
@@ -92,7 +92,7 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
        struct rt2x00_dev *rt2x00dev = eeprom->data;
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR);
 
        eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
        eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
@@ -122,7 +122,7 @@ static int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
        struct eeprom_93cx6 eeprom;
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR);
 
        eeprom.data = rt2x00dev;
        eeprom.register_read = rt2800pci_eepromregister_read;
index f11e3f532a84e48e17e9d530030c3f066099fe7f..685b8e0cd67d81997377e493555b2b6bffec5669 100644 (file)
@@ -61,12 +61,12 @@ static void rt2800usb_start_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL);
                rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
                rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
                break;
        case QID_BEACON:
-               rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
@@ -84,12 +84,12 @@ static void rt2800usb_stop_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL);
                rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
                rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
                break;
        case QID_BEACON:
-               rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
@@ -333,7 +333,7 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
        if (rt2800_wait_csr_ready(rt2x00dev))
                return -EBUSY;
 
-       rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL);
        rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
 
        reg = 0;
@@ -456,7 +456,7 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry,
        /*
         * Initialize TXINFO descriptor
         */
-       rt2x00_desc_read(txi, 0, &word);
+       word = rt2x00_desc_read(txi, 0);
 
        /*
         * The size of TXINFO_W0_USB_DMA_TX_PKT_LEN is
@@ -527,7 +527,7 @@ static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
         */
        txwi = rt2800usb_get_txwi(entry);
 
-       rt2x00_desc_read(txwi, 1, &word);
+       word = rt2x00_desc_read(txwi, 1);
        tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
        tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK);
        tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID);
@@ -652,7 +652,7 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
         * | RXINFO | RXWI | header | L2 pad | payload | pad | RXD | USB pad |
         *          |<------------ rx_pkt_len -------------->|
         */
-       rt2x00_desc_read(rxi, 0, &word);
+       word = rt2x00_desc_read(rxi, 0);
        rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);
 
        /*
@@ -676,7 +676,7 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
        /*
         * It is now safe to read the descriptor on all architectures.
         */
-       rt2x00_desc_read(rxd, 0, &word);
+       word = rt2x00_desc_read(rxd, 0);
 
        if (rt2x00_get_field32(word, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -1156,6 +1156,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
        { USB_DEVICE(0x2001, 0x3c17) },
        /* Panasonic */
        { USB_DEVICE(0x083a, 0xb511) },
+       /* Accton/Arcadyan/Epson */
+       { USB_DEVICE(0x083a, 0xb512) },
        /* Philips */
        { USB_DEVICE(0x0471, 0x20dd) },
        /* Ralink */
index 1bc353eafe37dea8408428ffc0b710ddd7ffadc9..1f38c338ca7a11cc610e6ca14673da7caafb1060 100644 (file)
@@ -1049,11 +1049,11 @@ struct rt2x00_bar_list_entry {
  * Generic RF access.
  * The RF is being accessed by word index.
  */
-static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev,
-                                 const unsigned int word, u32 *data)
+static inline u32 rt2x00_rf_read(struct rt2x00_dev *rt2x00dev,
+                                const unsigned int word)
 {
        BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
-       *data = rt2x00dev->rf[word - 1];
+       return rt2x00dev->rf[word - 1];
 }
 
 static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -1072,10 +1072,10 @@ static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev,
        return (void *)&rt2x00dev->eeprom[word];
 }
 
-static inline void rt2x00_eeprom_read(struct rt2x00_dev *rt2x00dev,
-                                     const unsigned int word, u16 *data)
+static inline u16 rt2x00_eeprom_read(struct rt2x00_dev *rt2x00dev,
+                                    const unsigned int word)
 {
-       *data = le16_to_cpu(rt2x00dev->eeprom[word]);
+       return le16_to_cpu(rt2x00dev->eeprom[word]);
 }
 
 static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev,
index 964aefdc11f004593d4f171a87895687dde57108..4a1bca1b1e2678e97387d19d338a46cb3b62aa34 100644 (file)
@@ -460,7 +460,7 @@ static ssize_t rt2x00debug_read_##__name(struct file *file, \
        if (debug->__name.flags & RT2X00DEBUGFS_OFFSET)         \
                index *= debug->__name.word_size;               \
                                                                \
-       debug->__name.read(intf->rt2x00dev, index, &value);     \
+       value = debug->__name.read(intf->rt2x00dev, index);     \
                                                                \
        size = sprintf(line, __format, value);                  \
                                                                \
index e65712c235bd2829f12a1b3f7d4daa1209837ec0..a357a0727a0b90def5b009f824d4d7c55945bf0a 100644 (file)
@@ -38,8 +38,8 @@ enum rt2x00debugfs_entry_flags {
 
 #define RT2X00DEBUGFS_REGISTER_ENTRY(__name, __type)           \
 struct reg##__name {                                           \
-       void (*read)(struct rt2x00_dev *rt2x00dev,              \
-                    const unsigned int word, __type *data);    \
+       __type (*read)(struct rt2x00_dev *rt2x00dev,            \
+                    const unsigned int word);                  \
        void (*write)(struct rt2x00_dev *rt2x00dev,             \
                      const unsigned int word, __type data);    \
                                                                \
index da38d254c26f042be2beadb1a0bed76660a65bc6..528cb0401df1de715643d3d959456af3f793bd18 100644 (file)
@@ -43,7 +43,7 @@ int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev,
                return 0;
 
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2x00mmio_register_read(rt2x00dev, offset, reg);
+               *reg = rt2x00mmio_register_read(rt2x00dev, offset);
                if (!rt2x00_get_field32(*reg, field))
                        return 1;
                udelay(REGISTER_BUSY_DELAY);
index 701c3127efb96bdb647ff19e21684134fc25e9e1..184a4148b2f8ff619915557bff928e17d93539e3 100644 (file)
 /*
  * Register access.
  */
-static inline void rt2x00mmio_register_read(struct rt2x00_dev *rt2x00dev,
-                                           const unsigned int offset,
-                                           u32 *value)
+static inline u32 rt2x00mmio_register_read(struct rt2x00_dev *rt2x00dev,
+                                          const unsigned int offset)
 {
-       *value = readl(rt2x00dev->csr.base + offset);
+       return readl(rt2x00dev->csr.base + offset);
 }
 
 static inline void rt2x00mmio_register_multiread(struct rt2x00_dev *rt2x00dev,
index 6055f36211b95fcd9dde9d5bb3fb8d981f8cd7a8..a15bae29917b96f1f8f2413ff9122fdb924b6676 100644 (file)
@@ -642,11 +642,10 @@ static inline int rt2x00queue_dma_timeout(struct queue_entry *entry)
  * _rt2x00_desc_read - Read a word from the hardware descriptor.
  * @desc: Base descriptor address
  * @word: Word index from where the descriptor should be read.
- * @value: Address where the descriptor value should be written into.
  */
-static inline void _rt2x00_desc_read(__le32 *desc, const u8 word, __le32 *value)
+static inline __le32 _rt2x00_desc_read(__le32 *desc, const u8 word)
 {
-       *value = desc[word];
+       return desc[word];
 }
 
 /**
@@ -654,13 +653,10 @@ static inline void _rt2x00_desc_read(__le32 *desc, const u8 word, __le32 *value)
  * function will take care of the byte ordering.
  * @desc: Base descriptor address
  * @word: Word index from where the descriptor should be read.
- * @value: Address where the descriptor value should be written into.
  */
-static inline void rt2x00_desc_read(__le32 *desc, const u8 word, u32 *value)
+static inline u32 rt2x00_desc_read(__le32 *desc, const u8 word)
 {
-       __le32 tmp;
-       _rt2x00_desc_read(desc, word, &tmp);
-       *value = le32_to_cpu(tmp);
+       return le32_to_cpu(_rt2x00_desc_read(desc, word));
 }
 
 /**
index c696f0ad6a68382c67af596516ba2b0b45270382..e2f4f5778267bcdd501e40bca10f9ee5a2ed0704 100644 (file)
@@ -145,7 +145,7 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
                return -ENODEV;
 
        for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
-               rt2x00usb_register_read_lock(rt2x00dev, offset, reg);
+               *reg = rt2x00usb_register_read_lock(rt2x00dev, offset);
                if (!rt2x00_get_field32(*reg, field))
                        return 1;
                udelay(REGISTER_BUSY_DELAY);
index 569363da00a2999fca8cac2d425347d759a62b08..ff94c6944cfcc7ec1d0c98e8d55d37bc6f177c1c 100644 (file)
@@ -190,40 +190,36 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
  * rt2x00usb_register_read - Read 32bit register word
  * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
  * @offset: Register offset
- * @value: Pointer to where register contents should be stored
  *
  * This function is a simple wrapper for 32bit register access
  * through rt2x00usb_vendor_request_buff().
  */
-static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev,
-                                          const unsigned int offset,
-                                          u32 *value)
+static inline u32 rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev,
+                                         const unsigned int offset)
 {
        __le32 reg = 0;
        rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
                                      USB_VENDOR_REQUEST_IN, offset,
                                      &reg, sizeof(reg));
-       *value = le32_to_cpu(reg);
+       return le32_to_cpu(reg);
 }
 
 /**
  * rt2x00usb_register_read_lock - Read 32bit register word
  * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
  * @offset: Register offset
- * @value: Pointer to where register contents should be stored
  *
  * This function is a simple wrapper for 32bit register access
  * through rt2x00usb_vendor_req_buff_lock().
  */
-static inline void rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
-                                               const unsigned int offset,
-                                               u32 *value)
+static inline u32 rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
+                                              const unsigned int offset)
 {
        __le32 reg = 0;
        rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
                                       USB_VENDOR_REQUEST_IN, offset,
                                       &reg, sizeof(reg), REGISTER_TIMEOUT);
-       *value = le32_to_cpu(reg);
+       return le32_to_cpu(reg);
 }
 
 /**
index 973d418b81130321a95d0f4e1dacb11c4a225e20..234310200759328ab674a2bc4e45ed20353bdc9d 100644 (file)
@@ -86,10 +86,11 @@ static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
        mutex_unlock(&rt2x00dev->csr_mutex);
 }
 
-static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
-                            const unsigned int word, u8 *value)
+static u8 rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
+                          const unsigned int word)
 {
        u32 reg;
+       u8 value;
 
        mutex_lock(&rt2x00dev->csr_mutex);
 
@@ -112,9 +113,11 @@ static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
                WAIT_FOR_BBP(rt2x00dev, &reg);
        }
 
-       *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
+       value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
 
        mutex_unlock(&rt2x00dev->csr_mutex);
+
+       return value;
 }
 
 static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -161,7 +164,7 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
                rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, HOST_CMD_CSR, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, HOST_CMD_CSR);
                rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
                rt2x00_set_field32(&reg, HOST_CMD_CSR_INTERRUPT_MCU, 1);
                rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, reg);
@@ -176,7 +179,7 @@ static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
        struct rt2x00_dev *rt2x00dev = eeprom->data;
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR);
 
        eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
        eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
@@ -240,7 +243,7 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR13);
        return rt2x00_get_field32(reg, MAC_CSR13_VAL5);
 }
 
@@ -291,7 +294,7 @@ static int rt61pci_blink_set(struct led_classdev *led_cdev,
            container_of(led_cdev, struct rt2x00_led, led_dev);
        u32 reg;
 
-       rt2x00mmio_register_read(led->rt2x00dev, MAC_CSR14, &reg);
+       reg = rt2x00mmio_register_read(led->rt2x00dev, MAC_CSR14);
        rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
        rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
        rt2x00mmio_register_write(led->rt2x00dev, MAC_CSR14, reg);
@@ -336,7 +339,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
                 */
                mask = (0xf << crypto->bssidx);
 
-               rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR0);
                reg &= mask;
 
                if (reg && reg == mask)
@@ -369,14 +372,14 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
                        field.bit_offset = (3 * key->hw_key_idx);
                        field.bit_mask = 0x7 << field.bit_offset;
 
-                       rt2x00mmio_register_read(rt2x00dev, SEC_CSR1, &reg);
+                       reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR1);
                        rt2x00_set_field32(&reg, field, crypto->cipher);
                        rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, reg);
                } else {
                        field.bit_offset = (3 * (key->hw_key_idx - 8));
                        field.bit_mask = 0x7 << field.bit_offset;
 
-                       rt2x00mmio_register_read(rt2x00dev, SEC_CSR5, &reg);
+                       reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR5);
                        rt2x00_set_field32(&reg, field, crypto->cipher);
                        rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, reg);
                }
@@ -401,7 +404,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
         */
        mask = 1 << key->hw_key_idx;
 
-       rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR0);
        if (crypto->cmd == SET_KEY)
                reg |= mask;
        else if (crypto->cmd == DISABLE_KEY)
@@ -430,10 +433,10 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
                 * When both registers are full, we drop the key.
                 * Otherwise, we use the first invalid entry.
                 */
-               rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR2);
                if (reg && reg == ~0) {
                        key->hw_key_idx = 32;
-                       rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, &reg);
+                       reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR3);
                        if (reg && reg == ~0)
                                return -ENOSPC;
                }
@@ -467,7 +470,7 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
                 * Without this, received frames will not be decrypted
                 * by the hardware.
                 */
-               rt2x00mmio_register_read(rt2x00dev, SEC_CSR4, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR4);
                reg |= (1 << crypto->bssidx);
                rt2x00mmio_register_write(rt2x00dev, SEC_CSR4, reg);
 
@@ -492,7 +495,7 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
        if (key->hw_key_idx < 32) {
                mask = 1 << key->hw_key_idx;
 
-               rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR2);
                if (crypto->cmd == SET_KEY)
                        reg |= mask;
                else if (crypto->cmd == DISABLE_KEY)
@@ -501,7 +504,7 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
        } else {
                mask = 1 << (key->hw_key_idx - 32);
 
-               rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR3);
                if (crypto->cmd == SET_KEY)
                        reg |= mask;
                else if (crypto->cmd == DISABLE_KEY)
@@ -523,7 +526,7 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
         * and broadcast frames will always be accepted since
         * there is no filter for it at this time.
         */
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0);
        rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
                           !(filter_flags & FIF_FCSFAIL));
        rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
@@ -555,7 +558,7 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
                /*
                 * Enable synchronisation.
                 */
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
                rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
                rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
        }
@@ -586,13 +589,13 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0);
        rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);
        rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
        rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
 
        if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4);
                rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
                rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
                                   !!erp->short_preamble);
@@ -604,18 +607,18 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
                                          erp->basic_rates);
 
        if (changed & BSS_CHANGED_BEACON_INT) {
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
                rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
                                   erp->beacon_int * 16);
                rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
        }
 
        if (changed & BSS_CHANGED_ERP_SLOT) {
-               rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR9);
                rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
                rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, MAC_CSR8, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR8);
                rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
                rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
                rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
@@ -630,9 +633,9 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
        u8 r4;
        u8 r77;
 
-       rt61pci_bbp_read(rt2x00dev, 3, &r3);
-       rt61pci_bbp_read(rt2x00dev, 4, &r4);
-       rt61pci_bbp_read(rt2x00dev, 77, &r77);
+       r3 = rt61pci_bbp_read(rt2x00dev, 3);
+       r4 = rt61pci_bbp_read(rt2x00dev, 4);
+       r77 = rt61pci_bbp_read(rt2x00dev, 77);
 
        rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF5325));
 
@@ -676,9 +679,9 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
        u8 r4;
        u8 r77;
 
-       rt61pci_bbp_read(rt2x00dev, 3, &r3);
-       rt61pci_bbp_read(rt2x00dev, 4, &r4);
-       rt61pci_bbp_read(rt2x00dev, 77, &r77);
+       r3 = rt61pci_bbp_read(rt2x00dev, 3);
+       r4 = rt61pci_bbp_read(rt2x00dev, 4);
+       r77 = rt61pci_bbp_read(rt2x00dev, 77);
 
        rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));
        rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
@@ -712,7 +715,7 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR13);
 
        rt2x00_set_field32(&reg, MAC_CSR13_DIR4, 0);
        rt2x00_set_field32(&reg, MAC_CSR13_VAL4, p1);
@@ -730,9 +733,9 @@ static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
        u8 r4;
        u8 r77;
 
-       rt61pci_bbp_read(rt2x00dev, 3, &r3);
-       rt61pci_bbp_read(rt2x00dev, 4, &r4);
-       rt61pci_bbp_read(rt2x00dev, 77, &r77);
+       r3 = rt61pci_bbp_read(rt2x00dev, 3);
+       r4 = rt61pci_bbp_read(rt2x00dev, 4);
+       r77 = rt61pci_bbp_read(rt2x00dev, 77);
 
        /*
         * Configure the RX antenna.
@@ -819,7 +822,7 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
        for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
                rt61pci_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
 
-       rt2x00mmio_register_read(rt2x00dev, PHY_CSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, PHY_CSR0);
 
        rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
                           rt2x00dev->curr_band == NL80211_BAND_2GHZ);
@@ -850,13 +853,13 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
                if (rt2x00_has_cap_external_lna_bg(rt2x00dev))
                        lna_gain += 14;
 
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+               eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG);
                lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
        } else {
                if (rt2x00_has_cap_external_lna_a(rt2x00dev))
                        lna_gain += 14;
 
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+               eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A);
                lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
        }
 
@@ -875,7 +878,7 @@ static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
 
        smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
 
-       rt61pci_bbp_read(rt2x00dev, 3, &r3);
+       r3 = rt61pci_bbp_read(rt2x00dev, 3);
        rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
        rt61pci_bbp_write(rt2x00dev, 3, r3);
 
@@ -913,10 +916,10 @@ static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev,
 {
        struct rf_channel rf;
 
-       rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
-       rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
-       rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
-       rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
+       rf.rf1 = rt2x00_rf_read(rt2x00dev, 1);
+       rf.rf2 = rt2x00_rf_read(rt2x00dev, 2);
+       rf.rf3 = rt2x00_rf_read(rt2x00dev, 3);
+       rf.rf4 = rt2x00_rf_read(rt2x00dev, 4);
 
        rt61pci_config_channel(rt2x00dev, &rf, txpower);
 }
@@ -926,7 +929,7 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4);
        rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1);
        rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_STEP, 0);
        rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0);
@@ -946,7 +949,7 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
        u32 reg;
 
        if (state == STATE_SLEEP) {
-               rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR11);
                rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
                                   rt2x00dev->beacon_int - 10);
                rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
@@ -967,7 +970,7 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
 
                rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0);
        } else {
-               rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR11);
                rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
                rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
                rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
@@ -1013,13 +1016,13 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
        /*
         * Update FCS error count from register.
         */
-       rt2x00mmio_register_read(rt2x00dev, STA_CSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, STA_CSR0);
        qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
 
        /*
         * Update False CCA count from register.
         */
-       rt2x00mmio_register_read(rt2x00dev, STA_CSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, STA_CSR1);
        qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
 }
 
@@ -1138,12 +1141,12 @@ static void rt61pci_start_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0);
                rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
                rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
                break;
        case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
                rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
                rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
                rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
@@ -1161,22 +1164,22 @@ static void rt61pci_kick_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_AC_VO:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
                rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, 1);
                rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
                break;
        case QID_AC_VI:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
                rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, 1);
                rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
                break;
        case QID_AC_BE:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
                rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, 1);
                rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
                break;
        case QID_AC_BK:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
                rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, 1);
                rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
                break;
@@ -1192,32 +1195,32 @@ static void rt61pci_stop_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_AC_VO:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
                rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, 1);
                rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
                break;
        case QID_AC_VI:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
                rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, 1);
                rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
                break;
        case QID_AC_BE:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
                rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, 1);
                rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
                break;
        case QID_AC_BK:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR);
                rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, 1);
                rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
                break;
        case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0);
                rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
                rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
                break;
        case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
                rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
                rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
                rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
@@ -1299,7 +1302,7 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
         * Wait for stable hardware.
         */
        for (i = 0; i < 100; i++) {
-               rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR0);
                if (reg)
                        break;
                msleep(1);
@@ -1338,7 +1341,7 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
        rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
 
        for (i = 0; i < 100; i++) {
-               rt2x00mmio_register_read(rt2x00dev, MCU_CNTL_CSR, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, MCU_CNTL_CSR);
                if (rt2x00_get_field32(reg, MCU_CNTL_CSR_READY))
                        break;
                msleep(1);
@@ -1362,12 +1365,12 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
        rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR1);
        rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
        rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
        rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR1);
        rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
        rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
 
@@ -1383,11 +1386,11 @@ static bool rt61pci_get_entry_state(struct queue_entry *entry)
        u32 word;
 
        if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
 
                return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
        } else {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
 
                return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
                        rt2x00_get_field32(word, TXD_W0_VALID));
@@ -1401,16 +1404,16 @@ static void rt61pci_clear_entry(struct queue_entry *entry)
        u32 word;
 
        if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 5, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 5);
                rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
                                   skbdesc->skb_dma);
                rt2x00_desc_write(entry_priv->desc, 5, word);
 
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
                rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
                rt2x00_desc_write(entry_priv->desc, 0, word);
        } else {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
                rt2x00_set_field32(&word, TXD_W0_VALID, 0);
                rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
                rt2x00_desc_write(entry_priv->desc, 0, word);
@@ -1425,7 +1428,7 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize registers.
         */
-       rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR0);
        rt2x00_set_field32(&reg, TX_RING_CSR0_AC0_RING_SIZE,
                           rt2x00dev->tx[0].limit);
        rt2x00_set_field32(&reg, TX_RING_CSR0_AC1_RING_SIZE,
@@ -1436,36 +1439,36 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
                           rt2x00dev->tx[3].limit);
        rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR0, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR1);
        rt2x00_set_field32(&reg, TX_RING_CSR1_TXD_SIZE,
                           rt2x00dev->tx[0].desc_size / 4);
        rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR1, reg);
 
        entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, AC0_BASE_CSR);
        rt2x00_set_field32(&reg, AC0_BASE_CSR_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, AC0_BASE_CSR, reg);
 
        entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, AC1_BASE_CSR);
        rt2x00_set_field32(&reg, AC1_BASE_CSR_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, AC1_BASE_CSR, reg);
 
        entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, AC2_BASE_CSR);
        rt2x00_set_field32(&reg, AC2_BASE_CSR_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, AC2_BASE_CSR, reg);
 
        entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, AC3_BASE_CSR);
        rt2x00_set_field32(&reg, AC3_BASE_CSR_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, AC3_BASE_CSR, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, RX_RING_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RX_RING_CSR);
        rt2x00_set_field32(&reg, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit);
        rt2x00_set_field32(&reg, RX_RING_CSR_RXD_SIZE,
                           rt2x00dev->rx->desc_size / 4);
@@ -1473,26 +1476,26 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
        rt2x00mmio_register_write(rt2x00dev, RX_RING_CSR, reg);
 
        entry_priv = rt2x00dev->rx->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, RX_BASE_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RX_BASE_CSR);
        rt2x00_set_field32(&reg, RX_BASE_CSR_RING_REGISTER,
                           entry_priv->desc_dma);
        rt2x00mmio_register_write(rt2x00dev, RX_BASE_CSR, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TX_DMA_DST_CSR);
        rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC0, 2);
        rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC1, 2);
        rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC2, 2);
        rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC3, 2);
        rt2x00mmio_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, LOAD_TX_RING_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, LOAD_TX_RING_CSR);
        rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC0, 1);
        rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1);
        rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1);
        rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1);
        rt2x00mmio_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR);
        rt2x00_set_field32(&reg, RX_CNTL_CSR_LOAD_RXD, 1);
        rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);
 
@@ -1503,13 +1506,13 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0);
        rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
        rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
        rt2x00_set_field32(&reg, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
        rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR1);
        rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */
        rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0_VALID, 1);
        rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1, 30); /* Rssi */
@@ -1523,7 +1526,7 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
        /*
         * CCK TXD BBP registers
         */
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR2, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR2);
        rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0, 13);
        rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0_VALID, 1);
        rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1, 12);
@@ -1537,7 +1540,7 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
        /*
         * OFDM TXD BBP registers
         */
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR3, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR3);
        rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0, 7);
        rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0_VALID, 1);
        rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1, 6);
@@ -1546,21 +1549,21 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2_VALID, 1);
        rt2x00mmio_register_write(rt2x00dev, TXRX_CSR3, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR7, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR7);
        rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_6MBS, 59);
        rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_9MBS, 53);
        rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_12MBS, 49);
        rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_18MBS, 46);
        rt2x00mmio_register_write(rt2x00dev, TXRX_CSR7, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR8, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR8);
        rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_24MBS, 44);
        rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_36MBS, 42);
        rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_48MBS, 42);
        rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
        rt2x00mmio_register_write(rt2x00dev, TXRX_CSR8, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
        rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
        rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
        rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
@@ -1573,7 +1576,7 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
 
        rt2x00mmio_register_write(rt2x00dev, MAC_CSR6, 0x00000fff);
 
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR9);
        rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
        rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg);
 
@@ -1619,24 +1622,24 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
         * These registers are cleared on read,
         * so we may pass a useless variable to store the value.
         */
-       rt2x00mmio_register_read(rt2x00dev, STA_CSR0, &reg);
-       rt2x00mmio_register_read(rt2x00dev, STA_CSR1, &reg);
-       rt2x00mmio_register_read(rt2x00dev, STA_CSR2, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, STA_CSR0);
+       reg = rt2x00mmio_register_read(rt2x00dev, STA_CSR1);
+       reg = rt2x00mmio_register_read(rt2x00dev, STA_CSR2);
 
        /*
         * Reset MAC and BBP registers.
         */
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR1);
        rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
        rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
        rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR1);
        rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
        rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
        rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR1);
        rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
        rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
 
@@ -1649,7 +1652,7 @@ static int rt61pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
        u8 value;
 
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt61pci_bbp_read(rt2x00dev, 0, &value);
+               value = rt61pci_bbp_read(rt2x00dev, 0);
                if ((value != 0xff) && (value != 0x00))
                        return 0;
                udelay(REGISTER_BUSY_DELAY);
@@ -1695,7 +1698,7 @@ static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev)
        rt61pci_bbp_write(rt2x00dev, 107, 0x04);
 
        for (i = 0; i < EEPROM_BBP_SIZE; i++) {
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+               eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i);
 
                if (eeprom != 0xffff && eeprom != 0x0000) {
                        reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
@@ -1722,10 +1725,10 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
         * should clear the register to assure a clean state.
         */
        if (state == STATE_RADIO_IRQ_ON) {
-               rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR);
                rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
 
-               rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR);
                rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
        }
 
@@ -1735,7 +1738,7 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
         */
        spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
 
-       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR);
        rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, mask);
        rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE, mask);
        rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, mask);
@@ -1743,7 +1746,7 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
        rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR);
        rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_0, mask);
        rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_1, mask);
        rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_2, mask);
@@ -1783,7 +1786,7 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
        /*
         * Enable RX.
         */
-       rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR);
        rt2x00_set_field32(&reg, RX_CNTL_CSR_ENABLE_RX_DMA, 1);
        rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);
 
@@ -1806,7 +1809,7 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
 
        put_to_sleep = (state != STATE_AWAKE);
 
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR12);
        rt2x00_set_field32(&reg, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
        rt2x00_set_field32(&reg, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
        rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg);
@@ -1817,7 +1820,7 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
         * device has entered the correct state.
         */
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, &reg2);
+               reg2 = rt2x00mmio_register_read(rt2x00dev, MAC_CSR12);
                state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
                if (state == !put_to_sleep)
                        return 0;
@@ -1876,7 +1879,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
        /*
         * Start writing the descriptor words.
         */
-       rt2x00_desc_read(txd, 1, &word);
+       word = rt2x00_desc_read(txd, 1);
        rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid);
        rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs);
        rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
@@ -1887,7 +1890,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
        rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
        rt2x00_desc_write(txd, 1, word);
 
-       rt2x00_desc_read(txd, 2, &word);
+       word = rt2x00_desc_read(txd, 2);
        rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
        rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
        rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
@@ -1901,7 +1904,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
                _rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
        }
 
-       rt2x00_desc_read(txd, 5, &word);
+       word = rt2x00_desc_read(txd, 5);
        rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
        rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx);
        rt2x00_set_field32(&word, TXD_W5_TX_POWER,
@@ -1910,12 +1913,12 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
        rt2x00_desc_write(txd, 5, word);
 
        if (entry->queue->qid != QID_BEACON) {
-               rt2x00_desc_read(txd, 6, &word);
+               word = rt2x00_desc_read(txd, 6);
                rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
                                   skbdesc->skb_dma);
                rt2x00_desc_write(txd, 6, word);
 
-               rt2x00_desc_read(txd, 11, &word);
+               word = rt2x00_desc_read(txd, 11);
                rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0,
                                   txdesc->length);
                rt2x00_desc_write(txd, 11, word);
@@ -1926,7 +1929,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
         * the device, whereby the device may take hold of the TXD before we
         * finished updating it.
         */
-       rt2x00_desc_read(txd, 0, &word);
+       word = rt2x00_desc_read(txd, 0);
        rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
        rt2x00_set_field32(&word, TXD_W0_VALID, 1);
        rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
@@ -1975,7 +1978,7 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
         * Disable beaconing while we are reloading the beacon data,
         * otherwise we might be sending out invalid data.
         */
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
        orig_reg = reg;
        rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
        rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
@@ -2036,7 +2039,7 @@ static void rt61pci_clear_beacon(struct queue_entry *entry)
         * Disable beaconing while we are reloading the beacon data,
         * otherwise we might be sending out invalid data.
         */
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &orig_reg);
+       orig_reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9);
        reg = orig_reg;
        rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
        rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
@@ -2092,8 +2095,8 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
        u32 word0;
        u32 word1;
 
-       rt2x00_desc_read(entry_priv->desc, 0, &word0);
-       rt2x00_desc_read(entry_priv->desc, 1, &word1);
+       word0 = rt2x00_desc_read(entry_priv->desc, 0);
+       word1 = rt2x00_desc_read(entry_priv->desc, 1);
 
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -2102,11 +2105,11 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
        rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
 
        if (rxdesc->cipher != CIPHER_NONE) {
-               _rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv[0]);
-               _rt2x00_desc_read(entry_priv->desc, 3, &rxdesc->iv[1]);
+               rxdesc->iv[0] = _rt2x00_desc_read(entry_priv->desc, 2);
+               rxdesc->iv[1] = _rt2x00_desc_read(entry_priv->desc, 3);
                rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
 
-               _rt2x00_desc_read(entry_priv->desc, 4, &rxdesc->icv);
+               rxdesc->icv = _rt2x00_desc_read(entry_priv->desc, 4);
                rxdesc->dev_flags |= RXDONE_CRYPTO_ICV;
 
                /*
@@ -2172,7 +2175,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
         * tx ring size for now.
         */
        for (i = 0; i < rt2x00dev->tx->limit; i++) {
-               rt2x00mmio_register_read(rt2x00dev, STA_CSR4, &reg);
+               reg = rt2x00mmio_register_read(rt2x00dev, STA_CSR4);
                if (!rt2x00_get_field32(reg, STA_CSR4_VALID))
                        break;
 
@@ -2195,7 +2198,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
 
                entry = &queue->entries[index];
                entry_priv = entry->priv_data;
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               word = rt2x00_desc_read(entry_priv->desc, 0);
 
                if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
                    !rt2x00_get_field32(word, TXD_W0_VALID))
@@ -2258,7 +2261,7 @@ static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
         */
        spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR);
        rt2x00_set_field32(&reg, irq_field, 0);
        rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
 
@@ -2276,7 +2279,7 @@ static void rt61pci_enable_mcu_interrupt(struct rt2x00_dev *rt2x00dev,
         */
        spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-       rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR);
        rt2x00_set_field32(&reg, irq_field, 0);
        rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
 
@@ -2328,10 +2331,10 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
         * Get the interrupt sources & saved to local variable.
         * Write register value back to clear pending interrupts.
         */
-       rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
+       reg_mcu = rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR);
        rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
 
-       rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR);
        rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
 
        if (!reg && !reg_mcu)
@@ -2369,11 +2372,11 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
         */
        spin_lock(&rt2x00dev->irqmask_lock);
 
-       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR);
        reg |= mask;
        rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR);
        reg |= mask_mcu;
        rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
 
@@ -2393,7 +2396,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        u8 *mac;
        s8 value;
 
-       rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR);
 
        eeprom.data = rt2x00dev;
        eeprom.register_read = rt61pci_eepromregister_read;
@@ -2414,7 +2417,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
        rt2x00lib_set_mac_address(rt2x00dev, mac);
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
                rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
@@ -2429,7 +2432,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_NIC_ENABLE_DIVERSITY, 0);
                rt2x00_set_field16(&word, EEPROM_NIC_TX_DIVERSITY, 0);
@@ -2442,7 +2445,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_LED);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_LED_LED_MODE,
                                   LED_MODE_DEFAULT);
@@ -2450,7 +2453,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
                rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);
@@ -2458,7 +2461,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
                rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
@@ -2474,7 +2477,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
                rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
@@ -2502,13 +2505,13 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Read EEPROM word for configuration.
         */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
 
        /*
         * Identify RF chipset.
         */
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR0);
        rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
                        value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
 
@@ -2549,7 +2552,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Read frequency offset and RF programming sequence.
         */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ);
        if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ))
                __set_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags);
 
@@ -2558,7 +2561,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Read external LNA informations.
         */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
 
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
                __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
@@ -2589,7 +2592,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * switch to default led mode.
         */
 #ifdef CONFIG_RT2X00_LIB_LEDS
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_LED);
        value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
 
        rt61pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
@@ -2850,7 +2853,7 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
         * Enable rfkill polling by setting GPIO direction of the
         * rfkill switch GPIO pin correctly.
         */
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, MAC_CSR13);
        rt2x00_set_field32(&reg, MAC_CSR13_DIR5, 1);
        rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg);
 
@@ -2922,7 +2925,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw,
        field.bit_offset = (queue_idx & 1) * 16;
        field.bit_mask = 0xffff << field.bit_offset;
 
-       rt2x00mmio_register_read(rt2x00dev, offset, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, offset);
        rt2x00_set_field32(&reg, field, queue->txop);
        rt2x00mmio_register_write(rt2x00dev, offset, reg);
 
@@ -2930,15 +2933,15 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw,
        field.bit_offset = queue_idx * 4;
        field.bit_mask = 0xf << field.bit_offset;
 
-       rt2x00mmio_register_read(rt2x00dev, AIFSN_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, AIFSN_CSR);
        rt2x00_set_field32(&reg, field, queue->aifs);
        rt2x00mmio_register_write(rt2x00dev, AIFSN_CSR, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, CWMIN_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CWMIN_CSR);
        rt2x00_set_field32(&reg, field, queue->cw_min);
        rt2x00mmio_register_write(rt2x00dev, CWMIN_CSR, reg);
 
-       rt2x00mmio_register_read(rt2x00dev, CWMAX_CSR, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, CWMAX_CSR);
        rt2x00_set_field32(&reg, field, queue->cw_max);
        rt2x00mmio_register_write(rt2x00dev, CWMAX_CSR, reg);
 
@@ -2951,9 +2954,9 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        u64 tsf;
        u32 reg;
 
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR13, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR13);
        tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR12, &reg);
+       reg = rt2x00mmio_register_read(rt2x00dev, TXRX_CSR12);
        tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
 
        return tsf;
index bb8d307a789ff77a619dc05fc045e58f79ee624b..fd913222abd1a013bdabbb47ebadbc1f648b9169 100644 (file)
@@ -84,10 +84,11 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
        mutex_unlock(&rt2x00dev->csr_mutex);
 }
 
-static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
-                            const unsigned int word, u8 *value)
+static u8 rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
+                          const unsigned int word)
 {
        u32 reg;
+       u8 value;
 
        mutex_lock(&rt2x00dev->csr_mutex);
 
@@ -110,9 +111,11 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
                WAIT_FOR_BBP(rt2x00dev, &reg);
        }
 
-       *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
+       value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
 
        mutex_unlock(&rt2x00dev->csr_mutex);
+
+       return value;
 }
 
 static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -185,7 +188,7 @@ static int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
 
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR13);
        return rt2x00_get_field32(reg, MAC_CSR13_VAL7);
 }
 
@@ -238,7 +241,7 @@ static int rt73usb_blink_set(struct led_classdev *led_cdev,
            container_of(led_cdev, struct rt2x00_led, led_dev);
        u32 reg;
 
-       rt2x00usb_register_read(led->rt2x00dev, MAC_CSR14, &reg);
+       reg = rt2x00usb_register_read(led->rt2x00dev, MAC_CSR14);
        rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
        rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
        rt2x00usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
@@ -283,7 +286,7 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
                 */
                mask = (0xf << crypto->bssidx);
 
-               rt2x00usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR0);
                reg &= mask;
 
                if (reg && reg == mask)
@@ -316,14 +319,14 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
                        field.bit_offset = (3 * key->hw_key_idx);
                        field.bit_mask = 0x7 << field.bit_offset;
 
-                       rt2x00usb_register_read(rt2x00dev, SEC_CSR1, &reg);
+                       reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR1);
                        rt2x00_set_field32(&reg, field, crypto->cipher);
                        rt2x00usb_register_write(rt2x00dev, SEC_CSR1, reg);
                } else {
                        field.bit_offset = (3 * (key->hw_key_idx - 8));
                        field.bit_mask = 0x7 << field.bit_offset;
 
-                       rt2x00usb_register_read(rt2x00dev, SEC_CSR5, &reg);
+                       reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR5);
                        rt2x00_set_field32(&reg, field, crypto->cipher);
                        rt2x00usb_register_write(rt2x00dev, SEC_CSR5, reg);
                }
@@ -348,7 +351,7 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
         */
        mask = 1 << key->hw_key_idx;
 
-       rt2x00usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR0);
        if (crypto->cmd == SET_KEY)
                reg |= mask;
        else if (crypto->cmd == DISABLE_KEY)
@@ -377,10 +380,10 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
                 * When both registers are full, we drop the key,
                 * otherwise we use the first invalid entry.
                 */
-               rt2x00usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR2);
                if (reg && reg == ~0) {
                        key->hw_key_idx = 32;
-                       rt2x00usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+                       reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR3);
                        if (reg && reg == ~0)
                                return -ENOSPC;
                }
@@ -417,7 +420,7 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
                 * without this received frames will not be decrypted
                 * by the hardware.
                 */
-               rt2x00usb_register_read(rt2x00dev, SEC_CSR4, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR4);
                reg |= (1 << crypto->bssidx);
                rt2x00usb_register_write(rt2x00dev, SEC_CSR4, reg);
 
@@ -442,7 +445,7 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
        if (key->hw_key_idx < 32) {
                mask = 1 << key->hw_key_idx;
 
-               rt2x00usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR2);
                if (crypto->cmd == SET_KEY)
                        reg |= mask;
                else if (crypto->cmd == DISABLE_KEY)
@@ -451,7 +454,7 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
        } else {
                mask = 1 << (key->hw_key_idx - 32);
 
-               rt2x00usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, SEC_CSR3);
                if (crypto->cmd == SET_KEY)
                        reg |= mask;
                else if (crypto->cmd == DISABLE_KEY)
@@ -473,7 +476,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
         * and broadcast frames will always be accepted since
         * there is no filter for it at this time.
         */
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
        rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
                           !(filter_flags & FIF_FCSFAIL));
        rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
@@ -505,7 +508,7 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
                /*
                 * Enable synchronisation.
                 */
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
                rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
                rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
        }
@@ -535,13 +538,13 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
 
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
        rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);
        rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
        rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
 
        if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR4);
                rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
                rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
                                   !!erp->short_preamble);
@@ -553,18 +556,18 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
                                         erp->basic_rates);
 
        if (changed & BSS_CHANGED_BEACON_INT) {
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
                rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
                                   erp->beacon_int * 16);
                rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
        }
 
        if (changed & BSS_CHANGED_ERP_SLOT) {
-               rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR9);
                rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
                rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
 
-               rt2x00usb_register_read(rt2x00dev, MAC_CSR8, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR8);
                rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
                rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
                rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
@@ -580,9 +583,9 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
        u8 r77;
        u8 temp;
 
-       rt73usb_bbp_read(rt2x00dev, 3, &r3);
-       rt73usb_bbp_read(rt2x00dev, 4, &r4);
-       rt73usb_bbp_read(rt2x00dev, 77, &r77);
+       r3 = rt73usb_bbp_read(rt2x00dev, 3);
+       r4 = rt73usb_bbp_read(rt2x00dev, 4);
+       r77 = rt73usb_bbp_read(rt2x00dev, 77);
 
        rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
 
@@ -627,9 +630,9 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
        u8 r4;
        u8 r77;
 
-       rt73usb_bbp_read(rt2x00dev, 3, &r3);
-       rt73usb_bbp_read(rt2x00dev, 4, &r4);
-       rt73usb_bbp_read(rt2x00dev, 77, &r77);
+       r3 = rt73usb_bbp_read(rt2x00dev, 3);
+       r4 = rt73usb_bbp_read(rt2x00dev, 4);
+       r77 = rt73usb_bbp_read(rt2x00dev, 77);
 
        rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
        rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
@@ -715,7 +718,7 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
        for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
                rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
 
-       rt2x00usb_register_read(rt2x00dev, PHY_CSR0, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, PHY_CSR0);
 
        rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
                           (rt2x00dev->curr_band == NL80211_BAND_2GHZ));
@@ -740,10 +743,10 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
                if (rt2x00_has_cap_external_lna_bg(rt2x00dev))
                        lna_gain += 14;
 
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+               eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG);
                lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
        } else {
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+               eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A);
                lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
        }
 
@@ -762,7 +765,7 @@ static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev,
 
        smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
 
-       rt73usb_bbp_read(rt2x00dev, 3, &r3);
+       r3 = rt73usb_bbp_read(rt2x00dev, 3);
        rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
        rt73usb_bbp_write(rt2x00dev, 3, r3);
 
@@ -796,10 +799,10 @@ static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
 {
        struct rf_channel rf;
 
-       rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
-       rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
-       rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
-       rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
+       rf.rf1 = rt2x00_rf_read(rt2x00dev, 1);
+       rf.rf2 = rt2x00_rf_read(rt2x00dev, 2);
+       rf.rf3 = rt2x00_rf_read(rt2x00dev, 3);
+       rf.rf4 = rt2x00_rf_read(rt2x00dev, 4);
 
        rt73usb_config_channel(rt2x00dev, &rf, txpower);
 }
@@ -809,7 +812,7 @@ static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
 
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR4);
        rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1);
        rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_STEP, 0);
        rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0);
@@ -829,7 +832,7 @@ static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev,
        u32 reg;
 
        if (state == STATE_SLEEP) {
-               rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR11);
                rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
                                   rt2x00dev->beacon_int - 10);
                rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
@@ -846,7 +849,7 @@ static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev,
                rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
                                            USB_MODE_SLEEP, REGISTER_TIMEOUT);
        } else {
-               rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR11);
                rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
                rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
                rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
@@ -888,13 +891,13 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
        /*
         * Update FCS error count from register.
         */
-       rt2x00usb_register_read(rt2x00dev, STA_CSR0, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, STA_CSR0);
        qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
 
        /*
         * Update False CCA count from register.
         */
-       rt2x00usb_register_read(rt2x00dev, STA_CSR1, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, STA_CSR1);
        qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
 }
 
@@ -1025,12 +1028,12 @@ static void rt73usb_start_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
                rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
                rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
                break;
        case QID_BEACON:
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
                rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
                rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
                rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
@@ -1048,12 +1051,12 @@ static void rt73usb_stop_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
                rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
                rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
                break;
        case QID_BEACON:
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
                rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
                rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
                rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
@@ -1112,7 +1115,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev,
         * Wait for stable hardware.
         */
        for (i = 0; i < 100; i++) {
-               rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+               reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR0);
                if (reg)
                        break;
                msleep(1);
@@ -1150,13 +1153,13 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
 
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR0);
        rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
        rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
        rt2x00_set_field32(&reg, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
        rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
 
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR1);
        rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */
        rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0_VALID, 1);
        rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1, 30); /* Rssi */
@@ -1170,7 +1173,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
        /*
         * CCK TXD BBP registers
         */
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR2);
        rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0, 13);
        rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0_VALID, 1);
        rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1, 12);
@@ -1184,7 +1187,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
        /*
         * OFDM TXD BBP registers
         */
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR3, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR3);
        rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0, 7);
        rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0_VALID, 1);
        rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1, 6);
@@ -1193,21 +1196,21 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2_VALID, 1);
        rt2x00usb_register_write(rt2x00dev, TXRX_CSR3, reg);
 
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR7, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR7);
        rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_6MBS, 59);
        rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_9MBS, 53);
        rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_12MBS, 49);
        rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_18MBS, 46);
        rt2x00usb_register_write(rt2x00dev, TXRX_CSR7, reg);
 
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR8, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR8);
        rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_24MBS, 44);
        rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_36MBS, 42);
        rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_48MBS, 42);
        rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
        rt2x00usb_register_write(rt2x00dev, TXRX_CSR8, reg);
 
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
        rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
        rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
        rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
@@ -1218,7 +1221,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
 
        rt2x00usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
 
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR6, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR6);
        rt2x00_set_field32(&reg, MAC_CSR6_MAX_FRAME_UNIT, 0xfff);
        rt2x00usb_register_write(rt2x00dev, MAC_CSR6, reg);
 
@@ -1246,7 +1249,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
        rt2x00usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408);
 
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR9);
        rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
        rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
 
@@ -1266,24 +1269,24 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
         * These registers are cleared on read,
         * so we may pass a useless variable to store the value.
         */
-       rt2x00usb_register_read(rt2x00dev, STA_CSR0, &reg);
-       rt2x00usb_register_read(rt2x00dev, STA_CSR1, &reg);
-       rt2x00usb_register_read(rt2x00dev, STA_CSR2, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, STA_CSR0);
+       reg = rt2x00usb_register_read(rt2x00dev, STA_CSR1);
+       reg = rt2x00usb_register_read(rt2x00dev, STA_CSR2);
 
        /*
         * Reset MAC and BBP registers.
         */
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR1);
        rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
        rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
        rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
 
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR1);
        rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
        rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
        rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
 
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR1);
        rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
        rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
 
@@ -1296,7 +1299,7 @@ static int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
        u8 value;
 
        for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
-               rt73usb_bbp_read(rt2x00dev, 0, &value);
+               value = rt73usb_bbp_read(rt2x00dev, 0);
                if ((value != 0xff) && (value != 0x00))
                        return 0;
                udelay(REGISTER_BUSY_DELAY);
@@ -1343,7 +1346,7 @@ static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev)
        rt73usb_bbp_write(rt2x00dev, 107, 0x04);
 
        for (i = 0; i < EEPROM_BBP_SIZE; i++) {
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+               eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i);
 
                if (eeprom != 0xffff && eeprom != 0x0000) {
                        reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
@@ -1390,7 +1393,7 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
 
        put_to_sleep = (state != STATE_AWAKE);
 
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR12, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR12);
        rt2x00_set_field32(&reg, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
        rt2x00_set_field32(&reg, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
        rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg);
@@ -1401,7 +1404,7 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
         * device has entered the correct state.
         */
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2x00usb_register_read(rt2x00dev, MAC_CSR12, &reg2);
+               reg2 = rt2x00usb_register_read(rt2x00dev, MAC_CSR12);
                state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
                if (state == !put_to_sleep)
                        return 0;
@@ -1459,7 +1462,7 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,
        /*
         * Start writing the descriptor words.
         */
-       rt2x00_desc_read(txd, 0, &word);
+       word = rt2x00_desc_read(txd, 0);
        rt2x00_set_field32(&word, TXD_W0_BURST,
                           test_bit(ENTRY_TXD_BURST, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_VALID, 1);
@@ -1485,7 +1488,7 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,
        rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
        rt2x00_desc_write(txd, 0, word);
 
-       rt2x00_desc_read(txd, 1, &word);
+       word = rt2x00_desc_read(txd, 1);
        rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid);
        rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs);
        rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
@@ -1495,7 +1498,7 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,
                           test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
        rt2x00_desc_write(txd, 1, word);
 
-       rt2x00_desc_read(txd, 2, &word);
+       word = rt2x00_desc_read(txd, 2);
        rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
        rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
        rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
@@ -1509,7 +1512,7 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,
                _rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
        }
 
-       rt2x00_desc_read(txd, 5, &word);
+       word = rt2x00_desc_read(txd, 5);
        rt2x00_set_field32(&word, TXD_W5_TX_POWER,
                           TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power));
        rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
@@ -1538,7 +1541,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
         * Disable beaconing while we are reloading the beacon data,
         * otherwise we might be sending out invalid data.
         */
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
        orig_reg = reg;
        rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
        rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
@@ -1603,7 +1606,7 @@ static void rt73usb_clear_beacon(struct queue_entry *entry)
         * Disable beaconing while we are reloading the beacon data,
         * otherwise we might be sending out invalid data.
         */
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &orig_reg);
+       orig_reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR9);
        reg = orig_reg;
        rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
        rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
@@ -1691,8 +1694,8 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
        /*
         * It is now safe to read the descriptor on all architectures.
         */
-       rt2x00_desc_read(rxd, 0, &word0);
-       rt2x00_desc_read(rxd, 1, &word1);
+       word0 = rt2x00_desc_read(rxd, 0);
+       word1 = rt2x00_desc_read(rxd, 1);
 
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
@@ -1701,11 +1704,11 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
        rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
 
        if (rxdesc->cipher != CIPHER_NONE) {
-               _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
-               _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]);
+               rxdesc->iv[0] = _rt2x00_desc_read(rxd, 2);
+               rxdesc->iv[1] = _rt2x00_desc_read(rxd, 3);
                rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
 
-               _rt2x00_desc_read(rxd, 4, &rxdesc->icv);
+               rxdesc->icv = _rt2x00_desc_read(rxd, 4);
                rxdesc->dev_flags |= RXDONE_CRYPTO_ICV;
 
                /*
@@ -1768,7 +1771,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
        mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
        rt2x00lib_set_mac_address(rt2x00dev, mac);
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
                rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
@@ -1783,14 +1786,14 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA, 0);
                rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
                rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_LED);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_LED_POLARITY_RDY_G, 0);
                rt2x00_set_field16(&word, EEPROM_LED_POLARITY_RDY_A, 0);
@@ -1806,7 +1809,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
                rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);
@@ -1814,7 +1817,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
                rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
@@ -1830,7 +1833,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
                rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
        }
 
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word);
+       word = rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
                rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
@@ -1858,13 +1861,13 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Read EEPROM word for configuration.
         */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA);
 
        /*
         * Identify RF chipset.
         */
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR0);
        rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
                        value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
 
@@ -1904,13 +1907,13 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Read frequency offset.
         */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ);
        rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
 
        /*
         * Read external LNA informations.
         */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC);
 
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) {
                __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
@@ -1921,7 +1924,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * Store led settings, for correct led behaviour.
         */
 #ifdef CONFIG_RT2X00_LIB_LEDS
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
+       eeprom = rt2x00_eeprom_read(rt2x00dev, EEPROM_LED);
 
        rt73usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
        rt73usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
@@ -2188,7 +2191,7 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
         * Enable rfkill polling by setting GPIO direction of the
         * rfkill switch GPIO pin correctly.
         */
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, MAC_CSR13);
        rt2x00_set_field32(&reg, MAC_CSR13_DIR7, 0);
        rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg);
 
@@ -2260,7 +2263,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw,
        field.bit_offset = (queue_idx & 1) * 16;
        field.bit_mask = 0xffff << field.bit_offset;
 
-       rt2x00usb_register_read(rt2x00dev, offset, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, offset);
        rt2x00_set_field32(&reg, field, queue->txop);
        rt2x00usb_register_write(rt2x00dev, offset, reg);
 
@@ -2268,15 +2271,15 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw,
        field.bit_offset = queue_idx * 4;
        field.bit_mask = 0xf << field.bit_offset;
 
-       rt2x00usb_register_read(rt2x00dev, AIFSN_CSR, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, AIFSN_CSR);
        rt2x00_set_field32(&reg, field, queue->aifs);
        rt2x00usb_register_write(rt2x00dev, AIFSN_CSR, reg);
 
-       rt2x00usb_register_read(rt2x00dev, CWMIN_CSR, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, CWMIN_CSR);
        rt2x00_set_field32(&reg, field, queue->cw_min);
        rt2x00usb_register_write(rt2x00dev, CWMIN_CSR, reg);
 
-       rt2x00usb_register_read(rt2x00dev, CWMAX_CSR, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, CWMAX_CSR);
        rt2x00_set_field32(&reg, field, queue->cw_max);
        rt2x00usb_register_write(rt2x00dev, CWMAX_CSR, reg);
 
@@ -2289,9 +2292,9 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        u64 tsf;
        u32 reg;
 
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR13, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR13);
        tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR12, &reg);
+       reg = rt2x00usb_register_read(rt2x00dev, TXRX_CSR12);
        tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
 
        return tsf;
index b94479441b0c77f41dada030834c8c4b64a86210..170cd504e8ff97bb92f5c96a31e958e4ff43e107 100644 (file)
@@ -247,7 +247,10 @@ static const UCHAR b4_default_startup_parms[] = {
        0x04, 0x08,             /* Noise gain, limit offset */
        0x28, 0x28,             /* det rssi, med busy offsets */
        7,                      /* det sync thresh */
-       0, 2, 2                 /* test mode, min, max */
+       0, 2, 2,                /* test mode, min, max */
+       0,                      /* rx/tx delay */
+       0, 0, 0, 0, 0, 0,       /* current BSS id */
+       0                       /* hop set */
 };
 
 /*===========================================================================*/
@@ -597,7 +600,7 @@ static void init_startup_params(ray_dev_t *local)
         *    a_beacon_period = hops    a_beacon_period = KuS
         *//* 64ms = 010000 */
        if (local->fw_ver == 0x55) {
-               memcpy((UCHAR *) &local->sparm.b4, b4_default_startup_parms,
+               memcpy(&local->sparm.b4, b4_default_startup_parms,
                       sizeof(struct b4_startup_params));
                /* Translate sane kus input values to old build 4/5 format */
                /* i = hop time in uS truncated to 3 bytes */
index 57e633dbf9a9ab76bdf31e4ec9c3c5094eab180e..9015512ed64720d3411cd446dffa4a3636b21c9a 100644 (file)
@@ -456,6 +456,39 @@ static void btc8192e2ant_query_bt_info(struct btc_coexist *btcoexist)
        btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter);
 }
 
+static
+bool btc8192e2ant_is_wifi_status_changed(struct btc_coexist *btcoexist)
+{
+       static bool pre_wifi_busy = false, pre_under_4way = false,
+                   pre_bt_hs_on = false;
+       bool wifi_busy = false, under_4way = false, bt_hs_on = false;
+       bool wifi_connected = false;
+
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
+                          &wifi_connected);
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS,
+                          &under_4way);
+
+       if (wifi_connected) {
+               if (wifi_busy != pre_wifi_busy) {
+                       pre_wifi_busy = wifi_busy;
+                       return true;
+               }
+               if (under_4way != pre_under_4way) {
+                       pre_under_4way = under_4way;
+                       return true;
+               }
+               if (bt_hs_on != pre_bt_hs_on) {
+                       pre_bt_hs_on = bt_hs_on;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 static void btc8192e2ant_update_bt_link_info(struct btc_coexist *btcoexist)
 {
        struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
@@ -2886,9 +2919,8 @@ void ex_btc8192e2ant_display_coex_info(struct btc_coexist *btcoexist)
        RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d",
                 "0x774(lp rx[31:16]/tx[15:0])",
                 coex_sta->low_priority_rx, coex_sta->low_priority_tx);
-#if (BT_AUTO_REPORT_ONLY_8192E_2ANT == 1)
-       btc8192e2ant_monitor_bt_ctr(btcoexist);
-#endif
+       if (btcoexist->auto_report_2ant)
+               btc8192e2ant_monitor_bt_ctr(btcoexist);
        btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS);
 }
 
@@ -3078,14 +3110,12 @@ void ex_btc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist,
                         */
                }
 
-#if (BT_AUTO_REPORT_ONLY_8192E_2ANT == 0)
-               if ((coex_sta->bt_info_ext & BIT4)) {
-                       /* BT auto report already enabled, do nothing */
-               } else {
-                       btc8192e2ant_bt_auto_report(btcoexist, FORCE_EXEC,
-                                                   true);
+               if (!btcoexist->auto_report_2ant) {
+                       if (!(coex_sta->bt_info_ext & BIT4))
+                               btc8192e2ant_bt_auto_report(btcoexist,
+                                                           FORCE_EXEC,
+                                                           true);
                }
-#endif
        }
 
        /* check BIT2 first ==> check if bt is under inquiry or page scan */
@@ -3207,13 +3237,13 @@ void ex_btc8192e2ant_periodical(struct btc_coexist *btcoexist)
                         "************************************************\n");
        }
 
-#if (BT_AUTO_REPORT_ONLY_8192E_2ANT == 0)
-       btc8192e2ant_query_bt_info(btcoexist);
-       btc8192e2ant_monitor_bt_ctr(btcoexist);
-       btc8192e2ant_monitor_bt_enable_disable(btcoexist);
-#else
-       if (btc8192e2ant_is_wifi_status_changed(btcoexist) ||
-           coex_dm->auto_tdma_adjust)
-               btc8192e2ant_run_coexist_mechanism(btcoexist);
-#endif
+       if (!btcoexist->auto_report_2ant) {
+               btc8192e2ant_query_bt_info(btcoexist);
+               btc8192e2ant_monitor_bt_ctr(btcoexist);
+               btc8192e2ant_monitor_bt_enable_disable(btcoexist);
+       } else {
+               if (btc8192e2ant_is_wifi_status_changed(btcoexist) ||
+                   coex_dm->auto_tdma_adjust)
+                       btc8192e2ant_run_coexist_mechanism(btcoexist);
+       }
 }
index fc0fa87ec404aa94a6185e87478f1f545783dbea..a57d6947eaf71a54d5f6e50a962ff78f874ea279 100644 (file)
@@ -25,8 +25,6 @@
 /*****************************************************************
  *   The following is for 8192E 2Ant BT Co-exist definition
  *****************************************************************/
-#define        BT_AUTO_REPORT_ONLY_8192E_2ANT                  0
-
 #define        BT_INFO_8192E_2ANT_B_FTP                        BIT7
 #define        BT_INFO_8192E_2ANT_B_A2DP                       BIT6
 #define        BT_INFO_8192E_2ANT_B_HID                        BIT5
index 2003c8c51dcc4c9deefcbe5f1045b010e53cc080..a0f3a18add250f2e5cc1d6456366cf715328a447 100644 (file)
@@ -210,11 +210,24 @@ static void halbtc8723b1ant_limited_rx(struct btc_coexist *btcoexist,
        btcoexist->btc_set(btcoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL);
 }
 
+static void halbtc8723b1ant_query_bt_info(struct btc_coexist *btcoexist)
+{
+       u8 h2c_parameter[1] = {0};
+
+       coex_sta->c2h_bt_info_req_sent = true;
+
+       /* trigger */
+       h2c_parameter[0] |= BIT(0);
+
+       btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter);
+}
+
 static void halbtc8723b1ant_monitor_bt_ctr(struct btc_coexist *btcoexist)
 {
        u32 reg_hp_txrx, reg_lp_txrx, u32tmp;
        u32 reg_hp_tx = 0, reg_hp_rx = 0;
        u32 reg_lp_tx = 0, reg_lp_rx = 0;
+       static u32 num_of_bt_counter_chk;
 
        reg_hp_txrx = 0x770;
        reg_lp_txrx = 0x774;
@@ -232,25 +245,122 @@ static void halbtc8723b1ant_monitor_bt_ctr(struct btc_coexist *btcoexist)
        coex_sta->low_priority_tx = reg_lp_tx;
        coex_sta->low_priority_rx = reg_lp_rx;
 
+       if ((coex_sta->low_priority_tx > 1050) &&
+           (!coex_sta->c2h_bt_inquiry_page))
+               coex_sta->pop_event_cnt++;
+
        /* reset counter */
        btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc);
+
+       /* This part is for wifi FW and driver to update BT's status as
+        * disabled.
+        *
+        * The flow is as the following
+        * 1. disable BT
+        * 2. if all BT Tx/Rx counter = 0, after 6 sec we query bt info
+        * 3. Because BT will not rsp from mailbox, so wifi fw will know BT is
+        * disabled
+        *
+        * 4. FW will rsp c2h for BT that driver will know BT is disabled.
+        */
+       if ((reg_hp_tx == 0) && (reg_hp_rx == 0) && (reg_lp_tx == 0) &&
+           (reg_lp_rx == 0)) {
+               num_of_bt_counter_chk++;
+               if (num_of_bt_counter_chk == 3)
+                       halbtc8723b1ant_query_bt_info(btcoexist);
+       } else {
+               num_of_bt_counter_chk = 0;
+       }
 }
 
-static void halbtc8723b1ant_query_bt_info(struct btc_coexist *btcoexist)
+static void halbtc8723b1ant_monitor_wifi_ctr(struct btc_coexist *btcoexist)
 {
-       struct rtl_priv *rtlpriv = btcoexist->adapter;
-       u8 h2c_parameter[1] = {0};
+       s32 wifi_rssi = 0;
+       bool wifi_busy = false, wifi_under_b_mode = false;
+       static u8 cck_lock_counter;
+       u32 total_cnt;
 
-       coex_sta->c2h_bt_info_req_sent = true;
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
+       btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi);
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_B_MODE,
+                          &wifi_under_b_mode);
 
-       /* trigger */
-       h2c_parameter[0] |= BIT0;
+       if (coex_sta->under_ips) {
+               coex_sta->crc_ok_cck = 0;
+               coex_sta->crc_ok_11g = 0;
+               coex_sta->crc_ok_11n = 0;
+               coex_sta->crc_ok_11n_agg = 0;
+
+               coex_sta->crc_err_cck = 0;
+               coex_sta->crc_err_11g = 0;
+               coex_sta->crc_err_11n = 0;
+               coex_sta->crc_err_11n_agg = 0;
+       } else {
+               coex_sta->crc_ok_cck =
+                       btcoexist->btc_read_4byte(btcoexist, 0xf88);
+               coex_sta->crc_ok_11g =
+                       btcoexist->btc_read_2byte(btcoexist, 0xf94);
+               coex_sta->crc_ok_11n =
+                       btcoexist->btc_read_2byte(btcoexist, 0xf90);
+               coex_sta->crc_ok_11n_agg =
+                       btcoexist->btc_read_2byte(btcoexist, 0xfb8);
+
+               coex_sta->crc_err_cck =
+                       btcoexist->btc_read_4byte(btcoexist, 0xf84);
+               coex_sta->crc_err_11g =
+                       btcoexist->btc_read_2byte(btcoexist, 0xf96);
+               coex_sta->crc_err_11n =
+                       btcoexist->btc_read_2byte(btcoexist, 0xf92);
+               coex_sta->crc_err_11n_agg =
+                       btcoexist->btc_read_2byte(btcoexist, 0xfba);
+       }
 
-       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n",
-                h2c_parameter[0]);
+       /* reset counter */
+       btcoexist->btc_write_1byte_bitmask(btcoexist, 0xf16, 0x1, 0x1);
+       btcoexist->btc_write_1byte_bitmask(btcoexist, 0xf16, 0x1, 0x0);
+
+       if ((wifi_busy) && (wifi_rssi >= 30) && (!wifi_under_b_mode)) {
+               total_cnt = coex_sta->crc_ok_cck + coex_sta->crc_ok_11g +
+                           coex_sta->crc_ok_11n + coex_sta->crc_ok_11n_agg;
+
+               if ((coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) ||
+                   (coex_dm->bt_status ==
+                    BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) ||
+                   (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_SCO_BUSY)) {
+                       if (coex_sta->crc_ok_cck >
+                           (total_cnt - coex_sta->crc_ok_cck)) {
+                               if (cck_lock_counter < 3)
+                                       cck_lock_counter++;
+                       } else {
+                               if (cck_lock_counter > 0)
+                                       cck_lock_counter--;
+                       }
 
-       btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter);
+               } else {
+                       if (cck_lock_counter > 0)
+                               cck_lock_counter--;
+               }
+       } else {
+               if (cck_lock_counter > 0)
+                       cck_lock_counter--;
+       }
+
+       if (!coex_sta->pre_ccklock) {
+               if (cck_lock_counter >= 3)
+                       coex_sta->cck_lock = true;
+               else
+                       coex_sta->cck_lock = false;
+       } else {
+               if (cck_lock_counter == 0)
+                       coex_sta->cck_lock = false;
+               else
+                       coex_sta->cck_lock = true;
+       }
+
+       if (coex_sta->cck_lock)
+               coex_sta->cck_ever_lock = true;
+
+       coex_sta->pre_ccklock = coex_sta->cck_lock;
 }
 
 static bool btc8723b1ant_is_wifi_status_changed(struct btc_coexist *btcoexist)
@@ -297,6 +407,7 @@ static void halbtc8723b1ant_update_bt_link_info(struct btc_coexist *btcoexist)
        bt_link_info->a2dp_exist = coex_sta->a2dp_exist;
        bt_link_info->pan_exist = coex_sta->pan_exist;
        bt_link_info->hid_exist = coex_sta->hid_exist;
+       bt_link_info->bt_hi_pri_link_exist = coex_sta->bt_hi_pri_link_exist;
 
        /* work around for HS mode. */
        if (bt_hs_on) {
@@ -333,6 +444,35 @@ static void halbtc8723b1ant_update_bt_link_info(struct btc_coexist *btcoexist)
                bt_link_info->hid_only = false;
 }
 
+static void halbtc8723b1ant_set_bt_auto_report(struct btc_coexist *btcoexist,
+                                              bool enable_auto_report)
+{
+       u8 h2c_parameter[1] = {0};
+
+       h2c_parameter[0] = 0;
+
+       if (enable_auto_report)
+               h2c_parameter[0] |= BIT(0);
+
+       btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter);
+}
+
+static void halbtc8723b1ant_bt_auto_report(struct btc_coexist *btcoexist,
+                                          bool force_exec,
+                                          bool enable_auto_report)
+{
+       coex_dm->cur_bt_auto_report = enable_auto_report;
+
+       if (!force_exec) {
+               if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report)
+                       return;
+       }
+       halbtc8723b1ant_set_bt_auto_report(btcoexist,
+                                          coex_dm->cur_bt_auto_report);
+
+       coex_dm->pre_bt_auto_report = coex_dm->cur_bt_auto_report;
+}
+
 static void btc8723b1ant_set_sw_pen_tx_rate_adapt(struct btc_coexist *btcoexist,
                                                  bool low_penalty_ra)
 {
@@ -430,6 +570,8 @@ static void halbtc8723b1ant_coex_table(struct btc_coexist *btcoexist,
 static void halbtc8723b1ant_coex_table_with_type(struct btc_coexist *btcoexist,
                                                 bool force_exec, u8 type)
 {
+       coex_sta->coex_table_type = type;
+
        switch (type) {
        case 0:
                halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555,
@@ -445,24 +587,68 @@ static void halbtc8723b1ant_coex_table_with_type(struct btc_coexist *btcoexist,
                break;
        case 3:
                halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555,
-                                          0xaaaaaaaa, 0xffffff, 0x3);
+                                          0x5a5a5a5a, 0xffffff, 0x3);
                break;
        case 4:
-               halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555,
-                                          0x5aaa5aaa, 0xffffff, 0x3);
+               if ((coex_sta->cck_ever_lock) && (coex_sta->scan_ap_num <= 5))
+                       halbtc8723b1ant_coex_table(btcoexist, force_exec,
+                                                  0x55555555, 0xaaaa5a5a,
+                                                  0xffffff, 0x3);
+               else
+                       halbtc8723b1ant_coex_table(btcoexist, force_exec,
+                                                  0x55555555, 0x5a5a5a5a,
+                                                  0xffffff, 0x3);
                break;
        case 5:
-               halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a,
-                                          0xaaaa5a5a, 0xffffff, 0x3);
+               if ((coex_sta->cck_ever_lock) && (coex_sta->scan_ap_num <= 5))
+                       halbtc8723b1ant_coex_table(btcoexist, force_exec,
+                                                  0x5a5a5a5a, 0x5aaa5a5a,
+                                                  0xffffff, 0x3);
+               else
+                       halbtc8723b1ant_coex_table(btcoexist, force_exec,
+                                                  0x5a5a5a5a, 0x5aaa5a5a,
+                                                  0xffffff, 0x3);
                break;
        case 6:
                halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555,
-                                          0xaaaa5a5a, 0xffffff, 0x3);
+                                          0xaaaaaaaa, 0xffffff, 0x3);
                break;
        case 7:
                halbtc8723b1ant_coex_table(btcoexist, force_exec, 0xaaaaaaaa,
                                           0xaaaaaaaa, 0xffffff, 0x3);
                break;
+       case 8:
+               halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55dd55dd,
+                                          0x5ada5ada, 0xffffff, 0x3);
+               break;
+       case 9:
+               halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55dd55dd,
+                                          0x5ada5ada, 0xffffff, 0x3);
+               break;
+       case 10:
+               halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55dd55dd,
+                                          0x5ada5ada, 0xffffff, 0x3);
+               break;
+       case 11:
+               halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55dd55dd,
+                                          0x5ada5ada, 0xffffff, 0x3);
+               break;
+       case 12:
+               halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55dd55dd,
+                                          0x5ada5ada, 0xffffff, 0x3);
+               break;
+       case 13:
+               halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x5fff5fff,
+                                          0xaaaaaaaa, 0xffffff, 0x3);
+               break;
+       case 14:
+               halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x5fff5fff,
+                                          0x5ada5ada, 0xffffff, 0x3);
+               break;
+       case 15:
+               halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55dd55dd,
+                                          0xaaaaaaaa, 0xffffff, 0x3);
+               break;
        default:
                break;
        }
@@ -611,14 +797,18 @@ static void halbtc8723b1ant_sw_mechanism(struct btc_coexist *btcoexist,
 }
 
 static void halbtc8723b1ant_set_ant_path(struct btc_coexist *btcoexist,
-                                        u8 ant_pos_type, bool init_hw_cfg,
-                                        bool wifi_off)
+                                        u8 ant_pos_type, bool force_exec,
+                                        bool init_hw_cfg, bool wifi_off)
 {
+       struct rtl_priv *rtlpriv = btcoexist->adapter;
        struct btc_board_info *board_info = &btcoexist->board_info;
-       u32 fw_ver = 0, u32tmp = 0;
+       u32 fw_ver = 0, u32tmp = 0, cnt_bt_cal_chk = 0;
        bool pg_ext_switch = false;
        bool use_ext_switch = false;
-       u8 h2c_parameter[2] = {0};
+       bool is_in_mp_mode = false;
+       u8 h2c_parameter[2] = {0}, u8tmp = 0;
+
+       coex_dm->cur_ant_pos_type = ant_pos_type;
 
        btcoexist->btc_get(btcoexist, BTC_GET_BL_EXT_SWITCH, &pg_ext_switch);
        /* [31:16] = fw ver, [15:0] = fw sub ver */
@@ -628,24 +818,103 @@ static void halbtc8723b1ant_set_ant_path(struct btc_coexist *btcoexist,
                use_ext_switch = true;
 
        if (init_hw_cfg) {
-               /*BT select s0/s1 is controlled by WiFi */
-               btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67, 0x20, 0x1);
+               /* WiFi TRx Mask on */
+               btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff,
+                                         0x780);
+               /* remove due to interrupt is disabled that polling c2h will
+                * fail and delay 100ms.
+                */
 
-               /*Force GNT_BT to Normal */
-               btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x0);
-       } else if (wifi_off) {
-               /*Force GNT_BT to High */
-               btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x3);
-               /*BT select s0/s1 is controlled by BT */
+               if (fw_ver >= 0x180000) {
+                       /* Use H2C to set GNT_BT to HIGH */
+                       h2c_parameter[0] = 1;
+                       btcoexist->btc_fill_h2c(btcoexist, 0x6E, 1,
+                                               h2c_parameter);
+               } else {
+                       /* set grant_bt to high */
+                       btcoexist->btc_write_1byte(btcoexist, 0x765, 0x18);
+               }
+               /* set wlan_act control by PTA */
+               btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4);
+
+               /* BT select s0/s1 is controlled by BT */
                btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67, 0x20, 0x0);
+               btcoexist->btc_write_1byte_bitmask(btcoexist, 0x39, 0x8, 0x1);
+               btcoexist->btc_write_1byte(btcoexist, 0x974, 0xff);
+               btcoexist->btc_write_1byte_bitmask(btcoexist, 0x944, 0x3, 0x3);
+               btcoexist->btc_write_1byte(btcoexist, 0x930, 0x77);
+       } else if (wifi_off) {
+               if (fw_ver >= 0x180000) {
+                       /* Use H2C to set GNT_BT to HIGH */
+                       h2c_parameter[0] = 1;
+                       btcoexist->btc_fill_h2c(btcoexist, 0x6E, 1,
+                                               h2c_parameter);
+               } else {
+                       /* set grant_bt to high */
+                       btcoexist->btc_write_1byte(btcoexist, 0x765, 0x18);
+               }
+               /* set wlan_act to always low */
+               btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4);
+
+               btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_IS_IN_MP_MODE,
+                                  &is_in_mp_mode);
+               if (!is_in_mp_mode)
+                       /* BT select s0/s1 is controlled by BT */
+                       btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67,
+                                                          0x20, 0x0);
+               else
+                       /* BT select s0/s1 is controlled by WiFi */
+                       btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67,
+                                                          0x20, 0x1);
 
-               /* 0x4c[24:23] = 00, Set Antenna control by BT_RFE_CTRL
-                * BT Vendor 0xac = 0xf002
+               /* 0x4c[24:23]=00, Set Antenna control by BT_RFE_CTRL
+                * BT Vendor 0xac=0xf002
                 */
                u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c);
                u32tmp &= ~BIT23;
                u32tmp &= ~BIT24;
                btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp);
+       } else {
+               /* Use H2C to set GNT_BT to LOW */
+               if (fw_ver >= 0x180000) {
+                       if (btcoexist->btc_read_1byte(btcoexist, 0x765) != 0) {
+                               h2c_parameter[0] = 0;
+                               btcoexist->btc_fill_h2c(btcoexist, 0x6E, 1,
+                                                       h2c_parameter);
+                       }
+               } else {
+                       /* BT calibration check */
+                       while (cnt_bt_cal_chk <= 20) {
+                               u8tmp = btcoexist->btc_read_1byte(btcoexist,
+                                                                 0x49d);
+                               cnt_bt_cal_chk++;
+                               if (u8tmp & BIT(0)) {
+                                       RT_TRACE(rtlpriv, COMP_BT_COEXIST,
+                                                DBG_LOUD,
+                                                "[BTCoex], ########### BT is calibrating (wait cnt=%d) ###########\n",
+                                                cnt_bt_cal_chk);
+                                       mdelay(50);
+                               } else {
+                                       RT_TRACE(rtlpriv, COMP_BT_COEXIST,
+                                                DBG_LOUD,
+                                                "[BTCoex], ********** BT is NOT calibrating (wait cnt=%d)**********\n",
+                                                cnt_bt_cal_chk);
+                                       break;
+                               }
+                       }
+
+                       /* set grant_bt to PTA */
+                       btcoexist->btc_write_1byte(btcoexist, 0x765, 0x0);
+               }
+
+               if (btcoexist->btc_read_1byte(btcoexist, 0x76e) != 0xc) {
+                       /* set wlan_act control by PTA */
+                       btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc);
+               }
+
+               btcoexist->btc_write_1byte_bitmask(
+                       btcoexist, 0x67, 0x20,
+                       0x1); /* BT select s0/s1 is controlled by WiFi */
        }
 
        if (use_ext_switch) {
@@ -658,216 +927,278 @@ static void halbtc8723b1ant_set_ant_path(struct btc_coexist *btcoexist,
                        u32tmp |= BIT24;
                        btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp);
 
+                       /* fixed internal switch S1->WiFi, S0->BT */
+                       btcoexist->btc_write_4byte(btcoexist, 0x948, 0x0);
+
                        if (board_info->btdm_ant_pos ==
                            BTC_ANTENNA_AT_MAIN_PORT) {
-                               /* Main Ant to BT for IPS case 0x4c[23] = 1 */
-                               btcoexist->btc_write_1byte_bitmask(btcoexist,
-                                                                  0x64, 0x1,
-                                                                  0x1);
-
                                /* tell firmware "no antenna inverse" */
                                h2c_parameter[0] = 0;
-                               h2c_parameter[1] = 1;  /*ext switch type*/
+                               /* ext switch type */
+                               h2c_parameter[1] = 1;
                                btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
                                                        h2c_parameter);
                        } else {
-                               /* Aux Ant to  BT for IPS case 0x4c[23] = 1 */
-                               btcoexist->btc_write_1byte_bitmask(btcoexist,
-                                                                  0x64, 0x1,
-                                                                  0x0);
-
                                /* tell firmware "antenna inverse" */
                                h2c_parameter[0] = 1;
-                               h2c_parameter[1] = 1; /* ext switch type */
+                               /* ext switch type */
+                               h2c_parameter[1] = 1;
                                btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
                                                        h2c_parameter);
                        }
                }
 
-               /* fixed internal switch first
-                * fixed internal switch S1->WiFi, S0->BT
-                */
-               if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT)
-                       btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
-               else    /* fixed internal switch S0->WiFi, S1->BT */
-                       btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280);
-
-               /* ext switch setting */
-               switch (ant_pos_type) {
-               case BTC_ANT_PATH_WIFI:
-                       if (board_info->btdm_ant_pos ==
-                           BTC_ANTENNA_AT_MAIN_PORT)
-                               btcoexist->btc_write_1byte_bitmask(btcoexist,
-                                                                  0x92c, 0x3,
-                                                                  0x1);
-                       else
-                               btcoexist->btc_write_1byte_bitmask(btcoexist,
-                                                                  0x92c, 0x3,
-                                                                  0x2);
-                       break;
-               case BTC_ANT_PATH_BT:
-                       if (board_info->btdm_ant_pos ==
-                           BTC_ANTENNA_AT_MAIN_PORT)
-                               btcoexist->btc_write_1byte_bitmask(btcoexist,
-                                                                  0x92c, 0x3,
-                                                                  0x2);
-                       else
-                               btcoexist->btc_write_1byte_bitmask(btcoexist,
-                                                                  0x92c, 0x3,
-                                                                  0x1);
-                       break;
-               default:
-               case BTC_ANT_PATH_PTA:
-                       if (board_info->btdm_ant_pos ==
-                           BTC_ANTENNA_AT_MAIN_PORT)
-                               btcoexist->btc_write_1byte_bitmask(btcoexist,
-                                                                  0x92c, 0x3,
-                                                                  0x1);
-                       else
-                               btcoexist->btc_write_1byte_bitmask(btcoexist,
-                                                                  0x92c, 0x3,
-                                                                  0x2);
-                       break;
+               if (force_exec ||
+                   (coex_dm->cur_ant_pos_type != coex_dm->pre_ant_pos_type)) {
+                       /* ext switch setting */
+                       switch (ant_pos_type) {
+                       case BTC_ANT_PATH_WIFI:
+                               if (board_info->btdm_ant_pos ==
+                                   BTC_ANTENNA_AT_MAIN_PORT)
+                                       btcoexist->btc_write_1byte_bitmask(
+                                               btcoexist, 0x92c, 0x3, 0x1);
+                               else
+                                       btcoexist->btc_write_1byte_bitmask(
+                                               btcoexist, 0x92c, 0x3, 0x2);
+                               break;
+                       case BTC_ANT_PATH_BT:
+                               if (board_info->btdm_ant_pos ==
+                                   BTC_ANTENNA_AT_MAIN_PORT)
+                                       btcoexist->btc_write_1byte_bitmask(
+                                               btcoexist, 0x92c, 0x3, 0x2);
+                               else
+                                       btcoexist->btc_write_1byte_bitmask(
+                                               btcoexist, 0x92c, 0x3, 0x1);
+                               break;
+                       default:
+                       case BTC_ANT_PATH_PTA:
+                               if (board_info->btdm_ant_pos ==
+                                   BTC_ANTENNA_AT_MAIN_PORT)
+                                       btcoexist->btc_write_1byte_bitmask(
+                                               btcoexist, 0x92c, 0x3, 0x1);
+                               else
+                                       btcoexist->btc_write_1byte_bitmask(
+                                               btcoexist, 0x92c, 0x3, 0x2);
+                               break;
+                       }
                }
-
        } else {
                if (init_hw_cfg) {
-                       /* 0x4c[23] = 1, 0x4c[24] = 0 Antenna control by 0x64 */
+                       /* 0x4c[23] = 1, 0x4c[24] = 0,
+                        * Antenna control by 0x64
+                        */
                        u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c);
                        u32tmp |= BIT23;
                        u32tmp &= ~BIT24;
                        btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp);
 
+                       /* Fix Ext switch Main->S1, Aux->S0 */
+                       btcoexist->btc_write_1byte_bitmask(btcoexist, 0x64, 0x1,
+                                                          0x0);
+
                        if (board_info->btdm_ant_pos ==
                            BTC_ANTENNA_AT_MAIN_PORT) {
-                               /* Main Ant to WiFi for IPS case 0x4c[23] = 1 */
-                               btcoexist->btc_write_1byte_bitmask(btcoexist,
-                                                                  0x64, 0x1,
-                                                                  0x0);
-
                                /* tell firmware "no antenna inverse" */
                                h2c_parameter[0] = 0;
-                               h2c_parameter[1] = 0; /* internal switch type */
+                               /* internal switch type */
+                               h2c_parameter[1] = 0;
                                btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
                                                        h2c_parameter);
                        } else {
-                               /* Aux Ant to BT for IPS case 0x4c[23] = 1 */
-                               btcoexist->btc_write_1byte_bitmask(btcoexist,
-                                                                  0x64, 0x1,
-                                                                  0x1);
-
                                /* tell firmware "antenna inverse" */
                                h2c_parameter[0] = 1;
-                               h2c_parameter[1] = 0; /* internal switch type */
+                               /* internal switch type */
+                               h2c_parameter[1] = 0;
                                btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
                                                        h2c_parameter);
                        }
                }
 
-               /* fixed external switch first
-                * Main->WiFi, Aux->BT
-                */
-               if (board_info->btdm_ant_pos ==
-                       BTC_ANTENNA_AT_MAIN_PORT)
-                       btcoexist->btc_write_1byte_bitmask(btcoexist, 0x92c,
-                                                          0x3, 0x1);
-               else    /* Main->BT, Aux->WiFi */
-                       btcoexist->btc_write_1byte_bitmask(btcoexist, 0x92c,
-                                                          0x3, 0x2);
-
-               /* internal switch setting */
-               switch (ant_pos_type) {
-               case BTC_ANT_PATH_WIFI:
-                       if (board_info->btdm_ant_pos ==
-                               BTC_ANTENNA_AT_MAIN_PORT)
-                               btcoexist->btc_write_2byte(btcoexist, 0x948,
-                                                          0x0);
-                       else
-                               btcoexist->btc_write_2byte(btcoexist, 0x948,
-                                                          0x280);
-                       break;
-               case BTC_ANT_PATH_BT:
-                       if (board_info->btdm_ant_pos ==
-                               BTC_ANTENNA_AT_MAIN_PORT)
-                               btcoexist->btc_write_2byte(btcoexist, 0x948,
-                                                          0x280);
-                       else
-                               btcoexist->btc_write_2byte(btcoexist, 0x948,
-                                                          0x0);
-                       break;
-               default:
-               case BTC_ANT_PATH_PTA:
-                       if (board_info->btdm_ant_pos ==
-                               BTC_ANTENNA_AT_MAIN_PORT)
-                               btcoexist->btc_write_2byte(btcoexist, 0x948,
-                                                          0x200);
-                       else
-                               btcoexist->btc_write_2byte(btcoexist, 0x948,
-                                                          0x80);
-                       break;
+               if (force_exec ||
+                   (coex_dm->cur_ant_pos_type != coex_dm->pre_ant_pos_type)) {
+                       /* internal switch setting */
+                       switch (ant_pos_type) {
+                       case BTC_ANT_PATH_WIFI:
+                               if (board_info->btdm_ant_pos ==
+                                   BTC_ANTENNA_AT_MAIN_PORT)
+                                       btcoexist->btc_write_4byte(btcoexist,
+                                                       0x948, 0x0);
+                               else
+                                       btcoexist->btc_write_4byte(btcoexist,
+                                                       0x948, 0x280);
+                               break;
+                       case BTC_ANT_PATH_BT:
+                               if (board_info->btdm_ant_pos ==
+                                   BTC_ANTENNA_AT_MAIN_PORT)
+                                       btcoexist->btc_write_4byte(btcoexist,
+                                                       0x948, 0x280);
+                               else
+                                       btcoexist->btc_write_4byte(btcoexist,
+                                                       0x948, 0x0);
+                               break;
+                       default:
+                       case BTC_ANT_PATH_PTA:
+                               if (board_info->btdm_ant_pos ==
+                                   BTC_ANTENNA_AT_MAIN_PORT)
+                                       btcoexist->btc_write_4byte(btcoexist,
+                                                       0x948, 0x200);
+                               else
+                                       btcoexist->btc_write_4byte(btcoexist,
+                                                       0x948, 0x80);
+                               break;
+                       }
                }
        }
+
+       coex_dm->pre_ant_pos_type = coex_dm->cur_ant_pos_type;
 }
 
 static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist,
                                    bool force_exec, bool turn_on, u8 type)
 {
-       struct rtl_priv *rtlpriv = btcoexist->adapter;
+       struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
        bool wifi_busy = false;
        u8 rssi_adjust_val = 0;
+       u8 ps_tdma_byte0_val = 0x51;
+       u8 ps_tdma_byte3_val = 0x10;
+       u8 ps_tdma_byte4_val = 0x50;
+       s8 wifi_duration_adjust = 0x0;
+       static bool pre_wifi_busy;
 
        coex_dm->cur_ps_tdma_on = turn_on;
        coex_dm->cur_ps_tdma = type;
 
        btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
 
-       if (!force_exec) {
-               if (coex_dm->cur_ps_tdma_on)
-                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                                "[BTCoex], ******** TDMA(on, %d) *********\n",
-                                coex_dm->cur_ps_tdma);
-               else
-                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                                "[BTCoex], ******** TDMA(off, %d) ********\n",
-                                coex_dm->cur_ps_tdma);
+       if (wifi_busy != pre_wifi_busy) {
+               force_exec = true;
+               pre_wifi_busy = wifi_busy;
+       }
 
+       if (!force_exec) {
                if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) &&
                    (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma))
                        return;
        }
+
+       if (coex_sta->scan_ap_num <= 5) {
+               wifi_duration_adjust = 5;
+
+               if (coex_sta->a2dp_bit_pool >= 35)
+                       wifi_duration_adjust = -10;
+               else if (coex_sta->a2dp_bit_pool >= 45)
+                       wifi_duration_adjust = -15;
+       } else if (coex_sta->scan_ap_num >= 40) {
+               wifi_duration_adjust = -15;
+
+               if (coex_sta->a2dp_bit_pool < 35)
+                       wifi_duration_adjust = -5;
+               else if (coex_sta->a2dp_bit_pool < 45)
+                       wifi_duration_adjust = -10;
+       } else if (coex_sta->scan_ap_num >= 20) {
+               wifi_duration_adjust = -10;
+
+               if (coex_sta->a2dp_bit_pool >= 45)
+                       wifi_duration_adjust = -15;
+       } else {
+               wifi_duration_adjust = 0;
+
+               if (coex_sta->a2dp_bit_pool >= 35)
+                       wifi_duration_adjust = -10;
+               else if (coex_sta->a2dp_bit_pool >= 45)
+                       wifi_duration_adjust = -15;
+       }
+
+       if ((type == 1) || (type == 2) || (type == 9) || (type == 11) ||
+           (type == 101) || (type == 102) || (type == 109) || (type == 101)) {
+               if (!coex_sta->force_lps_on) {
+                       /* Native power save TDMA, only for A2DP-only case
+                        * 1/2/9/11 while wifi noisy threshold > 30
+                        */
+
+                       /* no null-pkt */
+                       ps_tdma_byte0_val = 0x61;
+                       /* no tx-pause at BT-slot */
+                       ps_tdma_byte3_val = 0x11;
+                       /* 0x778 = d/1 toggle, no dynamic slot */
+                       ps_tdma_byte4_val = 0x10;
+               } else {
+                       /* null-pkt */
+                       ps_tdma_byte0_val = 0x51;
+                       /* tx-pause at BT-slot */
+                       ps_tdma_byte3_val = 0x10;
+                       /* 0x778 = d/1 toggle, dynamic slot */
+                       ps_tdma_byte4_val = 0x50;
+               }
+       } else if ((type == 3) || (type == 13) || (type == 14) ||
+                  (type == 103) || (type == 113) || (type == 114)) {
+               /* null-pkt */
+               ps_tdma_byte0_val = 0x51;
+               /* tx-pause at BT-slot */
+               ps_tdma_byte3_val = 0x10;
+               /* 0x778 = d/1 toggle, no dynamic slot */
+               ps_tdma_byte4_val = 0x10;
+       } else { /* native power save case */
+               /* no null-pkt */
+               ps_tdma_byte0_val = 0x61;
+               /* no tx-pause at BT-slot */
+               ps_tdma_byte3_val = 0x11;
+               /* 0x778 = d/1 toggle, no dynamic slot */
+               ps_tdma_byte4_val = 0x11;
+               /* psTdmaByte4Va is not define for 0x778 = d/1, 1/1 case */
+       }
+
+       /* if (bt_link_info->slave_role) */
+       if ((bt_link_info->slave_role) && (bt_link_info->a2dp_exist))
+               /* 0x778 = 0x1 at wifi slot (no blocking BT Low-Pri pkts) */
+               ps_tdma_byte4_val = ps_tdma_byte4_val | 0x1;
+
+       if (type > 100) {
+               /* set antenna control by SW     */
+               ps_tdma_byte0_val = ps_tdma_byte0_val | 0x82;
+               /* set antenna no toggle, control by antenna diversity */
+               ps_tdma_byte3_val = ps_tdma_byte3_val | 0x60;
+       }
+
        if (turn_on) {
                switch (type) {
                default:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x1a,
-                                                      0x1a, 0x0, 0x50);
+                                                     0x1a, 0x0,
+                                                     ps_tdma_byte4_val);
                        break;
                case 1:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x3a,
-                                                      0x03, 0x10, 0x50);
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val,
+                               0x3a + wifi_duration_adjust, 0x03,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
 
                        rssi_adjust_val = 11;
                        break;
                case 2:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x2b,
-                                                      0x03, 0x10, 0x50);
-                       rssi_adjust_val = 14;
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val,
+                               0x2d + wifi_duration_adjust, 0x03,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
                        break;
                case 3:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x1d,
-                                                      0x1d, 0x0, 0x52);
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x30, 0x03,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
                        break;
                case 4:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x15,
-                                                      0x3, 0x14, 0x0);
-                       rssi_adjust_val = 17;
+                                                     0x3, 0x14, 0x0);
                        break;
                case 5:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x15,
-                                                      0x3, 0x11, 0x10);
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x1f, 0x3,
+                               ps_tdma_byte3_val, 0x11);
                        break;
                case 6:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x20,
-                                                      0x3, 0x11, 0x13);
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x20, 0x3,
+                               ps_tdma_byte3_val, 0x11);
                        break;
                case 7:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xc,
@@ -875,33 +1206,44 @@ static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist,
                        break;
                case 8:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x25,
-                                                      0x3, 0x10, 0x0);
+                                                     0x3, 0x10, 0x0);
                        break;
                case 9:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51,  0x21,
-                                                      0x3, 0x10, 0x50);
-                       rssi_adjust_val = 18;
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x21, 0x3,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
                        break;
                case 10:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xa,
                                                       0xa, 0x0, 0x40);
                        break;
                case 11:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x15,
-                                                      0x03, 0x10, 0x50);
-                       rssi_adjust_val = 20;
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x21, 0x03,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
                        break;
                case 12:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x0a,
-                                                      0x0a, 0x0, 0x50);
+                                                     0x0a, 0x0, 0x50);
                        break;
                case 13:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x15,
-                                                      0x15, 0x0, 0x50);
+                       if (coex_sta->scan_ap_num <= 3)
+                               halbtc8723b1ant_set_fw_ps_tdma(
+                                       btcoexist, ps_tdma_byte0_val, 0x40, 0x3,
+                                       ps_tdma_byte3_val, ps_tdma_byte4_val);
+                       else
+                               halbtc8723b1ant_set_fw_ps_tdma(
+                                       btcoexist, ps_tdma_byte0_val, 0x21, 0x3,
+                                       ps_tdma_byte3_val, ps_tdma_byte4_val);
                        break;
                case 14:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x21,
-                                                      0x3, 0x10, 0x52);
+                       if (coex_sta->scan_ap_num <= 3)
+                               halbtc8723b1ant_set_fw_ps_tdma(
+                                       btcoexist, 0x51, 0x30, 0x3, 0x10, 0x50);
+                       else
+                               halbtc8723b1ant_set_fw_ps_tdma(
+                                       btcoexist, ps_tdma_byte0_val, 0x21, 0x3,
+                                       ps_tdma_byte3_val, ps_tdma_byte4_val);
                        break;
                case 15:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xa,
@@ -909,103 +1251,173 @@ static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist,
                        break;
                case 16:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x15,
-                                                      0x3, 0x10, 0x0);
-                       rssi_adjust_val = 18;
+                                                     0x3, 0x10, 0x0);
                        break;
                case 18:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x25,
-                                                      0x3, 0x10, 0x0);
-                       rssi_adjust_val = 14;
+                                                     0x3, 0x10, 0x0);
                        break;
                case 20:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x35,
-                                                      0x03, 0x11, 0x10);
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x3f, 0x03,
+                               ps_tdma_byte3_val, 0x10);
                        break;
                case 21:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x25,
-                                                      0x03, 0x11, 0x11);
+                                                     0x03, 0x11, 0x11);
                        break;
                case 22:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x25,
-                                                      0x03, 0x11, 0x10);
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x25, 0x03,
+                               ps_tdma_byte3_val, 0x10);
                        break;
                case 23:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x25,
-                                                      0x3, 0x31, 0x18);
-                       rssi_adjust_val = 22;
+                                                     0x3, 0x31, 0x18);
                        break;
                case 24:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x15,
-                                                      0x3, 0x31, 0x18);
-                       rssi_adjust_val = 22;
+                                                     0x3, 0x31, 0x18);
                        break;
                case 25:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0xa,
                                                       0x3, 0x31, 0x18);
-                       rssi_adjust_val = 22;
                        break;
                case 26:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0xa,
                                                       0x3, 0x31, 0x18);
-                       rssi_adjust_val = 22;
                        break;
                case 27:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x25,
-                                                      0x3, 0x31, 0x98);
-                       rssi_adjust_val = 22;
+                                                     0x3, 0x31, 0x98);
                        break;
                case 28:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x69, 0x25,
-                                                      0x3, 0x31, 0x0);
+                                                     0x3, 0x31, 0x0);
                        break;
                case 29:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xab, 0x1a,
-                                                      0x1a, 0x1, 0x10);
+                                                     0x1a, 0x1, 0x10);
                        break;
                case 30:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x14,
-                                                      0x3, 0x10, 0x50);
+                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x30,
+                                                      0x3, 0x10, 0x10);
                        break;
                case 31:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xd3, 0x1a,
-                                                      0x1a, 0, 0x58);
+                                                     0x1a, 0, 0x58);
                        break;
                case 32:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0xa,
-                                                      0x3, 0x10, 0x0);
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x35, 0x3,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
                        break;
                case 33:
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xa3, 0x25,
-                                                      0x3, 0x30, 0x90);
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x35, 0x3,
+                               ps_tdma_byte3_val, 0x10);
                        break;
                case 34:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x53, 0x1a,
-                                                      0x1a, 0x0, 0x10);
+                                                     0x1a, 0x0, 0x10);
                        break;
                case 35:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x63, 0x1a,
-                                                      0x1a, 0x0, 0x10);
+                                                     0x1a, 0x0, 0x10);
                        break;
                case 36:
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xd3, 0x12,
-                                                      0x3, 0x14, 0x50);
+                                                     0x3, 0x14, 0x50);
                        break;
-               /* SoftAP only with no sta associated, BT disable,
-                * TDMA mode for power saving
-                * here softap mode screen off will cost 70-80mA for phone
-                */
                case 40:
+                       /* SoftAP only with no sta associated,BT disable ,TDMA
+                        * mode for power saving
+                        *
+                        * here softap mode screen off will cost 70-80mA for
+                        * phone
+                        */
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x23, 0x18,
-                                                      0x00, 0x10, 0x24);
+                                                     0x00, 0x10, 0x24);
+                       break;
+
+               case 101:
+                       /* for 1-Ant translate to 2-Ant  */
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val,
+                               0x3a + wifi_duration_adjust, 0x03,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
+                       break;
+               case 102:
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val,
+                               0x2d + wifi_duration_adjust, 0x03,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
+                       break;
+               case 103:
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x3a, 0x03,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
+                       break;
+               case 105:
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x15, 0x3,
+                               ps_tdma_byte3_val, 0x11);
+                       break;
+               case 106:
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x20, 0x3,
+                               ps_tdma_byte3_val, 0x11);
+                       break;
+               case 109:
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x21, 0x3,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
+                       break;
+               case 111:
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x21, 0x03,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
+                       break;
+               case 113:
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x21, 0x3,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
+                       break;
+               case 114:
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x21, 0x3,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
+                       break;
+               case 120:
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x3f, 0x03,
+                               ps_tdma_byte3_val, 0x10);
+                       break;
+               case 122:
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x25, 0x03,
+                               ps_tdma_byte3_val, 0x10);
+                       break;
+               case 132:
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x25, 0x03,
+                               ps_tdma_byte3_val, ps_tdma_byte4_val);
+                       break;
+               case 133:
+                       halbtc8723b1ant_set_fw_ps_tdma(
+                               btcoexist, ps_tdma_byte0_val, 0x25, 0x03,
+                               ps_tdma_byte3_val, 0x11);
                        break;
                }
        } else {
+               /* disable PS tdma */
                switch (type) {
                case 8: /* PTA Control */
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x8, 0x0,
                                                       0x0, 0x0, 0x0);
                        halbtc8723b1ant_set_ant_path(btcoexist,
                                                     BTC_ANT_PATH_PTA,
+                                                    FORCE_EXEC,
                                                     false, false);
                        break;
                case 0:
@@ -1013,17 +1425,10 @@ static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist,
                        /* Software control, Antenna at BT side */
                        halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0,
                                                       0x0, 0x0, 0x0);
-                       halbtc8723b1ant_set_ant_path(btcoexist,
-                                                    BTC_ANT_PATH_BT,
-                                                    false, false);
                        break;
-               case 9:
-                       /* Software control, Antenna at WiFi side */
-                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0,
-                                                      0x0, 0x0, 0x0);
-                       halbtc8723b1ant_set_ant_path(btcoexist,
-                                                    BTC_ANT_PATH_WIFI,
-                                                    false, false);
+               case 1: /* 2-Ant, 0x778=3, antenna control by ant diversity */
+                       halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0, 0x0,
+                                                      0x48, 0x0);
                        break;
                }
        }
@@ -1037,8 +1442,191 @@ static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist,
        coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma;
 }
 
+void btc8723b1ant_tdma_dur_adj_for_acl(struct btc_coexist *btcoexist,
+                                      u8 wifi_status)
+{
+       struct rtl_priv *rtlpriv = btcoexist->adapter;
+       static s32 up, dn, m, n, wait_count;
+       /*  0: no change, +1: increase WiFi duration,
+        * -1: decrease WiFi duration
+        */
+       s32 result;
+       u8 retry_count = 0, bt_info_ext;
+       bool wifi_busy = false;
+
+       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                "[BTCoex], TdmaDurationAdjustForAcl()\n");
+
+       if (wifi_status == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY)
+               wifi_busy = true;
+       else
+               wifi_busy = false;
+
+       if ((wifi_status ==
+            BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN) ||
+           (wifi_status == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN) ||
+           (wifi_status == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT)) {
+               if (coex_dm->cur_ps_tdma != 1 && coex_dm->cur_ps_tdma != 2 &&
+                   coex_dm->cur_ps_tdma != 3 && coex_dm->cur_ps_tdma != 9) {
+                       halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+                                               true, 9);
+                       coex_dm->ps_tdma_du_adj_type = 9;
+
+                       up = 0;
+                       dn = 0;
+                       m = 1;
+                       n = 3;
+                       result = 0;
+                       wait_count = 0;
+               }
+               return;
+       }
+
+       if (!coex_dm->auto_tdma_adjust) {
+               coex_dm->auto_tdma_adjust = true;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], first run TdmaDurationAdjust()!!\n");
+
+               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2);
+               coex_dm->ps_tdma_du_adj_type = 2;
+
+               up = 0;
+               dn = 0;
+               m = 1;
+               n = 3;
+               result = 0;
+               wait_count = 0;
+       } else {
+               /* acquire the BT TRx retry count from BT_Info byte2 */
+               retry_count = coex_sta->bt_retry_cnt;
+               bt_info_ext = coex_sta->bt_info_ext;
+
+               if ((coex_sta->low_priority_tx) > 1050 ||
+                   (coex_sta->low_priority_rx) > 1250)
+                       retry_count++;
+
+               result = 0;
+               wait_count++;
+               /* no retry in the last 2-second duration */
+               if (retry_count == 0) {
+                       up++;
+                       dn--;
+
+                       if (dn <= 0)
+                               dn = 0;
+
+                       if (up >= n) {
+                               /* if retry count during continuous n*2 seconds
+                                * is 0, enlarge WiFi duration
+                                */
+                               wait_count = 0;
+                               n = 3;
+                               up = 0;
+                               dn = 0;
+                               result = 1;
+                               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                        "[BTCoex], Increase wifi duration!!\n");
+                       }
+               } else if (retry_count <= 3) {
+                       /* <=3 retry in the last 2-second duration */
+                       up--;
+                       dn++;
+
+                       if (up <= 0)
+                               up = 0;
+
+                       if (dn == 2) {
+                               /* if continuous 2 retry count(every 2 seconds)
+                                * >0 and < 3, reduce WiFi duration
+                                */
+                               if (wait_count <= 2)
+                                       /* avoid loop between the two levels */
+                                       m++;
+                               else
+                                       m = 1;
+
+                               if (m >= 20)
+                                       /* maximum of m = 20 ' will recheck if
+                                        * need to adjust wifi duration in
+                                        * maximum time interval 120 seconds
+                                        */
+                                       m = 20;
+
+                               n = 3 * m;
+                               up = 0;
+                               dn = 0;
+                               wait_count = 0;
+                               result = -1;
+                               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                        "[BTCoex], Decrease wifi duration for retryCounter<3!!\n");
+                       }
+               } else {
+                       /* retry count > 3, once retry count > 3, to reduce
+                        * WiFi duration
+                        */
+                       if (wait_count == 1)
+                               /* to avoid loop between the two levels */
+                               m++;
+                       else
+                               m = 1;
+
+                       if (m >= 20)
+                               /* maximum of m = 20 ' will recheck if need to
+                                * adjust wifi duration in maximum time interval
+                                * 120 seconds
+                                */
+                               m = 20;
+
+                       n = 3 * m;
+                       up = 0;
+                       dn = 0;
+                       wait_count = 0;
+                       result = -1;
+                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                "[BTCoex], Decrease wifi duration for retryCounter>3!!\n");
+               }
+
+               if (result == -1) {
+                       if (coex_dm->cur_ps_tdma == 1) {
+                               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+                                                       true, 2);
+                               coex_dm->ps_tdma_du_adj_type = 2;
+                       } else if (coex_dm->cur_ps_tdma == 2) {
+                               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+                                                       true, 9);
+                               coex_dm->ps_tdma_du_adj_type = 9;
+                       } else if (coex_dm->cur_ps_tdma == 9) {
+                               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+                                                       true, 11);
+                               coex_dm->ps_tdma_du_adj_type = 11;
+                       }
+               } else if (result == 1) {
+                       if (coex_dm->cur_ps_tdma == 11) {
+                               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+                                                       true, 9);
+                               coex_dm->ps_tdma_du_adj_type = 9;
+                       } else if (coex_dm->cur_ps_tdma == 9) {
+                               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+                                                       true, 2);
+                               coex_dm->ps_tdma_du_adj_type = 2;
+                       } else if (coex_dm->cur_ps_tdma == 2) {
+                               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
+                                                       true, 1);
+                               coex_dm->ps_tdma_du_adj_type = 1;
+                       }
+               }
+
+               if (coex_dm->cur_ps_tdma != 1 && coex_dm->cur_ps_tdma != 2 &&
+                   coex_dm->cur_ps_tdma != 9 && coex_dm->cur_ps_tdma != 11) {
+                       /* recover to previous adjust type */
+                       halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true,
+                                               coex_dm->ps_tdma_du_adj_type);
+               }
+       }
+}
+
 static void halbtc8723b1ant_ps_tdma_chk_pwr_save(struct btc_coexist *btcoexist,
-                                                bool new_ps_state)
+                                         bool new_ps_state)
 {
        u8 lps_mode = 0x0;
 
@@ -1078,6 +1666,7 @@ static void halbtc8723b1ant_power_save_state(struct btc_coexist *btcoexist,
                btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER,
                                   &low_pwr_disable);
                btcoexist->btc_set(btcoexist, BTC_SET_ACT_NORMAL_LPS, NULL);
+               coex_sta->force_lps_on = false;
                break;
        case BTC_PS_LPS_ON:
                halbtc8723b1ant_ps_tdma_chk_pwr_save(btcoexist, true);
@@ -1089,27 +1678,95 @@ static void halbtc8723b1ant_power_save_state(struct btc_coexist *btcoexist,
                                   &low_pwr_disable);
                /* power save must executed before psTdma */
                btcoexist->btc_set(btcoexist, BTC_SET_ACT_ENTER_LPS, NULL);
+               coex_sta->force_lps_on = true;
                break;
        case BTC_PS_LPS_OFF:
                halbtc8723b1ant_ps_tdma_chk_pwr_save(btcoexist, false);
                btcoexist->btc_set(btcoexist, BTC_SET_ACT_LEAVE_LPS, NULL);
+               coex_sta->force_lps_on = false;
                break;
        default:
                break;
        }
 }
 
+static void halbtc8723b1ant_action_wifi_only(struct btc_coexist *btcoexist)
+{
+       halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0);
+       halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+       halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+                                    FORCE_EXEC, false, false);
+}
+
+/* check if BT is disabled */
+static void halbtc8723b1ant_monitor_bt_enable_disable(struct btc_coexist
+                                                     *btcoexist)
+{
+       struct rtl_priv *rtlpriv = btcoexist->adapter;
+       static u32 bt_disable_cnt;
+       bool bt_active = true, bt_disabled = false;
+
+       if (coex_sta->high_priority_tx == 0 &&
+           coex_sta->high_priority_rx == 0 && coex_sta->low_priority_tx == 0 &&
+           coex_sta->low_priority_rx == 0)
+               bt_active = false;
+       if (coex_sta->high_priority_tx == 0xffff &&
+           coex_sta->high_priority_rx == 0xffff &&
+           coex_sta->low_priority_tx == 0xffff &&
+           coex_sta->low_priority_rx == 0xffff)
+               bt_active = false;
+       if (bt_active) {
+               bt_disable_cnt = 0;
+               bt_disabled = false;
+       } else {
+               bt_disable_cnt++;
+               if (bt_disable_cnt >= 2)
+                       bt_disabled = true;
+       }
+       if (coex_sta->bt_disabled != bt_disabled) {
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], BT is from %s to %s!!\n",
+                        (coex_sta->bt_disabled ? "disabled" : "enabled"),
+                        (bt_disabled ? "disabled" : "enabled"));
+
+               coex_sta->bt_disabled = bt_disabled;
+               btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE,
+                                  &bt_disabled);
+               if (bt_disabled) {
+                       halbtc8723b1ant_action_wifi_only(btcoexist);
+                       btcoexist->btc_set(btcoexist, BTC_SET_ACT_LEAVE_LPS,
+                                          NULL);
+                       btcoexist->btc_set(btcoexist, BTC_SET_ACT_NORMAL_LPS,
+                                          NULL);
+               }
+       }
+}
+
 /*****************************************************
  *
  *     Non-Software Coex Mechanism start
  *
  *****************************************************/
+
+static void halbtc8723b1ant_action_bt_whck_test(struct btc_coexist *btcoexist)
+{
+       halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, 0x0,
+                                        0x0);
+
+       halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+       halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA, NORMAL_EXEC,
+                                    false, false);
+       halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+}
+
 static void halbtc8723b1ant_action_wifi_multiport(struct btc_coexist *btcoexist)
 {
        halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
                                         0x0, 0x0);
 
        halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+       halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA, NORMAL_EXEC,
+                                    false, false);
        halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
 }
 
@@ -1123,35 +1780,56 @@ static void halbtc8723b1ant_action_bt_inquiry(struct btc_coexist *btcoexist)
 {
        struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
        bool wifi_connected = false, ap_enable = false;
+       bool wifi_busy = false, bt_busy = false;
 
        btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE,
                           &ap_enable);
        btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
                           &wifi_connected);
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
+       btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy);
 
-       if (!wifi_connected) {
-               halbtc8723b1ant_power_save_state(btcoexist,
-                                                BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+       if (coex_sta->bt_abnormal_scan) {
+               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 33);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7);
+       } else if (!wifi_connected && !coex_sta->wifi_is_high_pri_task) {
+               halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+                                                0x0, 0x0);
                halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
-               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
-       } else if (bt_link_info->sco_exist || bt_link_info->hid_only) {
-               /* SCO/HID-only busy */
+               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+                                            NORMAL_EXEC, false, false);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
+       } else if (bt_link_info->sco_exist || bt_link_info->hid_exist ||
+                  bt_link_info->a2dp_exist) {
+               /* SCO/HID/A2DP busy */
                halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
                                                 0x0, 0x0);
-               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32);
-               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
-       } else {
-               if (ap_enable)
-                       halbtc8723b1ant_power_save_state(btcoexist,
-                                                        BTC_PS_WIFI_NATIVE,
-                                                        0x0, 0x0);
+               if (coex_sta->c2h_bt_remote_name_req)
+                       halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true,
+                                               33);
                else
-                       halbtc8723b1ant_power_save_state(btcoexist,
-                                                        BTC_PS_LPS_ON,
-                                                        0x50, 0x4);
+                       halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true,
+                                               32);
 
-               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 30);
-               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+       } else if (bt_link_info->pan_exist || wifi_busy) {
+               halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+                                                0x0, 0x0);
+               if (coex_sta->c2h_bt_remote_name_req)
+                       halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true,
+                                               33);
+               else
+                       halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true,
+                                               32);
+
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+       } else {
+               halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+                                                0x0, 0x0);
+               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+                                            NORMAL_EXEC, false, false);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7);
        }
 }
 
@@ -1167,7 +1845,7 @@ static void btc8723b1ant_act_bt_sco_hid_only_busy(struct btc_coexist *btcoexist,
        /* tdma and coex table */
        if (bt_link_info->sco_exist) {
                halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5);
-               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5);
        } else {
                /* HID */
                halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 6);
@@ -1181,6 +1859,10 @@ static void halbtc8723b1ant_action_wifi_connected_bt_acl_busy(
 {
        struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
 
+       if ((coex_sta->low_priority_rx >= 950) && (!coex_sta->under_ips))
+               bt_link_info->slave_role = true;
+       else
+               bt_link_info->slave_role = false;
 
        if (bt_link_info->hid_only) { /* HID */
                btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist, wifi_status);
@@ -1189,39 +1871,40 @@ static void halbtc8723b1ant_action_wifi_connected_bt_acl_busy(
        } else if (bt_link_info->a2dp_only) { /* A2DP */
                if (wifi_status == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE) {
                        halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
-                                               false, 8);
+                                               true, 32);
                        halbtc8723b1ant_coex_table_with_type(btcoexist,
-                                                            NORMAL_EXEC, 2);
+                                                            NORMAL_EXEC, 4);
                        coex_dm->auto_tdma_adjust = false;
-               } else { /* for low BT RSSI */
-                       halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
-                                               true, 11);
+               } else {
+                       btc8723b1ant_tdma_dur_adj_for_acl(btcoexist,
+                                                         wifi_status);
                        halbtc8723b1ant_coex_table_with_type(btcoexist,
                                                             NORMAL_EXEC, 1);
-                       coex_dm->auto_tdma_adjust = false;
+                       coex_dm->auto_tdma_adjust = true;
                }
-       } else if (bt_link_info->hid_exist &&
-               bt_link_info->a2dp_exist) { /* HID + A2DP */
+       } else if (((bt_link_info->a2dp_exist) && (bt_link_info->pan_exist)) ||
+                  (bt_link_info->hid_exist && bt_link_info->a2dp_exist &&
+                   bt_link_info->pan_exist)) {
+               /* A2DP + PAN(OPP,FTP), HID + A2DP + PAN(OPP,FTP) */
+               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+               coex_dm->auto_tdma_adjust = false;
+       } else if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) {
+               /* HID + A2DP */
                halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14);
                coex_dm->auto_tdma_adjust = false;
 
-               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 6);
-        /* PAN(OPP,FTP), HID + PAN(OPP,FTP) */
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
        } else if (bt_link_info->pan_only ||
-                  (bt_link_info->hid_exist && bt_link_info->pan_exist)) {
+                       (bt_link_info->hid_exist && bt_link_info->pan_exist)) {
+               /* PAN(OPP,FTP), HID + PAN(OPP,FTP) */
                halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3);
-               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 6);
-               coex_dm->auto_tdma_adjust = false;
-        /* A2DP + PAN(OPP,FTP), HID + A2DP + PAN(OPP,FTP) */
-       } else if ((bt_link_info->a2dp_exist && bt_link_info->pan_exist) ||
-                  (bt_link_info->hid_exist && bt_link_info->a2dp_exist &&
-                   bt_link_info->pan_exist)) {
-               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13);
-               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
                coex_dm->auto_tdma_adjust = false;
        } else {
-               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11);
-               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+               /* BT no-profile busy (0x9) */
+               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 33);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
                coex_dm->auto_tdma_adjust = false;
        }
 }
@@ -1233,7 +1916,9 @@ static void btc8723b1ant_action_wifi_not_conn(struct btc_coexist *btcoexist)
                                         0x0, 0x0);
 
        /* tdma and coex table */
-       halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+       halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+       halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA, NORMAL_EXEC,
+                                    false, false);
        halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0);
 }
 
@@ -1246,30 +1931,31 @@ btc8723b1ant_action_wifi_not_conn_scan(struct btc_coexist *btcoexist)
                                         0x0, 0x0);
 
        /* tdma and coex table */
-       if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
-               if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) {
+       if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) {
+               if (bt_link_info->a2dp_exist) {
                        halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
-                                               true, 22);
+                                               true, 32);
                        halbtc8723b1ant_coex_table_with_type(btcoexist,
-                                                            NORMAL_EXEC, 1);
-               } else if (bt_link_info->pan_only) {
+                                                            NORMAL_EXEC, 4);
+               } else if (bt_link_info->a2dp_exist) {
                        halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
-                                               true, 20);
+                                               true, 22);
                        halbtc8723b1ant_coex_table_with_type(btcoexist,
-                                                            NORMAL_EXEC, 2);
+                                                            NORMAL_EXEC, 4);
                } else {
                        halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
                                                true, 20);
                        halbtc8723b1ant_coex_table_with_type(btcoexist,
                                                             NORMAL_EXEC, 1);
                }
-       } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) ||
-                  (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY ==
-                   coex_dm->bt_status)){
+       } else if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_SCO_BUSY ||
+                  coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY){
                btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist,
                                BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN);
        } else {
                halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+                                            NORMAL_EXEC, false, false);
                halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
        }
 }
@@ -1282,14 +1968,19 @@ btc8723b1ant_act_wifi_not_conn_asso_auth(struct btc_coexist *btcoexist)
        halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
                                         0x0, 0x0);
 
-       if ((BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == coex_dm->bt_status) ||
-           (bt_link_info->sco_exist) || (bt_link_info->hid_only) ||
-           (bt_link_info->a2dp_only) || (bt_link_info->pan_only)) {
-               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
-               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7);
-       } else {
+       /* tdma and coex table */
+       if ((bt_link_info->sco_exist) || (bt_link_info->hid_exist) ||
+           (bt_link_info->a2dp_exist)) {
+               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 4);
+       } else if (bt_link_info->pan_exist) {
                halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
-               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 4);
+       } else {
+               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+                                            NORMAL_EXEC, false, false);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 2);
        }
 }
 
@@ -1301,30 +1992,32 @@ static void btc8723b1ant_action_wifi_conn_scan(struct btc_coexist *btcoexist)
                                         0x0, 0x0);
 
        /* tdma and coex table */
-       if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
-               if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) {
+       if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) {
+               if (bt_link_info->a2dp_exist) {
                        halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
-                                               true, 22);
+                                               true, 32);
                        halbtc8723b1ant_coex_table_with_type(btcoexist,
-                                                            NORMAL_EXEC, 1);
-               } else if (bt_link_info->pan_only) {
+                                                            NORMAL_EXEC, 4);
+               } else if (bt_link_info->a2dp_exist &&
+                          bt_link_info->pan_exist) {
                        halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
-                                               true, 20);
+                                               true, 22);
                        halbtc8723b1ant_coex_table_with_type(btcoexist,
-                                                            NORMAL_EXEC, 2);
+                                                            NORMAL_EXEC, 4);
                } else {
                        halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
                                                true, 20);
                        halbtc8723b1ant_coex_table_with_type(btcoexist,
-                                                            NORMAL_EXEC, 1);
+                                                            NORMAL_EXEC, 4);
                }
-       } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) ||
-                  (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY ==
-                   coex_dm->bt_status)) {
+       } else if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_SCO_BUSY ||
+                  coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) {
                btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist,
                                BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN);
        } else {
                halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+                                            NORMAL_EXEC, false, false);
                halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
        }
 }
@@ -1332,23 +2025,34 @@ static void btc8723b1ant_action_wifi_conn_scan(struct btc_coexist *btcoexist)
 static void halbtc8723b1ant_action_wifi_connected_special_packet(
                                                struct btc_coexist *btcoexist)
 {
-       bool hs_connecting = false;
        struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
+       bool wifi_busy = false;
 
-       btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_CONNECTING, &hs_connecting);
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
+
+       /* no special packet process for both WiFi and BT very busy */
+       if ((wifi_busy) &&
+           ((bt_link_info->pan_exist) || (coex_sta->num_of_profile >= 2)))
+               return;
 
        halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
                                         0x0, 0x0);
 
        /* tdma and coex table */
-       if ((BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == coex_dm->bt_status) ||
-           (bt_link_info->sco_exist) || (bt_link_info->hid_only) ||
-           (bt_link_info->a2dp_only) || (bt_link_info->pan_only)) {
-               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
-               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7);
-       } else {
+       if ((bt_link_info->sco_exist) || (bt_link_info->hid_exist)) {
+               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5);
+       } else if (bt_link_info->a2dp_exist) {
+               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+       } else if (bt_link_info->pan_exist) {
                halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
-               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+       } else {
+               halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+                                            NORMAL_EXEC, false, false);
+               halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
        }
 }
 
@@ -1391,12 +2095,31 @@ static void halbtc8723b1ant_action_wifi_connected(struct btc_coexist *btcoexist)
        btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
        /* power save state */
        if (!ap_enable &&
-           BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status &&
+           coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY &&
            !btcoexist->bt_link_info.hid_only) {
-               if (!wifi_busy && btcoexist->bt_link_info.a2dp_only)
-                       halbtc8723b1ant_power_save_state(btcoexist,
+               if (btcoexist->bt_link_info.a2dp_only) {
+                       if (!wifi_busy) {
+                               halbtc8723b1ant_power_save_state(btcoexist,
                                                         BTC_PS_WIFI_NATIVE,
                                                         0x0, 0x0);
+                       } else { /* busy */
+                               if (coex_sta->scan_ap_num >=
+                                   BT_8723B_1ANT_WIFI_NOISY_THRESH)
+                                       /* no force LPS, no PS-TDMA,
+                                        * use pure TDMA
+                                        */
+                                       halbtc8723b1ant_power_save_state(
+                                               btcoexist, BTC_PS_WIFI_NATIVE,
+                                               0x0, 0x0);
+                               else
+                                       halbtc8723b1ant_power_save_state(
+                                               btcoexist, BTC_PS_LPS_ON, 0x50,
+                                               0x4);
+                       }
+               } else if ((!coex_sta->pan_exist) && (!coex_sta->a2dp_exist) &&
+                          (!coex_sta->hid_exist))
+                       halbtc8723b1ant_power_save_state(
+                               btcoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
                else
                        halbtc8723b1ant_power_save_state(btcoexist,
                                                         BTC_PS_LPS_ON,
@@ -1407,36 +2130,44 @@ static void halbtc8723b1ant_action_wifi_connected(struct btc_coexist *btcoexist)
        }
        /* tdma and coex table */
        if (!wifi_busy) {
-               if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
-                       halbtc8723b1ant_action_wifi_connected_bt_acl_busy(btcoexist,
-                                     BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE);
-               } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY ==
-                                               coex_dm->bt_status) ||
-                          (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY ==
-                                               coex_dm->bt_status)) {
+               if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) {
+                       halbtc8723b1ant_action_wifi_connected_bt_acl_busy(
+                               btcoexist,
+                               BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE);
+               } else if (coex_dm->bt_status ==
+                               BT_8723B_1ANT_BT_STATUS_SCO_BUSY ||
+                          coex_dm->bt_status ==
+                               BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) {
                        btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist,
                                     BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE);
                } else {
                        halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
                                                false, 8);
+                       halbtc8723b1ant_set_ant_path(btcoexist,
+                                                    BTC_ANT_PATH_PTA,
+                                                    NORMAL_EXEC, false, false);
                        halbtc8723b1ant_coex_table_with_type(btcoexist,
                                                             NORMAL_EXEC, 2);
                }
        } else {
-               if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
-                       halbtc8723b1ant_action_wifi_connected_bt_acl_busy(btcoexist,
-                                   BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY);
-               } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY ==
-                          coex_dm->bt_status) ||
-                          (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY ==
-                           coex_dm->bt_status)) {
+               if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) {
+                       halbtc8723b1ant_action_wifi_connected_bt_acl_busy(
+                               btcoexist,
+                               BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY);
+               } else if (coex_dm->bt_status ==
+                               BT_8723B_1ANT_BT_STATUS_SCO_BUSY ||
+                          coex_dm->bt_status ==
+                               BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) {
                        btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist,
                                    BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY);
                } else {
                        halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
-                                               false, 8);
+                                               true, 32);
+                       halbtc8723b1ant_set_ant_path(btcoexist,
+                                                    BTC_ANT_PATH_PTA,
+                                                    NORMAL_EXEC, false, false);
                        halbtc8723b1ant_coex_table_with_type(btcoexist,
-                                                            NORMAL_EXEC, 2);
+                                                            NORMAL_EXEC, 4);
                }
        }
 }
@@ -1445,12 +2176,15 @@ static void halbtc8723b1ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
 {
        struct rtl_priv *rtlpriv = btcoexist->adapter;
        struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
-       bool wifi_connected = false, bt_hs_on = false;
+       bool wifi_connected = false, bt_hs_on = false, wifi_busy = false;
        bool increase_scan_dev_num = false;
        bool bt_ctrl_agg_buf_size = false;
+       bool miracast_plus_bt = false;
        u8 agg_buf_size = 5;
+       u8 iot_peer = BTC_IOT_PEER_UNKNOWN;
        u32 wifi_link_status = 0;
        u32 num_of_wifi_link = 0;
+       u32 wifi_bw;
 
        RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                 "[BTCoex], RunCoexistMechanism()===>\n");
@@ -1473,54 +2207,99 @@ static void halbtc8723b1ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
                return;
        }
 
-       if ((BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) ||
-           (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) ||
-           (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) {
-               increase_scan_dev_num = true;
+       if (coex_sta->bt_whck_test) {
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], wifi is under IPS !!!\n");
+               halbtc8723b1ant_action_bt_whck_test(btcoexist);
+               return;
        }
 
+       if (coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_BUSY ||
+           coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_SCO_BUSY ||
+           coex_dm->bt_status == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY)
+               increase_scan_dev_num = true;
+
        btcoexist->btc_set(btcoexist, BTC_SET_BL_INC_SCAN_DEV_NUM,
                           &increase_scan_dev_num);
-
        btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
                           &wifi_connected);
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
 
        btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS,
                           &wifi_link_status);
        num_of_wifi_link = wifi_link_status >> 16;
-       if (num_of_wifi_link >= 2) {
-               halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0);
+
+       if (num_of_wifi_link >= 2 ||
+           wifi_link_status & WIFI_P2P_GO_CONNECTED) {
+               if (bt_link_info->bt_link_exist) {
+                       halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 1, 1,
+                                                  0, 1);
+                       miracast_plus_bt = true;
+               } else {
+                       halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0,
+                                                  0, 0);
+                       miracast_plus_bt = false;
+               }
+               btcoexist->btc_set(btcoexist, BTC_SET_BL_MIRACAST_PLUS_BT,
+                                  &miracast_plus_bt);
                halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false,
-                                          bt_ctrl_agg_buf_size,
-                                          agg_buf_size);
-               halbtc8723b1ant_action_wifi_multiport(btcoexist);
+                                          bt_ctrl_agg_buf_size, agg_buf_size);
+
+               if ((bt_link_info->a2dp_exist || wifi_busy) &&
+                   (coex_sta->c2h_bt_inquiry_page))
+                       halbtc8723b1ant_action_bt_inquiry(btcoexist);
+               else
+                       halbtc8723b1ant_action_wifi_multiport(btcoexist);
+
                return;
        }
 
-       if (!bt_link_info->sco_exist && !bt_link_info->hid_exist) {
-               halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0);
+       miracast_plus_bt = false;
+       btcoexist->btc_set(btcoexist, BTC_SET_BL_MIRACAST_PLUS_BT,
+                          &miracast_plus_bt);
+       btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+
+       if (bt_link_info->bt_link_exist && wifi_connected) {
+               halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 1, 1, 0, 1);
+
+               btcoexist->btc_get(btcoexist, BTC_GET_U1_IOT_PEER, &iot_peer);
+
+               if (iot_peer != BTC_IOT_PEER_CISCO &&
+                   iot_peer != BTC_IOT_PEER_BROADCOM) {
+                       if (bt_link_info->sco_exist)
+                               halbtc8723b1ant_limited_rx(btcoexist,
+                                                          NORMAL_EXEC, false,
+                                                          false, 0x5);
+                       else
+                               halbtc8723b1ant_limited_rx(btcoexist,
+                                                          NORMAL_EXEC, false,
+                                                          false, 0x5);
+               } else {
+                       if (bt_link_info->sco_exist) {
+                               halbtc8723b1ant_limited_rx(btcoexist,
+                                                          NORMAL_EXEC, true,
+                                                          false, 0x5);
+                       } else {
+                               if (wifi_bw == BTC_WIFI_BW_HT40)
+                                       halbtc8723b1ant_limited_rx(
+                                               btcoexist, NORMAL_EXEC, false,
+                                               true, 0x10);
+                               else
+                                       halbtc8723b1ant_limited_rx(
+                                               btcoexist, NORMAL_EXEC, false,
+                                               true, 0x8);
+                       }
+               }
+
+               halbtc8723b1ant_sw_mechanism(btcoexist, true);
        } else {
-               if (wifi_connected)
-                       halbtc8723b1ant_limited_tx(btcoexist,
-                                                  NORMAL_EXEC, 1, 1, 1, 1);
-               else
-                       halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC,
-                                                  0, 0, 0, 0);
-       }
+               halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0);
 
-       if (bt_link_info->sco_exist) {
-               bt_ctrl_agg_buf_size = true;
-               agg_buf_size = 0x3;
-       } else if (bt_link_info->hid_exist) {
-               bt_ctrl_agg_buf_size = true;
-               agg_buf_size = 0x5;
-       } else if (bt_link_info->a2dp_exist || bt_link_info->pan_exist) {
-               bt_ctrl_agg_buf_size = true;
-               agg_buf_size = 0x8;
-       }
-       halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false,
-                                  bt_ctrl_agg_buf_size, agg_buf_size);
+               halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false, false,
+                                          0x5);
 
+               halbtc8723b1ant_sw_mechanism(btcoexist, false);
+       }
        btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
 
        if (coex_sta->c2h_bt_inquiry_page) {
@@ -1556,88 +2335,138 @@ static void halbtc8723b1ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
        }
 }
 
+/* force coex mechanism to reset */
 static void halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist)
 {
        /* sw all off */
        halbtc8723b1ant_sw_mechanism(btcoexist, false);
 
-       halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
-       halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0);
+       coex_sta->pop_event_cnt = 0;
 }
 
 static void halbtc8723b1ant_init_hw_config(struct btc_coexist *btcoexist,
-                                          bool backup)
+                                          bool backup, bool wifi_only)
 {
        struct rtl_priv *rtlpriv = btcoexist->adapter;
        u32 u32tmp = 0;
-       u8 u8tmp = 0;
-       u32 cnt_bt_cal_chk = 0;
+       u8 u8tmpa = 0, u8tmpb = 0;
 
        RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                 "[BTCoex], 1Ant Init HW Config!!\n");
 
-       if (backup) {/* backup rf 0x1e value */
-               coex_dm->backup_arfr_cnt1 =
-                       btcoexist->btc_read_4byte(btcoexist, 0x430);
-               coex_dm->backup_arfr_cnt2 =
-                       btcoexist->btc_read_4byte(btcoexist, 0x434);
-               coex_dm->backup_retry_limit =
-                       btcoexist->btc_read_2byte(btcoexist, 0x42a);
-               coex_dm->backup_ampdu_max_time =
-                       btcoexist->btc_read_1byte(btcoexist, 0x456);
-       }
-
-       /* WiFi goto standby while GNT_BT 0-->1 */
-       btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x780);
-       /* BT goto standby while GNT_BT 1-->0 */
-       btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x2, 0xfffff, 0x500);
-
-       btcoexist->btc_write_1byte(btcoexist, 0x974, 0xff);
-       btcoexist->btc_write_1byte_bitmask(btcoexist, 0x944, 0x3, 0x3);
-       btcoexist->btc_write_1byte(btcoexist, 0x930, 0x77);
-
-       /* BT calibration check */
-       while (cnt_bt_cal_chk <= 20) {
-               u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x49d);
-               cnt_bt_cal_chk++;
-               if (u32tmp & BIT0) {
-                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                                "[BTCoex], ########### BT calibration(cnt=%d) ###########\n",
-                                     cnt_bt_cal_chk);
-                       mdelay(50);
-               } else {
-                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                                "[BTCoex], ********** BT NOT calibration (cnt=%d)**********\n",
-                                     cnt_bt_cal_chk);
-                       break;
-               }
-       }
+       /* 0xf0[15:12] --> Chip Cut information */
+       coex_sta->cut_version =
+               (btcoexist->btc_read_1byte(btcoexist, 0xf1) & 0xf0) >> 4;
+       /* enable TBTT interrupt */
+       btcoexist->btc_write_1byte_bitmask(btcoexist, 0x550, 0x8, 0x1);
 
        /* 0x790[5:0] = 0x5 */
-       u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x790);
-       u8tmp &= 0xc0;
-       u8tmp |= 0x5;
-       btcoexist->btc_write_1byte(btcoexist, 0x790, u8tmp);
+       btcoexist->btc_write_1byte(btcoexist, 0x790, 0x5);
 
        /* Enable counter statistics */
-       /*0x76e[3] = 1, WLAN_Act control by PTA */
-       btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc);
        btcoexist->btc_write_1byte(btcoexist, 0x778, 0x1);
        btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1);
 
+       halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+
        /* Antenna config */
-       halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA, true, false);
+       if (wifi_only)
+               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_WIFI,
+                                            FORCE_EXEC, true, false);
+       else
+               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT,
+                                            FORCE_EXEC, true, false);
+
        /* PTA parameter */
        halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0);
+
+       u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x948);
+       u8tmpa = btcoexist->btc_read_1byte(btcoexist, 0x765);
+       u8tmpb = btcoexist->btc_read_1byte(btcoexist, 0x67);
+
+       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                "############# [BTCoex], 0x948=0x%x, 0x765=0x%x, 0x67=0x%x\n",
+                u32tmp, u8tmpa, u8tmpb);
 }
 
 /**************************************************************
  * extern function start with ex_halbtc8723b1ant_
  **************************************************************/
+void ex_halbtc8723b1ant_power_on_setting(struct btc_coexist *btcoexist)
+{
+       struct rtl_priv *rtlpriv = btcoexist->adapter;
+       struct btc_board_info *board_info = &btcoexist->board_info;
+       u8 u8tmp = 0x0;
+       u16 u16tmp = 0x0;
+       u32 value;
+
+       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                "xxxxxxxxxxxxxxxx Execute 8723b 1-Ant PowerOn Setting xxxxxxxxxxxxxxxx!!\n");
+
+       btcoexist->stop_coex_dm = true;
+
+       btcoexist->btc_write_1byte(btcoexist, 0x67, 0x20);
+
+       /* enable BB, REG_SYS_FUNC_EN such that we can write 0x948 correctly. */
+       u16tmp = btcoexist->btc_read_2byte(btcoexist, 0x2);
+       btcoexist->btc_write_2byte(btcoexist, 0x2, u16tmp | BIT0 | BIT1);
+
+       /* set GRAN_BT = 1 */
+       btcoexist->btc_write_1byte(btcoexist, 0x765, 0x18);
+       /* set WLAN_ACT = 0 */
+       btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4);
+
+       /* S0 or S1 setting and Local register setting(By the setting fw can get
+        * ant number, S0/S1, ... info)
+        *
+        * Local setting bit define
+        *      BIT0: "0" for no antenna inverse; "1" for antenna inverse
+        *      BIT1: "0" for internal switch; "1" for external switch
+        *      BIT2: "0" for one antenna; "1" for two antenna
+        * NOTE: here default all internal switch and 1-antenna ==> BIT1=0 and
+        * BIT2 = 0
+        */
+       if (btcoexist->chip_interface == BTC_INTF_USB) {
+               /* fixed at S0 for USB interface */
+               btcoexist->btc_write_4byte(btcoexist, 0x948, 0x0);
+
+               u8tmp |= 0x1; /* antenna inverse */
+               btcoexist->btc_write_local_reg_1byte(btcoexist, 0xfe08, u8tmp);
+
+               board_info->btdm_ant_pos = BTC_ANTENNA_AT_AUX_PORT;
+       } else {
+               /* for PCIE and SDIO interface, we check efuse 0xc3[6] */
+               if (board_info->single_ant_path == 0) {
+                       /* set to S1 */
+                       btcoexist->btc_write_4byte(btcoexist, 0x948, 0x280);
+                       board_info->btdm_ant_pos = BTC_ANTENNA_AT_MAIN_PORT;
+                       value = 1;
+               } else if (board_info->single_ant_path == 1) {
+                       /* set to S0 */
+                       btcoexist->btc_write_4byte(btcoexist, 0x948, 0x0);
+                       u8tmp |= 0x1; /* antenna inverse */
+                       board_info->btdm_ant_pos = BTC_ANTENNA_AT_AUX_PORT;
+                       value = 0;
+               }
+
+               btcoexist->btc_set(btcoexist, BTC_SET_ACT_ANTPOSREGRISTRY_CTRL,
+                                  &value);
+
+               if (btcoexist->chip_interface == BTC_INTF_PCI)
+                       btcoexist->btc_write_local_reg_1byte(btcoexist, 0x384,
+                                                            u8tmp);
+               else if (btcoexist->chip_interface == BTC_INTF_SDIO)
+                       btcoexist->btc_write_local_reg_1byte(btcoexist, 0x60,
+                                                            u8tmp);
+       }
+}
+
 
-void ex_halbtc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist)
+void ex_halbtc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist,
+                                     bool wifi_only)
 {
-       halbtc8723b1ant_init_hw_config(btcoexist, true);
+       halbtc8723b1ant_init_hw_config(btcoexist, true, wifi_only);
+       btcoexist->stop_coex_dm = false;
 }
 
 void ex_halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist)
@@ -1687,11 +2516,6 @@ void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
                         "\r\n ==========================================");
        }
 
-       if (!board_info->bt_exist) {
-               RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n BT not exists !!!");
-               return;
-       }
-
        RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d",
                 "Ant PG Num/ Ant Mech/ Ant Pos:",
                 board_info->pg_ant_num, board_info->btdm_ant_num,
@@ -1760,7 +2584,7 @@ void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
 
        RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = [%s/ %d/ %d] ",
                 "BT [status/ rssi/ retryCnt]",
-                ((btcoexist->bt_info.bt_disabled) ? ("disabled") :
+                ((coex_sta->bt_disabled) ? ("disabled") :
                  ((coex_sta->c2h_bt_inquiry_page) ? ("inquiry/page scan") :
                   ((BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE ==
                     coex_dm->bt_status) ?
@@ -1835,6 +2659,9 @@ void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
                           coex_dm->error_condition);
        }
 
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d",
+                "Coex Table Type", coex_sta->coex_table_type);
+
        /* Hw setting */
        RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s",
                 "============[Hw setting]============");
@@ -1926,9 +2753,8 @@ void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
        RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d",
                 "0x774(low-pri rx/tx)", coex_sta->low_priority_rx,
                 coex_sta->low_priority_tx);
-#if (BT_AUTO_REPORT_ONLY_8723B_1ANT == 1)
-       halbtc8723b1ant_monitor_bt_ctr(btcoexist);
-#endif
+       if (btcoexist->auto_report_1ant)
+               halbtc8723b1ant_monitor_bt_ctr(btcoexist);
        btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS);
 }
 
@@ -1945,7 +2771,7 @@ void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
                coex_sta->under_ips = true;
 
                halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT,
-                                            false, true);
+                                            FORCE_EXEC, false, true);
                /* set PTA control */
                halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 0);
                halbtc8723b1ant_coex_table_with_type(btcoexist,
@@ -1955,7 +2781,7 @@ void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
                         "[BTCoex], IPS LEAVE notify\n");
                coex_sta->under_ips = false;
 
-               halbtc8723b1ant_init_hw_config(btcoexist, false);
+               halbtc8723b1ant_init_hw_config(btcoexist, false, false);
                halbtc8723b1ant_init_coex_dm(btcoexist);
                halbtc8723b1ant_query_bt_info(btcoexist);
        }
@@ -1983,13 +2809,41 @@ void ex_halbtc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type)
 {
        struct rtl_priv *rtlpriv = btcoexist->adapter;
        bool wifi_connected = false, bt_hs_on = false;
+       u8 u8tmpa, u8tmpb;
+       u32 u32tmp;
        u32 wifi_link_status = 0;
        u32 num_of_wifi_link = 0;
        bool bt_ctrl_agg_buf_size = false;
        u8 agg_buf_size = 5;
 
-       if (btcoexist->manual_control || btcoexist->stop_coex_dm ||
-           btcoexist->bt_info.bt_disabled)
+       if (btcoexist->manual_control || btcoexist->stop_coex_dm)
+               return;
+
+       if (type == BTC_SCAN_START) {
+               coex_sta->wifi_is_high_pri_task = true;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], SCAN START notify\n");
+               /* Force antenna setup for no scan result issue */
+               halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+                                            FORCE_EXEC, false, false);
+               u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x948);
+               u8tmpa = btcoexist->btc_read_1byte(btcoexist, 0x765);
+               u8tmpb = btcoexist->btc_read_1byte(btcoexist, 0x67);
+
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], 0x948=0x%x, 0x765=0x%x, 0x67=0x%x\n",
+                        u32tmp, u8tmpa, u8tmpb);
+       } else {
+               coex_sta->wifi_is_high_pri_task = false;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], SCAN FINISH notify\n");
+
+               btcoexist->btc_get(btcoexist, BTC_GET_U1_AP_NUM,
+                                  &coex_sta->scan_ap_num);
+       }
+
+       if (coex_sta->bt_disabled)
                return;
 
        btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
@@ -2043,13 +2897,32 @@ void ex_halbtc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type)
        bool wifi_connected = false, bt_hs_on = false;
        u32 wifi_link_status = 0;
        u32 num_of_wifi_link = 0;
-       bool bt_ctrl_agg_buf_size = false;
+       bool bt_ctrl_agg_buf_size = false, under_4way = false;
        u8 agg_buf_size = 5;
 
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS,
+                          &under_4way);
+
        if (btcoexist->manual_control || btcoexist->stop_coex_dm ||
-           btcoexist->bt_info.bt_disabled)
+           coex_sta->bt_disabled)
                return;
 
+       if (type == BTC_ASSOCIATE_START) {
+               coex_sta->wifi_is_high_pri_task = true;
+
+               /* Force antenna setup for no scan result issue */
+               halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+                                            FORCE_EXEC, false, false);
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], CONNECT START notify\n");
+               coex_dm->arp_cnt = 0;
+       } else {
+               coex_sta->wifi_is_high_pri_task = false;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], CONNECT FINISH notify\n");
+       }
+
        btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS,
                           &wifi_link_status);
        num_of_wifi_link = wifi_link_status>>16;
@@ -2094,27 +2967,62 @@ void ex_halbtc8723b1ant_media_status_notify(struct btc_coexist *btcoexist,
        struct rtl_priv *rtlpriv = btcoexist->adapter;
        u8 h2c_parameter[3] = {0};
        u32 wifi_bw;
-       u8 wifiCentralChnl;
+       u8 wifi_central_chnl;
+       bool wifi_under_b_mode = false;
 
        if (btcoexist->manual_control || btcoexist->stop_coex_dm ||
-           btcoexist->bt_info.bt_disabled)
+           coex_sta->bt_disabled)
                return;
 
-       if (BTC_MEDIA_CONNECT == type)
+       if (type == BTC_MEDIA_CONNECT) {
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], MEDIA connect notify\n");
-       else
+               /* Force antenna setup for no scan result issue */
+               halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA,
+                                            FORCE_EXEC, false, false);
+               btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_B_MODE,
+                                  &wifi_under_b_mode);
+
+               /* Set CCK Tx/Rx high Pri except 11b mode */
+               if (wifi_under_b_mode) {
+                       btcoexist->btc_write_1byte(btcoexist, 0x6cd,
+                                                  0x00); /* CCK Tx */
+                       btcoexist->btc_write_1byte(btcoexist, 0x6cf,
+                                                  0x00); /* CCK Rx */
+               } else {
+                       btcoexist->btc_write_1byte(btcoexist, 0x6cd,
+                                                  0x00); /* CCK Tx */
+                       btcoexist->btc_write_1byte(btcoexist, 0x6cf,
+                                                  0x10); /* CCK Rx */
+               }
+
+               coex_dm->backup_arfr_cnt1 =
+                       btcoexist->btc_read_4byte(btcoexist, 0x430);
+               coex_dm->backup_arfr_cnt2 =
+                       btcoexist->btc_read_4byte(btcoexist, 0x434);
+               coex_dm->backup_retry_limit =
+                       btcoexist->btc_read_2byte(btcoexist, 0x42a);
+               coex_dm->backup_ampdu_max_time =
+                       btcoexist->btc_read_1byte(btcoexist, 0x456);
+       } else {
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], MEDIA disconnect notify\n");
+               coex_dm->arp_cnt = 0;
+
+               btcoexist->btc_write_1byte(btcoexist, 0x6cd, 0x0); /* CCK Tx */
+               btcoexist->btc_write_1byte(btcoexist, 0x6cf, 0x0); /* CCK Rx */
+
+               coex_sta->cck_ever_lock = false;
+       }
 
        /* only 2.4G we need to inform bt the chnl mask */
        btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL,
-                          &wifiCentralChnl);
+                          &wifi_central_chnl);
 
-       if ((BTC_MEDIA_CONNECT == type) &&
-           (wifiCentralChnl <= 14)) {
+       if (type == BTC_MEDIA_CONNECT && wifi_central_chnl <= 14) {
                h2c_parameter[0] = 0x0;
-               h2c_parameter[1] = wifiCentralChnl;
+               h2c_parameter[1] = wifi_central_chnl;
                btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
                if (BTC_WIFI_BW_HT40 == wifi_bw)
                        h2c_parameter[2] = 0x30;
@@ -2141,13 +3049,46 @@ void ex_halbtc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist,
        bool bt_hs_on = false;
        u32 wifi_link_status = 0;
        u32 num_of_wifi_link = 0;
-       bool bt_ctrl_agg_buf_size = false;
+       bool bt_ctrl_agg_buf_size = false, under_4way = false;
        u8 agg_buf_size = 5;
 
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS,
+                          &under_4way);
+
        if (btcoexist->manual_control || btcoexist->stop_coex_dm ||
-           btcoexist->bt_info.bt_disabled)
+           coex_sta->bt_disabled)
                return;
 
+       if (type == BTC_PACKET_DHCP || type == BTC_PACKET_EAPOL ||
+           type == BTC_PACKET_ARP) {
+               if (type == BTC_PACKET_ARP) {
+                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                "[BTCoex], special Packet ARP notify\n");
+
+                       coex_dm->arp_cnt++;
+                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                "[BTCoex], ARP Packet Count = %d\n",
+                                coex_dm->arp_cnt);
+
+                       if ((coex_dm->arp_cnt >= 10) && (!under_4way))
+                               /* if APR PKT > 10 after connect, do not go to
+                                * ActionWifiConnectedSpecificPacket(btcoexist)
+                                */
+                               coex_sta->wifi_is_high_pri_task = false;
+                       else
+                               coex_sta->wifi_is_high_pri_task = true;
+               } else {
+                       coex_sta->wifi_is_high_pri_task = true;
+                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                "[BTCoex], special Packet DHCP or EAPOL notify\n");
+               }
+       } else {
+               coex_sta->wifi_is_high_pri_task = false;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], special Packet [Type = %d] notify\n",
+                        type);
+       }
+
        btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS,
                &wifi_link_status);
        num_of_wifi_link = wifi_link_status >> 16;
@@ -2209,16 +3150,58 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
                                 "0x%02x, ", tmp_buf[i]);
        }
 
-       if (BT_INFO_SRC_8723B_1ANT_WIFI_FW != rsp_source) {
-               coex_sta->bt_retry_cnt =        /* [3:0] */
+       /* if 0xff, it means BT is under WHCK test */
+       if (bt_info == 0xff)
+               coex_sta->bt_whck_test = true;
+       else
+               coex_sta->bt_whck_test = false;
+
+       if (rsp_source != BT_INFO_SRC_8723B_1ANT_WIFI_FW) {
+               coex_sta->bt_retry_cnt = /* [3:0] */
                        coex_sta->bt_info_c2h[rsp_source][2] & 0xf;
 
+               if (coex_sta->bt_retry_cnt >= 1)
+                       coex_sta->pop_event_cnt++;
+
+               if (coex_sta->bt_info_c2h[rsp_source][2] & 0x20)
+                       coex_sta->c2h_bt_remote_name_req = true;
+               else
+                       coex_sta->c2h_bt_remote_name_req = false;
+
                coex_sta->bt_rssi =
-                       coex_sta->bt_info_c2h[rsp_source][3] * 2 + 10;
+                       coex_sta->bt_info_c2h[rsp_source][3] * 2 - 90;
 
                coex_sta->bt_info_ext =
                        coex_sta->bt_info_c2h[rsp_source][4];
 
+               if (coex_sta->bt_info_c2h[rsp_source][1] == 0x49) {
+                       coex_sta->a2dp_bit_pool =
+                               coex_sta->bt_info_c2h[rsp_source][6];
+               } else {
+                       coex_sta->a2dp_bit_pool = 0;
+               }
+
+               coex_sta->bt_tx_rx_mask =
+                       (coex_sta->bt_info_c2h[rsp_source][2] & 0x40);
+               btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TX_RX_MASK,
+                                  &coex_sta->bt_tx_rx_mask);
+
+               if (!coex_sta->bt_tx_rx_mask) {
+                       /* BT into is responded by BT FW and BT RF REG
+                        * 0x3C != 0x15 => Need to switch BT TRx Mask
+                        */
+                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                "[BTCoex], Switch BT TRx Mask since BT RF REG 0x3C != 0x15\n");
+                       btcoexist->btc_set_bt_reg(btcoexist, BTC_BT_REG_RF,
+                                                 0x3c, 0x15);
+
+                       /* BT TRx Mask lock 0x2c[0], 0x30[0] = 0 */
+                       btcoexist->btc_set_bt_reg(btcoexist, BTC_BT_REG_RF,
+                                                 0x2c, 0x7c44);
+                       btcoexist->btc_set_bt_reg(btcoexist, BTC_BT_REG_RF,
+                                                 0x30, 0x7c44);
+               }
+
                /* Here we need to resend some wifi info to BT
                 * because bt is reset and loss of the info.
                 */
@@ -2247,14 +3230,15 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
                } else {
                        /* BT already NOT ignore Wlan active, do nothing here.*/
                }
-#if (BT_AUTO_REPORT_ONLY_8723B_1ANT == 0)
-               if (coex_sta->bt_info_ext & BIT4) {
-                       /* BT auto report already enabled, do nothing */
-               } else {
-                       halbtc8723b1ant_bt_auto_report(btcoexist, FORCE_EXEC,
-                                                      true);
+               if (!btcoexist->auto_report_1ant) {
+                       if (coex_sta->bt_info_ext & BIT4) {
+                               /* BT auto report already enabled, do nothing */
+                       } else {
+                               halbtc8723b1ant_bt_auto_report(btcoexist,
+                                                              FORCE_EXEC,
+                                                              true);
+                       }
                }
-#endif
        }
 
        /* check BIT2 first ==> check if bt is under inquiry or page scan */
@@ -2263,6 +3247,8 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
        else
                coex_sta->c2h_bt_inquiry_page = false;
 
+       coex_sta->num_of_profile = 0;
+
        /* set link exist status */
        if (!(bt_info & BT_INFO_8723B_1ANT_B_CONNECTION)) {
                coex_sta->bt_link_exist = false;
@@ -2270,30 +3256,77 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
                coex_sta->a2dp_exist = false;
                coex_sta->hid_exist = false;
                coex_sta->sco_exist = false;
+
+               coex_sta->bt_hi_pri_link_exist = false;
        } else {
                /* connection exists */
                coex_sta->bt_link_exist = true;
-               if (bt_info & BT_INFO_8723B_1ANT_B_FTP)
+               if (bt_info & BT_INFO_8723B_1ANT_B_FTP) {
                        coex_sta->pan_exist = true;
-               else
+                       coex_sta->num_of_profile++;
+               } else {
                        coex_sta->pan_exist = false;
-               if (bt_info & BT_INFO_8723B_1ANT_B_A2DP)
+               }
+               if (bt_info & BT_INFO_8723B_1ANT_B_A2DP) {
                        coex_sta->a2dp_exist = true;
-               else
+                       coex_sta->num_of_profile++;
+               } else {
                        coex_sta->a2dp_exist = false;
-               if (bt_info & BT_INFO_8723B_1ANT_B_HID)
+               }
+               if (bt_info & BT_INFO_8723B_1ANT_B_HID) {
                        coex_sta->hid_exist = true;
-               else
+                       coex_sta->num_of_profile++;
+               } else {
                        coex_sta->hid_exist = false;
-               if (bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO)
+               }
+               if (bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO) {
                        coex_sta->sco_exist = true;
-               else
+                       coex_sta->num_of_profile++;
+               } else {
                        coex_sta->sco_exist = false;
+               }
+
+               if ((!coex_sta->hid_exist) &&
+                   (!coex_sta->c2h_bt_inquiry_page) &&
+                   (!coex_sta->sco_exist)) {
+                       if (coex_sta->high_priority_tx +
+                                   coex_sta->high_priority_rx >=
+                           160) {
+                               coex_sta->hid_exist = true;
+                               coex_sta->wrong_profile_notification++;
+                               coex_sta->num_of_profile++;
+                               bt_info = bt_info | 0x28;
+                       }
+               }
+
+               /* Add Hi-Pri Tx/Rx counter to avoid false detection */
+               if (((coex_sta->hid_exist) || (coex_sta->sco_exist)) &&
+                   (coex_sta->high_priority_tx + coex_sta->high_priority_rx >=
+                    160) &&
+                   (!coex_sta->c2h_bt_inquiry_page))
+                       coex_sta->bt_hi_pri_link_exist = true;
+
+               if ((bt_info & BT_INFO_8723B_1ANT_B_ACL_BUSY) &&
+                   (coex_sta->num_of_profile == 0)) {
+                       if (coex_sta->low_priority_tx +
+                                   coex_sta->low_priority_rx >=
+                           160) {
+                               coex_sta->pan_exist = true;
+                               coex_sta->num_of_profile++;
+                               coex_sta->wrong_profile_notification++;
+                               bt_info = bt_info | 0x88;
+                       }
+               }
        }
 
        halbtc8723b1ant_update_bt_link_info(btcoexist);
 
-       if (!(bt_info&BT_INFO_8723B_1ANT_B_CONNECTION)) {
+       /* mask profile bit for connect-ilde identification
+        * ( for CSR case: A2DP idle --> 0x41)
+        */
+       bt_info = bt_info & 0x1f;
+
+       if (!(bt_info & BT_INFO_8723B_1ANT_B_CONNECTION)) {
                coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE;
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], BtInfoNotify(), BT Non-Connected idle!\n");
@@ -2315,8 +3348,7 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n");
        } else {
-               coex_dm->bt_status =
-                       BT_8723B_1ANT_BT_STATUS_MAX;
+               coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_MAX;
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], BtInfoNotify(), BT Non-Defined state!!\n");
        }
@@ -2332,6 +3364,43 @@ void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
        halbtc8723b1ant_run_coexist_mechanism(btcoexist);
 }
 
+void ex_halbtc8723b1ant_rf_status_notify(struct btc_coexist *btcoexist, u8 type)
+{
+       struct rtl_priv *rtlpriv = btcoexist->adapter;
+       u32 u32tmp;
+       u8 u8tmpa, u8tmpb, u8tmpc;
+
+       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                "[BTCoex], RF Status notify\n");
+
+       if (type == BTC_RF_ON) {
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], RF is turned ON!!\n");
+               btcoexist->stop_coex_dm = false;
+       } else if (type == BTC_RF_OFF) {
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], RF is turned OFF!!\n");
+
+               halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+                                                0x0, 0x0);
+               halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 0);
+               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT,
+                                            FORCE_EXEC, false, true);
+
+               halbtc8723b1ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true);
+               btcoexist->stop_coex_dm = true;
+
+               u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x948);
+               u8tmpa = btcoexist->btc_read_1byte(btcoexist, 0x765);
+               u8tmpb = btcoexist->btc_read_1byte(btcoexist, 0x67);
+               u8tmpc = btcoexist->btc_read_1byte(btcoexist, 0x76e);
+
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "############# [BTCoex], 0x948=0x%x, 0x765=0x%x, 0x67=0x%x, 0x76e=0x%x\n",
+                        u32tmp, u8tmpa, u8tmpb, u8tmpc);
+       }
+}
+
 void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist)
 {
        struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -2340,7 +3409,8 @@ void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist)
 
        btcoexist->stop_coex_dm = true;
 
-       halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, false, true);
+       halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, FORCE_EXEC,
+                                    false, true);
 
        halbtc8723b1ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true);
 
@@ -2349,6 +3419,8 @@ void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist)
        halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 0);
 
        ex_halbtc8723b1ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT);
+
+       btcoexist->stop_coex_dm = true;
 }
 
 void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
@@ -2360,18 +3432,27 @@ void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
        if (BTC_WIFI_PNP_SLEEP == pnp_state) {
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], Pnp notify to SLEEP\n");
-               btcoexist->stop_coex_dm = true;
-               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, false,
-                                            true);
+               halbtc8723b1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT,
+                                            FORCE_EXEC, false, true);
                halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
                                                 0x0, 0x0);
                halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 0);
                halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
+
+               /* Driver do not leave IPS/LPS when driver is going to sleep, so
+                * BTCoexistence think wifi is still under IPS/LPS
+                *
+                * BT should clear UnderIPS/UnderLPS state to avoid mismatch
+                * state after wakeup.
+                */
+               coex_sta->under_ips = false;
+               coex_sta->under_lps = false;
+               btcoexist->stop_coex_dm = true;
        } else if (BTC_WIFI_PNP_WAKE_UP == pnp_state) {
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], Pnp notify to WAKE UP\n");
                btcoexist->stop_coex_dm = false;
-               halbtc8723b1ant_init_hw_config(btcoexist, false);
+               halbtc8723b1ant_init_hw_config(btcoexist, false, false);
                halbtc8723b1ant_init_coex_dm(btcoexist);
                halbtc8723b1ant_query_bt_info(btcoexist);
        }
@@ -2384,57 +3465,33 @@ void ex_halbtc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist)
        RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                 "[BTCoex], *****************Coex DM Reset****************\n");
 
-       halbtc8723b1ant_init_hw_config(btcoexist, false);
-       btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-       btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x2, 0xfffff, 0x0);
+       halbtc8723b1ant_init_hw_config(btcoexist, false, false);
        halbtc8723b1ant_init_coex_dm(btcoexist);
 }
 
 void ex_halbtc8723b1ant_periodical(struct btc_coexist *btcoexist)
 {
        struct rtl_priv *rtlpriv = btcoexist->adapter;
-       struct btc_board_info *board_info = &btcoexist->board_info;
-       struct btc_stack_info *stack_info = &btcoexist->stack_info;
-       static u8 dis_ver_info_cnt;
-       u32 fw_ver = 0, bt_patch_ver = 0;
+       struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
 
        RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                 "[BTCoex], ==========================Periodical===========================\n");
 
-       if (dis_ver_info_cnt <= 5) {
-               dis_ver_info_cnt += 1;
-               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                        "[BTCoex], ****************************************************************\n");
-               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                        "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n",
-                        board_info->pg_ant_num, board_info->btdm_ant_num,
-                        board_info->btdm_ant_pos);
-               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                        "[BTCoex], BT stack/ hci ext ver = %s / %d\n",
-                        stack_info->profile_notified ? "Yes" : "No",
-                        stack_info->hci_version);
-               btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER,
-                                  &bt_patch_ver);
-               btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver);
-               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                        "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n",
-                        glcoex_ver_date_8723b_1ant,
-                        glcoex_ver_8723b_1ant, fw_ver,
-                        bt_patch_ver, bt_patch_ver);
-               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                        "[BTCoex], ****************************************************************\n");
-       }
+       if (!btcoexist->auto_report_1ant) {
+               halbtc8723b1ant_query_bt_info(btcoexist);
+               halbtc8723b1ant_monitor_bt_enable_disable(btcoexist);
+       } else {
+               halbtc8723b1ant_monitor_bt_ctr(btcoexist);
+               halbtc8723b1ant_monitor_wifi_ctr(btcoexist);
 
-#if (BT_AUTO_REPORT_ONLY_8723B_1ANT == 0)
-       halbtc8723b1ant_query_bt_info(btcoexist);
-       halbtc8723b1ant_monitor_bt_ctr(btcoexist);
-       halbtc8723b1ant_monitor_bt_enable_disable(btcoexist);
-#else
-       if (btc8723b1ant_is_wifi_status_changed(btcoexist) ||
-           coex_dm->auto_tdma_adjust) {
-               halbtc8723b1ant_run_coexist_mechanism(btcoexist);
-       }
+               if ((coex_sta->high_priority_tx + coex_sta->high_priority_rx < 50) &&
+                   bt_link_info->hid_exist)
+                       bt_link_info->hid_exist = false;
 
-       coex_sta->special_pkt_period_cnt++;
-#endif
+               if (btc8723b1ant_is_wifi_status_changed(btcoexist) ||
+                   coex_dm->auto_tdma_adjust) {
+                       halbtc8723b1ant_run_coexist_mechanism(btcoexist);
+               }
+               coex_sta->special_pkt_period_cnt++;
+       }
 }
index 75f8094b7a34732ad7079e0718a35ee23efbe2fe..506961a1ca567e3b728f36d4cf2fda4c96a7af55 100644 (file)
@@ -25,8 +25,6 @@
 /**********************************************************************
  * The following is for 8723B 1ANT BT Co-exist definition
  **********************************************************************/
-#define        BT_AUTO_REPORT_ONLY_8723B_1ANT                  1
-
 #define        BT_INFO_8723B_1ANT_B_FTP                        BIT7
 #define        BT_INFO_8723B_1ANT_B_A2DP                       BIT6
 #define        BT_INFO_8723B_1ANT_B_HID                        BIT5
@@ -41,6 +39,8 @@
 
 #define        BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT             2
 
+#define BT_8723B_1ANT_WIFI_NOISY_THRESH                        50
+
 enum _BT_INFO_SRC_8723B_1ANT {
        BT_INFO_SRC_8723B_1ANT_WIFI_FW                  = 0x0,
        BT_INFO_SRC_8723B_1ANT_BT_RSP                   = 0x1,
@@ -84,13 +84,16 @@ enum _BT_8723B_1ANT_COEX_ALGO {
 };
 
 struct coex_dm_8723b_1ant {
+       /* hw setting */
+       u8 pre_ant_pos_type;
+       u8 cur_ant_pos_type;
        /* fw mechanism */
        bool cur_ignore_wlan_act;
        bool pre_ignore_wlan_act;
        u8 pre_ps_tdma;
        u8 cur_ps_tdma;
        u8 ps_tdma_para[5];
-       u8 tdma_adj_type;
+       u8 ps_tdma_du_adj_type;
        bool auto_tdma_adjust;
        bool pre_ps_tdma_on;
        bool cur_ps_tdma_on;
@@ -133,16 +136,21 @@ struct coex_dm_8723b_1ant {
        u8 cur_retry_limit_type;
        u8 pre_ampdu_time_type;
        u8 cur_ampdu_time_type;
+       u32     arp_cnt;
 
        u8 error_condition;
 };
 
 struct coex_sta_8723b_1ant {
+       bool bt_disabled;
        bool bt_link_exist;
        bool sco_exist;
        bool a2dp_exist;
        bool hid_exist;
        bool pan_exist;
+       bool bt_hi_pri_link_exist;
+       u8 num_of_profile;
+       bool bt_abnormal_scan;
 
        bool under_lps;
        bool under_ips;
@@ -154,18 +162,47 @@ struct coex_sta_8723b_1ant {
        u8 bt_rssi;
        u8 pre_bt_rssi_state;
        u8 pre_wifi_rssi_state[4];
+       bool bt_tx_rx_mask;
        bool c2h_bt_info_req_sent;
        u8 bt_info_c2h[BT_INFO_SRC_8723B_1ANT_MAX][10];
        u32 bt_info_c2h_cnt[BT_INFO_SRC_8723B_1ANT_MAX];
+       bool bt_whck_test;
        bool c2h_bt_inquiry_page;
+       bool c2h_bt_remote_name_req;
+       bool wifi_is_high_pri_task;
        u8 bt_retry_cnt;
        u8 bt_info_ext;
+       u8 scan_ap_num;
+       bool cck_ever_lock;
+       u8 coex_table_type;
+       bool force_lps_on;
+       u32 pop_event_cnt;
+
+       u32 crc_ok_cck;
+       u32 crc_ok_11g;
+       u32 crc_ok_11n;
+       u32 crc_ok_11n_agg;
+
+       u32 crc_err_cck;
+       u32 crc_err_11g;
+       u32 crc_err_11n;
+       u32 crc_err_11n_agg;
+
+       bool cck_lock;
+       bool pre_ccklock;
+
+       u32 wrong_profile_notification;
+
+       u8 a2dp_bit_pool;
+       u8 cut_version;
 };
 
 /*************************************************************************
  * The following is interface which will notify coex module.
  *************************************************************************/
-void ex_halbtc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist);
+void ex_halbtc8723b1ant_power_on_setting(struct btc_coexist *btcoexist);
+void ex_halbtc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist,
+                                     bool wifi_only);
 void ex_halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist);
 void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type);
 void ex_halbtc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type);
@@ -177,6 +214,8 @@ void ex_halbtc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist,
                                              u8 type);
 void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist,
                                       u8 *tmpbuf, u8 length);
+void ex_halbtc8723b1ant_rf_status_notify(struct btc_coexist *btcoexist,
+                                        u8 type);
 void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist);
 void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate);
 void ex_halbtc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist);
index 2f3946be4ce29bdb581753b515faa78bf7750be8..31965f0ef69de64f6f5189c7e1833af3e0f25d74 100644 (file)
@@ -707,6 +707,36 @@ static void btc8723b2ant_dec_bt_pwr(struct btc_coexist *btcoexist,
        coex_dm->pre_dec_bt_pwr_lvl = coex_dm->cur_dec_bt_pwr_lvl;
 }
 
+static
+void halbtc8723b2ant_set_bt_auto_report(struct btc_coexist *btcoexist,
+                                       bool enable_auto_report)
+{
+       u8 h2c_parameter[1] = {0};
+
+       h2c_parameter[0] = 0;
+
+       if (enable_auto_report)
+               h2c_parameter[0] |= BIT(0);
+
+       btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter);
+}
+
+static
+void btc8723b2ant_bt_auto_report(struct btc_coexist *btcoexist,
+                                bool force_exec, bool enable_auto_report)
+{
+       coex_dm->cur_bt_auto_report = enable_auto_report;
+
+       if (!force_exec) {
+               if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report)
+                       return;
+       }
+       halbtc8723b2ant_set_bt_auto_report(btcoexist,
+                                          coex_dm->cur_bt_auto_report);
+
+       coex_dm->pre_bt_auto_report = coex_dm->cur_bt_auto_report;
+}
+
 static void btc8723b2ant_fw_dac_swing_lvl(struct btc_coexist *btcoexist,
                                          bool force_exec, u8 fw_dac_swing_lvl)
 {
@@ -3666,6 +3696,7 @@ void ex_btc8723b2ant_init_hwconfig(struct btc_coexist *btcoexist)
        btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4);
        btcoexist->btc_write_1byte(btcoexist, 0x778, 0x3);
        btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1);
+       btcoexist->auto_report_2ant = true;
 }
 
 void ex_btc8723b2ant_power_on_setting(struct btc_coexist *btcoexist)
@@ -3966,9 +3997,8 @@ void ex_btc8723b2ant_display_coex_info(struct btc_coexist *btcoexist)
        RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d",
                 "0x774(low-pri rx/tx)", coex_sta->low_priority_rx,
                 coex_sta->low_priority_tx);
-#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 1)
-       btc8723b2ant_monitor_bt_ctr(btcoexist);
-#endif
+       if (btcoexist->auto_report_2ant)
+               btc8723b2ant_monitor_bt_ctr(btcoexist);
        btcoexist->btc_disp_dbg_msg(btcoexist,
        BTC_DBG_DISP_COEX_STATISTICS);
 }
@@ -4190,14 +4220,11 @@ void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist,
                } else {
                        /* BT already NOT ignore Wlan active, do nothing here.*/
                }
-#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 0)
-               if ((coex_sta->bt_info_ext & BIT4)) {
-                       /* BT auto report already enabled, do nothing*/
-               } else {
-                       btc8723b2ant_bt_auto_report(btcoexist, FORCE_EXEC,
-                                                   true);
+               if (!btcoexist->auto_report_2ant) {
+                       if (!(coex_sta->bt_info_ext & BIT4))
+                               btc8723b2ant_bt_auto_report(btcoexist,
+                                                           FORCE_EXEC, true);
                }
-#endif
        }
 
        /* check BIT2 first ==> check if bt is under inquiry or page scan */
@@ -4347,21 +4374,22 @@ void ex_btc8723b2ant_periodical(struct btc_coexist *btcoexist)
                }
        }
 
-#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 0)
-       btc8723b2ant_query_bt_info(btcoexist);
-#else
-       btc8723b2ant_monitor_bt_ctr(btcoexist);
-       btc8723b2ant_monitor_wifi_ctr(btcoexist);
+       if (!btcoexist->auto_report_2ant) {
+               btc8723b2ant_query_bt_info(btcoexist);
+       } else {
+               btc8723b2ant_monitor_bt_ctr(btcoexist);
+               btc8723b2ant_monitor_wifi_ctr(btcoexist);
 
-       /* for some BT speakers that High-Priority pkts appear before
-        * playing, this will cause HID exist
-        */
-       if ((coex_sta->high_priority_tx + coex_sta->high_priority_rx < 50) &&
-           (bt_link_info->hid_exist))
-               bt_link_info->hid_exist = false;
-
-       if (btc8723b2ant_is_wifi_status_changed(btcoexist) ||
-           coex_dm->auto_tdma_adjust)
-               btc8723b2ant_run_coexist_mechanism(btcoexist);
-#endif
+               /* for some BT speakers that High-Priority pkts appear before
+                * playing, this will cause HID exist
+                */
+               if ((coex_sta->high_priority_tx +
+                   coex_sta->high_priority_rx < 50) &&
+                   (bt_link_info->hid_exist))
+                       bt_link_info->hid_exist = false;
+
+               if (btc8723b2ant_is_wifi_status_changed(btcoexist) ||
+                   coex_dm->auto_tdma_adjust)
+                       btc8723b2ant_run_coexist_mechanism(btcoexist);
+       }
 }
index 18a35c7faba92a1e8a0d0f858960329fc4a30462..50726beaeead2fba66dcc7e6c70600b24b70838b 100644 (file)
@@ -28,8 +28,6 @@
 /************************************************************************
  * The following is for 8723B 2Ant BT Co-exist definition
  ************************************************************************/
-#define        BT_AUTO_REPORT_ONLY_8723B_2ANT                  1
-
 #define        BT_INFO_8723B_2ANT_B_FTP                        BIT7
 #define        BT_INFO_8723B_2ANT_B_A2DP                       BIT6
 #define        BT_INFO_8723B_2ANT_B_HID                        BIT5
index 5e9f3b0f7a2583e36bc5c747325a52fbfb73141a..4efac5fe9982070d73e0e31f3979a1a130d83eeb 100644 (file)
@@ -1107,8 +1107,8 @@ static void btc8821a1ant_ps_tdma(struct btc_coexist *btcoexist,
                                                    0x3, 0x11, 0x10);
                        break;
                case 6:
-                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xa,
-                                                   0x3, 0x0, 0x0);
+                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x20,
+                                                   0x3, 0x11, 0x13);
                        break;
                case 7:
                        btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xc,
@@ -1128,8 +1128,8 @@ static void btc8821a1ant_ps_tdma(struct btc_coexist *btcoexist,
                                                    0xa, 0x0, 0x40);
                        break;
                case 11:
-                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x14,
-                                                   0x03, 0x10, 0x10);
+                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x15,
+                                                   0x03, 0x10, 0x50);
                        rssi_adjust_val = 20;
                        break;
                case 12:
@@ -1137,8 +1137,8 @@ static void btc8821a1ant_ps_tdma(struct btc_coexist *btcoexist,
                                                    0x0a, 0x0, 0x50);
                        break;
                case 13:
-                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x18,
-                                                   0x18, 0x0, 0x10);
+                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x12,
+                                                   0x12, 0x0, 0x50);
                        break;
                case 14:
                        btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x1e,
@@ -1163,8 +1163,8 @@ static void btc8821a1ant_ps_tdma(struct btc_coexist *btcoexist,
                                                    0x03, 0x11, 0x10);
                        break;
                case 21:
-                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x15,
-                                                   0x03, 0x11, 0x10);
+                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x25,
+                                                   0x03, 0x11, 0x11);
                        break;
                case 22:
                        btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x25,
@@ -1204,16 +1204,16 @@ static void btc8821a1ant_ps_tdma(struct btc_coexist *btcoexist,
                                                    0x1a, 0x1, 0x10);
                        break;
                case 30:
-                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x14,
-                                                   0x3, 0x10, 0x50);
+                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x30,
+                                                   0x3, 0x10, 0x10);
                        break;
                case 31:
                        btc8821a1ant_set_fw_ps_tdma(btcoexist, 0xd3, 0x1a,
                                                    0x1a, 0, 0x58);
                        break;
                case 32:
-                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x61, 0xa,
-                                                   0x3, 0x10, 0x0);
+                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x35,
+                                                   0x3, 0x11, 0x11);
                        break;
                case 33:
                        btc8821a1ant_set_fw_ps_tdma(btcoexist, 0xa3, 0x25,
@@ -1231,6 +1231,28 @@ static void btc8821a1ant_ps_tdma(struct btc_coexist *btcoexist,
                        btc8821a1ant_set_fw_ps_tdma(btcoexist, 0xd3, 0x12,
                                                    0x3, 0x14, 0x50);
                        break;
+               case 40:
+                       /* SoftAP only with no sta associated, BT disable, TDMA
+                        * mode for power saving
+                        *
+                        * here softap mode screen off will cost 70-80mA for
+                        * phone
+                        */
+                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x23, 0x18,
+                                                   0x00, 0x10, 0x24);
+                       break;
+               case 41:
+                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x15,
+                                                   0x3, 0x11, 0x11);
+                       break;
+               case 42:
+                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x20,
+                                                   0x3, 0x11, 0x11);
+                       break;
+               case 43:
+                       btc8821a1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x30,
+                                                   0x3, 0x10, 0x11);
+                       break;
                }
        } else {
                /* disable PS tdma */
@@ -1619,15 +1641,23 @@ static void btc8821a1ant_act_wifi_con_bt_acl_busy(struct btc_coexist *btcoexist,
                return;
        } else if (bt_link_info->a2dp_only) {
                /* A2DP */
-               if ((bt_rssi_state != BTC_RSSI_STATE_HIGH) &&
-                   (bt_rssi_state != BTC_RSSI_STATE_STAY_HIGH)) {
+               if (wifi_status == BT_8821A_1ANT_WIFI_STATUS_CONNECTED_IDLE) {
+                       btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32);
+                       btc8821a1ant_coex_table_with_type(btcoexist,
+                                                         NORMAL_EXEC, 1);
+                       coex_dm->auto_tdma_adjust = false;
+               } else if ((bt_rssi_state != BTC_RSSI_STATE_HIGH) &&
+                          (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
+                       btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14);
+                       btc8821a1ant_coex_table_with_type(btcoexist,
+                                                         NORMAL_EXEC, 1);
+               } else {
                        /* for low BT RSSI */
-                       btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
-                                            true, 11);
+                       btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14);
+                       btc8821a1ant_coex_table_with_type(btcoexist,
+                                                         NORMAL_EXEC, 1);
                        coex_dm->auto_tdma_adjust = false;
                }
-
-               btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
        } else if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) {
                /* HID+A2DP */
                if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
@@ -1638,7 +1668,7 @@ static void btc8821a1ant_act_wifi_con_bt_acl_busy(struct btc_coexist *btcoexist,
                } else {
                        /*for low BT RSSI*/
                        btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
-                                            true, 11);
+                                            true, 14);
                        coex_dm->auto_tdma_adjust = false;
                }
 
@@ -1647,13 +1677,13 @@ static void btc8821a1ant_act_wifi_con_bt_acl_busy(struct btc_coexist *btcoexist,
                (bt_link_info->hid_exist && bt_link_info->pan_exist)) {
                /* PAN(OPP, FTP), HID+PAN(OPP, FTP) */
                btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3);
-               btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+               btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 6);
                coex_dm->auto_tdma_adjust = false;
        } else if (((bt_link_info->a2dp_exist) && (bt_link_info->pan_exist)) ||
                   (bt_link_info->hid_exist && bt_link_info->a2dp_exist &&
                    bt_link_info->pan_exist)) {
                /* A2DP+PAN(OPP, FTP), HID+A2DP+PAN(OPP, FTP) */
-               btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13);
+               btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 43);
                btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
                coex_dm->auto_tdma_adjust = false;
        } else {
@@ -1718,52 +1748,49 @@ void btc8821a1ant_action_wifi_connected_scan(struct btc_coexist *btcoexist)
 
        /* tdma and coex table */
        if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
-               if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) {
-                       btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 22);
+               if (bt_link_info->a2dp_exist) {
+                       btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14);
                        btc8821a1ant_coex_table_with_type(btcoexist,
                                                          NORMAL_EXEC, 1);
                } else {
-               btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
-               btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
-       }
-       } else if ((BT_8821A_1ANT_BT_STATUS_SCO_BUSY ==
-                   coex_dm->bt_status) ||
-                  (BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY ==
-                   coex_dm->bt_status)) {
+                       btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
+                       btc8821a1ant_coex_table_with_type(btcoexist,
+                                                         NORMAL_EXEC, 4);
+               }
+       } else if ((coex_dm->bt_status == BT_8821A_1ANT_BT_STATUS_SCO_BUSY) ||
+                  (coex_dm->bt_status ==
+                   BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY)) {
                btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist,
                        BT_8821A_1ANT_WIFI_STATUS_CONNECTED_SCAN);
        } else {
-               btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
-               btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+               btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+               btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
        }
 }
 
 static void btc8821a1ant_act_wifi_conn_sp_pkt(struct btc_coexist *btcoexist)
 {
        struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info;
-       bool hs_connecting = false;
-
-       btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_CONNECTING, &hs_connecting);
 
        btc8821a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
                                      0x0, 0x0);
 
        /* tdma and coex table */
-       if (coex_dm->bt_status == BT_8821A_1ANT_BT_STATUS_ACL_BUSY) {
-               if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) {
-                       btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
-                                            true, 22);
-                       btc8821a1ant_coex_table_with_type(btcoexist,
-                                                         NORMAL_EXEC, 1);
-               } else {
-                       btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
-                                            true, 20);
-                       btc8821a1ant_coex_table_with_type(btcoexist,
-                                                         NORMAL_EXEC, 1);
-               }
-       } else {
-               btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
+       if ((bt_link_info->sco_exist) || (bt_link_info->hid_exist) ||
+           (bt_link_info->a2dp_exist)) {
+               btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32);
+               btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+       }
+
+       if ((bt_link_info->hid_exist) && (bt_link_info->a2dp_exist)) {
+               btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14);
                btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1);
+       } else if (bt_link_info->pan_exist) {
+               btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20);
+               btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 4);
+       } else {
+               btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+               btc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2);
        }
 }
 
@@ -1773,6 +1800,7 @@ static void btc8821a1ant_action_wifi_connected(struct btc_coexist *btcoexist)
        bool wifi_busy = false;
        bool scan = false, link = false, roam = false;
        bool under_4way = false;
+       bool ap_enable = false;
 
        RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                 "[BTCoex], CoexForWifiConnect()===>\n");
@@ -1790,24 +1818,37 @@ static void btc8821a1ant_action_wifi_connected(struct btc_coexist *btcoexist)
        btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link);
        btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam);
        if (scan || link || roam) {
-               btc8821a1ant_action_wifi_connected_scan(btcoexist);
+               if (scan)
+                       btc8821a1ant_action_wifi_connected_scan(btcoexist);
+               else
+                       btc8821a1ant_act_wifi_conn_sp_pkt(btcoexist);
+
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], CoexForWifiConnect(), return for wifi is under scan<===\n");
                return;
        }
 
        /* power save state*/
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE,
+                          &ap_enable);
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
        if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY ==
-                       coex_dm->bt_status && !btcoexist->bt_link_info.hid_only)
-               btc8821a1ant_power_save_state(btcoexist,
-                                             BTC_PS_LPS_ON, 0x50, 0x4);
-       else
+           coex_dm->bt_status && !ap_enable &&
+           !btcoexist->bt_link_info.hid_only) {
+               if (!wifi_busy && btcoexist->bt_link_info.a2dp_only)
+                       /* A2DP */
+                       btc8821a1ant_power_save_state(btcoexist,
+                                               BTC_PS_WIFI_NATIVE, 0x0, 0x0);
+               else
+                       btc8821a1ant_power_save_state(btcoexist, BTC_PS_LPS_ON,
+                                                     0x50, 0x4);
+       } else {
                btc8821a1ant_power_save_state(btcoexist,
                                              BTC_PS_WIFI_NATIVE,
                                              0x0, 0x0);
+       }
 
        /* tdma and coex table */
-       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
        if (!wifi_busy) {
                if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) {
                        btc8821a1ant_act_wifi_con_bt_acl_busy(btcoexist,
@@ -1819,8 +1860,7 @@ static void btc8821a1ant_action_wifi_connected(struct btc_coexist *btcoexist)
                        btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist,
                                BT_8821A_1ANT_WIFI_STATUS_CONNECTED_IDLE);
                } else {
-                       btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC,
-                                            true, 5);
+                       btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
                        btc8821a1ant_coex_table_with_type(btcoexist,
                                                          NORMAL_EXEC, 2);
                }
@@ -1835,7 +1875,7 @@ static void btc8821a1ant_action_wifi_connected(struct btc_coexist *btcoexist)
                        btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist,
                                BT_8821A_1ANT_WIFI_STATUS_CONNECTED_BUSY);
                } else {
-                       btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5);
+                       btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
                        btc8821a1ant_coex_table_with_type(btcoexist,
                                                          NORMAL_EXEC, 2);
                }
@@ -1988,11 +2028,11 @@ static void btc8821a1ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
                            (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
                                btc8821a1ant_limited_tx(btcoexist,
                                                        NORMAL_EXEC, 1, 1,
-                                                       1, 1);
+                                                       0, 1);
                        } else {
                                btc8821a1ant_limited_tx(btcoexist,
                                                        NORMAL_EXEC, 1, 1,
-                                                       1, 1);
+                                                       0, 1);
                        }
                } else {
                        btc8821a1ant_limited_tx(btcoexist, NORMAL_EXEC,
@@ -2056,7 +2096,6 @@ static void btc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist)
         */
        btc8821a1ant_sw_mechanism(btcoexist, false);
 
-       btc8821a1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
        btc8821a1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0);
 }
 
@@ -2116,6 +2155,7 @@ static void btc8821a1ant_init_hw_config(struct btc_coexist *btcoexist,
 void ex_btc8821a1ant_init_hwconfig(struct btc_coexist *btcoexist, bool wifionly)
 {
        btc8821a1ant_init_hw_config(btcoexist, true, wifionly);
+       btcoexist->auto_report_1ant = true;
 }
 
 void ex_btc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist)
@@ -2406,9 +2446,8 @@ void ex_btc8821a1ant_display_coex_info(struct btc_coexist *btcoexist)
        RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
                 "\r\n %-35s = %d/ %d", "0x774(low-pri rx/tx)",
                 coex_sta->low_priority_rx, coex_sta->low_priority_tx);
-#if (BT_AUTO_REPORT_ONLY_8821A_1ANT == 1)
-       btc8821a1ant_monitor_bt_ctr(btcoexist);
-#endif
+       if (btcoexist->auto_report_1ant)
+               btc8821a1ant_monitor_bt_ctr(btcoexist);
        btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS);
 }
 
@@ -2434,7 +2473,7 @@ void ex_btc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
                btc8821a1ant_set_ant_path(btcoexist,
                                          BTC_ANT_PATH_BT, false, true);
                /* set PTA control */
-               btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8);
+               btc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 0);
                btc8821a1ant_coex_table_with_type(btcoexist,
                                                  NORMAL_EXEC, 0);
        } else if (BTC_IPS_LEAVE == type) {
@@ -2442,7 +2481,9 @@ void ex_btc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
                         "[BTCoex], IPS LEAVE notify\n");
                coex_sta->under_ips = false;
 
-               btc8821a1ant_run_coexist_mechanism(btcoexist);
+               btc8821a1ant_init_hw_config(btcoexist, false, false);
+               btc8821a1ant_init_coex_dm(btcoexist);
+               btc8821a1ant_query_bt_info(btcoexist);
        }
 }
 
@@ -2484,6 +2525,19 @@ void ex_btc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type)
                return;
        }
 
+       if (type == BTC_SCAN_START) {
+               coex_sta->wifi_is_high_pri_task = true;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], SCAN START notify\n");
+
+               /* Force antenna setup for no scan result issue */
+               btc8821a1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8);
+       } else {
+               coex_sta->wifi_is_high_pri_task = false;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], SCAN FINISH notify\n");
+       }
+
        if (coex_sta->bt_disabled)
                return;
 
@@ -2538,7 +2592,7 @@ void ex_btc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type)
 void ex_btc8821a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type)
 {
        struct rtl_priv *rtlpriv = btcoexist->adapter;
-       bool    wifi_connected = false, bt_hs_on = false;
+       bool wifi_connected = false, bt_hs_on = false;
        u32 wifi_link_status = 0;
        u32 num_of_wifi_link = 0;
        bool bt_ctrl_agg_buf_size = false;
@@ -2556,6 +2610,18 @@ void ex_btc8821a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type)
                return;
        }
 
+       if (type == BTC_ASSOCIATE_START) {
+               coex_sta->wifi_is_high_pri_task = true;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], CONNECT START notify\n");
+               coex_dm->arp_cnt = 0;
+       } else {
+               coex_sta->wifi_is_high_pri_task = false;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], CONNECT FINISH notify\n");
+               coex_dm->arp_cnt = 0;
+       }
+
        btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS,
                           &wifi_link_status);
        num_of_wifi_link = wifi_link_status >> 16;
@@ -2621,6 +2687,7 @@ void ex_btc8821a1ant_media_status_notify(struct btc_coexist *btcoexist,
        } else {
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], MEDIA disconnect notify\n");
+               coex_dm->arp_cnt = 0;
        }
 
        /* only 2.4G we need to inform bt the chnl mask */
@@ -2674,6 +2741,24 @@ void ex_btc8821a1ant_special_packet_notify(struct btc_coexist *btcoexist,
                return;
        }
 
+       if (type == BTC_PACKET_DHCP || type == BTC_PACKET_EAPOL ||
+           type == BTC_PACKET_ARP) {
+               coex_sta->wifi_is_high_pri_task = true;
+
+               if (type == BTC_PACKET_ARP) {
+                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                "[BTCoex], specific Packet ARP notify\n");
+               } else {
+                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                "[BTCoex], specific Packet DHCP or EAPOL notify\n");
+               }
+       } else {
+               coex_sta->wifi_is_high_pri_task = false;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], specific Packet [Type = %d] notify\n",
+                        type);
+       }
+
        coex_sta->special_pkt_period_cnt = 0;
 
        btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS,
@@ -2696,8 +2781,20 @@ void ex_btc8821a1ant_special_packet_notify(struct btc_coexist *btcoexist,
                return;
        }
 
-       if (BTC_PACKET_DHCP == type ||
-           BTC_PACKET_EAPOL == type) {
+       if (type == BTC_PACKET_DHCP || type == BTC_PACKET_EAPOL ||
+           type == BTC_PACKET_ARP) {
+               if (type == BTC_PACKET_ARP) {
+                       coex_dm->arp_cnt++;
+                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                "[BTCoex], ARP Packet Count = %d\n",
+                                coex_dm->arp_cnt);
+                       if (coex_dm->arp_cnt >= 10)
+                               /* if APR PKT > 10 after connect, do not go to
+                                * btc8821a1ant_act_wifi_conn_sp_pkt
+                                */
+                               return;
+               }
+
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], special Packet(%d) notify\n", type);
                btc8821a1ant_act_wifi_conn_sp_pkt(btcoexist);
@@ -2742,14 +2839,28 @@ void ex_btc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist,
        }
 
        if (BT_INFO_SRC_8821A_1ANT_WIFI_FW != rsp_source) {
-               coex_sta->bt_retry_cnt =        /* [3:0]*/
-                       coex_sta->bt_info_c2h[rsp_source][2]&0xf;
+               /* [3:0] */
+               coex_sta->bt_retry_cnt =
+                       coex_sta->bt_info_c2h[rsp_source][2] & 0xf;
 
                coex_sta->bt_rssi =
-                       coex_sta->bt_info_c2h[rsp_source][3]*2+10;
+                       coex_sta->bt_info_c2h[rsp_source][3] * 2 + 10;
 
-               coex_sta->bt_info_ext =
-                       coex_sta->bt_info_c2h[rsp_source][4];
+               coex_sta->bt_info_ext = coex_sta->bt_info_c2h[rsp_source][4];
+
+               coex_sta->bt_tx_rx_mask =
+                       (coex_sta->bt_info_c2h[rsp_source][2] & 0x40);
+               btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TX_RX_MASK,
+                                  &coex_sta->bt_tx_rx_mask);
+               if (!coex_sta->bt_tx_rx_mask) {
+                       /* BT into is responded by BT FW and BT RF REG 0x3C !=
+                        * 0x15 => Need to switch BT TRx Mask
+                        */
+                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                "[BTCoex], Switch BT TRx Mask since BT RF REG 0x3C != 0x15\n");
+                       btcoexist->btc_set_bt_reg(btcoexist, BTC_BT_REG_RF,
+                                                 0x3c, 0x15);
+               }
 
                /* Here we need to resend some wifi info to BT
                 * because bt is reset and lost the info
@@ -2831,11 +2942,11 @@ void ex_btc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist,
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n");
        } else if ((bt_info&BT_INFO_8821A_1ANT_B_SCO_ESCO) ||
-               (bt_info&BT_INFO_8821A_1ANT_B_SCO_BUSY)) {
+               (bt_info & BT_INFO_8821A_1ANT_B_SCO_BUSY)) {
                coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_SCO_BUSY;
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n");
-       } else if (bt_info&BT_INFO_8821A_1ANT_B_ACL_BUSY) {
+       } else if (bt_info & BT_INFO_8821A_1ANT_B_ACL_BUSY) {
                if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY != coex_dm->bt_status)
                        coex_dm->auto_tdma_adjust = false;
                coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_ACL_BUSY;
@@ -2964,10 +3075,10 @@ void ex_btc8821a1ant_periodical(struct btc_coexist *btcoexist)
                         "[BTCoex], ****************************************************************\n");
        }
 
-#if (BT_AUTO_REPORT_ONLY_8821A_1ANT == 0)
-       btc8821a1ant_query_bt_info(btcoexist);
-       btc8821a1ant_monitor_bt_ctr(btcoexist);
-#else
-       coex_sta->special_pkt_period_cnt++;
-#endif
+       if (!btcoexist->auto_report_1ant) {
+               btc8821a1ant_query_bt_info(btcoexist);
+               btc8821a1ant_monitor_bt_ctr(btcoexist);
+       } else {
+               coex_sta->special_pkt_period_cnt++;
+       }
 }
index 1bd1ebe3364ebe3e0ac44e17cce0507a9aba566e..cb32e7a64ae6d6d2a1cc1975f52506a428e0f31d 100644 (file)
@@ -27,8 +27,6 @@
  * The following is for 8821A 1ANT BT Co-exist definition
  *===========================================
  */
-#define        BT_AUTO_REPORT_ONLY_8821A_1ANT                          0
-
 #define        BT_INFO_8821A_1ANT_B_FTP        BIT7
 #define        BT_INFO_8821A_1ANT_B_A2DP       BIT6
 #define        BT_INFO_8821A_1ANT_B_HID        BIT5
@@ -135,6 +133,7 @@ struct coex_dm_8821a_1ant {
        u8      cur_retry_limit_type;
        u8      pre_ampdu_time_type;
        u8      cur_ampdu_time_type;
+       u32     arp_cnt;
 
        u8      error_condition;
 };
@@ -155,6 +154,7 @@ struct coex_sta_8821a_1ant {
        u32     low_priority_tx;
        u32     low_priority_rx;
        u8      bt_rssi;
+       bool    bt_tx_rx_mask;
        u8      pre_bt_rssi_state;
        u8      pre_wifi_rssi_state[4];
        bool    c2h_bt_info_req_sent;
index 841b4a83ab70c8f3c5c343702b4a9b7ad7c8e5cc..41943c34edffffe21092f0cbdfc04159138e6f25 100644 (file)
@@ -3220,12 +3220,16 @@ static void btc8821a2ant_action_pan_edr_hid(struct btc_coexist *btcoexist)
 /* HID+A2DP+PAN(EDR) */
 static void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist)
 {
-       u8 wifi_rssi_state, bt_rssi_state, bt_info_ext;
+       u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
        u32 wifi_bw;
 
-       bt_info_ext = coex_sta->bt_info_ext;
        wifi_rssi_state = btc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
-       bt_rssi_state = btc8821a2ant_bt_rssi_state(btcoexist, 2, 35, 0);
+       wifi_rssi_state1 = btc8821a2ant_wifi_rssi_state(btcoexist, 1, 2,
+                               BT_8821A_2ANT_WIFI_RSSI_COEXSWITCH_THRES, 0);
+       bt_rssi_state = btc8821a2ant_bt_rssi_state(btcoexist,
+                               2, BT_8821A_2ANT_BT_RSSI_COEXSWITCH_THRES, 0);
+
+       btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
 
        btc8821a2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8);
        btc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
@@ -3235,44 +3239,32 @@ static void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist)
        else
                btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
 
+       if (BTC_RSSI_HIGH(wifi_rssi_state1) && BTC_RSSI_HIGH(bt_rssi_state)) {
+               btc8821a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7);
+               btc8821a2ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE,
+                                             0x0, 0x0);
+       } else {
+               btc8821a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 14);
+               btc8821a2ant_power_save_state(btcoexist, BTC_PS_LPS_ON, 0x50,
+                                             0x4);
+       }
+
        btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
 
-       if (wifi_bw == BTC_WIFI_BW_LEGACY) {
-               /* for HID at 11b/g mode */
-               btc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff,
-                                       0x5a5a5a5a, 0xffff, 0x3);
+       if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
+           (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
+               if (wifi_bw == BTC_WIFI_BW_HT40)
+                       btc8821a2ant_tdma_duration_adjust(btcoexist, true,
+                                                         true, 3);
+               else
+                       btc8821a2ant_tdma_duration_adjust(btcoexist, true,
+                                                         false, 3);
        } else {
-               /* for HID quality & wifi performance balance at 11n mode */
-               btc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff,
-                                       0x5a5a5a5a, 0xffff, 0x3);
+               btc8821a2ant_tdma_duration_adjust(btcoexist, true, true, 3);
        }
 
-       if (BTC_WIFI_BW_HT40 == wifi_bw) {
-               /* fw mechanism */
-               if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
-                   (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
-                       if (bt_info_ext&BIT0) {
-                               /* a2dp basic rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                       true, true, 3);
-                       } else {
-                               /* a2dp edr rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                       true, true, 3);
-                       }
-               } else {
-                       if (bt_info_ext&BIT0) {
-                               /* a2dp basic rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                       true, true, 3);
-                       } else {
-                               /* a2dp edr rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                       true, true, 3);
-                       }
-               }
-
-               /* sw mechanism */
+       /* sw mechanism */
+       if (wifi_bw == BTC_WIFI_BW_HT40) {
                if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) ||
                    (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
                        btc8821a2ant_sw_mechanism1(btcoexist, true, true,
@@ -3286,33 +3278,6 @@ static void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist)
                                                   false, 0x18);
                }
        } else {
-               /* fw mechanism */
-               if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
-                   (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
-                       if (bt_info_ext&BIT0) {
-                               /* a2dp basic rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                       true, false, 3);
-                       } else {
-                               /* a2dp edr rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                       true, false, 3);
-                       }
-               } else {
-                       if (bt_info_ext&BIT0) {
-                               /* a2dp basic rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                                 true, true,
-                                                                 3);
-                       } else {
-                               /* a2dp edr rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                                 true, true,
-                                                                 3);
-                       }
-               }
-
-               /* sw mechanism */
                if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) ||
                    (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
                        btc8821a2ant_sw_mechanism1(btcoexist, false, true,
@@ -3330,19 +3295,46 @@ static void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist)
 
 static void btc8821a2ant_action_hid_a2dp(struct btc_coexist *btcoexist)
 {
-       u8 wifi_rssi_state, bt_rssi_state, bt_info_ext;
        u32 wifi_bw;
+       u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state;
+       u8 ap_num = 0;
 
-       bt_info_ext = coex_sta->bt_info_ext;
        wifi_rssi_state = btc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, 15, 0);
-       bt_rssi_state = btc8821a2ant_bt_rssi_state(btcoexist, 2, 35, 0);
+       wifi_rssi_state1 = btc8821a2ant_wifi_rssi_state(btcoexist, 1, 2,
+                               BT_8821A_2ANT_WIFI_RSSI_COEXSWITCH_THRES, 0);
+       bt_rssi_state = btc8821a2ant_bt_rssi_state(btcoexist,
+                               3, BT_8821A_2ANT_BT_RSSI_COEXSWITCH_THRES, 37);
 
-       if (BTC_RSSI_HIGH(bt_rssi_state))
-               btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true);
-       else
-               btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false);
+       btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+
+       btc8821a2ant_limited_rx(btcoexist, NORMAL_EXEC, false, true, 0x5);
+       btc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6);
 
        btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw);
+       if (wifi_bw == BTC_WIFI_BW_LEGACY) {
+               if (BTC_RSSI_HIGH(bt_rssi_state))
+                       btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+               else if (BTC_RSSI_MEDIUM(bt_rssi_state))
+                       btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+               else
+                       btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+       } else {
+               /* only 802.11N mode we have to dec bt power to 4 degree */
+               if (BTC_RSSI_HIGH(bt_rssi_state)) {
+                       btcoexist->btc_get(btcoexist, BTC_GET_U1_AP_NUM,
+                                          &ap_num);
+                       if (ap_num < 10)
+                               btc8821a2ant_dec_bt_pwr(btcoexist,
+                                                       NORMAL_EXEC, 4);
+                       else
+                               btc8821a2ant_dec_bt_pwr(btcoexist,
+                                                       NORMAL_EXEC, 2);
+               } else if (BTC_RSSI_MEDIUM(bt_rssi_state)) {
+                       btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 2);
+               } else {
+                       btc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, 0);
+               }
+       }
 
        if (wifi_bw == BTC_WIFI_BW_LEGACY) {
                btc8821a2ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7);
@@ -3354,36 +3346,15 @@ static void btc8821a2ant_action_hid_a2dp(struct btc_coexist *btcoexist)
                                              0x4);
        }
 
-       if (BTC_WIFI_BW_HT40 == wifi_bw) {
-               /* fw mechanism */
-               if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
-                   (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
-                       if (bt_info_ext & BIT0) {
-                               /* a2dp basic rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                                 true, true,
-                                                                 2);
-                       } else {
-                               /* a2dp edr rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                                 true, true,
-                                                                 2);
-                       }
-               } else {
-                       if (bt_info_ext & BIT0) {
-                               /* a2dp basic rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                                 true, true,
-                                                                 2);
-                       } else {
-                               /* a2dp edr rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                                 true, true,
-                                                                 2);
-                       }
-               }
+       if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
+           (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
+               btc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 23);
+       } else {
+               btc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 23);
+       }
 
-               /* sw mechanism */
+       /* sw mechanism */
+       if (wifi_bw == BTC_WIFI_BW_HT40) {
                if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) ||
                    (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
                        btc8821a2ant_sw_mechanism1(btcoexist, true, true,
@@ -3397,36 +3368,6 @@ static void btc8821a2ant_action_hid_a2dp(struct btc_coexist *btcoexist)
                                                   false, 0x18);
                }
        } else {
-               /* fw mechanism */
-               if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) ||
-                   (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
-                       if (bt_info_ext & BIT0) {
-                               /* a2dp basic rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                                 true, true,
-                                                                 2);
-
-                       } else {
-                               /* a2dp edr rate */
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                                 true, true,
-                                                                 2);
-                       }
-               } else {
-                       if (bt_info_ext & BIT0) {
-                               /*a2dp basic rate*/
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                                 true, true,
-                                                                 2);
-                       } else {
-                               /*a2dp edr rate*/
-                               btc8821a2ant_tdma_duration_adjust(btcoexist,
-                                                                 true, true,
-                                                                 2);
-                       }
-               }
-
-               /* sw mechanism */
                if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) ||
                    (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) {
                        btc8821a2ant_sw_mechanism1(btcoexist, false, true,
@@ -3544,14 +3485,14 @@ static void btc8821a2ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
        if (btc8821a2ant_is_common_action(btcoexist)) {
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], Action 2-Ant common\n");
-               coex_dm->reset_tdma_adjust = true;
+               coex_dm->auto_tdma_adjust = true;
        } else {
                if (coex_dm->cur_algorithm != coex_dm->pre_algorithm) {
                        RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                                 "[BTCoex], pre_algorithm = %d, cur_algorithm = %d\n",
                                    coex_dm->pre_algorithm,
                                    coex_dm->cur_algorithm);
-                       coex_dm->reset_tdma_adjust = true;
+                       coex_dm->auto_tdma_adjust = false;
                }
                switch (coex_dm->cur_algorithm) {
                case BT_8821A_2ANT_COEX_ALGO_SCO:
@@ -3614,6 +3555,26 @@ static void btc8821a2ant_run_coexist_mechanism(struct btc_coexist *btcoexist)
        }
 }
 
+static void btc8821a2ant_wifi_off_hw_cfg(struct btc_coexist *btcoexist)
+{
+       u8 h2c_parameter[2] = {0};
+       u32 fw_ver = 0;
+
+       /* set wlan_act to low */
+       btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4);
+
+       /* WiFi goto standby while GNT_BT 0-->1 */
+       btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x780);
+       btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver);
+       if (fw_ver >= 0x180000) {
+               /* Use H2C to set GNT_BT to HIGH */
+               h2c_parameter[0] = 1;
+               btcoexist->btc_fill_h2c(btcoexist, 0x6E, 1, h2c_parameter);
+       } else {
+               btcoexist->btc_write_1byte(btcoexist, 0x765, 0x18);
+       }
+}
+
 /**************************************************************
  * extern function start with ex_btc8821a2ant_
  **************************************************************/
@@ -3637,6 +3598,7 @@ void ex_btc8821a2ant_init_hwconfig(struct btc_coexist *btcoexist)
 
        /* Antenna config */
        btc8821a2ant_set_ant_path(btcoexist, BTC_ANT_WIFI_AT_MAIN, true, false);
+       coex_sta->dis_ver_info_cnt = 0;
 
        /* PTA parameter */
        btc8821a2ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0);
@@ -3648,6 +3610,43 @@ void ex_btc8821a2ant_init_hwconfig(struct btc_coexist *btcoexist)
        btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1);
 }
 
+void ex_btc8821a2ant_pre_load_firmware(struct btc_coexist *btcoexist)
+{
+       struct btc_board_info *board_info = &btcoexist->board_info;
+       u8 u8tmp = 0x4; /* Set BIT2 by default since it's 2ant case */
+
+       /**
+        * S0 or S1 setting and Local register setting(By the setting fw can get
+        * ant number, S0/S1, ... info)
+        *
+        * Local setting bit define
+        *      BIT0: "0" for no antenna inverse; "1" for antenna inverse
+        *      BIT1: "0" for internal switch; "1" for external switch
+        *      BIT2: "0" for one antenna; "1" for two antenna
+        * NOTE: here default all internal switch and 1-antenna ==> BIT1=0 and
+        * BIT2=0
+        */
+       if (btcoexist->chip_interface == BTC_INTF_USB) {
+               /* fixed at S0 for USB interface */
+               u8tmp |= 0x1; /* antenna inverse */
+               btcoexist->btc_write_local_reg_1byte(btcoexist, 0xfe08, u8tmp);
+       } else {
+               /* for PCIE and SDIO interface, we check efuse 0xc3[6] */
+               if (board_info->single_ant_path == 0) {
+               } else if (board_info->single_ant_path == 1) {
+                       /* set to S0 */
+                       u8tmp |= 0x1; /* antenna inverse */
+               }
+
+               if (btcoexist->chip_interface == BTC_INTF_PCI)
+                       btcoexist->btc_write_local_reg_1byte(btcoexist, 0x384,
+                                                            u8tmp);
+               else if (btcoexist->chip_interface == BTC_INTF_SDIO)
+                       btcoexist->btc_write_local_reg_1byte(btcoexist, 0x60,
+                                                            u8tmp);
+       }
+}
+
 void ex_btc8821a2ant_init_coex_dm(struct btc_coexist *btcoexist)
 {
        struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -3748,14 +3747,6 @@ void ex_btc8821a2ant_display_coex_info(struct btc_coexist *btcoexist)
                    ((BTC_WIFI_TRAFFIC_TX == wifi_traffic_dir) ?
                     "uplink" : "downlink")));
 
-       RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-                "\r\n %-35s = [%s/ %d/ %d] ", "BT [status/ rssi/ retryCnt]",
-                  ((coex_sta->c2h_bt_inquiry_page) ? ("inquiry/page scan") :
-                   ((BT_8821A_2ANT_BT_STATUS_IDLE == coex_dm->bt_status)
-                    ? "idle" : ((BT_8821A_2ANT_BT_STATUS_CON_IDLE ==
-                    coex_dm->bt_status) ? "connected-idle" : "busy"))),
-                   coex_sta->bt_rssi, coex_sta->bt_retry_cnt);
-
        if (stack_info->profile_notified) {
                RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
                         "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP",
@@ -3790,11 +3781,6 @@ void ex_btc8821a2ant_display_coex_info(struct btc_coexist *btcoexist)
        /* Sw mechanism*/
        RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s",
                 "============[Sw mechanism]============");
-       RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-                "\r\n %-35s = %d/ %d/ %d/ %d ",
-                "SM1[ShRf/ LpRA/ LimDig/ btLna]",
-                coex_dm->cur_rf_rx_lpf_shrink, coex_dm->cur_low_penalty_ra,
-                coex_dm->limited_dig, coex_dm->cur_bt_lna_constrain);
        RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
                 "\r\n %-35s = %d/ %d/ %d(0x%x) ",
                 "SM2[AgcT/ AdcB/ SwDacSwing(lvl)]",
@@ -3900,11 +3886,16 @@ void ex_btc8821a2ant_ips_notify(struct btc_coexist *btcoexist, u8 type)
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], IPS ENTER notify\n");
                coex_sta->under_ips = true;
+               btc8821a2ant_wifi_off_hw_cfg(btcoexist);
+               btc8821a2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true);
                btc8821a2ant_coex_all_off(btcoexist);
        } else if (BTC_IPS_LEAVE == type) {
                RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                         "[BTCoex], IPS LEAVE notify\n");
                coex_sta->under_ips = false;
+               ex_btc8821a2ant_init_hwconfig(btcoexist);
+               btc8821a2ant_init_coex_dm(btcoexist);
+               btc8821a2ant_query_bt_info(btcoexist);
        }
 }
 
@@ -4016,9 +4007,12 @@ void ex_btc8821a2ant_bt_info_notify(struct btc_coexist *btcoexist,
        u8 bt_info = 0;
        u8 i, rsp_source = 0;
        bool bt_busy = false, limited_dig = false;
-       bool wifi_connected = false, bt_hs_on = false;
+       bool wifi_connected = false, wifi_under_5g = false;
 
        coex_sta->c2h_bt_info_req_sent = false;
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g);
+       btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED,
+                          &wifi_connected);
 
        rsp_source = tmp_buf[0] & 0xf;
        if (rsp_source >= BT_INFO_SRC_8821A_2ANT_MAX)
@@ -4041,16 +4035,35 @@ void ex_btc8821a2ant_bt_info_notify(struct btc_coexist *btcoexist,
                }
        }
 
+       if (btcoexist->manual_control) {
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], BtInfoNotify(), return for Manual CTRL<===\n");
+               return;
+       }
+
        if (BT_INFO_SRC_8821A_2ANT_WIFI_FW != rsp_source) {
                /* [3:0] */
                coex_sta->bt_retry_cnt =
                        coex_sta->bt_info_c2h[rsp_source][2]&0xf;
 
                coex_sta->bt_rssi =
-                       coex_sta->bt_info_c2h[rsp_source][3]*2+10;
+                       coex_sta->bt_info_c2h[rsp_source][3] * 2 + 10;
 
-               coex_sta->bt_info_ext =
-                       coex_sta->bt_info_c2h[rsp_source][4];
+               coex_sta->bt_info_ext = coex_sta->bt_info_c2h[rsp_source][4];
+
+               coex_sta->bt_tx_rx_mask =
+                       (coex_sta->bt_info_c2h[rsp_source][2] & 0x40);
+               btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TX_RX_MASK,
+                                  &coex_sta->bt_tx_rx_mask);
+               if (coex_sta->bt_tx_rx_mask) {
+                       /* BT into is responded by BT FW and BT RF REG 0x3C !=
+                        * 0x01 => Need to switch BT TRx Mask
+                        */
+                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                "[BTCoex], Switch BT TRx Mask since BT RF REG 0x3C != 0x01\n");
+                       btcoexist->btc_set_bt_reg(btcoexist, BTC_BT_REG_RF,
+                                                 0x3c, 0x01);
+               }
 
                /* Here we need to resend some wifi info to BT
                 * because bt is reset and loss of the info
@@ -4068,70 +4081,121 @@ void ex_btc8821a2ant_bt_info_notify(struct btc_coexist *btcoexist,
 
                }
 
-               if ((coex_sta->bt_info_ext & BIT3)) {
-                       btc8821a2ant_ignore_wlan_act(btcoexist,
-                                                    FORCE_EXEC, false);
-               } else {
-                       /* BT already NOT ignore Wlan active, do nothing here.*/
+               if (!btcoexist->manual_control && !wifi_under_5g) {
+                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                "[BTCoex], BT ext info = 0x%x!!\n",
+                                   coex_sta->bt_info_ext);
+                       if ((coex_sta->bt_info_ext & BIT(3))) {
+                               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                        "[BTCoex], BT ext info bit3=1, wifi_connected=%d\n",
+                                        wifi_connected);
+                               if (wifi_connected) {
+                                       RT_TRACE(rtlpriv, COMP_BT_COEXIST,
+                                                DBG_LOUD,
+                                                "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n");
+                                       btc8821a2ant_ignore_wlan_act(btcoexist,
+                                                                    FORCE_EXEC,
+                                                                    false);
+                               }
+                       } else {
+                               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                        "[BTCoex], BT ext info bit3=0, wifi_connected=%d\n",
+                                        wifi_connected);
+                               /* BT already NOT ignore Wlan active, do nothing
+                                * here.
+                                */
+                               if (!wifi_connected) {
+                                       RT_TRACE(rtlpriv, COMP_BT_COEXIST,
+                                                DBG_LOUD,
+                                               "[BTCoex], BT ext info bit3 check, set BT to ignore Wlan active!!\n");
+                                       btc8821a2ant_ignore_wlan_act(
+                                               btcoexist, FORCE_EXEC, true);
+                               }
+                       }
                }
        }
 
-       btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on);
        /* check BIT2 first ==> check if bt is under inquiry or page scan*/
        if (bt_info & BT_INFO_8821A_2ANT_B_INQ_PAGE) {
                coex_sta->c2h_bt_inquiry_page = true;
-               coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_NON_IDLE;
        } else {
                coex_sta->c2h_bt_inquiry_page = false;
-               if (bt_info == 0x1) {
-                       /* connection exists but not busy*/
-                       coex_sta->bt_link_exist = true;
-                       coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_CON_IDLE;
-               } else if (bt_info & BT_INFO_8821A_2ANT_B_CONNECTION) {
-                       /* connection exists and some link is busy*/
-                       coex_sta->bt_link_exist = true;
-                       if (bt_info & BT_INFO_8821A_2ANT_B_FTP)
-                               coex_sta->pan_exist = true;
-                       else
-                               coex_sta->pan_exist = false;
-                       if (bt_info & BT_INFO_8821A_2ANT_B_A2DP)
-                               coex_sta->a2dp_exist = true;
-                       else
-                               coex_sta->a2dp_exist = false;
-                       if (bt_info & BT_INFO_8821A_2ANT_B_HID)
-                               coex_sta->hid_exist = true;
-                       else
-                               coex_sta->hid_exist = false;
-                       if (bt_info & BT_INFO_8821A_2ANT_B_SCO_ESCO)
-                               coex_sta->sco_exist = true;
-                       else
-                               coex_sta->sco_exist = false;
-                       coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_NON_IDLE;
-               } else {
-                       coex_sta->bt_link_exist = false;
+       }
+       /* set link exist status */
+       if (!(bt_info & BT_INFO_8821A_2ANT_B_CONNECTION)) {
+               coex_sta->bt_link_exist = false;
+               coex_sta->pan_exist = false;
+               coex_sta->a2dp_exist = false;
+               coex_sta->hid_exist = false;
+               coex_sta->sco_exist = false;
+       } else { /* connection exists */
+               coex_sta->bt_link_exist = true;
+               if (bt_info & BT_INFO_8821A_2ANT_B_FTP)
+                       coex_sta->pan_exist = true;
+               else
                        coex_sta->pan_exist = false;
+               if (bt_info & BT_INFO_8821A_2ANT_B_A2DP)
+                       coex_sta->a2dp_exist = true;
+               else
                        coex_sta->a2dp_exist = false;
+               if (bt_info & BT_INFO_8821A_2ANT_B_HID)
+                       coex_sta->hid_exist = true;
+               else
                        coex_sta->hid_exist = false;
+               if (bt_info & BT_INFO_8821A_2ANT_B_SCO_ESCO)
+                       coex_sta->sco_exist = true;
+               else
                        coex_sta->sco_exist = false;
-                       coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_IDLE;
+
+               if ((!coex_sta->hid_exist) &&
+                   (!coex_sta->c2h_bt_inquiry_page) &&
+                   (!coex_sta->sco_exist)) {
+                       if (coex_sta->high_priority_tx +
+                                   coex_sta->high_priority_rx >= 160)
+                               coex_sta->hid_exist = true;
                }
+       }
 
-               btc8821a2ant_update_bt_link_info(btcoexist);
+       btc8821a2ant_update_bt_link_info(btcoexist);
+
+       if (!(bt_info & BT_INFO_8821A_2ANT_B_CONNECTION)) {
+               coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_IDLE;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], BtInfoNotify(), BT Non-Connected idle!!!\n");
+       } else if (bt_info == BT_INFO_8821A_2ANT_B_CONNECTION) {
+               /* connection exists but no busy */
+               coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_CON_IDLE;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n");
+       } else if ((bt_info & BT_INFO_8821A_2ANT_B_SCO_ESCO) ||
+                  (bt_info & BT_INFO_8821A_2ANT_B_SCO_BUSY)) {
+               coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_SCO_BUSY;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n");
+       } else if (bt_info & BT_INFO_8821A_2ANT_B_ACL_BUSY) {
+               coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_ACL_BUSY;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n");
+       } else {
+               coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_MAX;
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], BtInfoNotify(), BT Non-Defined state!!!\n");
        }
 
-       if (BT_8821A_2ANT_BT_STATUS_NON_IDLE == coex_dm->bt_status)
+       if ((coex_dm->bt_status == BT_8821A_2ANT_BT_STATUS_ACL_BUSY) ||
+           (coex_dm->bt_status == BT_8821A_2ANT_BT_STATUS_SCO_BUSY) ||
+           (coex_dm->bt_status == BT_8821A_2ANT_BT_STATUS_ACL_SCO_BUSY)) {
                bt_busy = true;
-       else
+               limited_dig = true;
+       } else {
                bt_busy = false;
+               limited_dig = false;
+       }
+
        btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy);
 
-       if (BT_8821A_2ANT_BT_STATUS_IDLE != coex_dm->bt_status)
-               limited_dig = true;
-       else
-               limited_dig = false;
        coex_dm->limited_dig = limited_dig;
-       btcoexist->btc_set(btcoexist,
-               BTC_SET_BL_BT_LIMITED_DIG, &limited_dig);
+       btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_LIMITED_DIG, &limited_dig);
 
        btc8821a2ant_run_coexist_mechanism(btcoexist);
 }
@@ -4143,46 +4207,57 @@ void ex_btc8821a2ant_halt_notify(struct btc_coexist *btcoexist)
        RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                 "[BTCoex], Halt notify\n");
 
+       btc8821a2ant_wifi_off_hw_cfg(btcoexist);
        btc8821a2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true);
        ex_btc8821a2ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT);
 }
 
+void ex_btc8821a2ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
+{
+       struct rtl_priv *rtlpriv = btcoexist->adapter;
+
+       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, "[BTCoex], Pnp notify\n");
+
+       if (pnp_state == BTC_WIFI_PNP_SLEEP) {
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], Pnp notify to SLEEP\n");
+       } else if (pnp_state == BTC_WIFI_PNP_WAKE_UP) {
+               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                        "[BTCoex], Pnp notify to WAKE UP\n");
+               ex_btc8821a2ant_init_hwconfig(btcoexist);
+               btc8821a2ant_init_coex_dm(btcoexist);
+               btc8821a2ant_query_bt_info(btcoexist);
+       }
+}
+
 void ex_btc8821a2ant_periodical(struct btc_coexist *btcoexist)
 {
        struct rtl_priv *rtlpriv = btcoexist->adapter;
-       static u8 dis_ver_info_cnt;
-       struct btc_board_info *board_info = &btcoexist->board_info;
-       struct btc_stack_info *stack_info = &btcoexist->stack_info;
-       u32 fw_ver = 0, bt_patch_ver = 0;
 
        RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
                 "[BTCoex], ==========================Periodical===========================\n");
 
-       if (dis_ver_info_cnt <= 5) {
-               dis_ver_info_cnt += 1;
-               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                        "[BTCoex], ****************************************************************\n");
-               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                        "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n",
-                        board_info->pg_ant_num,
-                        board_info->btdm_ant_num,
-                        board_info->btdm_ant_pos);
-               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                        "[BTCoex], BT stack/ hci ext ver = %s / %d\n",
-                        stack_info->profile_notified ? "Yes" : "No",
-                        stack_info->hci_version);
-               btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER,
-                                  &bt_patch_ver);
-               btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver);
-               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                        "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n",
-                        glcoex_ver_date_8821a_2ant, glcoex_ver_8821a_2ant,
-                        fw_ver, bt_patch_ver, bt_patch_ver);
-               RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
-                        "[BTCoex], ****************************************************************\n");
+       if (coex_sta->dis_ver_info_cnt <= 5) {
+               coex_sta->dis_ver_info_cnt += 1;
+               if (coex_sta->dis_ver_info_cnt == 3) {
+                       /* Antenna config to set 0x765 = 0x0 (GNT_BT control by
+                        * PTA) after initial
+                        */
+                       RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+                                "[BTCoex], Set GNT_BT control by PTA\n");
+                       btc8821a2ant_set_ant_path(btcoexist,
+                                       BTC_ANT_WIFI_AT_MAIN, false, false);
+               }
        }
 
-       btc8821a2ant_query_bt_info(btcoexist);
-       btc8821a2ant_monitor_bt_ctr(btcoexist);
-       btc8821a2ant_monitor_wifi_ctr(btcoexist);
+       if (btcoexist->auto_report_2ant) {
+               btc8821a2ant_query_bt_info(btcoexist);
+       } else {
+               btc8821a2ant_monitor_bt_ctr(btcoexist);
+               btc8821a2ant_monitor_wifi_ctr(btcoexist);
+
+               if (btc8821a2ant_is_wifi_status_changed(btcoexist) ||
+                   coex_dm->auto_tdma_adjust)
+                       btc8821a2ant_run_coexist_mechanism(btcoexist);
+       }
 }
index 535ca10e910b34e03cd66276f1102b87c668f96f..a1603e2d44e320233998292e44026ee8d1777e41 100644 (file)
@@ -54,6 +54,9 @@ enum _BT_8821A_2ANT_BT_STATUS {
        BT_8821A_2ANT_BT_STATUS_IDLE            = 0x0,
        BT_8821A_2ANT_BT_STATUS_CON_IDLE        = 0x1,
        BT_8821A_2ANT_BT_STATUS_NON_IDLE        = 0x2,
+       BT_8821A_2ANT_BT_STATUS_ACL_BUSY        = 0x3,
+       BT_8821A_2ANT_BT_STATUS_SCO_BUSY        = 0x4,
+       BT_8821A_2ANT_BT_STATUS_ACL_SCO_BUSY    = 0x5,
        BT_8821A_2ANT_BT_STATUS_MAX
 };
 
@@ -76,10 +79,6 @@ struct coex_dm_8821a_2ant {
        /* fw mechanism */
        bool            pre_dec_bt_pwr_lvl;
        bool            cur_dec_bt_pwr_lvl;
-       bool            pre_bt_lna_constrain;
-       bool            cur_bt_lna_constrain;
-       u8              pre_bt_psd_mode;
-       u8              cur_bt_psd_mode;
        u8              pre_fw_dac_swing_lvl;
        u8              cur_fw_dac_swing_lvl;
        bool            cur_ignore_wlan_act;
@@ -143,6 +142,7 @@ struct coex_sta_8821a_2ant {
        u32     low_priority_tx;
        u32     low_priority_rx;
        u8      bt_rssi;
+       bool    bt_tx_rx_mask;
        u8      pre_bt_rssi_state;
        u8      pre_wifi_rssi_state[4];
        bool    c2h_bt_info_req_sent;
@@ -164,6 +164,8 @@ struct coex_sta_8821a_2ant {
 
        u8      coex_table_type;
        bool    force_lps_on;
+
+       u8      dis_ver_info_cnt;
 };
 
 /*===========================================
index c8271135aaaaed26af1ba359374fc1f133542b38..c5c360e011a970259a43872c5470085a921dcc45 100644 (file)
@@ -30,6 +30,9 @@
 #define                NORMAL_EXEC                             false
 #define                FORCE_EXEC                              true
 
+#define                BTC_RF_OFF                              0x0
+#define                BTC_RF_ON                               0x1
+
 #define                BTC_RF_A                                RF90_PATH_A
 #define                BTC_RF_B                                RF90_PATH_B
 #define                BTC_RF_C                                RF90_PATH_C
@@ -196,6 +199,24 @@ enum btc_wifi_pnp {
        BTC_WIFI_PNP_MAX
 };
 
+enum btc_iot_peer {
+       BTC_IOT_PEER_UNKNOWN = 0,
+       BTC_IOT_PEER_REALTEK = 1,
+       BTC_IOT_PEER_REALTEK_92SE = 2,
+       BTC_IOT_PEER_BROADCOM = 3,
+       BTC_IOT_PEER_RALINK = 4,
+       BTC_IOT_PEER_ATHEROS = 5,
+       BTC_IOT_PEER_CISCO = 6,
+       BTC_IOT_PEER_MERU = 7,
+       BTC_IOT_PEER_MARVELL = 8,
+       BTC_IOT_PEER_REALTEK_SOFTAP = 9,
+       BTC_IOT_PEER_SELF_SOFTAP = 10, /* Self is SoftAP */
+       BTC_IOT_PEER_AIRGO = 11,
+       BTC_IOT_PEER_REALTEK_JAGUAR_BCUTAP = 12,
+       BTC_IOT_PEER_REALTEK_JAGUAR_CCUTAP = 13,
+       BTC_IOT_PEER_MAX,
+};
+
 enum btc_get_type {
        /* type bool */
        BTC_GET_BL_HS_OPERATION,
@@ -235,6 +256,7 @@ enum btc_get_type {
        BTC_GET_U1_WIFI_HS_CHNL,
        BTC_GET_U1_MAC_PHY_MODE,
        BTC_GET_U1_AP_NUM,
+       BTC_GET_U1_IOT_PEER,
 
        /* for 1Ant */
        BTC_GET_U1_LPS_MODE,
@@ -468,6 +490,7 @@ struct btc_statistics {
 
 struct btc_bt_link_info {
        bool bt_link_exist;
+       bool bt_hi_pri_link_exist;
        bool sco_exist;
        bool sco_only;
        bool a2dp_exist;
@@ -496,6 +519,11 @@ struct btc_coexist {
        enum btc_chip_interface chip_interface;
        struct btc_bt_link_info bt_link_info;
 
+       /* boolean variables to replace BT_AUTO_REPORT_ONLY_XXXXY_ZANT
+        * configuration parameters
+        */
+       bool auto_report_1ant;
+       bool auto_report_2ant;
        bool initilized;
        bool stop_coex_dm;
        bool manual_control;
index 6f5098a18655536e6c210a5cd70e0cef55c4b3a5..11d97fa0e921780d707dbf7333fd819997faf59b 100644 (file)
@@ -2506,7 +2506,7 @@ void rtl92ee_set_key(struct ieee80211_hw *hw, u32 key_index,
                                 "add one entry\n");
                        if (is_pairwise) {
                                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-                                        "set Pairwiase key\n");
+                                        "set Pairwise key\n");
 
                                rtl_cam_add_one_entry(hw, macaddr, key_index,
                                               entry_id, enc_algo,
index 859c045bd37c48b4c77b755126d403ace7d56b81..5ac7b815648a818778be12b2e5c927681c883ee9 100644 (file)
@@ -2264,7 +2264,7 @@ void rtl8723e_set_key(struct ieee80211_hw *hw, u32 key_index,
                                 "add one entry\n");
                        if (is_pairwise) {
                                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-                                        "set Pairwiase key\n");
+                                        "set Pairwise key\n");
 
                                rtl_cam_add_one_entry(hw, macaddr, key_index,
                                                      entry_id, enc_algo,
@@ -2313,7 +2313,7 @@ static void rtl8723e_bt_var_init(struct ieee80211_hw *hw)
                rtlpriv->btcoexist.eeprom_bt_radio_shared;
 
        RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
-                "BT Coexistance = 0x%x\n",
+                "BT Coexistence = 0x%x\n",
                 rtlpriv->btcoexist.bt_coexistence);
 
        if (rtlpriv->btcoexist.bt_coexistence) {
index 1acbfb86472cdab2e19a0e86a423eba7a3af41d9..a79f936bb3947d4bb3f6967dbf89fbda040cb006 100644 (file)
@@ -2637,7 +2637,7 @@ void rtl8723be_set_key(struct ieee80211_hw *hw, u32 key_index,
                                 "add one entry\n");
                        if (is_pairwise) {
                                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-                                        "set Pairwiase key\n");
+                                        "set Pairwise key\n");
 
                                rtl_cam_add_one_entry(hw, macaddr, key_index,
                                               entry_id, enc_algo,
index 25828b69275675845aa4b844897c2a9de3e72216..a475c813674ad783ab0c4a53b371d30c071dcd02 100644 (file)
@@ -2,7 +2,7 @@ rsi_91x-y                       += rsi_91x_main.o
 rsi_91x-y                      += rsi_91x_core.o
 rsi_91x-y                      += rsi_91x_mac80211.o
 rsi_91x-y                      += rsi_91x_mgmt.o
-rsi_91x-y                      += rsi_91x_pkt.o
+rsi_91x-y                      += rsi_91x_hal.o
 rsi_91x-$(CONFIG_RSI_DEBUGFS)  += rsi_91x_debugfs.o
 
 rsi_usb-y                      += rsi_91x_usb.o rsi_91x_usb_ops.o
index f3d3995d8f6b4c8ada23a5f25c6ad8035b108970..68f04a76769e246270ac7d88657d9f4ad97da45b 100644 (file)
@@ -306,7 +306,7 @@ void rsi_core_qos_processor(struct rsi_common *common)
                tstamp_2 = jiffies;
                mutex_unlock(&common->tx_rxlock);
 
-               if (tstamp_2 > tstamp_1 + (300 * HZ / 1000))
+               if (time_after(tstamp_2, tstamp_1 + (300 * HZ) / 1000))
                        schedule();
        }
 }
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
new file mode 100644 (file)
index 0000000..3d24e8e
--- /dev/null
@@ -0,0 +1,740 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/firmware.h>
+#include "rsi_mgmt.h"
+#include "rsi_hal.h"
+#include "rsi_sdio.h"
+
+/* FLASH Firmware */
+static struct ta_metadata metadata_flash_content[] = {
+       {"flash_content", 0x00010000},
+       {"rsi/rs9113_wlan_qspi.rps", 0x00010000},
+};
+
+/**
+ * rsi_send_data_pkt() - This function sends the recieved data packet from
+ *                      driver to device.
+ * @common: Pointer to the driver private structure.
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
+{
+       struct rsi_hw *adapter = common->priv;
+       struct ieee80211_hdr *tmp_hdr;
+       struct ieee80211_tx_info *info;
+       struct skb_info *tx_params;
+       struct ieee80211_bss_conf *bss;
+       int status;
+       u8 ieee80211_size = MIN_802_11_HDR_LEN;
+       u8 extnd_size;
+       __le16 *frame_desc;
+       u16 seq_num;
+
+       info = IEEE80211_SKB_CB(skb);
+       bss = &info->control.vif->bss_conf;
+       tx_params = (struct skb_info *)info->driver_data;
+
+       if (!bss->assoc) {
+               status = -EINVAL;
+               goto err;
+       }
+
+       tmp_hdr = (struct ieee80211_hdr *)&skb->data[0];
+       seq_num = (le16_to_cpu(tmp_hdr->seq_ctrl) >> 4);
+
+       extnd_size = ((uintptr_t)skb->data & 0x3);
+
+       if ((FRAME_DESC_SZ + extnd_size) > skb_headroom(skb)) {
+               rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__);
+               status = -ENOSPC;
+               goto err;
+       }
+
+       skb_push(skb, (FRAME_DESC_SZ + extnd_size));
+       frame_desc = (__le16 *)&skb->data[0];
+       memset((u8 *)frame_desc, 0, FRAME_DESC_SZ);
+
+       if (ieee80211_is_data_qos(tmp_hdr->frame_control)) {
+               ieee80211_size += 2;
+               frame_desc[6] |= cpu_to_le16(BIT(12));
+       }
+
+       if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) &&
+           (common->secinfo.security_enable)) {
+               if (rsi_is_cipher_wep(common))
+                       ieee80211_size += 4;
+               else
+                       ieee80211_size += 8;
+               frame_desc[6] |= cpu_to_le16(BIT(15));
+       }
+
+       frame_desc[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) |
+                                   (RSI_WIFI_DATA_Q << 12));
+       frame_desc[2] = cpu_to_le16((extnd_size) | (ieee80211_size) << 8);
+
+       if (common->min_rate != 0xffff) {
+               /* Send fixed rate */
+               frame_desc[3] = cpu_to_le16(RATE_INFO_ENABLE);
+               frame_desc[4] = cpu_to_le16(common->min_rate);
+
+               if (conf_is_ht40(&common->priv->hw->conf))
+                       frame_desc[5] = cpu_to_le16(FULL40M_ENABLE);
+
+               if (common->vif_info[0].sgi) {
+                       if (common->min_rate & 0x100) /* Only MCS rates */
+                               frame_desc[4] |=
+                                       cpu_to_le16(ENABLE_SHORTGI_RATE);
+               }
+
+       }
+
+       frame_desc[6] |= cpu_to_le16(seq_num & 0xfff);
+       frame_desc[7] = cpu_to_le16(((tx_params->tid & 0xf) << 4) |
+                                   (skb->priority & 0xf) |
+                                   (tx_params->sta_id << 8));
+
+       status = adapter->host_intf_ops->write_pkt(common->priv, skb->data,
+                                                  skb->len);
+       if (status)
+               rsi_dbg(ERR_ZONE, "%s: Failed to write pkt\n",
+                       __func__);
+
+err:
+       ++common->tx_stats.total_tx_pkt_freed[skb->priority];
+       rsi_indicate_tx_status(common->priv, skb, status);
+       return status;
+}
+
+/**
+ * rsi_send_mgmt_pkt() - This functions sends the received management packet
+ *                      from driver to device.
+ * @common: Pointer to the driver private structure.
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int rsi_send_mgmt_pkt(struct rsi_common *common,
+                     struct sk_buff *skb)
+{
+       struct rsi_hw *adapter = common->priv;
+       struct ieee80211_hdr *wh;
+       struct ieee80211_tx_info *info;
+       struct ieee80211_bss_conf *bss;
+       struct ieee80211_hw *hw = adapter->hw;
+       struct ieee80211_conf *conf = &hw->conf;
+       struct skb_info *tx_params;
+       int status = -E2BIG;
+       __le16 *msg;
+       u8 extnd_size;
+       u8 vap_id = 0;
+
+       info = IEEE80211_SKB_CB(skb);
+       tx_params = (struct skb_info *)info->driver_data;
+       extnd_size = ((uintptr_t)skb->data & 0x3);
+
+       if (tx_params->flags & INTERNAL_MGMT_PKT) {
+               if ((extnd_size) > skb_headroom(skb)) {
+                       rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__);
+                       dev_kfree_skb(skb);
+                       return -ENOSPC;
+               }
+               skb_push(skb, extnd_size);
+               skb->data[extnd_size + 4] = extnd_size;
+               status = adapter->host_intf_ops->write_pkt(common->priv,
+                                                          (u8 *)skb->data,
+                                                          skb->len);
+               if (status) {
+                       rsi_dbg(ERR_ZONE,
+                               "%s: Failed to write the packet\n", __func__);
+               }
+               dev_kfree_skb(skb);
+               return status;
+       }
+
+       bss = &info->control.vif->bss_conf;
+       wh = (struct ieee80211_hdr *)&skb->data[0];
+
+       if (FRAME_DESC_SZ > skb_headroom(skb))
+               goto err;
+
+       skb_push(skb, FRAME_DESC_SZ);
+       memset(skb->data, 0, FRAME_DESC_SZ);
+       msg = (__le16 *)skb->data;
+
+       if (skb->len > MAX_MGMT_PKT_SIZE) {
+               rsi_dbg(INFO_ZONE, "%s: Dropping mgmt pkt > 512\n", __func__);
+               goto err;
+       }
+
+       msg[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) |
+                           (RSI_WIFI_MGMT_Q << 12));
+       msg[1] = cpu_to_le16(TX_DOT11_MGMT);
+       msg[2] = cpu_to_le16(MIN_802_11_HDR_LEN << 8);
+       msg[3] = cpu_to_le16(RATE_INFO_ENABLE);
+       msg[6] = cpu_to_le16(le16_to_cpu(wh->seq_ctrl) >> 4);
+
+       if (wh->addr1[0] & BIT(0))
+               msg[3] |= cpu_to_le16(RSI_BROADCAST_PKT);
+
+       if (common->band == NL80211_BAND_2GHZ)
+               msg[4] = cpu_to_le16(RSI_11B_MODE);
+       else
+               msg[4] = cpu_to_le16((RSI_RATE_6 & 0x0f) | RSI_11G_MODE);
+
+       if (conf_is_ht40(conf)) {
+               msg[4] = cpu_to_le16(0xB | RSI_11G_MODE);
+               msg[5] = cpu_to_le16(0x6);
+       }
+
+       /* Indicate to firmware to give cfm */
+       if ((skb->data[16] == IEEE80211_STYPE_PROBE_REQ) && (!bss->assoc)) {
+               msg[1] |= cpu_to_le16(BIT(10));
+               msg[7] = cpu_to_le16(PROBEREQ_CONFIRM);
+               common->mgmt_q_block = true;
+       }
+
+       msg[7] |= cpu_to_le16(vap_id << 8);
+
+       status = adapter->host_intf_ops->write_pkt(common->priv, (u8 *)msg,
+                                                  skb->len);
+       if (status)
+               rsi_dbg(ERR_ZONE, "%s: Failed to write the packet\n", __func__);
+
+err:
+       rsi_indicate_tx_status(common->priv, skb, status);
+       return status;
+}
+
+static void bl_cmd_timeout(unsigned long priv)
+{
+       struct rsi_hw *adapter = (struct rsi_hw *)priv;
+
+       adapter->blcmd_timer_expired = true;
+       del_timer(&adapter->bl_cmd_timer);
+}
+
+static int bl_start_cmd_timer(struct rsi_hw *adapter, u32 timeout)
+{
+       init_timer(&adapter->bl_cmd_timer);
+       adapter->bl_cmd_timer.data = (unsigned long)adapter;
+       adapter->bl_cmd_timer.function = (void *)&bl_cmd_timeout;
+       adapter->bl_cmd_timer.expires = (msecs_to_jiffies(timeout) + jiffies);
+
+       adapter->blcmd_timer_expired = false;
+       add_timer(&adapter->bl_cmd_timer);
+
+       return 0;
+}
+
+static int bl_stop_cmd_timer(struct rsi_hw *adapter)
+{
+       adapter->blcmd_timer_expired = false;
+       if (timer_pending(&adapter->bl_cmd_timer))
+               del_timer(&adapter->bl_cmd_timer);
+
+       return 0;
+}
+
+static int bl_write_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp,
+                       u16 *cmd_resp)
+{
+       struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+       u32 regin_val = 0, regout_val = 0;
+       u32 regin_input = 0;
+       u8 output = 0;
+       int status;
+
+       regin_input = (REGIN_INPUT | adapter->priv->coex_mode);
+
+       while (!adapter->blcmd_timer_expired) {
+               regin_val = 0;
+               status = hif_ops->master_reg_read(adapter, SWBL_REGIN,
+                                                 &regin_val, 2);
+               if (status < 0) {
+                       rsi_dbg(ERR_ZONE,
+                               "%s: Command %0x REGIN reading failed..\n",
+                               __func__, cmd);
+                       return status;
+               }
+               mdelay(1);
+               if ((regin_val >> 12) != REGIN_VALID)
+                       break;
+       }
+       if (adapter->blcmd_timer_expired) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Command %0x REGIN reading timed out..\n",
+                       __func__, cmd);
+               return -ETIMEDOUT;
+       }
+
+       rsi_dbg(INFO_ZONE,
+               "Issuing write to Regin val:%0x sending cmd:%0x\n",
+               regin_val, (cmd | regin_input << 8));
+       status = hif_ops->master_reg_write(adapter, SWBL_REGIN,
+                                          (cmd | regin_input << 8), 2);
+       if (status < 0)
+               return status;
+       mdelay(1);
+
+       if (cmd == LOAD_HOSTED_FW || cmd == JUMP_TO_ZERO_PC) {
+               /* JUMP_TO_ZERO_PC doesn't expect
+                * any response. So return from here
+                */
+               return 0;
+       }
+
+       while (!adapter->blcmd_timer_expired) {
+               regout_val = 0;
+               status = hif_ops->master_reg_read(adapter, SWBL_REGOUT,
+                                            &regout_val, 2);
+               if (status < 0) {
+                       rsi_dbg(ERR_ZONE,
+                               "%s: Command %0x REGOUT reading failed..\n",
+                               __func__, cmd);
+                       return status;
+               }
+               mdelay(1);
+               if ((regout_val >> 8) == REGOUT_VALID)
+                       break;
+       }
+       if (adapter->blcmd_timer_expired) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Command %0x REGOUT reading timed out..\n",
+                       __func__, cmd);
+               return status;
+       }
+
+       *cmd_resp = ((u16 *)&regout_val)[0] & 0xffff;
+
+       output = ((u8 *)&regout_val)[0] & 0xff;
+
+       status = hif_ops->master_reg_write(adapter, SWBL_REGOUT,
+                                          (cmd | REGOUT_INVALID << 8), 2);
+       if (status < 0) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Command %0x REGOUT writing failed..\n",
+                       __func__, cmd);
+               return status;
+       }
+       mdelay(1);
+
+       if (output != exp_resp) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Recvd resp %x for cmd %0x\n",
+                       __func__, output, cmd);
+               return -EINVAL;
+       }
+       rsi_dbg(INFO_ZONE,
+               "%s: Recvd Expected resp %x for cmd %0x\n",
+               __func__, output, cmd);
+
+       return 0;
+}
+
+static int bl_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, char *str)
+{
+       u16 regout_val = 0;
+       u32 timeout;
+       int status;
+
+       if ((cmd == EOF_REACHED) || (cmd == PING_VALID) || (cmd == PONG_VALID))
+               timeout = BL_BURN_TIMEOUT;
+       else
+               timeout = BL_CMD_TIMEOUT;
+
+       bl_start_cmd_timer(adapter, timeout);
+       status = bl_write_cmd(adapter, cmd, exp_resp, &regout_val);
+       if (status < 0) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Command %s (%0x) writing failed..\n",
+                       __func__, str, cmd);
+               return status;
+       }
+       bl_stop_cmd_timer(adapter);
+       return 0;
+}
+
+#define CHECK_SUM_OFFSET 20
+#define LEN_OFFSET 8
+#define ADDR_OFFSET 16
+static int bl_write_header(struct rsi_hw *adapter, u8 *flash_content,
+                          u32 content_size)
+{
+       struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+       struct bl_header bl_hdr;
+       u32 write_addr, write_len;
+       int status;
+
+       bl_hdr.flags = 0;
+       bl_hdr.image_no = cpu_to_le32(adapter->priv->coex_mode);
+       bl_hdr.check_sum = cpu_to_le32(
+                               *(u32 *)&flash_content[CHECK_SUM_OFFSET]);
+       bl_hdr.flash_start_address = cpu_to_le32(
+                                       *(u32 *)&flash_content[ADDR_OFFSET]);
+       bl_hdr.flash_len = cpu_to_le32(*(u32 *)&flash_content[LEN_OFFSET]);
+       write_len = sizeof(struct bl_header);
+
+       if (adapter->rsi_host_intf == RSI_HOST_INTF_USB) {
+               write_addr = PING_BUFFER_ADDRESS;
+               status = hif_ops->write_reg_multiple(adapter, write_addr,
+                                                (u8 *)&bl_hdr, write_len);
+               if (status < 0) {
+                       rsi_dbg(ERR_ZONE,
+                               "%s: Failed to load Version/CRC structure\n",
+                               __func__);
+                       return status;
+               }
+       } else {
+               write_addr = PING_BUFFER_ADDRESS >> 16;
+               status = hif_ops->master_access_msword(adapter, write_addr);
+               if (status < 0) {
+                       rsi_dbg(ERR_ZONE,
+                               "%s: Unable to set ms word to common reg\n",
+                               __func__);
+                       return status;
+               }
+               write_addr = RSI_SD_REQUEST_MASTER |
+                            (PING_BUFFER_ADDRESS & 0xFFFF);
+               status = hif_ops->write_reg_multiple(adapter, write_addr,
+                                                (u8 *)&bl_hdr, write_len);
+               if (status < 0) {
+                       rsi_dbg(ERR_ZONE,
+                               "%s: Failed to load Version/CRC structure\n",
+                               __func__);
+                       return status;
+               }
+       }
+       return 0;
+}
+
+static u32 read_flash_capacity(struct rsi_hw *adapter)
+{
+       u32 flash_sz = 0;
+
+       if ((adapter->host_intf_ops->master_reg_read(adapter, FLASH_SIZE_ADDR,
+                                                    &flash_sz, 2)) < 0) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Flash size reading failed..\n",
+                       __func__);
+               return 0;
+       }
+       rsi_dbg(INIT_ZONE, "Flash capacity: %d KiloBytes\n", flash_sz);
+
+       return (flash_sz * 1024); /* Return size in kbytes */
+}
+
+static int ping_pong_write(struct rsi_hw *adapter, u8 cmd, u8 *addr, u32 size)
+{
+       struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+       u32 block_size = adapter->block_size;
+       u32 cmd_addr;
+       u16 cmd_resp, cmd_req;
+       u8 *str;
+       int status;
+
+       if (cmd == PING_WRITE) {
+               cmd_addr = PING_BUFFER_ADDRESS;
+               cmd_resp = PONG_AVAIL;
+               cmd_req = PING_VALID;
+               str = "PING_VALID";
+       } else {
+               cmd_addr = PONG_BUFFER_ADDRESS;
+               cmd_resp = PING_AVAIL;
+               cmd_req = PONG_VALID;
+               str = "PONG_VALID";
+       }
+
+       status = hif_ops->load_data_master_write(adapter, cmd_addr, size,
+                                           block_size, addr);
+       if (status) {
+               rsi_dbg(ERR_ZONE, "%s: Unable to write blk at addr %0x\n",
+                       __func__, *addr);
+               return status;
+       }
+
+       status = bl_cmd(adapter, cmd_req, cmd_resp, str);
+       if (status) {
+               bl_stop_cmd_timer(adapter);
+               return status;
+       }
+       return 0;
+}
+
+static int auto_fw_upgrade(struct rsi_hw *adapter, u8 *flash_content,
+                          u32 content_size)
+{
+       u8 cmd, *temp_flash_content;
+       u32 temp_content_size, num_flash, index;
+       u32 flash_start_address;
+       int status;
+
+       temp_flash_content = flash_content;
+
+       if (content_size > MAX_FLASH_FILE_SIZE) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Flash Content size is more than 400K %u\n",
+                       __func__, MAX_FLASH_FILE_SIZE);
+               return -EINVAL;
+       }
+
+       flash_start_address = *(u32 *)&flash_content[FLASH_START_ADDRESS];
+       rsi_dbg(INFO_ZONE, "flash start address: %08x\n", flash_start_address);
+
+       if (flash_start_address < FW_IMAGE_MIN_ADDRESS) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Fw image Flash Start Address is less than 64K\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       if (flash_start_address % FLASH_SECTOR_SIZE) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Flash Start Address is not multiple of 4K\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       if ((flash_start_address + content_size) > adapter->flash_capacity) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Flash Content will cross max flash size\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       temp_content_size  = content_size;
+       num_flash = content_size / FLASH_WRITE_CHUNK_SIZE;
+
+       rsi_dbg(INFO_ZONE, "content_size: %d, num_flash: %d\n",
+               content_size, num_flash);
+
+       for (index = 0; index <= num_flash; index++) {
+               rsi_dbg(INFO_ZONE, "flash index: %d\n", index);
+               if (index != num_flash) {
+                       content_size = FLASH_WRITE_CHUNK_SIZE;
+                       rsi_dbg(INFO_ZONE, "QSPI content_size:%d\n",
+                               content_size);
+               } else {
+                       content_size =
+                               temp_content_size % FLASH_WRITE_CHUNK_SIZE;
+                       rsi_dbg(INFO_ZONE,
+                               "Writing last sector content_size:%d\n",
+                               content_size);
+                       if (!content_size) {
+                               rsi_dbg(INFO_ZONE, "instruction size zero\n");
+                               break;
+                       }
+               }
+
+               if (index % 2)
+                       cmd = PING_WRITE;
+               else
+                       cmd = PONG_WRITE;
+
+               status = ping_pong_write(adapter, cmd, flash_content,
+                                        content_size);
+               if (status) {
+                       rsi_dbg(ERR_ZONE, "%s: Unable to load %d block\n",
+                               __func__, index);
+                       return status;
+               }
+
+               rsi_dbg(INFO_ZONE,
+                       "%s: Successfully loaded %d instructions\n",
+                       __func__, index);
+               flash_content += content_size;
+       }
+
+       status = bl_cmd(adapter, EOF_REACHED, FW_LOADING_SUCCESSFUL,
+                       "EOF_REACHED");
+       if (status) {
+               bl_stop_cmd_timer(adapter);
+               return status;
+       }
+       rsi_dbg(INFO_ZONE, "FW loading is done and FW is running..\n");
+       return 0;
+}
+
+static int rsi_load_firmware(struct rsi_hw *adapter)
+{
+       struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+       const struct firmware *fw_entry = NULL;
+       u32 regout_val = 0, content_size;
+       u16 tmp_regout_val = 0;
+       u8 *flash_content = NULL;
+       struct ta_metadata *metadata_p;
+       int status;
+
+       bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT);
+
+       while (!adapter->blcmd_timer_expired) {
+               status = hif_ops->master_reg_read(adapter, SWBL_REGOUT,
+                                             &regout_val, 2);
+               if (status < 0) {
+                       rsi_dbg(ERR_ZONE,
+                               "%s: REGOUT read failed\n", __func__);
+                       return status;
+               }
+               mdelay(1);
+               if ((regout_val >> 8) == REGOUT_VALID)
+                       break;
+       }
+       if (adapter->blcmd_timer_expired) {
+               rsi_dbg(ERR_ZONE, "%s: REGOUT read timedout\n", __func__);
+               rsi_dbg(ERR_ZONE,
+                       "%s: Soft boot loader not present\n", __func__);
+               return -ETIMEDOUT;
+       }
+       bl_stop_cmd_timer(adapter);
+
+       rsi_dbg(INFO_ZONE, "Received Board Version Number: %x\n",
+               (regout_val & 0xff));
+
+       status = hif_ops->master_reg_write(adapter, SWBL_REGOUT,
+                                       (REGOUT_INVALID | REGOUT_INVALID << 8),
+                                       2);
+       if (status < 0) {
+               rsi_dbg(ERR_ZONE, "%s: REGOUT writing failed..\n", __func__);
+               return status;
+       }
+       mdelay(1);
+
+       status = bl_cmd(adapter, CONFIG_AUTO_READ_MODE, CMD_PASS,
+                       "AUTO_READ_CMD");
+       if (status < 0)
+               return status;
+
+       adapter->flash_capacity = read_flash_capacity(adapter);
+       if (adapter->flash_capacity <= 0) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Unable to read flash size from EEPROM\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       metadata_p = &metadata_flash_content[adapter->priv->coex_mode];
+
+       rsi_dbg(INIT_ZONE, "%s: Loading file %s\n", __func__, metadata_p->name);
+       adapter->fw_file_name = metadata_p->name;
+
+       status = request_firmware(&fw_entry, metadata_p->name, adapter->device);
+       if (status < 0) {
+               rsi_dbg(ERR_ZONE, "%s: Failed to open file %s\n",
+                       __func__, metadata_p->name);
+               return status;
+       }
+       flash_content = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+       if (!flash_content) {
+               rsi_dbg(ERR_ZONE, "%s: Failed to copy firmware\n", __func__);
+               status = -EIO;
+               goto fail;
+       }
+       content_size = fw_entry->size;
+       rsi_dbg(INFO_ZONE, "FW Length = %d bytes\n", content_size);
+
+       status = bl_write_header(adapter, flash_content, content_size);
+       if (status) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: RPS Image header loading failed\n",
+                       __func__);
+               goto fail;
+       }
+
+       bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT);
+       status = bl_write_cmd(adapter, CHECK_CRC, CMD_PASS, &tmp_regout_val);
+       if (status) {
+               bl_stop_cmd_timer(adapter);
+               rsi_dbg(ERR_ZONE,
+                       "%s: CHECK_CRC Command writing failed..\n",
+                       __func__);
+               if ((tmp_regout_val & 0xff) == CMD_FAIL) {
+                       rsi_dbg(ERR_ZONE,
+                               "CRC Fail.. Proceeding to Upgrade mode\n");
+                       goto fw_upgrade;
+               }
+       }
+       bl_stop_cmd_timer(adapter);
+
+       status = bl_cmd(adapter, POLLING_MODE, CMD_PASS, "POLLING_MODE");
+       if (status)
+               goto fail;
+
+load_image_cmd:
+       status = bl_cmd(adapter, LOAD_HOSTED_FW, LOADING_INITIATED,
+                       "LOAD_HOSTED_FW");
+       if (status)
+               goto fail;
+       rsi_dbg(INFO_ZONE, "Load Image command passed..\n");
+       goto success;
+
+fw_upgrade:
+       status = bl_cmd(adapter, BURN_HOSTED_FW, SEND_RPS_FILE, "FW_UPGRADE");
+       if (status)
+               goto fail;
+
+       rsi_dbg(INFO_ZONE, "Burn Command Pass.. Upgrading the firmware\n");
+
+       status = auto_fw_upgrade(adapter, flash_content, content_size);
+       if (status == 0) {
+               rsi_dbg(ERR_ZONE, "Firmware upgradation Done\n");
+               goto load_image_cmd;
+       }
+       rsi_dbg(ERR_ZONE, "Firmware upgrade failed\n");
+
+       status = bl_cmd(adapter, CONFIG_AUTO_READ_MODE, CMD_PASS,
+                       "AUTO_READ_MODE");
+       if (status)
+               goto fail;
+
+success:
+       rsi_dbg(ERR_ZONE, "***** Firmware Loading successful *****\n");
+       kfree(flash_content);
+       release_firmware(fw_entry);
+       return 0;
+
+fail:
+       rsi_dbg(ERR_ZONE, "##### Firmware loading failed #####\n");
+       kfree(flash_content);
+       release_firmware(fw_entry);
+       return status;
+}
+
+int rsi_hal_device_init(struct rsi_hw *adapter)
+{
+       struct rsi_common *common = adapter->priv;
+
+       common->coex_mode = 1;
+       adapter->device_model = RSI_DEV_9113;
+
+       switch (adapter->device_model) {
+       case RSI_DEV_9113:
+               if (rsi_load_firmware(adapter)) {
+                       rsi_dbg(ERR_ZONE,
+                               "%s: Failed to load TA instructions\n",
+                               __func__);
+                       return -EINVAL;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rsi_hal_device_init);
+
diff --git a/drivers/net/wireless/rsi/rsi_91x_pkt.c b/drivers/net/wireless/rsi/rsi_91x_pkt.c
deleted file mode 100644 (file)
index 02920c9..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
- * Copyright (c) 2014 Redpine Signals Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "rsi_mgmt.h"
-
-/**
- * rsi_send_data_pkt() - This function sends the recieved data packet from
- *                      driver to device.
- * @common: Pointer to the driver private structure.
- * @skb: Pointer to the socket buffer structure.
- *
- * Return: status: 0 on success, -1 on failure.
- */
-int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
-{
-       struct rsi_hw *adapter = common->priv;
-       struct ieee80211_hdr *tmp_hdr;
-       struct ieee80211_tx_info *info;
-       struct skb_info *tx_params;
-       struct ieee80211_bss_conf *bss;
-       int status;
-       u8 ieee80211_size = MIN_802_11_HDR_LEN;
-       u8 extnd_size;
-       __le16 *frame_desc;
-       u16 seq_num;
-
-       info = IEEE80211_SKB_CB(skb);
-       bss = &info->control.vif->bss_conf;
-       tx_params = (struct skb_info *)info->driver_data;
-
-       if (!bss->assoc) {
-               status = -EINVAL;
-               goto err;
-       }
-
-       tmp_hdr = (struct ieee80211_hdr *)&skb->data[0];
-       seq_num = (le16_to_cpu(tmp_hdr->seq_ctrl) >> 4);
-
-       extnd_size = ((uintptr_t)skb->data & 0x3);
-
-       if ((FRAME_DESC_SZ + extnd_size) > skb_headroom(skb)) {
-               rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__);
-               status = -ENOSPC;
-               goto err;
-       }
-
-       skb_push(skb, (FRAME_DESC_SZ + extnd_size));
-       frame_desc = (__le16 *)&skb->data[0];
-       memset((u8 *)frame_desc, 0, FRAME_DESC_SZ);
-
-       if (ieee80211_is_data_qos(tmp_hdr->frame_control)) {
-               ieee80211_size += 2;
-               frame_desc[6] |= cpu_to_le16(BIT(12));
-       }
-
-       if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) &&
-           (common->secinfo.security_enable)) {
-               if (rsi_is_cipher_wep(common))
-                       ieee80211_size += 4;
-               else
-                       ieee80211_size += 8;
-               frame_desc[6] |= cpu_to_le16(BIT(15));
-       }
-
-       frame_desc[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) |
-                                   (RSI_WIFI_DATA_Q << 12));
-       frame_desc[2] = cpu_to_le16((extnd_size) | (ieee80211_size) << 8);
-
-       if (common->min_rate != 0xffff) {
-               /* Send fixed rate */
-               frame_desc[3] = cpu_to_le16(RATE_INFO_ENABLE);
-               frame_desc[4] = cpu_to_le16(common->min_rate);
-
-               if (conf_is_ht40(&common->priv->hw->conf))
-                       frame_desc[5] = cpu_to_le16(FULL40M_ENABLE);
-
-               if (common->vif_info[0].sgi) {
-                       if (common->min_rate & 0x100) /* Only MCS rates */
-                               frame_desc[4] |=
-                                       cpu_to_le16(ENABLE_SHORTGI_RATE);
-               }
-
-       }
-
-       frame_desc[6] |= cpu_to_le16(seq_num & 0xfff);
-       frame_desc[7] = cpu_to_le16(((tx_params->tid & 0xf) << 4) |
-                                   (skb->priority & 0xf) |
-                                   (tx_params->sta_id << 8));
-
-       status = adapter->host_intf_write_pkt(common->priv,
-                                             skb->data,
-                                             skb->len);
-       if (status)
-               rsi_dbg(ERR_ZONE, "%s: Failed to write pkt\n",
-                       __func__);
-
-err:
-       ++common->tx_stats.total_tx_pkt_freed[skb->priority];
-       rsi_indicate_tx_status(common->priv, skb, status);
-       return status;
-}
-
-/**
- * rsi_send_mgmt_pkt() - This functions sends the received management packet
- *                      from driver to device.
- * @common: Pointer to the driver private structure.
- * @skb: Pointer to the socket buffer structure.
- *
- * Return: status: 0 on success, -1 on failure.
- */
-int rsi_send_mgmt_pkt(struct rsi_common *common,
-                     struct sk_buff *skb)
-{
-       struct rsi_hw *adapter = common->priv;
-       struct ieee80211_hdr *wh;
-       struct ieee80211_tx_info *info;
-       struct ieee80211_bss_conf *bss;
-       struct ieee80211_hw *hw = adapter->hw;
-       struct ieee80211_conf *conf = &hw->conf;
-       struct skb_info *tx_params;
-       int status = -E2BIG;
-       __le16 *msg;
-       u8 extnd_size;
-       u8 vap_id = 0;
-
-       info = IEEE80211_SKB_CB(skb);
-       tx_params = (struct skb_info *)info->driver_data;
-       extnd_size = ((uintptr_t)skb->data & 0x3);
-
-       if (tx_params->flags & INTERNAL_MGMT_PKT) {
-               if ((extnd_size) > skb_headroom(skb)) {
-                       rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__);
-                       dev_kfree_skb(skb);
-                       return -ENOSPC;
-               }
-               skb_push(skb, extnd_size);
-               skb->data[extnd_size + 4] = extnd_size;
-               status = adapter->host_intf_write_pkt(common->priv,
-                                                     (u8 *)skb->data,
-                                                     skb->len);
-               if (status) {
-                       rsi_dbg(ERR_ZONE,
-                               "%s: Failed to write the packet\n", __func__);
-               }
-               dev_kfree_skb(skb);
-               return status;
-       }
-
-       bss = &info->control.vif->bss_conf;
-       wh = (struct ieee80211_hdr *)&skb->data[0];
-
-       if (FRAME_DESC_SZ > skb_headroom(skb))
-               goto err;
-
-       skb_push(skb, FRAME_DESC_SZ);
-       memset(skb->data, 0, FRAME_DESC_SZ);
-       msg = (__le16 *)skb->data;
-
-       if (skb->len > MAX_MGMT_PKT_SIZE) {
-               rsi_dbg(INFO_ZONE, "%s: Dropping mgmt pkt > 512\n", __func__);
-               goto err;
-       }
-
-       msg[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) |
-                           (RSI_WIFI_MGMT_Q << 12));
-       msg[1] = cpu_to_le16(TX_DOT11_MGMT);
-       msg[2] = cpu_to_le16(MIN_802_11_HDR_LEN << 8);
-       msg[3] = cpu_to_le16(RATE_INFO_ENABLE);
-       msg[6] = cpu_to_le16(le16_to_cpu(wh->seq_ctrl) >> 4);
-
-       if (wh->addr1[0] & BIT(0))
-               msg[3] |= cpu_to_le16(RSI_BROADCAST_PKT);
-
-       if (common->band == NL80211_BAND_2GHZ)
-               msg[4] = cpu_to_le16(RSI_11B_MODE);
-       else
-               msg[4] = cpu_to_le16((RSI_RATE_6 & 0x0f) | RSI_11G_MODE);
-
-       if (conf_is_ht40(conf)) {
-               msg[4] = cpu_to_le16(0xB | RSI_11G_MODE);
-               msg[5] = cpu_to_le16(0x6);
-       }
-
-       /* Indicate to firmware to give cfm */
-       if ((skb->data[16] == IEEE80211_STYPE_PROBE_REQ) && (!bss->assoc)) {
-               msg[1] |= cpu_to_le16(BIT(10));
-               msg[7] = cpu_to_le16(PROBEREQ_CONFIRM);
-               common->mgmt_q_block = true;
-       }
-
-       msg[7] |= cpu_to_le16(vap_id << 8);
-
-       status = adapter->host_intf_write_pkt(common->priv,
-                                             (u8 *)msg,
-                                             skb->len);
-       if (status)
-               rsi_dbg(ERR_ZONE, "%s: Failed to write the packet\n", __func__);
-
-err:
-       rsi_indicate_tx_status(common->priv, skb, status);
-       return status;
-}
index 8428858204a6763a6d4ccfbeb6c2c81a12e7a33f..2ef844adacf36886c0abb0160b60e863e00f8247 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include "rsi_sdio.h"
 #include "rsi_common.h"
+#include "rsi_hal.h"
 
 /**
  * rsi_sdio_set_cmd52_arg() - This function prepares cmd 52 read/write arg.
@@ -365,6 +366,7 @@ static int rsi_setblocklength(struct rsi_hw *adapter, u32 length)
 
        status = sdio_set_block_size(dev->pfunction, length);
        dev->pfunction->max_blksize = 256;
+       adapter->block_size = dev->pfunction->max_blksize;
 
        rsi_dbg(INFO_ZONE,
                "%s: Operational blk length is %d\n", __func__, length);
@@ -487,8 +489,8 @@ void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit)
  */
 static int rsi_sdio_read_register_multiple(struct rsi_hw *adapter,
                                           u32 addr,
-                                          u32 count,
-                                          u8 *data)
+                                          u8 *data,
+                                          u16 count)
 {
        struct rsi_91x_sdiodev *dev =
                (struct rsi_91x_sdiodev *)adapter->rsi_dev;
@@ -518,7 +520,7 @@ static int rsi_sdio_read_register_multiple(struct rsi_hw *adapter,
 int rsi_sdio_write_register_multiple(struct rsi_hw *adapter,
                                     u32 addr,
                                     u8 *data,
-                                    u32 count)
+                                    u16 count)
 {
        struct rsi_91x_sdiodev *dev =
                (struct rsi_91x_sdiodev *)adapter->rsi_dev;
@@ -552,6 +554,182 @@ int rsi_sdio_write_register_multiple(struct rsi_hw *adapter,
        return status;
 }
 
+static int rsi_sdio_load_data_master_write(struct rsi_hw *adapter,
+                                          u32 base_address,
+                                          u32 instructions_sz,
+                                          u16 block_size,
+                                          u8 *ta_firmware)
+{
+       u32 num_blocks, offset, i;
+       u16 msb_address, lsb_address;
+       u8 temp_buf[block_size];
+       int status;
+
+       num_blocks = instructions_sz / block_size;
+       msb_address = base_address >> 16;
+
+       rsi_dbg(INFO_ZONE, "ins_size: %d, num_blocks: %d\n",
+               instructions_sz, num_blocks);
+
+       /* Loading DM ms word in the sdio slave */
+       status = rsi_sdio_master_access_msword(adapter, msb_address);
+       if (status < 0) {
+               rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
+               return status;
+       }
+
+       for (offset = 0, i = 0; i < num_blocks; i++, offset += block_size) {
+               memset(temp_buf, 0, block_size);
+               memcpy(temp_buf, ta_firmware + offset, block_size);
+               lsb_address = (u16)base_address;
+               status = rsi_sdio_write_register_multiple
+                                       (adapter,
+                                        lsb_address | RSI_SD_REQUEST_MASTER,
+                                        temp_buf, block_size);
+               if (status < 0) {
+                       rsi_dbg(ERR_ZONE, "%s: failed to write\n", __func__);
+                       return status;
+               }
+               rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, i);
+               base_address += block_size;
+
+               if ((base_address >> 16) != msb_address) {
+                       msb_address += 1;
+
+                       /* Loading DM ms word in the sdio slave */
+                       status = rsi_sdio_master_access_msword(adapter,
+                                                              msb_address);
+                       if (status < 0) {
+                               rsi_dbg(ERR_ZONE,
+                                       "%s: Unable to set ms word reg\n",
+                                       __func__);
+                               return status;
+                       }
+               }
+       }
+
+       if (instructions_sz % block_size) {
+               memset(temp_buf, 0, block_size);
+               memcpy(temp_buf, ta_firmware + offset,
+                      instructions_sz % block_size);
+               lsb_address = (u16)base_address;
+               status = rsi_sdio_write_register_multiple
+                                       (adapter,
+                                        lsb_address | RSI_SD_REQUEST_MASTER,
+                                        temp_buf,
+                                        instructions_sz % block_size);
+               if (status < 0)
+                       return status;
+               rsi_dbg(INFO_ZONE,
+                       "Written Last Block in Address 0x%x Successfully\n",
+                       offset | RSI_SD_REQUEST_MASTER);
+       }
+       return 0;
+}
+
+#define FLASH_SIZE_ADDR                 0x04000016
+static int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr,
+                                   u32 *read_buf, u16 size)
+{
+       u32 addr_on_bus, *data;
+       u32 align[2] = {};
+       u16 ms_addr;
+       int status;
+
+       data = PTR_ALIGN(&align[0], 8);
+
+       ms_addr = (addr >> 16);
+       status = rsi_sdio_master_access_msword(adapter, ms_addr);
+       if (status < 0) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Unable to set ms word to common reg\n",
+                       __func__);
+               return status;
+       }
+       addr &= 0xFFFF;
+
+       addr_on_bus = (addr & 0xFF000000);
+       if ((addr_on_bus == (FLASH_SIZE_ADDR & 0xFF000000)) ||
+           (addr_on_bus == 0x0))
+               addr_on_bus = (addr & ~(0x3));
+       else
+               addr_on_bus = addr;
+
+       /* Bring TA out of reset */
+       status = rsi_sdio_read_register_multiple
+                                       (adapter,
+                                        (addr_on_bus | RSI_SD_REQUEST_MASTER),
+                                        (u8 *)data, 4);
+       if (status < 0) {
+               rsi_dbg(ERR_ZONE, "%s: AHB register read failed\n", __func__);
+               return status;
+       }
+       if (size == 2) {
+               if ((addr & 0x3) == 0)
+                       *read_buf = *data;
+               else
+                       *read_buf  = (*data >> 16);
+               *read_buf = (*read_buf & 0xFFFF);
+       } else if (size == 1) {
+               if ((addr & 0x3) == 0)
+                       *read_buf = *data;
+               else if ((addr & 0x3) == 1)
+                       *read_buf = (*data >> 8);
+               else if ((addr & 0x3) == 2)
+                       *read_buf = (*data >> 16);
+               else
+                       *read_buf = (*data >> 24);
+               *read_buf = (*read_buf & 0xFF);
+       } else {
+               *read_buf = *data;
+       }
+
+       return 0;
+}
+
+static int rsi_sdio_master_reg_write(struct rsi_hw *adapter,
+                                    unsigned long addr,
+                                    unsigned long data, u16 size)
+{
+       unsigned long data1[2], *data_aligned;
+       int status;
+
+       data_aligned = PTR_ALIGN(&data1[0], 8);
+
+       if (size == 2) {
+               *data_aligned = ((data << 16) | (data & 0xFFFF));
+       } else if (size == 1) {
+               u32 temp_data = data & 0xFF;
+
+               *data_aligned = ((temp_data << 24) | (temp_data << 16) |
+                                (temp_data << 8) | temp_data);
+       } else {
+               *data_aligned = data;
+       }
+       size = 4;
+
+       status = rsi_sdio_master_access_msword(adapter, (addr >> 16));
+       if (status < 0) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Unable to set ms word to common reg\n",
+                       __func__);
+               return -EIO;
+       }
+       addr = addr & 0xFFFF;
+
+       /* Bring TA out of reset */
+       status = rsi_sdio_write_register_multiple
+                                       (adapter,
+                                        (addr | RSI_SD_REQUEST_MASTER),
+                                        (u8 *)data_aligned, size);
+       if (status < 0) {
+               rsi_dbg(ERR_ZONE,
+                       "%s: Unable to do AHB reg write\n", __func__);
+               return status;
+       }
+       return 0;
+}
+
 /**
  * rsi_sdio_host_intf_write_pkt() - This function writes the packet to device.
  * @adapter: Pointer to the adapter structure.
@@ -614,8 +792,8 @@ int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter,
 
        status = rsi_sdio_read_register_multiple(adapter,
                                                 length,
-                                                length, /*num of bytes*/
-                                                (u8 *)pkt);
+                                                (u8 *)pkt,
+                                                length); /*num of bytes*/
 
        if (status)
                rsi_dbg(ERR_ZONE, "%s: Failed to read frame: %d\n", __func__,
@@ -676,8 +854,6 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
        }
        sdio_release_host(pfunction);
 
-       adapter->host_intf_write_pkt = rsi_sdio_host_intf_write_pkt;
-       adapter->host_intf_read_pkt = rsi_sdio_host_intf_read_pkt;
        adapter->determine_event_timeout = rsi_sdio_determine_event_timeout;
        adapter->check_hw_queue_status = rsi_sdio_read_buffer_status_register;
 
@@ -691,6 +867,17 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
        return status;
 }
 
+static struct rsi_host_intf_ops sdio_host_intf_ops = {
+       .write_pkt              = rsi_sdio_host_intf_write_pkt,
+       .read_pkt               = rsi_sdio_host_intf_read_pkt,
+       .master_access_msword   = rsi_sdio_master_access_msword,
+       .read_reg_multiple      = rsi_sdio_read_register_multiple,
+       .write_reg_multiple     = rsi_sdio_write_register_multiple,
+       .master_reg_read        = rsi_sdio_master_reg_read,
+       .master_reg_write       = rsi_sdio_master_reg_write,
+       .load_data_master_write = rsi_sdio_load_data_master_write,
+};
+
 /**
  * rsi_probe() - This function is called by kernel when the driver provided
  *              Vendor and device IDs are matched. All the initialization
@@ -713,6 +900,8 @@ static int rsi_probe(struct sdio_func *pfunction,
                        __func__);
                return 1;
        }
+       adapter->rsi_host_intf = RSI_HOST_INTF_SDIO;
+       adapter->host_intf_ops = &sdio_host_intf_ops;
 
        if (rsi_init_sdio_interface(adapter, pfunction)) {
                rsi_dbg(ERR_ZONE, "%s: Failed to init sdio interface\n",
@@ -720,13 +909,19 @@ static int rsi_probe(struct sdio_func *pfunction,
                goto fail;
        }
 
-       if (rsi_sdio_device_init(adapter->priv)) {
+       if (rsi_hal_device_init(adapter)) {
                rsi_dbg(ERR_ZONE, "%s: Failed in device init\n", __func__);
                sdio_claim_host(pfunction);
                sdio_disable_func(pfunction);
                sdio_release_host(pfunction);
                goto fail;
        }
+       rsi_dbg(INFO_ZONE, "===> RSI Device Init Done <===\n");
+
+       if (rsi_sdio_master_access_msword(adapter, MISC_CFG_BASE_ADDR)) {
+               rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
+               return -EIO;
+       }
 
        sdio_claim_host(pfunction);
        if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
index 40d72312f3df21dd6e4e12019febd6363a6f7912..df2a63b1f15cf2e289fe21994c6b827bf3d62d4e 100644 (file)
@@ -27,8 +27,7 @@
  *
  * Return: status: 0 on success, -1 on failure.
  */
-static int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
-                                        u16 ms_word)
+int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word)
 {
        u8 byte;
        u8 function = 0;
@@ -60,171 +59,6 @@ static int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
        return status;
 }
 
-/**
- * rsi_copy_to_card() - This function includes the actual funtionality of
- *                     copying the TA firmware to the card.Basically this
- *                     function includes opening the TA file,reading the
- *                     TA file and writing their values in blocks of data.
- * @common: Pointer to the driver private structure.
- * @fw: Pointer to the firmware value to be written.
- * @len: length of firmware file.
- * @num_blocks: Number of blocks to be written to the card.
- *
- * Return: 0 on success and -1 on failure.
- */
-static int rsi_copy_to_card(struct rsi_common *common,
-                           const u8 *fw,
-                           u32 len,
-                           u32 num_blocks)
-{
-       struct rsi_hw *adapter = common->priv;
-       struct rsi_91x_sdiodev *dev =
-               (struct rsi_91x_sdiodev *)adapter->rsi_dev;
-       u32 indx, ii;
-       u32 block_size = dev->tx_blk_size;
-       u32 lsb_address;
-       __le32 data[] = { TA_HOLD_THREAD_VALUE, TA_SOFT_RST_CLR,
-                         TA_PC_ZERO, TA_RELEASE_THREAD_VALUE };
-       u32 address[] = { TA_HOLD_THREAD_REG, TA_SOFT_RESET_REG,
-                         TA_TH0_PC_REG, TA_RELEASE_THREAD_REG };
-       u32 base_address;
-       u16 msb_address;
-
-       base_address = TA_LOAD_ADDRESS;
-       msb_address = base_address >> 16;
-
-       for (indx = 0, ii = 0; ii < num_blocks; ii++, indx += block_size) {
-               lsb_address = ((u16) base_address | RSI_SD_REQUEST_MASTER);
-               if (rsi_sdio_write_register_multiple(adapter,
-                                                    lsb_address,
-                                                    (u8 *)(fw + indx),
-                                                    block_size)) {
-                       rsi_dbg(ERR_ZONE,
-                               "%s: Unable to load %s blk\n", __func__,
-                               FIRMWARE_RSI9113);
-                       return -1;
-               }
-               rsi_dbg(INIT_ZONE, "%s: loading block: %d\n", __func__, ii);
-               base_address += block_size;
-               if ((base_address >> 16) != msb_address) {
-                       msb_address += 1;
-                       if (rsi_sdio_master_access_msword(adapter,
-                                                         msb_address)) {
-                               rsi_dbg(ERR_ZONE,
-                                       "%s: Unable to set ms word reg\n",
-                                       __func__);
-                               return -1;
-                       }
-               }
-       }
-
-       if (len % block_size) {
-               lsb_address = ((u16) base_address | RSI_SD_REQUEST_MASTER);
-               if (rsi_sdio_write_register_multiple(adapter,
-                                                    lsb_address,
-                                                    (u8 *)(fw + indx),
-                                                    len % block_size)) {
-                       rsi_dbg(ERR_ZONE,
-                               "%s: Unable to load f/w\n", __func__);
-                       return -1;
-               }
-       }
-       rsi_dbg(INIT_ZONE,
-               "%s: Succesfully loaded TA instructions\n", __func__);
-
-       if (rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR)) {
-               rsi_dbg(ERR_ZONE,
-                       "%s: Unable to set ms word to common reg\n",
-                       __func__);
-               return -1;
-       }
-
-       for (ii = 0; ii < ARRAY_SIZE(data); ii++) {
-               /* Bringing TA out of reset */
-               if (rsi_sdio_write_register_multiple(adapter,
-                                                    (address[ii] |
-                                                    RSI_SD_REQUEST_MASTER),
-                                                    (u8 *)&data[ii],
-                                                    4)) {
-                       rsi_dbg(ERR_ZONE,
-                               "%s: Unable to hold TA threads\n", __func__);
-                       return -1;
-               }
-       }
-
-       rsi_dbg(INIT_ZONE, "%s: loaded firmware\n", __func__);
-       return 0;
-}
-
-/**
- * rsi_load_ta_instructions() - This function includes the actual funtionality
- *                             of loading the TA firmware.This function also
- *                             includes opening the TA file,reading the TA
- *                             file and writing their value in blocks of data.
- * @common: Pointer to the driver private structure.
- *
- * Return: status: 0 on success, -1 on failure.
- */
-static int rsi_load_ta_instructions(struct rsi_common *common)
-{
-       struct rsi_hw *adapter = common->priv;
-       struct rsi_91x_sdiodev *dev =
-               (struct rsi_91x_sdiodev *)adapter->rsi_dev;
-       u32 len;
-       u32 num_blocks;
-       const u8 *fw;
-       const struct firmware *fw_entry = NULL;
-       u32 block_size = dev->tx_blk_size;
-       int status = 0;
-       u32 base_address;
-       u16 msb_address;
-
-       if (rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR)) {
-               rsi_dbg(ERR_ZONE,
-                       "%s: Unable to set ms word to common reg\n",
-                       __func__);
-               return -1;
-       }
-       base_address = TA_LOAD_ADDRESS;
-       msb_address = (base_address >> 16);
-
-       if (rsi_sdio_master_access_msword(adapter, msb_address)) {
-               rsi_dbg(ERR_ZONE,
-                       "%s: Unable to set ms word reg\n", __func__);
-               return -1;
-       }
-
-       status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device);
-       if (status < 0) {
-               rsi_dbg(ERR_ZONE, "%s Firmware file %s not found\n",
-                       __func__, FIRMWARE_RSI9113);
-               return status;
-       }
-
-       /* Copy firmware into DMA-accessible memory */
-       fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
-       if (!fw) {
-               status = -ENOMEM;
-               goto out;
-       }
-       len = fw_entry->size;
-
-       if (len % 4)
-               len += (4 - (len % 4));
-
-       num_blocks = (len / block_size);
-
-       rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len);
-       rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);
-
-       status = rsi_copy_to_card(common, fw, len, num_blocks);
-       kfree(fw);
-
-out:
-       release_firmware(fw_entry);
-       return status;
-}
-
 /**
  * rsi_process_pkt() - This Function reads rx_blocks register and figures out
  *                    the size of the rx pkt.
@@ -471,28 +305,6 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
        } while (1);
 }
 
-/**
- * rsi_device_init() - This Function Initializes The HAL.
- * @common: Pointer to the driver private structure.
- *
- * Return: 0 on success, -1 on failure.
- */
-int rsi_sdio_device_init(struct rsi_common *common)
-{
-       if (rsi_load_ta_instructions(common))
-               return -1;
-
-       if (rsi_sdio_master_access_msword(common->priv, MISC_CFG_BASE_ADDR)) {
-               rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n",
-                       __func__);
-               return -1;
-       }
-       rsi_dbg(INIT_ZONE,
-               "%s: Setting ms word to 0x41050000\n", __func__);
-
-       return 0;
-}
-
 /**
  * rsi_sdio_read_buffer_status_register() - This function is used to the read
  *                                         buffer status register and set
index cc8deecea8cbeeebbd7bc9216d7698a175ba8cae..f5de6934f7ecde922c96c6a7b73b8a53c8962d5e 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/module.h>
 #include "rsi_usb.h"
+#include "rsi_hal.h"
 
 /**
  * rsi_usb_card_write() - This function writes to the USB Card.
@@ -141,6 +142,9 @@ static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface,
        return 0;
 }
 
+#define RSI_USB_REQ_OUT        (USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE)
+#define RSI_USB_REQ_IN (USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE)
+
 /* rsi_usb_reg_read() - This function reads data from given register address.
  * @usbdev: Pointer to the usb_device structure.
  * @reg: Address of the register to be read.
@@ -164,11 +168,11 @@ static int rsi_usb_reg_read(struct usb_device *usbdev,
        status = usb_control_msg(usbdev,
                                 usb_rcvctrlpipe(usbdev, 0),
                                 USB_VENDOR_REGISTER_READ,
-                                USB_TYPE_VENDOR,
+                                RSI_USB_REQ_IN,
                                 ((reg & 0xffff0000) >> 16), (reg & 0xffff),
                                 (void *)buf,
                                 len,
-                                HZ * 5);
+                                USB_CTRL_GET_TIMEOUT);
 
        *value = (buf[0] | (buf[1] << 8));
        if (status < 0) {
@@ -211,12 +215,12 @@ static int rsi_usb_reg_write(struct usb_device *usbdev,
        status = usb_control_msg(usbdev,
                                 usb_sndctrlpipe(usbdev, 0),
                                 USB_VENDOR_REGISTER_WRITE,
-                                USB_TYPE_VENDOR,
+                                RSI_USB_REQ_OUT,
                                 ((reg & 0xffff0000) >> 16),
                                 (reg & 0xffff),
                                 (void *)usb_reg_buf,
                                 len,
-                                HZ * 5);
+                                USB_CTRL_SET_TIMEOUT);
        if (status < 0) {
                rsi_dbg(ERR_ZONE,
                        "%s: Reg write failed with error code :%d\n",
@@ -273,6 +277,46 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter)
        return status;
 }
 
+static int rsi_usb_read_register_multiple(struct rsi_hw *adapter, u32 addr,
+                                         u8 *data, u16 count)
+{
+       struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+       u8 *buf;
+       u16 transfer;
+       int status;
+
+       if (!addr)
+               return -EINVAL;
+
+       buf = kzalloc(RSI_USB_BUF_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       while (count) {
+               transfer = min_t(u16, count, RSI_USB_BUF_SIZE);
+               status = usb_control_msg(dev->usbdev,
+                                        usb_rcvctrlpipe(dev->usbdev, 0),
+                                        USB_VENDOR_REGISTER_READ,
+                                        RSI_USB_REQ_IN,
+                                        ((addr & 0xffff0000) >> 16),
+                                        (addr & 0xffff), (void *)buf,
+                                        transfer, USB_CTRL_GET_TIMEOUT);
+               if (status < 0) {
+                       rsi_dbg(ERR_ZONE,
+                               "Reg read failed with error code :%d\n",
+                                status);
+                       kfree(buf);
+                       return status;
+               }
+               memcpy(data, buf, transfer);
+               count -= transfer;
+               data += transfer;
+               addr += transfer;
+       }
+       kfree(buf);
+       return 0;
+}
+
 /**
  * rsi_usb_write_register_multiple() - This function writes multiple bytes of
  *                                    information to multiple registers.
@@ -283,41 +327,40 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter)
  *
  * Return: status: 0 on success, a negative error code on failure.
  */
-int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
-                                   u32 addr,
-                                   u8 *data,
-                                   u32 count)
+static int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr,
+                                          u8 *data, u16 count)
 {
        struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
        u8 *buf;
-       u8 transfer;
+       u16 transfer;
        int status = 0;
 
-       buf = kzalloc(4096, GFP_KERNEL);
+       buf = kzalloc(RSI_USB_BUF_SIZE, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
 
        while (count) {
-               transfer = (u8)(min_t(u32, count, 4096));
+               transfer = min_t(u16, count, RSI_USB_BUF_SIZE);
                memcpy(buf, data, transfer);
                status = usb_control_msg(dev->usbdev,
                                         usb_sndctrlpipe(dev->usbdev, 0),
                                         USB_VENDOR_REGISTER_WRITE,
-                                        USB_TYPE_VENDOR,
+                                        RSI_USB_REQ_OUT,
                                         ((addr & 0xffff0000) >> 16),
                                         (addr & 0xffff),
                                         (void *)buf,
                                         transfer,
-                                        HZ * 5);
+                                        USB_CTRL_SET_TIMEOUT);
                if (status < 0) {
                        rsi_dbg(ERR_ZONE,
                                "Reg write failed with error code :%d\n",
                                status);
-               } else {
-                       count -= transfer;
-                       data += transfer;
-                       addr += transfer;
+                       kfree(buf);
+                       return status;
                }
+               count -= transfer;
+               data += transfer;
+               addr += transfer;
        }
 
        kfree(buf);
@@ -348,6 +391,77 @@ static int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter,
                                  len);
 }
 
+static int rsi_usb_master_reg_read(struct rsi_hw *adapter, u32 reg,
+                                  u32 *value, u16 len)
+{
+       struct usb_device *usbdev =
+               ((struct rsi_91x_usbdev *)adapter->rsi_dev)->usbdev;
+
+       return rsi_usb_reg_read(usbdev, reg, (u16 *)value, len);
+}
+
+static int rsi_usb_master_reg_write(struct rsi_hw *adapter,
+                                   unsigned long reg,
+                                   unsigned long value, u16 len)
+{
+       struct usb_device *usbdev =
+               ((struct rsi_91x_usbdev *)adapter->rsi_dev)->usbdev;
+
+       return rsi_usb_reg_write(usbdev, reg, value, len);
+}
+
+static int rsi_usb_load_data_master_write(struct rsi_hw *adapter,
+                                         u32 base_address,
+                                         u32 instructions_sz, u16 block_size,
+                                         u8 *ta_firmware)
+{
+       u16 num_blocks;
+       u32 cur_indx, i;
+       u8 temp_buf[256];
+       int status;
+
+       num_blocks = instructions_sz / block_size;
+       rsi_dbg(INFO_ZONE, "num_blocks: %d\n", num_blocks);
+
+       for (cur_indx = 0, i = 0; i < num_blocks; i++, cur_indx += block_size) {
+               memset(temp_buf, 0, block_size);
+               memcpy(temp_buf, ta_firmware + cur_indx, block_size);
+               status = rsi_usb_write_register_multiple(adapter, base_address,
+                                                        (u8 *)(temp_buf),
+                                                        block_size);
+               if (status < 0)
+                       return status;
+
+               rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, i);
+               base_address += block_size;
+       }
+
+       if (instructions_sz % block_size) {
+               memset(temp_buf, 0, block_size);
+               memcpy(temp_buf, ta_firmware + cur_indx,
+                      instructions_sz % block_size);
+               status = rsi_usb_write_register_multiple
+                                               (adapter, base_address,
+                                                (u8 *)temp_buf,
+                                                instructions_sz % block_size);
+               if (status < 0)
+                       return status;
+               rsi_dbg(INFO_ZONE,
+                       "Written Last Block in Address 0x%x Successfully\n",
+                       cur_indx);
+       }
+       return 0;
+}
+
+static struct rsi_host_intf_ops usb_host_intf_ops = {
+       .write_pkt              = rsi_usb_host_intf_write_pkt,
+       .read_reg_multiple      = rsi_usb_read_register_multiple,
+       .write_reg_multiple     = rsi_usb_write_register_multiple,
+       .master_reg_read        = rsi_usb_master_reg_read,
+       .master_reg_write       = rsi_usb_master_reg_write,
+       .load_data_master_write = rsi_usb_load_data_master_write,
+};
+
 /**
  * rsi_deinit_usb_interface() - This function deinitializes the usb interface.
  * @adapter: Pointer to the adapter structure.
@@ -410,12 +524,14 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
        }
        rsi_dev->rx_usb_urb[0]->transfer_buffer = adapter->priv->rx_data_pkt;
        rsi_dev->tx_blk_size = 252;
+       adapter->block_size = rsi_dev->tx_blk_size;
 
        /* Initializing function callbacks */
        adapter->rx_urb_submit = rsi_rx_urb_submit;
-       adapter->host_intf_write_pkt = rsi_usb_host_intf_write_pkt;
        adapter->check_hw_queue_status = rsi_usb_check_queue_status;
        adapter->determine_event_timeout = rsi_usb_event_timeout;
+       adapter->rsi_host_intf = RSI_HOST_INTF_USB;
+       adapter->host_intf_ops = &usb_host_intf_ops;
 
        rsi_init_event(&rsi_dev->rx_thread.event);
        status = rsi_create_kthread(common, &rsi_dev->rx_thread,
@@ -467,6 +583,7 @@ static int rsi_probe(struct usb_interface *pfunction,
                        __func__);
                return -ENOMEM;
        }
+       adapter->rsi_host_intf = RSI_HOST_INTF_USB;
 
        status = rsi_init_usb_interface(adapter, pfunction);
        if (status) {
@@ -480,25 +597,20 @@ static int rsi_probe(struct usb_interface *pfunction,
        dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
 
        status = rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2);
-       if (status)
+       if (status < 0)
                goto err1;
        else
                fw_status &= 1;
 
        if (!fw_status) {
-               status = rsi_usb_device_init(adapter->priv);
+               rsi_dbg(INIT_ZONE, "Loading firmware...\n");
+               status = rsi_hal_device_init(adapter);
                if (status) {
                        rsi_dbg(ERR_ZONE, "%s: Failed in device init\n",
                                __func__);
                        goto err1;
                }
-
-               status = rsi_usb_reg_write(dev->usbdev,
-                                          USB_INTERNAL_REG_1,
-                                          RSI_USB_READY_MAGIC_NUM, 1);
-               if (status)
-                       goto err1;
-               rsi_dbg(INIT_ZONE, "%s: Performed device init\n", __func__);
+               rsi_dbg(INIT_ZONE, "%s: Device Init Done\n", __func__);
        }
 
        status = rsi_rx_urb_submit(adapter);
index de4900862836a55019a3033ad7045ac2fcc186d6..d3e0a07604a617cdcf8c9fc1ac61b902a9a1afcf 100644 (file)
 #include <linux/firmware.h>
 #include "rsi_usb.h"
 
-/**
- * rsi_copy_to_card() - This function includes the actual funtionality of
- *                     copying the TA firmware to the card.Basically this
- *                     function includes opening the TA file,reading the TA
- *                     file and writing their values in blocks of data.
- * @common: Pointer to the driver private structure.
- * @fw: Pointer to the firmware value to be written.
- * @len: length of firmware file.
- * @num_blocks: Number of blocks to be written to the card.
- *
- * Return: 0 on success and -1 on failure.
- */
-static int rsi_copy_to_card(struct rsi_common *common,
-                           const u8 *fw,
-                           u32 len,
-                           u32 num_blocks)
-{
-       struct rsi_hw *adapter = common->priv;
-       struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
-       u32 indx, ii;
-       u32 block_size = dev->tx_blk_size;
-       u32 lsb_address;
-       u32 base_address;
-
-       base_address = TA_LOAD_ADDRESS;
-
-       for (indx = 0, ii = 0; ii < num_blocks; ii++, indx += block_size) {
-               lsb_address = base_address;
-               if (rsi_usb_write_register_multiple(adapter,
-                                                   lsb_address,
-                                                   (u8 *)(fw + indx),
-                                                   block_size)) {
-                       rsi_dbg(ERR_ZONE,
-                               "%s: Unable to load %s blk\n", __func__,
-                               FIRMWARE_RSI9113);
-                       return -EIO;
-               }
-               rsi_dbg(INIT_ZONE, "%s: loading block: %d\n", __func__, ii);
-               base_address += block_size;
-       }
-
-       if (len % block_size) {
-               lsb_address = base_address;
-               if (rsi_usb_write_register_multiple(adapter,
-                                                   lsb_address,
-                                                   (u8 *)(fw + indx),
-                                                   len % block_size)) {
-                       rsi_dbg(ERR_ZONE,
-                               "%s: Unable to load %s blk\n", __func__,
-                               FIRMWARE_RSI9113);
-                       return -EIO;
-               }
-       }
-       rsi_dbg(INIT_ZONE,
-               "%s: Succesfully loaded %s instructions\n", __func__,
-               FIRMWARE_RSI9113);
-
-       rsi_dbg(INIT_ZONE, "%s: loaded firmware\n", __func__);
-       return 0;
-}
-
 /**
  * rsi_usb_rx_thread() - This is a kernel thread to receive the packets from
  *                      the USB device.
@@ -119,67 +58,3 @@ void rsi_usb_rx_thread(struct rsi_common *common)
        complete_and_exit(&dev->rx_thread.completion, 0);
 }
 
-
-/**
- * rsi_load_ta_instructions() - This function includes the actual funtionality
- *                             of loading the TA firmware.This function also
- *                             includes opening the TA file,reading the TA
- *                             file and writing their value in blocks of data.
- * @common: Pointer to the driver private structure.
- *
- * Return: status: 0 on success, -1 on failure.
- */
-static int rsi_load_ta_instructions(struct rsi_common *common)
-{
-       struct rsi_hw *adapter = common->priv;
-       struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
-       const struct firmware *fw_entry = NULL;
-       u32 block_size = dev->tx_blk_size;
-       const u8 *fw;
-       u32 num_blocks, len;
-       int status = 0;
-
-       status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device);
-       if (status < 0) {
-               rsi_dbg(ERR_ZONE, "%s Firmware file %s not found\n",
-                       __func__, FIRMWARE_RSI9113);
-               return status;
-       }
-
-       /* Copy firmware into DMA-accessible memory */
-       fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
-       if (!fw) {
-               status = -ENOMEM;
-               goto out;
-       }
-       len = fw_entry->size;
-
-       if (len % 4)
-               len += (4 - (len % 4));
-
-       num_blocks = (len / block_size);
-
-       rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len);
-       rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);
-
-       status = rsi_copy_to_card(common, fw, len, num_blocks);
-       kfree(fw);
-
-out:
-       release_firmware(fw_entry);
-       return status;
-}
-
-/**
- * rsi_device_init() - This Function Initializes The HAL.
- * @common: Pointer to the driver private structure.
- *
- * Return: 0 on success, -1 on failure.
- */
-int rsi_usb_device_init(struct rsi_common *common)
-{
-       if (rsi_load_ta_instructions(common))
-               return -EIO;
-
-       return 0;
-               }
index d3fbe33d23244bb37cf287736303365301e2e52e..44349696f5de39e1b0627b3e6a3632ccd3b5ade4 100644 (file)
@@ -20,8 +20,7 @@
 #include <linux/kthread.h>
 
 #define EVENT_WAIT_FOREVER              0
-#define TA_LOAD_ADDRESS                 0x00
-#define FIRMWARE_RSI9113                "rsi_91x.fw"
+#define FIRMWARE_RSI9113                "rs9113_wlan_qspi.rps"
 #define QUEUE_NOT_FULL                  1
 #define QUEUE_FULL                      0
 
diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h
new file mode 100644 (file)
index 0000000..b95200d
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2017 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_HAL_H__
+#define __RSI_HAL_H__
+
+#define FLASH_WRITE_CHUNK_SIZE         (4 * 1024)
+#define FLASH_SECTOR_SIZE              (4 * 1024)
+
+#define FLASH_SIZE_ADDR                        0x04000016
+#define PING_BUFFER_ADDRESS            0x19000
+#define PONG_BUFFER_ADDRESS            0x1a000
+#define SWBL_REGIN                     0x41050034
+#define SWBL_REGOUT                    0x4105003c
+#define PING_WRITE                     0x1
+#define PONG_WRITE                     0x2
+
+#define BL_CMD_TIMEOUT                 2000
+#define BL_BURN_TIMEOUT                        (50 * 1000)
+
+#define REGIN_VALID                    0xA
+#define REGIN_INPUT                    0xA0
+#define REGOUT_VALID                   0xAB
+#define REGOUT_INVALID                 (~0xAB)
+#define CMD_PASS                       0xAA
+#define CMD_FAIL                       0xCC
+
+#define LOAD_HOSTED_FW                 'A'
+#define BURN_HOSTED_FW                 'B'
+#define PING_VALID                     'I'
+#define PONG_VALID                     'O'
+#define PING_AVAIL                     'I'
+#define PONG_AVAIL                     'O'
+#define EOF_REACHED                    'E'
+#define CHECK_CRC                      'K'
+#define POLLING_MODE                   'P'
+#define CONFIG_AUTO_READ_MODE          'R'
+#define JUMP_TO_ZERO_PC                        'J'
+#define FW_LOADING_SUCCESSFUL          'S'
+#define LOADING_INITIATED              '1'
+
+/* Boot loader commands */
+#define SEND_RPS_FILE                  '2'
+
+#define FW_IMAGE_MIN_ADDRESS           (68 * 1024)
+#define MAX_FLASH_FILE_SIZE            (400 * 1024) //400K
+#define FLASH_START_ADDRESS            16
+
+#define COMMON_HAL_CARD_READY_IND      0x0
+
+#define COMMAN_HAL_WAIT_FOR_CARD_READY 1
+
+struct bl_header {
+       __le32 flags;
+       __le32 image_no;
+       __le32 check_sum;
+       __le32 flash_start_address;
+       __le32 flash_len;
+} __packed;
+
+struct ta_metadata {
+       char *name;
+       unsigned int address;
+};
+
+int rsi_hal_device_init(struct rsi_hw *adapter);
+
+#endif
index 1d5904bc2c7439459a87dc054f83b53857fb3ef3..ea4fc223cea7d35b5885dd3f12bb63fd38626488 100644 (file)
@@ -82,6 +82,8 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
        ((_q) == VI_Q) ? IEEE80211_AC_VI : \
        IEEE80211_AC_VO)
 
+#define RSI_DEV_9113           1
+
 struct version_info {
        u16 major;
        u16 minor;
@@ -204,13 +206,20 @@ struct rsi_common {
        struct cqm_info cqm_info;
 
        bool hw_data_qs_blocked;
+       u8 coex_mode;
        
        int tx_power;
        u8 ant_in_use;
 };
 
+enum host_intf {
+       RSI_HOST_INTF_SDIO = 0,
+       RSI_HOST_INTF_USB
+};
+
 struct rsi_hw {
        struct rsi_common *priv;
+       u8 device_model;
        struct ieee80211_hw *hw;
        struct ieee80211_vif *vifs[RSI_MAX_VIFS];
        struct ieee80211_tx_queue_params edca_params[NUM_EDCA_QUEUES];
@@ -219,16 +228,39 @@ struct rsi_hw {
        struct device *device;
        u8 sc_nvifs;
 
+       enum host_intf rsi_host_intf;
+       u16 block_size;
 #ifdef CONFIG_RSI_DEBUGFS
        struct rsi_debugfs *dfsentry;
        u8 num_debugfs_entries;
 #endif
+       char *fw_file_name;
+       struct timer_list bl_cmd_timer;
+       bool blcmd_timer_expired;
+       u32 flash_capacity;
        u8 dfs_region;
        void *rsi_dev;
-       int (*host_intf_read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
-       int (*host_intf_write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+       struct rsi_host_intf_ops *host_intf_ops;
        int (*check_hw_queue_status)(struct rsi_hw *adapter, u8 q_num);
        int (*rx_urb_submit)(struct rsi_hw *adapter);
        int (*determine_event_timeout)(struct rsi_hw *adapter);
 };
+
+struct rsi_host_intf_ops {
+       int (*read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+       int (*write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+       int (*master_access_msword)(struct rsi_hw *adapter, u16 ms_word);
+       int (*read_reg_multiple)(struct rsi_hw *adapter, u32 addr,
+                                u8 *data, u16 count);
+       int (*write_reg_multiple)(struct rsi_hw *adapter, u32 addr,
+                                 u8 *data, u16 count);
+       int (*master_reg_read)(struct rsi_hw *adapter, u32 addr,
+                              u32 *read_buf, u16 size);
+       int (*master_reg_write)(struct rsi_hw *adapter,
+                               unsigned long addr, unsigned long data,
+                               u16 size);
+       int (*load_data_master_write)(struct rsi_hw *adapter, u32 addr,
+                                     u32 instructions_size, u16 block_size,
+                                     u8 *fw);
+};
 #endif
index c7e8f2be790184399f6aa3f102d054f58852d423..9fb73f68282a8fd30a5b64ad9820ce64d311347a 100644 (file)
@@ -110,19 +110,19 @@ struct rsi_91x_sdiodev {
        u8 sdio_clock_speed;
        u32 cardcapability;
        u8 prev_desc[16];
-       u32 tx_blk_size;
+       u16 tx_blk_size;
        u8 write_fail;
 };
 
 void rsi_interrupt_handler(struct rsi_hw *adapter);
 int rsi_init_sdio_slave_regs(struct rsi_hw *adapter);
-int rsi_sdio_device_init(struct rsi_common *common);
 int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data);
 int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length);
 int rsi_sdio_write_register(struct rsi_hw *adapter, u8 function,
                            u32 addr, u8 *data);
 int rsi_sdio_write_register_multiple(struct rsi_hw *adapter, u32 addr,
-                                    u8 *data, u32 count);
+                                    u8 *data, u16 count);
+int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word);
 void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit);
 int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter);
 int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num);
index ebea0c411ead43f4411aa17445a6c003cb923aa1..59513ac61fb3aace9dbca852b81147b084a0909a 100644 (file)
@@ -35,6 +35,8 @@
 #define MGMT_EP                      1
 #define DATA_EP                      2
 
+#define RSI_USB_BUF_SIZE            4096
+
 struct rsi_91x_usbdev {
        struct rsi_thread rx_thread;
        u8 endpoint;
@@ -61,8 +63,5 @@ static inline int rsi_usb_event_timeout(struct rsi_hw *adapter)
        return EVENT_WAIT_FOREVER;
 }
 
-int rsi_usb_device_init(struct rsi_common *common);
-int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr,
-                                   u8 *data, u32 count);
 void rsi_usb_rx_thread(struct rsi_common *common);
 #endif
index de7e2a5fdffa048e2f00f2edab72f9363b56e01a..a2cb408be8aaaae14afccd23d7f29db0d903c837 100644 (file)
@@ -1149,15 +1149,9 @@ static ssize_t dev_mem_write(struct file *file, const char __user *user_buf,
        part.mem.start = *ppos;
        part.mem.size = bytes;
 
-       buf = kmalloc(bytes, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       ret = copy_from_user(buf, user_buf, bytes);
-       if (ret) {
-               ret = -EFAULT;
-               goto err_out;
-       }
+       buf = memdup_user(user_buf, bytes);
+       if (IS_ERR(buf))
+               return PTR_ERR(buf);
 
        mutex_lock(&wl->mutex);
 
@@ -1197,7 +1191,6 @@ static ssize_t dev_mem_write(struct file *file, const char __user *user_buf,
        if (ret == 0)
                *ppos += bytes;
 
-err_out:
        kfree(buf);
 
        return ((ret == 0) ? bytes : ret);
index f949ad2bd89827ff5e208e19ab978efe4ae02465..fa3547e06424721542980320ab3924f0ef9e1811 100644 (file)
 #define WSPI_MAX_CHUNK_SIZE    4092
 
 /*
- * wl18xx driver aggregation buffer size is (13 * PAGE_SIZE) compared to
- * (4 * PAGE_SIZE) for wl12xx, so use the larger buffer needed for wl18xx
+ * wl18xx driver aggregation buffer size is (13 * 4K) compared to
+ * (4 * 4K) for wl12xx, so use the larger buffer needed for wl18xx
  */
-#define SPI_AGGR_BUFFER_SIZE (13 * PAGE_SIZE)
+#define SPI_AGGR_BUFFER_SIZE (13 * SZ_4K)
 
 /* Maximum number of SPI write chunks */
 #define WSPI_MAX_NUM_OF_CHUNKS \
index 7e4c80f9b6cda0d37fe7ecca5fb276687ffa9c1e..9596be9a49d0907bb376195a7cc657b1ecd087bd 100644 (file)
@@ -226,7 +226,6 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
        /* Get bus level PHY reset GPIO details */
        mdio->reset_delay_us = DEFAULT_GPIO_RESET_DELAY;
        of_property_read_u32(np, "reset-delay-us", &mdio->reset_delay_us);
-       mdio->num_reset_gpios = of_gpio_named_count(np, "reset-gpios");
 
        /* Register the MDIO bus */
        rc = mdiobus_register(mdio);
index d1a750760cf30b270b44929ac91eb22971d15b22..65420a9f0e8202b1fb7d1214239c717b8fb25bbd 100644 (file)
@@ -480,7 +480,6 @@ static int ssb_devices_register(struct ssb_bus *bus)
 
                devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL);
                if (!devwrap) {
-                       ssb_err("Could not allocate device\n");
                        err = -ENOMEM;
                        goto error;
                }
index 781ef623233e769eb70a649a33049a2c00cb86cc..e05ae4645d91b1dff6c5ae38f3aab898268a66be 100644 (file)
@@ -179,7 +179,10 @@ static int xlr_get_link_ksettings(struct net_device *ndev,
 
        if (!phydev)
                return -ENODEV;
-       return phy_ethtool_ksettings_get(phydev, ecmd);
+
+       phy_ethtool_ksettings_get(phydev, ecmd);
+
+       return 0;
 }
 
 static int xlr_set_link_ksettings(struct net_device *ndev,
index d5990eb160bdf49a3a916c0195d04fbe521ef2b2..02781e78ffb69683d529a2930fa2f6b3d552e64a 100644 (file)
@@ -341,6 +341,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
        struct msghdr msg;
        struct kvec iov[1];
        size_t offset;
+       s64 tx_total_len;
        u32 abort_code;
        int ret;
 
@@ -364,9 +365,20 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
        srx.transport.sin.sin_port = call->port;
        memcpy(&srx.transport.sin.sin_addr, addr, 4);
 
+       /* Work out the length we're going to transmit.  This is awkward for
+        * calls such as FS.StoreData where there's an extra injection of data
+        * after the initial fixed part.
+        */
+       tx_total_len = call->request_size;
+       if (call->send_pages) {
+               tx_total_len += call->last_to - call->first_offset;
+               tx_total_len += (call->last - call->first) * PAGE_SIZE;
+       }
+
        /* create a call */
        rxcall = rxrpc_kernel_begin_call(afs_socket, &srx, call->key,
-                                        (unsigned long) call, gfp,
+                                        (unsigned long)call,
+                                        tx_total_len, gfp,
                                         (async ?
                                          afs_wake_up_async_call :
                                          afs_wake_up_call_waiter));
@@ -738,6 +750,8 @@ void afs_send_empty_reply(struct afs_call *call)
 
        _enter("");
 
+       rxrpc_kernel_set_tx_length(afs_socket, call->rxcall, 0);
+
        msg.msg_name            = NULL;
        msg.msg_namelen         = 0;
        iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, NULL, 0, 0);
@@ -772,6 +786,8 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
 
        _enter("");
 
+       rxrpc_kernel_set_tx_length(afs_socket, call->rxcall, len);
+
        iov[0].iov_base         = (void *) buf;
        iov[0].iov_len          = len;
        msg.msg_name            = NULL;
index a2e9d6ea1349fb85418a9ebafc55dd08d16ca6b0..e7c04c4e4bcd3e538b365b138a848df9ed96ede6 100644 (file)
@@ -150,8 +150,15 @@ struct in_ifaddr {
        unsigned long           ifa_tstamp; /* updated timestamp */
 };
 
+struct in_validator_info {
+       __be32                  ivi_addr;
+       struct in_device        *ivi_dev;
+};
+
 int register_inetaddr_notifier(struct notifier_block *nb);
 int unregister_inetaddr_notifier(struct notifier_block *nb);
+int register_inetaddr_validator_notifier(struct notifier_block *nb);
+int unregister_inetaddr_validator_notifier(struct notifier_block *nb);
 
 void inet_netconf_notify_devconf(struct net *net, int event, int type,
                                 int ifindex, struct ipv4_devconf *devconf);
index 56e96f6a0a45143afc69f5c71a2a9b852e4a91a5..32b044e953d22ae5ddbc2ffaa1f73ca4273db83d 100644 (file)
@@ -6627,6 +6627,24 @@ struct mlx5_ifc_create_flow_table_out_bits {
        u8         reserved_at_60[0x20];
 };
 
+struct mlx5_ifc_flow_table_context_bits {
+       u8         encap_en[0x1];
+       u8         decap_en[0x1];
+       u8         reserved_at_2[0x2];
+       u8         table_miss_action[0x4];
+       u8         level[0x8];
+       u8         reserved_at_10[0x8];
+       u8         log_size[0x8];
+
+       u8         reserved_at_20[0x8];
+       u8         table_miss_id[0x18];
+
+       u8         reserved_at_40[0x8];
+       u8         lag_master_next_table_id[0x18];
+
+       u8         reserved_at_60[0xe0];
+};
+
 struct mlx5_ifc_create_flow_table_in_bits {
        u8         opcode[0x10];
        u8         reserved_at_10[0x10];
@@ -6645,21 +6663,7 @@ struct mlx5_ifc_create_flow_table_in_bits {
 
        u8         reserved_at_a0[0x20];
 
-       u8         encap_en[0x1];
-       u8         decap_en[0x1];
-       u8         reserved_at_c2[0x2];
-       u8         table_miss_mode[0x4];
-       u8         level[0x8];
-       u8         reserved_at_d0[0x8];
-       u8         log_size[0x8];
-
-       u8         reserved_at_e0[0x8];
-       u8         table_miss_id[0x18];
-
-       u8         reserved_at_100[0x8];
-       u8         lag_master_next_table_id[0x18];
-
-       u8         reserved_at_120[0x80];
+       struct mlx5_ifc_flow_table_context_bits flow_table_context;
 };
 
 struct mlx5_ifc_create_flow_group_out_bits {
@@ -7291,7 +7295,8 @@ struct mlx5_ifc_ptys_reg_bits {
        u8         ib_link_width_oper[0x10];
        u8         ib_proto_oper[0x10];
 
-       u8         reserved_at_160[0x20];
+       u8         reserved_at_160[0x1c];
+       u8         connector_type[0x4];
 
        u8         eth_proto_lp_advertise[0x20];
 
@@ -7694,8 +7699,10 @@ struct mlx5_ifc_peir_reg_bits {
 };
 
 struct mlx5_ifc_pcam_enhanced_features_bits {
-       u8         reserved_at_0[0x7e];
+       u8         reserved_at_0[0x7c];
 
+       u8         ptys_connector_type[0x1];
+       u8         reserved_at_7d[0x1];
        u8         ppcnt_discard_group[0x1];
        u8         ppcnt_statistical_group[0x1];
 };
@@ -8277,17 +8284,7 @@ struct mlx5_ifc_modify_flow_table_in_bits {
        u8         reserved_at_a0[0x8];
        u8         table_id[0x18];
 
-       u8         reserved_at_c0[0x4];
-       u8         table_miss_mode[0x4];
-       u8         reserved_at_c8[0x18];
-
-       u8         reserved_at_e0[0x8];
-       u8         table_miss_id[0x18];
-
-       u8         reserved_at_100[0x8];
-       u8         lag_master_next_table_id[0x18];
-
-       u8         reserved_at_120[0x80];
+       struct mlx5_ifc_flow_table_context_bits flow_table_context;
 };
 
 struct mlx5_ifc_ets_tcn_config_reg_bits {
index e527732fb31bcc16791a93f1d45f5de2dd5d7649..c57d4b7de3a80203719f36319d17fb4794dd40b7 100644 (file)
@@ -92,6 +92,19 @@ enum mlx5e_link_mode {
        MLX5E_LINK_MODES_NUMBER,
 };
 
+enum mlx5e_connector_type {
+       MLX5E_PORT_UNKNOWN      = 0,
+       MLX5E_PORT_NONE                 = 1,
+       MLX5E_PORT_TP                   = 2,
+       MLX5E_PORT_AUI                  = 3,
+       MLX5E_PORT_BNC                  = 4,
+       MLX5E_PORT_MII                  = 5,
+       MLX5E_PORT_FIBRE                = 6,
+       MLX5E_PORT_DA                   = 7,
+       MLX5E_PORT_OTHER                = 8,
+       MLX5E_CONNECTOR_TYPE_NUMBER,
+};
+
 #define MLX5E_PROT_MASK(link_mode) (1 << link_mode)
 
 #define PORT_MODULE_EVENT_MODULE_STATUS_MASK 0xF
index c50c9218e31e06a98ef606967c973cdd10511460..524c7776ce96b2c661364b3297b807664338841e 100644 (file)
@@ -972,7 +972,7 @@ struct xfrmdev_ops {
  *      with PF and querying it may introduce a theoretical security risk.
  * int (*ndo_set_vf_rss_query_en)(struct net_device *dev, int vf, bool setting);
  * int (*ndo_get_vf_port)(struct net_device *dev, int vf, struct sk_buff *skb);
- * int (*ndo_setup_tc)(struct net_device *dev, u32 handle,
+ * int (*ndo_setup_tc)(struct net_device *dev, u32 handle, u32 chain_index,
  *                    __be16 protocol, struct tc_to_netdev *tc);
  *     Called to setup any 'tc' scheduler, classifier or action on @dev.
  *     This is always called from the stack with the rtnl lock held and netif
@@ -1222,7 +1222,7 @@ struct net_device_ops {
                                                   struct net_device *dev,
                                                   int vf, bool setting);
        int                     (*ndo_setup_tc)(struct net_device *dev,
-                                               u32 handle,
+                                               u32 handle, u32 chain_index,
                                                __be16 protocol,
                                                struct tc_to_netdev *tc);
 #if IS_ENABLED(CONFIG_FCOE)
index 414242200a9040427b5dbd1d1783782e4edddd04..23d2e46dd322992e1ed4326241d39e0fa8cb47da 100644 (file)
@@ -226,10 +226,8 @@ struct mii_bus {
 
        /* GPIO reset pulse width in microseconds */
        int reset_delay_us;
-       /* Number of reset GPIOs */
-       int num_reset_gpios;
-       /* Array of RESET GPIO descriptors */
-       struct gpio_desc **reset_gpiod;
+       /* RESET GPIO descriptor pointer */
+       struct gpio_desc *reset_gpiod;
 };
 #define to_mii_bus(d) container_of(d, struct mii_bus, dev)
 
@@ -874,8 +872,8 @@ void phy_start_machine(struct phy_device *phydev);
 void phy_stop_machine(struct phy_device *phydev);
 void phy_trigger_machine(struct phy_device *phydev, bool sync);
 int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
-int phy_ethtool_ksettings_get(struct phy_device *phydev,
-                             struct ethtool_link_ksettings *cmd);
+void phy_ethtool_ksettings_get(struct phy_device *phydev,
+                              struct ethtool_link_ksettings *cmd);
 int phy_ethtool_ksettings_set(struct phy_device *phydev,
                              const struct ethtool_link_ksettings *cmd);
 int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd);
index 4fb4666ea879c6e8f8b9da42cce9f8217e1681d9..5958b45eb6996cedfee6466b201a0fd3c4a70046 100644 (file)
 #include <linux/slab.h>
 #include <linux/qed/qed_if.h>
 
+enum qed_ll2_conn_type {
+       QED_LL2_TYPE_FCOE,
+       QED_LL2_TYPE_ISCSI,
+       QED_LL2_TYPE_TEST,
+       QED_LL2_TYPE_ISCSI_OOO,
+       QED_LL2_TYPE_RESERVED2,
+       QED_LL2_TYPE_ROCE,
+       QED_LL2_TYPE_RESERVED3,
+       MAX_QED_LL2_RX_CONN_TYPE
+};
+
+enum qed_ll2_roce_flavor_type {
+       QED_LL2_ROCE,
+       QED_LL2_RROCE,
+       MAX_QED_LL2_ROCE_FLAVOR_TYPE
+};
+
+enum qed_ll2_tx_dest {
+       QED_LL2_TX_DEST_NW, /* Light L2 TX Destination to the Network */
+       QED_LL2_TX_DEST_LB, /* Light L2 TX Destination to the Loopback */
+       QED_LL2_TX_DEST_MAX
+};
+
+enum qed_ll2_error_handle {
+       QED_LL2_DROP_PACKET,
+       QED_LL2_DO_NOTHING,
+       QED_LL2_ASSERT,
+};
+
 struct qed_ll2_stats {
        u64 gsi_invalid_hdr;
        u64 gsi_invalid_pkt_length;
@@ -67,6 +96,105 @@ struct qed_ll2_stats {
        u64 sent_bcast_pkts;
 };
 
+struct qed_ll2_comp_rx_data {
+       void *cookie;
+       dma_addr_t rx_buf_addr;
+       u16 parse_flags;
+       u16 vlan;
+       bool b_last_packet;
+       u8 connection_handle;
+
+       union {
+               u16 packet_length;
+               u16 data_length;
+       } length;
+
+       u32 opaque_data_0;
+       u32 opaque_data_1;
+
+       /* GSI only */
+       u32 gid_dst[4];
+       u16 qp_id;
+
+       union {
+               u8 placement_offset;
+               u8 data_length_error;
+       } u;
+};
+
+typedef
+void (*qed_ll2_complete_rx_packet_cb)(void *cxt,
+                                     struct qed_ll2_comp_rx_data *data);
+
+typedef
+void (*qed_ll2_release_rx_packet_cb)(void *cxt,
+                                    u8 connection_handle,
+                                    void *cookie,
+                                    dma_addr_t rx_buf_addr,
+                                    bool b_last_packet);
+
+typedef
+void (*qed_ll2_complete_tx_packet_cb)(void *cxt,
+                                     u8 connection_handle,
+                                     void *cookie,
+                                     dma_addr_t first_frag_addr,
+                                     bool b_last_fragment,
+                                     bool b_last_packet);
+
+typedef
+void (*qed_ll2_release_tx_packet_cb)(void *cxt,
+                                    u8 connection_handle,
+                                    void *cookie,
+                                    dma_addr_t first_frag_addr,
+                                    bool b_last_fragment, bool b_last_packet);
+
+struct qed_ll2_cbs {
+       qed_ll2_complete_rx_packet_cb rx_comp_cb;
+       qed_ll2_release_rx_packet_cb rx_release_cb;
+       qed_ll2_complete_tx_packet_cb tx_comp_cb;
+       qed_ll2_release_tx_packet_cb tx_release_cb;
+       void *cookie;
+};
+
+struct qed_ll2_acquire_data_inputs {
+       enum qed_ll2_conn_type conn_type;
+       u16 mtu;
+       u16 rx_num_desc;
+       u16 rx_num_ooo_buffers;
+       u8 rx_drop_ttl0_flg;
+       u8 rx_vlan_removal_en;
+       u16 tx_num_desc;
+       u8 tx_max_bds_per_packet;
+       u8 tx_tc;
+       enum qed_ll2_tx_dest tx_dest;
+       enum qed_ll2_error_handle ai_err_packet_too_big;
+       enum qed_ll2_error_handle ai_err_no_buf;
+       u8 gsi_enable;
+};
+
+struct qed_ll2_acquire_data {
+       struct qed_ll2_acquire_data_inputs input;
+       const struct qed_ll2_cbs *cbs;
+
+       /* Output container for LL2 connection's handle */
+       u8 *p_connection_handle;
+};
+
+struct qed_ll2_tx_pkt_info {
+       void *cookie;
+       dma_addr_t first_frag;
+       enum qed_ll2_tx_dest tx_dest;
+       enum qed_ll2_roce_flavor_type qed_roce_flavor;
+       u16 vlan;
+       u16 l4_hdr_offset_w;    /* from start of packet */
+       u16 first_frag_len;
+       u8 num_of_bds;
+       u8 bd_flags;
+       bool enable_ip_cksum;
+       bool enable_l4_cksum;
+       bool calc_ip_len;
+};
+
 #define QED_LL2_UNUSED_HANDLE   (0xff)
 
 struct qed_ll2_cb_ops {
index cbb2ff0ce4bc34c5179a5ad77167ac0b721f6a30..8e70f5ee05afd1da436fbd37bbf4641a11883537 100644 (file)
@@ -34,8 +34,6 @@
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/qed/qed_if.h>
 #include <linux/qed/qed_ll2_if.h>
@@ -491,42 +489,6 @@ struct qed_roce_ll2_packet {
        enum qed_roce_ll2_tx_dest tx_dest;
 };
 
-struct qed_roce_ll2_tx_params {
-       int reserved;
-};
-
-struct qed_roce_ll2_rx_params {
-       u16 vlan_id;
-       u8 smac[ETH_ALEN];
-       int rc;
-};
-
-struct qed_roce_ll2_cbs {
-       void (*tx_cb)(void *pdev, struct qed_roce_ll2_packet *pkt);
-
-       void (*rx_cb)(void *pdev, struct qed_roce_ll2_packet *pkt,
-                     struct qed_roce_ll2_rx_params *params);
-};
-
-struct qed_roce_ll2_params {
-       u16 max_rx_buffers;
-       u16 max_tx_buffers;
-       u16 mtu;
-       u8 mac_address[ETH_ALEN];
-       struct qed_roce_ll2_cbs cbs;
-       void *cb_cookie;
-};
-
-struct qed_roce_ll2_info {
-       u8 handle;
-       struct qed_roce_ll2_cbs cbs;
-       u8 mac_address[ETH_ALEN];
-       void *cb_cookie;
-
-       /* Lock to protect ll2 */
-       struct mutex lock;
-};
-
 enum qed_rdma_type {
        QED_RDMA_TYPE_ROCE,
 };
@@ -579,26 +541,40 @@ struct qed_rdma_ops {
        int (*rdma_query_qp)(void *rdma_cxt, struct qed_rdma_qp *qp,
                             struct qed_rdma_query_qp_out_params *oparams);
        int (*rdma_destroy_qp)(void *rdma_cxt, struct qed_rdma_qp *qp);
+
        int
        (*rdma_register_tid)(void *rdma_cxt,
                             struct qed_rdma_register_tid_in_params *iparams);
+
        int (*rdma_deregister_tid)(void *rdma_cxt, u32 itid);
        int (*rdma_alloc_tid)(void *rdma_cxt, u32 *itid);
        void (*rdma_free_tid)(void *rdma_cxt, u32 itid);
-       int (*roce_ll2_start)(struct qed_dev *cdev,
-                             struct qed_roce_ll2_params *params);
-       int (*roce_ll2_stop)(struct qed_dev *cdev);
-       int (*roce_ll2_tx)(struct qed_dev *cdev,
-                          struct qed_roce_ll2_packet *packet,
-                          struct qed_roce_ll2_tx_params *params);
-       int (*roce_ll2_post_rx_buffer)(struct qed_dev *cdev,
-                                      struct qed_roce_ll2_buffer *buf,
-                                      u64 cookie, u8 notify_fw);
-       int (*roce_ll2_set_mac_filter)(struct qed_dev *cdev,
-                                      u8 *old_mac_address,
-                                      u8 *new_mac_address);
-       int (*roce_ll2_stats)(struct qed_dev *cdev,
-                             struct qed_ll2_stats *stats);
+
+       int (*ll2_acquire_connection)(void *rdma_cxt,
+                                     struct qed_ll2_acquire_data *data);
+
+       int (*ll2_establish_connection)(void *rdma_cxt, u8 connection_handle);
+       int (*ll2_terminate_connection)(void *rdma_cxt, u8 connection_handle);
+       void (*ll2_release_connection)(void *rdma_cxt, u8 connection_handle);
+
+       int (*ll2_prepare_tx_packet)(void *rdma_cxt,
+                                    u8 connection_handle,
+                                    struct qed_ll2_tx_pkt_info *pkt,
+                                    bool notify_fw);
+
+       int (*ll2_set_fragment_of_tx_packet)(void *rdma_cxt,
+                                            u8 connection_handle,
+                                            dma_addr_t addr,
+                                            u16 nbytes);
+       int (*ll2_post_rx_buffer)(void *rdma_cxt, u8 connection_handle,
+                                 dma_addr_t addr, u16 buf_len, void *cookie,
+                                 u8 notify_fw);
+       int (*ll2_get_stats)(void *rdma_cxt,
+                            u8 connection_handle,
+                            struct qed_ll2_stats *p_stats);
+       int (*ll2_set_mac_filter)(struct qed_dev *cdev,
+                                 u8 *old_mac_address, u8 *new_mac_address);
+
 };
 
 const struct qed_rdma_ops *qed_get_rdma_ops(void);
index 707910c6c6c5ec0258e2d8377125b99a4fe7bb59..7343f71783dce943d5d884e158efecf1f11f9d87 100644 (file)
@@ -38,6 +38,7 @@ struct sockaddr_rxrpc {
 #define RXRPC_EXCLUSIVE_CONNECTION     3       /* Deprecated; use RXRPC_EXCLUSIVE_CALL instead */
 #define RXRPC_MIN_SECURITY_LEVEL       4       /* minimum security level */
 #define RXRPC_UPGRADEABLE_SERVICE      5       /* Upgrade service[0] -> service[1] */
+#define RXRPC_SUPPORTED_CMSG           6       /* Get highest supported control message type */
 
 /*
  * RxRPC control messages
@@ -45,16 +46,20 @@ struct sockaddr_rxrpc {
  * - terminal messages mean that a user call ID tag can be recycled
  * - s/r/- indicate whether these are applicable to sendmsg() and/or recvmsg()
  */
-#define RXRPC_USER_CALL_ID     1       /* sr: user call ID specifier */
-#define RXRPC_ABORT            2       /* sr: abort request / notification [terminal] */
-#define RXRPC_ACK              3       /* -r: [Service] RPC op final ACK received [terminal] */
-#define RXRPC_NET_ERROR                5       /* -r: network error received [terminal] */
-#define RXRPC_BUSY             6       /* -r: server busy received [terminal] */
-#define RXRPC_LOCAL_ERROR      7       /* -r: local error generated [terminal] */
-#define RXRPC_NEW_CALL         8       /* -r: [Service] new incoming call notification */
-#define RXRPC_ACCEPT           9       /* s-: [Service] accept request */
-#define RXRPC_EXCLUSIVE_CALL   10      /* s-: Call should be on exclusive connection */
-#define RXRPC_UPGRADE_SERVICE  11      /* s-: Request service upgrade for client call */
+enum rxrpc_cmsg_type {
+       RXRPC_USER_CALL_ID      = 1,    /* sr: user call ID specifier */
+       RXRPC_ABORT             = 2,    /* sr: abort request / notification [terminal] */
+       RXRPC_ACK               = 3,    /* -r: [Service] RPC op final ACK received [terminal] */
+       RXRPC_NET_ERROR         = 5,    /* -r: network error received [terminal] */
+       RXRPC_BUSY              = 6,    /* -r: server busy received [terminal] */
+       RXRPC_LOCAL_ERROR       = 7,    /* -r: local error generated [terminal] */
+       RXRPC_NEW_CALL          = 8,    /* -r: [Service] new incoming call notification */
+       RXRPC_ACCEPT            = 9,    /* s-: [Service] accept request */
+       RXRPC_EXCLUSIVE_CALL    = 10,   /* s-: Call should be on exclusive connection */
+       RXRPC_UPGRADE_SERVICE   = 11,   /* s-: Request service upgrade for client call */
+       RXRPC_TX_LENGTH         = 12,   /* s-: Total length of Tx data */
+       RXRPC__SUPPORTED
+};
 
 /*
  * RxRPC security levels
index 0873c2f9a9c113aa44ef991e1eb4543c2fb2e11c..1151b50892d1ac620c82db41560ca4d3468317ed 100644 (file)
@@ -867,10 +867,25 @@ static inline unsigned int skb_napi_id(const struct sk_buff *skb)
 #endif
 }
 
+/* decrement the reference count and return true if we can free the skb */
+static inline bool skb_unref(struct sk_buff *skb)
+{
+       if (unlikely(!skb))
+               return false;
+       if (likely(atomic_read(&skb->users) == 1))
+               smp_rmb();
+       else if (likely(!atomic_dec_and_test(&skb->users)))
+               return false;
+
+       return true;
+}
+
+void skb_release_head_state(struct sk_buff *skb);
 void kfree_skb(struct sk_buff *skb);
 void kfree_skb_list(struct sk_buff *segs);
 void skb_tx_error(struct sk_buff *skb);
 void consume_skb(struct sk_buff *skb);
+void consume_stateless_skb(struct sk_buff *skb);
 void  __kfree_skb(struct sk_buff *skb);
 extern struct kmem_cache *skbuff_head_cache;
 
index b43a4eec3ceca4f798bf7513ecd4aa999535c6e7..d0889cb501726685e56a2d6cf333ab55c2d0d48a 100644 (file)
@@ -48,11 +48,15 @@ struct prefix_info {
        struct in6_addr         prefix;
 };
 
-
 #include <linux/netdevice.h>
 #include <net/if_inet6.h>
 #include <net/ipv6.h>
 
+struct in6_validator_info {
+       struct in6_addr         i6vi_addr;
+       struct inet6_dev        *i6vi_dev;
+};
+
 #define IN6_ADDR_HSIZE_SHIFT   4
 #define IN6_ADDR_HSIZE         (1 << IN6_ADDR_HSIZE_SHIFT)
 
@@ -278,6 +282,10 @@ int register_inet6addr_notifier(struct notifier_block *nb);
 int unregister_inet6addr_notifier(struct notifier_block *nb);
 int inet6addr_notifier_call_chain(unsigned long val, void *v);
 
+int register_inet6addr_validator_notifier(struct notifier_block *nb);
+int unregister_inet6addr_validator_notifier(struct notifier_block *nb);
+int inet6addr_validator_notifier_call_chain(unsigned long val, void *v);
+
 void inet6_netconf_notify_devconf(struct net *net, int event, int type,
                                  int ifindex, struct ipv6_devconf *devconf);
 
index b5f5187f488cc1e663912ec1e12811d49ecb3fd5..c172709787af316efaee4cfa94cc185ca989b5fb 100644 (file)
@@ -33,6 +33,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *,
                                           struct sockaddr_rxrpc *,
                                           struct key *,
                                           unsigned long,
+                                          s64,
                                           gfp_t,
                                           rxrpc_notify_rx_t);
 int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *,
@@ -46,5 +47,6 @@ void rxrpc_kernel_get_peer(struct socket *, struct rxrpc_call *,
                           struct sockaddr_rxrpc *);
 int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
                               rxrpc_user_attach_call_t, unsigned long, gfp_t);
+void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64);
 
 #endif /* _NET_RXRPC_H */
index cd686c4fb32dc5409a08f818d48228bffa6f6778..9a14a0850b0e3601194479b4e1a433dc817e088e 100644 (file)
@@ -122,6 +122,9 @@ struct netns_ipv4 {
        int sysctl_tcp_fin_timeout;
        unsigned int sysctl_tcp_notsent_lowat;
        int sysctl_tcp_tw_reuse;
+       int sysctl_tcp_sack;
+       int sysctl_tcp_window_scaling;
+       int sysctl_tcp_timestamps;
        struct inet_timewait_death_row tcp_death_row;
        int sysctl_max_syn_backlog;
 
index b94006f6fbdde0d78fe33b9c2d86159e291c30cf..031bf16d15218329be98b1fb8c3f3e891a6f86e3 100644 (file)
@@ -8,10 +8,11 @@ u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
                               __be16 dport);
 u32 secure_tcp_seq(__be32 saddr, __be32 daddr,
                   __be16 sport, __be16 dport);
-u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr);
+u32 secure_tcp_ts_off(const struct net *net, __be32 saddr, __be32 daddr);
 u32 secure_tcpv6_seq(const __be32 *saddr, const __be32 *daddr,
                     __be16 sport, __be16 dport);
-u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr);
+u32 secure_tcpv6_ts_off(const struct net *net,
+                       const __be32 *saddr, const __be32 *daddr);
 u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
                                __be16 sport, __be16 dport);
 u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
index 3467d9e89e7dba1c35fa44a6268a28735f795319..858891c36f94ad2577726d6d21cf871dbcd55d98 100644 (file)
@@ -1080,6 +1080,7 @@ struct proto {
        bool                    (*stream_memory_free)(const struct sock *sk);
        /* Memory pressure */
        void                    (*enter_memory_pressure)(struct sock *sk);
+       void                    (*leave_memory_pressure)(struct sock *sk);
        atomic_long_t           *memory_allocated;      /* Current allocated memory. */
        struct percpu_counter   *sockets_allocated;     /* Current number of sockets. */
        /*
@@ -1088,7 +1089,7 @@ struct proto {
         * All the __sk_mem_schedule() is of this nature: accounting
         * is strict, actions are advisory and have some latency.
         */
-       int                     *memory_pressure;
+       unsigned long           *memory_pressure;
        long                    *sysctl_mem;
        int                     *sysctl_wmem;
        int                     *sysctl_rmem;
@@ -1193,25 +1194,6 @@ static inline bool sk_under_memory_pressure(const struct sock *sk)
        return !!*sk->sk_prot->memory_pressure;
 }
 
-static inline void sk_leave_memory_pressure(struct sock *sk)
-{
-       int *memory_pressure = sk->sk_prot->memory_pressure;
-
-       if (!memory_pressure)
-               return;
-
-       if (*memory_pressure)
-               *memory_pressure = 0;
-}
-
-static inline void sk_enter_memory_pressure(struct sock *sk)
-{
-       if (!sk->sk_prot->enter_memory_pressure)
-               return;
-
-       sk->sk_prot->enter_memory_pressure(sk);
-}
-
 static inline long
 sk_memory_allocated(const struct sock *sk)
 {
index 929d6af321cde71a509577cb14747ecd5b77ca8c..c784a6ac6ef1b95fa6252e694427b895d42dd76c 100644 (file)
@@ -46,6 +46,7 @@ enum switchdev_attr_id {
        SWITCHDEV_ATTR_ID_PORT_PARENT_ID,
        SWITCHDEV_ATTR_ID_PORT_STP_STATE,
        SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS,
+       SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT,
        SWITCHDEV_ATTR_ID_PORT_MROUTER,
        SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
        SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING,
@@ -62,6 +63,7 @@ struct switchdev_attr {
                struct netdev_phys_item_id ppid;        /* PORT_PARENT_ID */
                u8 stp_state;                           /* PORT_STP_STATE */
                unsigned long brport_flags;             /* PORT_BRIDGE_FLAGS */
+               unsigned long brport_flags_support;     /* PORT_BRIDGE_FLAGS_SUPPORT */
                bool mrouter;                           /* PORT_MROUTER */
                clock_t ageing_time;                    /* BRIDGE_AGEING_TIME */
                bool vlan_filtering;                    /* BRIDGE_VLAN_FILTERING */
@@ -153,8 +155,11 @@ struct switchdev_ops {
 };
 
 enum switchdev_notifier_type {
-       SWITCHDEV_FDB_ADD = 1,
-       SWITCHDEV_FDB_DEL,
+       SWITCHDEV_FDB_ADD_TO_BRIDGE = 1,
+       SWITCHDEV_FDB_DEL_TO_BRIDGE,
+       SWITCHDEV_FDB_ADD_TO_DEVICE,
+       SWITCHDEV_FDB_DEL_TO_DEVICE,
+       SWITCHDEV_FDB_OFFLOADED,
 };
 
 struct switchdev_notifier_info {
index 28b577a35786ddc9b223b54dd387e59910d9c521..3ab677d11d026e77deb3e7ec4fc2e0cf376af4ad 100644 (file)
@@ -237,9 +237,6 @@ void tcp_time_wait(struct sock *sk, int state, int timeo);
 
 
 /* sysctl variables for tcp */
-extern int sysctl_tcp_timestamps;
-extern int sysctl_tcp_window_scaling;
-extern int sysctl_tcp_sack;
 extern int sysctl_tcp_fastopen;
 extern int sysctl_tcp_retrans_collapse;
 extern int sysctl_tcp_stdurg;
@@ -279,7 +276,7 @@ extern int sysctl_tcp_pacing_ca_ratio;
 
 extern atomic_long_t tcp_memory_allocated;
 extern struct percpu_counter tcp_sockets_allocated;
-extern int tcp_memory_pressure;
+extern unsigned long tcp_memory_pressure;
 
 /* optimized version of sk_under_memory_pressure() for TCP sockets */
 static inline bool tcp_under_memory_pressure(const struct sock *sk)
@@ -427,7 +424,7 @@ void tcp_set_keepalive(struct sock *sk, int val);
 void tcp_syn_ack_timeout(const struct request_sock *req);
 int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
                int flags, int *addr_len);
-void tcp_parse_options(const struct sk_buff *skb,
+void tcp_parse_options(const struct net *net, const struct sk_buff *skb,
                       struct tcp_options_received *opt_rx,
                       int estab, struct tcp_fastopen_cookie *foc);
 const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
@@ -520,7 +517,8 @@ u32 __cookie_v4_init_sequence(const struct iphdr *iph, const struct tcphdr *th,
                              u16 *mssp);
 __u32 cookie_v4_init_sequence(const struct sk_buff *skb, __u16 *mss);
 u64 cookie_init_timestamp(struct request_sock *req);
-bool cookie_timestamp_decode(struct tcp_options_received *opt);
+bool cookie_timestamp_decode(const struct net *net,
+                            struct tcp_options_received *opt);
 bool cookie_ecn_ok(const struct tcp_options_received *opt,
                   const struct net *net, const struct dst_entry *dst);
 
@@ -1322,6 +1320,7 @@ extern void tcp_openreq_init_rwin(struct request_sock *req,
                                  const struct dst_entry *dst);
 
 void tcp_enter_memory_pressure(struct sock *sk);
+void tcp_leave_memory_pressure(struct sock *sk);
 
 static inline int keepalive_intvl_when(const struct tcp_sock *tp)
 {
@@ -1870,7 +1869,7 @@ struct tcp_request_sock_ops {
        struct dst_entry *(*route_req)(const struct sock *sk, struct flowi *fl,
                                       const struct request_sock *req);
        u32 (*init_seq)(const struct sk_buff *skb);
-       u32 (*init_ts_off)(const struct sk_buff *skb);
+       u32 (*init_ts_off)(const struct net *net, const struct sk_buff *skb);
        int (*send_synack)(const struct sock *sk, struct dst_entry *dst,
                           struct flowi *fl, struct request_sock *req,
                           struct tcp_fastopen_cookie *foc,
index 9b2c10b45733e4dc66d601ac2ea52fed65f3752d..f94b48b168dcc82cbd67b916951a4699f4f675ef 100644 (file)
@@ -513,6 +513,11 @@ union bpf_attr {
  *     Get the owner uid of the socket stored inside sk_buff.
  *     @skb: pointer to skb
  *     Return: uid of the socket owner on success or overflowuid if failed.
+ *
+ * u32 bpf_set_hash(skb, hash)
+ *     Set full skb->hash.
+ *     @skb: pointer to skb
+ *     @hash: hash to set
  */
 #define __BPF_FUNC_MAPPER(FN)          \
        FN(unspec),                     \
@@ -562,7 +567,8 @@ union bpf_attr {
        FN(xdp_adjust_head),            \
        FN(probe_read_str),             \
        FN(get_socket_cookie),          \
-       FN(get_socket_uid),
+       FN(get_socket_uid),             \
+       FN(set_hash),
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
index 1fe4c1e7d66e74c71724932bfe575d4ccc389f39..f904367c0ceef610d5ce9a78fea180bd4753a2f1 100644 (file)
@@ -110,6 +110,48 @@ struct igmpmsg {
        struct in_addr im_src,im_dst;
 };
 
+/* ipmr netlink table attributes */
+enum {
+       IPMRA_TABLE_UNSPEC,
+       IPMRA_TABLE_ID,
+       IPMRA_TABLE_CACHE_RES_QUEUE_LEN,
+       IPMRA_TABLE_MROUTE_REG_VIF_NUM,
+       IPMRA_TABLE_MROUTE_DO_ASSERT,
+       IPMRA_TABLE_MROUTE_DO_PIM,
+       IPMRA_TABLE_VIFS,
+       __IPMRA_TABLE_MAX
+};
+#define IPMRA_TABLE_MAX (__IPMRA_TABLE_MAX - 1)
+
+/* ipmr netlink vif attribute format
+ * [ IPMRA_TABLE_VIFS ] - nested attribute
+ *   [ IPMRA_VIF ] - nested attribute
+ *     [ IPMRA_VIFA_xxx ]
+ */
+enum {
+       IPMRA_VIF_UNSPEC,
+       IPMRA_VIF,
+       __IPMRA_VIF_MAX
+};
+#define IPMRA_VIF_MAX (__IPMRA_VIF_MAX - 1)
+
+/* vif-specific attributes */
+enum {
+       IPMRA_VIFA_UNSPEC,
+       IPMRA_VIFA_IFINDEX,
+       IPMRA_VIFA_VIF_ID,
+       IPMRA_VIFA_FLAGS,
+       IPMRA_VIFA_BYTES_IN,
+       IPMRA_VIFA_BYTES_OUT,
+       IPMRA_VIFA_PACKETS_IN,
+       IPMRA_VIFA_PACKETS_OUT,
+       IPMRA_VIFA_LOCAL_ADDR,
+       IPMRA_VIFA_REMOTE_ADDR,
+       IPMRA_VIFA_PAD,
+       __IPMRA_VIFA_MAX
+};
+#define IPMRA_VIFA_MAX (__IPMRA_VIFA_MAX - 1)
+
 /* That's all usermode folks */
 
 #define MFC_ASSERT_THRESH (3*HZ)               /* Maximal freq. of asserts */
index f3d16dbe09d64424d2d92c581f30771f6add6e0b..3199d28980b35442021ed1141151ab957b41c9f9 100644 (file)
@@ -41,6 +41,7 @@ enum {
 #define NTF_MASTER     0x04
 #define NTF_PROXY      0x08    /* == ATF_PUBL */
 #define NTF_EXT_LEARNED        0x10
+#define NTF_OFFLOADED   0x20
 #define NTF_ROUTER     0x80
 
 /*
index 95cffcb21dfdba7c974706131d0f43e21435e82d..d8569329579816213255169d0c183f4400835f7b 100644 (file)
@@ -228,6 +228,7 @@ enum
        LINUX_MIB_TCPABORTONLINGER,             /* TCPAbortOnLinger */
        LINUX_MIB_TCPABORTFAILED,               /* TCPAbortFailed */
        LINUX_MIB_TCPMEMORYPRESSURES,           /* TCPMemoryPressures */
+       LINUX_MIB_TCPMEMORYPRESSURESCHRONO,     /* TCPMemoryPressuresChrono */
        LINUX_MIB_TCPSACKDISCARD,               /* TCPSACKDiscard */
        LINUX_MIB_TCPDSACKIGNOREDOLD,           /* TCPSACKIgnoredOld */
        LINUX_MIB_TCPDSACKIGNOREDNOUNDO,        /* TCPSACKIgnoredNoUndo */
index 14ccb0759fa4daa57217fb334f43216feacd3f7b..519a6144d3d3a90f3a28b2eddc85adba9943d267 100644 (file)
@@ -1346,8 +1346,8 @@ static void clear_all_pkt_pointers(struct bpf_verifier_env *env)
                if (reg->type != PTR_TO_PACKET &&
                    reg->type != PTR_TO_PACKET_END)
                        continue;
-               reg->type = UNKNOWN_VALUE;
-               reg->imm = 0;
+               __mark_reg_unknown_value(state->spilled_regs,
+                                        i / BPF_REG_SIZE);
        }
 }
 
@@ -1952,6 +1952,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
                         */
                        regs[insn->dst_reg].type = CONST_IMM;
                        regs[insn->dst_reg].imm = insn->imm;
+                       regs[insn->dst_reg].id = 0;
                        regs[insn->dst_reg].max_value = insn->imm;
                        regs[insn->dst_reg].min_value = insn->imm;
                        regs[insn->dst_reg].min_align = calc_align(insn->imm);
@@ -2409,6 +2410,7 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn)
 
                regs[insn->dst_reg].type = CONST_IMM;
                regs[insn->dst_reg].imm = imm;
+               regs[insn->dst_reg].id = 0;
                return 0;
        }
 
@@ -2828,6 +2830,8 @@ static bool states_equal(struct bpf_verifier_env *env,
                        return false;
                if (i % BPF_REG_SIZE)
                        continue;
+               if (old->stack_slot_type[i] != STACK_SPILL)
+                       continue;
                if (memcmp(&old->spilled_regs[i / BPF_REG_SIZE],
                           &cur->spilled_regs[i / BPF_REG_SIZE],
                           sizeof(old->spilled_regs[0])))
index 08eb072430b9e2732d22bf79394a8c9ad91be8d7..051d7fca0c09bd0aa88e84339a435222b47f7be5 100644 (file)
@@ -266,14 +266,16 @@ static const struct bpf_func_proto bpf_perf_event_read_proto = {
        .arg2_type      = ARG_ANYTHING,
 };
 
+static DEFINE_PER_CPU(struct perf_sample_data, bpf_sd);
+
 static __always_inline u64
 __bpf_perf_event_output(struct pt_regs *regs, struct bpf_map *map,
                        u64 flags, struct perf_raw_record *raw)
 {
        struct bpf_array *array = container_of(map, struct bpf_array, map);
+       struct perf_sample_data *sd = this_cpu_ptr(&bpf_sd);
        unsigned int cpu = smp_processor_id();
        u64 index = flags & BPF_F_INDEX_MASK;
-       struct perf_sample_data sample_data;
        struct bpf_event_entry *ee;
        struct perf_event *event;
 
@@ -294,9 +296,9 @@ __bpf_perf_event_output(struct pt_regs *regs, struct bpf_map *map,
        if (unlikely(event->oncpu != cpu))
                return -EOPNOTSUPP;
 
-       perf_sample_data_init(&sample_data, 0, 0);
-       sample_data.raw = raw;
-       perf_event_output(event, &sample_data, regs);
+       perf_sample_data_init(sd, 0, 0);
+       sd->raw = raw;
+       perf_event_output(event, sd, regs);
        return 0;
 }
 
index 953b6728bd00c8ca7a4a20f2d2036c6f8f27f8e3..56d4b6977d03f1f900fc5eb08cf2372fd9904f26 100644 (file)
@@ -797,12 +797,6 @@ static const struct net_device_ops vlan_netdev_ops = {
        .ndo_netpoll_cleanup    = vlan_dev_netpoll_cleanup,
 #endif
        .ndo_fix_features       = vlan_dev_fix_features,
-       .ndo_fdb_add            = switchdev_port_fdb_add,
-       .ndo_fdb_del            = switchdev_port_fdb_del,
-       .ndo_fdb_dump           = switchdev_port_fdb_dump,
-       .ndo_bridge_setlink     = switchdev_port_bridge_setlink,
-       .ndo_bridge_getlink     = switchdev_port_bridge_getlink,
-       .ndo_bridge_dellink     = switchdev_port_bridge_dellink,
        .ndo_get_lock_subclass  = vlan_dev_get_lock_subclass,
        .ndo_get_iflink         = vlan_dev_get_iflink,
 };
index 495ba7cdcb0451c997656116a300a49b7e43a089..fa8d6b475c063b2ce39cfba4ed7c762aeb30c3e4 100644 (file)
@@ -1022,7 +1022,8 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
        u8 tq_avg;
 
        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                  "update_originator(): Searching and updating originator entry of received packet\n");
+                  "%s(): Searching and updating originator entry of received packet\n",
+                  __func__);
 
        rcu_read_lock();
        hlist_for_each_entry_rcu(tmp_neigh_node,
@@ -1944,7 +1945,7 @@ static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv,
 
                        batadv_iv_ogm_orig_print_neigh(orig_node, if_outgoing,
                                                       seq);
-                       seq_puts(seq, "\n");
+                       seq_putc(seq, '\n');
                        batman_count++;
 
 next:
index a36c8e7291d61f171cdb128dee865739d22cb00e..4e2724c5b33d8bda27339ffe65fc7d76f91fd119 100644 (file)
@@ -400,7 +400,7 @@ static void batadv_v_orig_print(struct batadv_priv *bat_priv,
                                   neigh_node->if_incoming->net_dev->name);
 
                        batadv_v_orig_print_neigh(orig_node, if_outgoing, seq);
-                       seq_puts(seq, "\n");
+                       seq_putc(seq, '\n');
                        batman_count++;
 
 next:
index b90c9903e2465bcfa9a287104dcd054b336c7398..b58007b79e3a19326d4291b9bc7ba8495044d3cc 100644 (file)
@@ -19,6 +19,7 @@
 #include "main.h"
 
 #include <linux/atomic.h>
+#include <linux/bitops.h>
 #include <linux/byteorder/generic.h>
 #include <linux/errno.h>
 #include <linux/etherdevice.h>
@@ -29,6 +30,7 @@
 #include <linux/kernel.h>
 #include <linux/kref.h>
 #include <linux/netdevice.h>
+#include <linux/nl80211.h>
 #include <linux/random.h>
 #include <linux/rculist.h>
 #include <linux/rcupdate.h>
@@ -109,8 +111,12 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
                         */
                        return 0;
                }
-               if (!ret)
-                       return sinfo.expected_throughput / 100;
+               if (ret)
+                       goto default_throughput;
+               if (!(sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT)))
+                       goto default_throughput;
+
+               return sinfo.expected_throughput / 100;
        }
 
        /* if not a wifi interface, check if this device provides data via
index d07e89ec84677d22a74891406ab6fa5ee6087011..cdd8e8e4df0b382b21ff674b9aafcd19e9a581e7 100644 (file)
@@ -394,7 +394,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, u8 *mac,
                 */
                ether_addr_copy(ethhdr->h_source, mac);
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                          "bla_send_claim(): CLAIM %pM on vid %d\n", mac,
+                          "%s(): CLAIM %pM on vid %d\n", __func__, mac,
                           batadv_print_vid(vid));
                break;
        case BATADV_CLAIM_TYPE_UNCLAIM:
@@ -403,7 +403,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, u8 *mac,
                 */
                ether_addr_copy(hw_src, mac);
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                          "bla_send_claim(): UNCLAIM %pM on vid %d\n", mac,
+                          "%s(): UNCLAIM %pM on vid %d\n", __func__, mac,
                           batadv_print_vid(vid));
                break;
        case BATADV_CLAIM_TYPE_ANNOUNCE:
@@ -412,7 +412,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, u8 *mac,
                 */
                ether_addr_copy(hw_src, mac);
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                          "bla_send_claim(): ANNOUNCE of %pM on vid %d\n",
+                          "%s(): ANNOUNCE of %pM on vid %d\n", __func__,
                           ethhdr->h_source, batadv_print_vid(vid));
                break;
        case BATADV_CLAIM_TYPE_REQUEST:
@@ -423,15 +423,15 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, u8 *mac,
                ether_addr_copy(hw_src, mac);
                ether_addr_copy(ethhdr->h_dest, mac);
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                          "bla_send_claim(): REQUEST of %pM to %pM on vid %d\n",
+                          "%s(): REQUEST of %pM to %pM on vid %d\n", __func__,
                           ethhdr->h_source, ethhdr->h_dest,
                           batadv_print_vid(vid));
                break;
        case BATADV_CLAIM_TYPE_LOOPDETECT:
                ether_addr_copy(ethhdr->h_source, mac);
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                          "bla_send_claim(): LOOPDETECT of %pM to %pM on vid %d\n",
-                          ethhdr->h_source, ethhdr->h_dest,
+                          "%s(): LOOPDETECT of %pM to %pM on vid %d\n",
+                          __func__, ethhdr->h_source, ethhdr->h_dest,
                           batadv_print_vid(vid));
 
                break;
@@ -509,7 +509,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, u8 *orig,
                return entry;
 
        batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                  "bla_get_backbone_gw(): not found (%pM, %d), creating new entry\n",
+                  "%s(): not found (%pM, %d), creating new entry\n", __func__,
                   orig, batadv_print_vid(vid));
 
        entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
@@ -605,7 +605,8 @@ static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
        int i;
 
        batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                  "bla_answer_request(): received a claim request, send all of our own claims again\n");
+                  "%s(): received a claim request, send all of our own claims again\n",
+                  __func__);
 
        backbone_gw = batadv_backbone_hash_find(bat_priv,
                                                primary_if->net_dev->dev_addr,
@@ -718,8 +719,8 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
                kref_init(&claim->refcount);
 
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                          "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n",
-                          mac, batadv_print_vid(vid));
+                          "%s(): adding new entry %pM, vid %d to hash ...\n",
+                          __func__, mac, batadv_print_vid(vid));
 
                kref_get(&claim->refcount);
                hash_added = batadv_hash_add(bat_priv->bla.claim_hash,
@@ -739,8 +740,9 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
                        goto claim_free_ref;
 
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                          "bla_add_claim(): changing ownership for %pM, vid %d to gw %pM\n",
-                          mac, batadv_print_vid(vid), backbone_gw->orig);
+                          "%s(): changing ownership for %pM, vid %d to gw %pM\n",
+                          __func__, mac, batadv_print_vid(vid),
+                          backbone_gw->orig);
 
                remove_crc = true;
        }
@@ -808,7 +810,7 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
        if (!claim)
                return;
 
-       batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n",
+       batadv_dbg(BATADV_DBG_BLA, bat_priv, "%s(): %pM, vid %d\n", __func__,
                   mac, batadv_print_vid(vid));
 
        batadv_hash_remove(bat_priv->bla.claim_hash, batadv_compare_claim,
@@ -848,8 +850,8 @@ static bool batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,
        crc = ntohs(*((__be16 *)(&an_addr[4])));
 
        batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                  "handle_announce(): ANNOUNCE vid %d (sent by %pM)... CRC = %#.4x\n",
-                  batadv_print_vid(vid), backbone_gw->orig, crc);
+                  "%s(): ANNOUNCE vid %d (sent by %pM)... CRC = %#.4x\n",
+                  __func__, batadv_print_vid(vid), backbone_gw->orig, crc);
 
        spin_lock_bh(&backbone_gw->crc_lock);
        backbone_crc = backbone_gw->crc;
@@ -857,8 +859,8 @@ static bool batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,
 
        if (backbone_crc != crc) {
                batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
-                          "handle_announce(): CRC FAILED for %pM/%d (my = %#.4x, sent = %#.4x)\n",
-                          backbone_gw->orig,
+                          "%s(): CRC FAILED for %pM/%d (my = %#.4x, sent = %#.4x)\n",
+                          __func__, backbone_gw->orig,
                           batadv_print_vid(backbone_gw->vid),
                           backbone_crc, crc);
 
@@ -903,8 +905,8 @@ static bool batadv_handle_request(struct batadv_priv *bat_priv,
                return true;
 
        batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                  "handle_request(): REQUEST vid %d (sent by %pM)...\n",
-                  batadv_print_vid(vid), ethhdr->h_source);
+                  "%s(): REQUEST vid %d (sent by %pM)...\n",
+                  __func__, batadv_print_vid(vid), ethhdr->h_source);
 
        batadv_bla_answer_request(bat_priv, primary_if, vid);
        return true;
@@ -940,7 +942,7 @@ static bool batadv_handle_unclaim(struct batadv_priv *bat_priv,
 
        /* this must be an UNCLAIM frame */
        batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                  "handle_unclaim(): UNCLAIM %pM on vid %d (sent by %pM)...\n",
+                  "%s(): UNCLAIM %pM on vid %d (sent by %pM)...\n", __func__,
                   claim_addr, batadv_print_vid(vid), backbone_gw->orig);
 
        batadv_bla_del_claim(bat_priv, claim_addr, vid);
@@ -1160,9 +1162,9 @@ static bool batadv_bla_process_claim(struct batadv_priv *bat_priv,
                                       ethhdr);
        if (ret == 1)
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                          "bla_process_claim(): received a claim frame from another group. From: %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
-                          ethhdr->h_source, batadv_print_vid(vid), hw_src,
-                          hw_dst);
+                          "%s(): received a claim frame from another group. From: %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
+                          __func__, ethhdr->h_source, batadv_print_vid(vid),
+                          hw_src, hw_dst);
 
        if (ret < 2)
                return !!ret;
@@ -1196,8 +1198,9 @@ static bool batadv_bla_process_claim(struct batadv_priv *bat_priv,
        }
 
        batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                  "bla_process_claim(): ERROR - this looks like a claim frame, but is useless. eth src %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
-                  ethhdr->h_source, batadv_print_vid(vid), hw_src, hw_dst);
+                  "%s(): ERROR - this looks like a claim frame, but is useless. eth src %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
+                  __func__, ethhdr->h_source, batadv_print_vid(vid), hw_src,
+                  hw_dst);
        return true;
 }
 
@@ -1237,8 +1240,8 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
                                continue;
 
                        batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
-                                  "bla_purge_backbone_gw(): backbone gw %pM timed out\n",
-                                  backbone_gw->orig);
+                                  "%s(): backbone gw %pM timed out\n",
+                                  __func__, backbone_gw->orig);
 
 purge_now:
                        /* don't wait for the pending request anymore */
@@ -1295,11 +1298,11 @@ static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
                                goto skip;
 
                        batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                                  "bla_purge_claims(): timed out.\n");
+                                  "%s(): timed out.\n", __func__);
 
 purge_now:
                        batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                                  "bla_purge_claims(): %pM, vid %d\n",
+                                  "%s(): %pM, vid %d\n", __func__,
                                   claim->addr, claim->vid);
 
                        batadv_handle_unclaim(bat_priv, primary_if,
@@ -1851,8 +1854,8 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
                 */
 
                batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                          "bla_rx(): Unclaimed MAC %pM found. Claim it. Local: %s\n",
-                          ethhdr->h_source,
+                          "%s(): Unclaimed MAC %pM found. Claim it. Local: %s\n",
+                          __func__, ethhdr->h_source,
                           batadv_is_my_client(bat_priv,
                                               ethhdr->h_source, vid) ?
                           "yes" : "no");
@@ -1978,15 +1981,15 @@ bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
                         * older than 100 ms to make sure we really
                         * have a roaming client here.
                         */
-                       batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_tx(): Roaming client %pM detected. Unclaim it.\n",
-                                  ethhdr->h_source);
+                       batadv_dbg(BATADV_DBG_BLA, bat_priv, "%s(): Roaming client %pM detected. Unclaim it.\n",
+                                  __func__, ethhdr->h_source);
                        batadv_handle_unclaim(bat_priv, primary_if,
                                              primary_if->net_dev->dev_addr,
                                              ethhdr->h_source, vid);
                        goto allow;
                } else {
-                       batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_tx(): Race for claim %pM detected. Drop packet.\n",
-                                  ethhdr->h_source);
+                       batadv_dbg(BATADV_DBG_BLA, bat_priv, "%s(): Race for claim %pM detected. Drop packet.\n",
+                                  __func__, ethhdr->h_source);
                        goto handled;
                }
        }
index 013e970eff393e0550aa250f7e72c27301071552..362cae2ef82a47b797d50e15bec53497bcab189c 100644 (file)
@@ -601,7 +601,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst,
                                                    BATADV_DAT_ADDR_MAX);
 
        batadv_dbg(BATADV_DBG_DAT, bat_priv,
-                  "dat_select_candidates(): IP=%pI4 hash(IP)=%u\n", &ip_dst,
+                  "%s(): IP=%pI4 hash(IP)=%u\n", __func__, &ip_dst,
                   ip_key);
 
        for (select = 0; select < BATADV_DAT_CANDIDATES_NUM; select++)
index 810f7d026f544027991af1714c169342792e1a68..2be8f1f4652958f7c90ee0237f9df986a87beb30 100644 (file)
@@ -24,7 +24,7 @@
 #define BATADV_DRIVER_DEVICE "batman-adv"
 
 #ifndef BATADV_SOURCE_VERSION
-#define BATADV_SOURCE_VERSION "2017.1"
+#define BATADV_SOURCE_VERSION "2017.2"
 #endif
 
 /* B.A.T.M.A.N. parameters */
@@ -168,7 +168,7 @@ enum batadv_uev_type {
 /* Maximum number of fragments for one packet */
 #define BATADV_FRAG_MAX_FRAGMENTS 16
 /* Maxumim size of each fragment */
-#define BATADV_FRAG_MAX_FRAG_SIZE 1400
+#define BATADV_FRAG_MAX_FRAG_SIZE 1280
 /* Time to keep fragments while waiting for rest of the fragments */
 #define BATADV_FRAG_TIMEOUT 10000
 
index e1f6fc72fe3e82cc3d55efdc1c08dfb60087ee23..3604d7899e2cb02dd4a2825cef3ffa490250eab2 100644 (file)
@@ -1935,9 +1935,7 @@ int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset)
                                                list)
                                seq_printf(seq, "%pM ",
                                           nc_node->addr);
-                       seq_puts(seq, "\n");
-
-                       seq_puts(seq, " Outgoing: ");
+                       seq_puts(seq, "\n Outgoing: ");
                        /* For out_nc_node to this orig_node */
                        list_for_each_entry_rcu(nc_node,
                                                &orig_node->out_coding_list,
index e1ebe14ee2a6e21cc8d6b4a42552cae4bd15061f..1338b9221613ce9092553ca62ac1afdefaf7b4f5 100644 (file)
@@ -985,8 +985,8 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
                        batadv_orig_node_put(orig_node_gw);
                        if (is_gw) {
                                batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                                          "recv_unicast_packet(): Dropped unicast pkt received from another backbone gw %pM.\n",
-                                          orig_addr_gw);
+                                          "%s(): Dropped unicast pkt received from another backbone gw %pM.\n",
+                                          __func__, orig_addr_gw);
                                return NET_RX_DROP;
                        }
                }
index 403df596a73d28afa8b31b46a2c0649052ce3db0..d239a9d72ac365d5bfb6916addd0d39cdab55423 100644 (file)
@@ -971,11 +971,11 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
 
        if (hard_iface)
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                          "purge_outstanding_packets(): %s\n",
-                          hard_iface->net_dev->name);
+                          "%s(): %s\n",
+                          __func__, hard_iface->net_dev->name);
        else
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                          "purge_outstanding_packets()\n");
+                          "%s()\n", __func__);
 
        /* claim bcast list for free() */
        spin_lock_bh(&bat_priv->forw_bcast_list_lock);
index 556f9a865ddfb5e488c65e9edd708fad187f56b1..e3e2585d097766a4128ee32b82ab0700a9c6f49c 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/etherdevice.h>
 #include <linux/fs.h>
 #include <linux/if_ether.h>
+#include <linux/init.h>
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/kref.h>
@@ -1497,7 +1498,7 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
 /**
  * batadv_tp_meter_init - initialize global tp_meter structures
  */
-void batadv_tp_meter_init(void)
+void __init batadv_tp_meter_init(void)
 {
        get_random_bytes(batadv_tp_prerandom, sizeof(batadv_tp_prerandom));
 }
index e75b4937b497401284bc553182737a2f7af54605..e1133bc634b5e8ed9a4639677e577a0d52e7c1d5 100644 (file)
@@ -2488,18 +2488,16 @@ static bool
 _batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry,
                       struct batadv_tt_global_entry *tt_global_entry)
 {
-       bool ret = false;
-
        if (tt_local_entry->common.flags & BATADV_TT_CLIENT_WIFI &&
            tt_global_entry->common.flags & BATADV_TT_CLIENT_WIFI)
-               ret = true;
+               return true;
 
        /* check if the two clients are marked as isolated */
        if (tt_local_entry->common.flags & BATADV_TT_CLIENT_ISOLA &&
            tt_global_entry->common.flags & BATADV_TT_CLIENT_ISOLA)
-               ret = true;
+               return true;
 
-       return ret;
+       return false;
 }
 
 /**
@@ -4010,19 +4008,22 @@ bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
                                          const unsigned char *addr,
                                          unsigned short vid)
 {
-       bool ret = false;
+       /* ignore loop detect macs, they are not supposed to be in the tt local
+        * data as well.
+        */
+       if (batadv_bla_is_loopdetect_mac(addr))
+               return false;
 
        if (!batadv_tt_global_add(bat_priv, orig_node, addr, vid,
                                  BATADV_TT_CLIENT_TEMP,
                                  atomic_read(&orig_node->last_ttvn)))
-               goto out;
+               return false;
 
        batadv_dbg(BATADV_DBG_TT, bat_priv,
                   "Added temporary global client (addr: %pM, vid: %d, orig: %pM)\n",
                   addr, batadv_print_vid(vid), orig_node->orig);
-       ret = true;
-out:
-       return ret;
+
+       return true;
 }
 
 /**
index 889e5640455f9636e2587e906da3194118b8f827..1407d1ba7577ffe553969d2cbefad2bd23f66aab 100644 (file)
@@ -121,7 +121,7 @@ static struct notifier_block br_device_notifier = {
        .notifier_call = br_device_event
 };
 
-/* called with RTNL */
+/* called with RTNL or RCU */
 static int br_switchdev_event(struct notifier_block *unused,
                              unsigned long event, void *ptr)
 {
@@ -131,27 +131,36 @@ static int br_switchdev_event(struct notifier_block *unused,
        struct switchdev_notifier_fdb_info *fdb_info;
        int err = NOTIFY_DONE;
 
-       p = br_port_get_rtnl(dev);
+       p = br_port_get_rtnl_rcu(dev);
        if (!p)
                goto out;
 
        br = p->br;
 
        switch (event) {
-       case SWITCHDEV_FDB_ADD:
+       case SWITCHDEV_FDB_ADD_TO_BRIDGE:
                fdb_info = ptr;
                err = br_fdb_external_learn_add(br, p, fdb_info->addr,
                                                fdb_info->vid);
-               if (err)
+               if (err) {
                        err = notifier_from_errno(err);
+                       break;
+               }
+               br_fdb_offloaded_set(br, p, fdb_info->addr,
+                                    fdb_info->vid);
                break;
-       case SWITCHDEV_FDB_DEL:
+       case SWITCHDEV_FDB_DEL_TO_BRIDGE:
                fdb_info = ptr;
                err = br_fdb_external_learn_del(br, p, fdb_info->addr,
                                                fdb_info->vid);
                if (err)
                        err = notifier_from_errno(err);
                break;
+       case SWITCHDEV_FDB_OFFLOADED:
+               fdb_info = ptr;
+               br_fdb_offloaded_set(br, p, fdb_info->addr,
+                                    fdb_info->vid);
+               break;
        }
 
 out:
index ab0c7cc8448f4824d69b9260e79ede7aac14dd9e..fef7872a320b4a0097009d25f2bd91e3f69d41dd 100644 (file)
@@ -511,6 +511,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
                fdb->is_static = is_static;
                fdb->added_by_user = 0;
                fdb->added_by_external_learn = 0;
+               fdb->offloaded = 0;
                fdb->updated = fdb->used = jiffies;
                hlist_add_head_rcu(&fdb->hlist, head);
        }
@@ -647,11 +648,16 @@ static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br,
        ndm->ndm_family  = AF_BRIDGE;
        ndm->ndm_pad1    = 0;
        ndm->ndm_pad2    = 0;
-       ndm->ndm_flags   = fdb->added_by_external_learn ? NTF_EXT_LEARNED : 0;
+       ndm->ndm_flags   = 0;
        ndm->ndm_type    = 0;
        ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex : br->dev->ifindex;
        ndm->ndm_state   = fdb_to_nud(br, fdb);
 
+       if (fdb->offloaded)
+               ndm->ndm_flags |= NTF_OFFLOADED;
+       if (fdb->added_by_external_learn)
+               ndm->ndm_flags |= NTF_EXT_LEARNED;
+
        if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr))
                goto nla_put_failure;
        if (nla_put_u32(skb, NDA_MASTER, br->dev->ifindex))
@@ -690,6 +696,8 @@ static void fdb_notify(struct net_bridge *br,
        struct sk_buff *skb;
        int err = -ENOBUFS;
 
+       br_switchdev_fdb_notify(fdb, type);
+
        skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
        if (skb == NULL)
                goto errout;
@@ -1075,7 +1083,6 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
        struct net_bridge_fdb_entry *fdb;
        int err = 0;
 
-       ASSERT_RTNL();
        spin_lock_bh(&br->hash_lock);
 
        head = &br->hash[br_mac_hash(addr, vid)];
@@ -1110,7 +1117,6 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
        struct net_bridge_fdb_entry *fdb;
        int err = 0;
 
-       ASSERT_RTNL();
        spin_lock_bh(&br->hash_lock);
 
        fdb = br_fdb_find(br, addr, vid);
@@ -1123,3 +1129,17 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
 
        return err;
 }
+
+void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
+                         const unsigned char *addr, u16 vid)
+{
+       struct net_bridge_fdb_entry *fdb;
+
+       spin_lock_bh(&br->hash_lock);
+
+       fdb = br_fdb_find(br, addr, vid);
+       if (fdb)
+               fdb->offloaded = 1;
+
+       spin_unlock_bh(&br->hash_lock);
+}
index 3bcda556971e71859bfe8fdf7395edb0f799a61e..63dca347b73bc04af101bf9598bcbb5c42d3cfc6 100644 (file)
@@ -662,16 +662,26 @@ static int br_set_port_state(struct net_bridge_port *p, u8 state)
 }
 
 /* Set/clear or port flags based on attribute */
-static void br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
-                          int attrtype, unsigned long mask)
+static int br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
+                           int attrtype, unsigned long mask)
 {
-       if (tb[attrtype]) {
-               u8 flag = nla_get_u8(tb[attrtype]);
-               if (flag)
-                       p->flags |= mask;
-               else
-                       p->flags &= ~mask;
-       }
+       unsigned long flags;
+       int err;
+
+       if (!tb[attrtype])
+               return 0;
+
+       if (nla_get_u8(tb[attrtype]))
+               flags = p->flags | mask;
+       else
+               flags = p->flags & ~mask;
+
+       err = br_switchdev_set_port_flag(p, flags, mask);
+       if (err)
+               return err;
+
+       p->flags = flags;
+       return 0;
 }
 
 /* Process bridge protocol info on port */
@@ -681,20 +691,55 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
        bool br_vlan_tunnel_old = false;
        int err;
 
-       br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
-       br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
-       br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
-       br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
-       br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
-       br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
-       br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
-       br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST);
-       br_set_port_flag(p, tb, IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD);
-       br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
-       br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
+       err = br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
+       if (err)
+               return err;
+
+       err = br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
+       if (err)
+               return err;
+
+       err = br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
+       if (err)
+               return err;
+
+       err = br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
+       if (err)
+               return err;
+
+       err = br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
+       if (err)
+               return err;
+
+       err = br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
+       if (err)
+               return err;
+
+       err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
+       if (err)
+               return err;
+
+       err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST);
+       if (err)
+               return err;
+
+       err = br_set_port_flag(p, tb, IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD);
+       if (err)
+               return err;
+
+       err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
+       if (err)
+               return err;
+
+       err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
+       if (err)
+               return err;
 
        br_vlan_tunnel_old = (p->flags & BR_VLAN_TUNNEL) ? true : false;
-       br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL);
+       err = br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL);
+       if (err)
+               return err;
+
        if (br_vlan_tunnel_old && !(p->flags & BR_VLAN_TUNNEL))
                nbp_vlan_tunnel_info_flush(p);
 
index 20626927f43368a32515ddc331461360a484f1be..c18682f804a0b4b40b76ceeae1998f21098c12c9 100644 (file)
@@ -169,7 +169,8 @@ struct net_bridge_fdb_entry {
        unsigned char                   is_local:1,
                                        is_static:1,
                                        added_by_user:1,
-                                       added_by_external_learn:1;
+                                       added_by_external_learn:1,
+                                       offloaded:1;
 
        /* write-heavy members should not affect lookups */
        unsigned long                   updated ____cacheline_aligned_in_smp;
@@ -284,6 +285,12 @@ static inline struct net_bridge_port *br_port_get_rtnl(const struct net_device *
                rtnl_dereference(dev->rx_handler_data) : NULL;
 }
 
+static inline struct net_bridge_port *br_port_get_rtnl_rcu(const struct net_device *dev)
+{
+       return br_port_exists(dev) ?
+               rcu_dereference_rtnl(dev->rx_handler_data) : NULL;
+}
+
 struct net_bridge {
        spinlock_t                      lock;
        spinlock_t                      hash_lock;
@@ -530,6 +537,8 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
                              const unsigned char *addr, u16 vid);
 int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
                              const unsigned char *addr, u16 vid);
+void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
+                         const unsigned char *addr, u16 vid);
 
 /* br_forward.c */
 enum br_pkt_type {
@@ -1076,6 +1085,11 @@ void nbp_switchdev_frame_mark(const struct net_bridge_port *p,
                              struct sk_buff *skb);
 bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
                                  const struct sk_buff *skb);
+int br_switchdev_set_port_flag(struct net_bridge_port *p,
+                              unsigned long flags,
+                              unsigned long mask);
+void br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb,
+                            int type);
 #else
 static inline int nbp_switchdev_mark_set(struct net_bridge_port *p)
 {
@@ -1092,6 +1106,18 @@ static inline bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
 {
        return true;
 }
+
+static inline int br_switchdev_set_port_flag(struct net_bridge_port *p,
+                                            unsigned long flags,
+                                            unsigned long mask)
+{
+       return 0;
+}
+
+static inline void
+br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
+{
+}
 #endif /* CONFIG_NET_SWITCHDEV */
 
 #endif
index f4097b900de1ff51a9d29c967c370c916c6092f5..181a44d0f1da6364a8965b54cf13aa6a5e44ef22 100644 (file)
@@ -55,3 +55,79 @@ bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
        return !skb->offload_fwd_mark ||
               BR_INPUT_SKB_CB(skb)->offload_fwd_mark != p->offload_fwd_mark;
 }
+
+/* Flags that can be offloaded to hardware */
+#define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | \
+                                 BR_MCAST_FLOOD | BR_BCAST_FLOOD)
+
+int br_switchdev_set_port_flag(struct net_bridge_port *p,
+                              unsigned long flags,
+                              unsigned long mask)
+{
+       struct switchdev_attr attr = {
+               .orig_dev = p->dev,
+               .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT,
+       };
+       int err;
+
+       if (mask & ~BR_PORT_FLAGS_HW_OFFLOAD)
+               return 0;
+
+       err = switchdev_port_attr_get(p->dev, &attr);
+       if (err == -EOPNOTSUPP)
+               return 0;
+       if (err)
+               return err;
+
+       /* Check if specific bridge flag attribute offload is supported */
+       if (!(attr.u.brport_flags_support & mask)) {
+               br_warn(p->br, "bridge flag offload is not supported %u(%s)\n",
+                       (unsigned int)p->port_no, p->dev->name);
+               return -EOPNOTSUPP;
+       }
+
+       attr.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS;
+       attr.flags = SWITCHDEV_F_DEFER;
+       attr.u.brport_flags = flags;
+       err = switchdev_port_attr_set(p->dev, &attr);
+       if (err) {
+               br_warn(p->br, "error setting offload flag on port %u(%s)\n",
+                       (unsigned int)p->port_no, p->dev->name);
+               return err;
+       }
+
+       return 0;
+}
+
+static void
+br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
+                               u16 vid, struct net_device *dev)
+{
+       struct switchdev_notifier_fdb_info info;
+       unsigned long notifier_type;
+
+       info.addr = mac;
+       info.vid = vid;
+       notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE;
+       call_switchdev_notifiers(notifier_type, dev, &info.info);
+}
+
+void
+br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
+{
+       if (!fdb->added_by_user)
+               return;
+
+       switch (type) {
+       case RTM_DELNEIGH:
+               br_switchdev_fdb_call_notifiers(false, fdb->addr.addr,
+                                               fdb->vlan_id,
+                                               fdb->dst->dev);
+               break;
+       case RTM_NEWNEIGH:
+               br_switchdev_fdb_call_notifiers(true, fdb->addr.addr,
+                                               fdb->vlan_id,
+                                               fdb->dst->dev);
+               break;
+       }
+}
index bc46118486fe8ffaae37f688467faa6494e3549c..e5311a7c70daf1d6c60d67fc6cf383e85cacc82e 100644 (file)
@@ -330,9 +330,7 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len)
 {
        bool slow;
 
-       if (likely(atomic_read(&skb->users) == 1))
-               smp_rmb();
-       else if (likely(!atomic_dec_and_test(&skb->users))) {
+       if (!skb_unref(skb)) {
                sk_peek_offset_bwd(sk, len);
                return;
        }
index 946f758d44f2f122d34aa33caec0a92f682a1802..a65a3b25e104221d49c6e26ac24a4d1843af2fe4 100644 (file)
@@ -1874,6 +1874,24 @@ static const struct bpf_func_proto bpf_set_hash_invalid_proto = {
        .arg1_type      = ARG_PTR_TO_CTX,
 };
 
+BPF_CALL_2(bpf_set_hash, struct sk_buff *, skb, u32, hash)
+{
+       /* Set user specified hash as L4(+), so that it gets returned
+        * on skb_get_hash() call unless BPF prog later on triggers a
+        * skb_clear_hash().
+        */
+       __skb_set_sw_hash(skb, hash, true);
+       return 0;
+}
+
+static const struct bpf_func_proto bpf_set_hash_proto = {
+       .func           = bpf_set_hash,
+       .gpl_only       = false,
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_CTX,
+       .arg2_type      = ARG_ANYTHING,
+};
+
 BPF_CALL_3(bpf_skb_vlan_push, struct sk_buff *, skb, __be16, vlan_proto,
           u16, vlan_tci)
 {
@@ -2744,6 +2762,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)
                return &bpf_get_hash_recalc_proto;
        case BPF_FUNC_set_hash_invalid:
                return &bpf_set_hash_invalid_proto;
+       case BPF_FUNC_set_hash:
+               return &bpf_set_hash_proto;
        case BPF_FUNC_perf_event_output:
                return &bpf_skb_event_output_proto;
        case BPF_FUNC_get_smp_processor_id:
@@ -2774,12 +2794,6 @@ xdp_func_proto(enum bpf_func_id func_id)
        }
 }
 
-static const struct bpf_func_proto *
-cg_skb_func_proto(enum bpf_func_id func_id)
-{
-       return sk_filter_func_proto(func_id);
-}
-
 static const struct bpf_func_proto *
 lwt_inout_func_proto(enum bpf_func_id func_id)
 {
@@ -3344,7 +3358,7 @@ const struct bpf_verifier_ops xdp_prog_ops = {
 };
 
 const struct bpf_verifier_ops cg_skb_prog_ops = {
-       .get_func_proto         = cg_skb_func_proto,
+       .get_func_proto         = sk_filter_func_proto,
        .is_valid_access        = sk_filter_is_valid_access,
        .convert_ctx_access     = bpf_convert_ctx_access,
        .test_run               = bpf_prog_test_run_skb,
index 26bbfababff27cecc589bca69e3eb14739187f5b..2178db8e47cd332a3ca0de850cd574a5acaadb10 100644 (file)
@@ -596,6 +596,7 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh,
 {
        struct net *net = sock_net(skb->sk);
        struct nlattr *tb[NETNSA_MAX + 1];
+       struct nlattr *nla;
        struct net *peer;
        int nsid, err;
 
@@ -603,23 +604,35 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh,
                          rtnl_net_policy, extack);
        if (err < 0)
                return err;
-       if (!tb[NETNSA_NSID])
+       if (!tb[NETNSA_NSID]) {
+               NL_SET_ERR_MSG(extack, "nsid is missing");
                return -EINVAL;
+       }
        nsid = nla_get_s32(tb[NETNSA_NSID]);
 
-       if (tb[NETNSA_PID])
+       if (tb[NETNSA_PID]) {
                peer = get_net_ns_by_pid(nla_get_u32(tb[NETNSA_PID]));
-       else if (tb[NETNSA_FD])
+               nla = tb[NETNSA_PID];
+       } else if (tb[NETNSA_FD]) {
                peer = get_net_ns_by_fd(nla_get_u32(tb[NETNSA_FD]));
-       else
+               nla = tb[NETNSA_FD];
+       } else {
+               NL_SET_ERR_MSG(extack, "Peer netns reference is missing");
                return -EINVAL;
-       if (IS_ERR(peer))
+       }
+       if (IS_ERR(peer)) {
+               NL_SET_BAD_ATTR(extack, nla);
+               NL_SET_ERR_MSG(extack, "Peer netns reference is invalid");
                return PTR_ERR(peer);
+       }
 
        spin_lock_bh(&net->nsid_lock);
        if (__peernet2id(net, peer) >= 0) {
                spin_unlock_bh(&net->nsid_lock);
                err = -EEXIST;
+               NL_SET_BAD_ATTR(extack, nla);
+               NL_SET_ERR_MSG(extack,
+                              "Peer netns already has a nsid assigned");
                goto out;
        }
 
@@ -628,6 +641,10 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (err >= 0) {
                rtnl_net_notifyid(net, RTM_NEWNSID, err);
                err = 0;
+       } else if (err == -ENOSPC && nsid >= 0) {
+               err = -EEXIST;
+               NL_SET_BAD_ATTR(extack, tb[NETNSA_NSID]);
+               NL_SET_ERR_MSG(extack, "The specified nsid is already used");
        }
 out:
        put_net(peer);
@@ -670,6 +687,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
 {
        struct net *net = sock_net(skb->sk);
        struct nlattr *tb[NETNSA_MAX + 1];
+       struct nlattr *nla;
        struct sk_buff *msg;
        struct net *peer;
        int err, id;
@@ -678,15 +696,22 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
                          rtnl_net_policy, extack);
        if (err < 0)
                return err;
-       if (tb[NETNSA_PID])
+       if (tb[NETNSA_PID]) {
                peer = get_net_ns_by_pid(nla_get_u32(tb[NETNSA_PID]));
-       else if (tb[NETNSA_FD])
+               nla = tb[NETNSA_PID];
+       } else if (tb[NETNSA_FD]) {
                peer = get_net_ns_by_fd(nla_get_u32(tb[NETNSA_FD]));
-       else
+               nla = tb[NETNSA_FD];
+       } else {
+               NL_SET_ERR_MSG(extack, "Peer netns reference is missing");
                return -EINVAL;
+       }
 
-       if (IS_ERR(peer))
+       if (IS_ERR(peer)) {
+               NL_SET_BAD_ATTR(extack, nla);
+               NL_SET_ERR_MSG(extack, "Peer netns reference is invalid");
                return PTR_ERR(peer);
+       }
 
        msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL);
        if (!msg) {
index ae35cce3a40d70387bee815798933aa43a0e6d84..7232274de334bbd0852b80fc286ee316e22946d7 100644 (file)
@@ -51,7 +51,8 @@ static u32 seq_scale(u32 seq)
 #endif
 
 #if IS_ENABLED(CONFIG_IPV6)
-u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr)
+u32 secure_tcpv6_ts_off(const struct net *net,
+                       const __be32 *saddr, const __be32 *daddr)
 {
        const struct {
                struct in6_addr saddr;
@@ -61,7 +62,7 @@ u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr)
                .daddr = *(struct in6_addr *)daddr,
        };
 
-       if (sysctl_tcp_timestamps != 1)
+       if (net->ipv4.sysctl_tcp_timestamps != 1)
                return 0;
 
        ts_secret_init();
@@ -113,9 +114,9 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
 #endif
 
 #ifdef CONFIG_INET
-u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr)
+u32 secure_tcp_ts_off(const struct net *net, __be32 saddr, __be32 daddr)
 {
-       if (sysctl_tcp_timestamps != 1)
+       if (net->ipv4.sysctl_tcp_timestamps != 1)
                return 0;
 
        ts_secret_init();
index 82cfc9c7a090060036f40f75954651c241db9dc1..304602784c3b78249c73609e8aad9cbc55e70e66 100644 (file)
@@ -643,12 +643,10 @@ static void kfree_skbmem(struct sk_buff *skb)
        kmem_cache_free(skbuff_fclone_cache, fclones);
 }
 
-static void skb_release_head_state(struct sk_buff *skb)
+void skb_release_head_state(struct sk_buff *skb)
 {
        skb_dst_drop(skb);
-#ifdef CONFIG_XFRM
-       secpath_put(skb->sp);
-#endif
+       secpath_reset(skb);
        if (skb->destructor) {
                WARN_ON(in_irq());
                skb->destructor(skb);
@@ -694,12 +692,9 @@ EXPORT_SYMBOL(__kfree_skb);
  */
 void kfree_skb(struct sk_buff *skb)
 {
-       if (unlikely(!skb))
-               return;
-       if (likely(atomic_read(&skb->users) == 1))
-               smp_rmb();
-       else if (likely(!atomic_dec_and_test(&skb->users)))
+       if (!skb_unref(skb))
                return;
+
        trace_kfree_skb(skb, __builtin_return_address(0));
        __kfree_skb(skb);
 }
@@ -746,17 +741,32 @@ EXPORT_SYMBOL(skb_tx_error);
  */
 void consume_skb(struct sk_buff *skb)
 {
-       if (unlikely(!skb))
-               return;
-       if (likely(atomic_read(&skb->users) == 1))
-               smp_rmb();
-       else if (likely(!atomic_dec_and_test(&skb->users)))
+       if (!skb_unref(skb))
                return;
+
        trace_consume_skb(skb);
        __kfree_skb(skb);
 }
 EXPORT_SYMBOL(consume_skb);
 
+/**
+ *     consume_stateless_skb - free an skbuff, assuming it is stateless
+ *     @skb: buffer to free
+ *
+ *     Works like consume_skb(), but this variant assumes that all the head
+ *     states have been already dropped.
+ */
+void consume_stateless_skb(struct sk_buff *skb)
+{
+       if (!skb_unref(skb))
+               return;
+
+       trace_consume_skb(skb);
+       if (likely(skb->head))
+               skb_release_data(skb);
+       kfree_skbmem(skb);
+}
+
 void __kfree_skb_flush(void)
 {
        struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache);
@@ -2646,7 +2656,8 @@ void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len)
 {
        int pos = skb_headlen(skb);
 
-       skb_shinfo(skb1)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG;
+       skb_shinfo(skb1)->tx_flags |= skb_shinfo(skb)->tx_flags &
+                                     SKBTX_SHARED_FRAG;
        if (len < pos)  /* Split line is inside header. */
                skb_split_inside_header(skb, skb1, len, pos);
        else            /* Second chunk has no header, nothing to copy. */
@@ -3261,8 +3272,8 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
                skb_copy_from_linear_data_offset(head_skb, offset,
                                                 skb_put(nskb, hsize), hsize);
 
-               skb_shinfo(nskb)->tx_flags = skb_shinfo(head_skb)->tx_flags &
-                       SKBTX_SHARED_FRAG;
+               skb_shinfo(nskb)->tx_flags |= skb_shinfo(head_skb)->tx_flags &
+                                             SKBTX_SHARED_FRAG;
 
                while (pos < offset + len) {
                        if (i >= nfrags) {
@@ -3948,7 +3959,8 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
                return;
 
        if (tsonly) {
-               skb_shinfo(skb)->tx_flags = skb_shinfo(orig_skb)->tx_flags;
+               skb_shinfo(skb)->tx_flags |= skb_shinfo(orig_skb)->tx_flags &
+                                            SKBTX_ANY_TSTAMP;
                skb_shinfo(skb)->tskey = skb_shinfo(orig_skb)->tskey;
        }
 
index bef844127e0182091678b9d57f7ec85c5241748d..ad8a4bc841267a442a1da3c56ef1cf074f9825b9 100644 (file)
@@ -2076,6 +2076,26 @@ int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
 }
 EXPORT_SYMBOL(sock_cmsg_send);
 
+static void sk_enter_memory_pressure(struct sock *sk)
+{
+       if (!sk->sk_prot->enter_memory_pressure)
+               return;
+
+       sk->sk_prot->enter_memory_pressure(sk);
+}
+
+static void sk_leave_memory_pressure(struct sock *sk)
+{
+       if (sk->sk_prot->leave_memory_pressure) {
+               sk->sk_prot->leave_memory_pressure(sk);
+       } else {
+               unsigned long *memory_pressure = sk->sk_prot->memory_pressure;
+
+               if (memory_pressure && *memory_pressure)
+                       *memory_pressure = 0;
+       }
+}
+
 /* On 32bit arches, an skb frag is limited to 2^15 */
 #define SKB_FRAG_PAGE_ORDER    get_order(32768)
 
index 405483a07efc7ac2efcfe86e285a7673547c9691..73a0399dc7a277178b0a432a067172131dce99ee 100644 (file)
@@ -447,7 +447,7 @@ static void dn_destruct(struct sock *sk)
        dst_release(rcu_dereference_check(sk->sk_dst_cache, 1));
 }
 
-static int dn_memory_pressure;
+static unsigned long dn_memory_pressure;
 
 static void dn_enter_memory_pressure(struct sock *sk)
 {
index 1cfdb31a2f442121d2cbff3243780e2d899da0ce..5e45ae5c3f710e1536240b2c3a0f57b210c33e49 100644 (file)
@@ -387,12 +387,13 @@ dsa_slave_get_link_ksettings(struct net_device *dev,
                             struct ethtool_link_ksettings *cmd)
 {
        struct dsa_slave_priv *p = netdev_priv(dev);
-       int err = -EOPNOTSUPP;
 
-       if (p->phy != NULL)
-               err = phy_ethtool_ksettings_get(p->phy, cmd);
+       if (!p->phy)
+               return -EOPNOTSUPP;
 
-       return err;
+       phy_ethtool_ksettings_get(p->phy, cmd);
+
+       return 0;
 }
 
 static int
@@ -836,10 +837,13 @@ static void dsa_slave_del_cls_matchall(struct net_device *dev,
 }
 
 static int dsa_slave_setup_tc(struct net_device *dev, u32 handle,
-                             __be16 protocol, struct tc_to_netdev *tc)
+                             u32 chain_index, __be16 protocol,
+                             struct tc_to_netdev *tc)
 {
        bool ingress = TC_H_MAJ(handle) == TC_H_MAJ(TC_H_INGRESS);
-       int ret = -EOPNOTSUPP;
+
+       if (chain_index)
+               return -EOPNOTSUPP;
 
        switch (tc->type) {
        case TC_SETUP_MATCHALL:
@@ -853,10 +857,8 @@ static int dsa_slave_setup_tc(struct net_device *dev, u32 handle,
                        return 0;
                }
        default:
-               break;
+               return -EOPNOTSUPP;
        }
-
-       return ret;
 }
 
 void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops)
index d8e5c311ee7cda455c961f09b542e301decadc94..f1029a8d0e20f2263f3a55230c7710d20ac15fbf 100644 (file)
@@ -159,19 +159,30 @@ static int dsa_switch_vlan_add(struct dsa_switch *ds,
 {
        const struct switchdev_obj_port_vlan *vlan = info->vlan;
        struct switchdev_trans *trans = info->trans;
+       DECLARE_BITMAP(members, ds->num_ports);
+       int port, err;
 
-       /* Do not care yet about other switch chips of the fabric */
-       if (ds->index != info->sw_index)
-               return 0;
+       /* Build a mask of VLAN members */
+       bitmap_zero(members, ds->num_ports);
+       if (ds->index == info->sw_index)
+               set_bit(info->port, members);
+       for (port = 0; port < ds->num_ports; port++)
+               if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
+                       set_bit(port, members);
 
        if (switchdev_trans_ph_prepare(trans)) {
                if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add)
                        return -EOPNOTSUPP;
 
-               return ds->ops->port_vlan_prepare(ds, info->port, vlan, trans);
+               for_each_set_bit(port, members, ds->num_ports) {
+                       err = ds->ops->port_vlan_prepare(ds, port, vlan, trans);
+                       if (err)
+                               return err;
+               }
        }
 
-       ds->ops->port_vlan_add(ds, info->port, vlan, trans);
+       for_each_set_bit(port, members, ds->num_ports)
+               ds->ops->port_vlan_add(ds, port, vlan, trans);
 
        return 0;
 }
@@ -181,14 +192,13 @@ static int dsa_switch_vlan_del(struct dsa_switch *ds,
 {
        const struct switchdev_obj_port_vlan *vlan = info->vlan;
 
-       /* Do not care yet about other switch chips of the fabric */
-       if (ds->index != info->sw_index)
-               return 0;
-
        if (!ds->ops->port_vlan_del)
                return -EOPNOTSUPP;
 
-       return ds->ops->port_vlan_del(ds, info->port, vlan);
+       if (ds->index == info->sw_index)
+               return ds->ops->port_vlan_del(ds, info->port, vlan);
+
+       return 0;
 }
 
 static int dsa_switch_event(struct notifier_block *nb,
index df14815a3b8ce74aeb613458ffaf5f6eee4a263d..a7dd088d5fc96da259813cae48c374527c9e251e 100644 (file)
@@ -176,6 +176,7 @@ EXPORT_SYMBOL(__ip_dev_find);
 static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32);
 
 static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
+static BLOCKING_NOTIFIER_HEAD(inetaddr_validator_chain);
 static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
                         int destroy);
 #ifdef CONFIG_SYSCTL
@@ -441,6 +442,8 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
 {
        struct in_device *in_dev = ifa->ifa_dev;
        struct in_ifaddr *ifa1, **ifap, **last_primary;
+       struct in_validator_info ivi;
+       int ret;
 
        ASSERT_RTNL();
 
@@ -471,6 +474,23 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
                }
        }
 
+       /* Allow any devices that wish to register ifaddr validtors to weigh
+        * in now, before changes are committed.  The rntl lock is serializing
+        * access here, so the state should not change between a validator call
+        * and a final notify on commit.  This isn't invoked on promotion under
+        * the assumption that validators are checking the address itself, and
+        * not the flags.
+        */
+       ivi.ivi_addr = ifa->ifa_address;
+       ivi.ivi_dev = ifa->ifa_dev;
+       ret = blocking_notifier_call_chain(&inetaddr_validator_chain,
+                                          NETDEV_UP, &ivi);
+       ret = notifier_to_errno(ret);
+       if (ret) {
+               inet_free_ifa(ifa);
+               return ret;
+       }
+
        if (!(ifa->ifa_flags & IFA_F_SECONDARY)) {
                prandom_seed((__force u32) ifa->ifa_local);
                ifap = last_primary;
@@ -1356,6 +1376,19 @@ int unregister_inetaddr_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_inetaddr_notifier);
 
+int register_inetaddr_validator_notifier(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_register(&inetaddr_validator_chain, nb);
+}
+EXPORT_SYMBOL(register_inetaddr_validator_notifier);
+
+int unregister_inetaddr_validator_notifier(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_unregister(&inetaddr_validator_chain,
+           nb);
+}
+EXPORT_SYMBOL(unregister_inetaddr_validator_notifier);
+
 /* Rename ifa_labels for a device name change. Make some effort to preserve
  * existing alias numbering and to create unique labels if possible.
 */
index 551de4d023a8edbf74835b43cb32d9173eedae36..9374b99c7c172435ebe0c442be244b489395241d 100644 (file)
@@ -2528,6 +2528,129 @@ static int ipmr_rtm_route(struct sk_buff *skb, struct nlmsghdr *nlh,
                return ipmr_mfc_delete(tbl, &mfcc, parent);
 }
 
+static bool ipmr_fill_table(struct mr_table *mrt, struct sk_buff *skb)
+{
+       u32 queue_len = atomic_read(&mrt->cache_resolve_queue_len);
+
+       if (nla_put_u32(skb, IPMRA_TABLE_ID, mrt->id) ||
+           nla_put_u32(skb, IPMRA_TABLE_CACHE_RES_QUEUE_LEN, queue_len) ||
+           nla_put_s32(skb, IPMRA_TABLE_MROUTE_REG_VIF_NUM,
+                       mrt->mroute_reg_vif_num) ||
+           nla_put_u8(skb, IPMRA_TABLE_MROUTE_DO_ASSERT,
+                      mrt->mroute_do_assert) ||
+           nla_put_u8(skb, IPMRA_TABLE_MROUTE_DO_PIM, mrt->mroute_do_pim))
+               return false;
+
+       return true;
+}
+
+static bool ipmr_fill_vif(struct mr_table *mrt, u32 vifid, struct sk_buff *skb)
+{
+       struct nlattr *vif_nest;
+       struct vif_device *vif;
+
+       /* if the VIF doesn't exist just continue */
+       if (!VIF_EXISTS(mrt, vifid))
+               return true;
+
+       vif = &mrt->vif_table[vifid];
+       vif_nest = nla_nest_start(skb, IPMRA_VIF);
+       if (!vif_nest)
+               return false;
+       if (nla_put_u32(skb, IPMRA_VIFA_IFINDEX, vif->dev->ifindex) ||
+           nla_put_u32(skb, IPMRA_VIFA_VIF_ID, vifid) ||
+           nla_put_u16(skb, IPMRA_VIFA_FLAGS, vif->flags) ||
+           nla_put_u64_64bit(skb, IPMRA_VIFA_BYTES_IN, vif->bytes_in,
+                             IPMRA_VIFA_PAD) ||
+           nla_put_u64_64bit(skb, IPMRA_VIFA_BYTES_OUT, vif->bytes_out,
+                             IPMRA_VIFA_PAD) ||
+           nla_put_u64_64bit(skb, IPMRA_VIFA_PACKETS_IN, vif->pkt_in,
+                             IPMRA_VIFA_PAD) ||
+           nla_put_u64_64bit(skb, IPMRA_VIFA_PACKETS_OUT, vif->pkt_out,
+                             IPMRA_VIFA_PAD) ||
+           nla_put_be32(skb, IPMRA_VIFA_LOCAL_ADDR, vif->local) ||
+           nla_put_be32(skb, IPMRA_VIFA_REMOTE_ADDR, vif->remote)) {
+               nla_nest_cancel(skb, vif_nest);
+               return false;
+       }
+       nla_nest_end(skb, vif_nest);
+
+       return true;
+}
+
+static int ipmr_rtm_dumplink(struct sk_buff *skb, struct netlink_callback *cb)
+{
+       struct net *net = sock_net(skb->sk);
+       struct nlmsghdr *nlh = NULL;
+       unsigned int t = 0, s_t;
+       unsigned int e = 0, s_e;
+       struct mr_table *mrt;
+
+       s_t = cb->args[0];
+       s_e = cb->args[1];
+
+       ipmr_for_each_table(mrt, net) {
+               struct nlattr *vifs, *af;
+               struct ifinfomsg *hdr;
+               u32 i;
+
+               if (t < s_t)
+                       goto skip_table;
+               nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid,
+                               cb->nlh->nlmsg_seq, RTM_NEWLINK,
+                               sizeof(*hdr), NLM_F_MULTI);
+               if (!nlh)
+                       break;
+
+               hdr = nlmsg_data(nlh);
+               memset(hdr, 0, sizeof(*hdr));
+               hdr->ifi_family = RTNL_FAMILY_IPMR;
+
+               af = nla_nest_start(skb, IFLA_AF_SPEC);
+               if (!af) {
+                       nlmsg_cancel(skb, nlh);
+                       goto out;
+               }
+
+               if (!ipmr_fill_table(mrt, skb)) {
+                       nlmsg_cancel(skb, nlh);
+                       goto out;
+               }
+
+               vifs = nla_nest_start(skb, IPMRA_TABLE_VIFS);
+               if (!vifs) {
+                       nla_nest_end(skb, af);
+                       nlmsg_end(skb, nlh);
+                       goto out;
+               }
+               for (i = 0; i < mrt->maxvif; i++) {
+                       if (e < s_e)
+                               goto skip_entry;
+                       if (!ipmr_fill_vif(mrt, i, skb)) {
+                               nla_nest_end(skb, vifs);
+                               nla_nest_end(skb, af);
+                               nlmsg_end(skb, nlh);
+                               goto out;
+                       }
+skip_entry:
+                       e++;
+               }
+               s_e = 0;
+               e = 0;
+               nla_nest_end(skb, vifs);
+               nla_nest_end(skb, af);
+               nlmsg_end(skb, nlh);
+skip_table:
+               t++;
+       }
+
+out:
+       cb->args[1] = e;
+       cb->args[0] = t;
+
+       return skb->len;
+}
+
 #ifdef CONFIG_PROC_FS
 /* The /proc interfaces to multicast routing :
  * /proc/net/ip_mr_cache & /proc/net/ip_mr_vif
@@ -2870,6 +2993,9 @@ int __init ip_mr_init(void)
                      ipmr_rtm_route, NULL, NULL);
        rtnl_register(RTNL_FAMILY_IPMR, RTM_DELROUTE,
                      ipmr_rtm_route, NULL, NULL);
+
+       rtnl_register(RTNL_FAMILY_IPMR, RTM_GETLINK,
+                     NULL, ipmr_rtm_dumplink, NULL);
        return 0;
 
 #ifdef CONFIG_IP_PIMSM_V2
index fa44e752a9a3f8eb9957314149ae15e6df10465a..43eb6567b3a0a2add9a1d36019eae5b6d5caf657 100644 (file)
@@ -250,6 +250,7 @@ static const struct snmp_mib snmp4_net_list[] = {
        SNMP_MIB_ITEM("TCPAbortOnLinger", LINUX_MIB_TCPABORTONLINGER),
        SNMP_MIB_ITEM("TCPAbortFailed", LINUX_MIB_TCPABORTFAILED),
        SNMP_MIB_ITEM("TCPMemoryPressures", LINUX_MIB_TCPMEMORYPRESSURES),
+       SNMP_MIB_ITEM("TCPMemoryPressuresChrono", LINUX_MIB_TCPMEMORYPRESSURESCHRONO),
        SNMP_MIB_ITEM("TCPSACKDiscard", LINUX_MIB_TCPSACKDISCARD),
        SNMP_MIB_ITEM("TCPDSACKIgnoredOld", LINUX_MIB_TCPDSACKIGNOREDOLD),
        SNMP_MIB_ITEM("TCPDSACKIgnoredNoUndo", LINUX_MIB_TCPDSACKIGNOREDNOUNDO),
index 6426250a58ea1afb29b673c00bb9d58bd3d21122..7835bb4a1fab2b335c65001cc3c9233ffb4fd5cc 100644 (file)
@@ -232,7 +232,8 @@ EXPORT_SYMBOL(tcp_get_cookie_sock);
  * return false if we decode a tcp option that is disabled
  * on the host.
  */
-bool cookie_timestamp_decode(struct tcp_options_received *tcp_opt)
+bool cookie_timestamp_decode(const struct net *net,
+                            struct tcp_options_received *tcp_opt)
 {
        /* echoed timestamp, lowest bits contain options */
        u32 options = tcp_opt->rcv_tsecr;
@@ -242,12 +243,12 @@ bool cookie_timestamp_decode(struct tcp_options_received *tcp_opt)
                return true;
        }
 
-       if (!sysctl_tcp_timestamps)
+       if (!net->ipv4.sysctl_tcp_timestamps)
                return false;
 
        tcp_opt->sack_ok = (options & TS_OPT_SACK) ? TCP_SACK_SEEN : 0;
 
-       if (tcp_opt->sack_ok && !sysctl_tcp_sack)
+       if (tcp_opt->sack_ok && !net->ipv4.sysctl_tcp_sack)
                return false;
 
        if ((options & TS_OPT_WSCALE_MASK) == TS_OPT_WSCALE_MASK)
@@ -256,7 +257,7 @@ bool cookie_timestamp_decode(struct tcp_options_received *tcp_opt)
        tcp_opt->wscale_ok = 1;
        tcp_opt->snd_wscale = options & TS_OPT_WSCALE_MASK;
 
-       return sysctl_tcp_window_scaling != 0;
+       return net->ipv4.sysctl_tcp_window_scaling != 0;
 }
 EXPORT_SYMBOL(cookie_timestamp_decode);
 
@@ -312,14 +313,16 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
 
        /* check for timestamp cookie support */
        memset(&tcp_opt, 0, sizeof(tcp_opt));
-       tcp_parse_options(skb, &tcp_opt, 0, NULL);
+       tcp_parse_options(sock_net(sk), skb, &tcp_opt, 0, NULL);
 
        if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) {
-               tsoff = secure_tcp_ts_off(ip_hdr(skb)->daddr, ip_hdr(skb)->saddr);
+               tsoff = secure_tcp_ts_off(sock_net(sk),
+                                         ip_hdr(skb)->daddr,
+                                         ip_hdr(skb)->saddr);
                tcp_opt.rcv_tsecr -= tsoff;
        }
 
-       if (!cookie_timestamp_decode(&tcp_opt))
+       if (!cookie_timestamp_decode(sock_net(sk), &tcp_opt))
                goto out;
 
        ret = NULL;
index 86957e9cd6c6748ac00aa0307154bb131c43f1da..7065234a89a50ae977f2de1c2ec7ca867ac2e6e2 100644 (file)
@@ -364,27 +364,6 @@ static int proc_tfo_blackhole_detect_timeout(struct ctl_table *table,
 }
 
 static struct ctl_table ipv4_table[] = {
-       {
-               .procname       = "tcp_timestamps",
-               .data           = &sysctl_tcp_timestamps,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec
-       },
-       {
-               .procname       = "tcp_window_scaling",
-               .data           = &sysctl_tcp_window_scaling,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec
-       },
-       {
-               .procname       = "tcp_sack",
-               .data           = &sysctl_tcp_sack,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec
-       },
        {
                .procname       = "tcp_retrans_collapse",
                .data           = &sysctl_tcp_retrans_collapse,
@@ -1116,6 +1095,27 @@ static struct ctl_table ipv4_net_table[] = {
                .extra2         = &one,
        },
 #endif
+       {
+               .procname       = "tcp_sack",
+               .data           = &init_net.ipv4.sysctl_tcp_sack,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec
+       },
+       {
+               .procname       = "tcp_window_scaling",
+               .data           = &init_net.ipv4.sysctl_tcp_window_scaling,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec
+       },
+       {
+               .procname       = "tcp_timestamps",
+               .data           = &init_net.ipv4.sysctl_tcp_timestamps,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec
+       },
        { }
 };
 
index 87981fcdfcf20c6846ea3474dce1e640aea6e092..cc8fd8b747a47e9b66492ecdf27256ef6d879877 100644 (file)
@@ -320,17 +320,36 @@ struct tcp_splice_state {
  * All the __sk_mem_schedule() is of this nature: accounting
  * is strict, actions are advisory and have some latency.
  */
-int tcp_memory_pressure __read_mostly;
-EXPORT_SYMBOL(tcp_memory_pressure);
+unsigned long tcp_memory_pressure __read_mostly;
+EXPORT_SYMBOL_GPL(tcp_memory_pressure);
 
 void tcp_enter_memory_pressure(struct sock *sk)
 {
-       if (!tcp_memory_pressure) {
+       unsigned long val;
+
+       if (tcp_memory_pressure)
+               return;
+       val = jiffies;
+
+       if (!val)
+               val--;
+       if (!cmpxchg(&tcp_memory_pressure, 0, val))
                NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMEMORYPRESSURES);
-               tcp_memory_pressure = 1;
-       }
 }
-EXPORT_SYMBOL(tcp_enter_memory_pressure);
+EXPORT_SYMBOL_GPL(tcp_enter_memory_pressure);
+
+void tcp_leave_memory_pressure(struct sock *sk)
+{
+       unsigned long val;
+
+       if (!tcp_memory_pressure)
+               return;
+       val = xchg(&tcp_memory_pressure, 0);
+       if (val)
+               NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPMEMORYPRESSURESCHRONO,
+                             jiffies_to_msecs(jiffies - val));
+}
+EXPORT_SYMBOL_GPL(tcp_leave_memory_pressure);
 
 /* Convert seconds to retransmits based on initial and max timeout */
 static u8 secs_to_retrans(int seconds, int timeout, int rto_max)
index 4ea8ec5c7bb410834d1c54e0159467ae08d4cd15..2ab7e2fa9bb9727a6d22552f851d6254ea074481 100644 (file)
@@ -76,9 +76,6 @@
 #include <asm/unaligned.h>
 #include <linux/errqueue.h>
 
-int sysctl_tcp_timestamps __read_mostly = 1;
-int sysctl_tcp_window_scaling __read_mostly = 1;
-int sysctl_tcp_sack __read_mostly = 1;
 int sysctl_tcp_fack __read_mostly;
 int sysctl_tcp_max_reordering __read_mostly = 300;
 int sysctl_tcp_dsack __read_mostly = 1;
@@ -3724,7 +3721,8 @@ static void tcp_parse_fastopen_option(int len, const unsigned char *cookie,
  * But, this can also be called on packets in the established flow when
  * the fast version below fails.
  */
-void tcp_parse_options(const struct sk_buff *skb,
+void tcp_parse_options(const struct net *net,
+                      const struct sk_buff *skb,
                       struct tcp_options_received *opt_rx, int estab,
                       struct tcp_fastopen_cookie *foc)
 {
@@ -3765,7 +3763,7 @@ void tcp_parse_options(const struct sk_buff *skb,
                                break;
                        case TCPOPT_WINDOW:
                                if (opsize == TCPOLEN_WINDOW && th->syn &&
-                                   !estab && sysctl_tcp_window_scaling) {
+                                   !estab && net->ipv4.sysctl_tcp_window_scaling) {
                                        __u8 snd_wscale = *(__u8 *)ptr;
                                        opt_rx->wscale_ok = 1;
                                        if (snd_wscale > TCP_MAX_WSCALE) {
@@ -3781,7 +3779,7 @@ void tcp_parse_options(const struct sk_buff *skb,
                        case TCPOPT_TIMESTAMP:
                                if ((opsize == TCPOLEN_TIMESTAMP) &&
                                    ((estab && opt_rx->tstamp_ok) ||
-                                    (!estab && sysctl_tcp_timestamps))) {
+                                    (!estab && net->ipv4.sysctl_tcp_timestamps))) {
                                        opt_rx->saw_tstamp = 1;
                                        opt_rx->rcv_tsval = get_unaligned_be32(ptr);
                                        opt_rx->rcv_tsecr = get_unaligned_be32(ptr + 4);
@@ -3789,7 +3787,7 @@ void tcp_parse_options(const struct sk_buff *skb,
                                break;
                        case TCPOPT_SACK_PERM:
                                if (opsize == TCPOLEN_SACK_PERM && th->syn &&
-                                   !estab && sysctl_tcp_sack) {
+                                   !estab && net->ipv4.sysctl_tcp_sack) {
                                        opt_rx->sack_ok = TCP_SACK_SEEN;
                                        tcp_sack_reset(opt_rx);
                                }
@@ -3858,7 +3856,8 @@ static bool tcp_parse_aligned_timestamp(struct tcp_sock *tp, const struct tcphdr
 /* Fast parse options. This hopes to only see timestamps.
  * If it is wrong it falls back on tcp_parse_options().
  */
-static bool tcp_fast_parse_options(const struct sk_buff *skb,
+static bool tcp_fast_parse_options(const struct net *net,
+                                  const struct sk_buff *skb,
                                   const struct tcphdr *th, struct tcp_sock *tp)
 {
        /* In the spirit of fast parsing, compare doff directly to constant
@@ -3873,7 +3872,7 @@ static bool tcp_fast_parse_options(const struct sk_buff *skb,
                        return true;
        }
 
-       tcp_parse_options(skb, &tp->rx_opt, 1, NULL);
+       tcp_parse_options(net, skb, &tp->rx_opt, 1, NULL);
        if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
                tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 
@@ -5234,7 +5233,8 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
        bool rst_seq_match = false;
 
        /* RFC1323: H1. Apply PAWS check first. */
-       if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp &&
+       if (tcp_fast_parse_options(sock_net(sk), skb, th, tp) &&
+           tp->rx_opt.saw_tstamp &&
            tcp_paws_discard(sk, skb)) {
                if (!th->rst) {
                        NET_INC_STATS(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED);
@@ -5605,7 +5605,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
                /* Get original SYNACK MSS value if user MSS sets mss_clamp */
                tcp_clear_options(&opt);
                opt.user_mss = opt.mss_clamp = 0;
-               tcp_parse_options(synack, &opt, 0, NULL);
+               tcp_parse_options(sock_net(sk), synack, &opt, 0, NULL);
                mss = opt.mss_clamp;
        }
 
@@ -5659,7 +5659,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
        int saved_clamp = tp->rx_opt.mss_clamp;
        bool fastopen_fail;
 
-       tcp_parse_options(skb, &tp->rx_opt, 0, &foc);
+       tcp_parse_options(sock_net(sk), skb, &tp->rx_opt, 0, &foc);
        if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
                tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 
@@ -6332,7 +6332,8 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
        tcp_clear_options(&tmp_opt);
        tmp_opt.mss_clamp = af_ops->mss_clamp;
        tmp_opt.user_mss  = tp->rx_opt.user_mss;
-       tcp_parse_options(skb, &tmp_opt, 0, want_cookie ? NULL : &foc);
+       tcp_parse_options(sock_net(sk), skb, &tmp_opt, 0,
+                         want_cookie ? NULL : &foc);
 
        if (want_cookie && !tmp_opt.saw_tstamp)
                tcp_clear_options(&tmp_opt);
@@ -6350,7 +6351,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
                goto drop_and_free;
 
        if (tmp_opt.tstamp_ok)
-               tcp_rsk(req)->ts_off = af_ops->init_ts_off(skb);
+               tcp_rsk(req)->ts_off = af_ops->init_ts_off(net, skb);
 
        if (!want_cookie && !isn) {
                /* Kill the following clause, if you dislike this way. */
index 191b2f78b19d2c8d62c59cc046bd608687679619..1dc8c449e16a5d5c0ed52708d1c88b669d55d6a8 100644 (file)
@@ -102,10 +102,9 @@ static u32 tcp_v4_init_seq(const struct sk_buff *skb)
                              tcp_hdr(skb)->source);
 }
 
-static u32 tcp_v4_init_ts_off(const struct sk_buff *skb)
+static u32 tcp_v4_init_ts_off(const struct net *net, const struct sk_buff *skb)
 {
-       return secure_tcp_ts_off(ip_hdr(skb)->daddr,
-                                ip_hdr(skb)->saddr);
+       return secure_tcp_ts_off(net, ip_hdr(skb)->daddr, ip_hdr(skb)->saddr);
 }
 
 int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
@@ -242,7 +241,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                                                       inet->inet_daddr,
                                                       inet->inet_sport,
                                                       usin->sin_port);
-               tp->tsoffset = secure_tcp_ts_off(inet->inet_saddr,
+               tp->tsoffset = secure_tcp_ts_off(sock_net(sk),
+                                                inet->inet_saddr,
                                                 inet->inet_daddr);
        }
 
@@ -2387,6 +2387,7 @@ struct proto tcp_prot = {
        .unhash                 = inet_unhash,
        .get_port               = inet_csk_get_port,
        .enter_memory_pressure  = tcp_enter_memory_pressure,
+       .leave_memory_pressure  = tcp_leave_memory_pressure,
        .stream_memory_free     = tcp_stream_memory_free,
        .sockets_allocated      = &tcp_sockets_allocated,
        .orphan_count           = &tcp_orphan_count,
@@ -2465,6 +2466,9 @@ static int __net_init tcp_sk_init(struct net *net)
        net->ipv4.tcp_death_row.hashinfo = &tcp_hashinfo;
 
        net->ipv4.sysctl_max_syn_backlog = max(128, cnt / 256);
+       net->ipv4.sysctl_tcp_sack = 1;
+       net->ipv4.sysctl_tcp_window_scaling = 1;
+       net->ipv4.sysctl_tcp_timestamps = 1;
 
        return 0;
 fail:
index d0642df7304452b57d2bc7f92a0a0c6d821553d3..d30ee31e94ebd4d76a0f2bd910f213bb994770f3 100644 (file)
@@ -98,7 +98,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
 
        tmp_opt.saw_tstamp = 0;
        if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) {
-               tcp_parse_options(skb, &tmp_opt, 0, NULL);
+               tcp_parse_options(twsk_net(tw), skb, &tmp_opt, 0, NULL);
 
                if (tmp_opt.saw_tstamp) {
                        if (tmp_opt.rcv_tsecr)
@@ -559,7 +559,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 
        tmp_opt.saw_tstamp = 0;
        if (th->doff > (sizeof(struct tcphdr)>>2)) {
-               tcp_parse_options(skb, &tmp_opt, 0, NULL);
+               tcp_parse_options(sock_net(sk), skb, &tmp_opt, 0, NULL);
 
                if (tmp_opt.saw_tstamp) {
                        tmp_opt.ts_recent = req->ts_recent;
index e3aab1c1cf78d7b5696fc1438fe54f8ce448c09e..9a9c395b62352513a42b3353434be8134ac9cdd7 100644 (file)
@@ -569,18 +569,18 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
        opts->mss = tcp_advertise_mss(sk);
        remaining -= TCPOLEN_MSS_ALIGNED;
 
-       if (likely(sysctl_tcp_timestamps && !*md5)) {
+       if (likely(sock_net(sk)->ipv4.sysctl_tcp_timestamps && !*md5)) {
                opts->options |= OPTION_TS;
                opts->tsval = tcp_skb_timestamp(skb) + tp->tsoffset;
                opts->tsecr = tp->rx_opt.ts_recent;
                remaining -= TCPOLEN_TSTAMP_ALIGNED;
        }
-       if (likely(sysctl_tcp_window_scaling)) {
+       if (likely(sock_net(sk)->ipv4.sysctl_tcp_window_scaling)) {
                opts->ws = tp->rx_opt.rcv_wscale;
                opts->options |= OPTION_WSCALE;
                remaining -= TCPOLEN_WSCALE_ALIGNED;
        }
-       if (likely(sysctl_tcp_sack)) {
+       if (likely(sock_net(sk)->ipv4.sysctl_tcp_sack)) {
                opts->options |= OPTION_SACK_ADVERTISE;
                if (unlikely(!(OPTION_TS & opts->options)))
                        remaining -= TCPOLEN_SACKPERM_ALIGNED;
@@ -3271,8 +3271,9 @@ static void tcp_connect_init(struct sock *sk)
        /* We'll fix this up when we get a response from the other end.
         * See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT.
         */
-       tp->tcp_header_len = sizeof(struct tcphdr) +
-               (sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0);
+       tp->tcp_header_len = sizeof(struct tcphdr);
+       if (sock_net(sk)->ipv4.sysctl_tcp_timestamps)
+               tp->tcp_header_len += TCPOLEN_TSTAMP_ALIGNED;
 
 #ifdef CONFIG_TCP_MD5SIG
        if (tp->af_specific->md5_lookup(sk, sk))
@@ -3303,7 +3304,7 @@ static void tcp_connect_init(struct sock *sk)
                                  tp->advmss - (tp->rx_opt.ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
                                  &tp->rcv_wnd,
                                  &tp->window_clamp,
-                                 sysctl_tcp_window_scaling,
+                                 sock_net(sk)->ipv4.sysctl_tcp_window_scaling,
                                  &rcv_wscale,
                                  dst_metric(dst, RTAX_INITRWND));
 
index fdcb7437cc1541d87dcf5bb2c861077473901499..2bc638c48b8616bc3574ec649bd7df36e9faba39 100644 (file)
@@ -1163,6 +1163,83 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset,
        return ret;
 }
 
+/* Copy as much information as possible into skb->dev_scratch to avoid
+ * possibly multiple cache miss on dequeue();
+ */
+#if BITS_PER_LONG == 64
+
+/* we can store multiple info here: truesize, len and the bit needed to
+ * compute skb_csum_unnecessary will be on cold cache lines at recvmsg
+ * time.
+ * skb->len can be stored on 16 bits since the udp header has been already
+ * validated and pulled.
+ */
+struct udp_dev_scratch {
+       u32 truesize;
+       u16 len;
+       bool is_linear;
+       bool csum_unnecessary;
+};
+
+static void udp_set_dev_scratch(struct sk_buff *skb)
+{
+       struct udp_dev_scratch *scratch;
+
+       BUILD_BUG_ON(sizeof(struct udp_dev_scratch) > sizeof(long));
+       scratch = (struct udp_dev_scratch *)&skb->dev_scratch;
+       scratch->truesize = skb->truesize;
+       scratch->len = skb->len;
+       scratch->csum_unnecessary = !!skb_csum_unnecessary(skb);
+       scratch->is_linear = !skb_is_nonlinear(skb);
+}
+
+static int udp_skb_truesize(struct sk_buff *skb)
+{
+       return ((struct udp_dev_scratch *)&skb->dev_scratch)->truesize;
+}
+
+static unsigned int udp_skb_len(struct sk_buff *skb)
+{
+       return ((struct udp_dev_scratch *)&skb->dev_scratch)->len;
+}
+
+static bool udp_skb_csum_unnecessary(struct sk_buff *skb)
+{
+       return ((struct udp_dev_scratch *)&skb->dev_scratch)->csum_unnecessary;
+}
+
+static bool udp_skb_is_linear(struct sk_buff *skb)
+{
+       return ((struct udp_dev_scratch *)&skb->dev_scratch)->is_linear;
+}
+
+#else
+static void udp_set_dev_scratch(struct sk_buff *skb)
+{
+       skb->dev_scratch = skb->truesize;
+}
+
+static int udp_skb_truesize(struct sk_buff *skb)
+{
+       return skb->dev_scratch;
+}
+
+static unsigned int udp_skb_len(struct sk_buff *skb)
+{
+       return skb->len;
+}
+
+static bool udp_skb_csum_unnecessary(struct sk_buff *skb)
+{
+       return skb_csum_unnecessary(skb);
+}
+
+static bool udp_skb_is_linear(struct sk_buff *skb)
+{
+       return !skb_is_nonlinear(skb);
+}
+#endif
+
 /* fully reclaim rmem/fwd memory allocated for skb */
 static void udp_rmem_release(struct sock *sk, int size, int partial,
                             bool rx_queue_lock_held)
@@ -1213,14 +1290,16 @@ static void udp_rmem_release(struct sock *sk, int size, int partial,
  */
 void udp_skb_destructor(struct sock *sk, struct sk_buff *skb)
 {
-       udp_rmem_release(sk, skb->dev_scratch, 1, false);
+       prefetch(&skb->data);
+       udp_rmem_release(sk, udp_skb_truesize(skb), 1, false);
 }
 EXPORT_SYMBOL(udp_skb_destructor);
 
 /* as above, but the caller held the rx queue lock, too */
 static void udp_skb_dtor_locked(struct sock *sk, struct sk_buff *skb)
 {
-       udp_rmem_release(sk, skb->dev_scratch, 1, true);
+       prefetch(&skb->data);
+       udp_rmem_release(sk, udp_skb_truesize(skb), 1, true);
 }
 
 /* Idea of busylocks is to let producers grab an extra spinlock
@@ -1274,10 +1353,7 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
                busy = busylock_acquire(sk);
        }
        size = skb->truesize;
-       /* Copy skb->truesize into skb->dev_scratch to avoid a cache line miss
-        * in udp_skb_destructor()
-        */
-       skb->dev_scratch = size;
+       udp_set_dev_scratch(skb);
 
        /* we drop only if the receive buf is full and the receive
         * queue contains some other skb
@@ -1359,7 +1435,8 @@ void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len)
                sk_peek_offset_bwd(sk, len);
                unlock_sock_fast(sk, slow);
        }
-       consume_skb(skb);
+
+       consume_stateless_skb(skb);
 }
 EXPORT_SYMBOL_GPL(skb_consume_udp);
 
@@ -1514,6 +1591,18 @@ struct sk_buff *__skb_recv_udp(struct sock *sk, unsigned int flags,
 }
 EXPORT_SYMBOL_GPL(__skb_recv_udp);
 
+static int copy_linear_skb(struct sk_buff *skb, int len, int off,
+                          struct iov_iter *to)
+{
+       int n, copy = len - off;
+
+       n = copy_to_iter(skb->data + off, copy, to);
+       if (n == copy)
+               return 0;
+
+       return -EFAULT;
+}
+
 /*
  *     This should be easy, if there is something there we
  *     return it, otherwise we block.
@@ -1540,7 +1629,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
        if (!skb)
                return err;
 
-       ulen = skb->len;
+       ulen = udp_skb_len(skb);
        copied = len;
        if (copied > ulen - off)
                copied = ulen - off;
@@ -1555,14 +1644,18 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
 
        if (copied < ulen || peeking ||
            (is_udplite && UDP_SKB_CB(skb)->partial_cov)) {
-               checksum_valid = !udp_lib_checksum_complete(skb);
+               checksum_valid = udp_skb_csum_unnecessary(skb) ||
+                               !__udp_lib_checksum_complete(skb);
                if (!checksum_valid)
                        goto csum_copy_err;
        }
 
-       if (checksum_valid || skb_csum_unnecessary(skb))
-               err = skb_copy_datagram_msg(skb, off, msg, copied);
-       else {
+       if (checksum_valid || udp_skb_csum_unnecessary(skb)) {
+               if (udp_skb_is_linear(skb))
+                       err = copy_linear_skb(skb, copied, off, &msg->msg_iter);
+               else
+                       err = skb_copy_datagram_msg(skb, off, msg, copied);
+       } else {
                err = skb_copy_and_csum_datagram_msg(skb, off, msg);
 
                if (err == -EINVAL)
@@ -1739,6 +1832,9 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                sk_mark_napi_id_once(sk, skb);
        }
 
+       /* clear all pending head states while they are hot in the cache */
+       skb_release_head_state(skb);
+
        rc = __udp_enqueue_schedule_skb(sk, skb);
        if (rc < 0) {
                int is_udplite = IS_UDPLITE(sk);
index 25443fd946a80f16e627e8ad60f466e60a6ccadf..0aa36b09301305a41daea121b52f0e050d8e9cd5 100644 (file)
@@ -963,6 +963,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
        struct net *net = dev_net(idev->dev);
        struct inet6_ifaddr *ifa = NULL;
        struct rt6_info *rt;
+       struct in6_validator_info i6vi;
        unsigned int hash;
        int err = 0;
        int addr_type = ipv6_addr_type(addr);
@@ -974,6 +975,9 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
                return ERR_PTR(-EADDRNOTAVAIL);
 
        rcu_read_lock_bh();
+
+       in6_dev_hold(idev);
+
        if (idev->dead) {
                err = -ENODEV;                  /*XXX*/
                goto out2;
@@ -984,6 +988,17 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
                goto out2;
        }
 
+       i6vi.i6vi_addr = *addr;
+       i6vi.i6vi_dev = idev;
+       rcu_read_unlock_bh();
+
+       err = inet6addr_validator_notifier_call_chain(NETDEV_UP, &i6vi);
+
+       rcu_read_lock_bh();
+       err = notifier_to_errno(err);
+       if (err)
+               goto out2;
+
        spin_lock(&addrconf_hash_lock);
 
        /* Ignore adding duplicate addresses on an interface */
@@ -1034,7 +1049,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
        ifa->rt = rt;
 
        ifa->idev = idev;
-       in6_dev_hold(idev);
        /* For caller */
        in6_ifa_hold(ifa);
 
@@ -1062,6 +1076,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
                inet6addr_notifier_call_chain(NETDEV_UP, ifa);
        else {
                kfree(ifa);
+               in6_dev_put(idev);
                ifa = ERR_PTR(err);
        }
 
index bfa941fc1165002903b5a0364e5584b075469e2e..9e3488d50b157eb8ee7f9be44370176c157a1c62 100644 (file)
@@ -88,6 +88,7 @@ int __ipv6_addr_type(const struct in6_addr *addr)
 EXPORT_SYMBOL(__ipv6_addr_type);
 
 static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
+static ATOMIC_NOTIFIER_HEAD(inet6addr_validator_chain);
 
 int register_inet6addr_notifier(struct notifier_block *nb)
 {
@@ -107,6 +108,24 @@ int inet6addr_notifier_call_chain(unsigned long val, void *v)
 }
 EXPORT_SYMBOL(inet6addr_notifier_call_chain);
 
+int register_inet6addr_validator_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_register(&inet6addr_validator_chain, nb);
+}
+EXPORT_SYMBOL(register_inet6addr_validator_notifier);
+
+int unregister_inet6addr_validator_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_unregister(&inet6addr_validator_chain, nb);
+}
+EXPORT_SYMBOL(unregister_inet6addr_validator_notifier);
+
+int inet6addr_validator_notifier_call_chain(unsigned long val, void *v)
+{
+       return atomic_notifier_call_chain(&inet6addr_validator_chain, val, v);
+}
+EXPORT_SYMBOL(inet6addr_validator_notifier_call_chain);
+
 static int eafnosupport_ipv6_dst_lookup(struct net *net, struct sock *u1,
                                        struct dst_entry **u2,
                                        struct flowi6 *u3)
index bf8a58a1c32d83a9605844075da5815be23a6bf1..0d6f3b6345de26c329ae1d6f25dde652a5452d4b 100644 (file)
@@ -67,9 +67,6 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
        struct in6_addr *nexthop;
        int ret;
 
-       skb->protocol = htons(ETH_P_IPV6);
-       skb->dev = dev;
-
        if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
                struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
 
@@ -154,6 +151,9 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
        struct net_device *dev = skb_dst(skb)->dev;
        struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
 
+       skb->protocol = htons(ETH_P_IPV6);
+       skb->dev = dev;
+
        if (unlikely(idev->cnf.disable_ipv6)) {
                IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
                kfree_skb(skb);
@@ -869,7 +869,6 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
        if (skb->sk && dst_allfrag(skb_dst(skb)))
                sk_nocaps_add(skb->sk, NETIF_F_GSO_MASK);
 
-       skb->dev = skb_dst(skb)->dev;
        icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
        err = -EMSGSIZE;
 
index 971823359f5b98da46c39b86c9ddcefd14df8559..2f7e99af67dbfd2324d39086881b9475045d7e1f 100644 (file)
@@ -162,15 +162,16 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 
        /* check for timestamp cookie support */
        memset(&tcp_opt, 0, sizeof(tcp_opt));
-       tcp_parse_options(skb, &tcp_opt, 0, NULL);
+       tcp_parse_options(sock_net(sk), skb, &tcp_opt, 0, NULL);
 
        if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) {
-               tsoff = secure_tcpv6_ts_off(ipv6_hdr(skb)->daddr.s6_addr32,
+               tsoff = secure_tcpv6_ts_off(sock_net(sk),
+                                           ipv6_hdr(skb)->daddr.s6_addr32,
                                            ipv6_hdr(skb)->saddr.s6_addr32);
                tcp_opt.rcv_tsecr -= tsoff;
        }
 
-       if (!cookie_timestamp_decode(&tcp_opt))
+       if (!cookie_timestamp_decode(sock_net(sk), &tcp_opt))
                goto out;
 
        ret = NULL;
index 233edfabe1dbceaeb6cdd42a2bb379072aeee361..84ad50218255dd64109c9cf834a8cff46a8ae45f 100644 (file)
@@ -109,9 +109,9 @@ static u32 tcp_v6_init_seq(const struct sk_buff *skb)
                                tcp_hdr(skb)->source);
 }
 
-static u32 tcp_v6_init_ts_off(const struct sk_buff *skb)
+static u32 tcp_v6_init_ts_off(const struct net *net, const struct sk_buff *skb)
 {
-       return secure_tcpv6_ts_off(ipv6_hdr(skb)->daddr.s6_addr32,
+       return secure_tcpv6_ts_off(net, ipv6_hdr(skb)->daddr.s6_addr32,
                                   ipv6_hdr(skb)->saddr.s6_addr32);
 }
 
@@ -292,7 +292,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
                                                         sk->sk_v6_daddr.s6_addr32,
                                                         inet->inet_sport,
                                                         inet->inet_dport);
-               tp->tsoffset = secure_tcpv6_ts_off(np->saddr.s6_addr32,
+               tp->tsoffset = secure_tcpv6_ts_off(sock_net(sk),
+                                                  np->saddr.s6_addr32,
                                                   sk->sk_v6_daddr.s6_addr32);
        }
 
@@ -1248,9 +1249,6 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
        if (skb->protocol == htons(ETH_P_IP))
                return tcp_v4_do_rcv(sk, skb);
 
-       if (tcp_filter(sk, skb))
-               goto discard;
-
        /*
         *      socket locking is here for SMP purposes as backlog rcv
         *      is currently called with bh processing disabled.
@@ -1909,6 +1907,7 @@ struct proto tcpv6_prot = {
        .unhash                 = inet_unhash,
        .get_port               = inet_csk_get_port,
        .enter_memory_pressure  = tcp_enter_memory_pressure,
+       .leave_memory_pressure  = tcp_leave_memory_pressure,
        .stream_memory_free     = tcp_stream_memory_free,
        .sockets_allocated      = &tcp_sockets_allocated,
        .memory_allocated       = &tcp_memory_allocated,
index 82ca49fba33606d019f009b9f97c9370b2a0136a..f9349a495caf0aed6a1c5106d32551dd8e11ee8a 100644 (file)
@@ -188,7 +188,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
 #define BLOCK_PRIV(x)          ((void *)((char *)(x) + BLOCK_O2PRIV(x)))
 
 struct packet_sock;
-static int tpacket_snd(struct packet_sock *po, struct msghdr *msg);
 static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
                       struct packet_type *pt, struct net_device *orig_dev);
 
index a9a8c7d5a4a983b9be12fe85a7f71f3e6a825f19..c7a5d861906bb63d17ee4e1c8b9327f43e7dbede 100644 (file)
@@ -111,6 +111,9 @@ struct qrtr_node {
        struct list_head item;
 };
 
+static int qrtr_local_enqueue(struct qrtr_node *node, struct sk_buff *skb);
+static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb);
+
 /* Release node resources and free the node.
  *
  * Do not call directly, use qrtr_node_release.  To be used with
@@ -245,14 +248,11 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
 }
 EXPORT_SYMBOL_GPL(qrtr_endpoint_post);
 
-/* Allocate and construct a resume-tx packet. */
-static struct sk_buff *qrtr_alloc_resume_tx(u32 src_node,
-                                           u32 dst_node, u32 port)
+static struct sk_buff *qrtr_alloc_ctrl_packet(u32 type, size_t pkt_len,
+                                             u32 src_node, u32 dst_node)
 {
-       const int pkt_len = 20;
        struct qrtr_hdr *hdr;
        struct sk_buff *skb;
-       __le32 *buf;
 
        skb = alloc_skb(QRTR_HDR_SIZE + pkt_len, GFP_KERNEL);
        if (!skb)
@@ -261,7 +261,7 @@ static struct sk_buff *qrtr_alloc_resume_tx(u32 src_node,
 
        hdr = (struct qrtr_hdr *)skb_put(skb, QRTR_HDR_SIZE);
        hdr->version = cpu_to_le32(QRTR_PROTO_VER);
-       hdr->type = cpu_to_le32(QRTR_TYPE_RESUME_TX);
+       hdr->type = cpu_to_le32(type);
        hdr->src_node_id = cpu_to_le32(src_node);
        hdr->src_port_id = cpu_to_le32(QRTR_PORT_CTRL);
        hdr->confirm_rx = cpu_to_le32(0);
@@ -269,6 +269,22 @@ static struct sk_buff *qrtr_alloc_resume_tx(u32 src_node,
        hdr->dst_node_id = cpu_to_le32(dst_node);
        hdr->dst_port_id = cpu_to_le32(QRTR_PORT_CTRL);
 
+       return skb;
+}
+
+/* Allocate and construct a resume-tx packet. */
+static struct sk_buff *qrtr_alloc_resume_tx(u32 src_node,
+                                           u32 dst_node, u32 port)
+{
+       const int pkt_len = 20;
+       struct sk_buff *skb;
+       __le32 *buf;
+
+       skb = qrtr_alloc_ctrl_packet(QRTR_TYPE_RESUME_TX, pkt_len,
+                                    src_node, dst_node);
+       if (!skb)
+               return NULL;
+
        buf = (__le32 *)skb_put(skb, pkt_len);
        memset(buf, 0, pkt_len);
        buf[0] = cpu_to_le32(QRTR_TYPE_RESUME_TX);
@@ -278,6 +294,45 @@ static struct sk_buff *qrtr_alloc_resume_tx(u32 src_node,
        return skb;
 }
 
+/* Allocate and construct a BYE message to signal remote termination */
+static struct sk_buff *qrtr_alloc_local_bye(u32 src_node)
+{
+       const int pkt_len = 20;
+       struct sk_buff *skb;
+       __le32 *buf;
+
+       skb = qrtr_alloc_ctrl_packet(QRTR_TYPE_BYE, pkt_len,
+                                    src_node, qrtr_local_nid);
+       if (!skb)
+               return NULL;
+
+       buf = (__le32 *)skb_put(skb, pkt_len);
+       memset(buf, 0, pkt_len);
+       buf[0] = cpu_to_le32(QRTR_TYPE_BYE);
+
+       return skb;
+}
+
+static struct sk_buff *qrtr_alloc_del_client(struct sockaddr_qrtr *sq)
+{
+       const int pkt_len = 20;
+       struct sk_buff *skb;
+       __le32 *buf;
+
+       skb = qrtr_alloc_ctrl_packet(QRTR_TYPE_DEL_CLIENT, pkt_len,
+                                    sq->sq_node, QRTR_NODE_BCAST);
+       if (!skb)
+               return NULL;
+
+       buf = (__le32 *)skb_put(skb, pkt_len);
+       memset(buf, 0, pkt_len);
+       buf[0] = cpu_to_le32(QRTR_TYPE_DEL_CLIENT);
+       buf[1] = cpu_to_le32(sq->sq_node);
+       buf[2] = cpu_to_le32(sq->sq_port);
+
+       return skb;
+}
+
 static struct qrtr_sock *qrtr_port_lookup(int port);
 static void qrtr_port_put(struct qrtr_sock *ipc);
 
@@ -369,11 +424,17 @@ EXPORT_SYMBOL_GPL(qrtr_endpoint_register);
 void qrtr_endpoint_unregister(struct qrtr_endpoint *ep)
 {
        struct qrtr_node *node = ep->node;
+       struct sk_buff *skb;
 
        mutex_lock(&node->ep_lock);
        node->ep = NULL;
        mutex_unlock(&node->ep_lock);
 
+       /* Notify the local controller about the event */
+       skb = qrtr_alloc_local_bye(node->nid);
+       if (skb)
+               qrtr_local_enqueue(NULL, skb);
+
        qrtr_node_release(node);
        ep->node = NULL;
 }
@@ -408,8 +469,15 @@ static void qrtr_port_put(struct qrtr_sock *ipc)
 /* Remove port assignment. */
 static void qrtr_port_remove(struct qrtr_sock *ipc)
 {
+       struct sk_buff *skb;
        int port = ipc->us.sq_port;
 
+       skb = qrtr_alloc_del_client(&ipc->us);
+       if (skb) {
+               skb_set_owner_w(skb, &ipc->sk);
+               qrtr_bcast_enqueue(NULL, skb);
+       }
+
        if (port == QRTR_PORT_CTRL)
                port = 0;
 
@@ -462,6 +530,26 @@ static int qrtr_port_assign(struct qrtr_sock *ipc, int *port)
        return 0;
 }
 
+/* Reset all non-control ports */
+static void qrtr_reset_ports(void)
+{
+       struct qrtr_sock *ipc;
+       int id;
+
+       mutex_lock(&qrtr_port_lock);
+       idr_for_each_entry(&qrtr_ports, ipc, id) {
+               /* Don't reset control port */
+               if (id == 0)
+                       continue;
+
+               sock_hold(&ipc->sk);
+               ipc->sk.sk_err = ENETRESET;
+               wake_up_interruptible(sk_sleep(&ipc->sk));
+               sock_put(&ipc->sk);
+       }
+       mutex_unlock(&qrtr_port_lock);
+}
+
 /* Bind socket to address.
  *
  * Socket should be locked upon call.
@@ -490,6 +578,10 @@ static int __qrtr_bind(struct socket *sock,
 
        sock_reset_flag(sk, SOCK_ZAPPED);
 
+       /* Notify all open ports about the new controller */
+       if (port == QRTR_PORT_CTRL)
+               qrtr_reset_ports();
+
        return 0;
 }
 
index 0c4dc4a7832c9fd7c1a45fd9a4d06860101c2205..58ae0db52ea13380582804cfa5431f25141cf7ef 100644 (file)
@@ -262,6 +262,7 @@ static int rxrpc_listen(struct socket *sock, int backlog)
  * @srx: The address of the peer to contact
  * @key: The security context to use (defaults to socket setting)
  * @user_call_ID: The ID to use
+ * @tx_total_len: Total length of data to transmit during the call (or -1)
  * @gfp: The allocation constraints
  * @notify_rx: Where to send notifications instead of socket queue
  *
@@ -276,6 +277,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
                                           struct sockaddr_rxrpc *srx,
                                           struct key *key,
                                           unsigned long user_call_ID,
+                                          s64 tx_total_len,
                                           gfp_t gfp,
                                           rxrpc_notify_rx_t notify_rx)
 {
@@ -303,7 +305,8 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
        cp.security_level       = 0;
        cp.exclusive            = false;
        cp.service_id           = srx->srx_service;
-       call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, gfp);
+       call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, tx_total_len,
+                                    gfp);
        /* The socket has been unlocked. */
        if (!IS_ERR(call))
                call->notify_rx = notify_rx;
@@ -581,6 +584,34 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname,
        return ret;
 }
 
+/*
+ * Get socket options.
+ */
+static int rxrpc_getsockopt(struct socket *sock, int level, int optname,
+                           char __user *optval, int __user *_optlen)
+{
+       int optlen;
+       
+       if (level != SOL_RXRPC)
+               return -EOPNOTSUPP;
+
+       if (get_user(optlen, _optlen))
+               return -EFAULT;
+       
+       switch (optname) {
+       case RXRPC_SUPPORTED_CMSG:
+               if (optlen < sizeof(int))
+                       return -ETOOSMALL;
+               if (put_user(RXRPC__SUPPORTED - 1, (int __user *)optval) ||
+                   put_user(sizeof(int), _optlen))
+                       return -EFAULT;
+               return 0;
+               
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
 /*
  * permit an RxRPC socket to be polled
  */
@@ -784,7 +815,7 @@ static const struct proto_ops rxrpc_rpc_ops = {
        .listen         = rxrpc_listen,
        .shutdown       = rxrpc_shutdown,
        .setsockopt     = rxrpc_setsockopt,
-       .getsockopt     = sock_no_getsockopt,
+       .getsockopt     = rxrpc_getsockopt,
        .sendmsg        = rxrpc_sendmsg,
        .recvmsg        = rxrpc_recvmsg,
        .mmap           = sock_no_mmap,
index e9b536cb0acf8534371a52214e8ec32390d0254e..adbf37946450c54d8d2aef9f05b9be3c09b4706f 100644 (file)
@@ -528,6 +528,7 @@ struct rxrpc_call {
        struct rb_node          sock_node;      /* Node in rx->calls */
        struct sk_buff          *tx_pending;    /* Tx socket buffer being filled */
        wait_queue_head_t       waitq;          /* Wait queue for channel or Tx */
+       s64                     tx_total_len;   /* Total length left to be transmitted (or -1) */
        __be32                  crypto_buf[2];  /* Temporary packet crypto buffer */
        unsigned long           user_call_ID;   /* user-defined call ID */
        unsigned long           flags;
@@ -683,7 +684,7 @@ struct rxrpc_call *rxrpc_alloc_call(gfp_t);
 struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *,
                                         struct rxrpc_conn_parameters *,
                                         struct sockaddr_rxrpc *,
-                                        unsigned long, gfp_t);
+                                        unsigned long, s64, gfp_t);
 void rxrpc_incoming_call(struct rxrpc_sock *, struct rxrpc_call *,
                         struct sk_buff *);
 void rxrpc_release_call(struct rxrpc_sock *, struct rxrpc_call *);
index 692110808baaa02db31ed1cf366ae39b2cadaff0..423030fd93bed29d1b2aac0e0f0c232ed42049bb 100644 (file)
@@ -127,6 +127,7 @@ struct rxrpc_call *rxrpc_alloc_call(gfp_t gfp)
        rwlock_init(&call->state_lock);
        atomic_set(&call->usage, 1);
        call->debug_id = atomic_inc_return(&rxrpc_debug_id);
+       call->tx_total_len = -1;
 
        memset(&call->sock_node, 0xed, sizeof(call->sock_node));
 
@@ -201,6 +202,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
                                         struct rxrpc_conn_parameters *cp,
                                         struct sockaddr_rxrpc *srx,
                                         unsigned long user_call_ID,
+                                        s64 tx_total_len,
                                         gfp_t gfp)
        __releases(&rx->sk.sk_lock.slock)
 {
@@ -219,6 +221,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
                return call;
        }
 
+       call->tx_total_len = tx_total_len;
        trace_rxrpc_call(call, rxrpc_call_new_client, atomic_read(&call->usage),
                         here, (const void *)user_call_ID);
 
index 5a4801e7f560d8a9a8ef06d93814f86f469c6dc7..2e636a525a651102da021b926a00e990e859bc04 100644 (file)
@@ -28,6 +28,15 @@ enum rxrpc_command {
        RXRPC_CMD_REJECT_BUSY,          /* [server] reject a call as busy */
 };
 
+struct rxrpc_send_params {
+       s64                     tx_total_len;   /* Total Tx data length (if send data) */
+       unsigned long           user_call_ID;   /* User's call ID */
+       u32                     abort_code;     /* Abort code to Tx (if abort) */
+       enum rxrpc_command      command : 8;    /* The command to implement */
+       bool                    exclusive;      /* Shared or exclusive call */
+       bool                    upgrade;        /* If the connection is upgradeable */
+};
+
 /*
  * wait for space to appear in the transmit/ACK window
  * - caller holds the socket locked
@@ -199,6 +208,13 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
 
        more = msg->msg_flags & MSG_MORE;
 
+       if (call->tx_total_len != -1) {
+               if (len > call->tx_total_len)
+                       return -EMSGSIZE;
+               if (!more && len != call->tx_total_len)
+                       return -EMSGSIZE;
+       }
+
        skb = call->tx_pending;
        call->tx_pending = NULL;
        rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
@@ -291,6 +307,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
                        sp->remain -= copy;
                        skb->mark += copy;
                        copied += copy;
+                       if (call->tx_total_len != -1)
+                               call->tx_total_len -= copy;
                }
 
                /* check for the far side aborting the call or a network error
@@ -362,19 +380,12 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
 /*
  * extract control messages from the sendmsg() control buffer
  */
-static int rxrpc_sendmsg_cmsg(struct msghdr *msg,
-                             unsigned long *user_call_ID,
-                             enum rxrpc_command *command,
-                             u32 *abort_code,
-                             bool *_exclusive,
-                             bool *_upgrade)
+static int rxrpc_sendmsg_cmsg(struct msghdr *msg, struct rxrpc_send_params *p)
 {
        struct cmsghdr *cmsg;
        bool got_user_ID = false;
        int len;
 
-       *command = RXRPC_CMD_SEND_DATA;
-
        if (msg->msg_controllen == 0)
                return -EINVAL;
 
@@ -394,49 +405,55 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg,
                        if (msg->msg_flags & MSG_CMSG_COMPAT) {
                                if (len != sizeof(u32))
                                        return -EINVAL;
-                               *user_call_ID = *(u32 *) CMSG_DATA(cmsg);
+                               p->user_call_ID = *(u32 *)CMSG_DATA(cmsg);
                        } else {
                                if (len != sizeof(unsigned long))
                                        return -EINVAL;
-                               *user_call_ID = *(unsigned long *)
+                               p->user_call_ID = *(unsigned long *)
                                        CMSG_DATA(cmsg);
                        }
-                       _debug("User Call ID %lx", *user_call_ID);
                        got_user_ID = true;
                        break;
 
                case RXRPC_ABORT:
-                       if (*command != RXRPC_CMD_SEND_DATA)
+                       if (p->command != RXRPC_CMD_SEND_DATA)
                                return -EINVAL;
-                       *command = RXRPC_CMD_SEND_ABORT;
-                       if (len != sizeof(*abort_code))
+                       p->command = RXRPC_CMD_SEND_ABORT;
+                       if (len != sizeof(p->abort_code))
                                return -EINVAL;
-                       *abort_code = *(unsigned int *) CMSG_DATA(cmsg);
-                       _debug("Abort %x", *abort_code);
-                       if (*abort_code == 0)
+                       p->abort_code = *(unsigned int *)CMSG_DATA(cmsg);
+                       if (p->abort_code == 0)
                                return -EINVAL;
                        break;
 
                case RXRPC_ACCEPT:
-                       if (*command != RXRPC_CMD_SEND_DATA)
+                       if (p->command != RXRPC_CMD_SEND_DATA)
                                return -EINVAL;
-                       *command = RXRPC_CMD_ACCEPT;
+                       p->command = RXRPC_CMD_ACCEPT;
                        if (len != 0)
                                return -EINVAL;
                        break;
 
                case RXRPC_EXCLUSIVE_CALL:
-                       *_exclusive = true;
+                       p->exclusive = true;
                        if (len != 0)
                                return -EINVAL;
                        break;
 
                case RXRPC_UPGRADE_SERVICE:
-                       *_upgrade = true;
+                       p->upgrade = true;
                        if (len != 0)
                                return -EINVAL;
                        break;
 
+               case RXRPC_TX_LENGTH:
+                       if (p->tx_total_len != -1 || len != sizeof(__s64))
+                               return -EINVAL;
+                       p->tx_total_len = *(__s64 *)CMSG_DATA(cmsg);
+                       if (p->tx_total_len < 0)
+                               return -EINVAL;
+                       break;
+
                default:
                        return -EINVAL;
                }
@@ -444,6 +461,8 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg,
 
        if (!got_user_ID)
                return -EINVAL;
+       if (p->tx_total_len != -1 && p->command != RXRPC_CMD_SEND_DATA)
+               return -EINVAL;
        _leave(" = 0");
        return 0;
 }
@@ -455,8 +474,7 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg,
  */
 static struct rxrpc_call *
 rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg,
-                                 unsigned long user_call_ID, bool exclusive,
-                                 bool upgrade)
+                                 struct rxrpc_send_params *p)
        __releases(&rx->sk.sk_lock.slock)
 {
        struct rxrpc_conn_parameters cp;
@@ -480,10 +498,11 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg,
        cp.local                = rx->local;
        cp.key                  = rx->key;
        cp.security_level       = rx->min_sec_level;
-       cp.exclusive            = rx->exclusive | exclusive;
-       cp.upgrade              = upgrade;
+       cp.exclusive            = rx->exclusive | p->exclusive;
+       cp.upgrade              = p->upgrade;
        cp.service_id           = srx->srx_service;
-       call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, GFP_KERNEL);
+       call = rxrpc_new_client_call(rx, &cp, srx, p->user_call_ID,
+                                    p->tx_total_len, GFP_KERNEL);
        /* The socket is now unlocked */
 
        _leave(" = %p\n", call);
@@ -499,26 +518,29 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
        __releases(&rx->sk.sk_lock.slock)
 {
        enum rxrpc_call_state state;
-       enum rxrpc_command cmd;
        struct rxrpc_call *call;
-       unsigned long user_call_ID = 0;
-       bool exclusive = false;
-       bool upgrade = true;
-       u32 abort_code = 0;
        int ret;
 
+       struct rxrpc_send_params p = {
+               .tx_total_len   = -1,
+               .user_call_ID   = 0,
+               .abort_code     = 0,
+               .command        = RXRPC_CMD_SEND_DATA,
+               .exclusive      = false,
+               .upgrade        = true,
+       };
+
        _enter("");
 
-       ret = rxrpc_sendmsg_cmsg(msg, &user_call_ID, &cmd, &abort_code,
-                                &exclusive, &upgrade);
+       ret = rxrpc_sendmsg_cmsg(msg, &p);
        if (ret < 0)
                goto error_release_sock;
 
-       if (cmd == RXRPC_CMD_ACCEPT) {
+       if (p.command == RXRPC_CMD_ACCEPT) {
                ret = -EINVAL;
                if (rx->sk.sk_state != RXRPC_SERVER_LISTENING)
                        goto error_release_sock;
-               call = rxrpc_accept_call(rx, user_call_ID, NULL);
+               call = rxrpc_accept_call(rx, p.user_call_ID, NULL);
                /* The socket is now unlocked. */
                if (IS_ERR(call))
                        return PTR_ERR(call);
@@ -526,13 +548,12 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
                return 0;
        }
 
-       call = rxrpc_find_call_by_user_ID(rx, user_call_ID);
+       call = rxrpc_find_call_by_user_ID(rx, p.user_call_ID);
        if (!call) {
                ret = -EBADSLT;
-               if (cmd != RXRPC_CMD_SEND_DATA)
+               if (p.command != RXRPC_CMD_SEND_DATA)
                        goto error_release_sock;
-               call = rxrpc_new_client_call_for_sendmsg(rx, msg, user_call_ID,
-                                                        exclusive, upgrade);
+               call = rxrpc_new_client_call_for_sendmsg(rx, msg, &p);
                /* The socket is now unlocked... */
                if (IS_ERR(call))
                        return PTR_ERR(call);
@@ -556,6 +577,15 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
                        ret = -ERESTARTSYS;
                        goto error_put;
                }
+
+               if (p.tx_total_len != -1) {
+                       ret = -EINVAL;
+                       if (call->tx_total_len != -1 ||
+                           call->tx_pending ||
+                           call->tx_top != 0)
+                               goto error_put;
+                       call->tx_total_len = p.tx_total_len;
+               }
        }
 
        state = READ_ONCE(call->state);
@@ -565,11 +595,11 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
        if (state >= RXRPC_CALL_COMPLETE) {
                /* it's too late for this call */
                ret = -ESHUTDOWN;
-       } else if (cmd == RXRPC_CMD_SEND_ABORT) {
+       } else if (p.command == RXRPC_CMD_SEND_ABORT) {
                ret = 0;
-               if (rxrpc_abort_call("CMD", call, 0, abort_code, -ECONNABORTED))
+               if (rxrpc_abort_call("CMD", call, 0, p.abort_code, -ECONNABORTED))
                        ret = rxrpc_send_abort_packet(call);
-       } else if (cmd != RXRPC_CMD_SEND_DATA) {
+       } else if (p.command != RXRPC_CMD_SEND_DATA) {
                ret = -EINVAL;
        } else if (rxrpc_is_client_call(call) &&
                   state != RXRPC_CALL_CLIENT_SEND_REQUEST) {
@@ -673,5 +703,24 @@ bool rxrpc_kernel_abort_call(struct socket *sock, struct rxrpc_call *call,
        mutex_unlock(&call->user_mutex);
        return aborted;
 }
-
 EXPORT_SYMBOL(rxrpc_kernel_abort_call);
+
+/**
+ * rxrpc_kernel_set_tx_length - Set the total Tx length on a call
+ * @sock: The socket the call is on
+ * @call: The call to be informed
+ * @tx_total_len: The amount of data to be transmitted for this call
+ *
+ * Allow a kernel service to set the total transmit length on a call.  This
+ * allows buffer-to-packet encrypt-and-copy to be performed.
+ *
+ * This function is primarily for use for setting the reply length since the
+ * request length can be set when beginning the call.
+ */
+void rxrpc_kernel_set_tx_length(struct socket *sock, struct rxrpc_call *call,
+                               s64 tx_total_len)
+{
+       WARN_ON(call->tx_total_len != -1);
+       call->tx_total_len = tx_total_len;
+}
+EXPORT_SYMBOL(rxrpc_kernel_set_tx_length);
index a9c56ad4533afb0789f32ca327ecd275bae3c1bb..be0cfdf489762cfbc28894214b1188ba3c1c5fda 100644 (file)
@@ -162,6 +162,7 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
        bpf_offload.gen_flags = prog->gen_flags;
 
        err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+                                           tp->chain->index,
                                            tp->protocol, &offload);
 
        if (!err && (cmd == TC_CLSBPF_ADD || cmd == TC_CLSBPF_REPLACE))
index 33feaee197cfd5b28e4fde72557d19d93a45d9b6..7832eb93379b3907c2b42d9cd304cfa998237396 100644 (file)
@@ -239,7 +239,8 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)
        tc->type = TC_SETUP_CLSFLOWER;
        tc->cls_flower = &offload;
 
-       dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, tc);
+       dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->chain->index,
+                                     tp->protocol, tc);
 }
 
 static int fl_hw_replace_filter(struct tcf_proto *tp,
@@ -275,8 +276,8 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
        tc->type = TC_SETUP_CLSFLOWER;
        tc->cls_flower = &offload;
 
-       err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol,
-                                           tc);
+       err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+                                           tp->chain->index, tp->protocol, tc);
        if (!err)
                f->flags |= TCA_CLS_FLAGS_IN_HW;
 
@@ -302,7 +303,8 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
        tc->type = TC_SETUP_CLSFLOWER;
        tc->cls_flower = &offload;
 
-       dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, tc);
+       dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+                                     tp->chain->index, tp->protocol, tc);
 }
 
 static void __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f)
index 51859b8edd7eff3845ca3d5b5b0d900583736d4a..9dc26c32cf321e475a8f783cf423ff67562479fa 100644 (file)
@@ -64,8 +64,9 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
        offload.cls_mall->exts = &head->exts;
        offload.cls_mall->cookie = cookie;
 
-       err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol,
-                                           &offload);
+       err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+                                           tp->chain->index,
+                                           tp->protocol, &offload);
        if (!err)
                head->flags |= TCA_CLS_FLAGS_IN_HW;
 
@@ -86,8 +87,8 @@ static void mall_destroy_hw_filter(struct tcf_proto *tp,
        offload.cls_mall->exts = NULL;
        offload.cls_mall->cookie = cookie;
 
-       dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol,
-                                            &offload);
+       dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->chain->index,
+                                     tp->protocol, &offload);
 }
 
 static void mall_destroy(struct tcf_proto *tp)
index d20e72a095d578e65eda0dafc62217146aeea1c1..2d01195153e6c80178328c65d3b94651f3e2094f 100644 (file)
@@ -441,7 +441,8 @@ static void u32_remove_hw_knode(struct tcf_proto *tp, u32 handle)
                offload.cls_u32->command = TC_CLSU32_DELETE_KNODE;
                offload.cls_u32->knode.handle = handle;
                dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-                                             tp->protocol, &offload);
+                                             tp->chain->index, tp->protocol,
+                                             &offload);
        }
 }
 
@@ -465,7 +466,8 @@ static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h,
        offload.cls_u32->hnode.prio = h->prio;
 
        err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-                                           tp->protocol, &offload);
+                                           tp->chain->index, tp->protocol,
+                                           &offload);
        if (tc_skip_sw(flags))
                return err;
 
@@ -488,7 +490,8 @@ static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
                offload.cls_u32->hnode.prio = h->prio;
 
                dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-                                             tp->protocol, &offload);
+                                             tp->chain->index, tp->protocol,
+                                             &offload);
        }
 }
 
@@ -522,7 +525,8 @@ static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
                offload.cls_u32->knode.link_handle = n->ht_down->handle;
 
        err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-                                           tp->protocol, &offload);
+                                           tp->chain->index, tp->protocol,
+                                           &offload);
 
        if (!err)
                n->flags |= TCA_CLS_FLAGS_IN_HW;
index 0a4cf27ea54bd78768d4fa084f7b082460f5f266..e0c02725cd487c2a2c5f063066f29faab8ae479d 100644 (file)
@@ -43,7 +43,7 @@ static void mqprio_destroy(struct Qdisc *sch)
                struct tc_to_netdev tc = { .type = TC_SETUP_MQPRIO,
                                           { .mqprio = &offload } };
 
-               dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
+               dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, 0, &tc);
        } else {
                netdev_set_num_tc(dev, 0);
        }
@@ -152,7 +152,8 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)
                struct tc_to_netdev tc = { .type = TC_SETUP_MQPRIO,
                                           { .mqprio = &offload } };
 
-               err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
+               err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle,
+                                                   0, 0, &tc);
                if (err)
                        return err;
 
index 288c5e0cda5d1f89fffe40279ae8a1610acd56b8..72b07dd9b9595cb76326fb60919f462f3cecbd3a 100644 (file)
@@ -1181,12 +1181,8 @@ void sctp_assoc_update(struct sctp_association *asoc,
                if (sctp_state(asoc, COOKIE_WAIT))
                        sctp_stream_update(&asoc->stream, &new->stream);
 
-               if (!asoc->assoc_id) {
-                       /* get a new association id since we don't have one
-                        * yet.
-                        */
-                       sctp_assoc_set_id(asoc, GFP_ATOMIC);
-               }
+               /* get a new assoc id if we don't have one yet. */
+               sctp_assoc_set_id(asoc, GFP_ATOMIC);
        }
 
        /* SCTP-AUTH: Save the peer parameters from the new associations
index 5a27d0f03df53be07ec50a245f0ce4a35c32ef76..8e34db56bc1db2a118722b5d88ab5e3f757f2fca 100644 (file)
@@ -218,8 +218,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
                return -ENOMEM;
 
        head = &sctp_ep_hashtable[hash];
-       local_bh_disable();
-       read_lock(&head->lock);
+       read_lock_bh(&head->lock);
        sctp_for_each_hentry(epb, &head->chain) {
                ep = sctp_ep(epb);
                sk = epb->sk;
@@ -234,8 +233,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
                sctp_seq_dump_local_addrs(seq, epb);
                seq_printf(seq, "\n");
        }
-       read_unlock(&head->lock);
-       local_bh_enable();
+       read_unlock_bh(&head->lock);
 
        return 0;
 }
index 0822046e4f3f5a1acd3f5382d915bf9004a25c1c..32d5495e793cdcc942f59c8b3e3279752d24765b 100644 (file)
@@ -103,7 +103,7 @@ static int sctp_autobind(struct sock *sk);
 static void sctp_sock_migrate(struct sock *, struct sock *,
                              struct sctp_association *, sctp_socket_type_t);
 
-static int sctp_memory_pressure;
+static unsigned long sctp_memory_pressure;
 static atomic_long_t sctp_memory_allocated;
 struct percpu_counter sctp_sockets_allocated;
 
@@ -1494,7 +1494,7 @@ static void sctp_close(struct sock *sk, long timeout)
 
        pr_debug("%s: sk:%p, timeout:%ld\n", __func__, sk, timeout);
 
-       lock_sock(sk);
+       lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
        sk->sk_shutdown = SHUTDOWN_MASK;
        sk->sk_state = SCTP_SS_CLOSING;
 
@@ -1544,7 +1544,7 @@ static void sctp_close(struct sock *sk, long timeout)
         * held and that should be grabbed before socket lock.
         */
        spin_lock_bh(&net->sctp.addr_wq_lock);
-       bh_lock_sock(sk);
+       bh_lock_sock_nested(sk);
 
        /* Hold the sock, since sk_common_release() will put sock_put()
         * and we have just a little more cleanup.
index 8d40a7d31c9908c22b757fc0ab92bce436211c90..25dc67ef9d37084f55ff7a49a2daabee6556a42c 100644 (file)
@@ -571,24 +571,17 @@ int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj,
 }
 EXPORT_SYMBOL_GPL(switchdev_port_obj_dump);
 
-static RAW_NOTIFIER_HEAD(switchdev_notif_chain);
+static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain);
 
 /**
  *     register_switchdev_notifier - Register notifier
  *     @nb: notifier_block
  *
- *     Register switch device notifier. This should be used by code
- *     which needs to monitor events happening in particular device.
- *     Return values are same as for atomic_notifier_chain_register().
+ *     Register switch device notifier.
  */
 int register_switchdev_notifier(struct notifier_block *nb)
 {
-       int err;
-
-       rtnl_lock();
-       err = raw_notifier_chain_register(&switchdev_notif_chain, nb);
-       rtnl_unlock();
-       return err;
+       return atomic_notifier_chain_register(&switchdev_notif_chain, nb);
 }
 EXPORT_SYMBOL_GPL(register_switchdev_notifier);
 
@@ -597,16 +590,10 @@ EXPORT_SYMBOL_GPL(register_switchdev_notifier);
  *     @nb: notifier_block
  *
  *     Unregister switch device notifier.
- *     Return values are same as for atomic_notifier_chain_unregister().
  */
 int unregister_switchdev_notifier(struct notifier_block *nb)
 {
-       int err;
-
-       rtnl_lock();
-       err = raw_notifier_chain_unregister(&switchdev_notif_chain, nb);
-       rtnl_unlock();
-       return err;
+       return atomic_notifier_chain_unregister(&switchdev_notif_chain, nb);
 }
 EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
 
@@ -616,18 +603,13 @@ EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
  *     @dev: port device
  *     @info: notifier information data
  *
- *     Call all network notifier blocks. This should be called by driver
- *     when it needs to propagate hardware event.
- *     Return values are same as for atomic_notifier_call_chain().
- *     rtnl_lock must be held.
+ *     Call all network notifier blocks.
  */
 int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
                             struct switchdev_notifier_info *info)
 {
-       ASSERT_RTNL();
-
        info->dev = dev;
-       return raw_notifier_call_chain(&switchdev_notif_chain, val, info);
+       return atomic_notifier_call_chain(&switchdev_notif_chain, val, info);
 }
 EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
 
index 9b2c10b45733e4dc66d601ac2ea52fed65f3752d..f94b48b168dcc82cbd67b916951a4699f4f675ef 100644 (file)
@@ -513,6 +513,11 @@ union bpf_attr {
  *     Get the owner uid of the socket stored inside sk_buff.
  *     @skb: pointer to skb
  *     Return: uid of the socket owner on success or overflowuid if failed.
+ *
+ * u32 bpf_set_hash(skb, hash)
+ *     Set full skb->hash.
+ *     @skb: pointer to skb
+ *     @hash: hash to set
  */
 #define __BPF_FUNC_MAPPER(FN)          \
        FN(unspec),                     \
@@ -562,7 +567,8 @@ union bpf_attr {
        FN(xdp_adjust_head),            \
        FN(probe_read_str),             \
        FN(get_socket_cookie),          \
-       FN(get_socket_uid),
+       FN(get_socket_uid),             \
+       FN(set_hash),
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
index 9644d4e069dec3e43ec654f6f44d933a02a7878a..1426594fdf6bcfc1384f62f140ccc497b104077d 100644 (file)
@@ -9,6 +9,8 @@
 #include <stddef.h>
 #include <stdbool.h>
 
+#include <sys/resource.h>
+
 #include <linux/unistd.h>
 #include <linux/filter.h>
 #include <linux/bpf_perf_event.h>
@@ -432,6 +434,9 @@ static int do_test(unsigned int from, unsigned int to)
 int main(int argc, char **argv)
 {
        unsigned int from = 0, to = ARRAY_SIZE(tests);
+       struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
+
+       setrlimit(RLIMIT_MEMLOCK, &rinf);
 
        if (argc == 3) {
                unsigned int l = atoi(argv[argc - 2]);
index 93314524de0d033ded2a00d71bbf500a0afbd60e..79601c81e169c22650ae545b6a5fefb8323655ee 100644 (file)
@@ -239,6 +239,54 @@ static void test_hashmap_percpu(int task, void *data)
        close(fd);
 }
 
+static void test_hashmap_walk(int task, void *data)
+{
+       int fd, i, max_entries = 100000;
+       long long key, value, next_key;
+       bool next_key_valid = true;
+
+       fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
+                           max_entries, map_flags);
+       if (fd < 0) {
+               printf("Failed to create hashmap '%s'!\n", strerror(errno));
+               exit(1);
+       }
+
+       for (i = 0; i < max_entries; i++) {
+               key = i; value = key;
+               assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
+       }
+
+       for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
+                                        &next_key) == 0; i++) {
+               key = next_key;
+               assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
+       }
+
+       assert(i == max_entries);
+
+       assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
+       for (i = 0; next_key_valid; i++) {
+               next_key_valid = bpf_map_get_next_key(fd, &key, &next_key) == 0;
+               assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
+               value++;
+               assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
+               key = next_key;
+       }
+
+       assert(i == max_entries);
+
+       for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
+                                        &next_key) == 0; i++) {
+               key = next_key;
+               assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
+               assert(value - 1 == key);
+       }
+
+       assert(i == max_entries);
+       close(fd);
+}
+
 static void test_arraymap(int task, void *data)
 {
        int key, next_key, fd;
@@ -464,6 +512,7 @@ static void test_map_stress(void)
        run_parallel(100, test_hashmap, NULL);
        run_parallel(100, test_hashmap_percpu, NULL);
        run_parallel(100, test_hashmap_sizes, NULL);
+       run_parallel(100, test_hashmap_walk, NULL);
 
        run_parallel(100, test_arraymap, NULL);
        run_parallel(100, test_arraymap_percpu, NULL);
@@ -549,6 +598,7 @@ static void run_all_tests(void)
 {
        test_hashmap(0, NULL);
        test_hashmap_percpu(0, NULL);
+       test_hashmap_walk(0, NULL);
 
        test_arraymap(0, NULL);
        test_arraymap_percpu(0, NULL);
index d8723aaf827a3eb4162457d87fabdedeb9aa9344..880d2963b4725192b6243200a9d81e0fe56329ab 100644 (file)
@@ -23,8 +23,8 @@ struct bpf_map_def SEC("maps") test_map_id = {
        .max_entries = 1,
 };
 
-SEC("test_prog_id")
-int test_prog_id(struct __sk_buff *skb)
+SEC("test_obj_id_dummy")
+int test_obj_id(struct __sk_buff *skb)
 {
        __u32 key = 0;
        __u64 *value;
index 8189bfc7e2773869f794408aa41be086b19aa6e6..fec13ab84fca43dba7a616e676c29563be7c3892 100644 (file)
@@ -23,7 +23,7 @@ typedef __u16 __sum16;
 #include <sys/wait.h>
 #include <sys/resource.h>
 #include <sys/types.h>
-#include <pwd.h>
+#include <fcntl.h>
 
 #include <linux/bpf.h>
 #include <linux/err.h>
@@ -297,6 +297,7 @@ static void test_bpf_obj_id(void)
        const __u32 array_key = 0;
        const int nr_iters = 2;
        const char *file = "./test_obj_id.o";
+       const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
 
        struct bpf_object *objs[nr_iters];
        int prog_fds[nr_iters], map_fds[nr_iters];
@@ -305,9 +306,18 @@ static void test_bpf_obj_id(void)
        struct bpf_map_info map_infos[nr_iters + 1];
        char jited_insns[128], xlated_insns[128];
        __u32 i, next_id, info_len, nr_id_found, duration = 0;
-       int err = 0;
+       int sysctl_fd, jit_enabled = 0, err = 0;
        __u64 array_value;
 
+       sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
+       if (sysctl_fd != -1) {
+               char tmpc;
+
+               if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1)
+                       jit_enabled = (tmpc != '0');
+               close(sysctl_fd);
+       }
+
        err = bpf_prog_get_fd_by_id(0);
        CHECK(err >= 0 || errno != ENOENT,
              "get-fd-by-notexist-prog-id", "err %d errno %d\n", err, errno);
@@ -339,13 +349,14 @@ static void test_bpf_obj_id(void)
                if (CHECK(err ||
                          prog_infos[i].type != BPF_PROG_TYPE_SOCKET_FILTER ||
                          info_len != sizeof(struct bpf_prog_info) ||
-                         !prog_infos[i].jited_prog_len ||
+                         (jit_enabled && !prog_infos[i].jited_prog_len) ||
                          !prog_infos[i].xlated_prog_len,
                          "get-prog-info(fd)",
-                         "err %d errno %d i %d type %d(%d) info_len %u(%lu) jited_prog_len %u xlated_prog_len %u\n",
+                         "err %d errno %d i %d type %d(%d) info_len %u(%lu) jit_enabled %d jited_prog_len %u xlated_prog_len %u\n",
                          err, errno, i,
                          prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER,
                          info_len, sizeof(struct bpf_prog_info),
+                         jit_enabled,
                          prog_infos[i].jited_prog_len,
                          prog_infos[i].xlated_prog_len))
                        goto done;