Skip to contentSkip to conversation

wifi: aic: add AIC8800 SDIO FullMAC driver

RFC PATCH Superseded Yanli Yang 1 participant 5 messages Jul 21

Subsystems (2)

v1 of 4 Superseded Latest is v4 →

lore
Share & tools
lore

Yanli Yang

author
#0 lore raw

cover wifi: aic: add AIC8800 SDIO FullMAC driver

This RFC adds an SDIO FullMAC driver for AIC8801, AIC8800DC and AIC8800D80 devices. It contains an SDIO/BSP layer, the firmware protocol, the cfg80211 FullMAC implementation, and diagnostic and compatibility interfaces.

The series is organized as follows:

1. build configuration, SDIO BSP, firmware loading and BSP chip support;
2. FullMAC firmware protocol, platform bring-up and control path;
3. cfg80211 core, data path, SDIO/chip support, wireless features,

     diagnostics and compatibility interfaces;

4. parent wireless build integration and MAINTAINERS.

The parent build integration is added last so that no incomplete driver state can be selected by Kconfig.

Validation performed for this series:

- default, W=1 and allmodconfig AIC object builds with GCC 11.4.0;
- strict checkpatch validation for all four patches;
- sequential git am application on wireless-next commit ac798f757d6475.

Runtime testing on production hardware has not yet been performed.

Known limitations of this RFC are:

- firmware redistribution permission and the corresponding linux-firmware

    submission are not yet available;

- DT power and wake bindings are not included;
- private generic-netlink and vendor interfaces, the regulatory database, and rwnx_settings.ini require follow-up work.

Zhirun Liu (4):
wifi: aic: add SDIO BSP and build configuration
wifi: aic: add FullMAC firmware and platform interface
wifi: aic: add FullMAC WLAN driver
wifi: aic: integrate AIC8800 driver

 MAINTAINERS                                   |   10 +
 drivers/net/wireless/Kconfig                  |    1 +
 drivers/net/wireless/Makefile                 |    1 +
 drivers/net/wireless/aic/Kconfig              |  135 +
 drivers/net/wireless/aic/Makefile             |   17 +
 drivers/net/wireless/aic/aic8800_bsp/Kconfig  |   97 +
 drivers/net/wireless/aic/aic8800_bsp/Makefile |   42 +
 .../aic/aic8800_bsp/aic8800d80_compat.c       |  290 +
 .../aic/aic8800_bsp/aic8800d80_compat.h       |   11 +
 .../aic/aic8800_bsp/aic8800dc_compat.c        | 1353 +++++
 .../aic/aic8800_bsp/aic8800dc_compat.h        |   40 +
 .../wireless/aic/aic8800_bsp/aic_bsp_driver.c | 1659 +++++
 .../wireless/aic/aic8800_bsp/aic_bsp_driver.h |  621 ++
 .../wireless/aic/aic8800_bsp/aic_bsp_export.h |   70 +
 .../wireless/aic/aic8800_bsp/aic_bsp_main.c   |  556 ++
 .../aic/aic8800_bsp/aic_chip_8800d80.c        |  116 +
 .../aic/aic8800_bsp/aic_chip_8800dc.c         |  133 +
 .../wireless/aic/aic8800_bsp/aic_chip_8801.c  |  117 +
 .../wireless/aic/aic8800_bsp/aic_chip_ops.c   |   77 +
 .../wireless/aic/aic8800_bsp/aic_chip_ops.h   |   71 +
 .../net/wireless/aic/aic8800_bsp/aicsdio.c    | 1999 ++++++
 .../net/wireless/aic/aic8800_bsp/aicsdio.h    |  176 +
 .../wireless/aic/aic8800_bsp/aicsdio_txrxif.c |  465 ++
 .../wireless/aic/aic8800_bsp/aicsdio_txrxif.h |  180 +
 .../aic/aic8800_bsp/aicwf_txq_prealloc.c      |   66 +
 .../aic/aic8800_bsp/aicwf_txq_prealloc.h      |    8 +
 drivers/net/wireless/aic/aic8800_bsp/md5.c    |  165 +
 drivers/net/wireless/aic/aic8800_bsp/md5.h    |   77 +
 .../aic/aic8800_bsp/rwnx_version_gen.h        |    5 +
 drivers/net/wireless/aic/aic8800_fdrv/Kconfig |  539 ++
 .../net/wireless/aic/aic8800_fdrv/Makefile    |  117 +
 .../wireless/aic/aic8800_fdrv/aic_br_ext.c    | 1598 +++++
 .../wireless/aic/aic8800_fdrv/aic_br_ext.h    |   72 +
 .../aic/aic8800_fdrv/aic_bsp_export.h         |   62 +
 .../wireless/aic/aic8800_fdrv/aic_btsdio.c    | 1164 ++++
 .../wireless/aic/aic8800_fdrv/aic_btsdio.h    |  472 ++
 .../net/wireless/aic/aic8800_fdrv/aic_bus.h   |  191 +
 .../wireless/aic/aic8800_fdrv/aic_priv_cmd.c  | 1967 ++++++
 .../wireless/aic/aic8800_fdrv/aic_priv_cmd.h  |  127 +
 .../wireless/aic/aic8800_fdrv/aic_vendor.c    |  950 +++
 .../wireless/aic/aic8800_fdrv/aic_vendor.h    |  370 ++
 .../aic/aic8800_fdrv/aicwf_chip_8800d80.c     |  291 +
 .../aic/aic8800_fdrv/aicwf_chip_8800dc.c      |  300 +
 .../aic/aic8800_fdrv/aicwf_chip_8801.c        |  279 +
 .../aic/aic8800_fdrv/aicwf_chip_ops.c         |  267 +
 .../aic/aic8800_fdrv/aicwf_chip_ops.h         |  186 +
 .../aic/aic8800_fdrv/aicwf_compat_8800d80.c   |   96 +
 .../aic/aic8800_fdrv/aicwf_compat_8800d80.h   |   16 +
 .../aic/aic8800_fdrv/aicwf_compat_8800dc.c    |  505 ++
 .../aic/aic8800_fdrv/aicwf_compat_8800dc.h    |   22 +
 .../wireless/aic/aic8800_fdrv/aicwf_debug.h   |   37 +
 .../wireless/aic/aic8800_fdrv/aicwf_genl.c    |  932 +++
 .../wireless/aic/aic8800_fdrv/aicwf_genl.h    |  112 +
 .../aic/aic8800_fdrv/aicwf_rx_prealloc.c      |  102 +
 .../aic/aic8800_fdrv/aicwf_rx_prealloc.h      |   32 +
 .../wireless/aic/aic8800_fdrv/aicwf_sdio.c    | 2813 +++++++++
 .../wireless/aic/aic8800_fdrv/aicwf_sdio.h    |  264 +
 .../wireless/aic/aic8800_fdrv/aicwf_tcp_ack.c |  572 ++
 .../wireless/aic/aic8800_fdrv/aicwf_tcp_ack.h |  104 +
 .../wireless/aic/aic8800_fdrv/aicwf_txrxif.c  |  753 +++
 .../wireless/aic/aic8800_fdrv/aicwf_txrxif.h  |  217 +
 .../aic/aic8800_fdrv/aicwf_wext_linux.c       | 1137 ++++
 .../aic/aic8800_fdrv/aicwf_wext_linux.h       |   15 +
 .../net/wireless/aic/aic8800_fdrv/hal_desc.h  |  362 ++
 .../wireless/aic/aic8800_fdrv/ipc_compat.h    |   25 +
 .../net/wireless/aic/aic8800_fdrv/ipc_host.c  |   42 +
 .../net/wireless/aic/aic8800_fdrv/ipc_host.h  |  169 +
 .../wireless/aic/aic8800_fdrv/ipc_shared.h    |  781 +++
 .../net/wireless/aic/aic8800_fdrv/lmac_mac.h  |  470 ++
 .../net/wireless/aic/aic8800_fdrv/lmac_msg.h  | 3124 ++++++++++
 .../wireless/aic/aic8800_fdrv/lmac_types.h    |   37 +
 drivers/net/wireless/aic/aic8800_fdrv/md5.c   |  175 +
 drivers/net/wireless/aic/aic8800_fdrv/md5.h   |   82 +
 .../wireless/aic/aic8800_fdrv/reg_access.h    |  146 +
 drivers/net/wireless/aic/aic8800_fdrv/regdb.c | 2770 +++++++++
 .../wireless/aic/aic8800_fdrv/rwnx_bfmer.c    |   93 +
 .../wireless/aic/aic8800_fdrv/rwnx_bfmer.h    |  100 +
 .../wireless/aic/aic8800_fdrv/rwnx_cfgfile.c  |  265 +
 .../wireless/aic/aic8800_fdrv/rwnx_cfgfile.h  |   33 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_cmds.c |  471 ++
 .../net/wireless/aic/aic8800_fdrv/rwnx_cmds.h |   99 +
 .../wireless/aic/aic8800_fdrv/rwnx_compat.h   |   93 +
 .../wireless/aic/aic8800_fdrv/rwnx_debugfs.c  | 2585 ++++++++
 .../wireless/aic/aic8800_fdrv/rwnx_debugfs.h  |  134 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_defs.h |  744 +++
 .../wireless/aic/aic8800_fdrv/rwnx_events.h   |  938 +++
 .../wireless/aic/aic8800_fdrv/rwnx_fw_trace.c |   50 +
 .../wireless/aic/aic8800_fdrv/rwnx_fw_trace.h |   28 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_gki.c  |  406 ++
 .../net/wireless/aic/aic8800_fdrv/rwnx_gki.h  |   46 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_irqs.c |   44 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_irqs.h |   12 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_main.c | 5406 +++++++++++++++++
 .../net/wireless/aic/aic8800_fdrv/rwnx_main.h |   34 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_mesh.c |   33 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_mesh.h |   35 +
 .../aic/aic8800_fdrv/rwnx_mod_params.c        | 1295 ++++
 .../aic/aic8800_fdrv/rwnx_mod_params.h        |   70 +
 .../wireless/aic/aic8800_fdrv/rwnx_msg_rx.c   | 1742 ++++++
 .../wireless/aic/aic8800_fdrv/rwnx_msg_rx.h   |    8 +
 .../wireless/aic/aic8800_fdrv/rwnx_msg_tx.c   | 3815 ++++++++++++
 .../wireless/aic/aic8800_fdrv/rwnx_msg_tx.h   |  285 +
 .../wireless/aic/aic8800_fdrv/rwnx_mu_group.c |  646 ++
 .../wireless/aic/aic8800_fdrv/rwnx_mu_group.h |  159 +
 .../wireless/aic/aic8800_fdrv/rwnx_platform.c | 2946 +++++++++
 .../wireless/aic/aic8800_fdrv/rwnx_platform.h |  186 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_prof.h |  142 +
 .../wireless/aic/aic8800_fdrv/rwnx_radar.c    | 1965 ++++++
 .../wireless/aic/aic8800_fdrv/rwnx_radar.h    |  278 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_rx.c   | 2443 ++++++++
 .../net/wireless/aic/aic8800_fdrv/rwnx_rx.h   |  358 ++
 .../net/wireless/aic/aic8800_fdrv/rwnx_strs.c |  268 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_strs.h |   31 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_tdls.c |  776 +++
 .../net/wireless/aic/aic8800_fdrv/rwnx_tdls.h |   57 +
 .../wireless/aic/aic8800_fdrv/rwnx_testmode.c |  217 +
 .../wireless/aic/aic8800_fdrv/rwnx_testmode.h |   68 +
 .../wireless/aic/aic8800_fdrv/rwnx_trace.c    |    5 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_tx.c   | 1805 ++++++
 .../net/wireless/aic/aic8800_fdrv/rwnx_tx.h   |  193 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_txq.c  | 1379 +++++
 .../net/wireless/aic/aic8800_fdrv/rwnx_txq.h  |  372 ++
 .../wireless/aic/aic8800_fdrv/rwnx_utils.c    |   36 +
 .../wireless/aic/aic8800_fdrv/rwnx_utils.h    |  131 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_v7.c   |  182 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_v7.h   |   21 +
 .../wireless/aic/aic8800_fdrv/rwnx_version.h  |   14 +
 .../aic/aic8800_fdrv/rwnx_version_gen.h       |    5 +
 .../wireless/aic/aic8800_fdrv/rwnx_wakelock.c |  109 +
 .../wireless/aic/aic8800_fdrv/rwnx_wakelock.h |   24 +
 .../net/wireless/aic/aic8800_fdrv/sdio_host.c |  132 +
 .../net/wireless/aic/aic8800_fdrv/sdio_host.h |   39 +
 132 files changed, 67273 insertions(+)
 create mode 100644 drivers/net/wireless/aic/Kconfig
 create mode 100644 drivers/net/wireless/aic/Makefile
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/Kconfig
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/Makefile
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic8800d80_compat.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic8800d80_compat.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic8800dc_compat.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic8800dc_compat.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_bsp_driver.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_bsp_driver.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_bsp_export.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_bsp_main.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_chip_8800d80.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_chip_8800dc.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_chip_8801.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_chip_ops.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_chip_ops.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aicsdio.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aicsdio.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aicsdio_txrxif.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aicsdio_txrxif.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aicwf_txq_prealloc.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aicwf_txq_prealloc.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/md5.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/md5.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/rwnx_version_gen.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/Kconfig
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/Makefile
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_br_ext.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_br_ext.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_bsp_export.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_btsdio.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_btsdio.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_bus.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_priv_cmd.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_priv_cmd.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_vendor.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_vendor.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_8800d80.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_8800dc.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_8801.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_ops.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_ops.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_compat_8800d80.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_compat_8800d80.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_compat_8800dc.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_compat_8800dc.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_debug.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_genl.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_genl.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_rx_prealloc.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_rx_prealloc.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_sdio.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_sdio.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_tcp_ack.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_tcp_ack.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_txrxif.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_txrxif.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_wext_linux.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_wext_linux.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/hal_desc.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/ipc_compat.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/ipc_host.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/ipc_host.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/ipc_shared.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/lmac_mac.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/lmac_msg.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/lmac_types.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/md5.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/md5.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/reg_access.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/regdb.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_bfmer.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_bfmer.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_cfgfile.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_cfgfile.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_cmds.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_cmds.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_compat.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_debugfs.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_debugfs.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_defs.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_events.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_fw_trace.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_fw_trace.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_gki.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_gki.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_irqs.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_irqs.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_main.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_main.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_mesh.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_mesh.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_mod_params.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_mod_params.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_msg_rx.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_msg_rx.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_msg_tx.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_msg_tx.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_mu_group.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_mu_group.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_platform.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_platform.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_prof.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_radar.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_radar.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_rx.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_rx.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_strs.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_strs.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_tdls.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_tdls.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_testmode.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_testmode.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_trace.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_tx.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_tx.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_txq.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_txq.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_utils.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_utils.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_v7.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_v7.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_version.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_version_gen.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_wakelock.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_wakelock.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/sdio_host.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/sdio_host.h

base-commit: ac798f757d6475dc6fee2ec899980d6740714596

author
#1 lore raw

RFC PATCH 1/4 wifi: aic: add SDIO BSP and build configuration

From: Zhirun Liu <[email protected]>

Add the vendor, BSP and FullMAC build descriptions together with the shared SDIO BSP, firmware loader and BSP chipset support. Keep parent wireless build integration in the final patch.

---
 drivers/net/wireless/aic/Kconfig              |  135 ++
 drivers/net/wireless/aic/Makefile             |   17 +
 drivers/net/wireless/aic/aic8800_bsp/Kconfig  |   97 +
 drivers/net/wireless/aic/aic8800_bsp/Makefile |   42 +
 .../aic/aic8800_bsp/aic8800d80_compat.c       |  290 +++
 .../aic/aic8800_bsp/aic8800d80_compat.h       |   11 +
 .../aic/aic8800_bsp/aic8800dc_compat.c        | 1353 +++++++++++
 .../aic/aic8800_bsp/aic8800dc_compat.h        |   40 +
 .../wireless/aic/aic8800_bsp/aic_bsp_driver.c | 1659 ++++++++++++++
 .../wireless/aic/aic8800_bsp/aic_bsp_driver.h |  621 +++++
 .../wireless/aic/aic8800_bsp/aic_bsp_export.h |   70 +
 .../wireless/aic/aic8800_bsp/aic_bsp_main.c   |  556 +++++
 .../aic/aic8800_bsp/aic_chip_8800d80.c        |  116 +
 .../aic/aic8800_bsp/aic_chip_8800dc.c         |  133 ++
 .../wireless/aic/aic8800_bsp/aic_chip_8801.c  |  117 +
 .../wireless/aic/aic8800_bsp/aic_chip_ops.c   |   77 +
 .../wireless/aic/aic8800_bsp/aic_chip_ops.h   |   71 +
 .../net/wireless/aic/aic8800_bsp/aicsdio.c    | 1999 +++++++++++++++++
 .../net/wireless/aic/aic8800_bsp/aicsdio.h    |  176 ++
 .../wireless/aic/aic8800_bsp/aicsdio_txrxif.c |  465 ++++
 .../wireless/aic/aic8800_bsp/aicsdio_txrxif.h |  180 ++
 .../aic/aic8800_bsp/aicwf_txq_prealloc.c      |   66 +
 .../aic/aic8800_bsp/aicwf_txq_prealloc.h      |    8 +
 drivers/net/wireless/aic/aic8800_bsp/md5.c    |  165 ++
 drivers/net/wireless/aic/aic8800_bsp/md5.h    |   77 +
 .../aic/aic8800_bsp/rwnx_version_gen.h        |    5 +
 drivers/net/wireless/aic/aic8800_fdrv/Kconfig |  539 +++++
 .../net/wireless/aic/aic8800_fdrv/Makefile    |  117 +
 28 files changed, 9202 insertions(+)
 create mode 100644 drivers/net/wireless/aic/Kconfig
 create mode 100644 drivers/net/wireless/aic/Makefile
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/Kconfig
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/Makefile
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic8800d80_compat.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic8800d80_compat.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic8800dc_compat.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic8800dc_compat.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_bsp_driver.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_bsp_driver.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_bsp_export.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_bsp_main.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_chip_8800d80.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_chip_8800dc.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_chip_8801.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_chip_ops.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aic_chip_ops.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aicsdio.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aicsdio.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aicsdio_txrxif.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aicsdio_txrxif.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aicwf_txq_prealloc.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/aicwf_txq_prealloc.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/md5.c
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/md5.h
 create mode 100644 drivers/net/wireless/aic/aic8800_bsp/rwnx_version_gen.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/Kconfig
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/Makefile
drivers/net/wireless/aic/Kconfig new file +135 -0
new file mode 100644
index 0000000000000..ed62a5f2d9333
@@ -0,0 +1,135 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config WLAN_VENDOR_AIC
+	bool "AIC devices"
+	default y
+	help
+	  Say Y to expose drivers for wireless devices based on AIC
+	  chipsets. The individual bus and WLAN drivers remain separately
+	  selectable below this vendor menu. Saying N hides those driver
+	  questions without changing any unrelated wireless drivers.
+
+if WLAN_VENDOR_AIC
+
+menuconfig AIC8800_BSP_SUPPORT
+	tristate "AIC8800 SDIO bus support"
+	depends on MMC
+	help
+	  Enable the AIC8800 bus support package. It provides the SDIO
+	  transport, chip operations and firmware download infrastructure
+	  shared by the AIC8800 FullMAC WLAN driver.
+	  Firmware files are loaded from the aic8800/ subdirectory of the
+	  kernel firmware search path, normally /lib/firmware/aic8800/.
+
+	  If unsure, say N.
+
+if AIC8800_BSP_SUPPORT
+
+# The current driver only implements an SDIO transport. Keep this internal
+# symbol for the existing Makefile and C preprocessor conditionals.
+config AIC8800_SDIO_SUPPORT
+	def_bool y
+
+menu "AIC8800 common firmware and transport options"
+
+config AIC8800_SDIO_PWRCTRL
+	bool "SDIO power control"
+	default y
+	help
+	  Allow the driver to control the SDIO interface power state while
+	  bringing the AIC device up and down. The BSP coordinates this
+	  state with firmware download and the WLAN function. This is the
+	  normal setting for supported AIC8800 SDIO modules.
+
+	  If unsure, say Y.
+
+config AIC8800_GPIO_WAKEUP
+	bool "GPIO wakeup support"
+	default y
+	help
+	  Enable a dedicated GPIO signal for device-to-host wakeup. The
+	  signal lets the device wake the host without polling the SDIO
+	  bus. Board wiring and firmware must both provide the wake signal.
+	  Disable this when the board has no dedicated wake GPIO.
+
+	  If unsure, say Y.
+
+config AIC8800_OOB
+	bool "Out-of-band interrupt support"
+	depends on AIC8800_GPIO_WAKEUP
+	help
+	  Use a dedicated GPIO interrupt instead of the in-band SDIO
+	  interrupt. The GPIO must be described by the platform and wired
+	  to the AIC device interrupt output. This mode is only suitable
+	  for boards whose firmware and hardware use out-of-band signaling.
+
+config AIC8800_PREALLOC_TXQ
+	bool "Preallocate TX queues"
+	default y
+	help
+	  Preallocate transmit queue buffers during driver initialization.
+	  This avoids data-path allocations after the interface starts and
+	  can reduce latency under memory pressure. It also reserves the
+	  queue memory for the lifetime of the driver.
+
+	  If unsure, say Y.
+
+config AIC8800_DPD
+	bool "DPD calibration support"
+	default y
+	help
+	  Enable Digital Pre-Distortion calibration support for radio
+	  transmit-path linearization. The driver loads or generates DPD
+	  data expected by supported firmware. Keep this enabled for boards
+	  whose supplied firmware requires DPD calibration data.
+
+	  If unsure, say Y.
+
+config AIC8800_FORCE_DPD_CALIB
+	bool "Force DPD calibration"
+	depends on AIC8800_DPD
+	default y
+	help
+	  Force DPD calibration instead of using existing calibration data.
+	  This makes initialization regenerate the result even when stored
+	  calibration data is available. It increases startup work but can
+	  be useful while validating a new board or radio configuration.
+
+config AIC8800_RESV_MEM_SUPPORT
+	bool "Reserved memory support"
+	default y
+	help
+	  Enable the driver's reserved-memory allocation path for transport
+	  buffers. Platforms may use this to avoid allocating large buffers
+	  during device initialization. The reserved area must be supplied
+	  by the platform integration when this option is selected.
+
+	  If unsure, say Y.
+
+config AIC8800_SDIO_BT
+	bool "Bluetooth over SDIO support"
+	depends on BROKEN
+	help
+	  Enable the downstream Bluetooth transport sharing the Wi-Fi SDIO
+	  interface. The retained implementation uses interfaces that are
+	  not available to a current mainline kernel. It remains disabled
+	  until it is converted to the upstream Bluetooth HCI interfaces.
+
+config AIC8800_VRF_DCDC_MODE
+	bool "VRF DCDC mode"
+	default y
+	help
+	  Configure the chipset's VRF rail to use its internal DC-DC mode.
+	  This affects radio power delivery and must agree with the module
+	  and board power design. The standard supported configuration uses
+	  the internal converter. Check the board design before changing it.
+
+	  If unsure, say Y.
+
+endmenu
+
+source "drivers/net/wireless/aic/aic8800_bsp/Kconfig"
+source "drivers/net/wireless/aic/aic8800_fdrv/Kconfig"
+
+endif # AIC8800_BSP_SUPPORT
+endif # WLAN_VENDOR_AIC
drivers/net/wireless/aic/Makefile new file +17 -0
new file mode 100644
index 0000000000000..247f7fbbc83b4
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_AIC8800_WLAN_SUPPORT) += aic8800_fdrv/
+obj-$(CONFIG_AIC8800_BSP_SUPPORT) += aic8800_bsp/
+
+ccflags-$(CONFIG_AIC8800_SDIO_SUPPORT)       += -DAICWF_SDIO_SUPPORT
+ccflags-$(CONFIG_AIC8800_SDIO_PWRCTRL)       += -DCONFIG_SDIO_PWRCTRL
+ccflags-$(CONFIG_AIC8800_GPIO_WAKEUP)        += -DCONFIG_GPIO_WAKEUP
+ccflags-$(CONFIG_AIC8800_OOB)                += -DCONFIG_OOB
+ccflags-$(CONFIG_AIC8800_PREALLOC_TXQ)       += -DCONFIG_PREALLOC_TXQ
+ccflags-$(CONFIG_AIC8800_PREALLOC_RX_SKB)    += -DCONFIG_PREALLOC_RX_SKB
+ccflags-$(CONFIG_AIC8800_DPD)                += -DCONFIG_DPD
+ccflags-$(CONFIG_AIC8800_FORCE_DPD_CALIB)    += -DCONFIG_FORCE_DPD_CALIB
+ccflags-$(CONFIG_AIC8800_RESV_MEM_SUPPORT)   += -DCONFIG_RESV_MEM_SUPPORT
+ccflags-$(CONFIG_AIC8800_SDIO_BT)            += -DCONFIG_SDIO_BT
+ccflags-$(CONFIG_AIC8800_FDRV_NO_REG_SDIO)   += -DCONFIG_FDRV_NO_REG_SDIO
+ccflags-$(CONFIG_AIC8800_VRF_DCDC_MODE)      += -DCONFIG_VRF_DCDC_MODE
drivers/net/wireless/aic/aic8800_bsp/Kconfig new file +97 -0

97 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/Makefile new file +42 -0

42 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aic8800d80_compat.c new file +290 -0

290 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aic8800d80_compat.h new file +11 -0
new file mode 100644
index 0000000000000..a22e440b09a66
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _AIC8800D80_COMPAT_H_
+#define _AIC8800D80_COMPAT_H_
+
+#include "aicsdio.h"
+
+int aicbsp_system_config_8800d80(struct aic_sdio_dev *sdiodev);
+int aicwifi_sys_config_8800d80(struct aic_sdio_dev *sdiodev);
+int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev);
+
+#endif
drivers/net/wireless/aic/aic8800_bsp/aic8800dc_compat.c new file +1353 -0

1,353 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aic8800dc_compat.h new file +40 -0
new file mode 100644
index 0000000000000..3db89a92dfe01
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _AIC8800DC_COMPAT_H_
+#define _AIC8800DC_COMPAT_H_
+
+#include "aicsdio.h"
+typedef u32 (*array2_tbl_t)[2];
+typedef u32 (*array3_tbl_t)[3];
+
+typedef u8 u8_l;
+typedef s8 s8_l;
+typedef u16 u16_l;
+typedef s16 s16_l;
+typedef u32 u32_l;
+typedef s32 s32_l;
+typedef u64 u64_l;
+
+extern u8 chip_sub_id;
+extern u8 chip_mcu_id;
+#define FW_PATH_MAX_LEN 200
+
+void aicwf_patch_config_8800dc(struct aic_sdio_dev *rwnx_hw);
+void system_config_8800dc(struct aic_sdio_dev *rwnx_hw);
+int rwnx_plat_patch_load_8800dc(struct aic_sdio_dev *sdiodev);
+int aicwf_misc_ram_init_8800dc(struct aic_sdio_dev *sdiodev);
+int start_from_bootrom_8800DC(struct aic_sdio_dev *sdiodev);
+
+#ifdef CONFIG_DPD
+int aicwf_dpd_calib_8800dc(struct aic_sdio_dev *sdiodev,
+			   struct rf_misc_ram_lite_t *dpd_res);
+int aicwf_dpd_result_apply_8800dc(struct aic_sdio_dev *sdiodev,
+				  struct rf_misc_ram_lite_t *dpd_res);
+#ifndef CONFIG_FORCE_DPD_CALIB
+int aicwf_dpd_result_load_8800dc(struct aic_sdio_dev *sdiodev,
+				 struct rf_misc_ram_lite_t *dpd_res);
+#endif /* !CONFIG_FORCE_DPD_CALIB */
+#endif
+
+int set_bbpll_config(struct aic_sdio_dev *rwnx_hw);
+
+#endif
drivers/net/wireless/aic/aic8800_bsp/aic_bsp_driver.c new file +1659 -0

1,015 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aic_bsp_driver.h new file +621 -0

621 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aic_bsp_export.h new file +70 -0

70 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aic_bsp_main.c new file +556 -0

556 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aic_chip_8800d80.c new file +116 -0

116 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aic_chip_8800dc.c new file +133 -0

133 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aic_chip_8801.c new file +117 -0

117 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aic_chip_ops.c new file +77 -0

77 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aic_chip_ops.h new file +71 -0

71 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aicsdio.c new file +1999 -0

1,999 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aicsdio.h new file +176 -0

176 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aicsdio_txrxif.c new file +465 -0

465 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aicsdio_txrxif.h new file +180 -0

180 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aicwf_txq_prealloc.c new file +66 -0

66 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/aicwf_txq_prealloc.h new file +8 -0
new file mode 100644
index 0000000000000..680d37ffca931

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_bsp/md5.c new file +165 -0

165 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/md5.h new file +77 -0

77 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_bsp/rwnx_version_gen.h new file +5 -0
new file mode 100644
index 0000000000000..8768db424ce78

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/Kconfig new file +539 -0

539 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/Makefile new file +117 -0

117 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Part of the diff is not shown here. View the raw message.

author
#2 lore raw

RFC PATCH 2/4 wifi: aic: add FullMAC firmware and platform interface

In reply to Yanli Yang

From: Zhirun Liu <[email protected]>

Add the FullMAC IPC and LMAC protocol definitions, command serialization, firmware request and confirmation handling, platform bring-up, interrupt helpers and BSP integration.

---
 .../aic/aic8800_fdrv/aic_bsp_export.h         |   62 +
 .../net/wireless/aic/aic8800_fdrv/aic_bus.h   |  191 +
 .../wireless/aic/aic8800_fdrv/aicwf_debug.h   |   37 +
 .../net/wireless/aic/aic8800_fdrv/hal_desc.h  |  362 ++
 .../wireless/aic/aic8800_fdrv/ipc_compat.h    |   25 +
 .../net/wireless/aic/aic8800_fdrv/ipc_host.c  |   42 +
 .../net/wireless/aic/aic8800_fdrv/ipc_host.h  |  169 +
 .../wireless/aic/aic8800_fdrv/ipc_shared.h    |  781 ++++
 .../net/wireless/aic/aic8800_fdrv/lmac_mac.h  |  470 ++
 .../net/wireless/aic/aic8800_fdrv/lmac_msg.h  | 3124 ++++++++++++++
 .../wireless/aic/aic8800_fdrv/lmac_types.h    |   37 +
 drivers/net/wireless/aic/aic8800_fdrv/md5.c   |  175 +
 drivers/net/wireless/aic/aic8800_fdrv/md5.h   |   82 +
 .../wireless/aic/aic8800_fdrv/reg_access.h    |  146 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_cmds.c |  471 ++
 .../net/wireless/aic/aic8800_fdrv/rwnx_cmds.h |   99 +
 .../wireless/aic/aic8800_fdrv/rwnx_compat.h   |   93 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_defs.h |  744 ++++
 .../wireless/aic/aic8800_fdrv/rwnx_events.h   |  938 ++++
 .../net/wireless/aic/aic8800_fdrv/rwnx_irqs.c |   44 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_irqs.h |   12 +
 .../wireless/aic/aic8800_fdrv/rwnx_msg_rx.c   | 1742 ++++++++
 .../wireless/aic/aic8800_fdrv/rwnx_msg_rx.h   |    8 +
 .../wireless/aic/aic8800_fdrv/rwnx_msg_tx.c   | 3815 +++++++++++++++++
 .../wireless/aic/aic8800_fdrv/rwnx_msg_tx.h   |  285 ++
 .../wireless/aic/aic8800_fdrv/rwnx_platform.c | 2946 +++++++++++++
 .../wireless/aic/aic8800_fdrv/rwnx_platform.h |  186 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_prof.h |  142 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_strs.c |  268 ++
 .../net/wireless/aic/aic8800_fdrv/rwnx_strs.h |   31 +
 .../wireless/aic/aic8800_fdrv/rwnx_utils.c    |   36 +
 .../wireless/aic/aic8800_fdrv/rwnx_utils.h    |  131 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_v7.c   |  182 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_v7.h   |   21 +
 .../wireless/aic/aic8800_fdrv/rwnx_version.h  |   14 +
 .../aic/aic8800_fdrv/rwnx_version_gen.h       |    5 +
 .../wireless/aic/aic8800_fdrv/rwnx_wakelock.c |  109 +
 .../wireless/aic/aic8800_fdrv/rwnx_wakelock.h |   24 +
 38 files changed, 18049 insertions(+)
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_bsp_export.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_bus.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_debug.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/hal_desc.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/ipc_compat.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/ipc_host.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/ipc_host.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/ipc_shared.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/lmac_mac.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/lmac_msg.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/lmac_types.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/md5.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/md5.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/reg_access.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_cmds.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_cmds.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_compat.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_defs.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_events.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_irqs.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_irqs.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_msg_rx.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_msg_rx.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_msg_tx.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_msg_tx.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_platform.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_platform.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_prof.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_strs.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_strs.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_utils.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_utils.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_v7.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_v7.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_version.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_version_gen.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_wakelock.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_wakelock.h
drivers/net/wireless/aic/aic8800_fdrv/aic_bsp_export.h new file +62 -0
new file mode 100644
index 0000000000000..11b414df42ce3
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __AIC_BSP_EXPORT_H
+#define __AIC_BSP_EXPORT_H
+
+#include <linux/types.h>
+
+enum aicbsp_subsys {
+	AIC_BLUETOOTH,
+	AIC_WIFI,
+};
+
+enum aicbsp_pwr_state {
+	AIC_PWR_OFF,
+	AIC_PWR_ON,
+};
+
+struct aicbsp_feature_t {
+	int hwinfo;
+	u32 sdio_clock;
+	u8 sdio_phase;
+	int fwlog_en;
+	u8 irqf;
+	u8 cpmode;
+	int adapt;
+};
+
+enum skb_buff_id {
+	AIC_RESV_MEM_TXDATA,
+};
+
+#ifdef CONFIG_DPD
+struct rf_misc_ram_t {
+	u32 bit_mask[3];
+	u32 reserved;
+	u32 dpd_high[96];
+	u32 dpd_11b[96];
+	u32 dpd_low[96];
+	u32 idac_11b[48];
+	u32 idac_high[48];
+	u32 idac_low[48];
+	u32 loft_res[18];
+	u32 rx_iqim_res[16];
+};
+
+struct rf_misc_ram_lite_t {
+	u32 bit_mask[4];
+	u32 dpd_high[96];
+	u32 loft_res[18];
+};
+
+#define MEMBER_SIZE(type, member) sizeof_field(type, member)
+#define DPD_RESULT_SIZE_8800DC    sizeof(struct rf_misc_ram_lite_t)
+
+extern struct rf_misc_ram_lite_t dpd_res;
+#endif
+
+int aicbsp_set_subsys(int, int);
+int aicbsp_get_feature(struct aicbsp_feature_t *feature);
+struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id);
+void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id);
+
+#endif
drivers/net/wireless/aic/aic8800_fdrv/aic_bus.h new file +191 -0

191 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_debug.h new file +37 -0
new file mode 100644
index 0000000000000..4a49c16f15a31
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _AICWF_DEBUG_H_
+#define _AICWF_DEBUG_H_
+
+#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__
+
+/* message levels */
+#define LOGERROR    0x0001
+#define LOGINFO     0x0002
+#define LOGTRACE    0x0004
+#define LOGDEBUG    0x0008
+#define LOGDATA     0x0010
+#define LOGIRQ      0x0020
+#define LOGSDPWRC   0x0040
+#define LOGWAKELOCK 0x0080
+#define LOGRXPOLL   0x0100
+
+extern int aicwf_dbg_level;
+void rwnx_data_dump(char *tag, void *data, unsigned long len);
+
+#define AICWF_LOG "AICWFDBG("
+
+#define AICWFDBG(level, args, arg...)                                          \
+	do {                                                                       \
+		if (aicwf_dbg_level & (level)) {                                         \
+			pr_debug(AICWF_LOG #level ")\t" args, ##arg);                        \
+		}                                                                      \
+	} while (0)
+
+#define RWNX_DBG(fmt, ...)                                                     \
+	do {                                                                       \
+		if (aicwf_dbg_level & LOGTRACE) {                                      \
+			pr_debug(AICWF_LOG "LOGTRACE)\t" fmt, ##__VA_ARGS__);                \
+		}                                                                      \
+	} while (0)
+
+#endif /* _AICWF_DEBUG_H_ */
drivers/net/wireless/aic/aic8800_fdrv/hal_desc.h new file +362 -0

362 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/ipc_compat.h new file +25 -0
new file mode 100644
index 0000000000000..8c5b22ce74d0a
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/**
+ ****************************************************************************************
+ *
+ * Copyright (C) 2020 AIC semiconductor.
+ *
+ ****************************************************************************************
+ */
+
+#ifndef _IPC_H_
+#define _IPC_H_
+
+#define __INLINE inline
+
+#define __ALIGN4 __aligned(4)
+
+#define ASSERT_ERR(condition)                                                  \
+	do {                                                                       \
+		if (unlikely(!(condition))) {                                          \
+			pr_err("%s:%d:ASSERT_ERR(" #condition ")\n", __FILE__,    \
+				   __LINE__);                                                  \
+		}                                                                      \
+	} while (0)
+
+#endif /* _IPC_H_ */
drivers/net/wireless/aic/aic8800_fdrv/ipc_host.c new file +42 -0

42 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/ipc_host.h new file +169 -0

169 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/ipc_shared.h new file +781 -0

781 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/lmac_mac.h new file +470 -0

470 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/lmac_msg.h new file +3124 -0

861 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/lmac_types.h new file +37 -0
new file mode 100644
index 0000000000000..59537b4575ddd

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/md5.c new file +175 -0

175 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/md5.h new file +82 -0

82 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/reg_access.h new file +146 -0

146 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_cmds.c new file +471 -0

471 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_cmds.h new file +99 -0

99 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_compat.h new file +93 -0

93 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_defs.h new file +744 -0

744 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_events.h new file +938 -0

938 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_irqs.c new file +44 -0

44 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_irqs.h new file +12 -0
new file mode 100644
index 0000000000000..ff6c766c727c3

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/rwnx_msg_rx.c new file +1742 -0

1,742 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_msg_rx.h new file +8 -0
new file mode 100644
index 0000000000000..211f2e616cbf4

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/rwnx_msg_tx.c new file +3815 -0

3,815 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_msg_tx.h new file +285 -0

285 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_platform.c new file +2946 -0

2,946 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_platform.h new file +186 -0

186 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_prof.h new file +142 -0

142 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_strs.c new file +268 -0

268 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_strs.h new file +31 -0
new file mode 100644
index 0000000000000..73de33c4f1c7d

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/rwnx_utils.c new file +36 -0
new file mode 100644
index 0000000000000..532b7cbb55b0e

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/rwnx_utils.h new file +131 -0

131 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_v7.c new file +182 -0

182 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_v7.h new file +21 -0
new file mode 100644
index 0000000000000..c77f26e48ee26

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/rwnx_version.h new file +14 -0
new file mode 100644
index 0000000000000..7f3f2d88d2d98

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/rwnx_version_gen.h new file +5 -0
new file mode 100644
index 0000000000000..8768db424ce78

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/rwnx_wakelock.c new file +109 -0

109 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_wakelock.h new file +24 -0
new file mode 100644
index 0000000000000..f3ec804f5732d

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Part of the diff is not shown here. View the raw message.

author
#3 lore raw

RFC PATCH 3/4 wifi: aic: add FullMAC WLAN driver

In reply to Yanli Yang

From: Zhirun Liu <[email protected]>

Add the cfg80211 FullMAC core, regulatory and configuration paths, TX/RX data path, SDIO and chipset integration, advanced wireless features, diagnostics and retained downstream compatibility interfaces.

This is the complete untrimmed RFC implementation. Private interfaces, the copied regulatory database and INI configuration are included for design review and are not claimed to be merge-ready.

---
 .../wireless/aic/aic8800_fdrv/aic_br_ext.c    | 1598 +++++
 .../wireless/aic/aic8800_fdrv/aic_br_ext.h    |   72 +
 .../wireless/aic/aic8800_fdrv/aic_btsdio.c    | 1164 ++++
 .../wireless/aic/aic8800_fdrv/aic_btsdio.h    |  472 ++
 .../wireless/aic/aic8800_fdrv/aic_priv_cmd.c  | 1967 ++++++
 .../wireless/aic/aic8800_fdrv/aic_priv_cmd.h  |  127 +
 .../wireless/aic/aic8800_fdrv/aic_vendor.c    |  950 +++
 .../wireless/aic/aic8800_fdrv/aic_vendor.h    |  370 ++
 .../aic/aic8800_fdrv/aicwf_chip_8800d80.c     |  291 +
 .../aic/aic8800_fdrv/aicwf_chip_8800dc.c      |  300 +
 .../aic/aic8800_fdrv/aicwf_chip_8801.c        |  279 +
 .../aic/aic8800_fdrv/aicwf_chip_ops.c         |  267 +
 .../aic/aic8800_fdrv/aicwf_chip_ops.h         |  186 +
 .../aic/aic8800_fdrv/aicwf_compat_8800d80.c   |   96 +
 .../aic/aic8800_fdrv/aicwf_compat_8800d80.h   |   16 +
 .../aic/aic8800_fdrv/aicwf_compat_8800dc.c    |  505 ++
 .../aic/aic8800_fdrv/aicwf_compat_8800dc.h    |   22 +
 .../wireless/aic/aic8800_fdrv/aicwf_genl.c    |  932 +++
 .../wireless/aic/aic8800_fdrv/aicwf_genl.h    |  112 +
 .../aic/aic8800_fdrv/aicwf_rx_prealloc.c      |  102 +
 .../aic/aic8800_fdrv/aicwf_rx_prealloc.h      |   32 +
 .../wireless/aic/aic8800_fdrv/aicwf_sdio.c    | 2813 +++++++++
 .../wireless/aic/aic8800_fdrv/aicwf_sdio.h    |  264 +
 .../wireless/aic/aic8800_fdrv/aicwf_tcp_ack.c |  572 ++
 .../wireless/aic/aic8800_fdrv/aicwf_tcp_ack.h |  104 +
 .../wireless/aic/aic8800_fdrv/aicwf_txrxif.c  |  753 +++
 .../wireless/aic/aic8800_fdrv/aicwf_txrxif.h  |  217 +
 .../aic/aic8800_fdrv/aicwf_wext_linux.c       | 1137 ++++
 .../aic/aic8800_fdrv/aicwf_wext_linux.h       |   15 +
 drivers/net/wireless/aic/aic8800_fdrv/regdb.c | 2770 +++++++++
 .../wireless/aic/aic8800_fdrv/rwnx_bfmer.c    |   93 +
 .../wireless/aic/aic8800_fdrv/rwnx_bfmer.h    |  100 +
 .../wireless/aic/aic8800_fdrv/rwnx_cfgfile.c  |  265 +
 .../wireless/aic/aic8800_fdrv/rwnx_cfgfile.h  |   33 +
 .../wireless/aic/aic8800_fdrv/rwnx_debugfs.c  | 2585 ++++++++
 .../wireless/aic/aic8800_fdrv/rwnx_debugfs.h  |  134 +
 .../wireless/aic/aic8800_fdrv/rwnx_fw_trace.c |   50 +
 .../wireless/aic/aic8800_fdrv/rwnx_fw_trace.h |   28 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_gki.c  |  406 ++
 .../net/wireless/aic/aic8800_fdrv/rwnx_gki.h  |   46 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_main.c | 5406 +++++++++++++++++
 .../net/wireless/aic/aic8800_fdrv/rwnx_main.h |   34 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_mesh.c |   33 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_mesh.h |   35 +
 .../aic/aic8800_fdrv/rwnx_mod_params.c        | 1295 ++++
 .../aic/aic8800_fdrv/rwnx_mod_params.h        |   70 +
 .../wireless/aic/aic8800_fdrv/rwnx_mu_group.c |  646 ++
 .../wireless/aic/aic8800_fdrv/rwnx_mu_group.h |  159 +
 .../wireless/aic/aic8800_fdrv/rwnx_radar.c    | 1965 ++++++
 .../wireless/aic/aic8800_fdrv/rwnx_radar.h    |  278 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_rx.c   | 2443 ++++++++
 .../net/wireless/aic/aic8800_fdrv/rwnx_rx.h   |  358 ++
 .../net/wireless/aic/aic8800_fdrv/rwnx_tdls.c |  776 +++
 .../net/wireless/aic/aic8800_fdrv/rwnx_tdls.h |   57 +
 .../wireless/aic/aic8800_fdrv/rwnx_testmode.c |  217 +
 .../wireless/aic/aic8800_fdrv/rwnx_testmode.h |   68 +
 .../wireless/aic/aic8800_fdrv/rwnx_trace.c    |    5 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_tx.c   | 1805 ++++++
 .../net/wireless/aic/aic8800_fdrv/rwnx_tx.h   |  193 +
 .../net/wireless/aic/aic8800_fdrv/rwnx_txq.c  | 1379 +++++
 .../net/wireless/aic/aic8800_fdrv/rwnx_txq.h  |  372 ++
 .../net/wireless/aic/aic8800_fdrv/sdio_host.c |  132 +
 .../net/wireless/aic/aic8800_fdrv/sdio_host.h |   39 +
 63 files changed, 40010 insertions(+)
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_br_ext.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_br_ext.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_btsdio.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_btsdio.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_priv_cmd.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_priv_cmd.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_vendor.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aic_vendor.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_8800d80.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_8800dc.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_8801.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_ops.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_ops.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_compat_8800d80.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_compat_8800d80.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_compat_8800dc.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_compat_8800dc.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_genl.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_genl.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_rx_prealloc.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_rx_prealloc.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_sdio.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_sdio.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_tcp_ack.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_tcp_ack.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_txrxif.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_txrxif.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_wext_linux.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/aicwf_wext_linux.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/regdb.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_bfmer.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_bfmer.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_cfgfile.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_cfgfile.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_debugfs.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_debugfs.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_fw_trace.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_fw_trace.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_gki.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_gki.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_main.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_main.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_mesh.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_mesh.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_mod_params.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_mod_params.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_mu_group.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_mu_group.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_radar.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_radar.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_rx.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_rx.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_tdls.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_tdls.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_testmode.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_testmode.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_trace.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_tx.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_tx.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_txq.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/rwnx_txq.h
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/sdio_host.c
 create mode 100644 drivers/net/wireless/aic/aic8800_fdrv/sdio_host.h
drivers/net/wireless/aic/aic8800_fdrv/aic_br_ext.c new file +1598 -0
new file mode 100644
index 0000000000000..4dc33b367cac3
@@ -0,0 +1,1598 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *****************************************************************************
+ *
+ * Copyright (C) 2020 AIC semiconductor.
+ *
+ * @brief bridge function definitions
+ *
+ ****************************************************************************
+ */
+
+#define _AIC_BR_EXT_C_
+
+#ifdef __KERNEL__
+#include "rwnx_defs.h"
+#include <linux/atalk.h>
+#include <linux/if_arp.h>
+#include <linux/if_pppox.h>
+#include <linux/udp.h>
+#include <net/ip.h>
+#include <net/ipx.h>
+#endif
+
+#ifdef CL_IPV6_PASS
+#ifdef __KERNEL__
+#include <linux/icmpv6.h>
+#include <linux/ipv6.h>
+#include <net/ndisc.h>
+#include <net/checksum.h>
+#endif
+#endif
+
+#ifdef CONFIG_AIC8800_BR_SUPPORT
+
+/* #define BR_SUPPORT_DEBUG */
+
+#define NAT25_IPV4  01
+#define NAT25_IPV6  02
+#define NAT25_IPX   03
+#define NAT25_APPLE 04
+#define NAT25_PPPOE 05
+
+#define RTL_RELAY_TAG_LEN (ETH_ALEN)
+#define TAG_HDR_LEN       4
+
+#define MAGIC_CODE      0x8186
+#define MAGIC_CODE_LEN  2
+#define WAIT_TIME_PPPOE 5 /* waiting time for pppoe server in sec */
+
+/*-----------------------------------------------------------------
+ * How database records network address:
+ *		   0    1    2    3    4    5    6    7    8    9   10
+ *		|----|----|----|----|----|----|----|----|----|----|----|
+ * IPv4  |type|                             |      IP addr      |
+ * IPX   |type|      Net addr     |          Node addr          |
+ * IPX   |type|      Net addr     |Sckt addr|
+ * Apple |type| Network |node|
+ * PPPoE |type|   SID   |           AC MAC            |
+ *-----------------------------------------------------------------
+ */
+
+/* Find a tag in pppoe frame and return the pointer */
+static inline unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph,
+						    unsigned short type)
+{
+	unsigned char *cur_ptr, *start_ptr;
+	unsigned short tag_len, tag_type;
+
+	cur_ptr = (unsigned char *)ph->tag;
+	start_ptr = cur_ptr;
+	while ((cur_ptr - start_ptr) < ntohs(ph->length)) {
+		/* prevent un-alignment access */
+		tag_type = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]);
+		tag_len = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]);
+		if (tag_type == type)
+			return cur_ptr;
+		cur_ptr = cur_ptr + TAG_HDR_LEN + tag_len;
+	}
+	return 0;
+}
+
+static inline int __nat25_add_pppoe_tag(struct sk_buff *skb,
+					struct pppoe_tag *tag)
+{
+	struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
+	int data_len;
+
+	data_len = tag->tag_len + TAG_HDR_LEN;
+	if (skb_tailroom(skb) < data_len) {
+		pr_err("skb_tailroom() failed in add SID tag!\n");
+		return -1;
+	}
+
+	skb_put(skb, data_len);
+	/* have a room for new tag */
+	memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag,
+		ntohs(ph->length));
+	ph->length = htons(ntohs(ph->length) + data_len);
+	memcpy((unsigned char *)ph->tag, tag, data_len);
+	return data_len;
+}
+
+static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len)
+{
+	int tail_len;
+	unsigned long end, tail;
+
+	if ((src + len) > skb_tail_pointer(skb) || skb->len < len)
+		return -1;
+
+	tail = (unsigned long)skb_tail_pointer(skb);
+	end = (unsigned long)src + len;
+	if (tail < end)
+		return -1;
+
+	tail_len = (int)(tail - end);
+	if (tail_len > 0)
+		memmove(src, src + len, tail_len);
+
+	skb_trim(skb, skb->len - len);
+	return 0;
+}
+
+static inline unsigned long __nat25_timeout(struct rwnx_vif *vif)
+{
+	unsigned long timeout;
+
+	timeout = jiffies - NAT25_AGEING_TIME * HZ;
+
+	return timeout;
+}
+
+static inline int __nat25_has_expired(struct rwnx_vif *vif,
+				      struct nat25_network_db_entry *fdb)
+{
+	if (time_before_eq(fdb->ageing_timer, __nat25_timeout(vif)))
+		return 1;
+
+	return 0;
+}
+
+static inline void
+__nat25_generate_ipv4_network_addr(unsigned char *network_addr,
+				   unsigned int *ip_addr)
+{
+	memset(network_addr, 0, MAX_NETWORK_ADDR_LEN);
+
+	network_addr[0] = NAT25_IPV4;
+	memcpy(network_addr + 7, (unsigned char *)ip_addr, 4);
+}
+
+static inline void
+__nat25_generate_ipx_network_addr_with_node(unsigned char *network_addr,
+					    unsigned int *ipx_net_addr,
+					    unsigned char *ipx_node_addr)
+{
+	memset(network_addr, 0, MAX_NETWORK_ADDR_LEN);
+
+	network_addr[0] = NAT25_IPX;
+	memcpy(network_addr + 1, (unsigned char *)ipx_net_addr, 4);
+	memcpy(network_addr + 5, ipx_node_addr, 6);
+}
+
+static inline void
+__nat25_generate_ipx_network_addr_with_socket(unsigned char *network_addr,
+					      unsigned int *ipx_net_addr,
+					      unsigned short *ipx_socket_addr)
+{
+	memset(network_addr, 0, MAX_NETWORK_ADDR_LEN);
+
+	network_addr[0] = NAT25_IPX;
+	memcpy(network_addr + 1, (unsigned char *)ipx_net_addr, 4);
+	memcpy(network_addr + 5, (unsigned char *)ipx_socket_addr, 2);
+}
+
+static inline void __nat25_generate_apple_network_addr(unsigned char *network_addr,
+						       unsigned short *network,
+						       unsigned char *node)
+{
+	memset(network_addr, 0, MAX_NETWORK_ADDR_LEN);
+
+	network_addr[0] = NAT25_APPLE;
+	memcpy(network_addr + 1, (unsigned char *)network, 2);
+	network_addr[3] = *node;
+}
+
+static inline void
+__nat25_generate_pppoe_network_addr(unsigned char *network_addr,
+				    unsigned char *ac_mac, unsigned short *sid)
+{
+	memset(network_addr, 0, MAX_NETWORK_ADDR_LEN);
+
+	network_addr[0] = NAT25_PPPOE;
+	memcpy(network_addr + 1, (unsigned char *)sid, 2);
+	memcpy(network_addr + 3, (unsigned char *)ac_mac, 6);
+}
+
+#ifdef CL_IPV6_PASS
+static void __nat25_generate_ipv6_network_addr(unsigned char *network_addr,
+					       unsigned int *ip_addr)
+{
+	memset(network_addr, 0, MAX_NETWORK_ADDR_LEN);
+
+	network_addr[0] = NAT25_IPV6;
+	memcpy(network_addr + 1, (unsigned char *)ip_addr, 16);
+}
+
+static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag,
+			       unsigned char len8b)
+{
+	while (len > 0) {
+		if (*data == tag && *(data + 1) == len8b && len >= len8b * 8)
+			return data + 2;
+
+		len -= (*(data + 1)) * 8;
+		data += (*(data + 1)) * 8;
+	}
+	return NULL;
+}
+
+static int update_nd_link_layer_addr(unsigned char *data, int len,
+				     unsigned char *replace_mac)
+{
+	struct icmp6hdr *icmphdr = (struct icmp6hdr *)data;
+	unsigned char *mac;
+
+	if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) {
+		if (len >= 8) {
+			mac = scan_tlv(&data[8], len - 8, 1, 1);
+			if (mac) {
+				pr_info("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+					mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+					replace_mac[0], replace_mac[1], replace_mac[2],
+					replace_mac[3], replace_mac[4], replace_mac[5]);
+				memcpy(mac, replace_mac, 6);
+				return 1;
+			}
+		}
+	} else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) {
+		if (len >= 16) {
+			mac = scan_tlv(&data[16], len - 16, 1, 1);
+			if (mac) {
+				pr_info("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+					mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+					replace_mac[0], replace_mac[1], replace_mac[2],
+					replace_mac[3], replace_mac[4], replace_mac[5]);
+				memcpy(mac, replace_mac, 6);
+				return 1;
+			}
+		}
+	} else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
+		if (len >= 24) {
+			mac = scan_tlv(&data[24], len - 24, 1, 1);
+			if (mac) {
+				pr_info("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+					mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+					replace_mac[0], replace_mac[1], replace_mac[2],
+					replace_mac[3], replace_mac[4], replace_mac[5]);
+				memcpy(mac, replace_mac, 6);
+				return 1;
+			}
+		}
+	} else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
+		if (len >= 24) {
+			mac = scan_tlv(&data[24], len - 24, 2, 1);
+			if (mac) {
+				pr_info("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+					mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+					replace_mac[0], replace_mac[1], replace_mac[2],
+					replace_mac[3], replace_mac[4], replace_mac[5]);
+				memcpy(mac, replace_mac, 6);
+				return 1;
+			}
+		}
+	} else if (icmphdr->icmp6_type == NDISC_REDIRECT) {
+		if (len >= 40) {
+			mac = scan_tlv(&data[40], len - 40, 2, 1);
+			if (mac) {
+				pr_info("Redirect,  replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+					mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+					replace_mac[0], replace_mac[1], replace_mac[2],
+					replace_mac[3], replace_mac[4], replace_mac[5]);
+				memcpy(mac, replace_mac, 6);
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
+#ifdef SUPPORT_RX_UNI2MCAST
+static void convert_ipv6_mac_to_mc(struct sk_buff *skb)
+{
+	struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN);
+	unsigned char *dst_mac = skb->data;
+
+	/*modified by qinjunjie,ipv6 multicast address ix 0x33-33-xx-xx-xx-xx */
+	dst_mac[0] = 0x33;
+	dst_mac[1] = 0x33;
+	memcpy(&dst_mac[2], &iph->daddr.s6_addr32[3], 4);
+#if defined(__LINUX_2_6__)
+	/*modified by qinjunjie,warning:should not remove next line */
+	skb->pkt_type = PACKET_MULTICAST;
+#endif
+}
+#endif /* CL_IPV6_PASS */
+#endif /* SUPPORT_RX_UNI2MCAST */
+
+static inline int __nat25_network_hash(unsigned char *network_addr)
+{
+	if (network_addr[0] == NAT25_IPV4) {
+		unsigned long x;
+
+		x = network_addr[7] ^ network_addr[8] ^ network_addr[9] ^ network_addr[10];
+
+		return x & (NAT25_HASH_SIZE - 1);
+	} else if (network_addr[0] == NAT25_IPX) {
+		unsigned long x;
+
+		x = network_addr[1] ^ network_addr[2] ^ network_addr[3] ^ network_addr[4] ^
+			network_addr[5] ^ network_addr[6] ^ network_addr[7] ^ network_addr[8] ^
+			network_addr[9] ^ network_addr[10];
+
+		return x & (NAT25_HASH_SIZE - 1);
+	} else if (network_addr[0] == NAT25_APPLE) {
+		unsigned long x;
+
+		x = network_addr[1] ^ network_addr[2] ^ network_addr[3];
+
+		return x & (NAT25_HASH_SIZE - 1);
+	} else if (network_addr[0] == NAT25_PPPOE) {
+		unsigned long x;
+
+		x = network_addr[0] ^ network_addr[1] ^ network_addr[2] ^ network_addr[3] ^
+			network_addr[4] ^ network_addr[5] ^ network_addr[6] ^ network_addr[7] ^
+			network_addr[8];
+
+		return x & (NAT25_HASH_SIZE - 1);
+#ifdef CL_IPV6_PASS
+	} else if (network_addr[0] == NAT25_IPV6) {
+		unsigned long x;
+
+		x = network_addr[1] ^ network_addr[2] ^ network_addr[3] ^ network_addr[4] ^
+			network_addr[5] ^ network_addr[6] ^ network_addr[7] ^ network_addr[8] ^
+			network_addr[9] ^ network_addr[10] ^ network_addr[11] ^
+			network_addr[12] ^ network_addr[13] ^ network_addr[14] ^
+			network_addr[15] ^ network_addr[16];
+
+		return x & (NAT25_HASH_SIZE - 1);
+#endif
+	} else {
+		unsigned long x = 0;
+		int i;
+
+		for (i = 0; i < MAX_NETWORK_ADDR_LEN; i++)
+			x ^= network_addr[i];
+
+		return x & (NAT25_HASH_SIZE - 1);
+	}
+}
+
+static inline void __network_hash_link(struct rwnx_vif *vif,
+				       struct nat25_network_db_entry *ent,
+				       int hash)
+{
+	/* Caller must _enter_critical_bh already! */
+	/* _irqL irqL; */
+	/* _enter_critical_bh(&priv->br_ext_lock, &irqL); */
+
+	ent->next_hash = vif->nethash[hash];
+	if (ent->next_hash)
+		ent->next_hash->pprev_hash = &ent->next_hash;
+	vif->nethash[hash] = ent;
+	ent->pprev_hash = &vif->nethash[hash];
+
+	/* _exit_critical_bh(&priv->br_ext_lock, &irqL); */
+}
+
+static inline void __network_hash_unlink(struct nat25_network_db_entry *ent)
+{
+	/* Caller must _enter_critical_bh already! */
+	/* _irqL irqL; */
+	/* _enter_critical_bh(&priv->br_ext_lock, &irqL); */
+
+	*ent->pprev_hash = ent->next_hash;
+	if (ent->next_hash)
+		ent->next_hash->pprev_hash = ent->pprev_hash;
+	ent->next_hash = NULL;
+	ent->pprev_hash = NULL;
+
+	/* _exit_critical_bh(&priv->br_ext_lock, &irqL); */
+}
+
+static int __nat25_db_network_lookup_and_replace(struct rwnx_vif *vif,
+						 struct sk_buff *skb,
+						 unsigned char *network_addr)
+{
+	struct nat25_network_db_entry *db;
+
+	spin_lock_bh(&vif->br_ext_lock);
+
+	db = vif->nethash[__nat25_network_hash(network_addr)];
+	while (db) {
+		if (!memcmp(db->network_addr, network_addr, MAX_NETWORK_ADDR_LEN)) {
+			if (!__nat25_has_expired(vif, db)) {
+				/* replace the destination mac address */
+				memcpy(skb->data, db->mac_addr, ETH_ALEN);
+				atomic_inc(&db->use_count);
+
+#ifdef CL_IPV6_PASS
+				pr_info("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+					db->mac_addr[0], db->mac_addr[1], db->mac_addr[2],
+					db->mac_addr[3], db->mac_addr[4], db->mac_addr[5],
+					db->network_addr[0], db->network_addr[1],
+					db->network_addr[2], db->network_addr[3],
+					db->network_addr[4], db->network_addr[5],
+					db->network_addr[6], db->network_addr[7],
+					db->network_addr[8], db->network_addr[9],
+					db->network_addr[10], db->network_addr[11],
+					db->network_addr[12], db->network_addr[13],
+					db->network_addr[14], db->network_addr[15],
+					db->network_addr[16]);
+#else
+				pr_info("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+					db->mac_addr[0], db->mac_addr[1], db->mac_addr[2],
+					db->mac_addr[3], db->mac_addr[4], db->mac_addr[5],
+					db->network_addr[0], db->network_addr[1],
+					db->network_addr[2], db->network_addr[3],
+					db->network_addr[4], db->network_addr[5],
+					db->network_addr[6], db->network_addr[7],
+					db->network_addr[8], db->network_addr[9],
+					db->network_addr[10]);
+#endif
+			}
+			spin_unlock_bh(&vif->br_ext_lock);
+			return 1;
+		}
+
+		db = db->next_hash;
+	}
+
+	spin_unlock_bh(&vif->br_ext_lock);
+	return 0;
+}
+
+static void __nat25_db_network_insert(struct rwnx_vif *vif,
+				      unsigned char *mac_addr,
+				      unsigned char *network_addr)
+{
+	struct nat25_network_db_entry *db;
+	int hash;
+
+	spin_lock_bh(&vif->br_ext_lock);
+
+	hash = __nat25_network_hash(network_addr);
+	db = vif->nethash[hash];
+
+	while (db) {
+		if (!memcmp(db->network_addr, network_addr, MAX_NETWORK_ADDR_LEN)) {
+			memcpy(db->mac_addr, mac_addr, ETH_ALEN);
+			db->ageing_timer = jiffies;
+			spin_unlock_bh(&vif->br_ext_lock);
+			return;
+		}
+
+		db = db->next_hash;
+	}
+
+	db = kmalloc(sizeof(*db), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+	if (!db) {
+		spin_unlock_bh(&vif->br_ext_lock);
+		return;
+	}
+
+	memcpy(db->network_addr, network_addr, MAX_NETWORK_ADDR_LEN);
+	memcpy(db->mac_addr, mac_addr, ETH_ALEN);
+	atomic_set(&db->use_count, 1);
+	db->ageing_timer = jiffies;
+
+	__network_hash_link(vif, db, hash);
+
+	spin_unlock_bh(&vif->br_ext_lock);
+}
+
+static void __nat25_db_print(struct rwnx_vif *vif)
+{
+	spin_lock_bh(&vif->br_ext_lock);
+
+#ifdef BR_SUPPORT_DEBUG
+	static int counter;
+	int i, j;
+	struct nat25_network_db_entry *db;
+
+	counter++;
+	if ((counter % 16) != 0)
+		return;
+
+	for (i = 0, j = 0; i < NAT25_HASH_SIZE; i++) {
+		db = vif->nethash[i];
+
+		while (db) {
+#ifdef CL_IPV6_PASS
+			pr_info("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+				j, i, atomic_read(&db->use_count), db->mac_addr[0],
+				db->mac_addr[1], db->mac_addr[2], db->mac_addr[3], db->mac_addr[4],
+				db->mac_addr[5], db->network_addr[0], db->network_addr[1],
+				db->network_addr[2], db->network_addr[3], db->network_addr[4],
+				db->network_addr[5], db->network_addr[6], db->network_addr[7],
+				db->network_addr[8], db->network_addr[9], db->network_addr[10],
+				db->network_addr[11], db->network_addr[12], db->network_addr[13],
+				db->network_addr[14], db->network_addr[15], db->network_addr[16]);
+#else
+			pr_info("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+				j, i, atomic_read(&db->use_count), db->mac_addr[0],
+				db->mac_addr[1], db->mac_addr[2], db->mac_addr[3],
+				db->mac_addr[4], db->mac_addr[5], db->network_addr[0],
+				db->network_addr[1], db->network_addr[2], db->network_addr[3],
+				db->network_addr[4], db->network_addr[5], db->network_addr[6],
+				db->network_addr[7], db->network_addr[8], db->network_addr[9],
+				db->network_addr[10]);
+#endif
+			j++;
+
+			db = db->next_hash;
+		}
+	}
+#endif
+
+	spin_unlock_bh(&vif->br_ext_lock);
+}
+
+/*
+ *	NAT2.5 interface
+ */
+
+void nat25_db_cleanup(struct rwnx_vif *vif)
+{
+	int i;
+
+	spin_lock_bh(&vif->br_ext_lock);
+
+	for (i = 0; i < NAT25_HASH_SIZE; i++) {
+		struct nat25_network_db_entry *f;
+
+		f = vif->nethash[i];
+		while (f) {
+			struct nat25_network_db_entry *g;
+
+			g = f->next_hash;
+			if (vif->scdb_entry == f) {
+				memset(vif->scdb_mac, 0, ETH_ALEN);
+				memset(vif->scdb_ip, 0, 4);
+				vif->scdb_entry = NULL;
+			}
+			__network_hash_unlink(f);
+			kfree(f);
+
+			f = g;
+		}
+	}
+
+	spin_unlock_bh(&vif->br_ext_lock);
+}
+
+static inline void clear_scdb_entry(struct rwnx_vif *vif,
+				    struct nat25_network_db_entry *f)
+{
+	if (vif->scdb_entry == f) {
+		memset(vif->scdb_mac, 0, ETH_ALEN);
+		memset(vif->scdb_ip, 0, 4);
+		vif->scdb_entry = NULL;
+	}
+}
+
+void nat25_db_expire(struct rwnx_vif *vif)
+{
+	int i;
+
+	spin_lock_bh(&vif->br_ext_lock);
+
+	/* if(!priv->eth_br_ext_info.nat25_disable) */
+	{
+		for (i = 0; i < NAT25_HASH_SIZE; i++) {
+			struct nat25_network_db_entry *f;
+
+			f = vif->nethash[i];
+
+			while (f) {
+				struct nat25_network_db_entry *g;
+
+				g = f->next_hash;
+
+				if (__nat25_has_expired(vif, f)) {
+					if (atomic_dec_and_test(&f->use_count)) {
+#ifdef BR_SUPPORT_DEBUG
+#ifdef CL_IPV6_PASS
+						panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+							     i, f->mac_addr[0], f->mac_addr[1],
+							     f->mac_addr[2], f->mac_addr[3],
+							     f->mac_addr[4], f->mac_addr[5],
+							     f->network_addr[0], f->network_addr[1],
+							     f->network_addr[2], f->network_addr[3],
+							     f->network_addr[4], f->network_addr[5],
+							     f->network_addr[6], f->network_addr[7],
+							     f->network_addr[8], f->network_addr[9],
+							     f->network_addr[10],
+							     f->network_addr[11],
+							     f->network_addr[12],
+							     f->network_addr[13],
+							     f->network_addr[14],
+							     f->network_addr[15],
+							     f->network_addr[16]);
+#else
+
+						panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+							     i, f->mac_addr[0], f->mac_addr[1],
+							     f->mac_addr[2], f->mac_addr[3],
+							     f->mac_addr[4], f->mac_addr[5],
+							     f->network_addr[0], f->network_addr[1],
+							     f->network_addr[2], f->network_addr[3],
+							     f->network_addr[4], f->network_addr[5],
+							     f->network_addr[6], f->network_addr[7],
+							     f->network_addr[8], f->network_addr[9],
+							     f->network_addr[10]);
+#endif
+#endif
+						clear_scdb_entry(vif, f);
+						__network_hash_unlink(f);
+						kfree(f);
+					}
+				}
+
+				f = g;
+			}
+		}
+	}
+
+	spin_unlock_bh(&vif->br_ext_lock);
+}
+
+#ifdef SUPPORT_TX_MCAST2UNI
+static int check_ip_mc_and_replace(struct rwnx_vif *vif, struct sk_buff *skb,
+				   unsigned int *dst_ip)
+{
+	struct stat_info *pstat;
+	struct list_head *phead, *plist;
+	int i;
+
+	phead = &vif->asoc_list;
+	plist = phead->next;
+
+	while (plist != phead) {
+		pstat = list_entry(plist, struct stat_info, asoc_list);
+		plist = plist->next;
+
+		if (pstat->ipmc_num == 0)
+			continue;
+
+		for (i = 0; i < MAX_IP_MC_ENTRY; i++) {
+			if (pstat->ipmc[i].used &&
+			    !memcmp(&pstat->ipmc[i].mcmac[3], ((unsigned char *)dst_ip) + 1,
+						3)) {
+				memcpy(skb->data, pstat->ipmc[i].mcmac, ETH_ALEN);
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+#endif
+
+static inline void check_and_reinit_br_mac(struct rwnx_vif *vif)
+{
+	if ((*(u32 *)vif->br_mac) == 0 &&
+	    (*(u16 *)(vif->br_mac + 4)) == 0) {
+		pr_info("Re-init netdev_br_init() due to br_mac==0!\n");
+		netdev_br_init(vif->ndev);
+	}
+}
+
+static int nat25_handle_pppoe_packet(struct rwnx_vif *vif,
+				     struct pppoe_hdr *ph,
+				     struct sk_buff *skb,
+				     unsigned char network_addr[MAX_NETWORK_ADDR_LEN])
+{
+	struct pppoe_tag *tag, *old_tag;
+	unsigned char tag_buf[40];
+	int old_tag_len = 0;
+	unsigned short *p_magic;
+
+	if (ph->sid == 0) {
+		/* Discovery phase */
+		if (ph->code != PADI_CODE && ph->code != PADR_CODE)
+			return -EINVAL;
+
+		if (vif->eth_br_ext_info.add_pppoe_tag) {
+			tag = (struct pppoe_tag *)tag_buf;
+			old_tag = __nat25_find_pppoe_tag(ph,
+							 ntohs(PTT_RELAY_SID));
+
+			if (old_tag) {
+				/* Copy old value and delete it */
+				old_tag_len = ntohs(old_tag->tag_len);
+
+				if (old_tag_len + TAG_HDR_LEN +
+				    MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN >
+				    sizeof(tag_buf)) {
+					pr_err("SID tag length too long!\n");
+					return -EINVAL;
+				}
+
+				memcpy(tag->tag_data + MAGIC_CODE_LEN +
+				       RTL_RELAY_TAG_LEN,
+				       old_tag->tag_data, old_tag_len);
+
+				if (skb_pull_and_merge(skb,
+						       (unsigned char *)old_tag,
+						       TAG_HDR_LEN + old_tag_len)
+						       < 0) {
+					pr_err("skb_pull_and_merge() failed in PADI/R packet!\n");
+					return -EINVAL;
+				}
+
+				ph->length = htons(ntohs(ph->length) -
+						   TAG_HDR_LEN - old_tag_len);
+			}
+
+			tag->tag_type = PTT_RELAY_SID;
+			tag->tag_len = htons(MAGIC_CODE_LEN +
+					     RTL_RELAY_TAG_LEN + old_tag_len);
+
+			/* Insert magic_code + client MAC */
+			p_magic = (unsigned short *)tag->tag_data;
+			*p_magic = htons(MAGIC_CODE);
+			memcpy(tag->tag_data + MAGIC_CODE_LEN,
+			       skb->data + ETH_ALEN, ETH_ALEN);
+
+			if (__nat25_add_pppoe_tag(skb, tag) < 0)
+				return -EINVAL;
+
+			pr_info("NAT25: Insert PPPoE, forward %s packet\n",
+				(ph->code == PADI_CODE) ? "PADI" : "PADR");
+
+		} else {
+			/* Not adding relay tag */
+			if (vif->pppoe_connection_in_progress &&
+			    memcmp(skb->data + ETH_ALEN,
+				   vif->pppoe_addr, ETH_ALEN)) {
+				pr_info("Discard PPPoE packet: another connection in progress!\n");
+				return -EBUSY;
+			}
+
+			if (vif->pppoe_connection_in_progress == 0)
+				memcpy(vif->pppoe_addr, skb->data + ETH_ALEN,
+				       ETH_ALEN);
+
+			vif->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
+		}
+
+	} else {
+		/* Session phase */
+		pr_info("NAT25: Insert PPPoE session packet to %s\n",
+			skb->dev->name);
+
+		__nat25_generate_pppoe_network_addr(network_addr,
+						    skb->data, &ph->sid);
+
+		__nat25_db_network_insert(vif, skb->data + ETH_ALEN,
+					  network_addr);
+
+		__nat25_db_print(vif);
+
+		if (!vif->eth_br_ext_info.add_pppoe_tag &&
+		    vif->pppoe_connection_in_progress &&
+		    !memcmp(skb->data + ETH_ALEN,
+			    vif->pppoe_addr, ETH_ALEN))
+			vif->pppoe_connection_in_progress = 0;
+	}
+
+	return 0;
+}
+
+int nat25_db_handle(struct rwnx_vif *vif, struct sk_buff *skb, int method)
+{
+	unsigned short protocol;
+	unsigned char network_addr[MAX_NETWORK_ADDR_LEN];
+
+	if (!skb)
+		return -1;
+
+	if (method <= NAT25_MIN || method >= NAT25_MAX)
+		return -1;
+
+	protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN));
+
+	/*---------------------------------------------------*/
+	/*                 Handle IP frame                  */
+	/*---------------------------------------------------*/
+	if (protocol == htons(ETH_P_IP)) {
+		struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
+
+		if (((unsigned char *)(iph) + (iph->ihl << 2)) >=
+			(skb->data + ETH_HLEN + skb->len)) {
+			pr_err("NAT25: malformed IP packet !\n");
+			return -1;
+		}
+
+		switch (method) {
+		case NAT25_CHECK:
+			return -1;
+
+		case NAT25_INSERT: {
+			/* some multicast with source IP is all zero, maybe other case is
+			 * illegal
+			 */
+			/* in class A, B, C, host address is all zero or all one is illegal
+			 */
+			if (iph->saddr == 0)
+				return 0;
+			pr_info("NAT25: Insert IP, SA=%08x, DA=%08x\n", iph->saddr,
+				iph->daddr);
+			__nat25_generate_ipv4_network_addr(network_addr, &iph->saddr);
+			/* record source IP address and , source mac address into db */
+			__nat25_db_network_insert(vif, skb->data + ETH_ALEN, network_addr);
+
+			__nat25_db_print(vif);
+		}
+			return 0;
+
+		case NAT25_LOOKUP: {
+			pr_info("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph->saddr,
+				iph->daddr);
+#ifdef SUPPORT_TX_MCAST2UNI
+			if (vif->pshare->rf_ft_var.mc2u_disable ||
+			    ((((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) ==
+				   (WIFI_STATION_STATE | WIFI_ASOC_STATE)) &&
+				  !check_ip_mc_and_replace(vif, skb, &iph->daddr)) ||
+				 (OPMODE & WIFI_ADHOC_STATE)))
+#endif
+			{
+				__nat25_generate_ipv4_network_addr(network_addr, &iph->daddr);
+
+				if (!__nat25_db_network_lookup_and_replace(vif, skb,
+									   network_addr)) {
+					if (*((unsigned char *)&iph->daddr + 3) == 0xff) {
+						/* L2 is unicast but L3 is broadcast, make L2 bacome
+						 * broadcast
+						 */
+						pr_info("NAT25: Set DA as broadcast\n");
+						memset(skb->data, 0xff, ETH_ALEN);
+					} else {
+						/* forward unknown IP packet to upper TCP/IP */
+						pr_info("NAT25: Replace DA with BR's MAC\n");
+						check_and_reinit_br_mac(vif);
+						memcpy(skb->data, vif->br_mac, ETH_ALEN);
+					}
+				}
+			}
+		}
+			return 0;
+
+		default:
+			return -1;
+		}
+	}
+
+	/*---------------------------------------------------*/
+	/*                 Handle ARP frame                 */
+	/*---------------------------------------------------*/
+	else if (protocol == htons(ETH_P_ARP)) {
+		struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN);
+		unsigned char *arp_ptr = (unsigned char *)(arp + 1);
+		unsigned int *sender, *target;
+
+		if (arp->ar_pro != htons(ETH_P_IP)) {
+			pr_err("NAT25: arp protocol unknown (%4x)!\n", htons(arp->ar_pro));
+			return -1;
+		}
+
+		switch (method) {
+		case NAT25_CHECK:
+			return 0; /* skb_copy for all ARP frame */
+
+		case NAT25_INSERT: {
+			pr_info("NAT25: Insert ARP, MAC=%02x%02x%02x%02x%02x%02x\n",
+				arp_ptr[0], arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4],
+				arp_ptr[5]);
+
+			/* change to ARP sender mac address to wlan STA address */
+			memcpy(arp_ptr, vif->ndev->dev_addr, ETH_ALEN);
+
+			arp_ptr += arp->ar_hln;
+			sender = (unsigned int *)arp_ptr;
+
+			__nat25_generate_ipv4_network_addr(network_addr, sender);
+
+			__nat25_db_network_insert(vif, skb->data + ETH_ALEN, network_addr);
+
+			__nat25_db_print(vif);
+		}
+			return 0;
+
+		case NAT25_LOOKUP: {
+			pr_info("NAT25: Lookup ARP\n");
+
+			arp_ptr += arp->ar_hln;
+			sender = (unsigned int *)arp_ptr;
+			arp_ptr += (arp->ar_hln + arp->ar_pln);
+			target = (unsigned int *)arp_ptr;
+
+			__nat25_generate_ipv4_network_addr(network_addr, target);
+
+			__nat25_db_network_lookup_and_replace(vif, skb, network_addr);
+
+			/* change to ARP target mac address to Lookup result */
+			arp_ptr = (unsigned char *)(arp + 1);
+			arp_ptr += (arp->ar_hln + arp->ar_pln);
+			memcpy(arp_ptr, skb->data, ETH_ALEN);
+		}
+			return 0;
+
+		default:
+			return -1;
+		}
+	}
+
+	/*---------------------------------------------------*/
+	/*         Handle IPX and Apple Talk frame          */
+	/*---------------------------------------------------*/
+	else if ((protocol == htons(ETH_P_IPX)) ||
+		 (protocol == htons(ETH_P_ATALK)) ||
+			 (protocol == htons(ETH_P_AARP))) {
+		unsigned char ipx_header[2] = {0xFF, 0xFF};
+		struct ipxhdr *ipx = NULL;
+		struct elapaarp *ea = NULL;
+		struct ddpehdr *ddp = NULL;
+		unsigned char *frame_ptr = skb->data + ETH_HLEN;
+
+		if (protocol == htons(ETH_P_IPX)) {
+			pr_info("NAT25: Protocol=IPX (Ethernet II)\n");
+			ipx = (struct ipxhdr *)frame_ptr;
+		} else { /* if(protocol <= __constant_htons(ETH_FRAME_LEN)) */
+			if (!memcmp(ipx_header, frame_ptr, 2)) {
+				pr_info("NAT25: Protocol=IPX (Ethernet 802.3)\n");
+				ipx = (struct ipxhdr *)frame_ptr;
+			} else {
+				unsigned char ipx_8022_type = 0xE0;
+				unsigned char snap_8022_type = 0xAA;
+
+				if (*frame_ptr == snap_8022_type) {
+					unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81,
+									0x37}; /* IPX SNAP ID */
+					unsigned char aarp_snap_id[5] = {
+						0x00, 0x00, 0x00, 0x80,
+						0xF3}; /* Apple Talk AARP SNAP ID */
+					unsigned char ddp_snap_id[5] = {
+						0x08, 0x00, 0x07, 0x80,
+						0x9B}; /* Apple Talk DDP SNAP ID */
+
+					frame_ptr += 3; /* eliminate the 802.2 header */
+
+					if (!memcmp(ipx_snap_id, frame_ptr, 5)) {
+						frame_ptr += 5; /* eliminate the SNAP header */
+
+						pr_info("NAT25: Protocol=IPX (Ethernet SNAP)\n");
+						ipx = (struct ipxhdr *)frame_ptr;
+					} else if (!memcmp(aarp_snap_id, frame_ptr, 5)) {
+						frame_ptr += 5; /* eliminate the SNAP header */
+
+						ea = (struct elapaarp *)frame_ptr;
+					} else if (!memcmp(ddp_snap_id, frame_ptr, 5)) {
+						frame_ptr += 5; /* eliminate the SNAP header */
+
+						ddp = (struct ddpehdr *)frame_ptr;
+					} else {
+						pr_info("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n",
+							frame_ptr[0], frame_ptr[1], frame_ptr[2],
+							frame_ptr[3], frame_ptr[4]);
+						return -1;
+					}
+				} else if (*frame_ptr == ipx_8022_type) {
+					frame_ptr += 3; /* eliminate the 802.2 header */
+
+					if (!memcmp(ipx_header, frame_ptr, 2)) {
+						pr_info("NAT25: Protocol=IPX (Ethernet 802.2)\n");
+						ipx = (struct ipxhdr *)frame_ptr;
+					} else {
+						return -1;
+					}
+				}
+			}
+		}
+
+		/*   IPX  */
+		if (ipx) {
+			unsigned int *ipx_net = NULL;
+			unsigned short *ipx_socket = NULL;
+
+			switch (method) {
+			case NAT25_CHECK:
+				if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node,
+					    ETH_ALEN)) {
+					pr_info("NAT25: Check IPX skb_copy\n");
+					return 0;
+				}
+				return -1;
+
+			case NAT25_INSERT: {
+				pr_info("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n",
+					ipx->ipx_dest.net, ipx->ipx_dest.node[0],
+					ipx->ipx_dest.node[1], ipx->ipx_dest.node[2],
+					ipx->ipx_dest.node[3], ipx->ipx_dest.node[4],
+					ipx->ipx_dest.node[5], ipx->ipx_dest.sock,
+					ipx->ipx_source.net, ipx->ipx_source.node[0],
+					ipx->ipx_source.node[1], ipx->ipx_source.node[2],
+					ipx->ipx_source.node[3], ipx->ipx_source.node[4],
+					ipx->ipx_source.node[5], ipx->ipx_source.sock);
+
+				if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node,
+					    ETH_ALEN)) {
+					unsigned int *ipx_net = NULL;
+					unsigned short *ipx_socket = NULL;
+
+					pr_info("NAT25: Use IPX Net, and Socket as network addr\n");
+
+					ipx_net = &ipx->ipx_source.net;
+					ipx_socket = &ipx->ipx_source.sock;
+					__nat25_generate_ipx_network_addr_with_socket(network_addr,
+										      ipx_net,
+										      ipx_socket);
+
+					/* change IPX source node addr to wlan STA address */
+					memcpy(ipx->ipx_source.node, vif->ndev->dev_addr, ETH_ALEN);
+				} else {
+					unsigned int *ipx_net = NULL;
+					unsigned char *ipx_node = NULL;
+
+					ipx_net = &ipx->ipx_source.net;
+					ipx_node = ipx->ipx_source.node;
+					__nat25_generate_ipx_network_addr_with_node(network_addr,
+										    ipx_net,
+										    ipx_node);
+				}
+
+				__nat25_db_network_insert(vif, skb->data + ETH_ALEN,
+							  network_addr);
+
+				__nat25_db_print(vif);
+			}
+				return 0;
+
+			case NAT25_LOOKUP: {
+				if (!memcmp(vif->ndev->dev_addr, ipx->ipx_dest.node,
+					    ETH_ALEN)) {
+					unsigned int *ipx_net = &ipx->ipx_dest.net;
+					unsigned short *ipx_socket = &ipx->ipx_dest.sock;
+
+					pr_info("NAT25: Lookup IPX, Modify Destination IPX Node addr\n");
+
+					__nat25_generate_ipx_network_addr_with_socket(network_addr,
+										      ipx_net,
+										      ipx_socket);
+
+					__nat25_db_network_lookup_and_replace(vif, skb,
+									      network_addr);
+
+					/* replace IPX destination node addr with Lookup destination
+					 * MAC addr
+					 */
+					memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN);
+				} else {
+					unsigned int *ipx_net = &ipx->ipx_dest.net;
+					unsigned char *ipx_node = ipx->ipx_dest.node;
+
+					__nat25_generate_ipx_network_addr_with_node(network_addr,
+										    ipx_net,
+										    ipx_node);
+
+					__nat25_db_network_lookup_and_replace(vif, skb,
+									      network_addr);
+				}
+			}
+				return 0;
+
+			default:
+				return -1;
+			}
+		}
+
+		/*   AARP  */
+		else if (ea) {
+			/* Sanity check fields. */
+			if (ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN) {
+				pr_err("NAT25: Appletalk AARP Sanity check fail!\n");
+				return -1;
+			}
+
+			switch (method) {
+			case NAT25_CHECK:
+				return 0;
+
+			case NAT25_INSERT: {
+				/* change to AARP source mac address to wlan STA address */
+				memcpy(ea->hw_src, vif->ndev->dev_addr, ETH_ALEN);
+
+				pr_info("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n",
+					ea->pa_src_net, ea->pa_src_node, ea->pa_dst_net,
+					ea->pa_dst_node);
+
+				__nat25_generate_apple_network_addr(network_addr,
+								    &ea->pa_src_net,
+								    &ea->pa_src_node);
+
+				__nat25_db_network_insert(vif, skb->data + ETH_ALEN,
+							  network_addr);
+
+				__nat25_db_print(vif);
+			}
+				return 0;
+
+			case NAT25_LOOKUP: {
+				pr_info("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n",
+					ea->pa_src_net, ea->pa_src_node, ea->pa_dst_net,
+					ea->pa_dst_node);
+
+				__nat25_generate_apple_network_addr(network_addr,
+								    &ea->pa_dst_net,
+								    &ea->pa_dst_node);
+
+				__nat25_db_network_lookup_and_replace(vif, skb, network_addr);
+
+				/* change to AARP destination mac address to Lookup result */
+				memcpy(ea->hw_dst, skb->data, ETH_ALEN);
+			}
+				return 0;
+
+			default:
+				return -1;
+			}
+		}
+
+		/*   DDP  */
+		else if (ddp) {
+			switch (method) {
+			case NAT25_CHECK:
+				return -1;
+
+			case NAT25_INSERT: {
+				pr_info("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n",
+					ddp->deh_snet, ddp->deh_snode, ddp->deh_dnet,
+					ddp->deh_dnode);
+
+				__nat25_generate_apple_network_addr(network_addr, &ddp->deh_snet,
+								    &ddp->deh_snode);
+
+				__nat25_db_network_insert(vif, skb->data + ETH_ALEN,
+							  network_addr);
+
+				__nat25_db_print(vif);
+			}
+				return 0;
+
+			case NAT25_LOOKUP: {
+				pr_info("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n",
+					ddp->deh_snet, ddp->deh_snode, ddp->deh_dnet,
+					ddp->deh_dnode);
+
+				__nat25_generate_apple_network_addr(network_addr, &ddp->deh_dnet,
+								    &ddp->deh_dnode);
+
+				__nat25_db_network_lookup_and_replace(vif, skb, network_addr);
+			}
+				return 0;
+
+			default:
+				return -1;
+			}
+		}
+
+		return -1;
+	}
+
+	/*---------------------------------------------------*/
+	/*                Handle PPPoE frame                */
+	/*---------------------------------------------------*/
+	else if ((protocol == htons(ETH_P_PPP_DISC)) ||
+		 (protocol == htons(ETH_P_PPP_SES))) {
+		struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
+		unsigned short *pmagic;
+
+		switch (method) {
+		case NAT25_CHECK:
+			if (ph->sid == 0)
+				return 0;
+			return 1;
+
+		case NAT25_INSERT:
+			return nat25_handle_pppoe_packet(vif, ph, skb,
+							 network_addr);
+
+		case NAT25_LOOKUP:
+			if (ph->code == PADO_CODE || ph->code == PADS_CODE) {
+				if (vif->eth_br_ext_info.add_pppoe_tag) {
+					struct pppoe_tag *tag;
+					unsigned char *ptr;
+					unsigned short tag_type, tag_len;
+					int offset = 0;
+
+					ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID));
+					if (ptr == 0) {
+						pr_err("Fail to find PTT_RELAY_SID in FADO!\n");
+						return -1;
+					}
+
+					tag = (struct pppoe_tag *)ptr;
+					tag_type = (unsigned short)((ptr[0] << 8) + ptr[1]);
+					tag_len = (unsigned short)((ptr[2] << 8) + ptr[3]);
+
+					if (tag_type != ntohs(PTT_RELAY_SID) ||
+					    (tag_len < (MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN))) {
+						pr_err("Invalid PTT_RELAY_SID tag length [%d]!\n",
+						       tag_len);
+						return -1;
+					}
+
+					pmagic = (unsigned short *)tag->tag_data;
+					if (ntohs(*pmagic) != MAGIC_CODE) {
+						pr_err("Can't find MAGIC_CODE in %s packet!\n",
+						       (ph->code == PADO_CODE ? "PADO" : "PADS"));
+						return -1;
+					}
+
+					memcpy(skb->data, tag->tag_data + MAGIC_CODE_LEN, ETH_ALEN);
+
+					if (tag_len > MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN)
+						offset = TAG_HDR_LEN;
+
+					if (skb_pull_and_merge(skb, ptr + offset,
+							       TAG_HDR_LEN + MAGIC_CODE_LEN +
+							       RTL_RELAY_TAG_LEN - offset) <
+						0) {
+						pr_err("call skb_pull_and_merge() failed in PADO packet!\n");
+						return -1;
+					}
+					ph->length = htons(ntohs(ph->length) -
+							   (TAG_HDR_LEN + MAGIC_CODE_LEN +
+							    RTL_RELAY_TAG_LEN - offset));
+					if (offset > 0)
+						tag->tag_len =
+							htons(tag_len - MAGIC_CODE_LEN -
+							      RTL_RELAY_TAG_LEN);
+
+					pr_info("NAT25: Lookup PPPoE, forward %s Packet from %s\n",
+						(ph->code == PADO_CODE ? "PADO" : "PADS"),
+						   skb->dev->name);
+				} else { /* not add relay tag */
+					if (!vif->pppoe_connection_in_progress) {
+						pr_err("Discard PPPoE packet due to no connection in progress!\n");
+						return -1;
+					}
+					memcpy(skb->data, vif->pppoe_addr, ETH_ALEN);
+					vif->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
+				}
+			} else {
+				if (ph->sid != 0) {
+					pr_info("NAT25: Lookup PPPoE, lookup session packet from %s\n",
+						skb->dev->name);
+					__nat25_generate_pppoe_network_addr(network_addr,
+									    skb->data +
+									    ETH_ALEN,
+									    &ph->sid);
+
+					__nat25_db_network_lookup_and_replace(vif, skb,
+									      network_addr);
+
+					__nat25_db_print(vif);
+				} else {
+					return -1;
+				}
+			}
+			return 0;
+
+		default:
+			return -1;
+		}
+	}
+
+	/*---------------------------------------------------*/
+	/*                 Handle EAP frame                 */
+	/*---------------------------------------------------*/
+	else if (protocol == htons(0x888e)) {
+		switch (method) {
+		case NAT25_CHECK:
+			return -1;
+
+		case NAT25_INSERT:
+			return 0;
+
+		case NAT25_LOOKUP:
+			return 0;
+
+		default:
+			return -1;
+		}
+	}
+
+	/*---------------------------------------------------*/
+	/*         Handle C-Media proprietary frame         */
+	/*---------------------------------------------------*/
+	else if ((protocol == htons(0xe2ae)) ||
+		 (protocol == htons(0xe2af))) {
+		switch (method) {
+		case NAT25_CHECK:
+			return -1;
+
+		case NAT25_INSERT:
+			return 0;
+
+		case NAT25_LOOKUP:
+			return 0;
+
+		default:
+			return -1;
+		}
+	}
+
+	/*---------------------------------------------------*/
+	/*         Handle IPV6 frame                                */
+	/*---------------------------------------------------*/
+#ifdef CL_IPV6_PASS
+	else if (protocol == htons(ETH_P_IPV6)) {
+		struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN);
+
+		if (sizeof(*iph) >= (skb->len - ETH_HLEN)) {
+			pr_err("NAT25: malformed IPv6 packet !\n");
+			return -1;
+		}
+
+		switch (method) {
+		case NAT25_CHECK:
+			if (skb->data[0] & 1)
+				return 0;
+			return -1;
+
+		case NAT25_INSERT: {
+			pr_info("NAT25: Insert IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x, DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
+				iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1],
+				iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3],
+				iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5],
+				iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7],
+				iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1],
+				iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3],
+				iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5],
+				iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]);
+
+			if (memcmp(&iph->saddr,
+				   "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0",
+					   16)) {
+				__nat25_generate_ipv6_network_addr(network_addr,
+								   (unsigned int *)&iph->saddr);
+				__nat25_db_network_insert(vif, skb->data + ETH_ALEN,
+							  network_addr);
+				__nat25_db_print(vif);
+
+				if (iph->nexthdr == IPPROTO_ICMPV6 &&
+				    skb->len > (ETH_HLEN + sizeof(*iph) + 4)) {
+					if (update_nd_link_layer_addr(skb->data +
+								      ETH_HLEN +
+								      sizeof(*iph),
+								      skb->len -
+								      ETH_HLEN -
+								      sizeof(*iph),
+								      vif->ndev->dev_addr)) {
+						struct icmp6hdr *hdr =
+							(struct icmp6hdr *)(skb->data + ETH_HLEN +
+									    sizeof(*iph));
+						hdr->icmp6_cksum = 0;
+						hdr->icmp6_cksum =
+						csum_ipv6_magic(&iph->saddr, &iph->daddr,
+								iph->payload_len, IPPROTO_ICMPV6,
+								csum_partial((__u8 *)hdr,
+									     iph->payload_len,
+									     0));
+					}
+				}
+			}
+		}
+			return 0;
+
+		case NAT25_LOOKUP:
+			pr_info("NAT25: Lookup IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x, DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
+				iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1],
+				iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3],
+				iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5],
+				iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7],
+				iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1],
+				iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3],
+				iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5],
+				iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]);
+
+			__nat25_generate_ipv6_network_addr(network_addr,
+							   (unsigned int *)&iph->daddr);
+			if (!__nat25_db_network_lookup_and_replace(vif, skb, network_addr)) {
+#ifdef SUPPORT_RX_UNI2MCAST
+				if (iph->daddr.s6_addr[0] == 0xff)
+					convert_ipv6_mac_to_mc(skb);
+#endif
+			}
+			return 0;
+
+		default:
+			return -1;
+		}
+	}
+#endif /* CL_IPV6_PASS */
+
+	return -1;
+}
+
+int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb)
+{
+	// printk("%s : vif_type=%d\n",__func__,RWNX_VIF_TYPE(vif));
+#ifdef BR_SUPPORT_DEBUG
+	if (!vif->eth_br_ext_info.nat25_disable && (!(skb->data[0] & 1))) {
+		pr_info("NAT25: Input Frame: DA=%02x%02x%02x%02x%02x%02x SA=%02x%02x%02x%02x%02x%02x\n",
+			skb->data[0], skb->data[1], skb->data[2], skb->data[3],
+			skb->data[4], skb->data[5], skb->data[6], skb->data[7],
+			skb->data[8], skb->data[9], skb->data[10], skb->data[11]);
+	}
+#endif
+
+	if (!(skb->data[0] & 1)) {
+		int is_vlan_tag = 0, i, retval = 0;
+		unsigned short vlan_hdr = 0;
+
+		if (*((unsigned short *)(skb->data + ETH_ALEN * 2)) ==
+			htons(ETH_P_8021Q)) {
+			is_vlan_tag = 1;
+			vlan_hdr = *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2));
+			for (i = 0; i < 6; i++)
+				*((unsigned short *)(skb->data + ETH_ALEN * 2 + 2 - i * 2)) =
+					*((unsigned short *)(skb->data + ETH_ALEN * 2 - 2 - i * 2));
+			skb_pull(skb, 4);
+		}
+
+		if (!vif->eth_br_ext_info.nat25_disable) {
+			unsigned long irqL;
+
+			spin_lock_bh(&vif->br_ext_lock);
+			/*
+			 *  This function look up the destination network address from
+			 *  the NAT2.5 database. Return value = -1 means that the
+			 *  corresponding network protocol is NOT support.
+			 */
+			if (!vif->eth_br_ext_info.nat25sc_disable &&
+			    (*((unsigned short *)(skb->data + ETH_ALEN * 2)) ==
+				 htons(ETH_P_IP)) &&
+				!memcmp(vif->scdb_ip, skb->data + ETH_HLEN + 16, 4)) {
+				memcpy(skb->data, vif->scdb_mac, ETH_ALEN);
+
+				spin_unlock_bh(&vif->br_ext_lock);
+			} else {
+				spin_unlock_bh(&vif->br_ext_lock);
+
+				retval = nat25_db_handle(vif, skb, NAT25_LOOKUP);
+			}
+		} else {
+			if (((*((unsigned short *)(skb->data + ETH_ALEN * 2)) ==
+				  htons(ETH_P_IP)) &&
+				 !memcmp(vif->br_ip, skb->data + ETH_HLEN + 16, 4)) ||
+				((*((unsigned short *)(skb->data + ETH_ALEN * 2)) ==
+				  htons(ETH_P_ARP)) &&
+				 !memcmp(vif->br_ip, skb->data + ETH_HLEN + 24, 4))) {
+				/* for traffic to upper TCP/IP */
+				retval = nat25_db_handle(vif, skb, NAT25_LOOKUP);
+			}
+		}
+
+		if (is_vlan_tag) {
+			skb_push(skb, 4);
+			for (i = 0; i < 6; i++)
+				*((unsigned short *)(skb->data + i * 2)) =
+					*((unsigned short *)(skb->data + 4 + i * 2));
+			*((unsigned short *)(skb->data + ETH_ALEN * 2)) =
+				htons(ETH_P_8021Q);
+			*((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)) = vlan_hdr;
+		}
+
+		if (retval == -1) {
+			/* DEBUG_ERR("NAT25: Lookup fail!\n"); */
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+#define SERVER_PORT    67
+#define CLIENT_PORT    68
+#define DHCP_MAGIC     0x63825363
+#define BROADCAST_FLAG 0x8000
+
+struct dhcp_message {
+	u8 op;
+	u8 htype;
+	u8 hlen;
+	u8 hops;
+	u32 xid;
+	u16 secs;
+	u16 flags;
+	u32 ciaddr;
+	u32 yiaddr;
+	u32 siaddr;
+	u32 giaddr;
+	u8 chaddr[16];
+	u8 sname[64];
+	u8 file[128];
+	u32 cookie;
+	u8 options[308]; /* 312 - cookie */
+};
+
+static inline void dhcp_fix_broadcast_flag(struct dhcp_message *dhcph,
+					   struct udphdr *udph)
+{
+	int sum;
+
+	if (dhcph->cookie == __constant_htonl(DHCP_MAGIC)) {
+		/* match magic word */
+		if (!(dhcph->flags & htons(BROADCAST_FLAG))) {
+			/* if not broadcast */
+			pr_info("DHCP: change flag of DHCP request to broadcast.\n");
+
+			/* OR BROADCAST flag */
+			dhcph->flags |= htons(BROADCAST_FLAG);
+
+			/* recalculate checksum */
+			sum = ~(udph->check) & 0xffff;
+			sum += dhcph->flags;
+			while (sum >> 16)
+				sum = (sum & 0xffff) + (sum >> 16);
+			udph->check = ~sum;
+		}
+	}
+}
+
+void dhcp_flag_bcast(struct rwnx_vif *vif, struct sk_buff *skb)
+{
+	if (!skb)
+		return;
+	// debug trace
+	// print_hex_dump(KERN_ERR, "SKB DUMP: SKB->DATA== ", DUMP_PREFIX_NONE, 32,
+	// 1, skb->data, 64,false);
+	if (!vif->eth_br_ext_info.dhcp_bcst_disable) {
+		unsigned short protocol =
+			*((unsigned short *)(skb->data + 2 * ETH_ALEN));
+		pr_info("%s  protocol: %04x\n", __func__, protocol);
+
+		if (protocol == htons(ETH_P_IP)) { /* IP */
+			struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
+
+			if (iph->protocol == IPPROTO_UDP) { /* UDP */
+				struct udphdr *udph =
+					(struct udphdr *)((u8 *)iph + (iph->ihl << 2));
+
+				if (udph->source == htons(CLIENT_PORT) &&
+				    udph->dest ==
+					 htons(SERVER_PORT)) { /* DHCP request */
+					struct dhcp_message *dhcph =
+						(struct dhcp_message *)((u8 *)udph +
+									sizeof(struct udphdr));
+					dhcp_fix_broadcast_flag(dhcph, udph);
+				}
+			}
+		}
+	}
+}
+
+void *scdb_find_entry(struct rwnx_vif *vif, unsigned char *mac_addr,
+		      unsigned char *ip_addr)
+{
+	unsigned char network_addr[MAX_NETWORK_ADDR_LEN];
+	struct nat25_network_db_entry *db;
+	int hash;
+
+	__nat25_generate_ipv4_network_addr(network_addr, (unsigned int *)ip_addr);
+	hash = __nat25_network_hash(network_addr);
+	db = vif->nethash[hash];
+	while (db) {
+		if (!memcmp(db->network_addr, network_addr, MAX_NETWORK_ADDR_LEN))
+			return (void *)db;
+
+		db = db->next_hash;
+	}
+
+	return NULL;
+}
+
+#endif /* CONFIG_AIC8800_BR_SUPPORT */
drivers/net/wireless/aic/aic8800_fdrv/aic_br_ext.h new file +72 -0

72 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aic_btsdio.c new file +1164 -0

1,164 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aic_btsdio.h new file +472 -0

166 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aic_priv_cmd.c new file +1967 -0

1,967 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aic_priv_cmd.h new file +127 -0

127 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aic_vendor.c new file +950 -0

950 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aic_vendor.h new file +370 -0

370 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_8800d80.c new file +291 -0

291 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_8800dc.c new file +300 -0

300 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_8801.c new file +279 -0

279 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_ops.c new file +267 -0

267 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_chip_ops.h new file +186 -0

186 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_compat_8800d80.c new file +96 -0

96 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_compat_8800d80.h new file +16 -0
new file mode 100644
index 0000000000000..22f882d3aa3a2

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/aicwf_compat_8800dc.c new file +505 -0

505 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_compat_8800dc.h new file +22 -0
new file mode 100644
index 0000000000000..12e8d60150452

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/aicwf_genl.c new file +932 -0

932 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_genl.h new file +112 -0

112 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_rx_prealloc.c new file +102 -0

102 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_rx_prealloc.h new file +32 -0
new file mode 100644
index 0000000000000..bc7a03cacd94f

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/aicwf_sdio.c new file +2813 -0

2,813 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_sdio.h new file +264 -0

264 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_tcp_ack.c new file +572 -0

572 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_tcp_ack.h new file +104 -0

104 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_txrxif.c new file +753 -0

753 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_txrxif.h new file +217 -0

217 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_wext_linux.c new file +1137 -0

1,137 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/aicwf_wext_linux.h new file +15 -0
new file mode 100644
index 0000000000000..eafd2a9d80b56

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/regdb.c new file +2770 -0

2,770 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_bfmer.c new file +93 -0

93 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_bfmer.h new file +100 -0

100 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_cfgfile.c new file +265 -0

265 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_cfgfile.h new file +33 -0
new file mode 100644
index 0000000000000..d76179316fe2a

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/rwnx_debugfs.c new file +2585 -0

2,585 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_debugfs.h new file +134 -0

134 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_fw_trace.c new file +50 -0

50 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_fw_trace.h new file +28 -0
new file mode 100644
index 0000000000000..9c9df4db93cc3

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/rwnx_gki.c new file +406 -0

406 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_gki.h new file +46 -0

46 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_main.c new file +5406 -0

5,406 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_main.h new file +34 -0
new file mode 100644
index 0000000000000..8ee08b978ec9c

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/rwnx_mesh.c new file +33 -0
new file mode 100644
index 0000000000000..e955debeeee66

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/rwnx_mesh.h new file +35 -0
new file mode 100644
index 0000000000000..c32d949851c12

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/rwnx_mod_params.c new file +1295 -0

1,295 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_mod_params.h new file +70 -0

70 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_mu_group.c new file +646 -0

646 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_mu_group.h new file +159 -0

159 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_radar.c new file +1965 -0

1,965 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_radar.h new file +278 -0

278 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_rx.c new file +2443 -0

2,443 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_rx.h new file +358 -0

358 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_tdls.c new file +776 -0

776 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_tdls.h new file +57 -0

57 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_testmode.c new file +217 -0

217 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_testmode.h new file +68 -0

68 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_trace.c new file +5 -0
new file mode 100644
index 0000000000000..732fca321d965

Lines of this file are not shown. View the raw message.

drivers/net/wireless/aic/aic8800_fdrv/rwnx_tx.c new file +1805 -0

1,805 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_tx.h new file +193 -0

193 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_txq.c new file +1379 -0

1,379 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/rwnx_txq.h new file +372 -0

372 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/sdio_host.c new file +132 -0

132 lines not on this page · raw message

drivers/net/wireless/aic/aic8800_fdrv/sdio_host.h new file +39 -0
new file mode 100644
index 0000000000000..9179dd4a4a916

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Part of the diff is not shown here. View the raw message.

author
#4 lore raw

RFC PATCH 4/4 wifi: aic: integrate AIC8800 driver

In reply to Yanli Yang

From: Zhirun Liu <[email protected]>

Connect the completed AIC vendor directory to the wireless build and add its MAINTAINERS entry. Keeping integration last prevents an earlier partial source state from being selected by Kconfig.

---
 MAINTAINERS                   | 10 ++++++++++
 drivers/net/wireless/Kconfig  |  1 +
 drivers/net/wireless/Makefile |  1 +
 3 files changed, 12 insertions(+)
MAINTAINERS +10 -0
index 52f1a55eca99b..bead7f483fba8 100644
@@ -736,6 +736,16 @@ L:	[email protected]
 S:	Maintained
 F:	drivers/scsi/aic7xxx/
 
+AIC8800 WIRELESS DRIVER
+M:	zhirun.liu <[email protected]>
+M:	dijia.xu <[email protected]>
+M:	chunqiu.liu <[email protected]>
+M:	liheng.wei <[email protected]>
+M:	Yanli Yang <[email protected]>
+L:	[email protected]
+S:	Maintained
+F:	drivers/net/wireless/aic/
+
 AIMSLAB FM RADIO RECEIVER DRIVER
 M:	Hans Verkuil <[email protected]>
 L:	[email protected]
drivers/net/wireless/Kconfig +1 -0
index c6599594dc995..65ab62d073693 100644
@@ -19,6 +19,7 @@ menuconfig WLAN
 if WLAN
 
 source "drivers/net/wireless/admtek/Kconfig"
+source "drivers/net/wireless/aic/Kconfig"
 source "drivers/net/wireless/ath/Kconfig"
 source "drivers/net/wireless/atmel/Kconfig"
 source "drivers/net/wireless/broadcom/Kconfig"
drivers/net/wireless/Makefile +1 -0
index e1c4141c60044..bb0c29cb3e82f 100644
@@ -4,6 +4,7 @@
 #
 
 obj-$(CONFIG_WLAN_VENDOR_ADMTEK) += admtek/
+obj-$(CONFIG_WLAN_VENDOR_AIC) += aic/
 obj-$(CONFIG_WLAN_VENDOR_ATH) += ath/
 obj-$(CONFIG_WLAN_VENDOR_ATMEL) += atmel/
 obj-$(CONFIG_WLAN_VENDOR_BROADCOM) += broadcom/